| Title: | Stratified Prevalence Comparison Across OMOP CDM Datasets |
|---|---|
| Description: | Derives stratified prevalence tables from the condition, procedure, and drug records in OMOP CDM (Observational Medical Outcomes Partnership Common Data Model) databases, computes log2 prevalence ratios between paired datasets, and synthesizes them via random-effects meta-analysis at multiple aggregation levels (year, age group, and sex). Between-study variance is estimated with the Paule-Mandel method, as described in Paule and Mandel (1982) <doi:10.6028/jres.087.022>. |
| Authors: | Maarja Pajusalu [aut, cre] |
| Maintainer: | Maarja Pajusalu <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.2 |
| Built: | 2026-09-21 11:28:17 UTC |
| Source: | https://github.com/healthinformaticsut/syrona |
Modifies db$cdm table references to filter by a standard OHDSI
cohort table. Filters person, observation_period, death, and event tables
to cohort members and their cohort windows.
apply_cohort_filter(db, cohort_id, cohort_schema = NULL)apply_cohort_filter(db, cohort_id, cohort_schema = NULL)
db |
Connection list (from |
cohort_id |
Integer |
cohort_schema |
Schema containing the cohort table ( |
Modified db list with filtered CDM table references.
Shows yearly points + CIs, meta-analysis diamond, and colored heatmap tile row. Faceted by sex x age group.
build_forest_detail( yearly_data, meta_data, concept_name, concept_code, name1, name2, scale_mode = "log2" )build_forest_detail( yearly_data, meta_data, concept_name, concept_code, name1, name2, scale_mode = "log2" )
yearly_data |
Yearly comparison data for one concept. |
meta_data |
Meta-analysis data (across years) for one concept. |
concept_name |
Concept name string. |
concept_code |
Concept code string. |
name1 |
Reference dataset name. |
name2 |
Comparison dataset name. |
scale_mode |
"fold" or "log2". |
A girafe object.
Compact forest showing Female, Male, Both meta PR for every concept. Concept y-axis ordering matches the heatmap.
build_forest_overview( meta_sex_df, meta_summary_df, concept_ids, concept_info, name1, name2, scale_mode = "log2", concept_order = NULL )build_forest_overview( meta_sex_df, meta_summary_df, concept_ids, concept_info, name1, name2, scale_mode = "log2", concept_order = NULL )
meta_sex_df |
Meta-analysis by sex data (F/M rows). |
meta_summary_df |
Meta-analysis summary data (Both rows). |
concept_ids |
Vector of concept_ids to include. |
concept_info |
Data frame with concept_id, concept_name, concept_code, pop_weight. |
name1 |
Reference dataset name. |
name2 |
Comparison dataset name. |
scale_mode |
"fold" or "log2". |
concept_order |
Vector of concept_ids in desired display order. |
A girafe object.
Build a compact F/M/Both forest plot for a single concept
build_forest_summary( meta_sex_data, meta_summary_data, concept_name, concept_code, name1, name2, scale_mode = "log2" )build_forest_summary( meta_sex_data, meta_summary_data, concept_name, concept_code, name1, name2, scale_mode = "log2" )
meta_sex_data |
Meta-analysis data by sex (F, M) for one concept. |
meta_summary_data |
Meta-analysis summary (Both) for one concept. |
concept_name |
Concept name string. |
concept_code |
Concept code string. |
name1 |
Reference dataset name. |
name2 |
Comparison dataset name. |
scale_mode |
"fold" or "log2". |
A girafe object.
Build an interactive heatmap of prevalence ratios
build_heatmap( data, name1, name2, scale_mode = "log2", concept_weights = NULL, concept_order = NULL )build_heatmap( data, name1, name2, scale_mode = "log2", concept_weights = NULL, concept_order = NULL )
data |
Data frame with meta_agegroups data (concept_id, concept_name, concept_code, sex, age_group, log2_pr, ci_low, ci_high, p_value). |
name1 |
Reference dataset name. |
name2 |
Comparison dataset name. |
scale_mode |
"fold" or "log2" for axis labels. |
concept_weights |
Data frame with concept_id, concept_name, pop_weight. |
concept_order |
Vector of concept_ids in desired display order. |
A girafe object.
Complements the forest detail (relative -> absolute). Same facet structure: sex x age_group.
build_point_diff(yearly_data, concept_name, concept_code, name1, name2)build_point_diff(yearly_data, concept_name, concept_code, name1, name2)
yearly_data |
Yearly comparison data for one concept. |
concept_name |
Concept name string. |
concept_code |
Concept code string. |
name1 |
Reference dataset name. |
name2 |
Comparison dataset name. |
A girafe object.
Build a PR distribution histogram from meta_summary data
build_pr_distribution( data, d1_name, d2_name, scale_mode = "fold", fold_thresh = FOLD_THRESHOLD, domain_label = "conditions" )build_pr_distribution( data, d1_name, d2_name, scale_mode = "fold", fold_thresh = FOLD_THRESHOLD, domain_label = "conditions" )
data |
Filtered meta_summary rows (one per concept). Expected columns: log2_pr, fold_diff, sig, concept_id. |
d1_name |
Name of reference dataset (shown on left side). |
d2_name |
Name of comparison dataset (shown on right side). |
scale_mode |
"fold" or "log2" - controls x-axis labels only. |
fold_thresh |
Fold difference threshold for zone coloring. |
domain_label |
Label for domain (e.g. "conditions", "drugs"). |
A ggplot object.
Interactive (ggiraph): clicking a chapter facet returns its chapter_id.
build_pr_distribution_chapters( data, d1_name, d2_name, scale_mode = "fold", fold_thresh = FOLD_THRESHOLD, domain_label = "conditions" )build_pr_distribution_chapters( data, d1_name, d2_name, scale_mode = "fold", fold_thresh = FOLD_THRESHOLD, domain_label = "conditions" )
data |
Filtered meta_summary joined with chapters (one row per concept x chapter). Expected columns: log2_pr, fold_diff, sig, concept_id, chapter_name, chapter_id. |
d1_name |
Name of reference dataset. |
d2_name |
Name of comparison dataset. |
scale_mode |
"fold" or "log2". |
fold_thresh |
Fold difference threshold. |
domain_label |
Label for domain. |
A girafe object. Selection data_id = chapter_id (character).
Build an interactive population pyramid
build_pyramid(demo_df, dataset_name)build_pyramid(demo_df, dataset_name)
demo_df |
Demographics data frame with birth_year, sex, patient_count. |
dataset_name |
Name of the dataset (used as title). |
A girafe object.
Get summary statistics for a cohort.
cohort_summary(con, cohort_id, cohort_schema = NULL)cohort_summary(con, cohort_id, cohort_schema = NULL)
con |
DBI connection. |
cohort_id |
Integer |
cohort_schema |
Schema containing the cohort table ( |
A tibble with n_entries, n_persons, min_start, max_end.
Loads both datasets, runs the 4-step comparison for each domain present in both, and optionally saves to CSV.
compare_all( d1_name, d2_name, domains = c("conditions", "procedures", "drugs"), save = TRUE )compare_all( d1_name, d2_name, domains = c("conditions", "procedures", "drugs"), save = TRUE )
d1_name |
Name of dataset 1 (reference). |
d2_name |
Name of dataset 2 (comparison). |
domains |
Character vector of domains to compare. |
save |
If |
Named list of domain results (invisible).
# Run the bundled demo (a curated 32-concept subset) end to end. # Copy it to a writable folder first, since the installed copy is read-only. base <- tempdir() file.copy(system.file("extdata", "demo", package = "syrona"), base, recursive = TRUE) dir <- file.path(base, "demo") old <- options(syrona.data_dir = dir) # One domain keeps the example quick; drop `domains` to compare all three. res <- compare_all("demo_population", "demo_selected", domains = "conditions") res$condition_meta_summary options(old) # Then explore interactively: run_app(data_dir = dir)# Run the bundled demo (a curated 32-concept subset) end to end. # Copy it to a writable folder first, since the installed copy is read-only. base <- tempdir() file.copy(system.file("extdata", "demo", package = "syrona"), base, recursive = TRUE) dir <- file.path(base, "demo") old <- options(syrona.data_dir = dir) # One domain keeps the example quick; drop `domains` to compare all three. res <- compare_all("demo_population", "demo_selected", domains = "conditions") res$condition_meta_summary options(old) # Then explore interactively: run_app(data_dir = dir)
Meta-analysis across years: one row per concept_id x sex x age_group.
compare_meta_agegroups(yearly_df)compare_meta_agegroups(yearly_df)
yearly_df |
Output of |
tibble with meta-analyzed rows.
Meta-analysis across age groups: one row per concept_id x sex.
compare_meta_by_sex(meta_agegroups_df)compare_meta_by_sex(meta_agegroups_df)
meta_agegroups_df |
Output of |
tibble with meta-analyzed rows.
Meta-analysis across sexes: one row per concept_id (sex = "Both").
compare_meta_summary(meta_by_sex_df)compare_meta_summary(meta_by_sex_df)
meta_by_sex_df |
Output of |
tibble with one summary row per concept.
Matches on concept_id x year x sex x age_group (inner join). Only keeps strata where both datasets have prevalence > 0.
compare_yearly(d1, d2, prev_table = "condition_prevalence")compare_yearly(d1, d2, prev_table = "condition_prevalence")
d1 |
Named list from |
d2 |
Named list from |
prev_table |
Name of the prevalence table to compare. |
tibble with one row per matched stratum, full PR column set.
For each person who visited the specified care site, their cohort window runs from their first visit start date to their last visit end date at that site. Optionally clips to observation period overlap.
create_caresite_cohort( con, care_site_id, cohort_id, cohort_schema = NULL, cdm_schema, overwrite = FALSE, restrict_to_observation = TRUE, collapse_strategy = c("person_span", "visit_occurrence") )create_caresite_cohort( con, care_site_id, cohort_id, cohort_schema = NULL, cdm_schema, overwrite = FALSE, restrict_to_observation = TRUE, collapse_strategy = c("person_span", "visit_occurrence") )
con |
DBI connection to the OMOP CDM database. |
care_site_id |
Integer |
cohort_id |
Integer |
cohort_schema |
Schema for the cohort table ( |
cdm_schema |
Schema containing OMOP CDM tables. |
overwrite |
If |
restrict_to_observation |
If |
collapse_strategy |
How to collapse visits per person:
|
This uses server-side INSERT...SELECT for performance on large
databases (avoids downloading + re-uploading patient-level data).
Number of rows inserted (invisible).
Delete a cohort from the cohort table.
delete_cohort(con, cohort_id, cohort_schema = NULL)delete_cohort(con, cohort_id, cohort_schema = NULL)
con |
DBI connection. |
cohort_id |
Integer |
cohort_schema |
Schema containing the cohort table ( |
Number of rows deleted (invisible).
Derives stratified prevalence tables from the records in an OMOP CDM database for one or more clinical domains. Applies k-anonymity suppression and optionally saves results to CSV.
extract_all( dataset_name, db, domains = c("conditions", "procedures", "drugs"), cohort_id = NULL, cohort_schema = NULL, save = TRUE )extract_all( dataset_name, db, domains = c("conditions", "procedures", "drugs"), cohort_id = NULL, cohort_schema = NULL, save = TRUE )
dataset_name |
Short label for the dataset (e.g. "EH30", "EstBB"). |
db |
Either a DuckDB file path (string) or an existing connection
list from |
domains |
Character vector of domains to extract.
Options: |
cohort_id |
Integer |
cohort_schema |
Schema containing the cohort table. |
save |
If |
Named list of tibbles matching the Syrona schema (invisible).
Vectorized. For values < 1, shows reciprocal in parentheses.
format_fold(log2_val)format_fold(log2_val)
log2_val |
Numeric vector of log2 PR values. |
Character vector of formatted fold strings.
Vectorized. Shows < 0.001 for very small values.
format_pval(p)format_pval(p)
p |
Numeric vector of p-values. |
Character vector of formatted p-value strings.
Uploads a data frame to the database via omopgenerics::insertTable
and marks it as a cohort table with omopgenerics::newCohortTable.
Use this when cohort membership has already been computed locally
(e.g. from a CSV or programmatic cohort definition).
insert_cohort(cdm, cohort_df, name = "cohort")insert_cohort(cdm, cohort_df, name = "cohort")
cdm |
A CDM reference (from |
cohort_df |
Data frame with columns: |
name |
Name for the cohort table in the database (default |
Requires that the CDM connection was created with a writeSchema.
Updated CDM reference with the cohort table attached.
Useful for identifying care_site_id values before creating cohorts.
list_care_sites(con, cdm_schema, min_patients = 100)list_care_sites(con, cdm_schema, min_patients = 100)
con |
DBI connection. |
cdm_schema |
Schema containing the OMOP CDM tables. |
min_patients |
Minimum number of patients to include (default 100). |
A tibble with care_site_id, care_site_name, n_patients.
List available comparisons.
list_comparisons()list_comparisons()
Character vector of comparison directory names.
List all available datasets.
list_datasets()list_datasets()
Character vector of dataset names.
Load a previously saved comparison from CSV.
load_comparison(d1_name, d2_name)load_comparison(d1_name, d2_name)
d1_name |
Dataset 1 name. |
d2_name |
Dataset 2 name. |
Named list of tibbles.
Load a previously saved dataset from CSV.
load_dataset(dataset_name)load_dataset(dataset_name)
dataset_name |
Short label (subfolder name under data/sources/). |
Named list of tibbles.
base <- tempdir() file.copy(system.file("extdata", "demo", package = "syrona"), base, recursive = TRUE) old <- options(syrona.data_dir = file.path(base, "demo")) d <- load_dataset("demo_population") names(d) options(old)base <- tempdir() file.copy(system.file("extdata", "demo", package = "syrona"), base, recursive = TRUE) old <- options(syrona.data_dir = file.path(base, "demo")) d <- load_dataset("demo_population") names(d) options(old)
Makes color constants, thresholds, and other design tokens available as variables. Used by the Shiny dashboard's global.R.
load_syrona_theme(envir = parent.frame())load_syrona_theme(envir = parent.frame())
envir |
Environment to load into (default: caller's environment). |
No return value, called for its side effect of assigning the design
tokens as variables in envir.
Launches the Shiny dashboard for exploring prevalence comparisons.
The app looks for data/sources/ and data/comparisons/
relative to your current working directory. Run this from the directory
that contains your data/ folder.
run_app(data_dir = getwd(), port = NULL, launch.browser = TRUE, ...)run_app(data_dir = getwd(), port = NULL, launch.browser = TRUE, ...)
data_dir |
Path to the directory containing |
port |
Port to run the app on (default: auto-select). |
launch.browser |
Whether to open a browser window (default: TRUE). |
... |
Additional arguments passed to |
No return value, called for its side effect of launching the Shiny dashboard.
# Copy the bundled demo, generate the comparison, then launch the dashboard. if (interactive()) { base <- tempdir() file.copy(system.file("extdata", "demo", package = "syrona"), base, recursive = TRUE) dir <- file.path(base, "demo") old <- options(syrona.data_dir = dir) compare_all("demo_population", "demo_selected") run_app(data_dir = dir) options(old) }# Copy the bundled demo, generate the comparison, then launch the dashboard. if (interactive()) { base <- tempdir() file.copy(system.file("extdata", "demo", package = "syrona"), base, recursive = TRUE) dir <- file.path(base, "demo") old <- options(syrona.data_dir = dir) compare_all("demo_population", "demo_selected") run_app(data_dir = dir) options(old) }
Opens a DuckDB file and creates a CDMConnector reference. The file is opened writable, because CDMConnector validates a CDM by writing a small probe table, so a read-only DuckDB connection cannot create a CDM reference. Syrona only writes temporary and cohort tables; your OMOP data is not modified.
syrona_connect( db_path, cdm_schema = "main", write_schema = cdm_schema, read_only = FALSE )syrona_connect( db_path, cdm_schema = "main", write_schema = cdm_schema, read_only = FALSE )
db_path |
Path to the DuckDB file. |
cdm_schema |
Schema containing OMOP CDM tables (default |
write_schema |
Schema for writing temp/cohort tables.
Defaults to |
read_only |
Logical. Open DuckDB in read-only mode? Default
|
A list with components:
DBI connection object.
CDMConnector CDM reference (cdm_reference).
For remote databases, typically accessed via SSH tunnel:
ssh -L 5432:localhost:5432 user@server.
syrona_connect_pg( host = "localhost", port = 5432, dbname, user, password = NULL, cdm_schema = "public", write_schema = cdm_schema )syrona_connect_pg( host = "localhost", port = 5432, dbname, user, password = NULL, cdm_schema = "public", write_schema = cdm_schema )
host |
Hostname (default |
port |
Port number (default |
dbname |
Database name. |
user |
PostgreSQL username. |
password |
Password. If |
cdm_schema |
Schema with OMOP CDM tables (e.g. |
write_schema |
Schema for cohort/temp tables (e.g. |
Same structure as syrona_connect.
Disconnect from an OMOP CDM database.
syrona_disconnect(db)syrona_disconnect(db)
db |
Connection list returned by |
No return value, called for its side effect of closing the database connection.
Adds "..." if truncated.
truncate_name(name, max = CONCEPT_NAME_MAX)truncate_name(name, max = CONCEPT_NAME_MAX)
name |
Character vector of names. |
max |
Maximum character length (default CONCEPT_NAME_MAX). |
Character vector of (possibly truncated) names.
Light gray for rare concepts, dark charcoal for common ones.
weight_color(pct)weight_color(pct)
pct |
Numeric vector of population weight percentages (0-100). |
Character vector of hex color strings.