OHDSI tool execution for OMOP CDM data on BigQuery. Deployed as Cloud Run service + jobs.
Executes OHDSI data quality and characterization tools on BigQuery OMOP datasets:
- DQD (DataQualityDashboard) - Data quality validation with 4,000+ checks
- Achilles - Database characterization and descriptive statistics for ATLAS.
- PASS (Profile of Analytic Suitability Score) - Evaluates data fitness-for-purpose across six dimensions (accessibility, provenance, standards, concept diversity, source diversity, temporal)
- Cloud Run Service - REST API for health checks, Atlas table creation, and report generation
- Cloud Run Jobs - Long-running tool executions (up to 24h):
ccc-omop-analyzer-dqd-jobccc-omop-analyzer-achilles-jobccc-omop-analyzer-pass-job
- Airflow Integration - Jobs triggered via
CloudRunExecuteJobOperator
Project IDs with hyphens require special handling:
- Achilles: Pass dataset name only (e.g.,
"ehr_synthea"). JDBC connection'sDefaultDatasetparameter handles qualification. - DQD: Use double-quoted fully qualified names (e.g.,
'"project-id".dataset'). SqlRender translates to backticks. - PASS: Uses
project.datasetformat directly (e.g.,"project-id.ehr_synthea").
The PASS job evaluates data quality across six evidence-based dimensions:
- Accessibility - Whether clinical data is present and accessible for analysis
- Provenance - Information preservation and traceability through mapping
- Standards - Use of standardized vocabularies for interoperable research
- Concept Diversity - Variety of distinct clinical concepts in the data
- Source Diversity - Variety of data source types (EHR, claims, registries)
- Temporal - Data distribution over time (span, density, consistency)
Default Settings (configured in constants.R):
METRICS = "all"- All six metrics are calculatedCALCULATE_COMPOSITE = TRUE- Weighted composite score is generatedVERBOSE_MODE = TRUE- Detailed logging enabled
Outputs: Five CSV files uploaded to GCS containing field-level, table-level, and overall scores with 95% confidence intervals.
| File | Purpose |
|---|---|
Dockerfile |
Container image with R, DQD, Achilles, PASS, and dependencies |
cloudbuild.yaml |
Cloud Build config for service + jobs (DQD, Achilles, PASS) |
plumber_api.R |
REST API with health check, Atlas table creation, and report generation |
entrypoint.sh |
Container entrypoint; writes SERVICE_ACCOUNT_JSON to /secrets/service-account.json before exec-ing the CMD |
| Path | Purpose |
|---|---|
ref/atlas_results_tables.sql |
DDL for Atlas results tables (executed by /create_atlas_results_tables) |
ref/achilles_concept_counts.sql |
Post-Achilles SQL that produces the *_concept_counts BigQuery tables |
bq_drivers/ |
Simba BigQuery JDBC driver + transitive JARs; required by DQD and Achilles via DATABASECONNECTOR_JAR_FOLDER=/app/bq_drivers |
| File | Purpose |
|---|---|
constants.R |
Configuration constants (DQD, Achilles, PASS) |
utils.R |
Helper functions (GCS, JDBC, authentication, SQL) |
run_dqd.R |
DQD execution logic |
run_dqd_job.R |
DQD job entrypoint |
run_achilles.R |
Achilles execution logic |
run_achilles_job.R |
Achilles job entrypoint |
run_pass.R |
PASS execution logic |
run_pass_job.R |
PASS job entrypoint |
run_create_atlas_results_tables.R |
Atlas results table creation |
run_generate_delivery_report.R |
OMOP delivery report generation |
gcloud builds submit --config cloudbuild.yamlRegion is hardcoded to us-central1. The build requires the following substitutions to be provided (via --substitutions or trigger config): _IMAGE_NAME, _ARTIFACT_GCS_BUCKET, _CLIENT_ID, _CLIENT_SECRET, SERVICE_ACCOUNT_EMAIL. The ccc-omop-analyzer-secret Secret Manager secret must already exist.
Deploys:
- Service:
ccc-omop-analyzer(4 CPU, 8GB RAM, 1h timeout,--concurrency=1) - Jobs (all
--max-retries=0):ccc-omop-analyzer-dqd-jobandccc-omop-analyzer-achilles-job(4 CPU, 8GB RAM, 2h task timeout, configurable to 24h)ccc-omop-analyzer-pass-job(4 CPU, 16GB RAM, 2h task timeout)
All jobs require PROJECT_ID, CDM_DATASET_ID, and GCS_ARTIFACT_PATH. Additional variables per job:
DQD job (all required):
ANALYTICS_DATASET_ID- Target dataset for resultsCDM_VERSION- OMOP CDM version (e.g., "5.4")CDM_SOURCE_NAME- Source identifier
Achilles job:
ANALYTICS_DATASET_ID(required) - Target dataset for resultsCDM_VERSION(optional) - OMOP CDM version (e.g., "5.4")CDM_SOURCE_NAME(optional) - Source identifier
PASS job: No additional variables required.
SERVICE_ACCOUNT_EMAIL is also required by all jobs and by the service — utils.R::get_jdbc_url() uses it to authenticate the BigQuery JDBC connection (DQD and Achilles), and will stop the run if it is unset. cloudbuild.yaml sets it automatically on every deployed resource, but anyone deploying outside this build config must provide it.
Service-account credentials are provided to all jobs via the SERVICE_ACCOUNT_JSON Secret Manager secret (written to /secrets/service-account.json by entrypoint.sh), not via a job env var.
Jobs are triggered from Airflow via CloudRunExecuteJobOperator. Each job:
- Authenticates with BigQuery/GCS
- Executes tool logic (
run_dqd(),run_achilles(), orrun_pass()) - Uploads results to GCS and/or BigQuery
- Exits with status code (0=success, 1=failure)
| Tool | Artifacts |
|---|---|
| DQD | GCS: dqdashboard_results.{json,csv} (plus any per-check error files under errors/) BigQuery: {analytics_dataset_id}.dqdashboard_results (written manually from the CSV by upload_dqd_results_to_bq; the DQD package's own writeToTable is disabled in constants.R due to a BigQuery write bug) |
| Achilles | GCS: achilles_results.csv, results/*.json (ARES) BigQuery: {analytics_dataset_id}.achilles_* (written by Achilles), {analytics_dataset_id}.*_concept_counts (written by ref/achilles_concept_counts.sql) |
| PASS | GCS: pass_overall.csv (scores by metric with CIs), pass_table_level.csv (scores by table), pass_field_level.csv (field-level detail), pass_composite_overall.csv (composite score), pass_composite_components.csv (metric contributions) |
| Endpoint | Method | Parameters | Purpose |
|---|---|---|---|
/heartbeat |
GET | - | Health check |
/create_atlas_results_tables |
POST | project_id, cdm_dataset_id, analytics_dataset_id |
Create Atlas results tables in BigQuery |
/generate_delivery_report |
POST | delivery_report_path, dqd_results_path, output_gcs_path, pass_results_path (optional) |
Generate HTML report from delivery metrics, DQD results, and (optionally) PASS results |
Service account credentials from Secret Manager (ccc-omop-analyzer-secret → SERVICE_ACCOUNT_JSON).
Required permissions:
- BigQuery read/write
- GCS write
- Secret Manager read