Chapter 6 Exploiting the cell ontology

6.1 Motivation

As previously discussed in Section 5.4, SingleR maps the labels in its references to the Cell Ontology. The most obvious advantage of doing this is to provide a standardized vocabulary with which to describe cell types, thus facilitating integrated analyses with multiple references. However, another useful feature of the Cell Ontology is its hierarchical organization of terms, allowing us to adjust cell type annotations to the desired resolution. This represents a more dynamic alternative to the static label.main and label.fine options in each reference.

6.2 Basic manipulation

We use the ontoProc package to load in the Cell Ontology. This produces an ontology_index object (from the ontologyIndex package) that we can query for various pieces of information.

# TODO: wrap in utility function.
library(ontoProc)
cl <- getOnto("cellOnto")
cl
## Ontology with 17206 terms
## 
## format-version: 1.2
## data-version: releases/2023-02-15
## ontology: cl
## 
## Properties:
##  id: character
##  name: character
##  parents: list
##  children: list
##  ancestors: list
##  obsolete: logical
##  format-version: list
##  data-version: list
##  subsetdef: list
##  synonymtypedef: list
##  remark: list
##  ontology: list
##  property_value: list
##  def: character
##  disjoint_from: list
##  part_of: list
##  is_a: list
##  equivalent_to: list
##  comment: character
##  subset: list
##  intersection_of: list
##  bearer_of: list
##  synonym: list
##  xref: list
##  union_of: list
##  has_component: list
##  creation_date: character
##  namespace: list
##  has_parent_hydride: list
##  is_conjugate_base_of: list
##  RO:0000087: list
##  is_conjugate_acid_of: list
##  alt_id: list
##  is_tautomer_of: list
##  has_part: list
##  has_functional_parent: list
##  is_enantiomer_of: list
##  is_substituent_group_from: list
##  only_in_taxon: list
##  replaced_by: list
##  consider: list
##  develops_from: list
##  capable_of_part_of: list
##  capable_of: list
##  participates_in: list
##  present_in_taxon: list
##  in_taxon: list
##  lacks_plasma_membrane_part: list
##  RO:0002104: list
##  produces: list
##  adjacent_to: list
##  never_in_taxon: list
##  located_in: list
##  RO:0015016: list
##  lacks_part: list
##  RO:0015015: list
##  RO:0002100: list
##  dc-contributor: list
##  output_of: list
##  RO:0002203: list
##  RO:0002120: list
##  has_not_completed: list
##  RO:0002102: list
##  RO:0002103: list
##  RO:0002292: list
##  RO:0002388: list
##  RO:0001000: list
##  RO:0013001: list
##  RO:0002130: list
##  RO:0002101: list
##  existence_starts_and_ends_during: list
##  existence_ends_during: list
##  existence_starts_during: list
##  seeAlso: list
##  created_by: character
##  RO:0013007: list
##  innervates: list
##  synapsed_by: list
##  results_in_distribution_of: list
##  regulates: list
##  has_input: list
##  has_primary_input: list
##  results_in_assembly_of: list
##  starts_with: list
##  bounding_layer_of: list
##  results_in_organization_of: list
##  has_primary_output: list
##  results_in_fission_of: list
##  results_in_fusion_of: list
##  results_in_morphogenesis_of: list
##  results_in_development_of: list
##  results_in_formation_of: list
##  results_in_growth_of: list
##  results_in_acquisition_of_features_of: list
##  results_in_maturation_of: list
##  has_participant: list
##  directly_positively_regulates: list
##  has_primary_input_or_output: list
##  results_in_movement_of: list
##  occurs_in: list
##  acts_on_population_of: list
##  negatively_regulates: list
##  positively_regulates: list
##  process_has_causal_agent: list
##  has_output: list
##  has_end_location: list
##  has_start_location: list
##  directly_negatively_regulates: list
##  regulated_by: list
##  directly_regulates: list
##  ends_with: list
##  results_in_transport_across: list
##  has_target_start_location: list
##  has_target_end_location: list
##  results_in_disassembly_of: list
##  results_in_transport_to_from_or_in: list
##  results_in_developmental_progression_of: list
##  results_in_transport_along: list
##  regulates_levels_of: list
##  overlaps: list
##  RO:0015011: list
##  RO:0015007: list
##  RO:0015008: list
##  RO:0015010: list
##  continuous_with: list
##  contributes_to_morphology_of: list
##  connects: list
##  in_lateral_side_of: list
##  has_skeleton: list
##  immediate_transformation_of: list
##  composed_primarily_of: list
##  immediately_deep_to: list
##  attaches_to: list
##  has_quality: list
##  has_potential_to_develop_into: list
##  surrounds: list
##  location_of: list
##  extends_fibers_into: list
##  channel_for: list
##  channels_from: list
##  channels_into: list
##  conduit_for: list
##  existence_ends_during_or_before: list
##  existence_starts_during_or_after: list
##  has_boundary: list
##  preceded_by: list
##  precedes: list
##  simultaneous_with: list
##  immediately_preceded_by: list
##  ends: list
##  surrounded_by: list
##  developmentally_replaces: list
##  developmentally_induced_by: list
##  starts: list
##  transformation_of: list
##  anterior_to: list
##  has_developmental_contribution_from: list
##  proximalmost_part_of: list
##  luminal_space_of: list
##  subdivision_of: list
##  has_member: list
##  functionally_related_to: list
##  dorsal_to: list
##  connected_to: list
##  contains: list
##  produced_by: list
##  branching_part_of: list
##  attaches_to_part_of: list
##  drains: list
##  in_left_side_of: list
##  supplies: list
##  existence_ends_with: list
##  existence_starts_with: list
##  has_muscle_insertion: list
##  has_muscle_origin: list
##  in_anterior_side_of: list
##  anteriorly_connected_to: list
##  posteriorly_connected_to: list
##  proximally_connected_to: list
##  distally_connected_to: list
##  preaxialmost_part_of: list
##  contains_process: list
##  distalmost_part_of: list
##  innervated_by: list
##  has_muscle_antagonist: list
##  in_right_side_of: list
##  protects: list
##  lumen_of: list
##  tributary_of: list
##  sexually_homologous_to: list
##  develops_in: list
##  filtered_through: list
##  skeleton_of: list
##  postaxialmost_part_of: list
##  directly_develops_from: list
##  indirectly_supplies: list
##  in_posterior_side_of: list
##  deep_to: list
##  site_of: list
##  superficial_to: list
##  immediately_superficial_to: list
##  ventral_to: list
##  trunk_part_of: list
##  distal_to: list
##  proximal_to: list
##  in_deep_part_of: list
##  in_superficial_part_of: list
##  posterior_to: list
##  has_potential_to_developmentally_contribute_to: list
##  intersects_midsagittal_plane_of: list
##  layer_part_of: list
##  in_proximal_side_of: list
##  in_dorsal_side_of: list
##  develops_from_part_of: list
##  is_functional: list
##  inverse_of: list
##  domain: list
##  range: list
##  holds_over_chain: list
##  is_transitive: list
##  transitive_over: list
##  expand_expression_to: list
##  is_symmetric: list
##  is_inverse_functional: list
##  is_metadata_tag: list
##  is_asymmetric: list
##  expand_assertion_to: list
##  is_class_level: list
##  equivalent_to: list
## Roots:
##  PR:000000001 - protein
##  BFO:0000003 - occurrent
##  functionally_related_to - functionally related to
##  GO:0050878 - regulation of body fluid levels
##  RO:0002323 - mereotopologically related to
##  has_participant - has participant
##  RO:0002222 - temporally related to
##  CHEBI:36342 - subatomic particle
##  RO:0002410 - causally related to
##  GO:0010817 - regulation of hormone levels
##  ... 92 more

The most immediate use of this object lies in mapping ontology terms to their plain-English descriptions. We can use this to translate annotations produced by SingleR() from the label.ont labels into a more interpretable form. We demonstrate this approach using celldex’s collection of mouse RNA-seq references (Aran et al. 2019).

head(cl$name) # short name
##              BFO:0000002              BFO:0000003              BFO:0000004 
##             "continuant"              "occurrent" "independent continuant" 
##              BFO:0000006              BFO:0000015              BFO:0000016 
##         "spatial region"                "process"            "disposition"
head(cl$def) # longer definition
##                                                                                                                                                   BFO:0000002 
## "\"An entity that exists in full at any time in which it exists at all, persists through time while maintaining its identity and has no temporal parts.\" []" 
##                                                                                                                                                   BFO:0000003 
##                                                                "\"An entity that has temporal parts and that happens, unfolds or develops through time.\" []" 
##                                                                                                                                                   BFO:0000004 
##  "\"A continuant that is a bearer of quality and realizable entity entities, in which other entities inhere and which itself cannot inhere in anything.\" []" 
##                                                                                                                                                   BFO:0000006 
##                                                                                                                                                            NA 
##                                                                                                                                                   BFO:0000015 
##                                           "\"An occurrent that has temporal proper parts and for some time t, p s-depends_on some material entity at t.\" []" 
##                                                                                                                                                   BFO:0000016 
##                                                                                                                                                            NA
library(celldex)
ref <- MouseRNAseqData(cell.ont="nonna")
translated <- cl$name[ref$label.ont]
head(translated)
## CL:0000136 CL:0000136 CL:0000136 CL:0000136 CL:0000136 CL:0000136 
## "fat cell" "fat cell" "fat cell" "fat cell" "fat cell" "fat cell"

Another interesting application involves examining the relationship between different terms. The ontology itself is a directed acyclic graph, so we can can convert it into graph object for advanced queries using the igraph package. Each edge represents an “is a” relationship where each vertex represents a specialized case of the concept of the parent node.

# TODO: wrap in utility function.
parents <- cl$parents
self <- rep(names(parents), lengths(parents))

library(igraph)
g <- make_graph(rbind(unlist(parents), self))
g
## IGRAPH bf4bf5c DN-- 17142 26923 -- 
## + attr: name (v/c)
## + edges from bf4bf5c (vertex names):
##  [1] BFO:0000002 ->BFO:0000004  BFO:0000141 ->BFO:0000006 
##  [3] BFO:0000003 ->BFO:0000015  BFO:0000017 ->BFO:0000016 
##  [5] BFO:0000020 ->BFO:0000017  BFO:0000020 ->BFO:0000019 
##  [7] BFO:0000002 ->BFO:0000020  BFO:0000002 ->BFO:0000031 
##  [9] BFO:0000016 ->BFO:0000034  BFO:0000004 ->BFO:0000040 
## [11] BFO:0000004 ->BFO:0000141  CARO:0030000->CARO:0000000
## [13] CARO:0000006->CARO:0000003 CARO:0001008->CARO:0000004
## [15] CARO:0000000->CARO:0000006 BFO:0000141 ->CARO:0000007
## + ... omitted several edges

One query involves identifying all descendents of a particular term of interest. This can be useful when searching for a cell type in the presence of variable annotation resolution; for example, a search for “epithelial cell” can be configured to pick up all child terms such as “endothelial cell” and “ependymal cell”.

term <- "CL:0000624"
cl$name[term]
##                        CL:0000624 
## "CD4-positive, alpha-beta T cell"
all.kids <- names(subcomponent(g, term))
head(cl$name[all.kids])
##                                                       CL:0000624 
##                                "CD4-positive, alpha-beta T cell" 
##                                                       CL:0000492 
##                                     "CD4-positive helper T cell" 
##                                                       CL:0001051 
## "CD4-positive, CXCR3-negative, CCR6-negative, alpha-beta T cell" 
##                                                       CL:0000791 
##                                       "mature alpha-beta T cell" 
##                                                       CL:0000792 
##      "CD4-positive, CD25-positive, alpha-beta regulatory T cell" 
##                                                       CL:0000793 
##                "CD4-positive, alpha-beta intraepithelial T cell"

Alternatively, we might be interested in the last common ancestor (LCA) for a set of terms. This is the furthest term - or, in some cases, multiple terms - from the root of the ontology that is also an ancestor of all of the terms of interest. We will use this LCA concept in the next section to adjust resolution across multiple references.

terms <- c("CL:0000624", "CL:0000785", "CL:0000623")
cl$name[terms]
##                        CL:0000624                        CL:0000785 
## "CD4-positive, alpha-beta T cell"                   "mature B cell" 
##                        CL:0000623 
##             "natural killer cell"
# TODO: god, put this in a function somewhere.
all.ancestors <- lapply(terms, subcomponent, graph=g, mode="in")
all.ancestors <- lapply(all.ancestors, names)
common.ancestors <- Reduce(intersect, all.ancestors)

ancestors.of.ancestors <- lapply(common.ancestors, subcomponent, graph=g, mode="in")
ancestors.of.ancestors <- lapply(ancestors.of.ancestors, names)
ancestors.of.ancestors <- mapply(setdiff, ancestors.of.ancestors, common.ancestors) 

latest.common.ancestors <- setdiff(common.ancestors, unlist(ancestors.of.ancestors))
cl$name[latest.common.ancestors]
##   CL:0000542 
## "lymphocyte"

6.3 Adjusting resolution

We can use the ontology graph to adjust the resolution of the reference labels by rolling up overly-specific terms to their LCA. The findCommonAncestors() utility takes a set of terms and returns a list of potential LCAs for various subsets of those terms. Users can inspect this list to identify LCAs at the desired resolution and then map their descendent terms to those LCAs.

findCommonAncestors <- function(..., g, remove.self=TRUE, names=NULL) {
    terms <- list(...)
    if (is.null(names(terms))) {
        names(terms) <- sprintf("set%i", seq_along(terms))
    }

    all.terms <- unique(unlist(terms))
    all.ancestors <- lapply(all.terms, subcomponent, graph=g, mode="in")
    all.ancestors <- lapply(all.ancestors, names)
    by.ancestor <- split(
        rep(all.terms, lengths(all.ancestors)),
        unlist(all.ancestors)
    )

    # Removing ancestor nodes with the same count as its children.
    available <- names(by.ancestor)
    for (i in available) {
        if (!i %in% names(by.ancestor)) {
            next
        }

        counts <- lengths(by.ancestor)
        cur.ancestors <- subcomponent(g, i, mode="in")
        cur.ancestors <- setdiff(names(cur.ancestors), i)
        drop <- cur.ancestors[counts[i]==counts[cur.ancestors]]
        by.ancestor <- by.ancestor[!names(by.ancestor) %in% drop]
    }

    if (remove.self) {
        by.ancestor <- by.ancestor[lengths(by.ancestor) > 1L]
    }
    by.ancestor <- by.ancestor[order(lengths(by.ancestor))] # most specific terms first.

    # Decorating the output.
    for (i in names(by.ancestor)) {
        current <- by.ancestor[[i]]
        df <- DataFrame(row.names=current)

        curout <- list()
        if (!is.null(names)) {
            curout$name <- unname(names[i])
            df$name <- names[current]
        }

        presence <- list()
        for (b in names(terms)) {
            presence[[b]] <- current %in% terms[[b]]
        }
        df <- cbind(df, do.call(DataFrame, presence))

        curout$descendents <- df
        by.ancestor[[i]] <- curout
    }

    by.ancestor
}

lca <- findCommonAncestors(ref$label.ont, g=g, names=cl$name)
head(lca)
## $`CL:0000081`
## $`CL:0000081`$name
## [1] "blood cell"
## 
## $`CL:0000081`$descendents
## DataFrame with 2 rows and 2 columns
##                   name      set1
##            <character> <logical>
## CL:0000232 erythrocyte      TRUE
## CL:0000094 granulocyte      TRUE
## 
## 
## $`CL:0000126`
## $`CL:0000126`$name
## [1] "macroglial cell"
## 
## $`CL:0000126`$descendents
## DataFrame with 2 rows and 2 columns
##                       name      set1
##                <character> <logical>
## CL:0000127       astrocyte      TRUE
## CL:0000128 oligodendrocyte      TRUE
## 
## 
## $`CL:0000393`
## $`CL:0000393`$name
## [1] "electrically responsive cell"
## 
## $`CL:0000393`$descendents
## DataFrame with 2 rows and 2 columns
##                           name      set1
##                    <character> <logical>
## CL:0000540              neuron      TRUE
## CL:0000746 cardiac muscle cell      TRUE
## 
## 
## $`CL:0002320`
## $`CL:0002320`$name
## [1] "connective tissue cell"
## 
## $`CL:0002320`$descendents
## DataFrame with 2 rows and 2 columns
##                   name      set1
##            <character> <logical>
## CL:0000136    fat cell      TRUE
## CL:0000057  fibroblast      TRUE
## 
## 
## $`CL:0011026`
## $`CL:0011026`$name
## [1] "progenitor cell"
## 
## $`CL:0011026`$descendents
## DataFrame with 2 rows and 2 columns
##                              name      set1
##                       <character> <logical>
## CL:0000576               monocyte      TRUE
## CL:0002453 oligodendrocyte prec..      TRUE
## 
## 
## $`CARO:0000006`
## $`CARO:0000006`$name
## [1] "material anatomical entity"
## 
## $`CARO:0000006`$descendents
## DataFrame with 3 rows and 2 columns
##                              name      set1
##                       <character> <logical>
## CL:0000094            granulocyte      TRUE
## CL:0000129        microglial cell      TRUE
## CL:0000890 alternatively activa..      TRUE

We can also use this function to synchronize multiple sets of terms to the same resolution. Here, we consider the ImmGen dataset (Heng et al. 2008), which provides highly resolved annotation of immune cell types. The findCommonAncestors() function specifies the origins of the descendents for each LCA, allowing us to focus on LCAs that have representatives in both sets of terms.

ref2 <- ImmGenData(cell.ont="nonna")
lca2 <- findCommonAncestors(MouseRNA=ref$label.ont,
    ImmGen=ref2$label.ont, g=g, names=cl$name)
head(lca2)
## $`CL:0000034`
## $`CL:0000034`$name
## [1] "stem cell"
## 
## $`CL:0000034`$descendents
## DataFrame with 2 rows and 3 columns
##                              name  MouseRNA    ImmGen
##                       <character> <logical> <logical>
## CL:0000034              stem cell     FALSE      TRUE
## CL:0000037 hematopoietic stem c..     FALSE      TRUE
## 
## 
## $`CL:0000126`
## $`CL:0000126`$name
## [1] "macroglial cell"
## 
## $`CL:0000126`$descendents
## DataFrame with 2 rows and 3 columns
##                       name  MouseRNA    ImmGen
##                <character> <logical> <logical>
## CL:0000127       astrocyte      TRUE     FALSE
## CL:0000128 oligodendrocyte      TRUE     FALSE
## 
## 
## $`CL:0000393`
## $`CL:0000393`$name
## [1] "electrically responsive cell"
## 
## $`CL:0000393`$descendents
## DataFrame with 2 rows and 3 columns
##                           name  MouseRNA    ImmGen
##                    <character> <logical> <logical>
## CL:0000540              neuron      TRUE     FALSE
## CL:0000746 cardiac muscle cell      TRUE     FALSE
## 
## 
## $`CL:0000623`
## $`CL:0000623`$name
## [1] "natural killer cell"
## 
## $`CL:0000623`$descendents
## DataFrame with 2 rows and 3 columns
##                              name  MouseRNA    ImmGen
##                       <character> <logical> <logical>
## CL:0000623    natural killer cell      TRUE      TRUE
## CL:0002438 NK1.1-positive natur..     FALSE      TRUE
## 
## 
## $`CL:0000813`
## $`CL:0000813`$name
## [1] "memory T cell"
## 
## $`CL:0000813`$descendents
## DataFrame with 2 rows and 3 columns
##                              name  MouseRNA    ImmGen
##                       <character> <logical> <logical>
## CL:0000897 CD4-positive, alpha-..     FALSE      TRUE
## CL:0000909 CD8-positive, alpha-..     FALSE      TRUE
## 
## 
## $`CL:0000815`
## $`CL:0000815`$name
## [1] "regulatory T cell"
## 
## $`CL:0000815`$descendents
## DataFrame with 2 rows and 3 columns
##                              name  MouseRNA    ImmGen
##                       <character> <logical> <logical>
## CL:0000792 CD4-positive, CD25-p..     FALSE      TRUE
## CL:0000815      regulatory T cell     FALSE      TRUE

For example, we might notice that the mouse RNA-seq reference only has a single “T cell” term. To synchronize resolution across references, we would need to roll up all of the ImmGen’s finely resolved subsets into that LCA as shown below. Of course, this results in some loss of precision and information; whether this is an acceptable price for simpler interpretation is a decision that is left to the user.

children <- lca2$`CL:0000084`$descendents
children
## DataFrame with 35 rows and 3 columns
##                              name  MouseRNA    ImmGen
##                       <character> <logical> <logical>
## CL:0000084                 T cell      TRUE      TRUE
## CL:0002427 resting double-posit..     FALSE      TRUE
## CL:0000809 double-positive, alp..     FALSE      TRUE
## CL:0002429 CD69-positive double..     FALSE      TRUE
## CL:0000624 CD4-positive, alpha-..     FALSE      TRUE
## ...                           ...       ...       ...
## CL:0002415 immature Vgamma1.1-p..     FALSE      TRUE
## CL:0002411 Vgamma1.1-positive, ..     FALSE      TRUE
## CL:0002416 mature Vgamma1.1-pos..     FALSE      TRUE
## CL:0002407 mature Vgamma2-posit..     FALSE      TRUE
## CL:0000815      regulatory T cell     FALSE      TRUE
# Synchronization:
synced.mm <- ref$label.ont
synced.mm[synced.mm %in% rownames(children)] <- "CL:0000084"
synced.ig <- ref2$label.ont
synced.ig[synced.ig %in% rownames(children)] <- "CL:0000084"

Session information

R Under development (unstable) (2024-10-21 r87258)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 24.04.1 LTS

Matrix products: default
BLAS:   /home/biocbuild/bbs-3.21-bioc/R/lib/libRblas.so 
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_GB              LC_COLLATE=C              
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

time zone: America/New_York
tzcode source: system (glibc)

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

other attached packages:
 [1] igraph_2.1.1                celldex_1.17.0             
 [3] SummarizedExperiment_1.37.0 Biobase_2.67.0             
 [5] GenomicRanges_1.59.1        GenomeInfoDb_1.43.1        
 [7] IRanges_2.41.1              S4Vectors_0.45.2           
 [9] BiocGenerics_0.53.3         generics_0.1.3             
[11] MatrixGenerics_1.19.0       matrixStats_1.4.1          
[13] ontoProc_2.1.0              ontologyIndex_2.12         
[15] BiocStyle_2.35.0            rebook_1.17.0              

loaded via a namespace (and not attached):
 [1] DBI_1.2.3                 httr2_1.0.6              
 [3] CodeDepends_0.6.6         rlang_1.1.4              
 [5] magrittr_2.0.3            gypsum_1.3.0             
 [7] compiler_4.5.0            RSQLite_2.3.8            
 [9] dir.expiry_1.15.0         DelayedMatrixStats_1.29.0
[11] png_0.1-8                 vctrs_0.6.5              
[13] pkgconfig_2.0.3           crayon_1.5.3             
[15] fastmap_1.2.0             dbplyr_2.5.0             
[17] XVector_0.47.0            utf8_1.2.4               
[19] promises_1.3.0            rmarkdown_2.29           
[21] graph_1.85.0              UCSC.utils_1.3.0         
[23] purrr_1.0.2               bit_4.5.0                
[25] xfun_0.49                 zlibbioc_1.53.0          
[27] cachem_1.1.0              jsonlite_1.8.9           
[29] blob_1.2.4                later_1.3.2              
[31] rhdf5filters_1.19.0       DelayedArray_0.33.2      
[33] Rhdf5lib_1.29.0           parallel_4.5.0           
[35] R6_2.5.1                  bslib_0.8.0              
[37] reticulate_1.40.0         jquerylib_0.1.4          
[39] Rcpp_1.0.13-1             bookdown_0.41            
[41] knitr_1.49                httpuv_1.6.15            
[43] Matrix_1.7-1              tidyselect_1.2.1         
[45] abind_1.4-8               yaml_2.3.10              
[47] codetools_0.2-20          curl_6.0.1               
[49] lattice_0.22-6            tibble_3.2.1             
[51] shiny_1.9.1               withr_3.0.2              
[53] KEGGREST_1.47.0           evaluate_1.0.1           
[55] BiocFileCache_2.15.0      alabaster.schemas_1.7.0  
[57] ExperimentHub_2.15.0      Biostrings_2.75.1        
[59] pillar_1.9.0              BiocManager_1.30.25      
[61] filelock_1.0.3            DT_0.33                  
[63] BiocVersion_3.21.1        sparseMatrixStats_1.19.0 
[65] alabaster.base_1.7.2      xtable_1.8-4             
[67] alabaster.ranges_1.7.0    glue_1.8.0               
[69] alabaster.matrix_1.7.0    tools_4.5.0              
[71] ontologyPlot_1.7          AnnotationHub_3.15.0     
[73] XML_3.99-0.17             rhdf5_2.51.0             
[75] grid_4.5.0                AnnotationDbi_1.69.0     
[77] GenomeInfoDbData_1.2.13   HDF5Array_1.35.1         
[79] cli_3.6.3                 rappdirs_0.3.3           
[81] fansi_1.0.6               S4Arrays_1.7.1           
[83] dplyr_1.1.4               Rgraphviz_2.51.0         
[85] alabaster.se_1.7.0        sass_0.4.9               
[87] digest_0.6.37             SparseArray_1.7.2        
[89] paintmap_1.0              htmlwidgets_1.6.4        
[91] memoise_2.0.1             htmltools_0.5.8.1        
[93] lifecycle_1.0.4           httr_1.4.7               
[95] mime_0.12                 bit64_4.5.2              

Bibliography

Aran, D., A. P. Looney, L. Liu, E. Wu, V. Fong, A. Hsu, S. Chak, et al. 2019. Reference-based analysis of lung single-cell sequencing reveals a transitional profibrotic macrophage.” Nat. Immunol. 20 (2): 163–72.
Heng, Tracy S. P., Michio W. Painter, Kutlu Elpek, Veronika Lukacs-Kornek, Nora Mauermann, Shannon J. Turley, Daphne Koller, et al. 2008. The immunological genome project: Networks of gene expression in immune cells.” Nature Immunology 9: 1091–94. https://doi.org/10.1038/ni1008-1091.