diff --git a/.github/workflows/dev_workflow.yml b/.github/workflows/dev_workflow.yml new file mode 100644 index 00000000..30e5dcbb --- /dev/null +++ b/.github/workflows/dev_workflow.yml @@ -0,0 +1,146 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# +# See https://github.com/r-lib/actions/tree/master/examples#readme for +# additional example workflows available for the R community. + + +name: Dev Workflow - Test and check +on: + push: + branches: [ "dev" ] + +permissions: + contents: read + +jobs: + R-CMD-check: + name: R CMD Check + env: + GITHUB_PAT: ${{ secrets.WORKFLOW_PAT }} + runs-on: ubuntu-latest + + steps: + + - name: Remove vignettes dir + run: rm -rf 'vignettes/' + shell: bash + + - name: Checkout repo for workflow access + uses: actions/checkout@v3 + + - name: Set up R environment + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Set up dependencies (general) + uses: r-lib/actions/setup-r-dependencies@v2 + env: + _R_CHECK_FORCE_SUGGESTS: false + _R_CHECK_RD_XREFS: false + with: + dependencies: '"hard"' # do not use suggested dependencies + extra-packages: any::rcmdcheck, any::testthat, any::rlang, any::R.utils, any::remotes + + - name: Set up dependencies (GiottoData) + run: | + suppressWarnings({ + remotes::install_github('drieslab/GiottoData@suite_modular', build = FALSE) + }) + shell: Rscript {0} + + - name: Run R CMD check + uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true + error-on: '"error"' # workflow errors on error only, can change to include warnings + + # show testthat output for ease of access + - name: Show testthat output + if: always() + run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true + shell: bash + + + test-coverage: + name: Code coverage + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + + steps: + + - name: Checkout repo for workflow access + uses: actions/checkout@v3 + + - name: Set up R environment + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Set up dependencies (general) + uses: r-lib/actions/setup-r-dependencies@v2 + env: + _R_CHECK_FORCE_SUGGESTS: false + _R_CHECK_RD_XREFS: false + with: + dependencies: '"hard"' # do not use suggested dependencies + extra-packages: any::rcmdcheck, any::testthat, any::rlang, any::R.utils, any::remotes, any::covr + needs: coverage + + - name: Set up dependencies (GiottoData) + run: | + suppressWarnings({ + remotes::install_github('drieslab/GiottoData@suite_modular', build = FALSE) + }) + shell: Rscript {0} + + - name: Test coverage + run: | + covr::codecov( + quiet = FALSE, + clean = FALSE, + install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package") + ) + shell: Rscript {0} + + # add code cov + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + + + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout repo for workflow access + uses: actions/checkout@v3 + + - name: Set up R environment + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Set up dependencies (general) + uses: r-lib/actions/setup-r-dependencies@v2 + env: + _R_CHECK_FORCE_SUGGESTS: false + _R_CHECK_RD_XREFS: false + with: + dependencies: '"hard"' # do not use suggested dependencies + extra-packages: any::lintr, local::. + needs: lint + + - name: Lint + run: lintr::lint_package() + shell: Rscript {0} + env: + LINTR_ERROR_ON_LINT: false + + + diff --git a/.github/workflows/github_workflow.yml b/.github/workflows/prod_workflow.yml similarity index 55% rename from .github/workflows/github_workflow.yml rename to .github/workflows/prod_workflow.yml index 2f7db7c1..7056e97b 100644 --- a/.github/workflows/github_workflow.yml +++ b/.github/workflows/prod_workflow.yml @@ -7,19 +7,21 @@ # additional example workflows available for the R community. +name: Master Workflow - Deploy to production + on: - push: - branches: [ "main" ] pull_request: + types: closed branches: [ "main" ] permissions: contents: read -name: github_workflow jobs: R-CMD-check: + env: + GITHUB_PAT: ${{ secrets.WORKFLOW_PAT }} runs-on: ${{ matrix.config.os }} name: ${{ matrix.config.os }} (${{ matrix.config.r }}) @@ -35,32 +37,46 @@ jobs: - {os: ubuntu-latest, r: 'oldrel-1'} steps: - # remove vignettes dir + - name: Remove vignettes dir run: rm -rf 'vignettes/' shell: bash - # checkout repo for workflow access - - uses: actions/checkout@v2 + - name: Checkout repo for workflow access + uses: actions/checkout@v3 - # setup R - - uses: r-lib/actions/setup-r@v2 + - name: Set up R environment + uses: r-lib/actions/setup-r@v2 with: r-version: ${{ matrix.config.r }} http-user-agent: ${{ matrix.config.http-user-agent }} use-public-rspm: true - # setup dependencies - - uses: r-lib/actions/setup-r-dependencies@v2 + - name: Set up dependencies (general) + uses: r-lib/actions/setup-r-dependencies@v2 env: _R_CHECK_FORCE_SUGGESTS: false _R_CHECK_RD_XREFS: false with: dependencies: '"hard"' # do not use suggested dependencies - extra-packages: any::rcmdcheck, any::testthat, any::data.table + extra-packages: any::rcmdcheck, any::testthat, any::rlang, any::R.utils, any::remotes, any::covr + + - name: Set up dependencies (GiottoData) + run: | + suppressWarnings({ + remotes::install_github('drieslab/GiottoData@suite_modular', build = FALSE) + }) + shell: Rscript {0} - # run R CMD check - - uses: r-lib/actions/check-r-package@v2 + - name: Test python env build + run: | + if (!GiottoClass::checkGiottoEnvironment()) { + GiottoClass::installGiottoEnvironment() + } + shell: Rscript {0} + + - name: Run R CMD check + uses: r-lib/actions/check-r-package@v2 with: upload-snapshots: true error-on: '"error"' # workflow errors on error only, can change to include warnings @@ -71,35 +87,40 @@ jobs: run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true shell: bash + test-coverage: + name: Code coverage runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v3 - - uses: r-lib/actions/setup-r@v2 + - name: Checkout repo for workflow access + uses: actions/checkout@v3 + + - name: Set up R environment + uses: r-lib/actions/setup-r@v2 with: use-public-rspm: true - # install extra dependencies - - name: Install GiottoData + - name: Set up dependencies (general) + uses: r-lib/actions/setup-r-dependencies@v2 + env: + _R_CHECK_FORCE_SUGGESTS: false + _R_CHECK_RD_XREFS: false + with: + dependencies: '"hard"' # do not use suggested dependencies + extra-packages: any::rcmdcheck, any::testthat, any::rlang, any::R.utils, any::remotes, any::covr + needs: coverage + + - name: Set up dependencies (GiottoData) run: | suppressWarnings({ - if(!require(remotes)){ - install.packages('R.utils', repos = 'http://cran.us.r-project.org') - install.packages('remotes', repos = 'http://cran.us.r-project.org') - } - remotes::install_github('drieslab/GiottoData', build = FALSE) + remotes::install_github('drieslab/GiottoData@suite_modular', build = FALSE) }) shell: Rscript {0} - - uses: r-lib/actions/setup-r-dependencies@v2 - with: - extra-packages: any::covr - needs: coverage - - name: Test coverage run: | covr::codecov( @@ -109,15 +130,14 @@ jobs: ) shell: Rscript {0} - # add code cov - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - # lint: # runs-on: ubuntu-latest + # needs: R-CMD-check # env: # GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} # steps: @@ -139,29 +159,31 @@ jobs: # LINTR_ERROR_ON_LINT: true - # render-rmarkdown: - # runs-on: ubuntu-latest - # env: - # GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - # steps: - # - name: Checkout repo - # uses: actions/checkout@v3 - # with: - # fetch-depth: 0 - # - # - uses: r-lib/actions/setup-pandoc@v2 - # - # - uses: r-lib/actions/setup-r@v2 - # - # - uses: r-lib/actions/setup-renv@v2 - # - # - name: Install rmarkdown - # run: Rscript -e 'install.packages("rmarkdown")' - # - # - name: Render README - # run: Rscript -e 'rmarkdown::render("README.Rmd")' - # - # - name: Commit results - # run: | - # git commit README.md -m 'Re-build README.Rmd' || echo "No changes to commit" - # git push origin || echo "No changes to commit" + render-rmarkdown: + name: Update README.Rmd + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + + - uses: r-lib/actions/setup-renv@v2 + + - name: Install rmarkdown + run: Rscript -e 'install.packages("rmarkdown")' + + - name: Render README + run: Rscript -e 'rmarkdown::render("README.Rmd")' + + - name: Commit results + run: | + git commit README.md -m 'Re-build README.Rmd' || echo "No changes to commit" + git push origin || echo "No changes to commit" + + + diff --git a/DESCRIPTION b/DESCRIPTION index 5c73cccb..a89a57d3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -52,6 +52,7 @@ Suggests: HDF5Array (>= 1.18.1), remotes, rhdf5, + rlang, RTriangle (>= 1.6-0.10), S4Vectors, scattermore, diff --git a/NAMESPACE b/NAMESPACE index c4c16278..dec2e2aa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -32,6 +32,7 @@ export(calculateOverlapParallel) export(calculateOverlapPolygonImages) export(calculateOverlapRaster) export(calculateOverlapSerial) +export(calculateSpatCellMetadataProportions) export(changeGiottoInstructions) export(changeImageBg) export(checkGiottoEnvironment) @@ -44,6 +45,7 @@ export(combineFeatureOverlapData) export(combineMetadata) export(combineSpatialCellFeatureInfo) export(combineSpatialCellMetadataInfo) +export(compatible_spatial_network) export(convertGiottoLargeImageToMG) export(convert_mgImage_to_array_DT) export(convert_to_full_spatial_network) diff --git a/R/classes.R b/R/classes.R index f4682dc5..2b7bd78e 100644 --- a/R/classes.R +++ b/R/classes.R @@ -1,4 +1,3 @@ - #' @include package_imports.R NULL @@ -9,19 +8,19 @@ NULL #' @description class to allow either NULL or character #' @keywords internal #' @noRd -setClassUnion('nullOrChar', c('NULL', 'character')) +setClassUnion("nullOrChar", c("NULL", "character")) #' @title NULL or list class union #' @description class to allow either NULL or list #' @keywords internal #' @noRd -setClassUnion('nullOrList', c('NULL', 'list')) +setClassUnion("nullOrList", c("NULL", "list")) #' @title NULL or data.table class union #' @description class to allow either NULL or data.table #' @keywords internal #' @noRd -setClassUnion('nullOrDatatable', c('NULL', 'data.table')) +setClassUnion("nullOrDatatable", c("NULL", "data.table")) @@ -34,19 +33,21 @@ setClassUnion('nullOrDatatable', c('NULL', 'data.table')) # ** nameData Class #### #' @keywords internal #' @noRd -setClass('nameData', - contains = 'VIRTUAL', - slots = list(name = 'character'), - prototype = prototype(name = NA_character_)) +setClass("nameData", + contains = "VIRTUAL", + slots = list(name = "character"), + prototype = prototype(name = NA_character_) +) # ** exprData Class #### #' Basic class for classes with expression information #' @keywords internal #' @noRd -setClass('exprData', - contains = 'VIRTUAL', - slots = list(exprMat = 'ANY'), - prototype = prototype(exprMat = NULL)) +setClass("exprData", + contains = "VIRTUAL", + slots = list(exprMat = "ANY"), + prototype = prototype(exprMat = NULL) +) @@ -59,10 +60,11 @@ setClass('exprData', #' retreival and setting. #' @keywords internal #' @noRd -setClass('coordDataDT', - contains = 'VIRTUAL', - slots = list(coordinates = 'data.table'), - prototype = prototype(coordinates = data.table::data.table())) +setClass("coordDataDT", + contains = "VIRTUAL", + slots = list(coordinates = "data.table"), + prototype = prototype(coordinates = data.table::data.table()) +) @@ -81,13 +83,16 @@ setClass('coordDataDT', #' with some basic generic operators for data retrieval and setting #' @keywords internal #' @noRd -setClass('metaData', - contains = 'VIRTUAL', - slots = list(metaDT = 'data.table', - col_desc = 'character'), - prototype = methods::prototype( - metaDT = data.table::data.table(), - col_desc = NA_character_) +setClass("metaData", + contains = "VIRTUAL", + slots = list( + metaDT = "data.table", + col_desc = "character" + ), + prototype = methods::prototype( + metaDT = data.table::data.table(), + col_desc = NA_character_ + ) ) @@ -98,12 +103,17 @@ setClass('metaData', #' enrData #' @keywords internal #' @noRd -setClass('enrData', - contains = 'VIRTUAL', - slots = list(method = 'character', - enrichDT = 'nullOrDatatable'), - prototype = methods::prototype(method = NA_character_, - enrichDT = NULL)) +setClass("enrData", + contains = "VIRTUAL", + slots = list( + method = "character", + enrichDT = "nullOrDatatable" + ), + prototype = methods::prototype( + method = NA_character_, + enrichDT = NULL + ) +) @@ -112,31 +122,41 @@ setClass('enrData', # ** nnData #### #' @keywords internal #' @noRd -setClass('nnData', - contains = 'VIRTUAL', - slots = list(nn_type = 'character', - igraph = 'ANY'), - prototype = methods::prototype(nn_type = NA_character_, - igraph = NULL)) +setClass("nnData", + contains = "VIRTUAL", + slots = list( + nn_type = "character", + igraph = "ANY" + ), + prototype = methods::prototype( + nn_type = NA_character_, + igraph = NULL + ) +) # ** spatNetData #### #' @keywords internal #' @noRd -setClass('spatNetData', - contains = 'VIRTUAL', - slots = list(method = 'character', - parameters = 'ANY', - outputObj = 'ANY', - networkDT = 'nullOrDatatable', - networkDT_before_filter = 'nullOrDatatable', - cellShapeObj = 'ANY'), - prototype = methods::prototype(method = NA_character_, - parameters = NULL, - outputObj = NULL, - networkDT = NULL, - networkDT_before_filter = NULL, - cellShapeObj = NULL)) +setClass("spatNetData", + contains = "VIRTUAL", + slots = list( + method = "character", + parameters = "ANY", + outputObj = "ANY", + networkDT = "nullOrDatatable", + networkDT_before_filter = "nullOrDatatable", + cellShapeObj = "ANY" + ), + prototype = methods::prototype( + method = NA_character_, + parameters = NULL, + outputObj = NULL, + networkDT = NULL, + networkDT_before_filter = NULL, + cellShapeObj = NULL + ) +) @@ -144,14 +164,19 @@ setClass('spatNetData', # ** spatGridData #### #' @keywords internal #' @noRd -setClass('spatGridData', - contains = 'VIRTUAL', - slots = list(method = 'character', - parameters = 'ANY', - gridDT = 'nullOrDatatable'), - prototype = prototype(method = NA_character_, - parameters = NULL, - gridDT = NULL)) +setClass("spatGridData", + contains = "VIRTUAL", + slots = list( + method = "character", + parameters = "ANY", + gridDT = "nullOrDatatable" + ), + prototype = prototype( + method = NA_character_, + parameters = NULL, + gridDT = NULL + ) +) @@ -168,10 +193,11 @@ setClass('spatGridData', #' z layers that were used in its generation. #' @keywords internal #' @noRd -setClass('provData', - contains = 'VIRTUAL', - slots = list(provenance = 'ANY'), - prototype = prototype(provenance = NULL)) +setClass("provData", + contains = "VIRTUAL", + slots = list(provenance = "ANY"), + prototype = prototype(provenance = NULL) +) @@ -185,10 +211,11 @@ setClass('provData', #' there is a nesting structure that first nests by spatial unit. #' @keywords internal #' @noRd -setClass('spatData', - contains = c('provData', 'VIRTUAL'), - slots = list(spat_unit = 'character'), # not allowed to be NULL - prototype = prototype(spat_unit = NA_character_)) +setClass("spatData", + contains = c("provData", "VIRTUAL"), + slots = list(spat_unit = "character"), # not allowed to be NULL + prototype = prototype(spat_unit = NA_character_) +) @@ -204,10 +231,11 @@ setClass('spatData', #' and then by feature type #' @keywords internal #' @noRd -setClass('featData', - contains = 'VIRTUAL', - slots = list(feat_type = 'character'), # not allowed to be NULL - prototype = prototype(feat_type = NA_character_)) +setClass("featData", + contains = "VIRTUAL", + slots = list(feat_type = "character"), # not allowed to be NULL + prototype = prototype(feat_type = NA_character_) +) @@ -218,10 +246,11 @@ setClass('featData', #' Classes (such as dimObj) that can hold information from multiple types of methods #' use the misc slot to hold additional information specific to each method. #' Information may be stored within as S3 structures. -setClass('miscData', - contains = 'VIRTUAL', - slots = list(misc = 'ANY'), - prototype = prototype(misc = NULL)) +setClass("miscData", + contains = "VIRTUAL", + slots = list(misc = "ANY"), + prototype = prototype(misc = NULL) +) @@ -236,8 +265,9 @@ setClass('miscData', #' Superclass for classes that contain both spatial and feature data #' @keywords internal #' @noRd -setClass('spatFeatData', - contains = c('spatData', 'featData', 'VIRTUAL')) +setClass("spatFeatData", + contains = c("spatData", "featData", "VIRTUAL") +) @@ -342,25 +372,24 @@ setClass('spatFeatData', #' } #' @examples #' \dontrun{ -#' gobject = updateGiottoObject(gobject) +#' gobject <- updateGiottoObject(gobject) #' } #' @export -updateGiottoObject = function(gobject) { - - if(!inherits(gobject, 'giotto')) { - stop(wrap_txt('This function is intended for updating giotto objects')) +updateGiottoObject <- function(gobject) { + if (!inherits(gobject, "giotto")) { + stop(wrap_txt("This function is intended for updating giotto objects")) } # 3.2.0 release adds multiomics slot - if(is.null(attr(gobject, 'multiomics'))) { - attr(gobject, 'multiomics') = NA - gobject@multiomics = NULL + if (is.null(attr(gobject, "multiomics"))) { + attr(gobject, "multiomics") <- NA + gobject@multiomics <- NULL } # 3.3.1 release adds h5_file slot - if(is.null(attr(gobject, 'h5_file'))) { - attr(gobject, 'h5_file') = NA - gobject@h5_file = NULL + if (is.null(attr(gobject, "h5_file"))) { + attr(gobject, "h5_file") <- NA + gobject@h5_file <- NULL } return(gobject) @@ -397,6 +426,7 @@ updateGiottoObject = function(gobject) { #' @slot OS_platform Operating System to run Giotto analysis on #' @slot join_info information about joined Giotto objects #' @slot multiomics multiomics integration results +#' @slot h5_file path to h5 file #' @details #' \[\strong{expression}\] There are several ways to provide expression information: #' @@ -420,7 +450,7 @@ giotto <- setClass( spatial_network = "ANY", spatial_grid = "ANY", spatial_enrichment = "ANY", - dimension_reduction = 'ANY', + dimension_reduction = "ANY", nn_network = "ANY", images = "ANY", largeImages = "ANY", @@ -431,9 +461,7 @@ giotto <- setClass( join_info = "ANY", multiomics = "ANY", h5_file = "ANY" - ), - prototype = list( expression = NULL, expression_feat = NULL, @@ -488,7 +516,6 @@ setClass( slots = c( packed_spatial_info = "ANY", packed_feat_info = "ANY", - expression = "nullOrList", expression_feat = "ANY", spatial_locs = "ANY", @@ -499,7 +526,7 @@ setClass( spatial_network = "ANY", spatial_grid = "ANY", spatial_enrichment = "ANY", - dimension_reduction = 'ANY', + dimension_reduction = "ANY", nn_network = "ANY", images = "ANY", largeImages = "ANY", @@ -508,14 +535,12 @@ setClass( offset_file = "ANY", OS_platform = "ANY", join_info = "ANY", - multiomics = "ANY" - + multiomics = "ANY", + h5_file = "ANY" ), - prototype = list( packed_spatial_info = NULL, packed_feat_info = NULL, - expression = NULL, expression_feat = NULL, spatial_locs = NULL, @@ -535,7 +560,8 @@ setClass( offset_file = NULL, OS_platform = NULL, join_info = NULL, - multiomics = NULL + multiomics = NULL, + h5_file = NULL ) ) @@ -557,21 +583,23 @@ setClass( #' @description Check function for S4 exprObj #' @param object S4 exprObj to check #' @keywords internal -check_expr_obj = function(object) { - errors = character() +check_expr_obj <- function(object) { + errors <- character() # Check for expr info - if(is.null(slot(object, 'exprMat'))) { - obj_info = paste0('exprObj ', - 'spat_unit "', slot(object, 'spat_unit'), '", ', - 'feat_type "', slot(object, 'feat_type'), '", ', - 'name "', slot(object, 'name'), '": \n') - - msg = paste0(obj_info, 'No expression information found.\n') - errors = c(errors, msg) + if (is.null(slot(object, "exprMat"))) { + obj_info <- paste0( + "exprObj ", + 'spat_unit "', slot(object, "spat_unit"), '", ', + 'feat_type "', slot(object, "feat_type"), '", ', + 'name "', slot(object, "name"), '": \n' + ) + + msg <- paste0(obj_info, "No expression information found.\n") + errors <- c(errors, msg) } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } @@ -588,9 +616,10 @@ check_expr_obj = function(object) { #' @slot provenance origin data of expression information (if applicable) #' @slot misc misc #' @export -setClass('exprObj', - contains = c('nameData', 'exprData', 'spatFeatData', 'miscData'), - validity = check_expr_obj) +setClass("exprObj", + contains = c("nameData", "exprData", "spatFeatData", "miscData"), + validity = check_expr_obj +) @@ -613,27 +642,24 @@ setClass('exprObj', #' @description Function to check S4 cellMetaObj #' @param object S4 cellMetaObj to check #' @keywords internal -check_cell_meta_obj = function(object) { - - errors = character() +check_cell_meta_obj <- function(object) { + errors <- character() - if(!'cell_ID' %in% colnames(object@metaDT)) { - msg = 'No "cell_ID" column found.' - errors = c(errors, msg) + if (!"cell_ID" %in% colnames(object@metaDT)) { + msg <- 'No "cell_ID" column found.' + errors <- c(errors, msg) } else { - - if(!is.character(object@metaDT[['cell_ID']])) { - msg = '"cell_ID" column must be of class character.' - errors = c(errors, msg) + if (!is.character(object@metaDT[["cell_ID"]])) { + msg <- '"cell_ID" column must be of class character.' + errors <- c(errors, msg) } - if(colnames(object@metaDT)[[1]] != 'cell_ID') { - msg = '"cell_ID" column should be the first column.' - errors = c(errors, msg) + if (colnames(object@metaDT)[[1]] != "cell_ID") { + msg <- '"cell_ID" column should be the first column.' + errors <- c(errors, msg) } - } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } # * Definition #### @@ -645,9 +671,10 @@ check_cell_meta_obj = function(object) { #' @slot feat_type feature type of aggregated expression (e.g. 'rna', 'protein') #' @slot provenance origin data of aggregated expression information (if applicable) #' @export -setClass('cellMetaObj', - contains = c('metaData', 'spatFeatData'), - validity = check_cell_meta_obj) +setClass("cellMetaObj", + contains = c("metaData", "spatFeatData"), + validity = check_cell_meta_obj +) @@ -660,27 +687,24 @@ setClass('cellMetaObj', #' @description Function to check S4 featMetaObj #' @param object S4 featMetaObj to check #' @keywords internal -check_feat_meta_obj = function(object) { +check_feat_meta_obj <- function(object) { + errors <- character() - errors = character() - - if(!'feat_ID' %in% colnames(object@metaDT)) { - msg = 'No "feat_ID" column found.' - errors = c(errors, msg) + if (!"feat_ID" %in% colnames(object@metaDT)) { + msg <- 'No "feat_ID" column found.' + errors <- c(errors, msg) } else { - - if(!is.character(object@metaDT[['feat_ID']])) { - msg = '"feat_ID" column must be of class character.' - errors = c(errors, msg) + if (!is.character(object@metaDT[["feat_ID"]])) { + msg <- '"feat_ID" column must be of class character.' + errors <- c(errors, msg) } - if(colnames(object@metaDT)[[1]] != 'feat_ID') { - msg = '"feat_ID" column should be the first column.' - errors = c(errors, msg) + if (colnames(object@metaDT)[[1]] != "feat_ID") { + msg <- '"feat_ID" column should be the first column.' + errors <- c(errors, msg) } - } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } # * Definition #### @@ -692,9 +716,10 @@ check_feat_meta_obj = function(object) { #' @slot feat_type feature type of aggregated expression (e.g. 'rna', 'protein') #' @slot provenance origin data of aggregated expression information (if applicable) #' @export -setClass('featMetaObj', - contains = c('metaData', 'spatFeatData'), - validity = check_feat_meta_obj) +setClass("featMetaObj", + contains = c("metaData", "spatFeatData"), + validity = check_feat_meta_obj +) @@ -713,24 +738,24 @@ setClass('featMetaObj', #' @description check function for S4 dimObj #' @param object S4 dimObj to check #' @keywords internal -check_dim_obj = function(object) { - errors = character() - length_reduction_method = length(object@reduction_method) - if(length_reduction_method > 1) { - msg = paste0('reduction_method is length ', length_reduction_method, '. Should be 1') - errors = c(errors, msg) +check_dim_obj <- function(object) { + errors <- character() + length_reduction_method <- length(object@reduction_method) + if (length_reduction_method > 1) { + msg <- paste0("reduction_method is length ", length_reduction_method, ". Should be 1") + errors <- c(errors, msg) } - if(length_reduction_method == 0) { - msg = 'A reduction_method must be given' - errors = c(errors, msg) + if (length_reduction_method == 0) { + msg <- "A reduction_method must be given" + errors <- c(errors, msg) } - lastCols = tail(colnames(object@coordinates),2) - col_dims = all(grepl(pattern = 'Dim.', x = lastCols)) - if(!isTRUE(col_dims)) { - msg = 'Dim reduction coordinates should be provided with dimensions ("Dim.#") as columns and samples as rows\n' - errors = c(errors, msg) + lastCols <- tail(colnames(object@coordinates), 2) + col_dims <- all(grepl(pattern = "Dim.", x = lastCols)) + if (!isTRUE(col_dims)) { + msg <- 'Dim reduction coordinates should be provided with dimensions ("Dim.#") as columns and samples as rows\n' + errors <- c(errors, msg) } # This check applied using check_dimension_reduction() @@ -739,7 +764,7 @@ check_dim_obj = function(object) { # errors = c(errors, msg) # } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } @@ -758,17 +783,22 @@ check_dim_obj = function(object) { #' @slot coordinates embedding coordinates #' @slot misc method-specific additional outputs #' @export -setClass('dimObj', - contains = c('nameData', 'spatFeatData'), - slots = c(reduction = 'character', - reduction_method = 'character', - coordinates = 'ANY', - misc = 'ANY'), - prototype = list(reduction = NA_character_, - reduction_method = NA_character_, - coordinates = NULL, - misc = NULL), - validity = check_dim_obj) +setClass("dimObj", + contains = c("nameData", "spatFeatData"), + slots = c( + reduction = "character", + reduction_method = "character", + coordinates = "ANY", + misc = "ANY" + ), + prototype = list( + reduction = NA_character_, + reduction_method = NA_character_, + coordinates = NULL, + misc = NULL + ), + validity = check_dim_obj +) @@ -783,15 +813,16 @@ setClass('dimObj', #' @description Convert S3 dimObj to S4 #' @param object S3 dimObj #' @keywords internal -S3toS4dimObj = function(object) { - if(!isS4(object)) { - object = new('dimObj', - name = object$name, - feat_type = object$feat_type, - spat_unit = object$spat_unit, - reduction_method = object$reduction_method, - coordinates = object$coordinates, - misc = object$misc) +S3toS4dimObj <- function(object) { + if (!isS4(object)) { + object <- new("dimObj", + name = object$name, + feat_type = object$feat_type, + spat_unit = object$spat_unit, + reduction_method = object$reduction_method, + coordinates = object$coordinates, + misc = object$misc + ) } object } @@ -815,8 +846,9 @@ S3toS4dimObj = function(object) { #' @slot provenance origin of aggregated information (if applicable) #' @slot misc misc #' @export -setClass('nnNetObj', - contains = c('nameData', 'nnData', 'spatFeatData', 'miscData')) +setClass("nnNetObj", + contains = c("nameData", "nnData", "spatFeatData", "miscData") +) @@ -848,26 +880,26 @@ setClass('nnNetObj', #' @description Check function for S4 spatLocsObj #' @param object S4 spatLocsObj to check #' @keywords internal -check_spat_locs_obj = function(object) { - errors = character() +check_spat_locs_obj <- function(object) { + errors <- character() - if(!'sdimx' %in% colnames(slot(object, 'coordinates'))) { - msg = 'Column "sdimx" for x spatial location was not found' - errors = c(errors, msg) + if (!"sdimx" %in% colnames(slot(object, "coordinates"))) { + msg <- 'Column "sdimx" for x spatial location was not found' + errors <- c(errors, msg) } - if(!'sdimy' %in% colnames(slot(object, 'coordinates'))) { - msg = 'Column "sdimy" for y spatial location was not found' - errors = c(errors, msg) + if (!"sdimy" %in% colnames(slot(object, "coordinates"))) { + msg <- 'Column "sdimy" for y spatial location was not found' + errors <- c(errors, msg) } # Allow check_spatial_location_data() to compensate for missing cell_ID - if(!'cell_ID' %in% colnames(slot(object, 'coordinates'))) { - msg = 'Column "cell_ID" for cell ID was not found' - errors = c(errors, msg) + if (!"cell_ID" %in% colnames(slot(object, "coordinates"))) { + msg <- 'Column "cell_ID" for cell ID was not found' + errors <- c(errors, msg) } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } @@ -881,9 +913,10 @@ check_spat_locs_obj = function(object) { #' @slot spat_unit spatial unit tag #' @slot provenance origin of aggregated information (if applicable) #' @export -setClass('spatLocsObj', - contains = c('nameData', 'coordDataDT', 'spatData', 'miscData'), - validity = check_spat_locs_obj) +setClass("spatLocsObj", + contains = c("nameData", "coordDataDT", "spatData", "miscData"), + validity = check_spat_locs_obj +) @@ -908,13 +941,13 @@ setClass('spatLocsObj', #' @description Check function for S4 spatialNetworkObj #' @param object S4 spatialNetworkObj to check #' @keywords internal -check_spat_net_obj = function(object) { - errors = character() - method_slot = slot(object, 'method') - length_method = length(method_slot) - if(length_method > 1) { - msg = paste0('method is length ', length_method, '. Should be 1') - errors = c(errors, msg) +check_spat_net_obj <- function(object) { + errors <- character() + method_slot <- slot(object, "method") + length_method <- length(method_slot) + if (length_method > 1) { + msg <- paste0("method is length ", length_method, ". Should be 1") + errors <- c(errors, msg) } # if(is.null(method_slot)) { @@ -922,12 +955,12 @@ check_spat_net_obj = function(object) { # errors = c(errors, msg) # } - if(is.null(object@networkDT) & is.null(object@networkDT_before_filter)) { - msg = 'No data in either networkDT or networkDT_before_filter slots.\nThis object contains no network information.\n' - errors = c(errors, msg) + if (is.null(object@networkDT) && is.null(object@networkDT_before_filter)) { + msg <- "No data in either networkDT or networkDT_before_filter slots.\nThis object contains no network information.\n" + errors <- c(errors, msg) } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } @@ -951,11 +984,12 @@ check_spat_net_obj = function(object) { #' @details The generic access operators work with the data within the \code{networkDT} #' slot (filtered). #' @export -setClass('spatialNetworkObj', - contains = c('nameData', 'spatNetData' ,'spatData', 'miscData'), - slots = c(crossSectionObjects = 'ANY'), - prototype = list(crossSectionObjects = NULL), - validity = check_spat_net_obj) +setClass("spatialNetworkObj", + contains = c("nameData", "spatNetData", "spatData", "miscData"), + slots = c(crossSectionObjects = "ANY"), + prototype = list(crossSectionObjects = NULL), + validity = check_spat_net_obj +) @@ -973,20 +1007,21 @@ setClass('spatialNetworkObj', #' @param object S3 spatNetworkObj #' @param spat_unit spatial unit metadata to append #' @keywords internal -S3toS4spatNetObj = function(object, - spat_unit = NULL) { - if(!isS4(object)) { - object = new('spatialNetworkObj', - name = object$name, - method = object$method, - parameters = object$parameters, - outputObj = object$outputObj, - networkDT = object$networkDT, - networkDT_before_filter = object$networkDT_before_filter, - cellShapeObj = object$cellShapeObj, - crossSectionObjects = object$crossSectionObjects, - spat_unit = spat_unit, - misc = object$misc) +S3toS4spatNetObj <- function(object, + spat_unit = NULL) { + if (!isS4(object)) { + object <- new("spatialNetworkObj", + name = object$name, + method = object$method, + parameters = object$parameters, + outputObj = object$outputObj, + networkDT = object$networkDT, + networkDT_before_filter = object$networkDT_before_filter, + cellShapeObj = object$cellShapeObj, + crossSectionObjects = object$crossSectionObjects, + spat_unit = spat_unit, + misc = object$misc + ) } object } @@ -1014,13 +1049,13 @@ S3toS4spatNetObj = function(object, #' @description Check function for S4 spatialGridObj #' @param object S4 spatialGridObj to check #' @keywords internal -check_spat_grid_obj = function(object) { - errors = character() - method_slot = slot(object, 'method') - length_method = length(method_slot) - if(length_method > 1) { - msg = paste0('method is length ', length_method, '. Should be 1') - errors = c(errors, msg) +check_spat_grid_obj <- function(object) { + errors <- character() + method_slot <- slot(object, "method") + length_method <- length(method_slot) + if (length_method > 1) { + msg <- paste0("method is length ", length_method, ". Should be 1") + errors <- c(errors, msg) } # if(is.null(method_slot)) { @@ -1028,12 +1063,12 @@ check_spat_grid_obj = function(object) { # errors = c(errors, msg) # } - if(is.null(object@gridDT)) { - msg = 'No data in gridDT slot.\nThis object contains no spatial grid information\n' - errors = c(errors, msg) + if (is.null(object@gridDT)) { + msg <- "No data in gridDT slot.\nThis object contains no spatial grid information\n" + errors <- c(errors, msg) } - if(length(errors) == 0) TRUE else errors + if (length(errors) == 0) TRUE else errors } @@ -1058,9 +1093,10 @@ check_spat_grid_obj = function(object) { #' of the grid and names for each of the spatial axis locations that make up the cell. #' Grids can be annotated with both spatial and feature information #' @export -setClass('spatialGridObj', - contains = c('nameData', 'spatGridData', 'spatFeatData', 'miscData'), - validity = check_spat_grid_obj) +setClass("spatialGridObj", + contains = c("nameData", "spatGridData", "spatFeatData", "miscData"), + validity = check_spat_grid_obj +) @@ -1078,14 +1114,15 @@ setClass('spatialGridObj', #' @description convert S3 spatialGridObj to S4 #' @param object S3 spatialGridObj #' @keywords internal -S3toS4spatialGridObj = function(object) { - if(!isS4(object)) { - object = new('spatialGridObj', - name = object$name, - method = object$method, - parameters = object$parameters, - gridDT = object$gridDT, - misc = object$misc) +S3toS4spatialGridObj <- function(object) { + if (!isS4(object)) { + object <- new("spatialGridObj", + name = object$name, + method = object$method, + parameters = object$parameters, + gridDT = object$gridDT, + misc = object$misc + ) } object } @@ -1107,8 +1144,9 @@ S3toS4spatialGridObj = function(object) { #' @slot provenance provenance information #' @slot misc misc #' @export -setClass('spatEnrObj', - contains = c('nameData', 'enrData', 'spatFeatData', 'miscData')) +setClass("spatEnrObj", + contains = c("nameData", "enrData", "spatFeatData", "miscData") +) @@ -1132,17 +1170,15 @@ setClass('spatEnrObj', #' @details holds polygon data #' #' @export -giottoPolygon = setClass( +giottoPolygon <- setClass( Class = "giottoPolygon", - contains = c('nameData'), - + contains = c("nameData"), slots = c( spatVector = "ANY", spatVectorCentroids = "ANY", overlaps = "ANY", - unique_ID_cache = 'character' + unique_ID_cache = "character" ), - prototype = list( spatVector = NULL, spatVectorCentroids = NULL, @@ -1158,14 +1194,14 @@ giottoPolygon = setClass( #' @name updateGiottoPolygonObject #' @param gpoly giotto polygon object #' @export -updateGiottoPolygonObject = function(gpoly) { - if(!inherits(gpoly, 'giottoPolygon')) { - stop('This function is only for giottoPoints') +updateGiottoPolygonObject <- function(gpoly) { + if (!inherits(gpoly, "giottoPolygon")) { + stop("This function is only for giottoPoints") } # 3.2.X adds cacheing of IDs - if(is.null(attr(gpoly, 'unique_ID_cache'))) { - attr(gpoly, 'unique_ID_cache') = unique(as.list(gpoly@spatVector)$poly_ID) + if (is.null(attr(gpoly, "unique_ID_cache"))) { + attr(gpoly, "unique_ID_cache") <- unique(as.list(gpoly@spatVector)$poly_ID) } gpoly @@ -1177,21 +1213,21 @@ updateGiottoPolygonObject = function(gpoly) { # for use with wrap() generic -setClass('packedGiottoPolygon', - contains = c('nameData'), - - slots = c( - packed_spatVector = 'ANY', - packed_spatVectorCentroids = 'ANY', - packed_overlaps = 'ANY', - unique_ID_cache = 'character' - ), - prototype = list( - packed_spatVector = NULL, - packed_spatVectorCentroids = NULL, - packed_overlaps = NULL, - unique_ID_cache = NA_character_ - )) +setClass("packedGiottoPolygon", + contains = c("nameData"), + slots = c( + packed_spatVector = "ANY", + packed_spatVectorCentroids = "ANY", + packed_overlaps = "ANY", + unique_ID_cache = "character" + ), + prototype = list( + packed_spatVector = NULL, + packed_spatVectorCentroids = NULL, + packed_overlaps = NULL, + unique_ID_cache = NA_character_ + ) +) @@ -1216,14 +1252,12 @@ setClass('packedGiottoPolygon', #' @export giottoPoints <- setClass( Class = "giottoPoints", - contains = c('featData'), - + contains = c("featData"), slots = c( spatVector = "ANY", networks = "ANY", - unique_ID_cache = 'character' + unique_ID_cache = "character" ), - prototype = list( spatVector = NULL, networks = NULL, @@ -1238,14 +1272,14 @@ giottoPoints <- setClass( #' @name updateGiottoPointsObject #' @param gpoints giotto points object #' @export -updateGiottoPointsObject = function(gpoints) { - if(!inherits(gpoints, 'giottoPoints')) { - stop('This function is only for giottoPoints') +updateGiottoPointsObject <- function(gpoints) { + if (!inherits(gpoints, "giottoPoints")) { + stop("This function is only for giottoPoints") } # 3.2.X adds cacheing of IDs - if(is.null(attr(gpoints, 'unique_ID_cache'))) { - attr(gpoints, 'unique_ID_cache') = unique(as.list(gpoints@spatVector)$feat_ID) + if (is.null(attr(gpoints, "unique_ID_cache"))) { + attr(gpoints, "unique_ID_cache") <- unique(as.list(gpoints@spatVector)$feat_ID) } gpoints @@ -1263,13 +1297,12 @@ updateGiottoPointsObject = function(gpoints) { # for use with wrap() generic setClass( - 'packedGiottoPoints', - + "packedGiottoPoints", slots = c( - feat_type = 'character', - packed_spatVector = 'ANY', - networks = 'ANY', - unique_ID_cache = 'character' + feat_type = "character", + packed_spatVector = "ANY", + networks = "ANY", + unique_ID_cache = "character" ), prototype = list( feat_type = NA_character_, @@ -1306,14 +1339,12 @@ setClass( #' @export featureNetwork <- setClass( Class = "featureNetwork", - contains = 'nameData', - + contains = "nameData", slots = c( network_datatable = "ANY", network_lookup_id = "ANY", full = "ANY" ), - prototype = list( network_datatable = NULL, network_lookup_id = NULL, @@ -1350,7 +1381,6 @@ featureNetwork <- setClass( #' @export giottoImage <- setClass( Class = "giottoImage", - slots = c( name = "ANY", mg_object = "ANY", @@ -1361,7 +1391,6 @@ giottoImage <- setClass( file_path = "ANY", OS_platform = "ANY" ), - prototype = list( name = NULL, mg_object = NULL, @@ -1402,7 +1431,6 @@ giottoImage <- setClass( #' @export giottoLargeImage <- setClass( Class = "giottoLargeImage", - slots = c( name = "ANY", raster_object = "ANY", @@ -1416,7 +1444,6 @@ giottoLargeImage <- setClass( file_path = "ANY", OS_platform = "ANY" ), - prototype = list( name = NULL, raster_object = NULL, @@ -1431,15 +1458,3 @@ giottoLargeImage <- setClass( OS_platform = NULL ) ) - - - - - - - - - - - - diff --git a/R/combine_metadata.R b/R/combine_metadata.R index 49e70d18..43a765f8 100644 --- a/R/combine_metadata.R +++ b/R/combine_metadata.R @@ -56,7 +56,8 @@ combineMetadata = function(gobject, cell_ID = NULL if(!is.null(spatial_locs)) { - metadata = cbind(metadata, spatial_locs[, cell_ID := NULL]) + # metadata = cbind(metadata, spatial_locs[, cell_ID := NULL]) + metadata = data.table::merge.data.table(metadata, spatial_locs, by = 'cell_ID') } @@ -88,11 +89,15 @@ combineMetadata = function(gobject, output = 'data.table', copy_obj = TRUE) - temp_spat[, 'cell_ID' := NULL] + # temp_spat[, 'cell_ID' := NULL] result_list[[spatenr]] = temp_spat } - final_meta = do.call('cbind', c(list(metadata), result_list)) + # final_meta = do.call('cbind', c(list(metadata), result_list)) + final_meta = Reduce( + function(x, y) data.table::merge.data.table(x, y, by = 'cell_ID'), + c(list(metadata), result_list) + ) duplicates = sum(duplicated(colnames(final_meta))) if(duplicates > 0) cat('Some column names are not unique. @@ -455,9 +460,6 @@ combineFeatureOverlapData = function(gobject, for(spat in unique(poly_info)) { - # feature meta - # feat_meta = gobject@feat_metadata[[feat]][[spat]] - feat_meta = get_feature_metadata(gobject = gobject, spat_unit = spat, feat_type = feat, @@ -481,11 +483,11 @@ combineFeatureOverlapData = function(gobject, feat_overlap_info = feat_overlap_info[feat_ID %in% selected_features] } - feat_overlap_info[, poly_info := poly] + feat_overlap_info[, 'poly_info' := poly] poly_list[[poly]] = feat_overlap_info } - poly_list_res = rbindlist(poly_list, fill = TRUE) + poly_list_res = data.table::rbindlist(poly_list, fill = TRUE) comb_dt = data.table::merge.data.table(x = feat_meta, y = poly_list_res, @@ -507,6 +509,153 @@ combineFeatureOverlapData = function(gobject, + + + +#' @title calculateSpatCellMetadataProportions +#' @name calculateSpatCellMetadataProportions +#' @description calculates a proportion table for a cell metadata column (e.g. cluster labels) +#' for all the spatial neighbors of a source cell. In other words it calculates the +#' niche composition for a given annotation for each cell. +#' @param gobject giotto object +#' @param spat_unit spatial unit +#' @param feat_type feature type +#' @param spat_network spatial network +#' @param metadata_column metadata column to use +#' @param name descriptive name for the calculated proportions +#' @param return_gobject return giotto object +#' @return giotto object (default) or enrichment object if return_gobject = FALSE +#' @export +calculateSpatCellMetadataProportions = function(gobject, + spat_unit = NULL, + feat_type = NULL, + spat_network = NULL, + metadata_column = NULL, + name = 'proportion', + return_gobject = TRUE){ + + # DT vars + proptable = target_clus = source_clus = network = target = NULL + + if(is.null(spat_network)) stop('spat_network = NULL, you need to provide an existing spatial network') + if(is.null(metadata_column)) stop('metadata_column = NULL, you need to provide an existing cell metadata column') + + # Set feat_type and spat_unit + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + feat_type = set_default_feat_type(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + + # get spatial network to use + sp_network = get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = spat_network, + output = 'networkDT') + + # convert spatial network to a full spatial network + sp_network = convert_to_full_spatial_network(reduced_spatial_network_DT = sp_network) + + # get cell metadata + cell_meta = get_cell_metadata(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + output = 'data.table') + + # merge spatial network and cell metadata + network_annot = data.table::merge.data.table(network, cell_meta[,c('cell_ID', metadata_column), with = FALSE], by.x = 'source', by.y = 'cell_ID') + setnames(network_annot, old = metadata_column, 'source_clus') + network_annot = data.table::merge.data.table(network_annot, cell_meta[,c('cell_ID', metadata_column), with = FALSE], by.x = 'target', by.y = 'cell_ID') + setnames(network_annot, old = metadata_column, 'target_clus') + + # create self information: source cell is its own neighbor + source_annot_info = unique(network_annot[,.(source, source_clus)]) + setnames(source_annot_info, 'source_clus', 'label') + source_annot_info[, target := source] + source_annot_info = source_annot_info[,.(source, target, label)] + + # network information: source cells and other neighbors + target_annot_info = unique(network_annot[,.(source, target, target_clus)]) + setnames(target_annot_info, 'target_clus', 'label') + + # combine: provides most detailed information about neighbors + final_annot_info = rbindlist(list(source_annot_info, target_annot_info)) + + + + # calculate proportions of neighbors + tableres = final_annot_info[, names(table(label)), by = 'source'] + setnames(tableres, 'V1', 'tablelabels') + propensities = final_annot_info[, prop.table(table(label)), by = 'source'] + setnames(propensities, 'V1', 'proptable') + + + # data.table variables + label = NULL + propensities[, 'label' := tableres$tablelabels] + propensities[, 'proptable' := as.numeric(proptable)] + proportions_mat = dcast.data.table(propensities, formula = 'source~label', fill = 0, value.var = 'proptable') + data.table::setnames(x = proportions_mat, old = 'source', new = 'cell_ID') + + # convert to matrix + # proportions_matrix = dt_to_matrix(proportions_mat) + # proportions_matrix[1:4, 1:10] + + # create spatial enrichment object + enrObj = create_spat_enr_obj(name = name, + method = 'rank', + enrichDT = proportions_mat, + spat_unit = spat_unit, + feat_type = feat_type, + provenance = NULL, + misc = NULL) + + + ## return object or results ## + if(return_gobject == TRUE) { + + spenr_names = list_spatial_enrichments_names(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + + + if(name %in% spenr_names) { + cat('\n ', name, ' has already been used, will be overwritten \n') + } + + ## update parameters used ## + parameters_list = gobject@parameters + number_of_rounds = length(parameters_list) + update_name = paste0(number_of_rounds,'_spatial_enrichment') + + + ## update parameters used ## + gobject = update_giotto_params(gobject, description = '_enrichment') + + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + gobject = set_spatial_enrichment(gobject = gobject, + spatenrichment = enrObj) + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + + return(gobject) + + } else { + + return(enrObj) + + } + + + +} + + + + + + + + # internals #### #' @title merge_spatial_locs_feat_info diff --git a/R/create.R b/R/create.R index bc2d66ad..7269b43b 100644 --- a/R/create.R +++ b/R/create.R @@ -37,6 +37,8 @@ NULL #' @param offset_file file used to stitch fields together (optional) #' @param instructions list of instructions or output result from \code{\link{createGiottoInstructions}} #' @param cores how many cores or threads to use to read data if paths are provided +#' @param expression_matrix_class class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray') +#' @param h5_file path to h5 file #' @param verbose be verbose when building Giotto object #' @return giotto object #' @details @@ -97,7 +99,7 @@ createGiottoObject = function(expression, instructions = NULL, cores = determine_cores(), raw_exprs = NULL, - expression_matrix_class = c('dgCMatrix', 'HDF5Matrix','rhdf5'), + expression_matrix_class = c('dgCMatrix', 'DelayedArray'), h5_file = NULL, verbose = FALSE) { @@ -193,8 +195,19 @@ createGiottoObject = function(expression, cores = cores, default_feat_type = expression_feat, verbose = debug_msg, - expression_matrix_class = expression_matrix_class, - h5_file = h5_file) + expression_matrix_class = expression_matrix_class) + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + ## evaluate if h5_file exists + if(!is.null(h5_file)) { + if(file.exists(h5_file)) { + wrap_msg("'", h5_file, "'", + " file already exists and will be replaced", sep = "") + file.remove(h5_file) + } else { + wrap_msg("Initializing file ", "'", h5_file, "'", sep = "") + } + } + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### gobject = setExpression(gobject = gobject, x = expression_data, @@ -1045,6 +1058,7 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, #' @param name name of exprObj #' @param provenance origin data of expression information (if applicable) #' @param misc misc +#' @param expression_matrix_class class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray') #' @export createExprObj = function(expression_data, name = 'test', @@ -1052,13 +1066,11 @@ createExprObj = function(expression_data, feat_type = 'rna', provenance = NULL, misc = NULL, - expression_matrix_class = c('dgCMatrix', 'HDF5Matrix', 'rhdf5'), - h5_file = NULL) { + expression_matrix_class = c('dgCMatrix', 'DelayedArray')) { exprMat = evaluate_expr_matrix(expression_data, expression_matrix_class = expression_matrix_class, - feat_type = feat_type, - h5_file = h5_file) + feat_type = feat_type) create_expr_obj(name = name, exprMat = exprMat, @@ -1706,7 +1718,7 @@ createGiottoPoints = function(x, spatVector = spatvec, unique_IDs = unique_IDs) - } else if(inherits(x, 'spatVector')) { + } else if(inherits(x, 'SpatVector')) { g_points = create_giotto_points_object(feat_type = feat_type, spatVector = x, diff --git a/R/data_evaluation.R b/R/data_evaluation.R index 55e066ad..5b8cad5f 100644 --- a/R/data_evaluation.R +++ b/R/data_evaluation.R @@ -37,16 +37,16 @@ evaluate_expr_matrix = function(inputmatrix, sparse = TRUE, cores = determine_cores(), feat_type = 'rna', - expression_matrix_class = c('dgCMatrix', 'HDF5Matrix', 'rhdf5'), - h5_file = NULL) { + expression_matrix_class = c('dgCMatrix', 'DelayedArray')) { if(inherits(inputmatrix, 'character')) { inputmatrix = path.expand(inputmatrix) mymatrix = readExprMatrix(inputmatrix, cores = cores, expression_matrix_class = expression_matrix_class, - feat_type = feat_type, - h5_file = h5_file) + feat_type = feat_type) + } else if(expression_matrix_class[1] == 'DelayedArray') { + mymatrix = DelayedArray::DelayedArray(inputmatrix) } else if(inherits(inputmatrix, 'Matrix')) { mymatrix = inputmatrix } else if(inherits(inputmatrix, 'DelayedMatrix')) { diff --git a/R/data_input.R b/R/data_input.R index ab06cb3e..b35d7873 100644 --- a/R/data_input.R +++ b/R/data_input.R @@ -12,6 +12,7 @@ #' @param path path to the expression matrix #' @param cores number of cores to use #' @param transpose transpose matrix +#' @param expression_matrix_class class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray') #' @inheritParams data_access_params #' @return sparse matrix #' @details The expression matrix needs to have both unique column names and row names @@ -20,8 +21,7 @@ readExprMatrix = function(path, cores = determine_cores(), transpose = FALSE, feat_type = 'rna', - expression_matrix_class = c('dgCMatrix', 'HDF5Matrix', 'rhdf5'), - h5_file = NULL) { + expression_matrix_class = c('dgCMatrix', 'DelayedArray')) { # check if path is a character vector and exists if(!is.character(path)) stop('path needs to be character vector') @@ -37,29 +37,8 @@ readExprMatrix = function(path, spM = t_flex(spM) } - if(expression_matrix_class[1] == 'HDF5Matrix') { - package_check('HDF5Array') - spM = methods::as(spM, 'HDF5Matrix') - } - - if(expression_matrix_class[1] == 'rhdf5') { - if(is.null(h5_file)) { - stop(wrap_txt('h5_file can not be NULL, please provide a file name', - errWidth = TRUE)) - } - - rhdf5::h5createGroup(h5_file, paste0('expression/',feat_type)) - - spM = as.matrix(DT[,-1]) - colnames(spM) = colnames(DT[,-1]) - rownames(spM) = DT[[1]] - - HDF5Array::writeHDF5Array(spM, - h5_file, - name = paste0('expression/',feat_type,'/raw'), - with.dimnames=TRUE) - - spM = paste0('expression/',feat_type,'/raw') + if(expression_matrix_class[1] == 'DelayedArray') { + spM = DelayedArray::DelayedArray(spM) } return(spM) @@ -82,6 +61,7 @@ readExprMatrix = function(path, #' @param data_list (nested) list of expression input data #' @param sparse (boolean, default = TRUE) read matrix data in a sparse manner #' @param cores number of cores to use +#' @param expression_matrix_class class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray') #' @inheritParams read_data_params #' @details #' @@ -106,8 +86,7 @@ readExprData = function(data_list, default_feat_type = NULL, verbose = TRUE, provenance = NULL, - expression_matrix_class = c('dgCMatrix', 'HDF5Matrix', 'rhdf5'), - h5_file = NULL) { + expression_matrix_class = c('dgCMatrix', 'DelayedArray')) { read_expression_data( expr_list = data_list, @@ -116,9 +95,7 @@ readExprData = function(data_list, default_feat_type = default_feat_type, verbose = verbose, provenance = provenance, - expression_matrix_class = expression_matrix_class, - h5_file = h5_file - ) + expression_matrix_class = expression_matrix_class) } @@ -132,8 +109,7 @@ read_expression_data = function(expr_list = NULL, default_feat_type = NULL, verbose = TRUE, provenance = NULL, - expression_matrix_class = c('dgCMatrix', 'HDF5Matrix', 'rhdf5'), - h5_file = NULL) { + expression_matrix_class = c('dgCMatrix', 'DelayedArray')) { # import box characters ch = box_chars() @@ -261,15 +237,6 @@ read_expression_data = function(expr_list = NULL, if(length(obj_list) > 0L) { - if(expression_matrix_class[1] == 'rhdf5') { - if(file.exists(h5_file)) { - wrap_txt("h5_file already exists, contents will be overwritten") - file.remove(h5_file)} - - rhdf5::h5createFile(h5_file) - rhdf5::h5createGroup(h5_file,"expression") - } - return_list = lapply(seq_along(obj_list), function(obj_i) { if(inherits(obj_list[[obj_i]], 'exprObj')) { @@ -301,8 +268,7 @@ read_expression_data = function(expr_list = NULL, feat_type = feat_type, provenance = if(is_empty_char(provenance)) spat_unit else provenance, # assumed misc = NULL, - expression_matrix_class = expression_matrix_class, - h5_file = h5_file + expression_matrix_class = expression_matrix_class ) ) } diff --git a/R/flex_functions.R b/R/flex_functions.R index fff68b23..0a5b90d7 100644 --- a/R/flex_functions.R +++ b/R/flex_functions.R @@ -146,7 +146,7 @@ colMeans_flex = function(mymatrix) { t_flex = function(mymatrix) { if(inherits(mymatrix, 'HDF5Matrix')) { - require(HDF5Array) + package_check('HDF5Array', repository = 'Bioc') return(methods::as(t(mymatrix), 'HDF5Matrix')) # } else if(inherits(mymatrix, 'DelayedMatrix')) { # return(t(mymatrix)) diff --git a/R/methods-show.R b/R/methods-show.R index b22b3066..eed081b2 100644 --- a/R/methods-show.R +++ b/R/methods-show.R @@ -123,7 +123,7 @@ setMethod( # packedGiotto #### setMethod("show", signature(object='packedGiotto'), function(object) { - print(paste("This is a", class(object), "object. Use 'Giotto::unwrap()' to unpack it")) + print(paste("This is a", class(object), "object. Use 'GiottoClass::vect()' to unpack it")) } ) @@ -507,7 +507,7 @@ setMethod('show', signature = 'giottoPolygon', function(object) { ## packedGiottoPolygon #### setMethod("show", signature(object='packedGiottoPolygon'), function(object) { - print(paste("This is a", class(object), "object. Use 'Giotto::unwrap()' to unpack it")) + print(paste("This is a", class(object), "object. Use 'GiottoClass::vect()' to unpack it")) } ) @@ -543,7 +543,7 @@ setMethod('show', signature = 'giottoPoints', function(object) { ## packedGiottoPoints #### setMethod("show", signature(object='packedGiottoPoints'), function(object) { - print(paste("This is a", class(object), "object. Use 'Giotto::unwrap()' to unpack it")) + print(paste("This is a", class(object), "object. Use 'GiottoClass::vect()' to unpack it")) } ) diff --git a/R/python_environment.R b/R/python_environment.R index de9ec27d..63b0445f 100644 --- a/R/python_environment.R +++ b/R/python_environment.R @@ -353,7 +353,9 @@ installGiottoEnvironment = function(packages_to_install = c('pandas==1.5.1', if (is.null(mini_install_path)){ conda_path = reticulate::miniconda_path() } else if (!dir.exists(mini_install_path)) { - stop(wrap_msg(paste0(" Unable to install miniconda in ", mini_install_path, "\nPlease ensure the directory has been created and provided as a string."))) + stop(wrap_msg(paste0(" Unable to install miniconda in ", + mini_install_path, + "\nPlease ensure the directory has been created and provided as a string."))) } else { conda_path = mini_install_path diff --git a/R/save_load.R b/R/save_load.R index 402078b1..a6a150c7 100644 --- a/R/save_load.R +++ b/R/save_load.R @@ -206,19 +206,33 @@ loadGiotto = function(path_to_folder, gobject_file = list.files(path_to_folder, pattern = 'gobject') - if(grepl('.RDS', x = gobject_file)) { - gobject = do.call('readRDS', c(file = paste0(path_to_folder,'/','gobject.RDS'), load_params)) - } + if(identical(gobject_file, character(0))) { + + if(verbose) wrap_msg('giotto object was not found, skip loading giotto object \n') + + } else if(length(gobject_file) > 1) { + + if(verbose) wrap_msg('more than 1 giotto object was found, skip loading giotto object \n') + + } else { + + if(grepl('.RDS', x = gobject_file)) { + gobject = do.call('readRDS', c(file = paste0(path_to_folder,'/','gobject.RDS'), load_params)) + } + + if(grepl('.qs', x = gobject_file)) { + package_check(pkg_name = 'qs', repository = 'CRAN') + qread_fun = get("qread", asNamespace("qs")) + gobject = do.call(qread_fun, c(file = paste0(path_to_folder,'/','gobject.qs'), load_params)) + } - if(grepl('.qs', x = gobject_file)) { - package_check(pkg_name = 'qs', repository = 'CRAN') - qread_fun = get("qread", asNamespace("qs")) - gobject = do.call(qread_fun, c(file = paste0(path_to_folder,'/','gobject.qs'), load_params)) } + + ## 2. read in features if(verbose) wrap_msg('2. read Giotto feature information \n') feat_files = list.files(path = paste0(path_to_folder, '/Features'), pattern = '.shp') @@ -244,6 +258,7 @@ loadGiotto = function(path_to_folder, } + ## 3. read in spatial polygons if(isTRUE(verbose)) wrap_msg('3. read Giotto spatial information \n') spat_paths = list.files(path = paste0(path_to_folder, '/SpatialInfo'), pattern = 'spatVector.shp', full.names = TRUE) @@ -274,49 +289,60 @@ loadGiotto = function(path_to_folder, } ## 3.2. centroids - centroid_search_term = gsub(spat_files, pattern = '_spatInfo_spatVector.shp', replacement = '_spatInfo_spatVectorCentroids.shp') + if(isTRUE(verbose)) { + wrap_msg('\n 3.2 read Giotto spatial centroid information \n') + } + centroid_search_term = gsub(spat_files, pattern = '_spatInfo_spatVector.shp', replacement = '_spatInfo_spatVectorCentroids.shp') centroid_paths = sapply(centroid_search_term, function(gp_centroid) { list.files(path = paste0(path_to_folder, '/SpatialInfo'), pattern = gp_centroid, full.names = TRUE) }, USE.NAMES = FALSE) - centroid_files = basename(centroid_paths) + # check if centroid are provided for spatvector polygons + test_missing = unlist(lapply(centroid_paths, FUN = function(x) identical(x, character(0)))) + centroid_paths = centroid_paths[!test_missing] - if(isTRUE(verbose)) { - wrap_msg('\n3.2 read Giotto spatial centroid information \n') - print(centroid_files) - } + if(length(centroid_paths) == 0) { + if(verbose) wrap_msg('No centroids were found, centroid loading will be skipped \n') + } else { + + centroid_files = basename(centroid_paths) - if(length(centroid_files != 0)) { - spat_names = gsub(centroid_files, pattern = '_spatInfo_spatVectorCentroids.shp', replacement = '') + if(length(centroid_files != 0)) { + spat_names = gsub(centroid_files, pattern = '_spatInfo_spatVectorCentroids.shp', replacement = '') - vector_names_paths = list.files(path = paste0(path_to_folder, '/SpatialInfo'), pattern = 'spatVectorCentroids_names.txt', full.names = TRUE) + vector_names_paths = list.files(path = paste0(path_to_folder, '/SpatialInfo'), pattern = 'spatVectorCentroids_names.txt', full.names = TRUE) - for(spat_i in 1:length(spat_names)) { - spatVector = terra::vect(x = centroid_paths[spat_i]) + for(spat_i in 1:length(spat_names)) { + spatVector = terra::vect(x = centroid_paths[spat_i]) - # read in original column names and assign to spatVector - spatVector_names = fread(input = vector_names_paths[spat_i], header = FALSE)[['V1']] - names(spatVector) = spatVector_names + # read in original column names and assign to spatVector + spatVector_names = fread(input = vector_names_paths[spat_i], header = FALSE)[['V1']] + names(spatVector) = spatVector_names - spat_name = spat_names[spat_i] - if(isTRUE(verbose)) message(spat_name) - gobject@spatial_info[[spat_name]]@spatVectorCentroids = spatVector + spat_name = spat_names[spat_i] + if(isTRUE(verbose)) message(spat_name) + gobject@spatial_info[[spat_name]]@spatVectorCentroids = spatVector + } } + } ## 3.3. overlaps - overlap_search_term = gsub(spat_files, pattern = '_spatInfo_spatVector.shp', replacement = '_spatInfo_spatVectorOverlaps.shp') - overlap_files = list.files(path = paste0(path_to_folder, '/SpatialInfo'), pattern = 'spatVectorOverlaps.shp') - if(isTRUE(verbose)) { wrap_msg('\n3.3 read Giotto spatial overlap information \n') - print(overlap_files) } - if(length(overlap_files != 0)) { + overlap_search_term = gsub(spat_files, pattern = '_spatInfo_spatVector.shp', replacement = '_spatInfo_spatVectorOverlaps.shp') + overlap_files = list.files(path = paste0(path_to_folder, '/SpatialInfo'), pattern = 'spatVectorOverlaps.shp') + # check if overlap information is available + if(length(overlap_files) == 0) { + if(verbose) wrap_msg('No overlaps were found, overlap loading will be skipped \n') + } else { + + print(overlap_files) # find overlaps per spatVector for(sv_i in seq_along(overlap_search_term)) { @@ -347,11 +373,11 @@ loadGiotto = function(path_to_folder, } } } - } + ## 4. images if(verbose) wrap_msg('\n4. read Giotto image information \n') image_files = list.files(path = paste0(path_to_folder, '/Images')) @@ -388,7 +414,6 @@ loadGiotto = function(path_to_folder, instructions(gobject) = instr } - ## 6. overallocate for data.tables # (data.tables when read from disk have a truelength of 0) gobject = giotto_alloc_dt_slots(gobject) diff --git a/R/slot_accessors.R b/R/slot_accessors.R index f180b38f..70d20682 100644 --- a/R/slot_accessors.R +++ b/R/slot_accessors.R @@ -284,8 +284,7 @@ set_cell_id = function(gobject, if(!is.null(slot(gobject, 'h5_file'))) { expr_dimnames = HDF5Array::h5readDimnames(filepath = slot(gobject, 'h5_file'), - name = paste0('expression/', - expr_avail$feat_type[[1L]],'/', + name = paste0(expr_avail$feat_type[[1L]],'_', expr_avail$name[[1L]])) cell_IDs = expr_dimnames[[2]] @@ -444,8 +443,7 @@ set_feat_id = function(gobject, if(!is.null(slot(gobject, 'h5_file'))) { expr_dimnames = HDF5Array::h5readDimnames(filepath = slot(gobject, 'h5_file'), - name = paste0('expression/', - feat_type,'/', + name = paste0(feat_type,'_', expr_avail$name[[1L]])) feat_IDs = expr_dimnames[[1]] @@ -1361,6 +1359,11 @@ getExpression = function(gobject, # **Controls expression slot nesting and structure** #' @name get_expression_values #' @title get_expression_values +#' @inheritParams data_access_params +#' @param values expression values to extract (e.g. "raw", "normalized", "scaled") +#' @param output what object type to retrieve the expression as. Currently either +#' 'matrix' for the matrix object contained in the exprObj or 'exprObj' (default) for +#' the exprObj itself are allowed. #' @export get_expression_values = function(gobject, spat_unit = NULL, @@ -1419,7 +1422,17 @@ get_expression_values = function(gobject, # Get info from slot nesting expr_vals = gobject@expression[[spat_unit]][[feat_type]][[values]] - + + # Read matrix from h5 file if needed + if(!is.null(slot(gobject, 'h5_file'))) { + matrix_path = expr_vals[] + expression_matrix = HDF5Array::HDF5Array(filepath = slot(gobject, 'h5_file'), + name = matrix_path, + as.sparse = TRUE) + slot(expr_vals,'exprMat') = expression_matrix + } + + # Output if(output == 'exprObj') return(expr_vals) else if(output == 'matrix') return(expr_vals[]) @@ -1667,7 +1680,18 @@ set_expression_values = function(gobject, 'Setting expression [', spatUnit(values), '][', featType(values), '] ', objName(values), sep = '' ) - + + ## 7. Write matrix to h5_file if needed + if(!is.null(slot(gobject, 'h5_file'))) { + expression_matrix = slot(values, 'exprMat') + expression_matrix = HDF5Array::writeHDF5Array(x = expression_matrix, + filepath = slot(gobject, 'h5_file'), + name = paste0(feat_type,"_",name), + with.dimnames = TRUE) + slot(values, 'exprMat') = paste0(feat_type,"_",name) + } + + # Output gobject@expression[[spat_unit]][[feat_type]][[name]] = values if(isTRUE(initialize)) return(initialize(gobject)) else return(gobject) diff --git a/R/spatial_structures.R b/R/spatial_structures.R index 81b727fb..91a7a38a 100644 --- a/R/spatial_structures.R +++ b/R/spatial_structures.R @@ -140,6 +140,31 @@ calculate_distance_and_weight <- function(networkDT = NULL, return(networkDT) } + + + +#' @title get_distance +#' @name get_distance +#' @description estimate average distance between neighboring cells with network table as input +#' @param networkDT networkDT +#' @param method method +#' @keywords internal +get_distance <- function(networkDT, + method=c("mean","median") +){ + + if (method=="median"){ + distance = stats::median(networkDT$distance) + }else if(method=="mean"){ + distance = mean(networkDT$distance) + } + return(distance) +} + + + + + #' @title filter_network #' @name filter_network #' @description function to filter a spatial network @@ -178,7 +203,10 @@ filter_network <- function(networkDT = NULL, #' @name compatible_spatial_network #' @description Function to evaluate if a spatial network is compatible #' with a provided expression matrix +#' @param spatial_network spatial network to evaluate +#' @param expression_matrix expression to compare against #' @keywords internal +#' @export compatible_spatial_network = function(spatial_network, expression_matrix) { diff --git a/man/calculateSpatCellMetadataProportions.Rd b/man/calculateSpatCellMetadataProportions.Rd new file mode 100644 index 00000000..a5bd7d39 --- /dev/null +++ b/man/calculateSpatCellMetadataProportions.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/combine_metadata.R +\name{calculateSpatCellMetadataProportions} +\alias{calculateSpatCellMetadataProportions} +\title{calculateSpatCellMetadataProportions} +\usage{ +calculateSpatCellMetadataProportions( + gobject, + spat_unit = NULL, + feat_type = NULL, + spat_network = NULL, + metadata_column = NULL, + name = "proportion", + return_gobject = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit} + +\item{feat_type}{feature type} + +\item{spat_network}{spatial network} + +\item{metadata_column}{metadata column to use} + +\item{name}{descriptive name for the calculated proportions} + +\item{return_gobject}{return giotto object} +} +\value{ +giotto object (default) or enrichment object if return_gobject = FALSE +} +\description{ +calculates a proportion table for a cell metadata column (e.g. cluster labels) +for all the spatial neighbors of a source cell. In other words it calculates the +niche composition for a given annotation for each cell. +} diff --git a/man/compatible_spatial_network.Rd b/man/compatible_spatial_network.Rd index 2a0dcf42..a3f620bc 100644 --- a/man/compatible_spatial_network.Rd +++ b/man/compatible_spatial_network.Rd @@ -6,6 +6,11 @@ \usage{ compatible_spatial_network(spatial_network, expression_matrix) } +\arguments{ +\item{spatial_network}{spatial network to evaluate} + +\item{expression_matrix}{expression to compare against} +} \description{ Function to evaluate if a spatial network is compatible with a provided expression matrix diff --git a/man/createExprObj.Rd b/man/createExprObj.Rd index 3341fc2e..4e1ac5ef 100644 --- a/man/createExprObj.Rd +++ b/man/createExprObj.Rd @@ -11,8 +11,7 @@ createExprObj( feat_type = "rna", provenance = NULL, misc = NULL, - expression_matrix_class = c("dgCMatrix", "HDF5Matrix", "rhdf5"), - h5_file = NULL + expression_matrix_class = c("dgCMatrix", "DelayedArray") ) } \arguments{ @@ -27,6 +26,8 @@ createExprObj( \item{provenance}{origin data of expression information (if applicable)} \item{misc}{misc} + +\item{expression_matrix_class}{class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray')} } \description{ Create an S4 exprObj diff --git a/man/createGiottoObject.Rd b/man/createGiottoObject.Rd index 848d3192..774ae4e3 100644 --- a/man/createGiottoObject.Rd +++ b/man/createGiottoObject.Rd @@ -26,7 +26,7 @@ createGiottoObject( instructions = NULL, cores = determine_cores(), raw_exprs = NULL, - expression_matrix_class = c("dgCMatrix", "HDF5Matrix", "rhdf5"), + expression_matrix_class = c("dgCMatrix", "DelayedArray"), h5_file = NULL, verbose = FALSE ) @@ -77,6 +77,10 @@ see \code{\link{createGiottoPoints}}} \item{raw_exprs}{deprecated, use expression} +\item{expression_matrix_class}{class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray')} + +\item{h5_file}{path to h5 file} + \item{verbose}{be verbose when building Giotto object} } \value{ diff --git a/man/get_distance.Rd b/man/get_distance.Rd new file mode 100644 index 00000000..bb432137 --- /dev/null +++ b/man/get_distance.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_structures.R +\name{get_distance} +\alias{get_distance} +\title{get_distance} +\usage{ +get_distance(networkDT, method = c("mean", "median")) +} +\arguments{ +\item{networkDT}{networkDT} + +\item{method}{method} +} +\description{ +estimate average distance between neighboring cells with network table as input +} +\keyword{internal} diff --git a/man/get_expression_values.Rd b/man/get_expression_values.Rd index 0f476662..aee9ea44 100644 --- a/man/get_expression_values.Rd +++ b/man/get_expression_values.Rd @@ -13,6 +13,22 @@ get_expression_values( set_defaults = TRUE ) } +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{values}{expression values to extract (e.g. "raw", "normalized", "scaled")} + +\item{output}{what object type to retrieve the expression as. Currently either +'matrix' for the matrix object contained in the exprObj or 'exprObj' (default) for +the exprObj itself are allowed.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when +expression and spat_info are not expected to exist.} +} \description{ get_expression_values } diff --git a/man/giotto-class.Rd b/man/giotto-class.Rd index 926c19a1..0488a7ee 100644 --- a/man/giotto-class.Rd +++ b/man/giotto-class.Rd @@ -60,6 +60,8 @@ that are provided in the expression slot. \item{\code{join_info}}{information about joined Giotto objects} \item{\code{multiomics}}{multiomics integration results} + +\item{\code{h5_file}}{path to h5 file} }} \concept{giotto object} diff --git a/man/readExprData.Rd b/man/readExprData.Rd index 225e1f32..b0608b95 100644 --- a/man/readExprData.Rd +++ b/man/readExprData.Rd @@ -11,8 +11,7 @@ readExprData( default_feat_type = NULL, verbose = TRUE, provenance = NULL, - expression_matrix_class = c("dgCMatrix", "HDF5Matrix", "rhdf5"), - h5_file = NULL + expression_matrix_class = c("dgCMatrix", "DelayedArray") ) } \arguments{ @@ -27,6 +26,8 @@ readExprData( \item{verbose}{be verbose} \item{provenance}{(optional) provenance information} + +\item{expression_matrix_class}{class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray')} } \description{ Read a nested list of expression data inputs in order to diff --git a/man/readExprMatrix.Rd b/man/readExprMatrix.Rd index 797b2eae..de8e0170 100644 --- a/man/readExprMatrix.Rd +++ b/man/readExprMatrix.Rd @@ -9,8 +9,7 @@ readExprMatrix( cores = determine_cores(), transpose = FALSE, feat_type = "rna", - expression_matrix_class = c("dgCMatrix", "HDF5Matrix", "rhdf5"), - h5_file = NULL + expression_matrix_class = c("dgCMatrix", "DelayedArray") ) } \arguments{ @@ -21,6 +20,8 @@ readExprMatrix( \item{transpose}{transpose matrix} \item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{expression_matrix_class}{class of expression matrix to use (e.g. 'dgCMatrix', 'DelayedArray')} } \value{ sparse matrix diff --git a/man/updateGiottoObject.Rd b/man/updateGiottoObject.Rd index b31eebbd..42e61510 100644 --- a/man/updateGiottoObject.Rd +++ b/man/updateGiottoObject.Rd @@ -22,6 +22,6 @@ Supported updates: } \examples{ \dontrun{ -gobject = updateGiottoObject(gobject) +gobject <- updateGiottoObject(gobject) } } diff --git a/tests/testthat.R b/tests/testthat.R index e04fd1a8..990afbe2 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -3,27 +3,10 @@ # # Where should you do additional test configuration? # Learn more about the roles of various files in: -# * https://r-pkgs.org/tests.html -# * https://testthat.r-lib.org/reference/test_package.html#special-files +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html library(testthat) library(GiottoClass) -# additional needed packages -suppressWarnings({ - if(!require(remotes)){ - install.packages('R.utils', repos = 'http://cran.us.r-project.org') - install.packages('remotes', repos = 'http://cran.us.r-project.org') - } - - if(!require(GiottoData)){ - remotes::install_github('drieslab/GiottoData', build = FALSE) - } -}) - -# install giotto environment -if (!checkGiottoEnvironment()) { - installGiottoEnvironment() -} - test_check("GiottoClass") diff --git a/tests/testthat/test-GiottoInstructions.R b/tests/testthat/test-GiottoInstructions.R new file mode 100644 index 00000000..d276f952 --- /dev/null +++ b/tests/testthat/test-GiottoInstructions.R @@ -0,0 +1,74 @@ +### TESTS FUNCTIONS FOR CREATING/CHANGING GIOTTO INSTRUCTIONS +# -------------------------------------------------------------- # + +# CREATE GIOTTO OBJECT FOR TESTING + +# no need for python env in these tests +options('giotto.use_conda' = FALSE) +# silence deprecated internals +rlang::local_options(lifecycle_verbosity = "quiet") + +suppressWarnings({ + instrs = createGiottoInstructions( + show_plot = TRUE, + return_plot = NULL, + save_plot = FALSE, + save_dir = NULL, + plot_format = "png", + dpi = 300, + units = NULL, + height = NULL, + width = NULL, + is_docker = FALSE, + plot_count = 0, + fiji_path = NULL) +}) + + +expression_matrix = matrix(1:100, nrow = 10) +colnames(expression_matrix) = paste0("cell",1:10) +colnames(expression_matrix) = paste0("feature",1:10) + +gobject = createGiottoObject(expression = expression_matrix, + instructions = instrs, + verbose = FALSE) + +# createGiottoInstructions +test_that("Instructions are created", { + expect_type(instrs, "list") +}) + +# readGiottoInstructions +test_that("readGiottoInstructions reads a few giotto object params correctly", { + + expect_type(readGiottoInstructions(gobject, param = "show_plot"), "logical") + expect_type(readGiottoInstructions(gobject, param = "plot_format"), "character") + expect_type(readGiottoInstructions(gobject, param = "dpi"), "double") +}) + +# showGiottoInstructions +test_that("showGiottoInstructions returns expected list", { + expect_type(showGiottoInstructions(gobject), "list") +}) + +# changeGiottoInstructions +gobject = changeGiottoInstructions( + gobject, + params = c("show_plot", "save_plot"), + new_values = c(FALSE, TRUE), + return_gobject = TRUE +) + +test_that("changeGiottoInstructions changes instruction params in object", { + expect_false(readGiottoInstructions(gobject, param = "show_plot")) + expect_true(readGiottoInstructions(gobject, param = "save_plot")) +}) + +# replaceGiottoInstructions +gobject = replaceGiottoInstructions(gobject, instrs) + +test_that("replaceGiottoInstructions returns object instructions to original", { + expect_true(readGiottoInstructions(gobject, param = "show_plot")) + expect_false(readGiottoInstructions(gobject, param = "save_plot")) +}) + diff --git a/tests/testthat/test_accessors.R b/tests/testthat/test-slot_accessors.R similarity index 53% rename from tests/testthat/test_accessors.R rename to tests/testthat/test-slot_accessors.R index 05196bcf..248c3c02 100644 --- a/tests/testthat/test_accessors.R +++ b/tests/testthat/test-slot_accessors.R @@ -1,52 +1,371 @@ -require(testthat) - -# Load subobjects -ex = GiottoData::loadSubObjectMini('exprObj') -sl = GiottoData::loadSubObjectMini('spatLocsObj') -cm = GiottoData::loadSubObjectMini('cellMetaObj') -fm = GiottoData::loadSubObjectMini('featMetaObj') -sn = GiottoData::loadSubObjectMini('spatialNetworkObj') -enr = GiottoData::loadSubObjectMini('spatEnrObj') -dr = GiottoData::loadSubObjectMini('dimObj') -nn = GiottoData::loadSubObjectMini('nnNetObj') -gpoly = GiottoData::loadSubObjectMini('giottoPolygon') -gpoints = GiottoData::loadSubObjectMini('giottoPoints') +# silence deprecated internal functions +rlang::local_options(lifecycle_verbosity = "quiet") +# Gobject can be generated without conda env, but will send warning +options('giotto.use_conda' = FALSE) # create test object -test = giotto() +suppressWarnings({ + giotto_object = giotto() +}) -ex1 = ex2 = ex -objName(ex1) = 'data1' -featType(ex1) = 'protein' -objName(ex2) = 'data2' -featType(ex2) = 'feat3' -spatUnit(ex2) = 'nucleus' - - - # GETTERS #### ## missing cases #### test_that('Not found exprObj returns error', { - expect_error( - getExpression(test, spat_unit = 'none', feat_type = 'none', values = 'raw') - ) + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getExpression(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found CellMetadata returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getCellMetadata(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found DimReduction returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getDimReduction(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found FeatureInfo returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getFeatureInfo(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found FeatureMetadata returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getFeatureMetadata(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found GiottoImage returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getGiottoImage(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found Multiomics returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getMultiomics(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found NearestNetwork returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getNearestNetwork(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found PolygonInfo returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getPolygonInfo(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found SpatialEnrichment returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getSpatialEnrichment(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found SpatialGrid returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getSpatialGrid(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found SpatialLocations returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getSpatialLocations(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +test_that('Not found SpatialNetwork returns error', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_error( + getSpatialNetwork(giotto_object, spat_unit = 'none', + feat_type = 'none', values = 'raw') + ) +}) + +## expect information #### + +### download pre-processed Giotto object +giotto_object = GiottoData::loadGiottoMini('vizgen') + +test_that('Finds exprObj', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getExpression(giotto_object), 'exprObj') +}) + +test_that('Finds CellMetadata', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getCellMetadata(giotto_object), 'cellMetaObj') +}) + +test_that('Finds DimReduction', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getDimReduction(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna'), + 'dimObj') +}) + +test_that('Finds FeatureInfo', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getFeatureInfo(giotto_object), 'SpatVector') +}) + +test_that('Finds FeatureMetadata', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getFeatureMetadata(giotto_object), 'featMetaObj') +}) + +test_that('Finds NearestNetwork', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getNearestNetwork(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna'), + 'nnNetObj') +}) + +test_that('Finds PolygonInfo', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getPolygonInfo(giotto_object), 'SpatVector') }) +test_that('Finds SpatialEnrichment', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getSpatialEnrichment(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna', + name = 'cluster_metagene'), + 'spatEnrObj') +}) + +test_that('Finds SpatialLocations', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getSpatialLocations(giotto_object), 'spatLocsObj') +}) +test_that('Finds SpatialNetwork', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getSpatialNetwork(giotto_object, + spat_unit = 'aggregate'), + 'spatialNetworkObj') +}) # SETTERS #### -## ------------------------------------------------------------------------ ## + +### create empty test object +suppressWarnings({ + giotto_empty = giotto() +}) + + +x = getExpression(giotto_object, + spat_unit = 'z0', + feat_type = 'rna') +giotto_empty = setExpression(giotto_empty, + spat_unit = 'z0', + feat_type = 'rna', + x = x) + +x = getExpression(giotto_object, + spat_unit = 'z1', + feat_type = 'rna') +giotto_empty = setExpression(giotto_empty, + spat_unit = 'z1', + feat_type = 'rna', + x = x) + +x = getExpression(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna') +giotto_empty = setExpression(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna', + x = x) + +test_that('Sets exprObj', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getExpression(giotto_empty), 'exprObj') +}) + +x = getCellMetadata(giotto_object) +giotto_empty = setCellMetadata(giotto_empty, + x = x) + +test_that('Sets CellMetadata', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getCellMetadata(giotto_empty), 'cellMetaObj') +}) + +x = getDimReduction(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna') +giotto_empty = setDimReduction(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna', + x = x) + +test_that('Sets DimReduction', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getDimReduction(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna'), + 'dimObj') +}) + +x = getFeatureInfo(giotto_object) +giotto_empty = setFeatureInfo(giotto_empty, + x = createGiottoPoints(x)) + +test_that('Sets FeatureInfo', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getFeatureInfo(giotto_empty), 'SpatVector') +}) + +x = getFeatureMetadata(giotto_object) +giotto_empty = setFeatureMetadata(giotto_empty, + x = x) + +test_that('Sets FeatureMetadata', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getFeatureMetadata(giotto_empty), 'featMetaObj') +}) + +x = getNearestNetwork(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna') +giotto_empty = setNearestNetwork(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna', + x = x) + +test_that('Sets NearestNetwork', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getNearestNetwork(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna'), + 'nnNetObj') +}) + +x = getPolygonInfo(giotto_object) +x_polygon = GiottoClass:::create_giotto_polygon_object(name = 'z0', + spatVector = x) +giotto_empty = setPolygonInfo(giotto_empty, + x = x_polygon, + name = 'z0') + +test_that('Sets PolygonInfo', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getPolygonInfo(giotto_empty), 'SpatVector') +}) + +x = getSpatialLocations(giotto_object) +giotto_empty = setSpatialLocations(giotto_empty, + x = x) + +x = getSpatialLocations(giotto_object, + spat_unit = 'aggregate') +giotto_empty = setSpatialLocations(giotto_empty, + spat_unit = 'aggregate', + x = x) + +test_that('Sets SpatialLocations', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getSpatialLocations(giotto_empty), 'spatLocsObj') +}) + +x = getSpatialEnrichment(giotto_object, + spat_unit = 'aggregate', + feat_type = 'rna', + name = 'cluster_metagene') +giotto_empty = setSpatialEnrichment(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna', + name = 'cluster_metagene', + x = x) + +test_that('Sets SpatialEnrichment', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getSpatialEnrichment(giotto_empty, + spat_unit = 'aggregate', + feat_type = 'rna', + name = 'cluster_metagene'), + 'spatEnrObj') +}) + +x = getSpatialNetwork(giotto_object, + spat_unit = 'aggregate') +giotto_empty = setSpatialNetwork(giotto_empty, + spat_unit = 'aggregate', + x = x) + +test_that('Sets SpatialNetwork', { + rlang::local_options(lifecycle_verbosity = "quiet") + expect_class(getSpatialNetwork(giotto_empty, + spat_unit = 'aggregate'), + 'spatialNetworkObj') +}) + + #### setting: expression #### + +suppressWarnings( + test <- giotto() +) + +# Load subobjects +ex = GiottoData::loadSubObjectMini('exprObj') +sl = GiottoData::loadSubObjectMini('spatLocsObj') +cm = GiottoData::loadSubObjectMini('cellMetaObj') +fm = GiottoData::loadSubObjectMini('featMetaObj') +sn = GiottoData::loadSubObjectMini('spatialNetworkObj') +enr = GiottoData::loadSubObjectMini('spatEnrObj') +dr = GiottoData::loadSubObjectMini('dimObj') +nn = GiottoData::loadSubObjectMini('nnNetObj') +gpoly = GiottoData::loadSubObjectMini('giottoPolygon') +gpoints = GiottoData::loadSubObjectMini('giottoPoints') + + ex1 = ex2 = ex objName(ex1) = 'data1' featType(ex1) = 'protein' @@ -56,7 +375,7 @@ spatUnit(ex2) = 'nucleus' test_that('Single: exprObj can be set', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setExpression(test, ex) avail_ex = list_expression(test_ex) @@ -69,7 +388,7 @@ test_that('Single: exprObj can be set', { }) test_that('List: exprObj can be set', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setExpression(test, list(ex, ex1, ex2)) avail_ex = list_expression(test_ex) @@ -82,6 +401,7 @@ test_that('List: exprObj can be set', { }) test_that('Non-native throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = expect_error(setExpression(test, ex[]), regexp = 'Only exprObj') }) @@ -110,7 +430,7 @@ spatUnit(sl2) = 'nucleus' test_that('Single: spatLocsObj can be set', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) avail_ex = list_spatial_locations(test_ex) @@ -122,6 +442,7 @@ test_that('Single: spatLocsObj can be set', { }) test_that('List: spatLocsObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") # setup test_ex = setExpression(test_ex, ex2) @@ -137,6 +458,7 @@ test_that('List: spatLocsObj can be set', { }) test_that('Non-native throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") expect_error(setSpatialLocations(test_ex, sl[]), regexp = 'Only spatLocsObj') }) @@ -153,6 +475,7 @@ spatUnit(sl2) = 'nucleus' spatUnit(sn2) = 'nucleus' test_that('Spatial network requires matching spatial locations', { + rlang::local_options(lifecycle_verbosity = "quiet") expect_error(setSpatialNetwork(test_ex, sn2), regexp = 'Add spatial location') # none test_ex = setSpatialLocations(test_ex, sl) expect_error(setSpatialNetwork(test_ex, sn2), regexp = 'Matching') # no match (nucleus vs aggregate) @@ -163,6 +486,7 @@ test_that('Spatial network requires matching spatial locations', { }) test_that('Single: spatialNetworkObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) test_ex = setSpatialNetwork(test_ex, sn) @@ -175,6 +499,7 @@ test_that('Single: spatialNetworkObj can be set', { }) test_that('List: spatialNetworkObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") # setup test_ex = setSpatialLocations(test_ex, sl) test_ex = setExpression(test_ex, ex2) @@ -192,6 +517,7 @@ test_that('List: spatialNetworkObj can be set', { }) test_that('Non-native throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) expect_error(setSpatialNetwork(test_ex, sn[]), regexp = 'Only spatialNetworkObj') }) @@ -209,6 +535,7 @@ spatUnit(sl2) = 'nucleus' spatUnit(enr2) = 'nucleus' test_that('Spatial enrichment requires matching spatial locations', { + rlang::local_options(lifecycle_verbosity = "quiet") expect_error(setSpatialEnrichment(test_ex, enr2), regexp = 'Add spatial location') # none test_ex = setSpatialLocations(test_ex, sl) expect_error(setSpatialEnrichment(test_ex, enr2), regexp = 'Matching') # no match (nucleus vs aggregate) @@ -219,6 +546,7 @@ test_that('Spatial enrichment requires matching spatial locations', { }) test_that('Single: spatEnrObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) test_ex = setSpatialEnrichment(test_ex, enr) @@ -231,6 +559,7 @@ test_that('Single: spatEnrObj can be set', { }) test_that('List: spatEnrObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") # setup test_ex = setSpatialLocations(test_ex, sl) test_ex = setExpression(test_ex, ex2) @@ -248,6 +577,7 @@ test_that('List: spatEnrObj can be set', { }) test_that('Non-native throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) expect_error(setSpatialEnrichment(test_ex, enr[]), regexp = 'Only spatEnrObj') }) @@ -265,6 +595,7 @@ spatUnit(dr2) = 'nucleus' featType(dr2) = 'test_feat' test_that('Dim red requires matching expression', { + rlang::local_options(lifecycle_verbosity = "quiet") expect_error(setDimReduction(test, dr2), regexp = 'Add expression') # none expect_error(setDimReduction(test_ex, dr2), regexp = 'Matching') # no match (nucleus vs aggregate) @@ -275,6 +606,7 @@ test_that('Dim red requires matching expression', { }) test_that('Single: dimObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) test_ex = setDimReduction(test_ex, dr) @@ -287,6 +619,7 @@ test_that('Single: dimObj can be set', { }) test_that('List: dimObj can be set', { + rlang::local_options(lifecycle_verbosity = "quiet") # setup featType(ex2) = 'test_feat' test_ex = setExpression(test_ex, ex2) @@ -308,6 +641,7 @@ test_that('List: dimObj can be set', { }) test_that('Non-native throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) expect_error(setDimReduction(test_ex, dr[]), regexp = 'Only dimObj') }) @@ -326,6 +660,7 @@ spatUnit(nn2) = 'nucleus' featType(nn2) = 'test_feat' test_that('Nearest neighbors requires matching dimreduction', { + rlang::local_options(lifecycle_verbosity = "quiet") expect_error(setNearestNetwork(test, nn2), regexp = 'Add dimension reduction') # none test_ex = setDimReduction(test_ex, dr) # no match (nucleus vs aggregate) @@ -373,6 +708,7 @@ test_that('Nearest neighbors requires matching dimreduction', { # }) test_that('Non-native throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setSpatialLocations(test_ex, sl) expect_error(setDimReduction(test_ex, nn[]), regexp = 'Only dimObj') }) @@ -392,7 +728,7 @@ test_that('Non-native throws error', { test_that('Native feature info is set directly', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_fi = expect_no_error(setFeatureInfo(test, gpoints)) avail_fi = list_feature_info(test_fi) @@ -403,7 +739,7 @@ test_that('Native feature info is set directly', { test_that('Native feature info is set with lists', { # issues currently happen with unnamed lists - + rlang::local_options(lifecycle_verbosity = "quiet") # assign names by list names - this now happens through read fxns only # test_fi = setFeatureInfo(test, x = list(rna = gpoints, # protein = gpoints2)) @@ -429,7 +765,7 @@ test_that('Native feature info is set with lists', { # issues currently happen w ## ------------------------------------------------------------------------ ## test_that('Native spatial info is set directly', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_si = expect_no_error(setPolygonInfo(test, gpoly)) avail_si = list_spatial_info(test_si) @@ -439,7 +775,7 @@ test_that('Native spatial info is set directly', { }) test_that('Spatlocs is also set if centroids are available', { - + rlang::local_options(lifecycle_verbosity = "quiet") # spat_unit (polygon_name) not explicitly set test_si = setPolygonInfo(test, gpoly, centroids_to_spatlocs = TRUE) @@ -474,7 +810,7 @@ test_that('Spatlocs is also set if centroids are available', { test_that('Spatlocs setting requires expression', { - + rlang::local_options(lifecycle_verbosity = "quiet") expect_error(setSpatialLocations(test, sl), regexp = 'Add expression') @@ -485,7 +821,7 @@ test_that('Spatlocs setting requires expression', { # set expression first test_sl = setExpression(test, ex) test_that('Native spatlocs is set', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_sl = suppressWarnings(setSpatialLocations(test_sl, sl)) avail_sl = list_spatial_locations(test_sl) @@ -497,7 +833,7 @@ test_that('Native spatlocs is set', { test_that('Native spatLocsObj is set with user specified nesting', { - + rlang::local_options(lifecycle_verbosity = "quiet") # add needed spat_unit in expression first test_sl = setExpression(test_sl, ex, spat_unit = 'new') @@ -517,6 +853,7 @@ test_that('Native spatLocsObj is set with user specified nesting', { test_that('Spatlocs missing spat_unit in expr and spatial_info throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") # available spat unit in expression is only 'aggregate' test_sl = expect_error(setSpatialLocations(test_sl, sl, spat_unit = 'new'), regexp = 'No expression') @@ -524,10 +861,10 @@ test_that('Spatlocs missing spat_unit in expr and spatial_info throws error', { test_that('Spatlocs spatID mismatch throws error', { + rlang::local_options(lifecycle_verbosity = "quiet") test_sl = setPolygonInfo(test_sl, gpoly, name = 'new') - # in spat_unit 'new', spatIDs have more entries (poly info) than the spatlocs - # which are based on the later aggregated expression information - expect_error(setSpatialLocations(test_sl, sl, spat_unit = 'new'), + # due to subset, expected that sl will have fewer IDs + expect_error(setSpatialLocations(test_sl, sl[1:6], spat_unit = 'new'), regexp = 'between spatial and') }) @@ -539,7 +876,7 @@ test_that('Spatlocs spatID mismatch throws error', { test_that('Native spatLocsObj can be removed', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_sl = setSpatialLocations(test_sl, sl) test_sl = setSpatialLocations(test_sl, diff --git a/tests/testthat/test_createObject.R b/tests/testthat/test_createObject.R index ca2164ef..acafd306 100644 --- a/tests/testthat/test_createObject.R +++ b/tests/testthat/test_createObject.R @@ -14,6 +14,10 @@ gpoly = GiottoData::loadSubObjectMini('giottoPolygon') gpoints = GiottoData::loadSubObjectMini('giottoPoints') +# Ignore internal usage of deprecated accessors +lifecycle_opt = getOption('lifecycle_verbosity') +options('lifecycle_verbosity' = 'quiet') + # TEST SUBOBJECT CREATION #### ## ------------------------------------------------------------------------ ## @@ -60,6 +64,7 @@ dgC = ex[] ex_IDs = spatIDs(ex) test_that('exprObj is created from array', { + rlang::local_options(lifecycle_verbosity = "quiet") exprObj = create_expr_obj(exprMat = a) expect_no_error(validObject(exprObj)) expect_s4_class(exprObj, 'exprObj') @@ -67,6 +72,7 @@ test_that('exprObj is created from array', { }) test_that('exprObj is created from matrix', { + rlang::local_options(lifecycle_verbosity = "quiet") exprObj = create_expr_obj(exprMat = m) expect_no_error(validObject(exprObj)) expect_s4_class(exprObj, 'exprObj') @@ -74,6 +80,7 @@ test_that('exprObj is created from matrix', { }) test_that('exprObj is created from dgCMatrix', { + rlang::local_options(lifecycle_verbosity = "quiet") exprObj = create_expr_obj(exprMat = dgC) expect_no_error(validObject(exprObj)) expect_s4_class(exprObj, 'exprObj') @@ -188,6 +195,7 @@ test_that('Read returns nnNetObj list directly', { test_that('Depth 1 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readNearestNetData(list(ig, ig)) expect_true(all(sapply(read_list, featType) == 'rna')) expect_true(all(sapply(read_list, spatUnit) == 'cell')) @@ -197,6 +205,7 @@ test_that('Depth 1 works', { test_that('Depth 2 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readNearestNetData(list(test_feat = list(ig,ig), list(test = ig))) expect_identical(sapply(read_list, featType), c('test_feat', 'test_feat', 'feat_2')) @@ -206,6 +215,7 @@ test_that('Depth 2 works', { }) test_that('Depth 3 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readNearestNetData(list(test_unit = list(test_feat = list(a = ig, ig), list(ig)), list(list(b = ig)))) @@ -216,6 +226,7 @@ test_that('Depth 3 works', { }) test_that('Depth 4 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readNearestNetData(list(test_unit = list(test_feat = list(list(a = ig), test_meth2 = list(x = ig)), list(test_meth = list(ig))), @@ -252,6 +263,7 @@ test_that('Read returns dimObj list directly', { test_that('Depth 1 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readDimReducData(list(drm, drm)) expect_true(all(sapply(read_list, featType) == 'rna')) expect_true(all(sapply(read_list, spatUnit) == 'cell')) @@ -261,6 +273,7 @@ test_that('Depth 1 works', { test_that('Depth 2 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readDimReducData(list(test_feat = list(drm,drm), list(test = drm))) expect_identical(sapply(read_list, featType), c('test_feat', 'test_feat', 'feat_2')) @@ -270,6 +283,7 @@ test_that('Depth 2 works', { }) test_that('Depth 3 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readDimReducData(list(test_unit = list(test_feat = list(a = drm, drm), list(drm)), list(list(b = drm)))) @@ -280,6 +294,7 @@ test_that('Depth 3 works', { }) test_that('Depth 4 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readDimReducData(list(test_unit = list(test_feat = list(list(a = drm), test_meth2 = list(x = drm)), list(test_meth = list(drm))), @@ -309,6 +324,7 @@ test_that('Read returns spatEnrObj list directly', { test_that('Depth 1 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatEnrichData(list(enrDT, enrDT)) expect_true(all(sapply(read_list, featType) == 'rna')) expect_true(all(sapply(read_list, spatUnit) == 'cell')) @@ -318,6 +334,7 @@ test_that('Depth 1 works', { test_that('Depth 2 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatEnrichData(list(test_feat = list(enrDT,enrDT), list(test = enrDT))) expect_identical(sapply(read_list, featType), c('test_feat', 'test_feat', 'feat_2')) @@ -327,6 +344,7 @@ test_that('Depth 2 works', { }) test_that('Depth 3 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatEnrichData(list(test_unit = list(test_feat = list(a = enrDT, enrDT), list(enrDT)), list(list(b = enrDT)))) @@ -338,6 +356,7 @@ test_that('Depth 3 works', { test_that('Depth 4 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatEnrichData(list(test_unit = list(test_feat = list(list(a = enrDT), test_meth2 = list(x = enrDT)), list(test_meth = list(enrDT))), @@ -369,6 +388,7 @@ test_that('Read returns spatialNetworkObj list directly', { test_that('Depth 1 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatNetData(list(snDT, snDT)) expect_true(all(sapply(read_list, spatUnit) == 'cell')) expect_identical(sapply(read_list, objName), c('sn_1', 'sn_2')) @@ -377,6 +397,7 @@ test_that('Depth 1 works', { test_that('Depth 2 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatNetData(list(test_unit = list(snDT,snDT), list(test = snDT))) expect_identical(sapply(read_list, spatUnit), c('test_unit', 'test_unit', 'unit_2')) @@ -401,6 +422,7 @@ test_that('Read returns spatLocsObj list directly', { }) test_that('Depth 1 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatLocsData(list(slDT, slDT)) expect_true(all(sapply(read_list, spatUnit) == 'cell')) expect_identical(sapply(read_list, objName), c('coord_1', 'coord_2')) @@ -408,6 +430,7 @@ test_that('Depth 1 works', { test_that('Depth 2 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readSpatLocsData(list(test_unit = list(slDT,slDT), list(test = slDT))) expect_identical(sapply(read_list, spatUnit), c('test_unit', 'test_unit', 'unit_2')) @@ -441,6 +464,7 @@ test_that('Read returns dimObj list directly', { test_that('Depth 1 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readExprData(list(exMat, exMat)) expect_true(all(sapply(read_list, featType) == 'rna')) expect_true(all(sapply(read_list, spatUnit) == 'cell')) @@ -449,6 +473,7 @@ test_that('Depth 1 works', { test_that('Depth 2 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readExprData(list(test_feat = list(exMat,exMat), list(test = exMat))) expect_identical(sapply(read_list, featType), c('test_feat', 'test_feat', 'feat_2')) @@ -457,6 +482,7 @@ test_that('Depth 2 works', { }) test_that('Depth 3 works', { + rlang::local_options(lifecycle_verbosity = "quiet") read_list = readExprData(list(test_unit = list(test_feat = list(a = exMat, exMat), list(exMat)), list(list(b = exMat)))) @@ -485,4 +511,4 @@ test_that('Depth 3 works', { - +options('lifecycle_verbosity' = lifecycle_opt) diff --git a/tests/testthat/test_giottoInstr.R b/tests/testthat/test_giottoInstr.R deleted file mode 100644 index abf4c910..00000000 --- a/tests/testthat/test_giottoInstr.R +++ /dev/null @@ -1,95 +0,0 @@ -# python_path = NULL -# if(is.null(python_path)) { -# installGiottoEnvironment() -# } - -require(testthat) - -### TESTS FUNCTIONS FOR CREATING/CHANGING GIOTTO INSTRUCTIONS -# -------------------------------------------------------------- # - -instrs = createGiottoInstructions( - #python_path = NULL, - show_plot = TRUE, - return_plot = NULL, - save_plot = FALSE, - save_dir = NULL, - plot_format = "png", - dpi = 300, - units = NULL, - height = NULL, - width = NULL, - is_docker = FALSE, - plot_count = 0, - fiji_path = NULL -) - -test_that("Instructions are created", { - # createGiottoInstructions - - expect_type(instrs, "list") -}) - - -GiottoData::getSpatialDataset(dataset = "merfish_preoptic", directory = paste0(getwd(), "/testdata/")) - -expr_path = "./testdata/merFISH_3D_data_expression.txt.gz" -loc_path = "./testdata/merFISH_3D_data_cell_locations.txt" -meta_path = "./testdata/merFISH_3D_metadata.txt" - -# CREATE GIOTTO OBJECT FOR TESTING -object <- createGiottoObject(expression = expr_path, - spatial_locs = loc_path, - instructions = instrs, - verbose = FALSE) - -# readGiottoInstructions -test_that("readGiottoInstructions reads a few giotto object params correctly", { - - expect_type(readGiottoInstructions(object, param = "show_plot"), "logical") - expect_type(readGiottoInstructions(object, param = "plot_format"), "character") - expect_type(readGiottoInstructions(object, param = "dpi"), "double") -}) - -# showGiottoInstructions -test_that("showGiottoInstructions returns expected list", { - expect_type(showGiottoInstructions(object), "list") -}) - - -# changeGiottoInstructions -object = changeGiottoInstructions( - object, - params = c("show_plot", "save_plot"), - new_values = c(FALSE, TRUE), - return_gobject = TRUE -) - -test_that("changeGiottoInstructions changes instruction params in object", { - expect_false(readGiottoInstructions(object, param = "show_plot")) - expect_true(readGiottoInstructions(object, param = "save_plot")) -}) - - -# replaceGiottoInstructions -object = replaceGiottoInstructions(object, instrs) - -test_that("replaceGiottoInstructions returns object instructions to original", { - expect_true(readGiottoInstructions(object, param = "show_plot")) - expect_false(readGiottoInstructions(object, param = "save_plot")) -}) - - -# --------------------------------------------- # -# remove downloaded datasets after tests run -if (file.exists("./testdata/merFISH_3D_data_expression.txt.gz")) { - unlink("./testdata/merFISH_3D_data_expression.txt.gz") -} - -if (file.exists("./testdata/merFISH_3D_data_cell_locations.txt")) { - unlink("./testdata/merFISH_3D_data_cell_locations.txt") -} - -if (file.exists("./testdata/merFISH_3D_metadata.txt")) { - unlink("./testdata/merFISH_3D_metadata.txt") -} diff --git a/tests/testthat/test_gobject.R b/tests/testthat/test_gobject.R index f1092675..f85bf012 100644 --- a/tests/testthat/test_gobject.R +++ b/tests/testthat/test_gobject.R @@ -16,12 +16,20 @@ gpoints = GiottoData::loadSubObjectMini('giottoPoints') +# Ignore internal usage of deprecated accessors +lifecycle_opt = getOption('lifecycle_verbosity') +options('lifecycle_verbosity' = 'quiet') + ### TESTS FOR GOBJECT FUNCTIONALITY #### ## ------------------------------------------------------------------------ ## -test = giotto() +options('giotto.use_conda' = FALSE) +# Gobject can be generated without conda env, but will send warning +suppressWarnings({ + test = giotto() +}) test_that('Gobject can be generated', { expect_s4_class(test, 'giotto') @@ -69,7 +77,7 @@ test_that('Providing feat_type returns unmodified', { #### Aggregate Initialization #### test_that('Expression initiates ID slots', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setExpression(test, ex) expect_identical(spatIDs(test_ex), spatIDs(ex)) @@ -84,7 +92,7 @@ test_that('Expression initiates ID slots', { test_that('Expression initiates metadata slots', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setExpression(test, ex) expect_identical(spatIDs(test_ex), pDataDT(test_ex)$cell_ID) @@ -99,6 +107,7 @@ test_that('Expression initiates metadata slots', { test_that('Expression sets active spat_unit and feat_type', { + rlang::local_options(lifecycle_verbosity = "quiet") test_ex = setExpression(test, ex) # check in instructions settings @@ -112,7 +121,7 @@ test_that('Expression sets active spat_unit and feat_type', { test_that('expression_feats slot is set by expression', { - + rlang::local_options(lifecycle_verbosity = "quiet") # test single test_ex = setExpression(test, ex, feat_type = 'test_feat') expect_identical(test_ex@expression_feat, 'test_feat') @@ -128,7 +137,7 @@ test_that('expression_feats slot is set by expression', { test_that('Spatial info initiates spat_ID slot', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_si = setPolygonInfo(test, gpoly) expect_identical(spatIDs(test_si), spatIDs(gpoly)) @@ -139,7 +148,7 @@ test_that('Spatial info initiates spat_ID slot', { }) test_that('Spatial info sets active spat_unit', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_si = setPolygonInfo(test, gpoly) expect_identical(activeSpatUnit(test_si), 'aggregate') @@ -149,7 +158,7 @@ test_that('Spatial info sets active spat_unit', { test_that('Feature info initiates feat_ID slot', { - + rlang::local_options(lifecycle_verbosity = "quiet") featType(gpoints) = 'test_feat' test_fi = setFeatureInfo(test, gpoints) @@ -160,7 +169,7 @@ test_that('Feature info initiates feat_ID slot', { test_that('Spat and Feat info initiates cell_metadata slot', { - + rlang::local_options(lifecycle_verbosity = "quiet") test_sf = setFeatureInfo(test, gpoints) expect_null(list_cell_metadata(test_sf)) @@ -175,7 +184,7 @@ test_that('Spat and Feat info initiates cell_metadata slot', { test_that('expression_feats slot is set by feature_info', { - + rlang::local_options(lifecycle_verbosity = "quiet") # test single test_fi = setFeatureInfo(test, gpoints, feat_type = 'test_feat') expect_identical(test_fi@expression_feat, 'test_feat') @@ -190,7 +199,7 @@ test_that('expression_feats slot is set by feature_info', { #### ID interaction interactions #### test_that('cell_ID from spatial_info is overwritten by expression', { - + rlang::local_options(lifecycle_verbosity = "quiet") expected_IDs = spatIDs(ex) test_int = setPolygonInfo(test, gpoly) @@ -203,7 +212,7 @@ test_that('cell_ID from spatial_info is overwritten by expression', { test_that('feat_ID from feat_info is overwritten by expression', { - + rlang::local_options(lifecycle_verbosity = "quiet") expected_IDs = featIDs(ex) test_int = setFeatureInfo(test, gpoints) @@ -238,5 +247,5 @@ test_that('feat_ID from feat_info is overwritten by expression', { - +options('lifecycle_verbosity' = lifecycle_opt)