Last updated: 2026-03-31

Checks: 7 0

Knit directory: genomics_ancest_disease_dispar/

This reproducible R Markdown analysis was created with workflowr (version 1.7.2). The Checks tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.


Great! Since the R Markdown file has been committed to the Git repository, you know the exact version of the code that produced these results.

Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.

The command set.seed(20220216) was run prior to running the code in the R Markdown file. Setting a seed ensures that any results that rely on randomness, e.g. subsampling or permutations, are reproducible.

Great job! Recording the operating system, R version, and package versions is critical for reproducibility.

Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.

Great job! Using relative paths to the files within your workflowr project makes it easier to run your code on other machines.

Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility.

The results in this page were generated with repository version f3cf2b5. See the Past versions tab to see a history of the changes made to the R Markdown and HTML files.

Note that you need to be careful to ensure that all relevant files for the analysis have been committed to Git prior to generating the results (you can use wflow_publish or wflow_git_commit). workflowr only checks the R Markdown file, but you know if there are other scripts or data files that it depends on. Below is the status of the Git repository when the results were generated:


Ignored files:
    Ignored:    .DS_Store
    Ignored:    .Rproj.user/
    Ignored:    .venv/
    Ignored:    BC2GM/
    Ignored:    BioC.dtd
    Ignored:    FormatConverter.jar
    Ignored:    FormatConverter.zip
    Ignored:    analysis/.DS_Store
    Ignored:    ancestry_dispar_env/
    Ignored:    code/.DS_Store
    Ignored:    code/full_text_conversion/.DS_Store
    Ignored:    data/.DS_Store
    Ignored:    data/RCDCFundingSummary_01042026.xlsx
    Ignored:    data/cdc/
    Ignored:    data/cohort/
    Ignored:    data/epmc/
    Ignored:    data/europe_pmc/
    Ignored:    data/gbd/.DS_Store
    Ignored:    data/gbd/IHME-GBD_2021_DATA-d8cf695e-1.csv
    Ignored:    data/gbd/IHME-GBD_2023_DATA-73cc01fd-1.csv
    Ignored:    data/gbd/gbd_2019_california_percent_deaths.csv
    Ignored:    data/gbd/ihme_gbd_2019_global_disease_burden_rate_all_ages.csv
    Ignored:    data/gbd/ihme_gbd_2019_global_paf_rate_percent_all_ages.csv
    Ignored:    data/gbd/ihme_gbd_2021_global_disease_burden_rate_all_ages.csv
    Ignored:    data/gbd/ihme_gbd_2021_global_paf_rate_percent_all_ages.csv
    Ignored:    data/gwas_catalog/
    Ignored:    data/icd/.DS_Store
    Ignored:    data/icd/2025AA/
    Ignored:    data/icd/IHME_GBD_2019_COD_CAUSE_ICD_CODE_MAP_Y2020M10D15.XLSX
    Ignored:    data/icd/IHME_GBD_2019_NONFATAL_CAUSE_ICD_CODE_MAP_Y2020M10D15.XLSX
    Ignored:    data/icd/IHME_GBD_2021_COD_CAUSE_ICD_CODE_MAP_Y2024M05D16.XLSX
    Ignored:    data/icd/IHME_GBD_2021_NONFATAL_CAUSE_ICD_CODE_MAP_Y2024M05D16.XLSX
    Ignored:    data/icd/UK_Biobank_master_file.tsv
    Ignored:    data/icd/cdc_valid_icd10_Sep_23_2025.xlsx
    Ignored:    data/icd/cdc_valid_icd9_Sep_23_2025.xlsx
    Ignored:    data/icd/hp_umls_mapping.csv
    Ignored:    data/icd/lancet_conditions_icd10.xlsx
    Ignored:    data/icd/manual_disease_icd10_mappings.xlsx
    Ignored:    data/icd/mondo_umls_mapping.csv
    Ignored:    data/icd/phecode_international_version_unrolled.csv
    Ignored:    data/icd/phecode_to_icd10_manual_mapping.xlsx
    Ignored:    data/icd/semiautomatic_ICD-pheno.txt
    Ignored:    data/icd/semiautomatic_ICD-pheno_UKB_subset.txt
    Ignored:    data/icd/umls-2025AA-mrconso.zip
    Ignored:    doccano_venv/
    Ignored:    figures/
    Ignored:    output/.DS_Store
    Ignored:    output/abstracts/
    Ignored:    output/doccano/
    Ignored:    output/fulltexts/
    Ignored:    output/gwas_cat/
    Ignored:    output/gwas_cohorts/
    Ignored:    output/icd_map/
    Ignored:    output/pubmedbert_entity_predictions.csv
    Ignored:    output/pubmedbert_entity_predictions.jsonl
    Ignored:    output/pubmedbert_predictions.csv
    Ignored:    output/pubmedbert_predictions.jsonl
    Ignored:    output/supplement/
    Ignored:    output/text_mining_predictions/
    Ignored:    output/trait_ontology/
    Ignored:    population_description_terms.txt
    Ignored:    pubmedbert-cohort-ner-model/
    Ignored:    pubmedbert-cohort-ner/
    Ignored:    renv/
    Ignored:    spacy_venv_requirements.txt
    Ignored:    spacyr_venv/

Untracked files:
    Untracked:  code/full_text_conversion/html_to_xml.R
    Untracked:  code/text_mining_models/tokenise_data.py

Unstaged changes:
    Modified:   analysis/disease_inves_by_ancest.Rmd
    Modified:   analysis/replication_ancestry_bias.Rmd
    Modified:   analysis/specific_aims_stats.Rmd
    Modified:   analysis/text_for_cohort_labels.Rmd

Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.


These are the previous versions of the repository in which changes were made to the R Markdown (analysis/gwas_to_gbd.Rmd) and HTML (docs/gwas_to_gbd.html) files. If you’ve configured a remote Git repository (see ?wflow_git_remote), click on the hyperlinks in the table below to view the files as they were in that past version.

File Version Author Date Message
Rmd f3cf2b5 IJbeasley 2026-03-31 Add upset plots to test paper overlap per condition
html 5f3289b IJbeasley 2026-03-26 Build site.
Rmd f754dc4 IJbeasley 2026-03-26 Adding missed papers
html 41c0bbe IJbeasley 2026-01-12 Build site.
Rmd 94b4ca3 IJbeasley 2026-01-12 Update initial trait categorisation
html bf2e581 IJbeasley 2026-01-05 Build site.
Rmd 11f714c IJbeasley 2026-01-05 Update filtering of GWAS traits
html 33cdcc6 IJbeasley 2026-01-03 Build site.
Rmd 6160eba IJbeasley 2026-01-03 Update fixing of trait mapping
html 9d0fd3f IJbeasley 2025-10-09 Build site.
Rmd 8e94754 IJbeasley 2025-10-09 Integrating gwas traits with ICD10

Set up

library(dplyr)
library(stringr)
library(purrr)
library(tidyr)
library(data.table)

Load Lancet priority diseases

gbd_2019 <- readxl::read_xlsx(here::here("data/icd/lancet_conditions_icd10.xlsx"))

gbd_2019 =
  gbd_2019 |>
  select(cause = mapped_gbd_term,
         icd10 = icd_10_non_fatal,
         cause_hierarchy_level = gbd_level)


gbd_2019 =
  gbd_2019 |>
  filter(!is.na(icd10))

Prepare GBD 2019 data for merging with GWAS traits

Tidy ICD codes

Make long format, separate multiple ICD code ranges into rows

# expand multiple ICD codes into rows
gbd_2019 = 
  gbd_2019 |>
  mutate(icd10 = str_split(icd10, ",\\s*")) |>
  tidyr::unnest(icd10) 

# separate ICD code ranges into start and end codes
gbd_2019 =
  gbd_2019 |>
  tidyr::separate_wider_delim(col = "icd10",
                        delim = "-", 
                       names = c("start_icd10_code", "end_icd10_code"),
                       too_few = "align_end"
                       ) 

# if only one ICD code (i.e. no range), set start and end to be the same
gbd_2019 =
  gbd_2019 |>
  mutate(start_icd10_code = 
         ifelse(is.na(start_icd10_code),
                end_icd10_code,
                start_icd10_code)
         )

gbd_2019 =
  gbd_2019 |>
  distinct()

head(gbd_2019)
# A tibble: 6 × 4
  cause                  start_icd10_code end_icd10_code cause_hierarchy_level
  <chr>                  <chr>            <chr>                          <dbl>
1 Ischemic heart disease I20              I21.6                              3
2 Ischemic heart disease I21.9            I25.9                              3
3 Ischemic heart disease Z82.4            Z82.49                             3
4 Ischemic stroke        G45              G46.8                              4
5 Ischemic stroke        I63              I63.9                              4
6 Ischemic stroke        I65              I66.9                              4

Where icd10 code ranges are the same, but missing decimal places, add .9 to end code (to help with filtering ranges)

gbd_2019 |>
  filter(start_icd10_code == end_icd10_code &
         !grepl(".", start_icd10_code, fixed = TRUE)
         ) |>
  arrange(start_icd10_code) |>
  head()
# A tibble: 5 × 4
  cause                    start_icd10_code end_icd10_code cause_hierarchy_level
  <chr>                    <chr>            <chr>                          <dbl>
1 Diarrhoeal diseases      A09              A09                                3
2 Lower respiratory infec… A70              A70                                3
3 Tracheal, bronchus, and… C33              C33                                3
4 Maternal disorders       N96              N96                                3
5 HIV/AIDS                 Z21              Z21                                3
gbd_2019 = 
gbd_2019 |>
  mutate(end_icd10_code =
         ifelse(
         start_icd10_code == end_icd10_code &
         !grepl(".", start_icd10_code, fixed = TRUE),
         paste0(end_icd10_code, ".9"),
         end_icd10_code
         ) 
  )

Seperate numeric and letter parts of ICD codes (to help with filtering ranges)

# replace O9A513 with O99.9
gbd_2019 =
  gbd_2019 |>
  mutate(end_icd10_code =
        ifelse(end_icd10_code == "O9A513",
               "O99.9",
               end_icd10_code)
         )

# replace Z3A49 with Z39.2
gbd_2019 =
  gbd_2019 |>
  mutate(end_icd10_code =
        ifelse(end_icd10_code == "Z3A49",
               "Z39.2",
               end_icd10_code)
         )

# check start_icd10_code and end_icd10_code start with the same letter
# if not, need to fix these rows
  gbd_2019 |>
  filter(str_extract(start_icd10_code, "^[A-Z]") != 
         str_extract(end_icd10_code, "^[A-Z]")
         )
# A tibble: 0 × 4
# ℹ 4 variables: cause <chr>, start_icd10_code <chr>, end_icd10_code <chr>,
#   cause_hierarchy_level <dbl>
gbd_2019 =
  gbd_2019 |>
  mutate(icd10_code_letter = str_extract(start_icd10_code, "^[A-Z]")) 

gbd_2019 =
  gbd_2019 |>
  mutate(start_icd10_code_num = as.numeric(str_remove(start_icd10_code, 
                                                      "^[A-Z]")
                                           ),
         end_icd10_code_num = as.numeric(str_remove(end_icd10_code, 
                                                    "^[A-Z]")
                                         )
         )

Merge GWAS traits with GBD causes

Load Disease Mapping

disease_mapping <- data.table::fread(
here::here("output/icd_map/gwas_disease_to_icd10_mapping.csv")
)

disease_mapping =
  disease_mapping |>
  mutate(icd10_code = sub("^([^-]+)-\\1$", "\\1", icd10_code))

disease_mapping =
  disease_mapping |>
    mutate(icd10_code_letter = str_extract(icd10_code, "^[A-Z]")) |>
    mutate(icd10_code_num = as.numeric(str_remove(icd10_code, "^[A-Z]")))

disease_mapping |>
  filter(is.na(icd10_code_num)) |>
  nrow()
[1] 3382
disease_mapping =
  disease_mapping |>
  filter(!is.na(icd10_code_num)) 

disease_mapping = 
  disease_mapping |>
  mutate(icd10_code_num = as.numeric(icd10_code_num))

Join disease mapping with GBD 2019 data

disease_mapping_with_cause <- disease_mapping |>
  rowwise() |>
  mutate(
    cause = 
      list(
      gbd_2019$cause[
      which(icd10_code_num >= gbd_2019$start_icd10_code_num &
            icd10_code_num <= gbd_2019$end_icd10_code_num & 
            icd10_code_letter == gbd_2019$icd10_code_letter)
      ]),
    cause_hierarchy_level  = 
       list(
            gbd_2019$cause_hierarchy_level[
      which(icd10_code_num >= gbd_2019$start_icd10_code_num &
            icd10_code_num <= gbd_2019$end_icd10_code_num & 
            icd10_code_letter == gbd_2019$icd10_code_letter)
      ])
  ) |>
  ungroup()


disease_mapping_with_cause = 
  disease_mapping_with_cause |>
  tidyr::unnest(c(cause, cause_hierarchy_level),
                keep_empty = TRUE
                )
# K76.1 ULMS mapping to chronic liver disease, but is actually about downstream consequences of
# heart failure/disease 
disease_mapping_with_cause |> 
  filter(icd10_code == "K76.1" & grepl("UMLS", icd10_code_origin)) |> 
  select(`DISEASE/TRAIT`, cause) |> 
  distinct()  |> 
  head()
# A tibble: 6 × 2
  `DISEASE/TRAIT`                                                     cause     
  <chr>                                                               <chr>     
1 coronary heart disease                                              Cirrhosis…
2 coronary artery disease                                             Cirrhosis…
3 myocardial infarction in coronary artery disease                    Cirrhosis…
4 coronary heart disease (snp x snp interaction)                      Cirrhosis…
5 coronary heart disease event reduction (statin therapy interaction) Cirrhosis…
6 sudden cardiac arrest in coronary artery disease                    Cirrhosis…
# remove this mapping 
disease_mapping_with_cause = 
  disease_mapping_with_cause |>
  filter(!(icd10_code == "K76.1" & grepl("UMLS", icd10_code_origin)))
print("Number of unique studies mapped to a cause:")
[1] "Number of unique studies mapped to a cause:"
disease_mapping_with_cause |> 
  filter(!is.na(cause)) |> 
  pull(PUBMED_ID) |> 
  unique() |> 
  length()
[1] 1001
print("Number of unique studies mapped to non-communicable diseases:")
[1] "Number of unique studies mapped to non-communicable diseases:"
# filter out infectious diseases
disease_mapping_with_cause |>
    dplyr::filter(!cause %in% c("HIV/AIDS",
                             "Tuberculosis",
                             "Malaria",
                             "Lower respiratory infections",
                             "Diarrhoeal diseases",
                             "Neonatal disorders",
                             "Tetanus",
                             "Diphtheria",
                             "Pertussis" ,
                             "Measles",
                             "Maternal disorders")) |>
    filter(!is.na(cause)) |> 
  pull(PUBMED_ID) |> 
  unique() |> 
  length()
[1] 828

Check overlap (upset plot) of studies mapped to different causes

Between type 1 diabetes, type 2 diabetes, and diabetes mellitus

diabetes_studies = disease_mapping_with_cause |>
  filter(cause %in% c("Type 1 diabetes mellitus", 
                      "Type 2 diabetes mellitus", 
                      "Diabetes mellitus",
                      "Chronic kidney disease due to diabetes mellitus type 2",
                      "Chronic kidney disease due to diabetes mellitus type 1")) |>
  select(PUBMED_ID, cause) |>
  distinct()

library(ComplexHeatmap)
Loading required package: grid
========================================
ComplexHeatmap version 2.18.0
Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
Github page: https://github.com/jokergoo/ComplexHeatmap
Documentation: http://jokergoo.github.io/ComplexHeatmap-reference

If you use it in published research, please cite either one:
- Gu, Z. Complex Heatmap Visualization. iMeta 2022.
- Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
    genomic data. Bioinformatics 2016.


The new InteractiveComplexHeatmap package can directly export static 
complex heatmaps into an interactive Shiny app with zero effort. Have a try!

This message can be suppressed by:
  suppressPackageStartupMessages(library(ComplexHeatmap))
========================================
# create a binary matrix indicating which studies are mapped to which causes

diabetes_studies_wide = diabetes_studies |>
  tidyr::pivot_wider(names_from = cause, values_from = cause, values_fill = NA) |>
  select(-PUBMED_ID) |>
  mutate_all(~ ifelse(is.na(.), 0, 1)) |>
  as.data.frame()

upset_matrix = make_comb_mat(diabetes_studies_wide)

# create an upset plot
UpSet(upset_matrix,
      comb_order = order(comb_size(upset_matrix), decreasing = TRUE)
      #nsets = 3, 
      #order.by = "freq", 
      # sets.bar.color = "#56B4E9", 
      # main.bar.color = "#0072B2", 
      # matrix.color = "#D55E00", 
      #text.scale = c(1.5, 1.5, 1.5, 1.5, 1.5, 1.5)
      )

Between different types of cancer

cancer_studies = disease_mapping_with_cause |>
  filter(grepl("cancer|neoplasm", cause, ignore.case = TRUE)) |>
  select(PUBMED_ID, cause) |>
  distinct()

cancer_studies_wide = cancer_studies |>
  tidyr::pivot_wider(names_from = cause, values_from = cause, values_fill = NA) |>
  select(-PUBMED_ID) |>
  mutate_all(~ ifelse(is.na(.), 0, 1)) |>
  as.data.frame()

upset_matrix_cancer = make_comb_mat(cancer_studies_wide)

UpSet(upset_matrix_cancer,
      comb_order = order(comb_size(upset_matrix_cancer), decreasing = TRUE)
      #nsets = 3, 
      #order.by = "freq", 
      # sets.bar.color = "#56B4E9", 
      # main.bar.color = "#0072B2", 
      # matrix.color = "#D55E00", 
      #text.scale = c(1.5, 1.5, 1.5, 1.5, 1.5, 1.5)
      )

Between different cardiovascular diseases

cardiovascular_studies = disease_mapping_with_cause |>
  filter(grepl("heart|stroke|hemorrhage", cause, ignore.case = TRUE)) |>
  select(PUBMED_ID, cause) |>
  distinct()

cardiovascular_studies_wide = cardiovascular_studies |>
  tidyr::pivot_wider(names_from = cause, values_from = cause, values_fill = NA) |>
  select(-PUBMED_ID) |>
  mutate_all(~ ifelse(is.na(.), 0, 1)) |>
  as.data.frame()

upset_matrix_cardiovascular = make_comb_mat(cardiovascular_studies_wide)

UpSet(upset_matrix_cardiovascular,
      comb_order = order(comb_size(upset_matrix_cardiovascular), decreasing = TRUE)
      #nsets = 3, 
      #order.by = "freq", 
      # sets.bar.color = "#56B4E9", 
      # main.bar.color = "#0072B2", 
      # matrix.color = "#D55E00", 
      #text.scale = c(1.5, 1.5, 1.5, 1.5, 1.5, 1.5)
      )

Across liver diseases

Cirrhosis and other chronic liver diseases, Liver cancer due to hepatitis C, Liver cancer due to hepatitis B, Diabetes

liver_studies = disease_mapping_with_cause |>
  filter(grepl("liver|diabetes", cause, ignore.case = TRUE)) |>
  filter(!grepl("Type 2|Type 1", cause, ignore.case = TRUE)) |>
  select(PUBMED_ID, cause) |>
  distinct()


liver_studies_wide = liver_studies |>
  tidyr::pivot_wider(names_from = cause, values_from = cause, values_fill = NA) |>
  select(-PUBMED_ID) |>
  mutate_all(~ ifelse(is.na(.), 0, 1)) |>
  as.data.frame()

upset_matrix_liver = make_comb_mat(liver_studies_wide)

UpSet(upset_matrix_liver,
      comb_order = order(comb_size(upset_matrix_liver), decreasing = TRUE)
      #nsets = 3, 
      #order.by = "freq", 
      # sets.bar.color = "#56B4E9", 
      # main.bar.color = "#0072B2", 
      # matrix.color = "#D55E00", 
      #text.scale = c(1.5, 1.5, 1.5, 1.5, 1.5, 1.5)
      )

Across all non-communicable diseases

non_communicable_studies =
disease_mapping_with_cause |>
    dplyr::filter(!cause %in% c("HIV/AIDS",
                             "Tuberculosis",
                             "Malaria",
                             "Lower respiratory infections",
                             "Diarrhoeal diseases",
                             "Neonatal disorders",
                             "Tetanus",
                             "Diphtheria",
                             "Pertussis" ,
                             "Measles",
                             "Maternal disorders")) |>
  filter(!is.na(cause)) |>
  select(PUBMED_ID, cause) |>
  distinct() 
  
non_communicable_studies_wide = non_communicable_studies |>
  tidyr::pivot_wider(names_from = cause, values_from = cause, values_fill = NA) |>
  select(-PUBMED_ID) |>
  mutate_all(~ ifelse(is.na(.), 0, 1)) |>
  as.data.frame()

upset_matrix_non_communicable = make_comb_mat(non_communicable_studies_wide)

UpSet(upset_matrix_non_communicable,
      comb_order = order(comb_size(upset_matrix_non_communicable), decreasing = TRUE)
      #nsets = 3, 
      #order.by = "freq", 
      # sets.bar.color = "#56B4E9", 
      # main.bar.color = "#0072B2", 
      # matrix.color = "#D55E00", 
      #text.scale = c(1.5, 1.5, 1.5, 1.5, 1.5, 1.5)
      )

Between different respiratory diseases

Chronic obstructive pulmonary disease, “Tracheal, bronchus, and lung cancer

respiratory_studies = disease_mapping_with_cause |>
  filter(grepl("chronic obstructive pulmonary disease|tracheal|bronchus|lung cancer", cause, ignore.case = TRUE)) |>
  select(PUBMED_ID, cause) |>
  distinct()

respiratory_studies_wide = respiratory_studies |>
  tidyr::pivot_wider(names_from = cause, values_from = cause, values_fill = NA) |>
  select(-PUBMED_ID) |>
  mutate_all(~ ifelse(is.na(.), 0, 1)) |>
  as.data.frame()


upset_matrix_respiratory = make_comb_mat(respiratory_studies_wide)

UpSet(upset_matrix_respiratory,
      comb_order = order(comb_size(upset_matrix_respiratory), decreasing = TRUE)
      #nsets = 3, 
      #order.by = "freq", 
      # sets.bar.color = "#56B4E9", 
      # main.bar.color = "#0072B2", 
      # matrix.color = "#D55E00", 
      #text.scale = c(1.5, 1.5, 1.5, 1.5, 1.5, 1.5)
      )

Check recall i.e. that I have identified most/all studies of the priority diseases

Diabetes

no_capture <- paste0("(?<!no )",
                "(?<!non )",
                "(?<!no type 2 )"
                )

diabetes_grep = paste0(no_capture, "diabetes")

disease_mapping_with_cause |>
  filter(grepl(diabetes_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(diabetes_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  select(PUBMED_ID, 
         `DISEASE/TRAIT`,
         collected_all_disease_terms, 
         icd10_code,
         cause) |>
  distinct() 
# A tibble: 0 × 5
# Groups:   PUBMED_ID [0]
# ℹ 5 variables: PUBMED_ID <int>, DISEASE/TRAIT <chr>,
#   collected_all_disease_terms <chr>, icd10_code <chr>, cause <chr>

Liver cancer, and other chronic liver diseases (e.g. cirrhosis)

Check recall for these together as they are often comorbid and may be captured by similar terms

liver_cancer_grep = paste0(no_capture, "liver|cirhosis|hepatocellular carcinoma|hepatoma|hepatic carcinoma")

disease_mapping_with_cause |>
  filter(grepl(liver_cancer_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(liver_cancer_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T)) |>
  ungroup() |>
  select(`DISEASE/TRAIT`,
         collected_all_disease_terms) |>
  distinct()
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 21 × 2
   `DISEASE/TRAIT`                                        collected_all_diseas…¹
   <chr>                                                  <chr>                 
 1 immunoglobulin light chain (al) amyloidosis (liver in… amyloidosis           
 2 biliverdin reductase a level in chronic kidney diseas… chronic kidney disease
 3 biliverdin reductase a level in chronic kidney diseas… hypertension          
 4 fatty acid-binding protein, liver level in chronic ki… chronic kidney disease
 5 fatty acid-binding protein, liver level in chronic ki… hypertension          
 6 glycogen phosphorylase, liver form level in chronic k… chronic kidney disease
 7 glycogen phosphorylase, liver form level in chronic k… hypertension          
 8 hepatoma-derived growth factor level in chronic kidne… chronic kidney disease
 9 hepatoma-derived growth factor level in chronic kidne… hypertension          
10 hepatoma-derived growth factor-like protein 1 level i… chronic kidney disease
# ℹ 11 more rows
# ℹ abbreviated name: ¹​collected_all_disease_terms

Stroke

stroke_grep = paste0(no_capture, 
                     "stroke|cerebrovascular|cerebral|hemorrhage")

disease_mapping_with_cause |>
  filter(grepl(stroke_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(stroke_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                collapse = ", ",
                                na.rm = T)) |>
  ungroup() |>
  select(`DISEASE/TRAIT`,
         collected_all_disease_terms) |>
  distinct()
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 30 × 2
   `DISEASE/TRAIT`                                        collected_all_diseas…¹
   <chr>                                                  <chr>                 
 1 progressive supranuclear palsy                         dementia with cerebra…
 2 hippocampal atrophy                                    other cerebral degene…
 3 brain arteriovenous malformations (sporadic)           cerebral arteriovenou…
 4 cerebral amyloid angiopathy                            cerebral amyloid angi…
 5 neuropathologic traits                                 cerebral amyloid angi…
 6 progressive supranuclear palsy and immune-mediated di… dementia with cerebra…
 7 neuritic plaques or cerebral amyloid angiopathy        cerebral amyloid angi…
 8 neuritic plaques or neurofibrillary tangles or cerebr… cerebral amyloid angi…
 9 neurofibrillary tangles or cerebral amyloid angiopathy cerebral amyloid angi…
10 non-richardson's syndrome vs richardson's syndrome in… dementia with cerebra…
# ℹ 20 more rows
# ℹ abbreviated name: ¹​collected_all_disease_terms

Stomach cancer

stomach_cancer_grep = paste0(no_capture, 
                     "stomach|gastric")

disease_mapping_with_cause |>
  filter(grepl(stomach_cancer_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(stomach_cancer_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                collapse = ", ",
                                na.rm = T)) |>
  ungroup() |>
  select(`DISEASE/TRAIT`,
         collected_all_disease_terms) |>
  distinct()
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 15 × 2
   `DISEASE/TRAIT`                                        collected_all_diseas…¹
   <chr>                                                  <chr>                 
 1 weight loss (gastric bypass surgery)                   body weight loss      
 2 gastric atrophy                                        atrophic gastritis    
 3 severe gastric atrophy                                 atrophic gastritis    
 4 gastric or stomach ulcers                              gastric ulcer         
 5 gastroesophageal reflux disease or gastric reflux      gastroesophageal refl…
 6 stomach disorder                                       stomach disease       
 7 gastric inhibitory polypeptide level in chronic kidne… chronic kidney disease
 8 gastric inhibitory polypeptide level in chronic kidne… hypertension          
 9 gastric intrinsic factor level in chronic kidney dise… chronic kidney disease
10 gastric intrinsic factor level in chronic kidney dise… hypertension          
11 chronic stomach pain                                   abdominal pain        
12 comorbidity of gastric and duodenal ulcers             duodenal ulcer        
13 comorbidity of gastric and duodenal ulcers             gastric ulcer         
14 gastric ulcer                                          gastric ulcer         
15 gastric reflux                                         gastroesophageal refl…
# ℹ abbreviated name: ¹​collected_all_disease_terms

Cervical cancer

cervical_cancer_grep = paste0(no_capture, 
                     "cervical|cervix")

disease_mapping_with_cause |>
  filter(grepl(cervical_cancer_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(cervical_cancer_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                collapse = ", ",
                                na.rm = T)) |>
  ungroup() |>
  select(`DISEASE/TRAIT`,
         collected_all_disease_terms) |>
  distinct()
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 8 × 2
  `DISEASE/TRAIT`                                         collected_all_diseas…¹
  <chr>                                                   <chr>                 
1 cervical high-risk human papilloma virus infection      human papilloma virus…
2 cervical high-risk human papilloma virus infection (pe… human papilloma virus…
3 cervical spondylosis                                    cervical spondylosis  
4 back problem (firth correction)                         abnormality of the ce…
5 back problem (spa correction)                           abnormality of the ce…
6 cervical dystonia                                       cervical dystonia     
7 uterine cancer                                          cervical cancer       
8 back problem                                            abnormality of the ce…
# ℹ abbreviated name: ¹​collected_all_disease_terms
# pubmed 35729236 studies 
# hormone-sensitive cancers: breast, ovarian, thyroid, prostate, and uterine cancer
# but GWAS Catalog mapped uterine cancer to cervical cancer, which is
# why it is picked up in this recall, but correctly not 
# mapped to cervical cancer in ICD-10 mapping!


# human papilloma virus (HPV) is a major cause of cervical cancer ...
# so do we include studies of HPV in our mapping of cervical cancer?
hpv_grep <- paste0(no_capture, 
                     "hpv|human papilloma virus|pap smear")

disease_mapping_with_cause |>
  filter(grepl(hpv_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(hpv_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                collapse = ", ",
                                na.rm = T)) |>
  ungroup() |>
  select(`DISEASE/TRAIT`,
         collected_all_disease_terms) |>
  distinct()
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 12 × 2
   `DISEASE/TRAIT`                                        collected_all_diseas…¹
   <chr>                                                  <chr>                 
 1 hpv seropositivity                                     hpv seropositivity    
 2 abnormal papanicolaou smear of cervix and cervical hpv abnormal pap smear    
 3 abnormal papanicolaou smear of cervix and cervical hpv hpv seropositivity    
 4 viral warts & hpv                                      benign neoplasm       
 5 viral warts & hpv                                      hpv seropositivity    
 6 cervical high-risk human papilloma virus infection     human papilloma virus…
 7 cervical high-risk human papilloma virus infection (p… human papilloma virus…
 8 abnormal smear cervix                                  abnormal pap smear    
 9 icd10 r87619: abnormal smear cervix                    abnormal pap smear    
10 human papillomavirus seropositivity (hpv16 e6/e7/l1 o… hpv seropositivity    
11 human papillomavirus seropositivity (hpv16 e6/e7/l1)   hpv seropositivity    
12 human papillomavirus seropositivity (hpv18 l1)         hpv seropositivity    
# ℹ abbreviated name: ¹​collected_all_disease_terms
disease_mapping_with_cause <- 
  disease_mapping_with_cause |>
  mutate(icd10_code = str_replace(icd10_code, "R879", "R87.9")) 

Lip and oral cavity cancer

lip_oral_cavity_cancer_grep = paste0(no_capture, 
                     "lip\\b|oral cavity|mouth|tongue|pharynx|larynx|pharyngeal|laryngeal")

disease_mapping_with_cause |>
  filter(grepl(lip_oral_cavity_cancer_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(lip_oral_cavity_cancer_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  filter(!grepl("cleft", `DISEASE/TRAIT`, ignore.case = TRUE)) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                collapse = ", ",
                                na.rm = T))
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 22 × 5
# Groups:   PUBMED_ID, DISEASE/TRAIT, collected_all_disease_terms [22]
   PUBMED_ID `DISEASE/TRAIT`             collected_all_diseas…¹ cause icd10_code
       <int> <chr>                       <chr>                  <chr> <chr>     
 1  29855589 velopharyngeal dysfunction  velopharyngeal dysfun… Q35,… Q35, Q38.8
 2  30837455 mouth ulcers                oral ulcer             K12.0 K12.0     
 3  31235808 mouth ulcers                oral ulcer             K12.0 K12.0     
 4  32634583 cv-a6-associated hand, foo… hand foot and mouth d… B08.4 B08.4     
 5  33959723 throat or larynx disorder   laryngeal disease      J38.… J38.7, S1…
 6  33959723 throat or larynx disorder   throat disease         R04.… R04.0, R0…
 7  34662886 icd10 d10: benign neoplasm… benign neoplasm        D10   D10       
 8  34662886 icd10 d37: neoplasm of unc… neoplasm               D37   D37       
 9  34662886 icd10 j38.7: other disease… laryngeal disease      J38.7 J38.7     
10  34662886 icd10 j38: diseases of voc… laryngeal disease      J38   J38       
# ℹ 12 more rows
# ℹ abbreviated name: ¹​collected_all_disease_terms
# !!!!!!!!!!!! Maybe caught one! 

Heart disease

heart_disease_grep = paste0(no_capture, 
                     "heart disease|cardiovascular|coronary|myocardial|angina|heart failure")

disease_mapping_with_cause |>
  filter(grepl(heart_disease_grep, 
               `DISEASE/TRAIT`, 
               ignore.case = TRUE, 
               perl = TRUE)|
           grepl(heart_disease_grep,
                collected_all_disease_terms,
                ignore.case = TRUE,
                perl = TRUE
                )
         ) |>
  group_by(PUBMED_ID) |>
  filter(all(is.na(cause))) |>
  group_by(PUBMED_ID, 
           `DISEASE/TRAIT`,
           collected_all_disease_terms,
           cause) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(icd10_code), 
                                collapse = ", ",
                                na.rm = T))
`summarise()` has grouped output by 'PUBMED_ID', 'DISEASE/TRAIT',
'collected_all_disease_terms'. You can override using the `.groups` argument.
# A tibble: 90 × 5
# Groups:   PUBMED_ID, DISEASE/TRAIT, collected_all_disease_terms [90]
   PUBMED_ID `DISEASE/TRAIT`             collected_all_diseas…¹ cause icd10_code
       <int> <chr>                       <chr>                  <chr> <chr>     
 1  17903304 heart failure               heart failure          I50,… I50, I50.…
 2  17903304 major cvd                   cardiovascular disease I51.6 I51.6     
 3  20400778 mortality in heart failure  heart failure          I50   I50       
 4  20445134 heart failure               heart failure          I50,… I50, I50.…
 5  20838585 cardiovascular risk factors cardiovascular disease I51.6 I51.6     
 6  20838585 cardiovascular risk factor… cardiovascular disease I51.6 I51.6     
 7  21779381 cardiovascular disease ris… cardiovascular disease I51.6 I51.6     
 8  23297363 tetralogy of fallot         congenital anomaly of… Q21.3 Q21.3     
 9  23337848 vascular constriction       cardiovascular disease I51.6 I51.6     
10  23708190 congenital heart malformat… congenital anomaly of… I35.… I35.0, Q2…
# ℹ 80 more rows
# ℹ abbreviated name: ¹​collected_all_disease_terms

Check precision i.e. that the studies I have mapped to the priority diseases are actually about those diseases

Type 2 diabetes

disease_mapping_with_cause |>
  filter(cause == "Type 2 diabetes mellitus") |>
  filter(!grepl("type 2 diabetes|diabetes type 2|e11|type ii diabetes", `DISEASE/TRAIT`, ignore.case = TRUE) 
         ) |>
 group_by(PUBMED_ID,
          STUDY_ACCESSION,
          `DISEASE/TRAIT`,
          collected_all_disease_terms) |>
  summarise(icd10_code = str_flatten(unique(icd10_code), 
                                     collapse = ", ",
                                     na.rm = T),
            cause = str_flatten(unique(cause), 
                                collapse = ", ",
                                na.rm = T)) |>
  select(PUBMED_ID, 
         `DISEASE/TRAIT`,
         collected_all_disease_terms, 
         icd10_code,
         cause) |>
  distinct()
`summarise()` has grouped output by 'PUBMED_ID', 'STUDY_ACCESSION',
'DISEASE/TRAIT'. You can override using the `.groups` argument.
Adding missing grouping variables: `STUDY_ACCESSION`
# A tibble: 134 × 6
# Groups:   PUBMED_ID, STUDY_ACCESSION, DISEASE/TRAIT [134]
   STUDY_ACCESSION PUBMED_ID `DISEASE/TRAIT`   collected_all_diseas…¹ icd10_code
   <chr>               <int> <chr>             <chr>                  <chr>     
 1 GCST000108       17903298 diabetes (incide… diabetes mellitus      E11       
 2 GCST001965       23575436 glycemic traits   type 2 diabetes melli… E11       
 3 GCST002025       23670970 cystic fibrosis-… type 2 diabetes melli… E11       
 4 GCST009161       23696881 diabetes biomark… diabetes mellitus      E11       
 5 GCST002153       23982368 cardiovascular h… type 2 diabetes melli… E11       
 6 GCST002637       25317111 medication adher… diabetes mellitus      E11       
 7 GCST003250       26631737 urinary albumin-… diabetes mellitus      E11       
 8 GCST003373       26831199 glomerular filtr… diabetes mellitus      E11       
 9 GCST003457       26915486 soluble receptor… type 2 diabetes melli… E11       
10 GCST003797       27670767 diabetes in resp… diabetes mellitus      E11       
# ℹ 124 more rows
# ℹ abbreviated name: ¹​collected_all_disease_terms
# ℹ 1 more variable: cause <chr>
# problems with GCST90079743, GCST90083729 study provided mapping

# pubmed id 29703844 - should map to type 2 diabetes
#  genome-wide association study (GWAS) of DKD in type 2 diabetes (T2D)


# ? idk: 27670767

Checking hierarchy levels

# disease_mapping_with_cause = 
#   disease_mapping_with_cause |>
#   filter(!is.na(cause))

# filtering na to deal with pivoting 
# disease_mapping_with_cause_grouped = 
# disease_mapping_with_cause |>
# select(-icd10_code_num) |>
# tidyr::pivot_wider(
#             id_cols = c("collected_all_disease_terms", 
#                         "icd10_code", 
#                         "icd10_description"),
#             names_from = cause_hierarchy_level, 
#             names_glue = "l{.name}_{.value}",
#             values_from = cause,
#             values_fn = ~str_flatten(unique(.x), collapse = ", ", na.rm = TRUE)
#             )
# check which l2 causes are NA but l3 causes are not NA
# can use l3 causes therefore to fill in l2 causes
# disease_mapping_with_cause_grouped |> 
#   rowwise() |> 
#   filter(is.na(l2_cause) & !is.na(l3_cause)) |>
#   head()
# 
# neoplasms = c("Other neoplasms", 
#                                     "Hodgkin lymphoma",
#                                     "Leukemia",
#                                     "Non-Hodgkin lymphoma",
#               "Multiple myeloma")
# 
# disease_mapping_with_cause_grouped = 
#   disease_mapping_with_cause_grouped |>
#   rowwise() |>
#   mutate(l2_cause = 
#            list(ifelse(is.na(l2_cause),
#                   case_when(map_lgl(l3_cause, ~ .x %in% neoplasms) ~ "Neoplasms",
#                             map_lgl(l3_cause, ~ .x %in% "Neonatal disorders") ~ "Maternal and neonatal disorders",
#                             map_lgl(l3_cause, ~ .x %in% "Other cardiovascular and circulatory diseases") ~ "Cardiovascular diseases"
#                             ),
#                   l2_cause
#            )
#            )) |>
#   ungroup()
          

# to_map_manually <- 
# disease_mapping_with_cause_grouped |> 
#   rowwise() |> 
#   filter(is.null(l2_cause)) |> 
#   pull(collected_all_disease_terms) |> 
#   unique()
# 
# 
# update_unmapped_cause = function(df, 
#                                  unmapped_term, 
#                                  l2_cause_rep, 
#                                  l3_cause_rep){
#   
#   df = 
#   df |>
#     mutate(l3_cause = 
#            ifelse(collected_all_disease_terms == unmapped_term,
#                   l3_cause_rep,
#                   l3_cause
#            )) |>
#     mutate(l2_cause = 
#            ifelse(collected_all_disease_terms == unmapped_term,
#                   l2_cause_rep,
#                   l2_cause
#            ))    
#            
#     return(df)
#            
# }
# 
# disease_mapping_with_cause_grouped = 
# update_unmapped_cause(disease_mapping_with_cause_grouped, 
#                       "bone cancer",
#                       "Neoplasms",
#                       "Malignant neoplasms of bone and articular cartilage")

Save + combine with GWAS data

# disease_mapping_orig <- data.table::fread(
# here::here("output/icd_map/gwas_disease_to_icd10_mapping.csv")
# )
# 
# disease_mapping_with_cause_grouped =
#   disease_mapping_with_cause_grouped |>
#   tidyr::unnest_longer(c("l3_cause", "l4_cause")) 

disease_mapping_final =  disease_mapping_with_cause
  # left_join(
  #   disease_mapping_orig,
  #   disease_mapping_with_cause,
  #   by = c("collected_all_disease_terms", 
  #          "icd10_code", 
  #          "icd10_description")
  # )

# gwas_study_info <- fread(here::here("output/gwas_cat/gwas_study_info_group_v2.csv"))
# 
# gwas_study_info =
#   gwas_study_info |>
#   select(`DISEASE/TRAIT`, PUBMED_ID, STUDY_ACCESSION, COHORT)
# 
# disease_mapping_final =
#   left_join(
#     disease_mapping_final,
#     gwas_study_info
#   )


# disease_mapping_final = 
#   disease_mapping_final |>
#   group_by(STUDY_ACCESSION, collected_all_disease_terms) |>
#   summarise(
#     PUBMED_ID = paste0(unique(PUBMED_ID), collapse = "; "),
#     COHORT = paste0(unique(COHORT), collapse = "; "),
#     icd10_code = paste0(unique(icd10_code), collapse = "; "),
#     icd10_description = paste0(unique(icd10_description), collapse = "; "),
#     # l2_cause = str_flatten(unique(str_split(l2_cause, ", ")), # add separation step here ... 
#     #                        collapse = "; ", na.rm = TRUE),
#     l3_cause = str_flatten(unique(str_split(l3_cause, ", ")), 
#                            collapse = "; ", na.rm = TRUE),
#     l4_cause = str_flatten(unique(str_split(l4_cause, ", ")), 
#                            collapse = "; ", na.rm = TRUE)
#   ) 

data.table::fwrite(
# disease_mapping_final,
disease_mapping_with_cause,
here::here("output/icd_map/gwas_study_gbd_causes.csv")
)

sessionInfo()
R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS 26.3.1

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Los_Angeles
tzcode source: internal

attached base packages:
[1] grid      stats     graphics  grDevices datasets  utils     methods  
[8] base     

other attached packages:
[1] ComplexHeatmap_2.18.0 data.table_1.17.8     tidyr_1.3.1          
[4] purrr_1.1.0           stringr_1.6.0         dplyr_1.1.4          
[7] workflowr_1.7.2      

loaded via a namespace (and not attached):
 [1] shape_1.4.6.1       circlize_0.4.16     rjson_0.2.23       
 [4] xfun_0.55           bslib_0.9.0         GlobalOptions_0.1.2
 [7] processx_3.8.6      callr_3.7.6         vctrs_0.6.5        
[10] tools_4.3.1         ps_1.9.1            generics_0.1.4     
[13] stats4_4.3.1        parallel_4.3.1      tibble_3.3.0       
[16] cluster_2.1.4       pkgconfig_2.0.3     RColorBrewer_1.1-3 
[19] S4Vectors_0.40.2    readxl_1.4.5        lifecycle_1.0.4    
[22] compiler_4.3.1      git2r_0.36.2        getPass_0.2-4      
[25] codetools_0.2-19    clue_0.3-66         httpuv_1.6.16      
[28] htmltools_0.5.8.1   sass_0.4.10         yaml_2.3.10        
[31] later_1.4.4         pillar_1.11.1       crayon_1.5.3       
[34] jquerylib_0.1.4     whisker_0.4.1       cachem_1.1.0       
[37] iterators_1.0.14    foreach_1.5.2       tidyselect_1.2.1   
[40] digest_0.6.37       stringi_1.8.7       rprojroot_2.1.0    
[43] fastmap_1.2.0       here_1.0.1          colorspace_2.1-2   
[46] cli_3.6.5           magrittr_2.0.4      utf8_1.2.6         
[49] withr_3.0.2         promises_1.3.3      rmarkdown_2.30     
[52] httr_1.4.7          matrixStats_1.5.0   cellranger_1.1.0   
[55] png_0.1-8           GetoptLong_1.0.5    evaluate_1.0.5     
[58] knitr_1.50          IRanges_2.36.0      doParallel_1.0.17  
[61] rlang_1.1.6         Rcpp_1.1.0          glue_1.8.0         
[64] BiocManager_1.30.26 renv_1.1.8          BiocGenerics_0.48.1
[67] rstudioapi_0.17.1   jsonlite_2.0.0      R6_2.6.1           
[70] fs_1.6.6