OHDSI Home | Forums | Wiki | Github

SOS AntiVegfKidneyFailure Exposure Cohort Review

I really enjoyed @asieh’s presentation yesterday on building out the exposure cohort for the
AntiVegfKidneyFailure SOS study.

I want to bring up some questions I had with the definition though. First a quick review of the definition.

According to the protocol the cohort is described as:

"Patients ≥18 years who have received ≥3 monthly intravitreal anti-VEGF injections with ranibizumab, aflibercept, or bevacizumab for a diagnosis of DME/DR, AMD, and VO will be included in the study. Cohort entry will begin with the initiation of the anti-VEGF medications. Patients with pre-existing kidney failure will be excluded. (Figure 1, Figure 2) For the primary analysis, only patients who are on monotherapy (e.g., only ranibizumab, only aflibercept, only bevacizumab) will be included.

Here are the graphical representation presented by on the OHDSI community call.

A few differences I notice between the text and image are

  • The picture identifies only bevacizumab while the text describes all anti-VEGF medications. Is the idea that we would have similar logic for each anti-VEGF drug? Would these other drugs be added to this cohort or created a separate cohort definitions?
  • The protocol says “Cohort entry will begin with the initiation of the anti-VEGF medications.” but the picture shows cohort entry at the third bevacizumab exposure. Should a person who has kidney failure after their first bevacizumab exposure be excluded?
  • According to the picture the first bevacizumab exposure in the sequence must be the first in the person’s history. I’m not sure I see that requirement in the text though. For example if a person had bevacizumab exposures on days Jan 1, 2020; Jan 1, 2021; Feb 1, 2021, March 1, 2021 then they would not be included in the study be cause of the “first ever” requirement.

Here is the cohort definition in Atlas as implemented on the OHDSI community call.

  • One difference between the picture and the Atlas implementation I see is that it appears to me that four bevacizumab are required to be included in this cohort. So A person with the exact sequence in the picture would not be included because they did not have four bevacizumab exposures.

I tried this cohort on a real EHR dataset and it returned 0 persons. I broke out the single inclusion criteria into multiple steps that are increasingly restrictive and these are the results.

image

I also looked at the distribution of all bevacizumab exposures exposure relative to the first AMD condition. Here is a boxplot summary of the first 10 bevacizumab exposures for each person relative to first AMD diagnosis. The top boxplot shows the distribution of day of bevacizumab exposure relative to first AMD diagnosis. The second boxplot (labeled 2 on the y axis) is the distribution of the second bevacizumab exposure relative to first AMD diagnosis. And so on.

Here is a table of median times for each of the first 20 bevacizumab exposures

Hope this helps with this cohort design!

Thanks very much @Adam_Black , this is quite helpful. Indeed, the protocol has to be revised, that’s on Cindy’s to-do list, after we discussed what is needed (which is aligned to what @agolozar presented). Long story short: for an estimation study, we need an index date that cleanly delineates baseline time from follow-up time, and so it’s important to have 3rd exposure to look back for prior 2 exposures, not start on first and look forward to find next 2 exposures.

Re: the comment about looking like you need 4 exposures, strictly speaking this cohort finds ALL exposures ON or after the 3rd, do will get the 3rd, 4th, 5th, etc., and then will era-fy them together.

The distribution data is helpful to see that we can feel good with the 21d-70d interval we’re using to find the sequence of 3 treatments, in this EHR.

I tried to create a simple test of this cohort definition to test if it is indeed possible to pick up persons with only three bevacizumab exposures. However I could not create a passing test with Eunomia. I’m not sure what I’m doing wrong but here is my code. In addition to the actual cohort I also tried a very simple bevacizumab cohort definition.

library(dplyr, warn.conflicts = F)
# devtools::install_github("OHDSI/Eunomia", "develop")

connectionDetails <- DatabaseConnector::createConnectionDetails(
  dbms = "duckdb", 
  server = Eunomia::eunomiaDir("GiBleed", dbms = "duckdb")
)

cohortDefinitionSet <- ROhdsiWebApi::exportCohortDefinitionSet(
  baseUrl = "https://atlas-demo.ohdsi.org/WebAPI",
  cohortIds = c(1782491, 1782502)
)
#> Fetching cohortId: 1782491
#> Fetching cohortId: 1782502

nm <- CohortGenerator::getCohortTableNames()
con <- DatabaseConnector::connect(connectionDetails)
#> Connecting using DuckDB driver

CohortGenerator::createCohortTables(connection = con, 
                                    cohortDatabaseSchema = "main",
                                    cohortTableNames = nm)
#> Currently in a tryCatch or withCallingHandlers block, so unable to add global calling handlers. ParallelLogger will not capture R messages, errors, and warnings, only explicit calls to ParallelLogger. (This message will not be shown again this R session)
#> Creating cohort tables took 0.24secs

CohortGenerator::generateCohortSet(connection = con,
                                   cdmDatabaseSchema = "main",
                                   cohortDatabaseSchema = "main",
                                   cohortDefinitionSet = cohortDefinitionSet,
                                   cohortTableNames = nm)
#> 1/2- Generating cohort: [SOS Phenotype Devt] bevacizumab exposures cohort SHELL

#> Executing SQL took 0.481 secs
#> 2/2- Generating cohort: bevacizumab exposure

#> Executing SQL took 0.0326 secs
#> Generating cohort set took 1.05 secs

DatabaseConnector::querySql(con, "select * from main.cohort")
#> [1] COHORT_DEFINITION_ID SUBJECT_ID           COHORT_START_DATE   
#> [4] COHORT_END_DATE     
#> <0 rows> (or 0-length row.names)
# looks like the image of this definition on GiBleed Eunomia is empty

# Let's now insert records for a person, say person Id 1

DBI::dbExecute(con, "delete from main.condition_occurrence where person_id = 1")
#>   |                                                                              |                                                                      |   0%  |                                                                              |======================================================================| 100%
#> Executing SQL took 0.00665 secs
#> numeric(0)
DBI::dbExecute(con, "delete from main.drug_exposure where person_id = 1")
#>   |                                                                              |                                                                      |   0%  |                                                                              |======================================================================| 100%
#> Executing SQL took 0.00811 secs
#> numeric(0)


drugs_to_add <- tribble(
  ~drug_exposure_id, ~person_id, ~drug_concept_id, ~drug_exposure_start_date, ~drug_exposure_end_date,
  100000,                   1,          1397141,          "2000-01-01",              "2000-01-02",
  100001,                   1,          1397141,          "2000-02-01",              "2000-02-02",
  100002,                   1,          1397141,          "2000-03-01",              "2000-03-02"
) %>% 
  mutate(drug_type_concept_id = 32817)

conditions_to_add <- tibble(
  condition_occurrence_id = 1000000, 
  person_id = 1, 
  condition_concept_id = 374028,
  condition_start_date = "1999-12-01", 
  condition_end_date = "1999-12-02",
  condition_type_concept_id = 32020)


DBI::dbWriteTable(con, "drug_exposure", drugs_to_add, append = TRUE)
#> Inserting data took 0.018 secs
DBI::dbWriteTable(con, "condition_occurrence", conditions_to_add, append = TRUE)
#> Inserting data took 0.0254 secs

# check that these records are in the cdm now

DBI::dbGetQuery(con, "select * from main.drug_exposure where person_id = 1")[,1:4]
#>   drug_exposure_id person_id drug_concept_id drug_exposure_start_date
#> 1           100000         1         1397141               2000-01-01
#> 2           100001         1         1397141               2000-02-01
#> 3           100002         1         1397141               2000-03-01
DBI::dbGetQuery(con, "select * from main.condition_occurrence where person_id = 1")[,1:4]
#>   condition_occurrence_id person_id condition_concept_id condition_start_date
#> 1                   1e+06         1               374028           1999-12-01
DBI::dbGetQuery(con, "select * from main.observation_period where person_id = 1")[,1:4]
#>   observation_period_id person_id observation_period_start_date
#> 1                     1         1                    1949-01-28
#>   observation_period_end_date
#> 1                  2019-05-24

# So we should have at least one person who meets the cohort definition right?

CohortGenerator::generateCohortSet(connection = con,
                                   cdmDatabaseSchema = "main",
                                   cohortDatabaseSchema = "main",
                                   cohortDefinitionSet = cohortDefinitionSet,
                                   cohortTableNames = nm)
#> 1/2- Generating cohort: [SOS Phenotype Devt] bevacizumab exposures cohort SHELL


#> Executing SQL took 0.468 secs
#> 2/2- Generating cohort: bevacizumab exposure

#> Executing SQL took 0.0306 secs
#> Generating cohort set took 0.78 secs

DatabaseConnector::querySql(con, "select * from main.cohort")
#> [1] COHORT_DEFINITION_ID SUBJECT_ID           COHORT_START_DATE   
#> [4] COHORT_END_DATE     
#> <0 rows> (or 0-length row.names)

# But still nothing....

# Lets try adding a fourth drug exposure
drugs_to_add2 <- tribble(
  ~drug_exposure_id, ~person_id, ~drug_concept_id, ~drug_exposure_start_date, ~drug_exposure_end_date,
  100003,                   1,          1397141,          "2000-04-01",              "2000-04-02"
)
DBI::dbWriteTable(con, "drug_exposure", drugs_to_add2, append = TRUE)
#> Inserting data took 0.0104 secs

DBI::dbGetQuery(con, "select * from main.drug_exposure where person_id = 1")[,1:4]
#>   drug_exposure_id person_id drug_concept_id drug_exposure_start_date
#> 1           100000         1         1397141               2000-01-01
#> 2           100001         1         1397141               2000-02-01
#> 3           100002         1         1397141               2000-03-01
#> 4           100003         1         1397141               2000-04-01
DBI::dbGetQuery(con, "select * from main.condition_occurrence where person_id = 1")[,1:4]
#>   condition_occurrence_id person_id condition_concept_id condition_start_date
#> 1                   1e+06         1               374028           1999-12-01

CohortGenerator::generateCohortSet(connection = con,
                                   cdmDatabaseSchema = "main",
                                   cohortDatabaseSchema = "main",
                                   cohortDefinitionSet = cohortDefinitionSet,
                                   cohortTableNames = nm)
#> 1/2- Generating cohort: [SOS Phenotype Devt] bevacizumab exposures cohort SHELL

#> Executing SQL took 0.464 secs
#> 2/2- Generating cohort: bevacizumab exposure

#> Executing SQL took 0.0284 secs
#> Generating cohort set took 0.72 secs

DatabaseConnector::querySql(con, "select * from main.cohort")
#> [1] COHORT_DEFINITION_ID SUBJECT_ID           COHORT_START_DATE   
#> [4] COHORT_END_DATE     
#> <0 rows> (or 0-length row.names)

# still nothing

DatabaseConnector::disconnect(con)

Created on 2023-04-12 with reprex v2.0.2

Update: I think the issue is that the concepts being used are not in the mini-eunomia vocabulary. I tried adding them but that gave me a different error when I generated the cohorts.

1 Like

One thing I see from the distribution of timepoints of first bevacizumab exposure relative to first AMD condition is that more than half of people taking bevacizumab have their first ever bevacizumab exposure before their first AMD diagnosis and as such will be excluded from this cohort definition since it requires AMD prior to the first ever bevacizumab exposure.

1 Like

Yes, and thats intentional. Bevacizumab is indicated for various cancers and is off-label use for opthamalogy. So we require seeing the AMD pre-exposure to reduce risk of indication misclassification, so that we aren’t observing exposure for its primary indications. Heres the Avastin product label: DailyMed - AVASTIN- bevacizumab injection, solution

2 Likes

Maybe the intraocular application can be possibly distinguished by using the details of the medication record. (route of administration or drug packaging). But I have to do some research on what drug forms are used in cancer indication.

As background research, it would be interesting to see the drug forms we observe in a given database for bevacizumab.
Also, what percentage of ophthalmic-ever-bevacizumab users are also at the same time cancer-ever-bevacizumab users. Using a visit to eye doctor as factor in the definition is another possibility.

t