11# OMOPHub R SDK
22
3- <!-- badges: start -->
3+ ** Query millions of standardized medical concepts from R**
4+
5+ Access SNOMED CT, ICD-10, RxNorm, LOINC, and 90+ OHDSI ATHENA vocabularies without downloading, installing, or maintaining local databases.
6+
7+ [ ![ CRAN status] ( https://www.r-pkg.org/badges/version/omophub )] ( https://CRAN.R-project.org/package=omophub )
8+ [ ![ CRAN downloads] ( https://cranlogs.r-pkg.org/badges/omophub )] ( https://cran.r-project.org/package=omophub )
49[ ![ R-CMD-check] ( https://github.com/omopHub/omophub-R/actions/workflows/R-CMD-check.yaml/badge.svg )] ( https://github.com/omopHub/omophub-R/actions/workflows/R-CMD-check.yaml )
5- [ ![ Codecov test coverage ] ( https://codecov.io/gh/omopHub/omophub-R/branch/main/graph/badge.svg )] ( https://app.codecov.io/gh/omopHub/omophub-R?branch=main )
10+ [ ![ Codecov] ( https://codecov.io/gh/omopHub/omophub-R/branch/main/graph/badge.svg )] ( https://app.codecov.io/gh/omopHub/omophub-R?branch=main )
611[ ![ License: MIT] ( https://img.shields.io/badge/License-MIT-blue.svg )] ( https://opensource.org/licenses/MIT )
7- [ ![ CRAN status] ( https://www.r-pkg.org/badges/version/omophub )] ( https://CRAN.R-project.org/package=omophub )
8- [ ![ CRAN_Status_Badge] ( https://cranlogs.r-pkg.org/badges/omophub )] ( https://cran.r-project.org/package=omophub )
912
10- <!-- badges: end -->
13+ ** [ Documentation] ( https://docs.omophub.com/sdks/r/overview ) ** ·
14+ ** [ API Reference] ( https://docs.omophub.com/api-reference ) ** ·
15+ ** [ Examples] ( https://github.com/omopHub/omophub-R/tree/main/inst/examples ) **
1116
12- R client for the [ OMOPHub API ] ( https://docs.omophub.com ) , providing access to OHDSI ATHENA standardized medical vocabularies.
17+ ---
1318
14- ## Installation
19+ ## Why OMOPHub?
20+ Working with OHDSI ATHENA vocabularies traditionally requires downloading multi-gigabyte files, setting up a database, and writing complex SQL queries. ** OMOPHub eliminates this friction.**
21+
22+ | Traditional Approach | With OMOPHub |
23+ | ---------------------| --------------|
24+ | Download 5GB+ ATHENA vocabulary files | ` install.packages("omophub") ` |
25+ | Set up and maintain database instance | One API call |
26+ | Write complex SQL with multiple JOINs | Simple R functions |
27+ | Manually update vocabularies quarterly | Always current data |
28+ | Local infrastructure required | Works anywhere R runs |
1529
16- You can install the development version of omophub from [ GitHub ] ( https://github.com/omopHub/omophub-R ) :
30+ ## Installation
1731
1832``` r
33+ # Install from CRAN
1934install.packages(" omophub" )
2035
21- # OR install from GitHub
22-
36+ # Or install development version from GitHub
2337# install.packages("pak")
2438pak :: pak(" omopHub/omophub-R" )
2539```
2640
2741## Authentication
2842
29- Set your API key using one of these methods:
30-
3143``` r
44+ library(omophub )
45+
3246# Option 1: Environment variable (recommended)
33- Sys.setenv(OMOPHUB_API_KEY = " your_api_key " )
47+ Sys.setenv(OMOPHUB_API_KEY = " oh_xxxxxxxxx " )
3448
35- # Option 2: Use the helper function
36- library(omophub )
37- set_api_key(" your_api_key" )
49+ # Option 2: Use helper function
50+ set_api_key(" oh_xxxxxxxxx" )
3851
3952# Option 3: Store securely in system keyring
40- set_api_key(" your_api_key " , store = " keyring" )
53+ set_api_key(" oh_xxxxxxxxx " , store = " keyring" )
4154```
4255
56+ Get your API key from the [ OMOPHub Dashboard] ( https://dashboard.omophub.com/api-keys ) .
57+
4358## Quick Start
4459
4560``` r
4661library(omophub )
4762
48- # Create a client
63+ # Create client
4964client <- OMOPHubClient $ new()
5065
51- # Search for concepts
52- results <- client $ search $ basic(" diabetes" )
53- results $ data
54-
55- # Get a specific concept
66+ # Get a concept by ID
5667concept <- client $ concepts $ get(201826 )
5768concept $ concept_name
5869# [1] "Type 2 diabetes mellitus"
5970
71+ # Search for concepts
72+ results <- client $ search $ basic(" metformin" , vocabulary_ids = " RxNorm" )
73+ results $ data
74+
6075# Get concept by vocabulary code
61- concept <- client $ concepts $ get_by_code(" SNOMED" , " 44054006" )
76+ snomed_concept <- client $ concepts $ get_by_code(" SNOMED" , " 44054006" )
77+
78+ # Map to another vocabulary
79+ mappings <- client $ mappings $ get(201826 , target_vocabularies = " ICD10CM" )
80+
81+ # Navigate hierarchy
82+ ancestors <- client $ hierarchy $ ancestors(201826 , max_levels = 3 )
83+ ```
6284
63- # Batch lookup multiple concepts
64- batch <- client $ concepts $ batch(c(201826 , 320128 , 4329847 ))
85+ ## Use Cases
6586
66- # Get concept ancestors (hierarchy)
67- ancestors <- client $ hierarchy $ ancestors(201826 )
87+ ### ETL & Data Pipelines
6888
69- # Get concept mappings to another vocabulary
70- mappings <- client $ mappings $ get(201826 , target_vocabularies = " ICD10CM" )
89+ Validate and map clinical codes during OMOP CDM transformations:
90+
91+ ``` r
92+ # Validate source codes and find standard equivalents
93+ validate_and_map <- function (source_vocab , source_code ) {
94+ concept <- client $ concepts $ get_by_code(source_vocab , source_code )
95+
96+ if (concept $ standard_concept != " S" ) {
97+ mappings <- client $ mappings $ get(
98+ concept $ concept_id ,
99+ target_vocabularies = " SNOMED"
100+ )
101+ return (mappings $ mappings [[1 ]]$ target_concept_id )
102+ }
103+
104+ concept $ concept_id
105+ }
106+
107+ # Example: Map ICD-10 to SNOMED
108+ standard_id <- validate_and_map(" ICD10CM" , " E11.9" )
71109```
72110
73- ## Resources
111+ ### Data Quality Checks
74112
75- The client provides access to these resources :
113+ Verify codes exist and are valid :
76114
77- | Resource | Description |
78- | ----------| -------------|
79- | ` concepts ` | Concept lookup, batch operations, suggestions |
80- | ` search ` | Basic and advanced concept search |
81- | ` vocabularies ` | Vocabulary listing and details |
82- | ` domains ` | Domain listing and concept filtering |
83- | ` hierarchy ` | Ancestor and descendant navigation |
84- | ` relationships ` | Concept relationships |
85- | ` mappings ` | Concept mappings between vocabularies |
115+ ``` r
116+ # Check if condition codes are valid
117+ condition_codes <- c(" E11.9" , " I10" , " J44.9" )
118+
119+ for (code in condition_codes ) {
120+ tryCatch({
121+ concept <- client $ concepts $ get_by_code(" ICD10CM" , code )
122+ message(sprintf(" OK %s: %s" , code , concept $ concept_name ))
123+ }, omophub_api_error = function (e ) {
124+ message(sprintf(" ERROR %s: Invalid code!" , code ))
125+ })
126+ }
127+ ```
86128
87- ## Pagination
129+ ### Phenotype Development
130+
131+ Explore hierarchies to build comprehensive concept sets:
88132
89- For large result sets, use automatic pagination:
133+ ``` r
134+ # Get all descendants for phenotype definition
135+ descendants <- client $ hierarchy $ descendants(
136+ 201826 , # Type 2 diabetes mellitus
137+ max_levels = 5 ,
138+ standard_only = TRUE
139+ )
140+
141+ concept_set <- sapply(descendants $ concepts , function (x ) x $ concept_id )
142+ message(sprintf(" Found %d concepts for T2DM phenotype" , length(concept_set )))
143+ ```
144+
145+ ### Integration with tidyverse
146+
147+ ``` r
148+ library(dplyr )
149+ library(purrr )
150+
151+ # Search and convert to tibble
152+ results <- client $ search $ basic(" hypertension" , page_size = 100 )
153+
154+ concepts_df <- results $ data %> %
155+ map_dfr(~ tibble(
156+ concept_id = .x $ concept_id ,
157+ concept_name = .x $ concept_name ,
158+ vocabulary_id = .x $ vocabulary_id ,
159+ domain_id = .x $ domain_id
160+ ))
161+
162+ # Filter and analyze
163+ concepts_df %> %
164+ filter(vocabulary_id == " SNOMED" ) %> %
165+ count(domain_id )
166+ ```
167+
168+ ## API Resources
169+
170+ | Resource | Description | Key Methods |
171+ | ----------| -------------| -------------|
172+ | ` concepts ` | Concept lookup and batch operations | ` get() ` , ` get_by_code() ` , ` batch() ` , ` suggest() ` |
173+ | ` search ` | Full-text and semantic search | ` basic() ` , ` advanced() ` , ` basic_all() ` |
174+ | ` hierarchy ` | Navigate concept relationships | ` ancestors() ` , ` descendants() ` |
175+ | ` mappings ` | Cross-vocabulary mappings | ` get() ` , ` map() ` |
176+ | ` vocabularies ` | Vocabulary metadata | ` list() ` , ` get() ` , ` stats() ` |
177+ | ` domains ` | Domain information | ` list() ` , ` get() ` , ` concepts() ` |
178+
179+ ## Pagination
90180
91181``` r
92- # Fetch all results automatically
182+ # Automatic pagination - fetch all results
93183all_results <- client $ search $ basic_all(" diabetes" , page_size = 100 )
94184
95- # Or paginate manually
185+ # Manual pagination
96186page1 <- client $ search $ basic(" diabetes" , page = 1 , page_size = 20 )
97187page2 <- client $ search $ basic(" diabetes" , page = 2 , page_size = 20 )
98188```
99189
100- ## Vocabulary Versioning
190+ ## Configuration
101191
102- Specify a vocabulary version when creating the client:
103192``` r
193+ # Specify vocabulary version
104194client <- OMOPHubClient $ new(vocab_version = " 2025.2" )
195+
196+ # Custom configuration
197+ client <- OMOPHubClient $ new(
198+ api_key = " oh_xxx" ,
199+ base_url = " https://api.omophub.com/v1" ,
200+ timeout = 30
201+ )
105202```
106203
107204## Error Handling
108205
109- The package uses structured error classes:
110-
111206``` r
112- tryCatch(
113- {
114- result <- client $ concepts $ get( 999999999 )
115- },
116- omophub_api_error = function (e ) {
117- message(" API error: " , conditionMessage( e ) )
118- },
119- omophub_auth_error = function ( e ) {
120- message( " Authentication failed " )
121- }
122- )
207+ tryCatch({
208+ result <- client $ concepts $ get( 999999999 )
209+ }, omophub_not_found_error = function ( e ) {
210+ message( " Concept not found: " , conditionMessage( e ))
211+ }, omophub_auth_error = function (e ) {
212+ message(" Check your API key " )
213+ }, omophub_rate_limit_error = function ( e ) {
214+ message( " Rate limited, please wait " )
215+ }, omophub_api_error = function ( e ) {
216+ message( " API error: " , conditionMessage( e ))
217+ } )
123218```
124219
220+ ## Compared to Alternatives
221+
222+ | Feature | OMOPHub SDK | ATHENA Download | OHDSI WebAPI |
223+ | ---------| -------------| -----------------| --------------|
224+ | Setup time | 1 minute | Hours | Hours |
225+ | Infrastructure | None | PostgreSQL required | Full OHDSI stack |
226+ | Updates | Automatic | Manual download | Manual |
227+ | Programmatic access | Native R | SQL/DatabaseConnector | REST API |
228+ | Offline support | No | Yes | Depends |
229+ | Cost | Free tier available | Free | Free (self-hosted) |
230+
231+ ** Best for:** R users who need quick, programmatic access to OMOP vocabularies without infrastructure overhead.
232+
125233## Examples
126234
127235The package includes comprehensive examples in ` inst/examples/ ` :
128236
129237| Example | Description |
130238| ---------| -------------|
131- | [ ` basic_usage.R ` ] ( inst/examples/basic_usage.R ) | Getting started - client setup, concept lookup, search |
132- | [ ` search_concepts.R ` ] ( inst/examples/search_concepts.R ) | Search capabilities - filters, autocomplete, pagination |
133- | [ ` navigate_hierarchy.R ` ] ( inst/examples/navigate_hierarchy.R ) | Hierarchy navigation - ancestors, descendants, relationships |
134- | [ ` map_between_vocabularies.R ` ] ( inst/examples/map_between_vocabularies.R ) | Vocabulary mapping - ICD-10, SNOMED, batch mapping |
135- | [ ` error_handling.R ` ] ( inst/examples/error_handling.R ) | Error handling patterns - tryCatch, retry logic |
239+ | ` basic_usage.R ` | Getting started - client setup, concept lookup, search |
240+ | ` search_concepts.R ` | Search capabilities - filters, autocomplete, pagination |
241+ | ` navigate_hierarchy.R ` | Hierarchy navigation - ancestors, descendants |
242+ | ` map_between_vocabularies.R ` | Cross-vocabulary mapping |
243+ | ` error_handling.R ` | Error handling patterns |
136244
137245Run an example:
246+
138247``` r
139- # After installing the package
140248example_path <- system.file(" examples" , " basic_usage.R" , package = " omophub" )
141249source(example_path )
142250```
@@ -145,14 +253,36 @@ source(example_path)
145253
146254- [ Full Documentation] ( https://docs.omophub.com/sdks/r/overview )
147255- [ API Reference] ( https://docs.omophub.com/api-reference )
148- - [ Examples] ( https://github.com/omopHub/omophub-r/tree/main/inst/examples )
256+ - [ Examples] ( https://github.com/omopHub/omophub-R/tree/main/inst/examples )
257+ - [ Get API Key] ( https://dashboard.omophub.com/api-keys )
258+
259+ ## Contributing
260+
261+ We welcome contributions!
262+
263+ ``` r
264+ # Clone and install for development
265+ # install.packages("devtools")
266+ devtools :: install_github(" omopHub/omophub-R" )
267+
268+ # Run tests
269+ devtools :: test()
270+
271+ # Check package
272+ devtools :: check()
273+ ```
274+
275+ ## Support
276+
277+ - [ GitHub Issues] ( https://github.com/omopHub/omophub-R/issues )
278+ - [ GitHub Discussions] ( https://github.com/omopHub/omophub-R/discussions )
279+ - Email: support@omophub.com
280+ - Website: [ omophub.com] ( https://omophub.com )
149281
150282## License
151283
152284MIT License - see [ LICENSE] ( LICENSE ) for details.
153285
154- ## Support
286+ ---
155287
156- - [ GitHub Issues] ( https://github.com/omopHub/omophub-r/issues )
157- - [ Documentation] ( https://docs.omophub.com )
158- - [ Website] ( https://omophub.com )
288+ * Built for the OHDSI community*
0 commit comments