diff --git a/.gitignore b/.gitignore
index 0bd2a448..95aa7b8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ errorReportSql.txt
/Meta/
work/*
scratch/
+inst/doc
diff --git a/DESCRIPTION b/DESCRIPTION
index c361772a..868eaf92 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: Capr
Title: Cohort Definition Application Programming
-Version: 2.0.4
+Version: 2.0.5
Authors@R: c(
person("Martin", "Lavallee", , "mdlavallee92@gmail.com", role = c("aut", "cre")),
person("Adam", "Black", , "black@ohdsi.org", role = "aut")
diff --git a/NAMESPACE b/NAMESPACE
index 702b8477..f003a377 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -11,16 +11,16 @@ export(bt)
export(censoringEvents)
export(cohort)
export(compile.Cohort)
-export(condition)
export(conditionEra)
+export(conditionOccurrence)
export(continuousObservation)
export(cs)
export(daysOfSupply)
export(death)
export(descendants)
-export(drug)
export(drugEra)
export(drugExit)
+export(drugExposure)
export(drugQuantity)
export(drugRefills)
export(duringInterval)
diff --git a/NEWS.md b/NEWS.md
index 410ff7cd..2a9fbd9a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,10 @@
+Capr 2.0.5
+==========
+- change query functions to match known syntax (i.e. drug => drugExposure, condition => conditionOccurrence)
+- require a name for `cs()`
+- improve documentation (add vignette for query, count and group)
+
+
Capr 2.0.4
==========
- hot fix add procedure occurrence into query
diff --git a/R/conceptSet.R b/R/conceptSet.R
index 73f86320..2359a828 100644
--- a/R/conceptSet.R
+++ b/R/conceptSet.R
@@ -193,7 +193,7 @@ newConcept <- function(id,
#' cs(1, 2, 3, exclude(4, 5), mapped(6, 7), descendants(8, 9))
#' cs(descendants(1, 2, 3), exclude(descendants(8, 9)))
#' }
-cs <- function(..., name = "", id = NULL) {
+cs <- function(..., name, id = NULL) {
dots <- unlist(list(...), recursive = F)
conceptList <- lapply(dots, function(x) {
diff --git a/R/query.R b/R/query.R
index fd908f4e..64e854a5 100644
--- a/R/query.R
+++ b/R/query.R
@@ -115,7 +115,7 @@ query <- function(domain, conceptSet = NULL, ...) {
#'
#' @return A Capr Query
#' @export
-condition <- function(conceptSet, ...) {
+conditionOccurrence <- function(conceptSet, ...) {
query(domain = "ConditionOccurrence",
conceptSet = conceptSet,
@@ -129,7 +129,7 @@ condition <- function(conceptSet, ...) {
#'
#' @return A Capr Query
#' @export
-drug <- function(conceptSet, ...) {
+drugExposure <- function(conceptSet, ...) {
query(domain = "DrugExposure",
conceptSet = conceptSet,
diff --git a/README.md b/README.md
index 76bdb5e9..4f1504ef 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,6 @@ Learn more about the OHDSI approach to cohort building in the [cohorts chapter o
# Installation
-Capr can be installed via:
-
-``` r
-# install.packages("Capr")
-```
Users can install the current development version of Capr from [GitHub](https://github.com/) with:
@@ -29,246 +24,19 @@ Users can install the current development version of Capr from [GitHub](https://
devtools::install_github("ohdsi/Capr")
```
-# How to Use
-
-## Examples
-
-Capr uses many defaults that match the defaults in Atlas. Creating a simple cohort is a single line of code. As an example we will define a cohort of new users of diclofenac described in the [Book of OHDSI.](https://ohdsi.github.io/TheBookOfOhdsi/SuggestedAnswers.html#Cohortsanswers)
-
-### Simple diclofenac cohort
-
-``` r
-library(Capr)
-
-# Define concepts sets with cs()
-diclofenac <- cs(descendants(1124300))
-
-ch <- cohort(
- entry = entry(drugEra(diclofenac))
-)
-
-ch
-#> Formal class 'Cohort' [package "Capr"] with 4 slots
-#> ..@ entry :Formal class 'CohortEntry' [package "Capr"] with 5 slots
-#> ..@ attrition:Formal class 'CohortAttrition' [package "Capr"] with 2 slots
-#> ..@ exit :Formal class 'CohortExit' [package "Capr"] with 2 slots
-#> ..@ era :Formal class 'CohortEra' [package "Capr"] with 3 slots
-```
-
-### Adding more complexity
-
-We can make more complex cohorts by adding a window of continuous observation and a custom cohort exit. The following information was added to the diclofenac cohort:
-
-- Ages 16 or older
-- With at least 365 days of continuous observation prior to exposure
-- With cohort exit defined as discontinuation of exposure (allowing for a 30-day gap)
-
-``` r
-diclofenac <- cs(descendants(1124300))
-
-ch <- cohort(
- entry = entry(drugEra(diclofenac, age(gte(16))),
- observationWindow = continuousObservation(-365L, 0L)),
- exit = exit(drugExit(diclofenac))
-)
-
-ch
-#> Formal class 'Cohort' [package "Capr"] with 4 slots
-#> ..@ entry :Formal class 'CohortEntry' [package "Capr"] with 5 slots
-#> ..@ attrition:Formal class 'CohortAttrition' [package "Capr"] with 2 slots
-#> ..@ exit :Formal class 'CohortExit' [package "Capr"] with 2 slots
-#> ..@ era :Formal class 'CohortEra' [package "Capr"] with 3 slots
-```
-
-### Adding cohort attrition
-
-Users can also add attrition to the cohort by specifying inclusion and exclusion criteria to modify the cohort entry. The following exclusion criteria were added to the diclofenac cohort:
-
-- Without prior exposure to any NSAID (Non-Steroidal Anti-Inflammatory Drug)
-- Without prior diagnosis of cancer
-
-``` r
-diclofenac <- cs(descendants(1124300), name = "diclofenac")
-nsaid <- cs(descendants(21603933), name = "nsaid")
-cancer <- cs(descendants(443392), name = "cancer")
-
-ch <- cohort(
- entry = entry(drugEra(diclofenac, age(gte(16))),
- observationWindow = continuousObservation(-365L, 0L)),
- attrition = attrition(
- withAll(
- exactly(0, drug(nsaid), eventStarts(-Inf, 0, index = "startDate")),
- exactly(0, condition(cancer), eventStarts(-Inf, 0, index = "startDate"))
- )
- ),
- exit = exit(
- endStrategy = drugExit(diclofenac, persistenceWindow = 30)
- )
-)
-
-ch
-#> Formal class 'Cohort' [package "Capr"] with 4 slots
-#> ..@ entry :Formal class 'CohortEntry' [package "Capr"] with 5 slots
-#> ..@ attrition:Formal class 'CohortAttrition' [package "Capr"] with 2 slots
-#> ..@ exit :Formal class 'CohortExit' [package "Capr"] with 2 slots
-#> ..@ era :Formal class 'CohortEra' [package "Capr"] with 3 slots
-```
-
-## Save cohort as JSON
-
-OHDSI standard cohorts are represented as json files and can be copy and pasted into Atlas.
-
-``` r
-
-path <- file.path(tempdir(), "diclofenacCohort.json")
-
-writeCohort(ch, path)
-
-cat(substr(readr::read_file(path), 1, 100))
-#> {
-#> "ConceptSets": [
-#> {
-#> "id": 0,
-#> "name": "diclofenac",
-#> "expression": {
-#>
-```
-
-### Fill in missing concept set details
-
-Users can build valid cohorts with minimal concept information, only supplying a concept id and name. The example below shows the minimal concept set input for Capr.
-
-``` r
-
-diclofenac <- cs(descendants(1124300), name = "diclofenac")
-
-cat(as.json(diclofenac))
-#> {
-#> "id": "11d012608fce118593830a3039042e56",
-#> "name": "diclofenac",
-#> "expression": {
-#> "items": [
-#> {
-#> "concept": {
-#> "CONCEPT_ID": 1124300,
-#> "CONCEPT_NAME": "",
-#> "STANDARD_CONCEPT": "",
-#> "STANDARD_CONCEPT_CAPTION": "",
-#> "INVALID_REASON": "",
-#> "INVALID_REASON_CAPTION": "",
-#> "CONCEPT_CODE": "",
-#> "DOMAIN_ID": "",
-#> "VOCABULARY_ID": "",
-#> "CONCEPT_CLASS_ID": ""
-#> },
-#> "isExcluded": false,
-#> "includeDescendants": true,
-#> "includeMapped": false
-#> }
-#> ]
-#> }
-#> }
-```
-
-However, when saving cohorts it is helpful to fill in the concept details. This requires a live connection to an OMOP CDM database that includes the vocabularies used in the cohort definition.
-
-``` r
-con <- DatabaseConnector::connect(Eunomia::getEunomiaConnectionDetails())
-diclofenac <- getConceptSetDetails(diclofenac, con, vocabularyDatabaseSchema = "main")
-cat(as.json(diclofenac))
-#> {
-#> "id": "11d012608fce118593830a3039042e56",
-#> "name": "diclofenac",
-#> "expression": {
-#> "items": [
-#> {
-#> "concept": {
-#> "CONCEPT_ID": 1124300,
-#> "CONCEPT_NAME": "Diclofenac",
-#> "STANDARD_CONCEPT": "S",
-#> "STANDARD_CONCEPT_CAPTION": "Standard",
-#> "INVALID_REASON": "V",
-#> "INVALID_REASON_CAPTION": "Valid",
-#> "CONCEPT_CODE": "3355",
-#> "DOMAIN_ID": "Drug",
-#> "VOCABULARY_ID": "RxNorm",
-#> "CONCEPT_CLASS_ID": "Ingredient"
-#> },
-#> "isExcluded": false,
-#> "includeDescendants": true,
-#> "includeMapped": false
-#> }
-#> ]
-#> }
-#> }
-```
-
-### Generating Capr Cohorts
-
-Once a Capr cohort has been constructed, the user can generate this cohort definition on an OMOP CDM connection. It is suggested to use [CohortGenerator](https://github.com/OHDSI/CohortGenerator) and [CirceR](https://github.com/OHDSI/CirceR) to generate Capr cohorts on a database.
-
-## Building Capr Templates
-
-A Capr cohort template is a function that always returns a Capr cohort. It can accept arguments that can be used to parameterize any part of a cohort definition. Capr cohort templates are the recommended approach for building large numbers of similar cohorts in R.
-
-``` r
-
-# A Capr cohort template is a function that returns a cohort
-drugEraTemplate <- function(ingredientConceptId) {
-
- drugConceptSet <- cs(descendants(ingredientConceptId))
-
- cohort(
- entry = entry(drugEra(drugConceptSet, age(gte(16))),
- observationWindow = continuousObservation(-365L, 0L)),
- exit = exit(drugExit(drugConceptSet, persistenceWindow = 30))
- )
-}
-
-
-library(dplyr, warn.conflicts = FALSE)
-
-# create a cohort for every single ingredient
-df <- DBI::dbGetQuery(con,
- "Select * from concept where concept_class_id = 'Ingredient'") %>%
- tibble() %>%
- select(concept_id, concept_name) %>%
- mutate(capr_cohort = purrr::map(concept_id, drugEraTemplate)) %>%
- mutate(cohort_json = purrr::map_chr(capr_cohort, as.json))
-
-df
-#> # A tibble: 91 × 4
-#> concept_id concept_name capr_cohort cohort_json
-#> By default, Now we add in the CDM connection to get the remaining
+information: Persons with atrial fibrillation per Subramanya et al
2021 https://atlas-phenotype.ohdsi.org/#/cohortdefinition/94 The GIBleed concept set will include all descendants of the
@@ -159,7 +162,7 @@
Defining a concept set name = "aceInhibitors")
ace1
#> -- <Capr Concept Set> aceInhibitors --------------------------------------------
-#> # A tibble: 5 x 4
-#> conceptId includeDescendants isExcluded includeMapped
-#> <int> <lgl> <lgl> <lgl>
-#> 1 1335471 FALSE FALSE FALSE
-#> 2 1340128 FALSE FALSE FALSE
-#> 3 1341927 FALSE FALSE FALSE
-#> 4 1308216 FALSE FALSE FALSE
-#> 5 1363749 FALSE FALSE FALSE
+#> # A tibble: 5 x 9
+#> conceptId conceptCode conceptName domainId vocabularyId standardConcept
+#> <int> <chr> <chr> <chr> <chr> <chr>
+#> 1 1335471 "" "" "" "" ""
+#> 2 1340128 "" "" "" "" ""
+#> 3 1341927 "" "" "" "" ""
+#> 4 1308216 "" "" "" "" ""
+#> 5 1363749 "" "" "" "" ""
+#> # i 3 more variables: includeDescendants <lgl>, isExcluded <lgl>,
+#> # includeMapped <lgl>
Including Descendants
@@ -162,14 +167,16 @@
Including Descendants name = "aceInhibitors")
ace2
#> -- <Capr Concept Set> aceInhibitors --------------------------------------------
-#> # A tibble: 5 x 4
-#> conceptId includeDescendants isExcluded includeMapped
-#> <int> <lgl> <lgl> <lgl>
-#> 1 1335471 TRUE FALSE FALSE
-#> 2 1340128 TRUE FALSE FALSE
-#> 3 1341927 TRUE FALSE FALSE
-#> 4 1363749 TRUE FALSE FALSE
-#> 5 1308216 TRUE FALSE FALSE
Toggling other logic
@@ -182,14 +189,35 @@
Toggling other logic= "aceInhibitors")
ace3
#> -- <Capr Concept Set> aceInhibitors --------------------------------------------
-#> # A tibble: 5 x 4
-#> conceptId includeDescendants isExcluded includeMapped
-#> <int> <lgl> <lgl> <lgl>
-#> 1 1335471 TRUE FALSE FALSE
-#> 2 1340128 TRUE FALSE FALSE
-#> 3 1341927 TRUE FALSE FALSE
-#> 4 1363749 TRUE FALSE FALSE
-#> 5 1308216 FALSE TRUE FALSE
Fill in missing concept set details
+
+Capr
puts in minimal information for the
+concept set, the concept id. However it is often helpful to fill out the
+remaining information of the concept using the OMOP vocabularies. To
+fill out the remaining information, a user needs to connect to a OMOP
+CDM to access the vocabulary information for the concept in the concept
+set. First we show a regular concept set, and the json it renders.
+
diclofenac <- cs(descendants(1124300), name = "diclofenac")
+cat(as.json(diclofenac))
+
con <- DatabaseConnector::connect(Eunomia::getEunomiaConnectionDetails())
+diclofenac <- getConceptSetDetails(diclofenac, con, vocabularyDatabaseSchema = "main")
+cat(as.json(diclofenac))
Type 2 diabetes mellitus
ch <- cohort(
entry = entry(
- condition(cs0),
+ conditionOccurrence(cs0),
observationWindow = continuousObservation(priorDays = 365)
),
exit = exit(
@@ -164,12 +167,12 @@
Type 2 diabetes mellitus
ch <- cohort(
entry = entry(
- condition(cs0),
+ conditionOccurrence(cs0),
observationWindow = continuousObservation(priorDays = 365)
),
attrition = attrition(
- exactly(0, condition(cs1), duringInterval(eventStarts(-Inf, 0))),
- exactly(0, condition(cs2), duringInterval(eventStarts(-Inf, 0)))
+ exactly(0, conditionOccurrence(cs1), duringInterval(eventStarts(-Inf, 0))),
+ exactly(0, conditionOccurrence(cs2), duringInterval(eventStarts(-Inf, 0)))
),
exit = exit(
endStrategy = observationExit()
@@ -200,18 +203,18 @@
Type 2 diabetes mellitus
ch <- cohort(
entry = entry(
- condition(cs0),
- drug(cs4),
+ conditionOccurrence(cs0),
+ drugExposure(cs4),
measurement(cs3, valueAsNumber(bt(6.5, 30)), unit("%")),
measurement(cs3, valueAsNumber(bt(48, 99)), unit("mmol/mol")),
observationWindow = continuousObservation(priorDays = 365)
),
attrition = attrition(
'no T1D' = withAll(
- exactly(0, condition(cs1), duringInterval(eventStarts(-Inf, 0)))
+ exactly(0, conditionOccurrence(cs1), duringInterval(eventStarts(-Inf, 0)))
),
'no secondary diabettes' = withAll(
- exactly(0, condition(cs2), duringInterval(eventStarts(-Inf, 0)))
+ exactly(0, conditionOccurrence(cs2), duringInterval(eventStarts(-Inf, 0)))
)
),
exit = exit(
@@ -230,7 +233,7 @@
Type 1 diabetes mellitus
ch <- cohort(
entry = entry(
- condition(cs0),
+ conditionOccurrence(cs0),
observationWindow = continuousObservation(priorDays = 365)
)
)
@@ -253,12 +256,12 @@
Type 1 diabetes mellitus
ch <- cohort(
entry = entry(
- condition(cs1),
+ conditionOccurrence(cs1),
observationWindow = continuousObservation(priorDays = 365)
),
attrition = attrition(
- "no prior T2DM" = exactly(0, condition(cs0), duringInterval(eventStarts(-Inf, 0))),
- "no prior secondary T1DM" = exactly(0, condition(cs2), duringInterval(eventStarts(-Inf, 0)))
+ "no prior T2DM" = exactly(0, conditionOccurrence(cs0), duringInterval(eventStarts(-Inf, 0))),
+ "no prior secondary T1DM" = exactly(0, conditionOccurrence(cs2), duringInterval(eventStarts(-Inf, 0)))
)
)
@@ -273,7 +276,7 @@
Atrial Fibrillationcs0 <- cs(descendants(313217),
name = "Atrial fibrillation")
-ch <- cohort(condition(cs0))
+ch <- cohort(conditionOccurrence(cs0))
Atrial Fibrillationch <- cohort(
entry = entry(
- condition(afib,
+ conditionOccurrence(afib,
nestedWithAny(
atLeast(1, visit(ip), duringInterval(eventStarts(-Inf, 0), eventEnds(0, Inf))),
nestedWithAll(
atLeast(1, visit(op, duringInterval(eventStarts(-Inf, 0), eventEnds(0, Inf)),
nestedWithAll(
- atLeast(1, condition(afib, duringInterval(eventStarts(7, 365)),
+ atLeast(1, conditionOccurrence(afib, duringInterval(eventStarts(7, 365)),
nestedWithAll(
atLeast(1, visit(op, duringInterval(eventStarts(-Inf, 0), eventEnds(0, Inf))))
)
diff --git a/docs/articles/Using-Capr.html b/docs/articles/Using-Capr.html
index 889f4be7..4ae3b12a 100644
--- a/docs/articles/Using-Capr.html
+++ b/docs/articles/Using-Capr.html
@@ -40,7 +40,7 @@
@@ -62,6 +62,9 @@
Building a concept set
library(Capr)
-GIBleed <- cs(descendants(192671))
+GIBleed <- cs(descendants(192671), name = "GIbleed")
GIBleed
Creating a cohort
giBleedCohort <- cohort(
entry = entry(
- condition(GIBleed),
+ conditionOccurrence(GIBleed),
observationWindow = continuousObservation(0L, 0L),
primaryCriteriaLimit = "First"
),
diff --git a/docs/articles/capr_design.html b/docs/articles/capr_design.html
index 695c44e4..ca011e80 100644
--- a/docs/articles/capr_design.html
+++ b/docs/articles/capr_design.html
@@ -40,7 +40,7 @@
@@ -62,6 +62,9 @@
1) Query
CDM. For example:
The conceptSet input takes on a a concept set built from the cs command. The dots argument is where the user can supply attributes that contextualize the query to a specific subpopulation.
@@ -491,9 +494,9 @@
-condition(cs(descendants(201826L), name = "T2D"), male())
-condition(cs(descendants(201826L), name = "T2D"), age(gte(18)))
-condition(cs(descendants(201826L), name = "T2D"), first())
+condition(cs(descendants(201826L), name = "T2D"), male())
+condition(cs(descendants(201826L), name = "T2D"), age(gte(18)))
+condition(cs(descendants(201826L), name = "T2D"), first())
The first example in code snippet 4 utilizes a concept attribute. The
male()
function automatically maps the concept to the male
concept id. Other concept attribute functions will have mappers and
@@ -558,7 +561,7 @@
exactly(0,
- query = condition(cs(descendants(201826L), name = "T2D")),
+ query = condition(cs(descendants(201826L), name = "T2D")),
aperture = duringInterval(eventStarts(-Inf, -1))
)
A note for the criteria is that its meaning is tethered to an event diff --git a/docs/articles/capr_objects.html b/docs/articles/capr_objects.html new file mode 100644 index 00000000..e07aca05 --- /dev/null +++ b/docs/articles/capr_objects.html @@ -0,0 +1,708 @@ + + +
+ + + + +Capr
allows users to build OHDSI cohort definitions in R
+outside of ATLAS. Capr
, like ATLAS, uses the same
+underlying software circe-be
to compose the cohort logic
+into an actionable query. Therefore we must understand sub-components of
+the cohort definition, in order to properly apply them to our cohort
+construction. There are three main sub-components that drive building of
+the cohort logic: 1) query, 2) criteria and 3) group. In this vignette,
+we will describe the purpose of each sub-component and demonstrate the
+Capr
commands to invoke these structures.
The query is a circe-be
construct that defines
+which concepts to extract from which domain table in the OMOP CDM. In
+basic terms it is finding the persons that have a particular code in the
+data. Through a more technical lens, the query is supplying the
+WHERE and FROM logic in portions of
+the SQL script. Ultimately the logic we construct in Capr
+or ATLAS render a standardized SQL script that finds persons in the
+database, of which the query is vital in providing the code sets to
+search from. The query will be found all over the cohort
+definition. Whenever we need to apply a concept set, it will be through
+a query. In Capr
the query function is
+specified based on the domain tables available in the CDM. The table
+below provides the mapping between the OMOP domain and the the
+Capr
function call.
OMOP Domain | +Capr Function | +
---|---|
DrugExposure | +drugExposure | +
DrugEra | +drugEra | +
ConditionOccurrence | +conditionOccurrence | +
ConditionEra | +conditionEra | +
ProcedureOccurrence | +procedure | +
Measurement | +measurement | +
VisitOccurrence | +visit | +
Observation | +observation | +
Death | +death | +
A simple example of how to use a query in Capr
can be
+seen below:
+t1dConceptSet <- cs(descendants(195771), name = "T1D")
+t1dQuery <- conditionOccurrence(t1dConceptSet)
With our query we can apply this in a variety of places within the +cohort definition. Below we give an example of a cohort of persons +starting on metformin as our index event, where they could not have been +diagnosed with Type 1 Diabetes any time prior.
+
+metforminConceptSet <- cs(descendants(1503297), name = "metformin")
+t1dConceptSet <- cs(descendants(195771), name = "T1D")
+
+metforminCohort <- cohort(
+ entry = entry(
+ # metformin drug query as index event
+ drugExposure(metforminConceptSet, firstOccurrence()),
+ observationWindow = continuousObservation(priorDays = -365, postDays = 365L),
+ primaryCriteriaLimit = "All"
+ ),
+ attrition = attrition(
+ 'noT1d' = withAll(
+ exactly(
+ x = 0,
+ # query for t1d occurrence to exclude patients
+ query = conditionOccurrence(t1dConceptSet),
+ aperture = duringInterval(
+ startWindow = eventStarts(a = -Inf, b = 0, index = "startDate")
+ )
+ )
+ )
+ ),
+ exit = exit(
+ endStrategy = observationExit(),
+ censor = censoringEvents(
+ #exit based on observence of t1d condition
+ # query for t1d occurrence for censor
+ conditionOccurrence(t1dConceptSet)
+ )
+ )
+)
Notice that the query is applied all over this cohort +definition. The metformin query sets the concept set to use as the index +event. The Type 1 Diabetes (T1D) query sets the attrition of the +patients identified at index who should be excluded for having the +condition. The T1D query also sets the exit from cohort. The cohort ends +when the person has no more observation time in the database or they +have been diagnosed with T1D. Remember the query is infusing +the concept sets into the cohort logic based on which domain to search +for codes in person healthcare records.
+The query is often contextualized by an attribute. For
+example in the cohort above, we are searching for metformin in the drug
+exposure table given it has occurred for the first time in the person
+history. The attribute is a object that modifies queries by filtering
+records based on the presence of another parameter. Attributes can be
+based on person information (such as gender, race, or age), time based
+(observation at a certain time window), domain based (presence of a code
+in a different column of the same domain), or event based (based on the
+observation of another event occurring). We will go into more details on
+different attributes in a different vignette. In Capr
as
+many attributes can be attached within the query after providing the
+concept set. Example below:
+t1dConceptSet <- cs(descendants(195771), name = "T1D")
+
+maleT1D <- conditionOccurrence(t1dConceptSet, male())
+maleT1D18andOlder <- conditionOccurrence(t1dConceptSet, male(), age(gte(18)))
+maleT1D18andOlderFirstDx <- conditionOccurrence(
+ t1dConceptSet, male(), age(gte(18)), firstOccurrence())
One special type of attribute is a nested query. This construct is +more complex and requires understanding of the criteria and +group objects. We will return to this idea later in this +vignette.
+A criteria object is one that enumerates the presence or +absence of an event within a window of observation relative to an index +point. The index point may be the entry event of the cohort definition. +It could also be a prior event if we are building a nested query. The +purpose of this object is to count whether a person has experienced +certain events that would either include or exclude them from the +cohort. Its easiest to show a criteria using a figure. Say +relative from index we want to see two exposures of a drug within 365 +days and 30 days before index. Those that fit that criteria remain in +the cohort, those that do not are excluded from the cohort. See the +figure below as an example:
+When building a criteria object the user needs: 1) a query, +2) an operator that specifies the number of times a query is observed +(occurrences), and 3) a time window which we call the aperture. Using +the figure as an example, think of the stars as the query, the number of +stars as the occurrences, and the box as the aperture. We could orient +this idea around the index event in a variety of different ways.
+With this definition in mind, let us build an example of a +criteria object that reflects the image above.
+
+atenololConceptSet <- cs(descendants(1314002), name - "atenolol")
+
+atenololCriteria <- atLeast(
+ x = 2,
+ query = drugExposure(atenololConceptSet),
+ aperture = duringInterval(
+ startWindow = eventStarts(a = -365, b = -30, index = "startDate")
+ )
+)
This criteria specifies that we must observe at least 2 drug
+exposures of atenolol within 365 days and 30 days before the index start
+date. By itself, a criteria makes little sense. It must sit
+within the context of the entire cohort definition, where an index event
+has been specified. In Capr
the criteria object is
+called in three ways: atLeast
, atMost
and
+exactly
. The criteria object in Capr
+is contextualized by the number of occurrences of the query for its
+function call. If we wanted to have exactly 2 drug exposures of atenolol
+or at most 2 drug exposures they can be done as shown below.
+atenololConceptSet <- cs(descendants(1314002), name - "atenolol")
+
+atenololCriteriaA <- exactly(
+ x = 2,
+ query = drugExposure(atenololConceptSet),
+ aperture = duringInterval(
+ startWindow = eventStarts(a = -365, b = -30, index = "startDate")
+ )
+)
+
+atenololCriteriaB <- atMost(
+ x = 2,
+ query = drugExposure(atenololConceptSet),
+ aperture = duringInterval(
+ startWindow = eventStarts(a = -365, b = -30, index = "startDate")
+ )
+)
An important part of the criteria object is providing the
+temporal context to enumerating the occurrences of the query. In
+Capr
we term this interval relative to index as the
+aperture. It is the opening in the patient timeline at which we are
+enumerating the event of interest. An aperture can view when an event
+starts and when the event ends. For both event start and event end, we
+define a window for which the event is observed. Below we illustrate a
+few examples of building an aperture and then show the corresponding the
+Capr
code.
In this first example we
+are observing when an event starts between time of 365 to 30 days before
+the index start date. To build this aperture we use the following
+Capr
code:
+aperture1 <- duringInterval(
+ startWindow = eventStarts(a = -365, b = -30, index = "startDate")
+)
Notice that we define the anchor for our index, either the index +start date or the index end date. More times than not this will be the +index start date.
+ This next
+example is similar to the first, however now we have an unbounded event
+window. In this case the event start must be between any time before and
+30 days before the index start date. In Capr
we can always
+create an unbounded event window by using the Inf
operator
+in our code, as shown below.
+aperture2 <- duringInterval(
+ startWindow = eventStarts(a = -Inf, b = -30, index = "startDate")
+)
Our next example
+provides an instance where we want our event window to utilize future
+time. Normally we want to observe an event prior to index. On occasion
+we can allow for an event to take place after index. The
+Capr
code to build this aperture is shown below:
+aperture3 <- duringInterval(
+ startWindow = eventStarts(a = -30, b = 30, index = "startDate")
+)
Our final example
+shows a scenario when we want the aperture to be constrained by both a
+start window and end window. The end window is considering observation
+of the end of the event. Say for example the event era starts with an
+exposure to a drug and end is when the person stops taking the drug. If
+the interest is the full time the person was encountering this medical
+event we need to create both a start and end window in the aperture. The
+Capr
code below would replicate the concept from the
+figure.
+aperture4 <- duringInterval(
+ startWindow = eventStarts(a = -365, b = -30, index = "startDate"),
+ endWindow = eventEnds(a = 30, b = 365, index = "startDate")
+)
An aperture has two more potential toggles: a) restrict event to the
+same visit and b) allow events outside the observation period. By
+default these options are toggled as FALSE
, so they do not
+need to be defined in the Capr
code unless made
+TRUE
. These are more advanced options in cohort building.
+To use the we add this to aperture example 4 to show a full set of
+options for an aperture in Capr
:
+aperture5 <- duringInterval(
+ startWindow = eventStarts(a = -365, b = -30, index = "startDate"),
+ endWindow = eventEnds(a = 30, b = 365, index = "startDate"),
+ restrictVisit = TRUE,
+ ignoreObservationPeriod = TRUE
+)
A group object is one that binds multiple criteria and
+sub-groups as a single expression. This is a very powerful construction
+because it allows us to build all sorts of complexity in our cohort
+definition. A group must have an operator informing how many
+criteria must be TRUE
in order for the person to
+enter the cohort. In Capr
the options available to build a
+group are: withAll
, withAny
,
+withAtLeast
and withAtMost
. The functions are
+meant to be intuitive in terms of logic building. withAll
+indicates all the criteria must be TRUE
for the person to
+remain in the cohort. withAny
indicates any one of the
+criteria needs to be TRUE
. The functions
+withAtLeast
and withAtMost
require an integer
+to determine how many criteria must be TRUE
.
To show the idea of a group let us consider a very
+complicated cohort, like the PheKB
+T2D case algorithm. To consider a person to be a case of T2D, any
+one of 5 pathways needs to be TRUE
.
+t2dAlgo <- withAny(
+ # Path 1: 0 T2Dx + 1 T2Rx + 1 abLab
+ withAll(
+ exactly(0,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ t2dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ withAny(
+ atLeast(1,
+ abLabHb,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ abLabRan,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ abLabFast,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ )
+ )
+ ),
+ #Path 2: 1 T2Dx + 0 T1Rx + 0 T2Rx + 1 AbLab
+ withAll(
+ atLeast(1,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ exactly(0,
+ t1dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ exactly(0,
+ t2dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ withAny(
+ atLeast(1,
+ abLabHb,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ abLabRan,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ abLabFast,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ )
+ )
+ ),
+ #Path 3: 1 T2Dx + 0 T1Rx + 1 T2Rx
+ withAll(
+ atLeast(1,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ exactly(0,
+ t1dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ t2dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ )
+ ),
+ #Path 4: 1 T2Dx + 1 T1Rx + 1 T1Rx|T2Rx
+ withAll(
+ atLeast(1,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ t1dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ t1dDrugWT2Drug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ )
+ ),
+ #Path 5: 1 T2Dx + 1 T1Rx + 0 T2Rx + 2 T2Dx
+ withAll(
+ atLeast(1,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ t1dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ exactly(0,
+ t2dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(2,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ )
+ )
+)
Each pathway is complex and require multiple criteria to determine a +T2D case. The group allows us to bundle multiple ideas together +to build one complex expression.
+Now that we have introduced the criteria and group,
+there are a few important comments on how these objects are used within
+circe-be
.
1) Criteria must be placed within a group
+A criteria can not be used on its own, it must be wrapped in +a group. Even if only one criteria is needed, still +wrap it in a group. An example would be:
+
+noT1d <- withAll(
+ # criteria: no t1d prior
+ exactly(
+ x = 0,
+ query = conditionOccurrence(t1dConceptSet),
+ aperture = duringInterval(
+ startWindow = eventStarts(a = -Inf, b = 0, index = "startDate")
+ )
+ )
+)
+# wrap this in a group withAll
Further to this point, a single attrition rule is a group.
+The example of noT1d
above would be a single rule in the
+cohort attrition. This is how we would apply it:
+cohort <- cohort(
+ entry = entry(
+ # index event....
+ ),
+ attrition = attrition(
+ 'noT1d' = withAll(
+ exactly(
+ x = 0,
+ # query for t1d occurrence to exclude patients
+ query = conditionOccurrence(t1dConceptSet),
+ aperture = duringInterval(
+ startWindow = eventStarts(a = -Inf, b = 0, index = "startDate")
+ )
+ )
+ )
+ ),
+ exit = exit(
+ #cohort exit....
+ )
+)
2) Groups may contain groups
+A group may contain more groups as part of the same object. We saw +this in the PheKB T2D example where one path required an abnormal lab. +In the definition there are 3 types of abnormal labs: random glucose, +fasting glucose and HbA1c. Any one of these three could be abnormal as +part of path 1 of the case algorithm. To build this we need a group +within a group.
+
+# Path 1: 0 T2Dx + 1 T2Rx + 1 abLab
+path1 <- withAll(
+ exactly(0,
+ t2d,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ t2dDrug,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ withAny(
+ atLeast(1,
+ abLabHb,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ abLabRan,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ ),
+ atLeast(1,
+ abLabFast,
+ duringInterval(startWindow = eventStarts(-Inf, 0))
+ )
+ )
+)
3) Nested criteria are groups
+Previously we mentioned a special kind of attribute called a nested
+criteria (also known via ATLAS as a correlated criteria). The idea of a
+nested criteria is that the index event is based on a particular concept
+set expression as opposed to the entry event of the cohort definition.
+For example, we want to build a cohort based on a hospitalization due to
+heart failure. In this case a person is counted in the cohort if they
+have first an inpatient visit given that a heart failure (HF) diagnosis
+has occurred around the time of the inpatient visit. In
+Capr
a nested attribute uses the same syntax as a
+group with a prefix of nested-
, as shown in the
+example below. The enumeration of the criteria is now indexed
+based on the inpatient visit rather than the entry event of the cohort
+definition.
+ipCse <- cs(descendants(9201, 9203, 262), name = "visit")
+hf <- cs(descendants(316139), name = "heart failure")
+
+query <- visit(
+ ipCse, #index
+ #nested attribute
+ nestedWithAll(
+ atLeast(1,
+ conditionOccurrence(hf),
+ duringInterval(
+ startWindow = eventStarts(0, Inf, index = "startDate"),
+ endWindow = eventStarts(-Inf, 0, index = "endDate")
+ )
+ )
+ )
+)
For more information on sub-components of a cohort definition via
+circe-be
, users should watch the videos created by
+Chris Knoll outlining these ideas. while these videos utilize ATLAS,
+Capr
follows the same principles.
+@@ -37,6 +37,9 @@cvEvents <- function(conceptSet) { cd <- cohort( entry = entry( - condition(conceptSet), + conditionOccurrence(conceptSet), observationWindow = continuousObservation(365, 0) ), exit = exit( @@ -147,7 +148,7 @@
Building a TemplateAthena, I look up the OMOP concept ids for the concepts of interest. With these concept ids, I can create a concept set for each cardiovascular event -
@@ -39,6 +39,9 @@+@@ -171,13 +172,13 @@afib <- cs(descendants(313217), name = "Atrial Fibrillation") stroke <- cs(descendants(4310996), name = "Ischemic Stroke") hyp <- cs(descendants(320128), name = "Hypertension") @@ -160,7 +161,7 @@
Building a Template
+Improving the Template -
++@@ -37,6 +37,9 @@cvEvents2 <- function(conceptSet) { #Capr template logic cd <- cohort( entry = entry( - condition(conceptSet), + conditionOccurrence(conceptSet), observationWindow = continuousObservation(365, 0) ), exit = exit( @@ -204,7 +205,7 @@
Building templates from concept se .csv or .json file that we can use towards the cohort template. We update our Capr template function to handle the import of a concept set, as shown below. -
@@ -68,6 +68,9 @@+cvEvents3 <- function(file) { # get file name @@ -216,7 +217,7 @@
Building templates from concept se #Capr template logic cd <- cohort( entry = entry( - condition(conceptSet), + conditionOccurrence(conceptSet), observationWindow = continuousObservation(365, 0) ), exit = exit( @@ -237,137 +238,10 @@
Building templates from concept se Luckily, we have a concept set from ATLAS that we used in a previous study that has this already detailed. We can import the csv file for this concept set and apply it to the Capr template. -
++cat(miCohort)miPath <- fs::path_package("Capr", "extdata/acuteMI.csv") miCohort <- cvEvents3(miPath) -cat(miCohort) -#> { -#> "ConceptSets": [ -#> { -#> "id": 0, -#> "name": "Inpatient or ER visit", -#> "expression": { -#> "items": [ -#> { -#> "concept": { -#> "CONCEPT_ID": 262, -#> "CONCEPT_NAME": "Emergency Room and Inpatient Visit", -#> "STANDARD_CONCEPT": "S", -#> "STANDARD_CONCEPT_CAPTION": "", -#> "INVALID_REASON": "", -#> "INVALID_REASON_CAPTION": "", -#> "CONCEPT_CODE": "ERIP", -#> "DOMAIN_ID": "Visit", -#> "VOCABULARY_ID": "Visit", -#> "CONCEPT_CLASS_ID": "" -#> }, -#> "isExcluded": false, -#> "includeDescendants": true, -#> "includeMapped": false -#> }, -#> { -#> "concept": { -#> "CONCEPT_ID": 9203, -#> "CONCEPT_NAME": "Emergency Room Visit", -#> "STANDARD_CONCEPT": "S", -#> "STANDARD_CONCEPT_CAPTION": "", -#> "INVALID_REASON": "", -#> "INVALID_REASON_CAPTION": "", -#> "CONCEPT_CODE": "ER", -#> "DOMAIN_ID": "Visit", -#> "VOCABULARY_ID": "Visit", -#> "CONCEPT_CLASS_ID": "" -#> }, -#> "isExcluded": false, -#> "includeDescendants": true, -#> "includeMapped": false -#> }, -#> { -#> "concept": { -#> "CONCEPT_ID": 9201, -#> "CONCEPT_NAME": "Inpatient Visit", -#> "STANDARD_CONCEPT": "S", -#> "STANDARD_CONCEPT_CAPTION": "", -#> "INVALID_REASON": "", -#> "INVALID_REASON_CAPTION": "", -#> "CONCEPT_CODE": "IP", -#> "DOMAIN_ID": "Visit", -#> "VOCABULARY_ID": "Visit", -#> "CONCEPT_CLASS_ID": "" -#> }, -#> "isExcluded": false, -#> "includeDescendants": true, -#> "includeMapped": false -#> }, -#> { -#> "concept": { -#> "CONCEPT_ID": 4329847, -#> "CONCEPT_NAME": "Myocardial infarction", -#> "STANDARD_CONCEPT": "S", -#> "STANDARD_CONCEPT_CAPTION": "", -#> "INVALID_REASON": "", -#> "INVALID_REASON_CAPTION": "", -#> "CONCEPT_CODE": "22298006", -#> "DOMAIN_ID": "Condition", -#> "VOCABULARY_ID": "SNOMED", -#> "CONCEPT_CLASS_ID": "" -#> }, -#> "isExcluded": false, -#> "includeDescendants": true, -#> "includeMapped": false -#> }, -#> { -#> "concept": { -#> "CONCEPT_ID": 314666, -#> "CONCEPT_NAME": "Old myocardial infarction", -#> "STANDARD_CONCEPT": "S", -#> "STANDARD_CONCEPT_CAPTION": "", -#> "INVALID_REASON": "", -#> "INVALID_REASON_CAPTION": "", -#> "CONCEPT_CODE": "1755008", -#> "DOMAIN_ID": "Condition", -#> "VOCABULARY_ID": "SNOMED", -#> "CONCEPT_CLASS_ID": "" -#> }, -#> "isExcluded": true, -#> "includeDescendants": true, -#> "includeMapped": false -#> } -#> ] -#> } -#> } -#> ], -#> "PrimaryCriteria": { -#> "CriteriaList": [ -#> { -#> "ConditionOccurrence": { -#> "CodesetId": 0 -#> } -#> } -#> ], -#> "ObservationWindow": { -#> "PriorDays": 365, -#> "PostDays": 0 -#> }, -#> "PrimaryCriteriaLimit": { -#> "Type": "First" -#> } -#> }, -#> "QualifiedLimit": { -#> "Type": "First" -#> }, -#> "ExpressionLimit": { -#> "Type": "First" -#> }, -#> "InclusionRules": [], -#> "CensoringCriteria": [], -#> "CollapseSettings": { -#> "CollapseType": "ERA", -#> "EraPad": 0 -#> }, -#> "CensorWindow": {}, -#> "cdmVersionRange": ">=5.0.0" -#> }
@@ -37,6 +37,9 @@Saving Capr cohorts @@ -376,7 +250,7 @@
Saving Capr cohortsreadr::write_file or the base R equivalent. -
@@ -37,6 +37,9 @@+diff --git a/docs/articles/images/aperture1.png b/docs/articles/images/aperture1.png new file mode 100644 index 00000000..b48c043d Binary files /dev/null and b/docs/articles/images/aperture1.png differ diff --git a/docs/articles/images/aperture2.png b/docs/articles/images/aperture2.png new file mode 100644 index 00000000..568f2d3b Binary files /dev/null and b/docs/articles/images/aperture2.png differ diff --git a/docs/articles/images/aperture3.png b/docs/articles/images/aperture3.png new file mode 100644 index 00000000..ff21a0c2 Binary files /dev/null and b/docs/articles/images/aperture3.png differ diff --git a/docs/articles/images/aperture4.png b/docs/articles/images/aperture4.png new file mode 100644 index 00000000..372e0548 Binary files /dev/null and b/docs/articles/images/aperture4.png differ diff --git a/docs/articles/images/criteria_example.png b/docs/articles/images/criteria_example.png new file mode 100644 index 00000000..bb02c0b6 Binary files /dev/null and b/docs/articles/images/criteria_example.png differ diff --git a/docs/articles/index.html b/docs/articles/index.html index 917cd175..663a6675 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -17,7 +17,7 @@outputPath <- fs::path(here::here("cohorts"), "miCohort", ext = "json") readr::write_file(miCohort, file = outputPath)
Capr Design Guide and Roadmap ++ Capr Objects + Capr for Templating Cohort Definitions @@ -79,6 +82,8 @@All vignettes
Capr Design Guide and Roadmap + Capr Objects +Capr for Templating Cohort Definitions Cohort Definition Examples diff --git a/docs/authors.html b/docs/authors.html index f0fb78cb..532583b1 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -17,7 +17,7 @@Capr Design Guide and Roadmap ++ Capr Objects + Capr for Templating Cohort Definitions diff --git a/docs/index.html b/docs/index.html index 8f097fbb..6ccaf345 100644 --- a/docs/index.html +++ b/docs/index.html @@ -46,7 +46,7 @@Capr Design Guide and Roadmap ++ Capr Objects + Capr for Templating Cohort Definitions @@ -124,249 +127,28 @@Introduction
Installation
-Capr can be installed via:
--# install.packages("Capr")
Users can install the current development version of Capr from GitHub with:
-+# install.packages("devtools") devtools::install_github("ohdsi/Capr")
--How to Use -
---Examples -
-Capr uses many defaults that match the defaults in Atlas. Creating a simple cohort is a single line of code. As an example we will define a cohort of new users of diclofenac described in the Book of OHDSI.
---Simple diclofenac cohort -
---library(Capr) - -# Define concepts sets with cs() -diclofenac <- cs(descendants(1124300)) - -ch <- cohort( - entry = entry(drugEra(diclofenac)) -) - -ch -#> Formal class 'Cohort' [package "Capr"] with 4 slots -#> ..@ entry :Formal class 'CohortEntry' [package "Capr"] with 5 slots -#> ..@ attrition:Formal class 'CohortAttrition' [package "Capr"] with 2 slots -#> ..@ exit :Formal class 'CohortExit' [package "Capr"] with 2 slots -#> ..@ era :Formal class 'CohortEra' [package "Capr"] with 3 slots
--Adding more complexity -
-We can make more complex cohorts by adding a window of continuous observation and a custom cohort exit. The following information was added to the diclofenac cohort:
--
-- Ages 16 or older
-- With at least 365 days of continuous observation prior to exposure
-- With cohort exit defined as discontinuation of exposure (allowing for a 30-day gap)
---diclofenac <- cs(descendants(1124300)) - -ch <- cohort( - entry = entry(drugEra(diclofenac, age(gte(16))), - observationWindow = continuousObservation(-365L, 0L)), - exit = exit(drugExit(diclofenac)) -) - -ch -#> Formal class 'Cohort' [package "Capr"] with 4 slots -#> ..@ entry :Formal class 'CohortEntry' [package "Capr"] with 5 slots -#> ..@ attrition:Formal class 'CohortAttrition' [package "Capr"] with 2 slots -#> ..@ exit :Formal class 'CohortExit' [package "Capr"] with 2 slots -#> ..@ era :Formal class 'CohortEra' [package "Capr"] with 3 slots
--Adding cohort attrition -
-Users can also add attrition to the cohort by specifying inclusion and exclusion criteria to modify the cohort entry. The following exclusion criteria were added to the diclofenac cohort:
--
-- Without prior exposure to any NSAID (Non-Steroidal Anti-Inflammatory Drug)
-- Without prior diagnosis of cancer
---diclofenac <- cs(descendants(1124300), name = "diclofenac") -nsaid <- cs(descendants(21603933), name = "nsaid") -cancer <- cs(descendants(443392), name = "cancer") - -ch <- cohort( - entry = entry(drugEra(diclofenac, age(gte(16))), - observationWindow = continuousObservation(-365L, 0L)), - attrition = attrition( - withAll( - exactly(0, drug(nsaid), eventStarts(-Inf, 0, index = "startDate")), - exactly(0, condition(cancer), eventStarts(-Inf, 0, index = "startDate")) - ) - ), - exit = exit( - endStrategy = drugExit(diclofenac, persistenceWindow = 30) - ) -) - -ch -#> Formal class 'Cohort' [package "Capr"] with 4 slots -#> ..@ entry :Formal class 'CohortEntry' [package "Capr"] with 5 slots -#> ..@ attrition:Formal class 'CohortAttrition' [package "Capr"] with 2 slots -#> ..@ exit :Formal class 'CohortExit' [package "Capr"] with 2 slots -#> ..@ era :Formal class 'CohortEra' [package "Capr"] with 3 slots
--Save cohort as JSON -
-OHDSI standard cohorts are represented as json files and can be copy and pasted into Atlas.
----path <- file.path(tempdir(), "diclofenacCohort.json") - -writeCohort(ch, path) - -cat(substr(readr::read_file(path), 1, 100)) -#> { -#> "ConceptSets": [ -#> { -#> "id": 0, -#> "name": "diclofenac", -#> "expression": { -#>
--Fill in missing concept set details -
-Users can build valid cohorts with minimal concept information, only supplying a concept id and name. The example below shows the minimal concept set input for Capr.
----diclofenac <- cs(descendants(1124300), name = "diclofenac") - -cat(as.json(diclofenac)) -#> { -#> "id": "11d012608fce118593830a3039042e56", -#> "name": "diclofenac", -#> "expression": { -#> "items": [ -#> { -#> "concept": { -#> "CONCEPT_ID": 1124300, -#> "CONCEPT_NAME": "", -#> "STANDARD_CONCEPT": "", -#> "STANDARD_CONCEPT_CAPTION": "", -#> "INVALID_REASON": "", -#> "INVALID_REASON_CAPTION": "", -#> "CONCEPT_CODE": "", -#> "DOMAIN_ID": "", -#> "VOCABULARY_ID": "", -#> "CONCEPT_CLASS_ID": "" -#> }, -#> "isExcluded": false, -#> "includeDescendants": true, -#> "includeMapped": false -#> } -#> ] -#> } -#> }
However, when saving cohorts it is helpful to fill in the concept details. This requires a live connection to an OMOP CDM database that includes the vocabularies used in the cohort definition.
---con <- DatabaseConnector::connect(Eunomia::getEunomiaConnectionDetails()) -diclofenac <- getConceptSetDetails(diclofenac, con, vocabularyDatabaseSchema = "main") -cat(as.json(diclofenac)) -#> { -#> "id": "11d012608fce118593830a3039042e56", -#> "name": "diclofenac", -#> "expression": { -#> "items": [ -#> { -#> "concept": { -#> "CONCEPT_ID": 1124300, -#> "CONCEPT_NAME": "Diclofenac", -#> "STANDARD_CONCEPT": "S", -#> "STANDARD_CONCEPT_CAPTION": "Standard", -#> "INVALID_REASON": "V", -#> "INVALID_REASON_CAPTION": "Valid", -#> "CONCEPT_CODE": "3355", -#> "DOMAIN_ID": "Drug", -#> "VOCABULARY_ID": "RxNorm", -#> "CONCEPT_CLASS_ID": "Ingredient" -#> }, -#> "isExcluded": false, -#> "includeDescendants": true, -#> "includeMapped": false -#> } -#> ] -#> } -#> }
--Generating Capr Cohorts -
-Once a Capr cohort has been constructed, the user can generate this cohort definition on an OMOP CDM connection. It is suggested to use CohortGenerator and CirceR to generate Capr cohorts on a database.
---Building Capr Templates -
-A Capr cohort template is a function that always returns a Capr cohort. It can accept arguments that can be used to parameterize any part of a cohort definition. Capr cohort templates are the recommended approach for building large numbers of similar cohorts in R.
----# A Capr cohort template is a function that returns a cohort -drugEraTemplate <- function(ingredientConceptId) { - - drugConceptSet <- cs(descendants(ingredientConceptId)) - - cohort( - entry = entry(drugEra(drugConceptSet, age(gte(16))), - observationWindow = continuousObservation(-365L, 0L)), - exit = exit(drugExit(drugConceptSet, persistenceWindow = 30)) - ) -} - - -library(dplyr, warn.conflicts = FALSE) - -# create a cohort for every single ingredient -df <- DBI::dbGetQuery(con, - "Select * from concept where concept_class_id = 'Ingredient'") %>% - tibble() %>% - select(concept_id, concept_name) %>% - mutate(capr_cohort = purrr::map(concept_id, drugEraTemplate)) %>% - mutate(cohort_json = purrr::map_chr(capr_cohort, as.json)) - -df -#> # A tibble: 91 × 4 -#> concept_id concept_name capr_cohort cohort_json -#> <dbl> <chr> <list> <chr> -#> 1 1557272 Alendronate <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 2 708298 Midazolam <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 3 701322 Memantine <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 4 723013 Diazepam <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 5 1129625 Diphenhydramine <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 6 1149196 Cetirizine <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 7 1149380 fluticasone <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 8 1150770 Astemizole <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 9 1150836 Terfenadine <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> 10 1124300 Diclofenac <Cohort> "{\n \"ConceptSets\": [\n {\n … -#> # … with 81 more rows
The capr_cohort column of the dataframe is a list of Capr cohort object. The cohort_json column contains the json specifications for each cohort.
---DatabaseConnector::disconnect(con)
diff --git a/docs/news/index.html b/docs/news/index.html index f602e6bd..19bf366f 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -17,7 +17,7 @@User Documentation
Documentation can be found on the package website.
+PDF versions of the documentation are also available:
-
- Vignette: Using Capr +
- Vignette: Using Capr +
+- Vignette: Capr Examples +
+- Vignette: Working with Concept Sets in Capr +
+- Vignette: Capr for Templating Cohort Definitions
-- Vignette: Examples +
- Vignette: Capr components
-- Design Document
+- Design Document
- Package manual
Capr Design Guide and Roadmap ++ Capr Objects + Capr for Templating Cohort Definitions @@ -72,6 +75,13 @@Changelog
Source:NEWS.md
+Capr 2.0.5
+
- change query functions to match known syntax (i.e. drug => drugExposure, condition => conditionOccurrence)
+- require a name for
+cs()
+- improve documentation (add vignette for query, count and group)
+@@ -38,6 +38,9 @@Capr 2.0.4
- hot fix add procedure occurrence into query
diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 21d2d712..ce97bf9f 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -4,8 +4,9 @@ pkgdown_sha: ~ articles: Capr-conceptSets: Capr-conceptSets.html capr_design: capr_design.html + capr_objects: capr_objects.html capr_templates: capr_templates.html Examples: Examples.html Using-Capr: Using-Capr.html -last_built: 2023-06-13T19:42Z +last_built: 2023-07-03T17:28Z diff --git a/docs/reference/Capr-package.html b/docs/reference/Capr-package.html index 478e324a..92efe96b 100644 --- a/docs/reference/Capr-package.html +++ b/docs/reference/Capr-package.html @@ -18,7 +18,7 @@Capr Design Guide and Roadmap ++ Capr Objects + Capr for Templating Cohort Definitions diff --git a/docs/reference/CensoringCriteria-class.html b/docs/reference/CensoringCriteria-class.html index bc079fa7..083d2a9a 100644 --- a/docs/reference/CensoringCriteria-class.html +++ b/docs/reference/CensoringCriteria-class.html @@ -19,7 +19,7 @@Capr Design Guide and Roadmap ++ Capr Objects + Capr for Templating Cohort Definitions diff --git a/docs/reference/Concept-class.html b/docs/reference/Concept-class.html index 5edfd275..86ba0cd3 100644 --- a/docs/reference/Concept-class.html +++ b/docs/reference/Concept-class.html @@ -17,7 +17,7 @@
if (FALSE) {
# Create a cohort of males with Type 1 diabetes
t1dm <- cs(descendants(201254, 435216, 40484648))
-t1dm_males <- cohort(condition(t1dm, male()))
+t1dm_males <- cohort(condition(t1dm, male()))
}
if (FALSE) {
# Create a cohort of males with Type 1 diabetes
t1dm <- cs(descendants(201254, 435216, 40484648))
-t1dm_females <- cohort(condition(t1dm, female()))
+t1dm_females <- cohort(condition(t1dm, female()))
}
Query the condition domain
+conditionOccurrence(conceptSet, ...)
A condition concept set
optional attributes
A Capr Query
+cs(..., name = "", id = NULL)
+ cs(..., name, id = NULL)
exclude(...)
diff --git a/docs/reference/daysOfSupply.html b/docs/reference/daysOfSupply.html
index db4db445..94219f52 100644
--- a/docs/reference/daysOfSupply.html
+++ b/docs/reference/daysOfSupply.html
@@ -19,7 +19,7 @@
@@ -39,6 +39,9 @@
Capr Design Guide and Roadmap
+
+ Capr Objects
+
Capr for Templating Cohort Definitions
diff --git a/docs/reference/death.html b/docs/reference/death.html
index e994d363..124f7be4 100644
--- a/docs/reference/death.html
+++ b/docs/reference/death.html
@@ -17,7 +17,7 @@
Query the drug domain
+drugExposure(conceptSet, ...)
A drug concept set
optional attributes
A Capr Query
+ConceptSetItem-class
An S4 class for ConceptSetItem
Query the condition domain
Query the condition era domain
Query the condition domain
death()
Query the condition era domain
Query the drug domain
drugExit()
Function to create an exit based on exit based on the end of a continuous drug exposure
Query the drug domain
if (FALSE) {
cs1 <- cs(descendants(exclude(436665),440383,442306,4175329))
cs1 <- getConceptSetDetails(cs1)
-x <- cohort(condition(cs1))
+x <- cohort(condition(cs1))
writeCohort(x, "cohortDefinition.json")
}