This vignette provides a number of example cohorts built with Capr from the OHDSI Phenotype Phebruary event.

Type 2 diabetes mellitus

Persons with new type 2 diabetes mellitus at first diagnosis

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/88/definition

cs0 <- cs(descendants(443238, 201820, 442793), 
          descendants(exclude(195771, 201254, 435216, 761051, 4058243, 40484648)),
          name = "Type 2 diabetes mellitus (diabetes mellitus excluding T1DM and secondary)")

ch <- cohort(
  entry = entry(
    conditionOccurrence(cs0),
    observationWindow = continuousObservation(priorDays = 365)
  ),
  exit = exit(
    endStrategy = observationExit()
  )
)

chJson <- toCohortJson(ch)

Persons with new type 2 diabetes and no prior T1DM or secondary diabetes

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/89/export

cs0 <- cs(descendants(443238, 201820, 442793), 
          descendants(exclude(195771, 201254, 435216, 761051, 4058243, 40484648)),
          name = "Type 2 diabetes mellitus (diabetes mellitus excluding T1DM and secondary)")

cs1 <- cs(descendants(201254, 435216, 40484648),
          name = "Type 1 diabetes mellitus")

cs2 <- cs(descendants(195771),
          name = "Secondary diabetes mellitus")

ch <- cohort(
  entry = entry(
    conditionOccurrence(cs0),
    observationWindow = continuousObservation(priorDays = 365)
  ),
  attrition = attrition(
    't1d' = withAll(
    exactly(0, conditionOccurrence(cs1), duringInterval(eventStarts(-Inf, 0)))
    ),
    'secondaryDiabetes' = withAll(
    exactly(0, conditionOccurrence(cs2), duringInterval(eventStarts(-Inf, 0)))
    )
  ),
  exit = exit(
    endStrategy = observationExit()
  )
)

chJson <- toCohortJson(ch)

Persons with new type 2 diabetes mellitus at first dx rx or lab

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/90

cs0 <- cs(descendants(443238, 201820, 442793), 
          descendants(exclude(195771, 201254, 435216, 761051, 4058243, 40484648)),
          name = "Type 2 diabetes mellitus (diabetes mellitus excluding T1DM and secondary)")

cs1 <- cs(descendants(201254, 435216, 40484648),
          name = "Type 1 diabetes mellitus")

cs2 <- cs(descendants(195771),
          name = "Secondary diabetes mellitus")

cs3 <- cs(descendants(4184637, 37059902),
          name = "Hemoglobin A1c (HbA1c) measurements")

cs4 <- cs(descendants(21600744),
          name = "Drugs for diabetes except insulin")


ch <- cohort(
  entry = entry(
    conditionOccurrence(cs0),
    drugExposure(cs4),
    measurement(cs3, valueAsNumber(bt(6.5, 30)), measurementUnit(8554L)),   # percent
    measurement(cs3, valueAsNumber(bt(48, 99)), measurementUnit(9579L)),    # mmol/mol
    observationWindow = continuousObservation(priorDays = 365)
  ),
  attrition = attrition(
    'no T1D' = withAll(
      exactly(0, conditionOccurrence(cs1), duringInterval(eventStarts(-Inf, 0)))
      ),
    'no secondary diabetes' = withAll(
      exactly(0, conditionOccurrence(cs2), duringInterval(eventStarts(-Inf, 0)))
    )
  ),
  exit = exit(
    endStrategy = observationExit()
  )
)

chJson <- toCohortJson(ch)

Type 1 diabetes mellitus

Persons with new type 1 diabetes

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/92

cs0 <- cs(descendants(195771),
          name = "Type 1 diabetes mellitus")

ch <- cohort(
  entry = entry(
    conditionOccurrence(cs0),
    observationWindow = continuousObservation(priorDays = 365)
  )
)

chJson <- toCohortJson(ch)

Persons with new type 1 diabetes and no prior T2DM or secondary diabetes

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/91


cs0 <- cs(descendants(443238, 201820, 442793), 
          descendants(exclude(195771, 201254, 435216, 761051, 4058243, 40484648)),
          name = "Type 2 diabetes mellitus (diabetes mellitus excluding T1DM and secondary)")

cs1 <- cs(descendants(201254, 435216, 40484648),
          name = "Type 1 diabetes mellitus")

cs2 <- cs(descendants(195771),
          name = "Secondary diabetes mellitus")

ch <- cohort(
  entry = entry(
    conditionOccurrence(cs1),
    observationWindow = continuousObservation(priorDays = 365)
  ),
  attrition = attrition(
    "no prior T2DM" = withAll(exactly(0, conditionOccurrence(cs0), duringInterval(eventStarts(-Inf, 0)))),
    "no prior secondary T1DM" = withAll(exactly(0, conditionOccurrence(cs2), duringInterval(eventStarts(-Inf, 0))))
  )
)

chJson <- toCohortJson(ch)

Atrial Fibrillation

Persons with atrial fibrillation per Wharton et al 2021

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/93


cs0 <- cs(descendants(313217),
          name = "Atrial fibrillation")

ch <- cohort(conditionOccurrence(cs0))

chJson <- toCohortJson(ch)

Persons with atrial fibrillation per Subramanya et al 2021

https://atlas-phenotype.ohdsi.org/#/cohortdefinition/94


afib <- cs(descendants(313217),
           name = "Atrial fibrillation")

ip <- cs(descendants(262, 9201),
         name = "Inpatient or inpatient ER visit")

op <- cs(descendants(9202, 9203),
         name = "Outpatient or ER visit")

ch <- cohort(
  entry = entry(
    conditionOccurrence(
      conceptSet = afib,
      nestedWithAll(
        # an inpatient afib
        atLeast(
          x = 1, 
          aperture = duringInterval(eventStarts(-Inf, 0), eventEnds(0, Inf)),
          query = visit(conceptSet = ip)
        )
      )
    ), 
    conditionOccurrence(
      conceptSet = afib,
      nestedWithAll(
        # 2 afib in outpatient
        atLeast(
          x = 1,
          aperture = duringInterval(eventStarts(-Inf, 0), eventEnds(0, Inf)),
          query = visit(
            conceptSet = op, 
            nestedWithAll(
              atLeast(
                x = 1, 
                aperture = duringInterval(eventStarts(7, 365)),
                query = conditionOccurrence(
                  conceptSet = afib, 
                  nestedWithAll(
                    atLeast(
                      x = 1, 
                      aperture = duringInterval(eventStarts(-Inf, 0), eventEnds(0, Inf)),
                      query = visit(conceptSet = op)
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
    
  )
)

chJson <- toCohortJson(ch)

Source Concept Example


lf <- cs(descendants(4197819), name = "lung fibrosis")
lfSource <- cs(
  725357,35208074,45543276,45548125,45552899,45562465,45567273,45581864,45586679,45586680,45601135,
  name = "Lung Fibrosis Source"
)

# Want cohort where entry is lung fibrosis but only using source ICD10CM codes

cd <- cohort(
  entry = entry(
    conditionOccurrence(
      conceptSet = lf,
      conditionSourceConcept(lfSource) # add source concept as attribute
    ),
    observationWindow = continuousObservation(365L, 0L),
    primaryCriteriaLimit = "First"
  )
)

cdJson <- toCohortJson(cd)

Primary Criteria Limit: First vs All

Regardless of entry criteria complexity:

  • Era cohort -> primaryCriteriaLimit = "First", expressionLimit = "First", no era collapse
  • Occ cohort -> primaryCriteriaLimit = "All", expressionLimit = "All", era = era(eraDays = 99999L)

The two patterns below show different ways to get one row per person:

  • Era version: take the first qualifying event and follow until end of continuous observation.
  • Occ version: take all qualifying events and stitch them into one long era from first to last event.

Example 1: Nested criteria with prior diagnosis requirement

1a. Era version

# Placeholder concept IDs for disease of interest
disease_concept_set <- c(201826L)

# Index event: first diagnosis with a prior diagnosis at least 365 days earlier
diagnosisEraCohort <- cohort(
  entry = entry(
    conditionOccurrence(
      conceptSet = cs(disease_concept_set, name = "Disease"),
      nestedWithAll(
        atLeast(
          1,
          conditionOccurrence(conceptSet = cs(disease_concept_set, name = "Disease")),
          aperture = duringInterval(eventStarts(-Inf, -365))
        )
      )
    ),
    primaryCriteriaLimit = "First"
  ),
  attrition = attrition(
    expressionLimit = "First"
  ),
  exit = exit(
    endStrategy = observationExit()
  )
)

diagnosisEraJson <- toCohortJson(diagnosisEraCohort)

1b. Occ version (same cohort logic, different type)

# Entry at each diagnosis with a prior diagnosis at least 365 days earlier
diagnosisOccCohort <- cohort(
  entry = entry(
    conditionOccurrence(
      conceptSet = cs(disease_concept_set, name = "Disease"),
      nestedWithAll(
        atLeast(
          1,
          conditionOccurrence(conceptSet = cs(disease_concept_set, name = "Disease")),
          aperture = duringInterval(eventStarts(-Inf, -365))
        )
      )
    ),
    primaryCriteriaLimit = "All"
  ),
  attrition = attrition(
    expressionLimit = "All"
  ),
  exit = exit(
    endStrategy = fixedExit(offsetDays = 0L)
  ),
  era = era(eraDays = 99999L)
)

diagnosisOccJson <- toCohortJson(diagnosisOccCohort)