Repository: enblacar/SCpubr
Branch: main
Commit: a3ae2999ce50
Files: 175
Total size: 1.8 MB
Directory structure:
gitextract_myymkbek/
├── .Rbuildignore
├── .github/
│ ├── .gitignore
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.md
│ │ └── feature-request.md
│ └── workflows/
│ ├── R-CMD-check.yaml
│ └── test-coverage.yaml
├── .gitignore
├── CRAN-SUBMISSION
├── DESCRIPTION
├── LICENSE.md
├── NAMESPACE
├── NEWS.md
├── R/
│ ├── data.R
│ ├── do_ActivityHeatmap.R
│ ├── do_AlluvialPlot.R
│ ├── do_BarPlot.R
│ ├── do_BeeSwarmPlot.R
│ ├── do_BoxPlot.R
│ ├── do_CNVHeatmap.R
│ ├── do_CellularStatesPlot.R
│ ├── do_ChordDiagramPlot.R
│ ├── do_ColorBlindCheck.R
│ ├── do_ColorPalette.R
│ ├── do_CorrelationHeatmap.R
│ ├── do_DimPlot.R
│ ├── do_DotPlot.R
│ ├── do_EnrichmentHeatmap.R
│ ├── do_ExpressionHeatmap.R
│ ├── do_FeaturePlot.R
│ ├── do_GroupwiseDEHeatmap.R
│ ├── do_LigandReceptorPlot.R
│ ├── do_LoadingsHeatmap.R
│ ├── do_MetadataHeatmap.R
│ ├── do_NebulosaPlot.R
│ ├── do_PathwayActivityHeatmap.R
│ ├── do_RankedEnrichmentHeatmap.R
│ ├── do_RankedExpressionHeatmap.R
│ ├── do_RidgePlot.R
│ ├── do_SCEnrichmentHeatmap.R
│ ├── do_SCExpressionHeatmap.R
│ ├── do_StripPlot.R
│ ├── do_TFActivityHeatmap.R
│ ├── do_TermEnrichmentPlot.R
│ ├── do_ViolinPlot.R
│ ├── do_VolcanoPlot.R
│ ├── do_WafflePlot.R
│ ├── globals.R
│ ├── plot_density_patch.R
│ ├── utils.R
│ └── zzz.R
├── README.md
├── cran-comments.md
├── data/
│ └── human_chr_locations.rda
├── inst/
│ ├── CITATION
│ └── extdata/
│ ├── de_genes_example.rds
│ ├── dorothea_activities_example.rds
│ ├── enriched_terms_example.rds
│ ├── genes_example.rds
│ ├── infercnv_object_example.rds
│ ├── infercnv_object_metacells_example.rds
│ ├── liana_output_example.rds
│ ├── metacell_mapping_example.rds
│ ├── progeny_activities_example.rds
│ └── seurat_dataset_example.rds
├── man/
│ ├── do_ActivityHeatmap.Rd
│ ├── do_AlluvialPlot.Rd
│ ├── do_BarPlot.Rd
│ ├── do_BeeSwarmPlot.Rd
│ ├── do_BoxPlot.Rd
│ ├── do_CNVHeatmap.Rd
│ ├── do_CellularStatesPlot.Rd
│ ├── do_ChordDiagramPlot.Rd
│ ├── do_ColorBlindCheck.Rd
│ ├── do_ColorPalette.Rd
│ ├── do_CorrelationHeatmap.Rd
│ ├── do_DimPlot.Rd
│ ├── do_DotPlot.Rd
│ ├── do_EnrichmentHeatmap.Rd
│ ├── do_ExpressionHeatmap.Rd
│ ├── do_FeaturePlot.Rd
│ ├── do_GroupwiseDEHeatmap.Rd
│ ├── do_LigandReceptorPlot.Rd
│ ├── do_LoadingsHeatmap.Rd
│ ├── do_MetadataHeatmap.Rd
│ ├── do_NebulosaPlot.Rd
│ ├── do_PackageReport.Rd
│ ├── do_PathwayActivityHeatmap.Rd
│ ├── do_RankedEnrichmentHeatmap.Rd
│ ├── do_RankedExpressionHeatmap.Rd
│ ├── do_RidgePlot.Rd
│ ├── do_SCEnrichmentHeatmap.Rd
│ ├── do_SCExpressionHeatmap.Rd
│ ├── do_StripPlot.Rd
│ ├── do_TFActivityHeatmap.Rd
│ ├── do_TermEnrichmentPlot.Rd
│ ├── do_ViolinPlot.Rd
│ ├── do_VolcanoPlot.Rd
│ ├── do_WafflePlot.Rd
│ ├── doc_function.Rd
│ ├── examples/
│ │ ├── examples_do_ActivityHeatmap.R
│ │ ├── examples_do_AlluvialPlot.R
│ │ ├── examples_do_BarPlot.R
│ │ ├── examples_do_BeeSwarmPlot.R
│ │ ├── examples_do_BoxPlot.R
│ │ ├── examples_do_CNVHeatmap.R
│ │ ├── examples_do_CellularStatesPlot.R
│ │ ├── examples_do_ChordDiagramPlot.R
│ │ ├── examples_do_ColorBlindCheck.R
│ │ ├── examples_do_ColorPalette.R
│ │ ├── examples_do_CorrelationHeatmap.R
│ │ ├── examples_do_DimPlot.R
│ │ ├── examples_do_DotPlot.R
│ │ ├── examples_do_EnrichmentHeatmap.R
│ │ ├── examples_do_ExpressionHeatmap.R
│ │ ├── examples_do_FeaturePlot.R
│ │ ├── examples_do_GroupwiseDEHeatmap.R
│ │ ├── examples_do_LigandReceptorPlot.R
│ │ ├── examples_do_LoadingsHeatmap.R
│ │ ├── examples_do_MetadataHeatmap.R
│ │ ├── examples_do_NebulosaPlot.R
│ │ ├── examples_do_PathwayActivityHeatmap.R
│ │ ├── examples_do_RankedEnrichmentHeatmap.R
│ │ ├── examples_do_RankedExpressionHeatmap.R
│ │ ├── examples_do_RidgePlot.R
│ │ ├── examples_do_SCEnrichmentHeatmap.R
│ │ ├── examples_do_SCExpressionHeatmap.R
│ │ ├── examples_do_StripPlot.R
│ │ ├── examples_do_TFActivityHeatmap.R
│ │ ├── examples_do_TermEnrichmentPlot.R
│ │ ├── examples_do_ViolinPlot.R
│ │ ├── examples_do_VolcanoPlot.R
│ │ └── examples_do_WafflePlot.R
│ ├── human_chr_locations.Rd
│ ├── named_list.Rd
│ └── named_vector.Rd
├── revdep/
│ ├── .gitignore
│ └── email.yml
├── tests/
│ ├── testthat/
│ │ ├── setup.R
│ │ ├── test-do_ActivityHeatmap.R
│ │ ├── test-do_AlluvialPlot.R
│ │ ├── test-do_BarPlot.R
│ │ ├── test-do_BeeSwarmPlot.R
│ │ ├── test-do_BoxPlot.R
│ │ ├── test-do_CNVHeatmap.R
│ │ ├── test-do_CellularStatesPlot.R
│ │ ├── test-do_ChordDiagramPlot.R
│ │ ├── test-do_ColorBlindCheck.R
│ │ ├── test-do_ColorPalette.R
│ │ ├── test-do_CorrelationHeatmap.R
│ │ ├── test-do_DimPlot.R
│ │ ├── test-do_DotPlot.R
│ │ ├── test-do_EnrichmentHeatmap.R
│ │ ├── test-do_ExpressionHeatmap.R
│ │ ├── test-do_FeaturePlot.R
│ │ ├── test-do_GroupwiseDEHeatmap.R
│ │ ├── test-do_LigandReceptorPlot.R
│ │ ├── test-do_LoadingsHeatmap.R
│ │ ├── test-do_MetadataHeatmap.R
│ │ ├── test-do_NebulosaPlot.R
│ │ ├── test-do_PathwayActivityHeatmap.R
│ │ ├── test-do_RankedEnrichmentHeatmap.R
│ │ ├── test-do_RankedExpressionHeatmap.R
│ │ ├── test-do_RidgePlot.R
│ │ ├── test-do_SCEnrichmentHeatmap.R
│ │ ├── test-do_SCExpressionHeatmap.R
│ │ ├── test-do_StripPlot.R
│ │ ├── test-do_TFActivityHeatmap.R
│ │ ├── test-do_TermEnrichmentPlot.R
│ │ ├── test-do_ViolinPlot.R
│ │ ├── test-do_VolcanoPlot.R
│ │ ├── test-do_WafflePlot.R
│ │ └── test-utils.R
│ └── testthat.R
└── vignettes/
├── .gitignore
└── reference_manual.Rmd
================================================
FILE CONTENTS
================================================
================================================
FILE: .Rbuildignore
================================================
^.*\.Rproj$
^\.Rproj\.user$
^LICENSE\.md$
^.mailmap$
^\.github$
^doc$
^Meta$
^codecov\.yml$
^.*\.Rproj$
^\.Rproj\.user$
^NEWS$
^cran-comments\.md$
^revdep$
^README\.Rmd$
^data-raw$
^pkgdown$
^_pkgdown\.yml$
^man/figures$
^man/figures/*
^tests/testthat/output_figure.svg$
^tests/testthat/test.jpeg$
^tests/testthat/test.pdf$
^tests/testthat/test.png$
^tests/testthat/test.svg$
^tests/testthat/test.tiff$
^CRAN-SUBMISSION$
================================================
FILE: .github/.gitignore
================================================
*.html
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: "\U0001F41B | Bug report"
about: 'Found a bug?! '
title: BUG | FUNCTION NAME | BRIEF DESCRIPTION
labels: bug
assignees: enblacar
---
**Bug:**
```
# Your description of the bug goes here.
```
**Reproducible example:**
```r
# Your reproducible example goes here.
# How to make a good one: https://www.r-bloggers.com/2020/10/how-to-make-a-reprex/
```
**Error log:**
```r
# Paste the full error log here
```
**SCpubr version:**
```r
# Put the version of SCpubr that you are using here.
# Can be checked by: utils::packageVersion("SCpubr")
```
**Session info:**
```r
# Include the output of sessionInfo() here.
```
================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: "\U0001F4AD | Feature request"
about: Do you have a cool idea you wish to be added to SCpubr?
title: REQUEST | FUNCTION NAME | DESCRIPTION
labels: enhancement
assignees: enblacar
---
**Feature request:**
```
# Your description of the feature goes here.
```
**Example:**
```r
# Add an example image of how would you want the output to look like.
# Can be a screenshot from another source, a sketch concept, etc.
```
**Implementation:**
```r
# Do you have any ideas/leads on how to implement your suggestion?
# If not, just remove this part entirely.
```
**SCpubr version:**
```r
# Put the version of SCpubr that you are using here.
# Can be checked by: utils::packageVersion("SCpubr")
```
================================================
FILE: .github/workflows/R-CMD-check.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
name: R-CMD-check.yaml
permissions: read-all
jobs:
R-CMD-check:
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
strategy:
fail-fast: false
matrix:
config:
- {os: macos-latest, r: 'release'}
- {os: windows-latest, r: 'release'}
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-pandoc@v2
- 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
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::rcmdcheck
needs: check
- uses: r-lib/actions/check-r-package@v2
with:
upload-snapshots: true
build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
================================================
FILE: .github/workflows/test-coverage.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
name: test-coverage.yaml
permissions: read-all
jobs:
test-coverage:
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::covr, any::xml2
needs: coverage
- name: Test coverage
run: |
cov <- covr::package_coverage(
quiet = FALSE,
clean = FALSE,
install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
)
print(cov)
covr::to_cobertura(cov)
shell: Rscript {0}
- uses: codecov/codecov-action@v5
with:
# Fail if error if not on PR, or if on PR and token is given
fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
files: ./cobertura.xml
plugins: noop
disable_search: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Show testthat output
if: always()
run: |
## --------------------------------------------------------------------
find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
shell: bash
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: coverage-test-failures
path: ${{ runner.temp }}/package
================================================
FILE: .gitignore
================================================
.Rproj.user
.Rhistory
.RData
.Ruserdata
inst/doc
SCpubr.Rproj
/doc/
/Meta/
.renviron
.rprofile
.rproj
.rproj.user
.rhistory
.rapp.history
.o
.sl
.so
.dylib
.a
.dll
.def
.ds_store
unsrturl.bst
.log
.aux
.backups
.cproject
.directory
.dropbox
.exrc
.gdb.history
.gitattributes
.gitmodules
.hgtags
.project
.seed
.settings
.tm_properties
omnipathr-log/*
tests/testthat/omnipathr-log
tests/testthat/omnipathr-log/*
tests/testthat/_snaps/
tests/testthat/output_figure*
tests/testthat/test.*
output_figure*
test.*
================================================
FILE: CRAN-SUBMISSION
================================================
Version: 3.0.1
Date: 2026-01-09 14:31:18 UTC
SHA: 06d205ffb706dae9d0889dbd0bd0503f944a28d4
================================================
FILE: DESCRIPTION
================================================
Type: Package
Package: SCpubr
Title: Generate Publication Ready Visualizations of Single Cell
Transcriptomics Data
Version: 3.0.1
Authors@R:
person("Enrique", "Blanco-Carmona", , "scpubr@gmail.com", role = c("cre", "aut"),
comment = c(ORCID = "0000-0002-1208-1691"))
Description: A system that provides a streamlined way of generating
publication ready plots for known Single-Cell transcriptomics data in
a “publication ready” format. This is, the goal is to automatically
generate plots with the highest quality possible, that can be used
right away or with minimal modifications for a research article.
License: GPL-3
URL: https://github.com/enblacar/SCpubr/,
https://enblacar.github.io/SCpubr-book/
BugReports: https://github.com/enblacar/SCpubr/issues/
Depends:
R (>= 4.0.0)
Suggests:
assertthat,
circlize,
cli,
cluster,
colorspace,
ComplexHeatmap,
covr,
decoupleR,
dplyr (>= 1.1.0),
enrichplot,
forcats,
ggalluvial (>= 0.12.5),
ggbeeswarm,
ggdist,
ggExtra,
ggh4x,
ggplot2 (>= 3.4.0),
ggplotify,
ggrastr,
ggrepel,
ggridges,
ggsignif,
graphics,
infercnv,
KernSmooth,
knitr,
labeling,
magrittr,
MASS,
Matrix,
methods,
Nebulosa,
org.Hs.eg.db,
patchwork,
pheatmap,
plyr,
purrr,
qpdf,
RColorBrewer,
rjags,
rlang,
rmarkdown,
scales,
scattermore,
Seurat,
SeuratObject,
sf,
stringr,
svglite,
testthat (>= 3.0.0),
tibble,
tidyr,
UCell,
viridis,
withr
VignetteBuilder:
knitr
biocViews: Software, SingleCell, Visualization
Config/testthat/edition: 3
Encoding: UTF-8
LazyData: true
LazyDataCompression: xz
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.3
================================================
FILE: LICENSE.md
================================================
GNU General Public License
==========================
_Version 3, 29 June 2007_
_Copyright © 2007 Free Software Foundation, Inc. <>_
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
## Preamble
The GNU General Public License is a free, copyleft license for software and other
kinds of works.
The licenses for most software and other practical works are designed to take away
your freedom to share and change the works. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change all versions of a
program--to make sure it remains free software for all its users. We, the Free
Software Foundation, use the GNU General Public License for most of our software; it
applies also to any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute
copies of free software (and charge for them if you wish), that you receive source
code or can get it if you want it, that you can change the software or use pieces of
it in new free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or
asking you to surrender the rights. Therefore, you have certain responsibilities if
you distribute copies of the software, or if you modify it: responsibilities to
respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee,
you must pass on to the recipients the same freedoms that you received. You must make
sure that they, too, receive or can get the source code. And you must show them these
terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: **(1)** assert
copyright on the software, and **(2)** offer you this License giving you legal permission
to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains that there is
no warranty for this free software. For both users' and authors' sake, the GPL
requires that modified versions be marked as changed, so that their problems will not
be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of
the software inside them, although the manufacturer can do so. This is fundamentally
incompatible with the aim of protecting users' freedom to change the software. The
systematic pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we have designed
this version of the GPL to prohibit the practice for those products. If such problems
arise substantially in other domains, we stand ready to extend this provision to
those domains in future versions of the GPL, as needed to protect the freedom of
users.
Finally, every program is threatened constantly by software patents. States should
not allow patents to restrict development and use of software on general-purpose
computers, but in those that do, we wish to avoid the special danger that patents
applied to a free program could make it effectively proprietary. To prevent this, the
GPL assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
## TERMS AND CONDITIONS
### 0. Definitions
“This License” refers to version 3 of the GNU General Public License.
“Copyright” also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this
License. Each licensee is addressed as “you”. “Licensees” and
“recipients” may be individuals or organizations.
To “modify” a work means to copy from or adapt all or part of the work in
a fashion requiring copyright permission, other than the making of an exact copy. The
resulting work is called a “modified version” of the earlier work or a
work “based on” the earlier work.
A “covered work” means either the unmodified Program or a work based on
the Program.
To “propagate” a work means to do anything with it that, without
permission, would make you directly or secondarily liable for infringement under
applicable copyright law, except executing it on a computer or modifying a private
copy. Propagation includes copying, distribution (with or without modification),
making available to the public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through a computer
network, with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices” to the
extent that it includes a convenient and prominently visible feature that **(1)**
displays an appropriate copyright notice, and **(2)** tells the user that there is no
warranty for the work (except to the extent that warranties are provided), that
licensees may convey the work under this License, and how to view a copy of this
License. If the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
### 1. Source Code
The “source code” for a work means the preferred form of the work for
making modifications to it. “Object code” means any non-source form of a
work.
A “Standard Interface” means an interface that either is an official
standard defined by a recognized standards body, or, in the case of interfaces
specified for a particular programming language, one that is widely used among
developers working in that language.
The “System Libraries” of an executable work include anything, other than
the work as a whole, that **(a)** is included in the normal form of packaging a Major
Component, but which is not part of that Major Component, and **(b)** serves only to
enable use of the work with that Major Component, or to implement a Standard
Interface for which an implementation is available to the public in source code form.
A “Major Component”, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system (if any) on which
the executable work runs, or a compiler used to produce the work, or an object code
interpreter used to run it.
The “Corresponding Source” for a work in object code form means all the
source code needed to generate, install, and (for an executable work) run the object
code and to modify the work, including scripts to control those activities. However,
it does not include the work's System Libraries, or general-purpose tools or
generally available free programs which are used unmodified in performing those
activities but which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for the work, and
the source code for shared libraries and dynamically linked subprograms that the work
is specifically designed to require, such as by intimate data communication or
control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate
automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
### 2. Basic Permissions
All rights granted under this License are granted for the term of copyright on the
Program, and are irrevocable provided the stated conditions are met. This License
explicitly affirms your unlimited permission to run the unmodified Program. The
output from running a covered work is covered by this License only if the output,
given its content, constitutes a covered work. This License acknowledges your rights
of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without
conditions so long as your license otherwise remains in force. You may convey covered
works to others for the sole purpose of having them make modifications exclusively
for you, or provide you with facilities for running those works, provided that you
comply with the terms of this License in conveying all material for which you do not
control copyright. Those thus making or running the covered works for you must do so
exclusively on your behalf, under your direction and control, on terms that prohibit
them from making any copies of your copyrighted material outside their relationship
with you.
Conveying under any other circumstances is permitted solely under the conditions
stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
### 3. Protecting Users' Legal Rights From Anti-Circumvention Law
No covered work shall be deemed part of an effective technological measure under any
applicable law fulfilling obligations under article 11 of the WIPO copyright treaty
adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention
of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of
technological measures to the extent such circumvention is effected by exercising
rights under this License with respect to the covered work, and you disclaim any
intention to limit operation or modification of the work as a means of enforcing,
against the work's users, your or third parties' legal rights to forbid circumvention
of technological measures.
### 4. Conveying Verbatim Copies
You may convey verbatim copies of the Program's source code as you receive it, in any
medium, provided that you conspicuously and appropriately publish on each copy an
appropriate copyright notice; keep intact all notices stating that this License and
any non-permissive terms added in accord with section 7 apply to the code; keep
intact all notices of the absence of any warranty; and give all recipients a copy of
this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer
support or warranty protection for a fee.
### 5. Conveying Modified Source Versions
You may convey a work based on the Program, or the modifications to produce it from
the Program, in the form of source code under the terms of section 4, provided that
you also meet all of these conditions:
* **a)** The work must carry prominent notices stating that you modified it, and giving a
relevant date.
* **b)** The work must carry prominent notices stating that it is released under this
License and any conditions added under section 7. This requirement modifies the
requirement in section 4 to “keep intact all notices”.
* **c)** You must license the entire work, as a whole, under this License to anyone who
comes into possession of a copy. This License will therefore apply, along with any
applicable section 7 additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no permission to license the
work in any other way, but it does not invalidate such permission if you have
separately received it.
* **d)** If the work has interactive user interfaces, each must display Appropriate Legal
Notices; however, if the Program has interactive interfaces that do not display
Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are
not by their nature extensions of the covered work, and which are not combined with
it such as to form a larger program, in or on a volume of a storage or distribution
medium, is called an “aggregate” if the compilation and its resulting
copyright are not used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work in an aggregate
does not cause this License to apply to the other parts of the aggregate.
### 6. Conveying Non-Source Forms
You may convey a covered work in object code form under the terms of sections 4 and
5, provided that you also convey the machine-readable Corresponding Source under the
terms of this License, in one of these ways:
* **a)** Convey the object code in, or embodied in, a physical product (including a
physical distribution medium), accompanied by the Corresponding Source fixed on a
durable physical medium customarily used for software interchange.
* **b)** Convey the object code in, or embodied in, a physical product (including a
physical distribution medium), accompanied by a written offer, valid for at least
three years and valid for as long as you offer spare parts or customer support for
that product model, to give anyone who possesses the object code either **(1)** a copy of
the Corresponding Source for all the software in the product that is covered by this
License, on a durable physical medium customarily used for software interchange, for
a price no more than your reasonable cost of physically performing this conveying of
source, or **(2)** access to copy the Corresponding Source from a network server at no
charge.
* **c)** Convey individual copies of the object code with a copy of the written offer to
provide the Corresponding Source. This alternative is allowed only occasionally and
noncommercially, and only if you received the object code with such an offer, in
accord with subsection 6b.
* **d)** Convey the object code by offering access from a designated place (gratis or for
a charge), and offer equivalent access to the Corresponding Source in the same way
through the same place at no further charge. You need not require recipients to copy
the Corresponding Source along with the object code. If the place to copy the object
code is a network server, the Corresponding Source may be on a different server
(operated by you or a third party) that supports equivalent copying facilities,
provided you maintain clear directions next to the object code saying where to find
the Corresponding Source. Regardless of what server hosts the Corresponding Source,
you remain obligated to ensure that it is available for as long as needed to satisfy
these requirements.
* **e)** Convey the object code using peer-to-peer transmission, provided you inform
other peers where the object code and Corresponding Source of the work are being
offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the
Corresponding Source as a System Library, need not be included in conveying the
object code work.
A “User Product” is either **(1)** a “consumer product”, which
means any tangible personal property which is normally used for personal, family, or
household purposes, or **(2)** anything designed or sold for incorporation into a
dwelling. In determining whether a product is a consumer product, doubtful cases
shall be resolved in favor of coverage. For a particular product received by a
particular user, “normally used” refers to a typical or common use of
that class of product, regardless of the status of the particular user or of the way
in which the particular user actually uses, or expects or is expected to use, the
product. A product is a consumer product regardless of whether the product has
substantial commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
“Installation Information” for a User Product means any methods,
procedures, authorization keys, or other information required to install and execute
modified versions of a covered work in that User Product from a modified version of
its Corresponding Source. The information must suffice to ensure that the continued
functioning of the modified object code is in no case prevented or interfered with
solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for
use in, a User Product, and the conveying occurs as part of a transaction in which
the right of possession and use of the User Product is transferred to the recipient
in perpetuity or for a fixed term (regardless of how the transaction is
characterized), the Corresponding Source conveyed under this section must be
accompanied by the Installation Information. But this requirement does not apply if
neither you nor any third party retains the ability to install modified object code
on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to
continue to provide support service, warranty, or updates for a work that has been
modified or installed by the recipient, or for the User Product in which it has been
modified or installed. Access to a network may be denied when the modification itself
materially and adversely affects the operation of the network or violates the rules
and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with
this section must be in a format that is publicly documented (and with an
implementation available to the public in source code form), and must require no
special password or key for unpacking, reading or copying.
### 7. Additional Terms
“Additional permissions” are terms that supplement the terms of this
License by making exceptions from one or more of its conditions. Additional
permissions that are applicable to the entire Program shall be treated as though they
were included in this License, to the extent that they are valid under applicable
law. If additional permissions apply only to part of the Program, that part may be
used separately under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any
additional permissions from that copy, or from any part of it. (Additional
permissions may be written to require their own removal in certain cases when you
modify the work.) You may place additional permissions on material, added by you to a
covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a
covered work, you may (if authorized by the copyright holders of that material)
supplement the terms of this License with terms:
* **a)** Disclaiming warranty or limiting liability differently from the terms of
sections 15 and 16 of this License; or
* **b)** Requiring preservation of specified reasonable legal notices or author
attributions in that material or in the Appropriate Legal Notices displayed by works
containing it; or
* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that
modified versions of such material be marked in reasonable ways as different from the
original version; or
* **d)** Limiting the use for publicity purposes of names of licensors or authors of the
material; or
* **e)** Declining to grant rights under trademark law for use of some trade names,
trademarks, or service marks; or
* **f)** Requiring indemnification of licensors and authors of that material by anyone
who conveys the material (or modified versions of it) with contractual assumptions of
liability to the recipient, for any liability that these contractual assumptions
directly impose on those licensors and authors.
All other non-permissive additional terms are considered “further
restrictions” within the meaning of section 10. If the Program as you received
it, or any part of it, contains a notice stating that it is governed by this License
along with a term that is a further restriction, you may remove that term. If a
license document contains a further restriction but permits relicensing or conveying
under this License, you may add to a covered work material governed by the terms of
that license document, provided that the further restriction does not survive such
relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in
the relevant source files, a statement of the additional terms that apply to those
files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a
separately written license, or stated as exceptions; the above requirements apply
either way.
### 8. Termination
You may not propagate or modify a covered work except as expressly provided under
this License. Any attempt otherwise to propagate or modify it is void, and will
automatically terminate your rights under this License (including any patent licenses
granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a
particular copyright holder is reinstated **(a)** provisionally, unless and until the
copyright holder explicitly and finally terminates your license, and **(b)** permanently,
if the copyright holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently
if the copyright holder notifies you of the violation by some reasonable means, this
is the first time you have received notice of violation of this License (for any
work) from that copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of
parties who have received copies or rights from you under this License. If your
rights have been terminated and not permanently reinstated, you do not qualify to
receive new licenses for the same material under section 10.
### 9. Acceptance Not Required for Having Copies
You are not required to accept this License in order to receive or run a copy of the
Program. Ancillary propagation of a covered work occurring solely as a consequence of
using peer-to-peer transmission to receive a copy likewise does not require
acceptance. However, nothing other than this License grants you permission to
propagate or modify any covered work. These actions infringe copyright if you do not
accept this License. Therefore, by modifying or propagating a covered work, you
indicate your acceptance of this License to do so.
### 10. Automatic Licensing of Downstream Recipients
Each time you convey a covered work, the recipient automatically receives a license
from the original licensors, to run, modify and propagate that work, subject to this
License. You are not responsible for enforcing compliance by third parties with this
License.
An “entity transaction” is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an organization, or
merging organizations. If propagation of a covered work results from an entity
transaction, each party to that transaction who receives a copy of the work also
receives whatever licenses to the work the party's predecessor in interest had or
could give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if the predecessor
has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or
affirmed under this License. For example, you may not impose a license fee, royalty,
or other charge for exercise of rights granted under this License, and you may not
initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging
that any patent claim is infringed by making, using, selling, offering for sale, or
importing the Program or any portion of it.
### 11. Patents
A “contributor” is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The work thus
licensed is called the contributor's “contributor version”.
A contributor's “essential patent claims” are all patent claims owned or
controlled by the contributor, whether already acquired or hereafter acquired, that
would be infringed by some manner, permitted by this License, of making, using, or
selling its contributor version, but do not include claims that would be infringed
only as a consequence of further modification of the contributor version. For
purposes of this definition, “control” includes the right to grant patent
sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license
under the contributor's essential patent claims, to make, use, sell, offer for sale,
import and otherwise run, modify and propagate the contents of its contributor
version.
In the following three paragraphs, a “patent license” is any express
agreement or commitment, however denominated, not to enforce a patent (such as an
express permission to practice a patent or covenant not to sue for patent
infringement). To “grant” such a patent license to a party means to make
such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the
Corresponding Source of the work is not available for anyone to copy, free of charge
and under the terms of this License, through a publicly available network server or
other readily accessible means, then you must either **(1)** cause the Corresponding
Source to be so available, or **(2)** arrange to deprive yourself of the benefit of the
patent license for this particular work, or **(3)** arrange, in a manner consistent with
the requirements of this License, to extend the patent license to downstream
recipients. “Knowingly relying” means you have actual knowledge that, but
for the patent license, your conveying the covered work in a country, or your
recipient's use of the covered work in a country, would infringe one or more
identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you
convey, or propagate by procuring conveyance of, a covered work, and grant a patent
license to some of the parties receiving the covered work authorizing them to use,
propagate, modify or convey a specific copy of the covered work, then the patent
license you grant is automatically extended to all recipients of the covered work and
works based on it.
A patent license is “discriminatory” if it does not include within the
scope of its coverage, prohibits the exercise of, or is conditioned on the
non-exercise of one or more of the rights that are specifically granted under this
License. You may not convey a covered work if you are a party to an arrangement with
a third party that is in the business of distributing software, under which you make
payment to the third party based on the extent of your activity of conveying the
work, and under which the third party grants, to any of the parties who would receive
the covered work from you, a discriminatory patent license **(a)** in connection with
copies of the covered work conveyed by you (or copies made from those copies), or **(b)**
primarily for and in connection with specific products or compilations that contain
the covered work, unless you entered into that arrangement, or that patent license
was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied
license or other defenses to infringement that may otherwise be available to you
under applicable patent law.
### 12. No Surrender of Others' Freedom
If conditions are imposed on you (whether by court order, agreement or otherwise)
that contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot convey a covered work so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not convey it at all. For example, if you
agree to terms that obligate you to collect a royalty for further conveying from
those to whom you convey the Program, the only way you could satisfy both those terms
and this License would be to refrain entirely from conveying the Program.
### 13. Use with the GNU Affero General Public License
Notwithstanding any other provision of this License, you have permission to link or
combine any covered work with a work licensed under version 3 of the GNU Affero
General Public License into a single combined work, and to convey the resulting work.
The terms of this License will continue to apply to the part which is the covered
work, but the special requirements of the GNU Affero General Public License, section
13, concerning interaction through a network will apply to the combination as such.
### 14. Revised Versions of this License
The Free Software Foundation may publish revised and/or new versions of the GNU
General Public License from time to time. Such new versions will be similar in spirit
to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that
a certain numbered version of the GNU General Public License “or any later
version” applies to it, you have the option of following the terms and
conditions either of that numbered version or of any later version published by the
Free Software Foundation. If the Program does not specify a version number of the GNU
General Public License, you may choose any version ever published by the Free
Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU
General Public License can be used, that proxy's public statement of acceptance of a
version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no
additional obligations are imposed on any author or copyright holder as a result of
your choosing to follow a later version.
### 15. Disclaimer of Warranty
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
### 16. Limitation of Liability
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
### 17. Interpretation of Sections 15 and 16
If the disclaimer of warranty and limitation of liability provided above cannot be
given local legal effect according to their terms, reviewing courts shall apply local
law that most closely approximates an absolute waiver of all civil liability in
connection with the Program, unless a warranty or assumption of liability accompanies
a copy of the Program in return for a fee.
_END OF TERMS AND CONDITIONS_
## How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to
the public, the best way to achieve this is to make it free software which everyone
can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them
to the start of each source file to most effectively state the exclusion of warranty;
and each file should have at least the “copyright” line and a pointer to
where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this
when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type 'show c' for details.
The hypothetical commands `show w` and `show c` should show the appropriate parts of
the General Public License. Of course, your program's commands might be different;
for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to
sign a “copyright disclaimer” for the program, if necessary. For more
information on this, and how to apply and follow the GNU GPL, see
<>.
The GNU General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may consider it
more useful to permit linking proprietary applications with the library. If this is
what you want to do, use the GNU Lesser General Public License instead of this
License. But first, please read
<>.
================================================
FILE: NAMESPACE
================================================
# Generated by roxygen2: do not edit by hand
export(do_ActivityHeatmap)
export(do_AlluvialPlot)
export(do_BarPlot)
export(do_BeeSwarmPlot)
export(do_BoxPlot)
export(do_CNVHeatmap)
export(do_CellularStatesPlot)
export(do_ChordDiagramPlot)
export(do_ColorBlindCheck)
export(do_ColorPalette)
export(do_CorrelationHeatmap)
export(do_DimPlot)
export(do_DotPlot)
export(do_EnrichmentHeatmap)
export(do_ExpressionHeatmap)
export(do_FeaturePlot)
export(do_GroupwiseDEHeatmap)
export(do_LigandReceptorPlot)
export(do_LoadingsHeatmap)
export(do_MetadataHeatmap)
export(do_NebulosaPlot)
export(do_PackageReport)
export(do_PathwayActivityHeatmap)
export(do_RankedEnrichmentHeatmap)
export(do_RankedExpressionHeatmap)
export(do_RidgePlot)
export(do_SCEnrichmentHeatmap)
export(do_SCExpressionHeatmap)
export(do_StripPlot)
export(do_TFActivityHeatmap)
export(do_TermEnrichmentPlot)
export(do_ViolinPlot)
export(do_VolcanoPlot)
export(do_WafflePlot)
================================================
FILE: NEWS.md
================================================
# SCpubr v3.0.2 (In Development)
## Bug fixes
- Fixed bug in `do_DotPlot()` where passing metadata columns (e.g., UCell enrichment scores, `nCount_RNA`, `nFeature_RNA`) as features would cause a "subscript out of bounds" error. The function now correctly retrieves metadata features from `sample@meta.data` alongside gene features from the assay matrix, allowing both to be plotted together.
## Documentation
- Improved roxygen titles and descriptions for `do_ViolinPlot()`, `do_DimPlot()`, `do_FeaturePlot()`, `do_NebulosaPlot()`, `do_DotPlot()`, `do_BeeSwarmPlot()`, `do_CellularStatesPlot()`, and `do_WafflePlot()`. Replaced uninformative "Wrapper for ..." titles with descriptive summaries of each function's purpose.
# SCpubr v3.0.1
## General
- Fixed compatibility with SeuratObject >= 5.0.0. Updated all instances of `GetAssayData()` to use the `layer` parameter instead of the deprecated `slot` parameter when SeuratObject version is 5.0.0 or higher. Affected functions: `do_FeaturePlot()`, `do_SCExpressionHeatmap()`, `do_CorrelationHeatmap()`, `do_LoadingsHeatmap()`, `do_TFActivityHeatmap()`, `do_PathwayActivityHeatmap()`, and `do_StripPlot()`.
- Added compatibility wrapper for `do_NebulosaPlot()` to handle Nebulosa package incompatibility with SeuratObject >= 5.0.0. The function now gracefully falls back to `do_FeaturePlot()` with an informative message when using newer SeuratObject versions, ensuring uninterrupted workflow.
- Packaging & documentation: Removed `waffle` from `Suggests` by implementing an internal waffle rendering in `do_WafflePlot()` using `ggplot2`. Replaced `\link[liana]{...}` cross-references with inline `\code{...}` mentions and removed `liana` from `Suggests`.
- Fixed bug in `do_DimPlot()` where using `label = TRUE` with `label.box = TRUE` would cause an error when attempting to add a fill scale that didn't exist. The internal `add_scale()` function now checks for scale existence before removal.
- Fixed bug in `do_DotPlot()` where the `cluster` parameter was clustering both features and identities, contrary to its documentation. Renamed `cluster` to `cluster.identities` and added `cluster.features` parameter for explicit control. Both default to `FALSE`.
- Fixed bug in `do_TermEnrichmentPlot()` where y-axis labels were derived from the original unfiltered data instead of the filtered/ordered terms, causing label mismatches. Labels now correctly correspond to the displayed terms.
- Fixed a bug in `do_ActivityHeatmap()` where asserthat calls would trigger an error regardless of the condition being met or not.
# SCpbur v3.0.0
## Reason for the mejor version change
- Due to the preparation for the publication of SCpubr's manuscript, a major effort has been made to further standardize and wrap up the package nicely.
- Some functions have been removed, and many have been renamed, for consistency.
- Development version of functions have been transferred to the normal release, with the exception of `SCpubr::do_SavePlot()`.
## General
- Enhanced startup message for clarity. Not it guides the user to run `SCpubr::package_report(extended = TRUE)` to get an overview of the missing dependencies.
- Added black border to glyphs in legends.
- Whenever a categorical color scale is used, now you can set `colorblind = TRUE`, and it will pull from a collection of different published colorblind-safe palettes. If the length of the classes in the categorical variable matches the length of one of the palettes, that palettes is used. If not, a pool will be selected, with a total maximum of 85 categories allowed. If `colors.use` is used, `colorblind` has no effect (thus, check if your palette is colorblind-safe with `do_ColorBlindCheck()`). For continuous variables, `YlGnBu` is used. For divergent variables, `RdBu` is used. Both `YlGnBu` and `RdBu` are colorblind-safe. Since they are set as default, there is no need for `colorblind` parameter in the functions that only plot continuous/divergent variables.
- Added support to show the values as text in most heatmap-based functions. This is achieved by using `values.show = TRUE`.
- Aesthetics of the text labels can be tuned with `values.threshold`, `values.size` and `values.round`.
- Fixed an issue where `symmetry_center` would not work as intended. Now it correctly displays the color scale with the provided value in the center.
## Added functions
- `do_WafflePlot()`: This function displays proportions as a pictogram grid of 10x10 tiles. It helps to visually see at a glance the proportions of your data. This fails to correctly convey decimal proportions and completely ignores heavily under-represented classes in your dataset.
- `do_RankedExpressionHeatmap()` to plot expression values as a heatmap along a dimensional reduction component.
- `do_ColorBlindCheck` to provide a comparative view of a given color paletter under different kinds of color blindness. This will allow to check for the suitability of a given set of colors for publication.
## Removed functions
- `do_FunctionalAnnotationPlot()`.
- `do_GroupedGOTermPlot()`.
The reason behind it is that they, together with do_TermEnrichmentPlot() targeted the same analysis and, therefore, were redundant.
## Renamed functions
In an effort to standardize function names, the following changes have been implemented:
- `do_DiffusionMapPlot()` is now called `do_RankedEnrichmentHeatmap()`.
- `save_plot()` (development release only) is now called `do_SavePlot()`.
- `package_report()` is now called `do_PackageReport()`.
- `do_LoadingsPlot()` is now called `do_LoadingsHeatmap()`.
- `do_AffinityAnalysisPlot()` is now called `do_ActivityHeatmap()`.
- `do_PathwayActivityPlot()` is now called `do_PathwayActivityHeatmap()`.
- `do_TFActivityPlot()` is now called `do_TFActivityHeatmap()`.
- `do_GroupwiseDEPlot()` is now called `do_GroupwiseDEHeatmap()`.
- `do_CopyNumberVariantPlot()` is now called `do_CNVHeatmap()`.
- `do_CorrelationPlot()` is now called `do_CorrelationHeatmap()`.
- `do_MetadataPlot()` is now called `do_MetadataHeatmap()`.
- `do_GeyserPlot()` is now called `do_StripPlot()`.
## Heavily modified functions.
- `do_TermEnrichmentPlot()`: Recoded the whole function. Now accepts the result of using `clusterProfiler::enrichGO()`, `clusterProfiler::enrichKEGG()`, etc. The output is a dot plot with the terms on the Y axis, the Gene Ratio in the X, colored by the adjusted p-value and size mapped to the Gene Count.
- `do_DotPlot()`: Removed dependencies with `Seurat::DotPlot()`.
- `do_RankedEnrichmentPlot()`, `do_EnrichmentHeatmap()` and `do_SCEnrichmentHeatmap()` do not longer accept `flavor = "AUCell"` due to dependency issues and lack of development support.
The reason of these modification is to allow for a much clearer and concise output than before.
## do_ActivityHeatmap()
- Changed legend title to "Z-Scored | ulm score", for consistency with other functions in the package.
## do_AlluvialPlot()
- Enforced a minimum version of `ggalluvial` to deal with deprecation of functions from `dplyr` and `tidyr` that were still used in `ggalluvial` functions.
- Modified the legend items to have a black border.
- Changed default legend position to bottom and legend title to top and centered.
## do_BoxPlot()
- Added `legend.ncol`, `legend.nrow` and `legend.byrow` parameters to control legend behavior.
- Fixed a bug in which `map_signif_levels` would only accept a logical and not custom mappings.
- When `map_signif_levels` is used, the mapping now appears as a plot legend for clarity.
- Added black borders to the legend glyphs when using `use_silhouette = FALSE`.
## do_CellularStatesPlot()
- Added reference lines to the plot to better visualize the segments.
- Added black border around the legend items.
- Fixed bug where axis text will always display in bold.
## do_ChortDiagramPlot()
- Added `font.size` parameter to control the font size of the plot.
## do_CNVHeatmap()
- Added `include_chr_arms` parameter to decide whether the heatmap should include a breakdown of the arms or just keep it by chromosomes.
## do_ColorPalette()
- Changed "Wheel" to "Color wheel" when plotting the output without additional parameters.
## do_DimPlot()
- Fixed a bug caused by using `cells.highlight` with only one cell.
- Fixed a bug causing the "Combined" plot resulting of the use of `split.by` and `group.by` to have a different size than the rest of panels when `ncol` parameter was also used.
- Fixed a bug causing a "selected_cells" plot title to show up when using `cells.highlight` and `idents.highlight`.
- Changed the plot title of the "Combined" plot to either `group.by` or `split.by` depending of the usage context.
- Added `split.by.combined` parameter and set its default value to `TRUE`. This allows to toggle on or off whether to display the combined view when `split.by` is used.
- However, when `split.by`is used alongside `group.by`, it is now enforced to show the combined plot (`split.by.combined = TRUE`), to avoid bugs.
- Added `legend.dot.border` parameter to select whether we want a black border around the legend dots or not.
- Fixed a bug in which `font.family` would not be applied when `label = TRUE`.
- Fixed a bug in which groups would not cluster if `cluster = TRUE` if there were missing values.
## do_DotPlot()
- Fixed a bug that caused sequential palettes to not be checked properly.
- Changed default value of `dot.scale` to 8.
- Removed legacy parameter `colors.use`, which had no effect as of previous version but was still listed as parameter.
- Removed dependency with `Seurat::DotPlot()`. This means that there will be some differences with the output of this function. However, this is a design choice for the sake of preventing future dependency problems.
- Added `split.by` parameter.
- If `features` is provided as a named list, the plot facets them based on the belonging list (duplcated genes are removed). Cannot be used alongside `split.by`.
- Removed `scale`and `scale.by` parameters. In the sense of how they worked in `Seurat`.
- Added `zscore.data` parameter. When set to `TRUE`, it computes Z-scores for each gene across the different groups, allowing for inspection of which group has highest or lowest expression, but prevents you from comparing values across different genes. It is intended to be used alongside `slot = "data"`.
- Removed the possibility to use a list of features. Instead, facets are being drawn according to `split.by` parameter.
- Removed `dot_border`. This is a design choice of `SCpubr`.
- Added `dot.min` parameter to exclude dots falling below a threshold for `P.Exp`.
## do_EnrichmentHeatmap()
- Changed default value of `scale_scores` to `FALSE`.
- Fixed a bug in which scores were not actually being scaled when `scale_scores = TRUE`.
- Fixed a bug in which setting `scale_scores = TRUE` and `features.order` would trigger an error since the output had the suffix `_scaled` on it. This has been patched.
## do_FeaturePlot()
- Fixed a bug in which legend titles would not show up as intended.
- Enabled the use of several legend titles when multiple features are provided. The number of legend titles and features have to be equal.
- Fixed a bug in which `font.family` would not be applied when `label = TRUE`.
- Added `scale.limits` parameter to control the range of values the color scale should take. This is specially useful if you want to plot several features and make the color comparable between them.
## do_GroupwiseDEHeatmap()
- Reduced the legend title texts to allow for more room in the plot.
- Fixed a bug in which providing a DE genes object with `p_val_adj = 0` would cause the function to crash.
## do_LigandReceptorPlot()
- Added a new parameter `top_interactions_by_group` which when set to `TRUE` will report for each pair of `source` and `target`, as many interactions as stated in `top_interactions`.
## do_MetadataHeatmap()
- Modified the legend items to have a black border.
- Set `cluster = FALSE` as default.
## do_PathwayActivityHeatmap
- Changed legend title to "Z-Scored | score", for consistency with other functions in the package.
## do_RidgePlot()
- Removed `size = 1.25` aesthetic from the call to `ggridges::geom_ridge...`.
- Set default legend position to bottom.
- Fixed a bug in which plot grid would not react properly to `flip`.
- Simplified the functionality of the function due to inconsistent interactions with `ggridges` package. As such, parameters `compute_quantiles`, `compute_custom_quantiles`, `quantiles`, `compute_distribution_tails`, `prob_tails` and `color_by_probabilities` are removed.
## do_SavePlot()
- Added `limitsize` parameter, that allows for very big ggplot2-based plots to be saved with big dimensions.
## do_TFActivityHeatmap()
- Changed legend title to "Z-Scored | score", for consistency with other functions in the package.
## do_ViolinPlot()
- Added `order` parameter to reorder the groups based on the median. Only works when `split.by` is set to `NULL`.
- Fixed typos in error logging.
- Fixed a bug in which color palettes would not display by default when using `split.by`.
## do_VolcanoPlot()
- Fixed an issue in which tags would be duplicated when using `use_labels = TRUE` in combination with `order_tabs_by = "both"`.
- Renewed aesthetics.
- Parameter `colors.use` now defaults to `NULL`, allowing a default color scheme to take place. Setting this parameter to a color will modify the color scheme appropriately.
- Simplified axis titles.
# SCpbur v2.0.2
## General.
- Fixed a bug that prevented error messages stating the dependencies missing per function to show up properly.
- Fixed assumptions on Seurat v4 and v5 and reverted to the use of cannonical `GetAssayData` and `SetAssayData` functions.
- Fixed dependency problems with archived packages.
## do_BeeSwarmPlot()
- Changed default continuous palette to `YlGnBu`.
- Changed default legend title to `feature_to_rank` if `continous_feature = TRUE`.
- Changed default value of `sequential.direction` to `1`.
- Changed default value of `legend.position` to `bottom` when `continuous_feature = FALSE`.
## do_BoxPlot()
- Changed default value of `legend.position` to `bottom`.
- Fixed a bug in which legend key glyphs would not show up when using `use_silhouette = TRUE`.
## do_CopyNumberVariantPlot()
- Fixed an issue in which using `min.cutoff` or `max.cutoff` would render the values outside these bounds to NA and therefore being plotted as grey. Now they will have the highest/lowest value possible.
## do_FeaturePlot()
- Added `symmetry.type` parameter, that allows to control how the symmetry is computed: either in absolute values (taking into account the highest and lowest value) or in the middle point specified by `symmetry.center`.
- Added `symmetry.center` parameter, that allows to control the center of symmetry when `symmetry.type` is set to `centered`.
## do_ViolinPlot()
- Changed default value of `legend.position` to `bottom`.
- Fixed a bug in which the default color palette would not be applied when `plot_boxplots = FALSE`.
- Added `legend.title.position` parameter and set it up as `top` by default.
- Fixed a bug in which plot grid would not react properly to `flip`.
# SCpubr v2.0.1
## General
- Refactored startup messages to comply with CRAN policies.
## Removed functions
- Removed `SCpubr::check_dependencies()` to support the use of `SCpubr::package_report()`.
## `SCpubr::do_EnrichmentHeatmap`
- Fixed a bug that checked the package dependencies for the wrong function.
# SCpubr v2.0.0
This major update focus on a complete re-implementation of all heatmap-based functions into `ggplot2` instead of `ComplexHeatmap`. This will lead to many of the existing code to break. The trade-off between the difficulty of debug, expand and maintain the existing heatmap-based functions with regards to the capabilities ComplexHeatmap offers with regards to ggplot2 was not worthy.
All heatmap-specific parameters have been replaced with the overarching parameters that are used across functions. This decision was taking after a lot of thought, but ultimately, having all plots rely on ggplot2 makes it way more compatible to work with them together, to debug, and to further implement new ideas.
Many (except a few selected cases) of the functions that returned list of different plots have been modified to return a single (and most important/relevant) plot and the option to return the Seurat object with the data generated added to it has been implemented so that the user can still generate plots with it. This goes in line with the fact that having so many interconnected functions made it very difficult to expand on them, if needed, as the downstream effects will cascade to other functions as well.
## Parameter renaming
- Changed `viridis_color_map` to `viridis.palette`.
- Changed `viridis_direction` to `viridis.direction`.
- Changed `sequential_direction` to `sequential.direction`.
- Changed `rotate_x_axis_labels` to `axis.text.x.angle`.
- Changed `rotate_strip_text` to `strip.text.angle`.
## New functions (available on the development build for extended texting)
- `SCpubr::do_MetadataPlot()` to generate metadata heatmaps with ease both from Seurat object or from a data frame. Will be first released as part of the `development version` and then released in CRAN as part of future updates. The idea is to gather feedback from users before officially releasing it.
- `SCpubr::do_SCExpressionHeatmap()` to generate heatmaps of expression of genes across all cells in the dataset. Will be first released as part of the `development version` and then released in CRAN as part of future updates. The idea is to gather feedback from users before officially releasing it.
- `SCpubr::do_SCEnrichementHeatmap()` to generate heatmaps of enrichment of genes across all cells in the dataset. Will be first released as part of the `development version` and then released in CRAN as part of future updates. The idea is to gather feedback from users before officially releasing it.
- `SCpubr::do_AffinityAnalysisPlot()` to assess the affinity of gene sets to subset of cells in the Seurat objects using the weighted means algorithms from DecoupleR. Will be first released as part of the `development version` and then released in CRAN as part of future updates. The idea is to gather feedback from users before officially releasing it.
- `SCpubr::do_LoadingsPlot()` to generate a summary heatmap of the PCA loadings (top and bottom scored genes for each PC) together with a expression heatmap of the same genes. Will be first released as part of the `development version` and then released in CRAN as part of future updates. The idea is to gather feedback from users before officially releasing it.
- `SCpubr::do_DiffusionMapPlot()` to analyze the output of a diffusion map analysis on the context of enrichment in gene sets used for the generation of the diffusion map. Will be first released as part of the `development version` and then released in CRAN as part of future updates. The idea is to gather feedback from users before officially releasing it.
- `SCpubr::check_dependencies()` to generate a per-function summary of the needed packages to run the function. The report has been enhanced with `cli` package and now clearly illustrates what is missing to run the function.
## Removed functions
- `SCpubr::do_SankeyPlot()` has been removed and replaced by `SCpubr::do_AlluvialPlot()`, which is present in the official CRAN versions.
- `SCpubr::do_PseudotimePlot()` has been removed indefinitely until a better, revamped, state-of-the-art version is generated.
- `SCpubr::do_AzimuthAnalysisPlot()` has been removed as the output can be accomplished by a combination of the current functions in `SCpubr`. A vignette will be added to reproduce the same analysis.
## General
- Now when using `min.cutoff` or `max.cutoff`, the legend will show that the min/max value is higher/lower than the one provided, if such value appeared originally in the legend breaks. This potentially interacts with `enforce_symmetry`.
- Added `number.breaks` parameter to control the number of breaks in the legend of ggplot2-based plots. It will not always work, as the function will try to fit the breaks accordingly. But still, will give some range of freedom to the user.
- Removed `colorsteps` from `legend.type` parameters as it was prone to generate unintended bugs.
- Changed default values from `min.cutoff` and `max.cutoff` from `NULL` to `NA`.
- Implemented `diverging.palette` parameter in all plots that have a symmetrical color scale to help selecting other possible color scales for the plot.
- Implemented `sequential.palette` parameter in all plots that have a continuous, non-symmetrical color scale to help selecting other possible color scales for the plot, in the case the user does not want to use viridis color scales.
- Renamed `SCpubr::state_dependencies()` to `SCpubr::check_dependencies()`.
- Renewed printed messages at startup and while running functions using `cli` package.
- Added the complete control of the font style of plot titles, subtitles, captions, axis titles, axis text, legend titles and legend text. For this, the following parameters have been added to all ggplot2-based functions:
- `plot.title.face`: To control the style of the **title**.
- `plot.subtitle.face`: To control the style of the **subtitle**.
- `plot.caption.face`: To control the style of the **caption**.
- `axis.title.face`: To control the style of the **axis title**.
- `axis.text.face`: To control the style of the **axis text**.
- `legend.title.face`: To control the style of the **legend title**.
- `legend.text.face`: To control the style of the **legend text**.
- Changed default font style for legend text from `bold` to `plain`.
- Changed default font style for axis text from `bold` to `plain`.
- When using `plot.axes = TRUE` parameter in `SCpubr::do_DimPlot()`, `SCpubr::do_FeaturePlot()` and `SCpubr::do_NebulosaPlot()`, now the entirety of the X and Y axis is removed, titles included.
- Remove plot margin padding in `SCpubr::do_DimPlot()`, `SCpubr::do_FeaturePlot()` and `SCpubr::do_NebulosaPlot()`.
## `SCpubr::do_AlluvialPlot`
- Added `sequential.palette` and `sequential.direction` parameters.
## `SCpubr::do_BarPlot`
- Added `facet.by` parameter to extra group the bars by a third metadata variable.
- Added `order.by` to reorder the bars when using `position = fill` based on a value in `group.by`.
- Limited the possible interactions from `group.by`, `split.by` and `order.by` to those that make sense to plot. For instance, a bar plot using `group.by` and `position = fill` but not using `split.by ` resulted in bars of equal lenght with only one value per group of proportion `1`.
- Set default value of `plot.grid` to `FALSE`.
- Added parameter `add.n` to display the total count on top when `position = fill`.
- Added parameter `add.n.face` to control the appearance of the text displayed.
- Added parameter `add.n.expand` to control the range of values in the Y axis. This has to be minimum 0 and maximum at least 1. This is set in order to tweak the limits so that the labels fit when `flip = TRUE`.
## `SCpubr::do_BeeSwarmPlot`
- Added `order` parameter to reorder the groups based on the median rank.
## `SCpubr::do_BoxPlot`
- Changed the reordering of boxplots based on the median rather than the mean.
- Added `na.rm` to `geom_boxplot` to avoid unnecessary warnings when introducing NAs as part of the data.
- Fixed a bug in which `order` would not work if `NAs` are in the data.
- Changed default value of `boxplot.linewidth` from `1` to `0.5`.
- Fixed a bug in which when using a combination of `group.by` and `split.by`, the package would check that the colors provided to `colors.use` need to match the values in `group.by` and not `split.by`.
## `SCpubr::do_CorrelationPlot`
- Added parameter to fix a bug in which viridis scales did not apply due to the lack of the parameter.
- Added `min.cutoff` and `max.cutoff` parameter to add cutoffs to the scales.
- Added `mode = "jaccard"` to compute a correlation matrix of a list of gene sets based on jaccard similarity.
- Added `use_viridis`, `sequential.palette` and `sequential_direction` and `diverging.palette` to control color palettes.
- Added `cluster` parameter to toggle on/off the clustering of the rows and columns in the heatmap.
- Added `remove.diagonal` parameter to toggle on/off the conversion of the diagonal in the correlation matrix to `NA`.
- Fixed several issues with setting cutoffs for the color scale using `min.cutoff` and `max.cutoff`.
- Fixed an issue where `number.breaks` will not work in `mode = "jaccard"`.
## `SCpubr::do_CopyNumberVariantPlot()`
- Removed the option to compute Feature and Geyser plots.
- Instead, a new paramerter `return_object` has been added to return the Seurat object with a new assay containing the CNV scores per cell on the `data` slot of the `CNV_scores` assay.
- The main output visualization is now a heatmap with the averaged scores by chromosome and groups and also by chromosome arms.
## `SCpubr::do_DimPlot`
- Modified underlying code to correctly display borders around cells when `cells.highlight` or `idents.hightlight` or `idents.keep` are used. Also removed the "Not selected" item from the legend when doing so, as it was redundant.
- Fixed a bug in which multiple legend would appear when using a combination of `group.by` and `split.by`, given that the individual UMAPs would not have the same number of entities to plot and color.
## `SCpubr::do_DotPlot`
- Added `scale` parameter to allow for the data to be scaled or not scaled.
- Removed `split.by` parameter in favor or the higher consistency and proper functionality accross parameters. Will probably come in the future, implemented outside of the umbrella of Seurat.
- Renamed parameter `cluster.idents` to `cluster`.
- Removed the limitation of `flip` when `features` was a list of genes. Now any combination of `flip` and `features` is possible.
## `SCpubr::do_EnrichmentHeatmap`
- Removed options to plot FeaturePlots, GeyserPlots, ViolinPlots, etc. - together with its related parameters. For the sake of simplicity in the function and its use, the user can get the Seurat object back with `return_object = TRUE` and plot the enrichment scores separately, that are stored as a new Assay.
- Removed `return_matrix` parameter as the scores can now be retrieved from the Seurat object as an assay.
- Enforcing the use of `named lists` as input for the function.
- Added `cluster` parameter to allow for clustering of rows and columns.
- Added `groups.order` to allow for specifically arrange the groups defined by `group.by` with a given order.
- Added `features.order` to allow for specifically arrange the gene sets defined by `input_gene_list`.
## `SCpubr::do_ExpressionHeatmap`
- Added `cluster` parameter to allow for clustering of rows and columns.
- Added `groups.order` to allow for specifically arrange the groups defined by `group.by` with a given order.
- Added `features.order` to allow for specifically arrange the features defined by `features`.
## `SCpubr::do_FeaturePlot`
- Modified underlying code to show a border around selected cells when using `split.by`, `cells.hightlight` and `idents.highlight`.
- Added parameter `border.density` to reduce the amount of extra cells drawn on the background to generate the borders. This will be a number between 0 and 1 corresponding to the quantile of the distribution of density of the points in the scatterplot drawn in the background. The lower the value, the harder it will be to keep a border around all cells, while it will significantly reduce the overall weight of the plot object.
- Added parameter `group.by`, that allows to plot a big dot in the center of each group designated by `group.by` and thus allowing to locate easily where each identity is in the FeaturePlot. Also, plots a legend matching the color of the dots. This can be tweaked with additional parameters such as:
- `group.by.show.dots` to controlw hether these dots are plotted or not (to allow only plotting colored borders around cells - see below).
- `group.by.dot.size` to control the size of the introduced dots.
- `group.by.cell_border` to plot another contour-like border which also displays the color coding of the clusters designated by `group.by`, to signal the reach of each cluster. However, this basically signals the cluster the cells in the periphery of the cell blobs belong to. Take that into account.
- `group.by.cell_borders.alpha` controls the alpha of the new cell borders.
- `group.by.legend` controls the legend title of the new legend.
- Renamed `split.by.idents` to `idents.keep` to better synergize with the parameter in `SCpubr::do_DimPlot`. Only works when `split.by` is used.
## `SCpubr::do_FunctionalAnnotationPlot`
- Removed the tree plots as they proved to behave inconsistently across datasets and the quality of visualizations were compromised.
- Removed the option to plot the bar plots and dot plots in the sake of a more simplified, streamlined plot generation.
- The option to return the result matrix using `return_matrix` is added, so that the user can use it to compute further analysis or visualizations.
## `SCpubr::do_FunctionalAnnotationPlot`
- Renamed `order_by_mean` to `order`.
- Ordering using `order = TRUE` now is done based on the median instead of the mean.
## `SCpubr::do_LigandReceptorPlot()`
- Modified the accepted input so that only the result of `liana::liana_aggregate()` is taken into account.
- Removed `arrange_interactions_by` as now the function only accepts the output of `liana::liana_aggregate()`.
- Added a `sort.by` parameter instead to select how the output of `liana::liana_aggregate()` should be ordered prior the subset by `top_interactions`. Five modes are available:
- `A`: Orders the output by `specificity`.
- `B`: Orders the output by `magnitude`.
- `C`: Orders the output by `specificity` then `magnitude`. This prioritizes the `specificity` column.
- `D`: Orders the output by `magnitude` then `specificity`. This prioritizes the `magnitude` column.
- `E`: Orders the output by `specificity` and `magnitude` providing equal weights to both columns.
- Removed `flip` parameter as the output was prone to errors.
- Removed parameter `compute_ChordDiagrams` and added `return_interactions`. This parameter returns two tibbles that can be used alongside `SCpubr::do_ChordDiagramPlot` to plot the diagrams.
- Now the filtering applied by using `keep_source` and `keep_target` takes place before subsetting for the top N interactions defined by `top_interactions`. This ensures that, if the user wants to focus on a given interaction subset, we retrieve the most important interactions for the subset.
- Added `magnitude` and `specificity` columns to allow the user to choose which variables to use for plotting.
- Added `sorting.type.magnitude` and `sorting.type.specificity` to allow the user to choose how the columns are sorted prior plotting.
- Added `invert_magnitude` and `invert_specificity` to allow the user to choose how the data is displayed for columns that tend to 0. Inverting performs a `-log10` transformation on the column.
- Added a `verbose` parameter and set it to `TRUE` by default to inform the user of the arrangements taking place in the output of `liana::liana_aggregate()` prior plotting.
## `SCpubr::do_PathwayActivityPlot()`
- Removed the option to plot geyser and feature plots to simplify the use (and computational time) of the function.
- Introduced `return_object` parameter that returns the Seurat object with the new assay to use for other plotting purposes (such as Geyser and Feature plots).
- Removed options to plot FeaturePlots, GeyserPlots - together with its related parameters. For the sake of simplicity in the function and its use, the user can get the Seurat object back with `return_object = TRUE` and plot the scores separately.
- Added `slot` parameter to decide whether to plot scale data or not.
- Fixed bug in which after setting `enforce_symmetry = FALSE` the color palette used was `diverging.palette` instead.
## `SCpubr::do_TFActivityPlot()`
- Removed the option to plot geyser and feature plots to simplify the use (and computational time) of the function.
- Introduced `return_object` parameter that returns the Seurat object with the new assay to use for other plotting purposes (such as Geyser and Feature plots).
- Removed options to plot FeaturePlots, GeyserPlots - together with its related parameters. For the sake of simplicity in the function and its use, the user can get the Seurat object back with `return_object = TRUE` and plot the scores separately.
- Added `slot` parameter to decide whether to plot scale data or not.
- Fixed bug in which after setting `enforce_symmetry = FALSE` the color palette used was `diverging.palette` instead.
# SCpubr v1.1.2
More hotfixes in unit tests to comply with CRAN checks.
# SCpubr v1.1.1
Hotfixes in unit tests to comply with CRAN checks.
# SCpubr v1.1.0
## General
- Increased the cell size of all heatmap-based functions from 5 to 8.
- Decreased the thickness of frame and ticks of all ggplot2-based continuous legends to retrieve a similar behavior as in previous versions of ggplot2, as with the new update, the overall thickness of the frame and ticks increased, probably due to the changes related to `element_line`,
- Added five new functions: `do_AlluvialPlot()`, `do_AzimuthAnalysisPlot()`, `do_ExpressionHeatmap()`, `do_GroupedGOTermPlot()` and `do_FunctionalAnnotationPlot()`.
- Added `legend.ncol`, `legend.nrow`, `legend.title` and `legend.byrow` to as many functions as possible to further customize legend appearance.
## `SCpubr::do_BeeSwarmPlot()`
- Added `min.cutoff` and `max.cutoff` parameter.
- Added ticks to the plot, that were missing.
- Added missing axes titles.
- Added `viridis_direction` parameter to control how the continuous color scale is formed.
- Added `return_object` parameter to return the Seurat object with the enrichment scores computed.
- Added BoxPlots, BeeSwarmPlots and ViolinPlots to the possible outputs the user can choose from.
- Make `legend.position` conditional of whether `continuous_feature` is set to TRUE. If it is false, legend is not displayed unless the user specifies otherwise.
## `SCpubr::do_BarPlot()`
- Fixed a bug in which axes titles were not displaying correctly under certain combinations of `flip` and `split.by`.
- Fixed a bug in which `x_lab` and `y_lab` would not rotate accordingly when using `flip = TRUE`.
## `SCpubr::do_BeeSwarmPlot()`
- Adapted the code to the new 0.7.1 version of the package, thus deprecating the `groupOnX` parameter of `geom_quarirandom`. This will likely affect users with a lower version.
- A warning has been placed for the users in lower versions of the need to upgrade to 0.7.1.
- This changes are subject to the new behaviors/deprecations of ggplot2 and ggplot2.
## `SCpubr::do_BoxPlot()`
- Set `assay` to NULL and will default to the default assay in the seurat object.
## `SCpubr::do_CellularStatesPlot()`
- Fixed a bug that prevented FeaturePlots to have symmetrical axes with respect to the main plot.
## `SCpubr::do_CorrelationPlot()`
- Added `viridis_direction` parameter.
## `SCpubr::do_DimPlot()`
- Fixed a bug in which the legend title will not show up in regular basic plots even though the parameter `legend.title` was used.
- Completely reformatted the way `split.by` works, so that now only one legend is displayed for the whole group and cells have border.
- Added `label.size` and `label.box` parameters for further customize the appearance of the plot when using `label = TRUE`.
- Changed `repel` to `FALSE` by default.
## `SCpubr::do_EnrichmentHeatmap()`
- Fixed a bug in the code that prevented the feature plots and the geyser plots to be computed if the input gene list was not a named list of genes.
- Added `flavor = "AUCell"`, that lets the user compute AUCell scoring of the gene sets.
- Added the option to query multiple `group.by` parameters at the same time.
- Fixed a bug in the code that prevented multiple outputs with different values of `group.by` to be returned properly, leading to the last value of `group.by` replacing all the rest.
## `SCpubr::do_FeaturePlot()`
- Added `label`, `label.size` and `label.color` parameter to reproduce the same behavior as in `Seurat::FeaturePlot()`.
## `SCpubr::do_GroupwiseDEPlot()`
- Set `assay` to NULL and will default to the default assay in the seurat object.
## `SCpubr::do_LigandReceptorPlot()`
- Added `arrange_interactions_by` to control how output interactions are arranged (either by aggregate_rank, specificity, magnitude or a combination of magnitude and specificity).
- Added `sort_interactions_alphabetically` to control whether the output dotplot has the interactions ordered alphabetically or as they come in the original matrix (meaning, they follow the arrangement specified in `arrange_interactions_by`). (([liana's issue #72](https://github.com/saezlab/liana/issues/72)))
## `do_PathwayActivityPlot()`
- Added a fix in which when `enforce_symmetry` is set to `FALSE`, then the color scale turns into a viridis-based one instead of a two-color gradient scale.
## `do_TFActivityPlot()`
- Added a fix in which when `enforce_symmetry` is set to `FALSE`, then the color scale turns into a viridis-based one instead of a two-color gradient scale.
## `SCpubr::do_ViolinPlot()`
- Fixed a bug in the code in which no different colors could be passed to `colors.use`.
- Reduced default line width from 1 to 0.5.
# SCpubr v1.0.4
- Hotfix for v1.0.3 in which `do_GeyserPlot` with categorical variables had a bug that mapped the legend to the continuous axis.
# SCpubr v1.0.3
## General changes
- Added `min.cutoff` and `max.cutoff` parameter to effectively subset the color scale and remove the effect of extreme outliers in all ComplexHeatmap-based functions.
- Added `min.cutoff` and `max.cutoff` parameter to effectively subset the color scale and remove the effect of extreme outliers in all ggplot2-based functions susceptible to be biased by outliers.
## `SCpubr::do_DimPlot()`
- Implemented a change in which when using `split.by` and `group.by` in combination, the cells colored on top of the UMAP also have a border.
- Implemented a bug-fix in which when using `split.by` and `group.by` in combination, the extra new layers would not raster if `raster = TRUE`.
- Implemented a bug-fix in which when using `split.by` and `group.by` in combination, no plots will appear if `ncol` is set.
- Implemented a new feature to add density line contours using `plot_density_contour`.
- Implemented the conditional use of `raster.dpi` to Seurat versions higher or equal to 4.1.0.
## `SCpubr::do_EnrichmentHeatmap()`
- Implemented a bug fix for internal checks in the function.
- Added `plot_FeaturePlots` and `plot_GeyserPlots` to also report the enrichment scores in a gene set-based manner.
- Added `flavor` parameter, that accepts `Seurat` and `UCell` to allow for different enrichment scoring methods. It requires `R 4.2.0` to run.
- Renamed `symmetrical_scale` to `enforce_symmetry` to have a greater coherence across functions.
## `SCpubr::do_FeaturePlot()`
- Implemented a new feature to add density line contours using `plot_density_contour`.
- Implemented the conditional use of `raster.dpi` to Seurat versions higher or equal to 4.1.0.
## `SCpubr::do_GeyserPlot()`
- Fixed bug in which internal parameter names made it to the X axis title.
- Removed `color.by` implementation due to it being very buggy. This will be re-implemented in a future patch.
## `SCpubr::do_RidgePlot()`
- Implemented a bug-fix in which using `assay = "RNA"` or, in fact, any other assay rather than `SCT` will result in an error.
## `SCpubr::do_ViolinPlot()`
- Corrected a bug in which legend title when using `split.by` was an actual line of code.
- Added `legend.title` parameter to control the title of the legend.
### SCpubr v.1.0.3-dev-stable
- Same as v1.0.3, but with all the functions that do not pass CRAN checks. These functions are: `SCpubr::save_Plot()` `SCpubr::do_LigandReceptorPlot()` and `SCpubr::do_SankeyPlot()`.
# SCpubr v1.0.2
## General changes
- Change color palette when using `enforce_symmetry = TRUE` to have the middle color as `grey95` instead of the previous one, which made middle values seem closer to the positive end of the scale.
- Modified internal structure of all functions to abide with [tidyselect v1.2.0 lifecycle modifications](https://tidyselect.r-lib.org/news/index.html#lifecycle-changes-1-2-0).
- Modified `rotate_x_axis_labels` parameter in all functions that made use of it. Now, instead of accepting a `logical`, accepts a `numeric`: either `0`, `45` or `90`, corresponding to the degrees in which the X axis labels should be rotated. ([#5](https://github.com/enblacar/SCpubr/issues/5#issuecomment-1289203453))
## `SCpubr::do_CopyNumberVariantPlot`
- Modified the code for `SCpubr::do_CopyNumberVariantPlot` to also report results for the whole chromosome as well as for each chromosome arm.
- Include the `verbose` argument to `SCpubr::do_CopyNumberVariantPlot` to silence the messages when there are not enough genes in the chromosome to perform the analysis.
## `SCpubr::do_DimPlot()`
- Fixed a typo that prevented labels to be bold in `SCpubr::do_DimPlot()` when cell borders are displayed.
- Added `group.by` and `split.by` functionality to `SCpubr::do_DimPlot()`. ([#4](https://github.com/enblacar/SCpubr/issues/4))
## `SCpubr::do_DotPlot()`
- Added ticks to axes.
- Modified default colors to convey a better aesthetic.
## `SCpubr::do_FeaturePlot()`
- Fixed potential bugs in `SCpubr::do_FeaturePlot` when setting `enforce_symmetry = TRUE`.
- Changed default value of `order` in `SCpubr::do_FeaturePlot()` from `TRUE` to `FALSE`.
- Added `min.cutoff` and `max.cutoff` parameters to `SCpubr::do_FeaturePlot()`. This allows to effectively subset the color scale to the values provided. Cells outside the range will be converted to the min or max values provided, respectively. ([#2](https://github.com/enblacar/SCpubr/issues/2))
## `SCpubr::do_GeyserPlot()`
- Added `flip` parameter.
## `SCpubr::do_GroupwiseDEPlot()`
- Fixed bug in `SCpubr::do_GroupwiseDEPlot` in which the heatmap could not be computed. ([#3](https://github.com/enblacar/SCpubr/issues/3))
- Added extra checks to ensure proper input in `SCpubr::do_GroupwiseDEPlot`. ([#3](https://github.com/enblacar/SCpubr/issues/3))
## `SCpubr::do_LigandReceptorPlot()` (development release)
- Changed parameter `x_labels_angle` to `rotate_x_axis_labels` to keep a consistent terminology.
## `SCpubr::do_RidgePlot()`
- Fixed a typo that made the lines in `panel.grid.minor` to be displayed in `SCpubr::do_Ridgeplot()`.
- Added `flip` parameter.
## `SCpubr::do_ViolinPlot()`
- Added `split.by` functionality to `SCpubr::do_ViolinPlot()`. ([#4](https://github.com/enblacar/SCpubr/issues/4), [#5](https://github.com/enblacar/SCpubr/issues/5))
- Added `flip` parameter.
- Now multiple features can be queried ad the same time. ([#5](https://github.com/enblacar/SCpubr/issues/5#issuecomment-1289203453))
- Changed `feature` parameter to `features`, to better reflect the multiple feature behavior.
- Recreated `Seurat`'s `share.y.lims` behavior and set it to `share.y.lims` parameter. ([#5](https://github.com/enblacar/SCpubr/issues/5#issuecomment-1289203453))
### SCpubr v1.0.2-dev-stable
- Same as v1.0.2, but with all the functions that do not pass CRAN checks. These functions are: `SCpubr::save_Plot()` `SCpubr::do_LigandReceptorPlot()` and `SCpubr::do_SankeyPlot()`.
# SCpubr v1.0.1
- Rework on unit tests and examples so that it can pass CRAN R CMD Check without packages in Suggests. This is, to make sure all Suggested packages are used conditionally.
## SCpubr v1.0.1-dev-stable
- Same as v1.0.1, but with all the functions that do not pass CRAN checks. These functions are: `SCpubr::save_Plot()` `SCpubr::do_LigandReceptorPlot()` and `SCpubr::do_SankeyPlot()`.
# SCpubr v1.0.0
- Modified internal checks so that the functions that do not use `Seurat` do not require this to be installed. This is just for the very side case in which somebody downloads the package just for the `SCpubr::do_ColorPalette()` function.
- Removed the option to use `individual.titles`, 'individual.subtitles`and`individual.captions`in`SCpubr::do_NebulosaPlot()\` as the benefit of such parameters did not surpass the problems the code was causing. The feature might come back in the future, once fully optimized.
- Removed `SCpubr::save_Plot()` function to align with CRAN policies that the package should not write to the file system. The code is still available in the v0.0.0.0.9000 release in Github.
- Removed `SCpubr::do_LigandReceptorPlot()`, `SCpubr::do_SankeyPlot()` and `SCpubr::do_PseudotimePlot()` to align with CRAN policies and make it possible to publish the package. These functions can still be accessed in the v0.0.0.0.9000 release in Github.
- Removed `SCpubr::do_PseudotimePlot()` for the reason above and because the dependency `Matrix.utils` was removed from CRAN on *09-10-2022*.
## SCpubr v1.0.0-dev-stable
- Same as v1.0.0, but with all the functions that do not pass CRAN checks. These functions are: `SCpubr::save_Plot()` `SCpubr::do_LigandReceptorPlot()` and `SCpubr::do_SankeyPlot()`.
# SCpubr 0.0.0.9000
- Added a `NEWS.md` file to track changes to the package.
- Prepare package for submission to CRAN.
================================================
FILE: R/data.R
================================================
#' Chromosome arm locations for human genome GRCh38.
#'
#' A tibble containing the chromosome, arm and start and end coordinates.
#'
#' @format A tibble with 48 rows and 4 columns:
#' \describe{
#' \item{chr}{Chromosome.}
#' \item{arm}{Chromosome arm.}
#' \item{start}{Start coordinates.}
#' \item{end}{End coordinates.}
#' }
#' @usage data(human_chr_locations)
"human_chr_locations"
================================================
FILE: R/do_ActivityHeatmap.R
================================================
#' Compute affinity of gene sets to cell populations using decoupleR.
#'
#' Major contributions to this function:
#' - \href{https://github.com/MarcElosua}{Marc Elosua Bayés} for the core concept code and idea.
#' - \href{https://github.com/paubadiam}{Pau Badia i Mompel} for the network generation.
#'
#' @inheritParams doc_function
#' @param statistic \strong{\code{\link[base]{character}}} | DecoupleR statistic to use for the analysis.
#' values in the Idents of the Seurat object are reported, assessing how specific a given gene set is for a given cell population compared to other gene sets of equal expression.
#'
#' @return A list containing different plots.
#' @export
#'
#' @example /man/examples/examples_do_ActivityHeatmap.R
do_ActivityHeatmap <- function(sample,
input_gene_list,
subsample = 2500,
group.by = NULL,
assay = NULL,
slot = NULL,
statistic = "ulm",
number.breaks = 5,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
diverging.palette = "RdBu",
diverging.direction = -1,
enforce_symmetry = TRUE,
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
na.value = "grey75",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
flip = FALSE,
colors.use = NULL,
min.cutoff = NA,
max.cutoff = NA,
verbose = FALSE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
flavor = "Seurat",
nbin = 24,
ctrl = 100,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests("do_ActivityHeatmap")
check_Seurat(sample)
if (is.null(assay)){assay <- check_and_set_assay(sample)$assay}
slot <- if(is.null(slot)){"data"} else {slot}
# Check logical parameters.
logical_list <- list("verbose" = verbose,
"flip" = flip,
"enforce_symmetry" = enforce_symmetry,
"use_viridis" = use_viridis,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"legend.length" = legend.length,
"legend.width" = legend.width,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"subsample" = subsample,
"viridis.direction" = viridis.direction,
"axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction,
"nbin" = nbin,
"ctrl" = ctrl,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"assay" = assay,
"slot" = slot,
"statistic" = statistic,
"legend.type" = legend.type,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"font.type" = font.type,
"viridis.palette" = viridis.palette,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"grid.color" = grid.color,
"border.color" = border.color,
"flavor" = flavor,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"na.value" = na.value)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
`%>%` <- magrittr::`%>%`
check_colors(grid.color, parameter_name = "grid.color")
check_colors(na.value, parameter_name = "na.value")
check_colors(border.color, parameter_name = "border.color")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
# Assign a group.by if this is null.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (!is.na(subsample)){
sample <- sample[, sample(colnames(sample), subsample)]
}
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
# Generate a network with the names of the list of genes as source and the gene sets as targets with 1 of mode of regulation.
# Step 1: Check for underscores in the names of the gene sets.
if (length(unlist(stringr::str_match_all(names(input_gene_list), "_"))) > 0){
warning(paste0(add_warning(), crayon_body("Found "),
crayon_key("underscores (_)"),
crayon_body(" in the name of the gene sets provided. Replacing them with "),
crayon_key("dots (.)"),
crayon_body(" to avoid conflicts when generating the Seurat assay.")), call. = FALSE)
names.use <- stringr::str_replace_all(names(input_gene_list), "_", ".")
names(input_gene_list) <- names.use
}
# Step 2: make the lists of equal length.
max_value <- max(unname(unlist(lapply(input_gene_list, length))))
min_value <- min(unname(unlist(lapply(input_gene_list, length))))
assertthat::assert_that(length(input_gene_list) >= 2,
msg = paste0(add_cross(),
crayon_body("Please make sure that the gene list you provide to "),
crayon_key("input_gene_list"),
crayon_body(" have at least "),
crayon_key("two different"),
crayon_body(" gene sets.")))
assertthat::assert_that(min_value >= 5,
msg = paste0(add_cross(),
crayon_body("Please make sure that the gene list you provide to "),
crayon_key("input_gene_list"),
crayon_body(" have at least "),
crayon_key("five genes"),
crayon_body(" each.")))
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
# Add fake genes until all lists have the same length so that it can be converted into a tibble.
gene_list <- lapply(input_gene_list, function(x){
if (length(x) != max_value){
remaining <- max_value - length(x)
x <- append(x, rep("deleteme", remaining))
x
} else{
x
}
})
# Generate the network as a tibble and filter out fake genes.
network <- gene_list %>%
tibble::as_tibble() %>%
tidyr::pivot_longer(cols = dplyr::everything(),
names_to = "source",
values_to = "target") %>%
dplyr::mutate("mor" = 1) %>%
dplyr::filter(.data$target != "deleteme")
# Get expression data.
# Conditional behaviour for Seurat versions.
if (utils::packageVersion("Seurat") < "5.0.0"){
mat <- SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = slot)
} else {
mat <- SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = slot)
}
# Compute activities.
if(isTRUE(verbose)){message(paste0(add_info(), crayon_body("Computing "),
crayon_key("activities"),
crayon_body("...")))}
if (statistic == "ulm"){
acts <- decoupleR::run_ulm(mat = mat,
network = network)
} else {
acts <- decoupleR::run_wmean(mat = mat,
network = network)
}
# Turn them into a matrix compatible to turn into a Seurat assay.
acts.matrix <- acts %>%
dplyr::filter(.data$statistic == .env$statistic) %>%
tidyr::pivot_wider(id_cols = dplyr::all_of("source"),
names_from = "condition",
values_from = "score") %>%
tibble::column_to_rownames('source')
# Generate a Seurat assay.
assay.add <- Seurat::CreateAssayObject(acts.matrix)
# Add the assay to the Seurat object.
sample@assays$affinity <- assay.add
sample@assays$affinity@key <- "affinity_"
# Set it as default assay.
Seurat::DefaultAssay(sample) <- "affinity"
# Scale and center the activity data.
sample <- Seurat::ScaleData(sample, verbose = FALSE, assay = "affinity")
# Plotting.
# Get the data frames per group.by value for plotting.
list.data <- list()
counter <- 0
for (group in group.by){
counter <- counter + 1
if (utils::packageVersion("Seurat") < "5.0.0"){
data.use <- SeuratObject::GetAssayData(object = sample,
assay = "affinity",
slot = "scale.data")
} else {
data.use <- SeuratObject::GetAssayData(object = sample,
assay = "affinity",
layer = "scale.data")
}
data.use <- data.use %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::select(dplyr::all_of(c("cell", group)))},
by = "cell") %>%
tidyr::pivot_longer(cols = -dplyr::all_of(c("cell", group)),
names_to = "source",
values_to = "score")
# Clustering based on the median across all cells.
data.cluster <- data.use %>%
tidyr::pivot_wider(id_cols = dplyr::all_of(c("cell", group)),
names_from = "source",
values_from = "score") %>%
dplyr::group_by(.data[[group]]) %>%
dplyr::summarise(dplyr::across(.cols = dplyr::all_of(c(names(input_gene_list))),
function(x){stats::median(x, na.rm = TRUE)})) %>%
as.data.frame() %>%
tibble::column_to_rownames(var = group)
list.data[[group]][["data"]] <- data.use
list.data[[group]][["data.cluster"]] <- data.cluster
}
# Plot individual heatmaps.
list.heatmaps <- list()
counter <- 0
row.order.list <- list()
for (group in group.by){
counter <- counter + 1
data.use <- list.data[[group]][["data"]]
data.cluster <- list.data[[group]][["data.cluster"]]
# nocov start
if (counter == 1){
if (length(colnames(data.cluster)) == 1){
col_order <- colnames(data.cluster)[1]
} else {
col_order <- colnames(data.cluster)[stats::hclust(stats::dist(t(data.cluster), method = "euclidean"), method = "ward.D")$order]
}
}
# nocov end
if(length(rownames(data.cluster)) == 1){
row_order <- rownames(data.cluster)[1]
} else {
row_order <- rownames(data.cluster)[stats::hclust(stats::dist(data.cluster, method = "euclidean"), method = "ward.D")$order]
}
row.order.list[[group]] <- row_order
data.use <- data.use %>%
dplyr::group_by(.data[[group]], .data$source) %>%
dplyr::summarise("mean" = mean(.data$score, na.rm = TRUE))
list.data[[group]][["data.mean"]] <- data.use
if (!is.na(min.cutoff)){
data.use <- data.use %>%
dplyr::mutate("mean" = ifelse(.data$mean < min.cutoff, min.cutoff, .data$mean))
}
if (!is.na(max.cutoff)){
data.use <- data.use %>%
dplyr::mutate("mean" = ifelse(.data$mean > max.cutoff, max.cutoff, .data$mean))
}
p <- data.use %>%
dplyr::mutate("source" = factor(.data$source, levels = col_order),
"target" = factor(.data[[group]], levels = row_order)) %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if (isTRUE(flip)){.data$source} else {.data$target},
y = if (isTRUE(flip)){.data$target} else {.data$source},
fill = .data$mean)) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5, na.rm = TRUE)
if (base::isTRUE(values.show)){
if (base::isTRUE(enforce_symmetry)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(abs(.data$mean) > values.threshold, "white", "black")),
size = values.size)
} else {
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(.data$mean > values.threshold, "white", "black")),
size = values.size)
}
p <- p + ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
# nocov start
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(if (isTRUE(flip)){.data$target} else {.data$source}))),
x.sec = guide_axis_label_trans(~paste0(levels(if (isTRUE(flip)){.data$source} else {.data$target})))) +
# nocov end
ggplot2::coord_equal()
list.heatmaps[[group]] <- p
}
# Compute limits.
min.vector <- NULL
max.vector <- NULL
for (group in group.by){
data.limits <- list.data[[group]][["data.mean"]]
min.vector <- append(min.vector, min(data.limits$mean, na.rm = TRUE))
max.vector <- append(max.vector, max(data.limits$mean, na.rm = TRUE))
}
# Get the absolute limits of the datasets.
limits <- c(min(min.vector, na.rm = TRUE),
max(max.vector, na.rm = TRUE))
# Compute overarching scales for all heatmaps.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
for (group in group.by){
p <- list.heatmaps[[group]]
p <- p +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = paste0("Z-scored | ", statistic, " score"),
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
list.heatmaps[[group]] <- p
}
# Modify legends.
for (group in group.by){
p <- list.heatmaps[[group]]
p <- modify_continuous_legend(p = p,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
list.heatmaps[[group]] <- p
}
# Add theme
counter <- 0
for (group in group.by){
counter <- counter + 1
p <- list.heatmaps[[group]]
# Set axis titles.
if (isTRUE(flip)){
if (counter == 1){
ylab <- group
xlab <- NULL
if (length(group.by) == counter){
xlab <- "Gene set"
}
} else {
xlab <- "Gene set"
ylab <- group
}
} else {
if (counter == 1){
ylab <- "Gene set"
xlab <- group
} else {
ylab <- NULL
xlab <- group
}
}
p <- list.heatmaps[[group]]
axis.parameters <- handle_axis(flip = !flip,
group.by = rep("A", length(group.by)),
group = group,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = legend.position,
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.spacing.x = ggplot2::unit(0, "cm"))
list.heatmaps[[group]] <- p
}
if (isTRUE(flip)){
list.heatmaps <- list.heatmaps[rev(group.by)]
}
p <- patchwork::wrap_plots(list.heatmaps,
ncol = if (base::isFALSE(flip)){NULL} else {1},
nrow = if(base::isFALSE(flip)){1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = "bold",
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
list.output <- list()
list.output[["Heatmap"]] <- p
if (isTRUE(return_object)){
list.output[["Object"]] <- sample
}
if (isTRUE(return_object)){
return_me <- list.output
} else {
return_me <- list.output$Heatmap
}
return(return_me)
}
================================================
FILE: R/do_AlluvialPlot.R
================================================
#' Generate Alluvial plots.
#'
#' This function is based on the \pkg{ggalluvial} package. It allows you to generate alluvial plots from a given Seurat object.
#'
#' @inheritParams doc_function
#'
#' @param first_group \strong{\code{\link[base]{character}}} | Categorical metadata variable. First group of nodes of the alluvial plot.
#' @param last_group \strong{\code{\link[base]{character}}} | Categorical metadata variable. Last group of nodes of the alluvial plot.
#' @param middle_groups \strong{\code{\link[base]{character}}} | Categorical metadata variable. Vector of groups of nodes of the alluvial plot.
#' @param colors.use \strong{\code{\link[base]{character}}} | Named list of colors corresponding to the unique values in fill.by (which defaults to last_group).
#' @param fill.by \strong{\code{\link[base]{character}}} | One of first_group, middle_groups (one of the values, if multiple mid_groups) or last_group. These values will be used to color the alluvium/flow.
#' @param use_labels \strong{\code{\link[base]{logical}}} | Whether to use labels instead of text for the stratum.
#' @param stratum.color,alluvium.color,flow.color \strong{\code{\link[base]{character}}} | Color for the border of the alluvium (and flow) and stratum.
#' @param stratum.fill \strong{\code{\link[base]{character}}} | Color to fill the stratum.
#' @param stratum.width \strong{\code{\link[base]{logical}}} | Width of the stratum.
#' @param stratum.fill.conditional \strong{\code{\link[base]{logical}}} | Whether to fill the stratum with the same colors as the alluvium/flow.
#' @param use_geom_flow \strong{\code{\link[base]{logical}}} | Whether to use \code{\link[ggalluvial]{geom_flow}} instead of \code{\link[ggalluvial]{geom_alluvium}}. Visual results might differ.
#' @param label.color \strong{\code{\link[base]{character}}} | Color for the text labels.
#' @param curve_type \strong{\code{\link[base]{character}}} | Type of curve used in \code{\link[ggalluvial]{geom_alluvium}}. One of:
#' \itemize{
#' \item \emph{\code{linear}}.
#' \item \emph{\code{cubic}}.
#' \item \emph{\code{quintic}}.
#' \item \emph{\code{sine}}.
#' \item \emph{\code{arctangent}}.
#' \item \emph{\code{sigmoid}}.
#' \item \emph{\code{xspline}}.
#' }
#'
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_AlluvialPlot.R
do_AlluvialPlot <- function(sample,
first_group,
last_group,
middle_groups = NULL,
colors.use = NULL,
colorblind = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
font.size = 14,
font.type = "sans",
xlab = NULL,
ylab = "Number of cells",
repel = FALSE,
fill.by = last_group,
use_labels = FALSE,
stratum.color = "black",
stratum.fill = "white",
stratum.width = 1/3,
stratum.fill.conditional = FALSE,
use_geom_flow = FALSE,
alluvium.color = "white",
flow.color = "white",
flip = FALSE,
label.color = "black",
curve_type = "sigmoid",
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.grid = FALSE,
grid.color = "grey75",
grid.type = "dashed",
na.value = "white",
legend.position = "bottom",
legend.title = NULL,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_AlluvialPlot")
check_Seurat(sample)
# Check logical parameters.
logical_list <- list("use_labels" = use_labels,
"stratum.fill.conditional" = stratum.fill.conditional,
"flip" = flip,
"plot.grid" = plot.grid,
"repel" = repel,
"use_geom_flow" = use_geom_flow,
"use_viridis" = use_viridis,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("stratum.width" = stratum.width,
"font.size" = font.size,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("first_group" = first_group,
"last_group" = last_group,
"middle_groups" = middle_groups,
"colors.use" = colors.use,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"font.type" = font.type,
"xlab" = xlab,
"ylab" = ylab,
"fill.by" = fill.by,
"stratum.color" = stratum.color,
"stratum.fill" = stratum.fill,
"alluvium.color" = alluvium.color,
"flow.color" = flow.color,
"label.color" = label.color,
"curve_type" = curve_type,
"viridis.palette" = viridis.palette,
"grid.color" = grid.color,
"grid.type" = grid.type,
"na.value" = na.value,
"legend.position" = legend.position,
"legend.title" = legend.title,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"sequential.palette" = sequential.palette)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
# Check minimum version.
assertthat::assert_that(utils::packageVersion("ggalluvial") >= "0.12.5",
msg = paste0(add_cross(), crayon_body("Please, update "),
crayon_key("ggalluvial"),
crayon_body(" to minimum version "),
crayon_key("0.12.5"),
crayon_body(".")))
#StatStratum <- ggalluvial::StatStratum
`%>%` <- magrittr::`%>%`
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
if (isTRUE(use_labels)){
if (isTRUE(repel)){
func_use <- ggrepel::geom_label_repel
} else if (base::isFALSE(repel)){
func_use <- ggplot2::geom_label
}
} else if (base::isFALSE(use_labels)){
if (isTRUE(repel)){
func_use <- ggrepel::geom_text_repel
} else if (base::isFALSE(repel)){
func_use <- ggplot2::geom_text
}
}
vars.use <- c(first_group)
for (variable in middle_groups){
vars.use <- append(vars.use, variable)
}
vars.use <- append(vars.use, last_group)
for (var in vars.use){
assertthat::assert_that(var %in% colnames(sample@meta.data),
msg = paste0(add_cross(), crayon_body("Please make sure that the variables provided to "),
crayon_key("first_group"),
crayon_body(", "),
crayon_key("middle_groups"),
crayon_body(" and "),
crayon_key("last_group"),
crayon_body(" are "),
crayon_key("metadata variables"),
crayon_body(".")))
assertthat::assert_that(class(sample@meta.data[, var]) %in% c("character", "factor"),
msg = paste0(add_cross(), crayon_body("Please make sure that the variables provided to "),
crayon_key("first_group"),
crayon_body(", "),
crayon_key("middle_groups"),
crayon_body(" and "),
crayon_key("last_group"),
crayon_body(" are of class "),
crayon_key("character"),
crayon_body(" or "),
crayon_key("factor"),
crayon_body(".")))
}
assertthat::assert_that(length(fill.by) == 1,
msg = paste0(add_cross(), crayon_body("Please provide a single value to "),
crayon_key("fill.by"),
crayon_body(".")))
assertthat::assert_that(isTRUE(fill.by %in% vars.use),
msg = paste0(add_cross(), crayon_body("Paramter "),
crayon_key("fill.by"),
crayon_body(" has to be the same as one of the values in "),
crayon_key("first_group"),
crayon_body(", "),
crayon_key("middle_groups"),
crayon_body(" and "),
crayon_key("last_group"),
crayon_body(".")))
suppressMessages({
data <- sample@meta.data %>%
dplyr::select(dplyr::all_of(vars.use)) %>%
dplyr::group_by_at(vars.use) %>%
dplyr::summarise(n = dplyr::n())
})
# COLORS.
if (is.null(colors.use)){
if (is.factor(data[[fill.by]])){
colors.use <- generate_color_scale(levels(data[[fill.by]]), colorblind = colorblind)
} else {
colors.use <- generate_color_scale(sort(unique(data[[fill.by]])), colorblind = colorblind)
}
} else {
check_colors(colors.use)
}
if (is.null(legend.title)){
legend.title = last_group
}
p <- prepare_ggplot_alluvial_plot(data = data,
vars.use = vars.use)
if (isTRUE(use_geom_flow)){
p <- p +
ggalluvial::geom_flow(mapping = ggplot2::aes(fill = .data[[fill.by]]),
color = flow.color)
} else if (base::isFALSE(use_geom_flow)){
p <- p +
ggalluvial::geom_alluvium(mapping = ggplot2::aes(fill = .data[[fill.by]]),
color = alluvium.color,
curve_type = curve_type)
}
if (isTRUE(stratum.fill.conditional)){
p <- p +
ggalluvial::geom_stratum(color = stratum.color,
mapping = ggplot2::aes(fill = .data[[fill.by]]),
width = stratum.width)
} else if (base::isFALSE(stratum.fill.conditional)){
p <- p +
ggalluvial::geom_stratum(color = stratum.color,
fill = stratum.fill,
width = stratum.width)
}
p <- p +
func_use(stat = ggalluvial::StatStratum,
mapping = ggplot2::aes(label = ggplot2::after_stat(stratum)),
color = label.color,
fontface = "bold") +
ggplot2::scale_x_discrete(limits = vars.use)
if (is.null(colors.use)){
p <- p +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title)
} else if (base::isFALSE(use_viridis)){
p <- p +
ggplot2::scale_fill_manual(values = colors.use,
na.value = na.value,
name = legend.title)
}
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.title = ggplot2::element_text(color = "black",
face = axis.title.face),
axis.line.x = if (base::isFALSE(flip)){ggplot2::element_blank()} else {ggplot2::element_line(color = "black")},
axis.line.y = if (base::isFALSE(flip)){ggplot2::element_line(color = "black")} else {ggplot2::element_blank()},
axis.ticks.y = if (base::isFALSE(flip)){ggplot2::element_line(color = "black")} else {ggplot2::element_blank()},
axis.ticks.x = if (base::isFALSE(flip)){ggplot2::element_blank()} else {ggplot2::element_line(color = "black")},
axis.text.y = ggplot2::element_text(color = "black", face = axis.text.face),
axis.text.x = ggplot2::element_text(color = "black", face = axis.text.face),
panel.grid.major = ggplot2::element_blank(),
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
panel.grid = ggplot2::element_blank(),
panel.grid.major.y = if (base::isFALSE(flip)) {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)}} else if (isTRUE(flip)) {ggplot2::element_blank()},
panel.grid.major.x = if (isTRUE(flip)) {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)}} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
strip.text =ggplot2::element_text(color = "black", face = "bold"))
p <- p +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.title,
title.position = "top",
title.hjust = 0.5,
override.aes = list(color = "black",
shape = 22)))
if (isTRUE(flip)){
p <- p + ggplot2::coord_flip()
}
return(p)
}
================================================
FILE: R/do_BarPlot.R
================================================
#' Create Bar Plots.
#'
#' @inheritParams doc_function
#' @param group.by \strong{\code{\link[base]{character}}} | Metadata column to compute the counts of. Has to be either a character or factor column.
#' @param split.by \strong{\code{\link[base]{character}}} | Metadata column to split the values of group.by by. If not used, defaults to the active idents.
#' @param facet.by \strong{\code{\link[base]{character}}} | Metadata column to gather the columns by. This is useful if you have other overarching metadata.
#' @param order \strong{\code{\link[base]{logical}}} | Whether to order the results in descending order of counts.
#' @param order.by \strong{\code{\link[base]{character}}} | When \strong{\code{split.by}} is used, value of \strong{\code{group.by}} to reorder the columns based on its value.
#' @param position \strong{\code{\link[base]{character}}} | Position function from \pkg{ggplot2}. Either stack or fill.
#' @param return_data \strong{\code{\link[base]{logical}}} | Returns a data.frame with the count and proportions displayed in the plot.
#' @param add.n \strong{\code{\link[base]{logical}}} | Whether to add the total counts on top of each bar.
#' @param add.n.face \strong{\code{\link[base]{character}}} | Font face of the labels added by \strong{\code{add.n}}.
#' @param add.n.size \strong{\code{\link[base]{numeric}}} | Size of the labels
#' @param add.n.expand \strong{\code{\link[base]{numeric}}} | Vector of two numerics representing the start and end of the scale. Minimum should be 0 and max should be above 1. This basically expands the Y axis so that the labels fit when \strong{\code{flip = TRUE}}.
#' \itemize{
#' \item \emph{\code{stack}}: Set the bars side by side, displaying the total number of counts. Uses \link[ggplot2]{position_stack}.
#' \item \emph{\code{fill}}: Set the bars on top of each other, displaying the proportion of counts from the total that each group represents. Uses \link[ggplot2]{position_fill}.
#' }
#' @return A ggplot2 object containing a Bar plot.
#' @export
#'
#' @example /man/examples/examples_do_BarPlot.R
do_BarPlot <- function(sample,
group.by,
order = FALSE,
add.n = FALSE,
add.n.face = "bold",
add.n.expand = c(0, 1.15),
add.n.size = 4,
order.by = NULL,
split.by = NULL,
facet.by = NULL,
position = "stack",
font.size = 14,
font.type = "sans",
legend.position = "bottom",
legend.title = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
axis.text.x.angle = 45,
xlab = NULL,
ylab = NULL,
colors.use = NULL,
colorblind = FALSE,
flip = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
plot.grid = FALSE,
grid.color = "grey75",
grid.type = "dashed",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
strip.text.face = "bold",
return_data = FALSE) {
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_BarPlot")
check_Seurat(sample)
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
# Check logical parameters.
logical_list <- list("order" = order,
"flip" = flip,
"plot.grid" = plot.grid,
"legend.byrow" = legend.byrow,
"add.n" = add.n,
"return_data" = return_data,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"axis.text.x.angle" = axis.text.x.angle,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow,
"add.n.expand" = add.n.expand)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"split.by" = split.by,
"facet.by" = facet.by,
"order.by" = order.by,
"position" = position,
"font.type" = font.type,
"legend.position" = legend.position,
"legend.title" = legend.title,
"xlab" = xlab,
"ylab" = ylab,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"grid.color" = grid.color,
"grid.type" = grid.type,
"legend.title" = legend.title,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
# Checks
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(grid.color, parameter_name = "grid.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(strip.text.face, parameter_name = "strip.text.face")
# Get the general table.
assertthat::assert_that(class(sample@meta.data[, group.by]) %in% c("character", "factor"),
msg = paste0(add_cross(), crayon_body("Please provide to "),
crayon_key("feature"),
crayon_body(" a "),
crayon_key(" metadta categorical "),
crayon_body(" variable.")))
assertthat::assert_that(base::isFALSE(position == "fill" & is.null(split.by)),
msg = paste0(add_cross(),
crayon_body("Please use "),
crayon_key("position = fill"),
crayon_body(" alongisde "),
crayon_key("split.by"),
crayon_body(".")))
assertthat::assert_that(base::isFALSE(position == "stack" & isTRUE(order) & !is.null(order.by)),
msg = paste0(add_cross(),
crayon_body("Please use "),
crayon_key("order.by"),
crayon_body(" alongisde "),
crayon_key("position = fill"),
crayon_body(".")))
assertthat::assert_that(base::isFALSE(position == "fill" & isTRUE(order) & is.null(order.by)),
msg = paste0(add_cross(),
crayon_body("Please use "),
crayon_key("order.by"),
crayon_body(" alongisde "),
crayon_key("position = fill"),
crayon_body(".")))
if (is.null(colors.use)){
colors.use <- generate_color_scale(names_use = if (is.factor(sample@meta.data[, group.by])) {levels(sample@meta.data[, group.by])} else {sort(unique(sample@meta.data[, group.by]))}, colorblind = colorblind)
} else {
check_colors(colors.use, parameter_name = "colors.use")
check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = group.by)
colors.use <- colors.use[unique(sample@meta.data[, group.by])]
}
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
data <- sample@meta.data %>%
tibble::as_tibble() %>%
dplyr::select(dplyr::all_of(c(group.by, split.by, facet.by)))
if (isTRUE(order)){
if (is.null(order.by)){
order.use <- sample@meta.data %>%
tibble::as_tibble() %>%
dplyr::select(dplyr::all_of(c(group.by, split.by))) %>%
dplyr::group_by(.data[[group.by]]) %>%
dplyr::summarise("n" = dplyr::n()) %>%
dplyr::arrange(if(base::isFALSE(flip)){dplyr::desc(.data[["n"]])} else {.data[["n"]]}) %>%
dplyr::pull(.data[[group.by]]) %>%
as.character()
data <- data %>%
dplyr::mutate("{group.by}" := factor(as.character(.data[[group.by]]),
levels = order.use))
} else {
order.use <- sample@meta.data %>%
tibble::as_tibble() %>%
dplyr::mutate(dplyr::across(dplyr::all_of(c(group.by, split.by)), as.character),
"count" = 1) %>%
tidyr::complete(.data[[split.by]], .data[[group.by]], explicit = FALSE) %>%
dplyr::group_by(.data[[split.by]], .data[[group.by]]) %>%
dplyr::summarise("n" = sum(.data$count, na.rm = TRUE),
"{split.by}" := unique(.data[[split.by]])) %>%
dplyr::reframe("freq" = .data$n / sum(.data$n),
"{split.by}" := unique(.data[[split.by]]),
"{group.by}" := unique(.data[[group.by]])) %>%
dplyr::filter(.data[[group.by]] == order.by) %>%
dplyr::arrange(if(base::isFALSE(flip)){dplyr::desc(.data[["freq"]])} else {.data[["freq"]]}) %>%
dplyr::pull(.data[[split.by]]) %>%
as.character()
data <- data %>%
dplyr::mutate("{split.by}" := factor(as.character(.data[[split.by]]),
levels = order.use))
}
}
if (isTRUE(add.n)){
assertthat::assert_that(position == "fill",
msg = paste0(add_cross(),
crayon_body("Parameter "),
crayon_key("add.n"),
crayon_body(" can only be used alongside "),
crayon_key("position = fill"),
crayon_body(".")))
if (is.null(split.by) & !is.null(group.by)){
# nocov start
data.n <- data %>%
dplyr::group_by(.data[[group.by]]) %>%
dplyr::summarise(n = dplyr::n()) %>%
dplyr::mutate(n = paste0("n = ", .data$n))
# nocov end
} else if (!is.null(split.by) & !is.null(group.by)){
data.n <- data %>%
dplyr::group_by(.data[[split.by]]) %>%
dplyr::summarise(n = dplyr::n()) %>%
dplyr::mutate(n = paste0("n = ", .data$n))
}
max.char <- max(vapply(data.n$n, nchar, FUN.VALUE = integer(1)))
data.n$n <- vapply(data.n$n, function(x){return(paste0(x, paste(rep(" ", (max.char - nchar(x))), collapse = "")))}, FUN.VALUE = character(1))
}
if (is.null(split.by)){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data[[group.by]],
fill = .data[[group.by]]))
} else {
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data[[split.by]],
fill = .data[[group.by]]))
}
if (is.null(xlab)){
if (!is.null(group.by) & is.null(split.by)){
xlab <- group.by
} else if (!is.null(group.by) & !is.null(split.by)){
xlab <- split.by
}
}
if (is.null(ylab)){
ylab <- ifelse(position == "stack", "Count", "Proportion")
}
if (is.null(legend.title)){
if (position == "stack"){
if (is.null(split.by)){
legend.title <- NULL
} else {
legend.title <- split.by
}
} else {
legend.title <- group.by
}
}
p <- p +
ggplot2::stat_count(geom = "bar", position = position, color = "black")
if (isTRUE(add.n)){
if (is.null(split.by) & !is.null(group.by)){
# nocov start
p <- p +
ggplot2::geom_text(data = data.n,
mapping = ggplot2::aes(x = .data[[group.by]],
y = ifelse(base::isFALSE(flip), 1.03, 1.01),
label = .data$n,
fill = NULL),
hjust = ifelse(isTRUE(flip), 0, 0.5),
fontface = "plain",
size = add.n.size)
# nocov end
} else if (!is.null(split.by) & !is.null(group.by)){
p <- p +
ggplot2::geom_text(data = data.n,
mapping = ggplot2::aes(x = .data[[split.by]],
y = ifelse(base::isFALSE(flip), 1.03, 1.01),
label = .data$n,
fill = NULL),
hjust = ifelse(isTRUE(flip), 0, 0.5),
fontface = "plain",
size = add.n.size)
}
p <- p +
ggplot2::scale_y_continuous(limits = add.n.expand, labels = c("0", "0.25", "0.5", "0.75", "1"), breaks = c(0, 0.25, 0.5, 0.75, 1))
}
if (isTRUE(flip)){
p <- p + ggplot2::coord_flip()
}
if (!is.null(facet.by)){
if (base::isFALSE(flip)){
p <- p +
ggplot2::facet_grid(cols = ggplot2::vars(.data[[facet.by]]),
scales = "free",
space = "free",
drop = TRUE)
} else {
p <- p +
ggplot2::facet_grid(rows = ggplot2::vars(.data[[facet.by]]),
scales = "free",
space = "free",
drop = TRUE)
}
}
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::scale_fill_manual(values = colors.use) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.title,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.title = ggplot2::element_text(color = "black",
face = axis.title.face),
panel.grid.major.y = if (base::isFALSE(flip)) {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)}} else if (isTRUE(flip)) {ggplot2::element_blank()},
panel.grid.major.x = if (isTRUE(flip)) {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)}} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
axis.line.x = if (base::isFALSE(flip)) {ggplot2::element_line(color = "black")} else if (isTRUE(flip)) {ggplot2::element_blank()},
axis.line.y = if (isTRUE(flip)) {ggplot2::element_line(color = "black")} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(color = "black", face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
strip.text = ggplot2::element_text(color = "black", face = strip.text.face),
strip.background = ggplot2::element_blank())
if (isTRUE(return_data)){
data <- sample@meta.data %>%
tibble::as_tibble() %>%
dplyr::mutate(dplyr::across(dplyr::all_of(c(group.by, split.by)), as.character),
"count" = 1) %>%
tidyr::complete(.data[[split.by]], .data[[group.by]], explicit = FALSE) %>%
dplyr::group_by(.data[[split.by]], .data[[group.by]]) %>%
dplyr::summarise("n" = sum(.data$count, na.rm = TRUE),
"{split.by}" := unique(.data[[split.by]])) %>%
dplyr::reframe("n" = .data$n,
"freq" = .data$n / sum(.data$n),
"{split.by}" := unique(.data[[split.by]]),
"{group.by}" := unique(.data[[group.by]]))
return(list("Plot" = p,
"Data" = data))
} else {
return(p)
}
}
================================================
FILE: R/do_BeeSwarmPlot.R
================================================
#' Generate BeeSwarm plots of ranked cells colored by gene expression or metadata.
#'
#' This function ranks cells along a continuous feature and displays them as a
#' bee swarm, colored by a second variable. Useful for visualizing continuous
#' enrichment scores across cell populations.
#'
#' @inheritParams doc_function
#' @param feature_to_rank \strong{\code{\link[base]{character}}} | Feature for which the cells are going to be ranked. Ideal case is that this feature is stored as a metadata column.
#' @param continuous_feature \strong{\code{\link[base]{logical}}} | Is the feature to rank and color for continuous? I.e: an enrichment score.
#' @param order \strong{\code{\link[base]{logical}}} | Whether to reorder the groups based on the median of the ranking.
#' @param remove_x_axis,remove_y_axis \strong{\code{\link[base]{logical}}} | Remove X axis labels and ticks from the plot.
#' @return A ggplot2 object containing a Bee Swarm plot.
#' @export
#'
#' @example /man/examples/examples_do_BeeSwarmPlot.R
do_BeeSwarmPlot <- function(sample,
feature_to_rank,
group.by = NULL,
assay = NULL,
reduction = NULL,
slot = NULL,
continuous_feature = FALSE,
order = FALSE,
colors.use = NULL,
colorblind = FALSE,
legend.title = NULL,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.icon.size = 4,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
font.size = 14,
font.type = "sans",
remove_x_axis = FALSE,
remove_y_axis = FALSE,
flip = FALSE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
verbose = TRUE,
raster = FALSE,
raster.dpi = 300,
plot_cell_borders = TRUE,
border.size = 1.5,
border.color = "black",
pt.size = 2,
min.cutoff = NA,
max.cutoff = NA,
na.value = "grey75",
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_BeeSwarmPlot")
`%>%` <- magrittr::`%>%`
# Check ggbeeswarm version:
# nocov start
if(utils::packageVersion("ggbeeswarm") < "0.7.1"){
warning(paste0(add_warning(), crayon_body("Due to recent updates in ggbeeswarm package, some internal interaction with ggplot2 have changed. Please update ggbeeswarm and ggplot2 to ensure correct plotting."), call. = FALSE))
}
# nocov end
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check the assay.
out <- check_and_set_assay(sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
# Check the reduction.
reduction <- check_and_set_reduction(sample = sample, reduction = reduction)
# Check logical parameters.
logical_list <- list("continuous_feature" = continuous_feature,
"remove_x_axis" = remove_x_axis,
"remove_y_axis" = remove_y_axis,
"flip" = flip,
"verbose" = verbose,
"raster" = raster,
"plot_cell_borders" = plot_cell_borders,
"use_viridis" = use_viridis,
"order" = order,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"raster.dpi" = raster.dpi,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"pt.size" = pt.size,
"border.size" = border.size,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"viridis.direction" = viridis.direction,
"legend.ncol" = legend.ncol,
"legend.icon.size" = legend.icon.size,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("legend.position" = legend.position,
"legend.title" = legend.title,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"feature_to_rank" = feature_to_rank,
"group.by" = group.by,
"ylab" = ylab,
"xlab" = xlab,
"slot" = slot,
"viridis.palette" = viridis.palette,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"border.color" = border.color,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"na.value" = na.value)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check slot.
slot <- if(is.null(slot)){"data"} else {slot}
# Check the colors provided to legend.framecolor and legend.tickcolor and border color.
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(border.color, parameter_name = "border.color")
check_colors(na.value, parameter_name = "na.value")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
assertthat::assert_that(length(feature_to_rank) == 1,
msg = paste0(crayon_body("Please provide only "),
crayon_key("one feature"),
crayon_body(" to "),
crayon_key("feature_to_rank"),
crayon_body(".")))
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
# Assign legend title.
if (is.null(legend.title)){
legend.title <- if (isTRUE(continuous_feature)) {feature_to_rank} else {group.by}
}
dim_colnames <- check_feature(sample = sample, features = feature_to_rank, dump_reduction_names = TRUE)
if (feature_to_rank %in% colnames(sample@meta.data)) {
sample@meta.data$rank_me <- sample@meta.data[, feature_to_rank]
sample@meta.data$rank <- rank(sample@meta.data$rank_me)
} else if (feature_to_rank %in% rownames(sample)){
if (utils::packageVersion("Seurat") < "5.0.0"){
sample@meta.data$rank_me <- SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = slot)[feature_to_rank, ]
} else {
sample@meta.data$rank_me <- SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = slot)[feature_to_rank, ]
}
sample@meta.data$rank <- rank(sample@meta.data$rank_me)
} else if (feature_to_rank %in% dim_colnames){
for(red in Seurat::Reductions(object = sample)){
if (feature_to_rank %in% colnames(sample@reductions[[red]][[]])){
reduction <- red
sample@meta.data$rank_me <- sample@reductions[[reduction]][[]][, feature_to_rank]
sample@meta.data$rank <- rank(sample@meta.data$rank_me)
}
}
}
# Compute the ranking
sample@meta.data$ranked_groups <- factor(sample@meta.data[, group.by], levels = sort(unique(sample@meta.data[, group.by])))
if (isTRUE(order)){
# Get median rank by group.
order <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c("ranked_groups", "rank"))) %>%
dplyr::group_by(.data$ranked_groups) %>%
dplyr::summarise("median" = stats::median(.data$rank, na.rm = TRUE)) %>%
dplyr::arrange(dplyr::desc(.data$median)) %>%
dplyr::pull(.data$ranked_groups) %>%
as.character()
sample@meta.data$ranked_groups <- factor(sample@meta.data$ranked_groups, levels = rev(order))
}
color_by <- ifelse(continuous_feature == TRUE, "rank_me", "ranked_groups")
# Compute the limits.
if (isTRUE(continuous_feature)){
data <- sample$rank_me
range.data <- c(min(data, na.rm = TRUE),
max(data, na.rm = TRUE))
scale.setup <- compute_scales(sample = NULL,
feature = feature_to_rank,
assay = NULL,
reduction = NULL,
slot = NULL,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = FALSE,
from_data = TRUE,
limits.use = range.data)
sample$rank_me[sample$rank_me < min.cutoff] <- min.cutoff
sample$rank_me[sample$rank_me > max.cutoff] <- max.cutoff
}
p <- ggplot2::ggplot(sample@meta.data,
mapping = ggplot2::aes(x = .data[["rank"]],
y = .data[["ranked_groups"]],
color = !!rlang::sym(color_by)))
# Add raster layer if desired.
if (isTRUE(raster)){
p <- p +
ggrastr::geom_quasirandom_rast(raster.dpi = raster.dpi,
size = pt.size)
} else {
p <- p +
ggbeeswarm::geom_quasirandom(size = pt.size)
}
p <- p +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
panel.grid = ggplot2::element_blank(),
plot.title.position = "plot",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
axis.title.x = ggplot2::element_text(face = axis.title.face),
axis.title.y = ggplot2::element_text(face = axis.title.face, angle = 90),
axis.ticks.y = if(base::isFALSE(flip)){ggplot2::element_line(color = "black")} else {ggplot2::element_blank()},
axis.ticks.x = if(isTRUE(flip)){ggplot2::element_line(color = "black")} else {ggplot2::element_blank()},
axis.text = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.line = ggplot2::element_line(color = "black"),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
if (continuous_feature == TRUE){
p <- p +
ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "color",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
} else if (continuous_feature == FALSE) {
if (is.null(colors.use)){
colors.use <- generate_color_scale(levels(sample), colorblind = colorblind)
} else {
colors.use <- check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = group.by)
}
# Adapt the legend to categorical variables.
if (is.null(legend.title)){
legend.title <- "Groups"
}
p <- p +
ggplot2::scale_color_manual(values = colors.use) +
ggplot2::guides(color = ggplot2::guide_legend(title = legend.title,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
override.aes = list(size = legend.icon.size))) +
ggplot2::theme(legend.position = legend.position)
}
if (base::isTRUE(remove_x_axis)){
p <- p +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.ticks.x = ggplot2::element_blank())
}
if (base::isTRUE(remove_y_axis)){
p <- p +
ggplot2::theme(axis.text.y = ggplot2::element_blank(),
axis.ticks.y = ggplot2::element_blank())
}
if (base::isTRUE(flip)){
p <- p +
ggplot2::coord_flip() +
ggplot2::theme(axis.text.y = ggplot2::element_blank(),
axis.ticks.y = ggplot2::element_blank()) +
ggplot2::xlab(ifelse(is.null(ylab), paste0("Ranking of ", feature_to_rank), ylab)) +
ggplot2::ylab(if(is.null(xlab)) {group.by} else {xlab})
} else {
p <- p +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.ticks.x = ggplot2::element_blank()) +
ggplot2::xlab(ifelse(is.null(xlab), paste0("Ranking of ", feature_to_rank), xlab)) +
ggplot2::ylab(if(is.null(ylab)) {group.by} else {ylab})
}
if (isTRUE(plot_cell_borders)){
# Generate base layer.
if (isTRUE(raster)){
base_layer <- ggrastr::geom_quasirandom_rast(data = sample@meta.data,
mapping = ggplot2::aes(x = .data[["rank"]],
y = .data[["ranked_groups"]]),
raster.dpi = raster.dpi,
color = border.color,
size = pt.size * border.size,
show.legend = FALSE)
} else if (base::isFALSE(raster)){
base_layer <-ggbeeswarm::geom_quasirandom(data = sample@meta.data,
mapping = ggplot2::aes(x = .data[["rank"]],
y = .data[["ranked_groups"]]),
color = border.color,
size = pt.size * border.size,
show.legend = FALSE)
}
p[["layers"]] <- append(base_layer, p[["layers"]])
}
return(p)
}
================================================
FILE: R/do_BoxPlot.R
================================================
#' Generate Box Plots.
#'
#' @inheritParams doc_function
#' @inheritParams ggsignif::geom_signif
#'
#' @param boxplot.line.color \strong{\code{\link[base]{character}}} | Color of the borders of the boxplots if use_silhouette is FALSE.
#' @param outlier.color \strong{\code{\link[base]{character}}} | Color of the outlier dots.
#' @param outlier.alpha \strong{\code{\link[base]{numeric}}} | Alpha applied to the outliers.
#' @param boxplot.linewidth \strong{\code{\link[base]{numeric}}} | Width of the lines in the boxplots. Also controls the lines of the tests applied if use_test is set to true.
#' @param boxplot.width \strong{\code{\link[base]{numeric}}} | Width of the boxplots.
#' @param use_silhouette \strong{\code{\link[base]{logical}}} | Whether to color the borders of the boxplots instead of the inside area.
#' @param use_test \strong{\code{\link[base]{logical}}} | Whether to apply a statistical test to a given pair of elements. Can not be used alongside split.by.
#'
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_BoxPlot.R
do_BoxPlot <- function(sample,
feature,
group.by = NULL,
split.by = NULL,
assay = NULL,
slot = "data",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
colors.use = NULL,
colorblind = FALSE,
na.value = "grey75",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
legend.title = NULL,
legend.title.position = "top",
legend.position = "bottom",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
boxplot.line.color = "black",
outlier.color = "black",
outlier.alpha = 0.5,
boxplot.linewidth = 0.5,
boxplot.width = NULL,
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
flip = FALSE,
order = FALSE,
use_silhouette = FALSE,
use_test = FALSE,
comparisons = NULL,
test = "wilcox.test",
map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05),
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_BoxPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check the assay.
out <- check_and_set_assay(sample = sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
# Check slot.
slot <- if(is.null(slot)){"data"} else {slot}
# Check logical parameters.
logical_list <- list("flip" = flip,
"plot.grid" = plot.grid,
"order" = order,
"use_silhouette" = use_silhouette,
"legend.byrow" = legend.byrow,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"outlier.alpha" = outlier.alpha,
"boxplot.linewidth" = boxplot.linewidth,
"boxplot.width" = boxplot.width,
"axis.text.x.angle" = axis.text.x.angle,
"legend.nrow" = legend.nrow,
"legend.ncol" = legend.ncol)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("feature" = feature,
"group.by" = group.by,
"split.by" = split.by,
"assay" = assay,
"slot" = slot,
"font.type" = font.type,
"colors.use" = colors.use,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"xlab" = xlab,
"ylab" = ylab,
"legend.title" = legend.title,
"legend.title.position" = legend.title.position,
"legend.position" = legend.position,
"boxplot.line.color" = boxplot.line.color,
"outlier.color" = outlier.color,
"grid.color" = grid.color,
"grid.type" = grid.type,
"comparisons" = comparisons,
"test" = test,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check the feature.
feature <- check_feature(sample = sample, features = feature, permissive = TRUE)
`%>%` <- magrittr::`%>%`
check_colors(na.value, parameter_name = "na.value")
check_colors(boxplot.line.color, parameter_name = "boxplot.line.color")
check_colors(outlier.color, parameter_name = "outlier.color")
check_colors(grid.color, parameter_name = "grid.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
if (is.null(legend.title)){
if (is.null(split.by)){
if (is.null(group.by)) {
legend.title <- "Groups"
} else {
legend.title <- group.by
}
} else {
legend.title <- split.by
}
}
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
# Custom function to draw black border in legend.
# Define the custom draw_key function
draw_key_square_black_border <- function(data,
params,
size) {
grid::rectGrob(width = grid::unit(1, "npc"), # Full size of the key (square)
height = grid::unit(1, "npc"),
gp = grid::gpar(col = "black", # Black border
fill = ggplot2::alpha(data$fill, data$alpha), # Fill with specified color and alpha
lwd = 1) # Border line width
)
}
if (is.null(colors.use)){
if (is.null(split.by)){
colors.use <- generate_color_scale(names_use = if (is.factor(sample@meta.data[, group.by])) {
levels(sample@meta.data[, group.by])
} else {
sort(unique(sample@meta.data[, group.by]))
}, colorblind = colorblind)
} else {
colors.use <- generate_color_scale(names_use = if (is.factor(sample@meta.data[, split.by])) {levels(sample@meta.data[, split.by])} else {sort(unique(sample@meta.data[, split.by]))}, colorblind = colorblind)
}
} else {
check_colors(colors.use, parameter_name = "colors.use")
check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = ifelse(!is.null(split.by), split.by, group.by))
}
data <- get_data_column_in_context(sample,
feature = feature,
assay = assay,
slot = slot,
group.by = group.by,
split.by = split.by)
if (isTRUE(order) & is.null(split.by)){
data <- data %>%
dplyr::mutate("group.by" = factor(as.character(.data[["group.by"]]),
levels = {data %>%
tibble::as_tibble() %>%
dplyr::group_by(.data[["group.by"]]) %>%
dplyr::summarise("median" = stats::median(.data[["feature"]], na.rm = TRUE)) %>%
dplyr::arrange(if(base::isFALSE(flip)){dplyr::desc(.data[["median"]])} else {.data[["median"]]}) %>%
dplyr::pull(.data[["group.by"]]) %>%
as.character()}))
}
if (isTRUE(order)){
assertthat::assert_that(is.null(split.by),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("split.by"),
crayon_body(" cannot be used alonside "),
crayon_key("order"),
crayon_body(".")))
}
if (!is.null(split.by)){
assertthat::assert_that(base::isFALSE(order),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("split.by"),
crayon_body(" cannot be used alonside "),
crayon_key("order"),
crayon_body(".")))
}
if (!is.null(map_signif_level)){
assertthat::assert_that(base::isTRUE(is.logical(map_signif_level) | is.numeric(map_signif_level)),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("map_signif_level"),
crayon_body(" needs to be a "),
crayon_key("logical"),
crayon_body(" or a "),
crayon_key("custom mapping"),
crayon_body(" such as "),
crayon_key('c("***" = 0.001, "**" = 0.01, "*" = 0.05)'),
crayon_body(".")))
}
if (isTRUE(use_silhouette) & is.null(split.by)){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data[["group.by"]],
y = .data[["feature"]],
color = .data[["group.by"]])) +
ggplot2::scale_color_manual(values = colors.use, na.value = na.value) +
ggplot2::geom_boxplot(outlier.color = outlier.color,
outlier.alpha = outlier.alpha,
width = boxplot.width,
lwd = boxplot.linewidth,
fatten = 1,
na.rm = TRUE) +
ggplot2::guides(color = ggplot2::guide_legend(title = legend.title,
title.position = legend.title.position,
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow))
} else if (isTRUE(use_silhouette) & !is.null(split.by)){
stop(paste0(add_cross(), crayon_body("Parameter "), crayon_key("use_silhouette"), crayon_body("can not be used alongside "), crayon_key("split.by"), crayon_body(".")), call. = FALSE)
} else if (base::isFALSE(use_silhouette)){
if (is.null(split.by)){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data[["group.by"]],
y = .data[["feature"]],
fill = .data[["group.by"]]))
} else {
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data[["group.by"]],
y = .data[["feature"]],
fill = .data[["split.by"]]))
}
p <- p +
ggplot2::scale_fill_manual(values = colors.use, na.value = na.value) +
ggplot2::geom_boxplot(color = boxplot.line.color,
outlier.color = outlier.color,
outlier.alpha = outlier.alpha,
width = boxplot.width,
lwd = boxplot.linewidth,
fatten = 1,
key_glyph = draw_key_square_black_border,
na.rm = TRUE) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.title,
title.position = legend.title.position,
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow))
}
p <- p +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::xlab(if (is.null(xlab)) {"Groups"} else (xlab)) +
ggplot2::ylab(if (is.null(ylab)) {feature} else (ylab)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.title = ggplot2::element_text(color = "black",
face = axis.title.face),
axis.line.x = if (base::isFALSE(flip)) {ggplot2::element_line(color = "black")} else if (isTRUE(flip)) {ggplot2::element_blank()},
axis.line.y = if (isTRUE(flip)) {ggplot2::element_line(color = "black")} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(color = "black", face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
panel.grid.major = ggplot2::element_blank(),
panel.grid.major.y = if (base::isFALSE(flip)) {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)}} else if (isTRUE(flip)) {ggplot2::element_blank()},
panel.grid.major.x = if (isTRUE(flip)) {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)}} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
strip.text =ggplot2::element_text(color = "black", face = "bold"))
if (isTRUE(flip)){
p <- p + ggplot2::coord_flip()
}
if (isTRUE(use_test) & is.null(split.by)){
if (!(is.null(comparisons))){
p <- p +
ggsignif::geom_signif(comparisons = comparisons,
map_signif_level = map_signif_level,
test = test,
color = "black",
size = boxplot.linewidth,
textsize = font.size - 8,
family = font.type,
fontface = "bold")
if (!is.logical(map_signif_level)){
caption <- c()
for (i in seq_len(length(map_signif_level))){caption <- append(caption, paste0(names(map_signif_level)[i], " = ", format(map_signif_level[i], scientific = FALSE)))}
caption <- paste(caption, collapse = ", ")
p <- p + ggplot2::labs(caption = caption)
}
} else {
stop(paste0(add_cross(), crayon_body("Please provide the pair of groups to test.")), call. = FALSE)
}
} else if (isTRUE(use_test) & !is.null(split.by)){
stop(paste0(add_cross(), crayon_body("Tests can not be made if "), crayon_key("split.by"), crayon_body(" is set.")), call. = FALSE)
}
return(p)
}
================================================
FILE: R/do_CNVHeatmap.R
================================================
#' Display CNV scores from inferCNV as Feature Plots.
#'
#'
#' @inheritParams doc_function
#' @param infercnv_object \strong{\code{\link[infercnv]{infercnv}}} | Output inferCNV object run on the same Seurat object.
#' @param using_metacells \strong{\code{\link[base]{logical}}} | Whether inferCNV was run using metacells or not.
#' @param metacell_mapping \strong{\code{\link[SCpubr]{named_vector}}} | Vector or cell - metacell mapping.
#' @param chromosome_locations \strong{\code{\link[tibble]{tibble}}} | Tibble containing the chromosome regions to use. Can be obtained using \strong{\code{utils::data("human_chr_locations", package = "SCpubr")}}.
#' @param include_chr_arms \strong{\code{\link[base]{logical}}} | Whether the output heatmap should also include chromosome arms or just whole chromosomes.
#'
#' @return A list containing Feature Plots for different chromosome regions and corresponding dot plots by groups..
#' @export
#'
#' @example man/examples/examples_do_CNVHeatmap.R
do_CNVHeatmap <- function(sample,
infercnv_object,
chromosome_locations,
group.by = NULL,
using_metacells = FALSE,
metacell_mapping = NULL,
include_chr_arms = FALSE,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
legend.type = "colorbar",
legend.position = "bottom",
legend.length = 20,
legend.width = 1,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
font.size = 14,
pt.size = 1,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = TRUE,
legend.title = NULL,
na.value = "grey75",
viridis.palette = "G",
viridis.direction = 1,
verbose = FALSE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = -1,
use_viridis = TRUE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
flip = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests("do_CNVHeatmap")
# Check logical parameters.
logical_list <- list("using_metacells" = using_metacells,
"enforce_symmetry" = enforce_symmetry,
"use_viridis" = use_viridis,
"include_chr_arms" = include_chr_arms,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"legend.length" = legend.length,
"legend.width" = legend.width,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"pt.size" = pt.size,
"viridis.direction" = viridis.direction,
"axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"legend.type" = legend.type,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"font.type" = font.type,
"legend.title" = legend.title,
"viridis.palette" = viridis.palette,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
`:=` <- rlang::`:=`
`%>%` <- magrittr::`%>%`
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(na.value, parameter_name = "na.value")
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
chromosome_list <- c(as.character(seq(1, 22)))
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
# Retrieve the genes.
genes <- infercnv_object@gene_order
# Retrieve chr coordinates.
chr_locations <- chromosome_locations
# This list will contain all the outputs.
return_list <- list()
scores.assay <- data.frame(row.names = colnames(sample))
skipped_chr <- FALSE
for (chromosome in chromosome_list){
# Retrieve chr locations of the chromosome.
locations <- chr_locations %>%
dplyr::filter(.data[["chr"]] == chromosome)
events <- if(base::isTRUE(include_chr_arms)) {c("p", "q")} else {"whole"}
for (chr_arm in events){
if (chr_arm != "whole"){
# Retrieve the start.
start <- locations %>%
dplyr::filter(.data[["arm"]] == chr_arm) %>%
dplyr::pull(start)
# Retrieve the end.
end <- locations %>%
dplyr::filter(.data[["arm"]] == chr_arm) %>%
dplyr::pull(end)
# Retrieve the genes present in the chromosome arm.
genes_use <- rownames(genes %>%
dplyr::filter(.data[["chr"]] == paste0("chr", chromosome),
stop <= end))
} else {
# Retrieve the start.
start <- locations %>%
dplyr::filter(.data[["arm"]] == "p") %>%
dplyr::pull(start)
# Retrieve the end.
end <- locations %>%
dplyr::filter(.data[["arm"]] == "q") %>%
dplyr::pull(end)
# Retrieve the genes present in the chromosome arm.
genes_use <- rownames(genes %>%
dplyr::filter(.data[["chr"]] == paste0("chr", chromosome)))
}
# Retrieve the CNV scores from the inferCNV object.
CNV_scores <- infercnv_object@expr.data
# Make it at least 2 genes in the object (this will only be applicable in VERY LOW QUALITY DATASETS)
if (sum(genes_use %in% rownames(CNV_scores)) > 1){
# Filter the scores for only the genes in the chromosome arm.
CNV_scores <- CNV_scores[genes_use[genes_use %in% rownames(CNV_scores)], ]
scores_name <- if (chr_arm != "whole"){paste0(chromosome, chr_arm)} else {chromosome}
CNV_scores_final <- tibble::tibble(!!scores_name := colMeans(CNV_scores),
"cells" = colnames(CNV_scores))
# If metacells were used.
if (isTRUE(using_metacells)){
sample[["metacell_mapping"]] <- metacell_mapping
scores.assay[[scores_name]] <- sample@meta.data %>%
dplyr::mutate("cells" = colnames(sample)) %>%
dplyr::left_join(y = {sample@meta.data %>%
dplyr::select(dplyr::all_of("metacell_mapping")) %>%
tibble::rownames_to_column(var = "cells") %>%
dplyr::left_join(y = {CNV_scores_final %>% dplyr::rename("metacell_mapping" = dplyr::all_of("cells"))},
by = "metacell_mapping") %>%
dplyr::select(-dplyr::all_of("metacell_mapping"))},
by = "cells") %>%
tibble::column_to_rownames(var = "cells") %>%
dplyr::select(.env$scores_name)
# If no metacells were used.
} else if (base::isFALSE(using_metacells)){
scores.assay[[scores_name]] <- CNV_scores_final[, scores_name]
}
} else {
skipped_chr <- TRUE
#nocov start
if(isTRUE(verbose)){message(paste0(add_info(), "Your sample has only one gene in ", chromosome, chr_arm, ". Skipping this chromosome arm."))}
#nocov end
}
}
}
# Generate an assay.
assay <- scores.assay %>%
t() %>%
Seurat::CreateAssayObject(.)
sample@assays$CNV_scores <- assay
Seurat::DefaultAssay(sample) <- "CNV_scores"
sample@assays$CNV_scores@key <- "CNV_scores_"
list.data <- list()
for (group in group.by){
if (utils::packageVersion("Seurat") < "5.0.0"){
data.use <- SeuratObject::GetAssayData(object = sample,
assay = "CNV_scores",
slot = "data")
} else {
data.use <- SeuratObject::GetAssayData(object = sample,
assay = "CNV_scores",
layer = "data")
}
data.use <- data.use %>%
as.matrix() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
dplyr::left_join(y = {sample@meta.data %>%
tibble::rownames_to_column(var = "Cell") %>%
dplyr::select(dplyr::all_of(c("Cell", group)))},
by = "Cell") %>%
tidyr::pivot_longer(cols = -dplyr::all_of(c("Cell", group)),
values_to = "CNV_score",
names_to = "Event") %>%
dplyr::group_by(.data[[group]], .data$Event) %>%
dplyr::summarise("mean" = mean(.data$CNV_score, na.rm = TRUE))
# Fix the out of bound values.
if (!is.na(min.cutoff)){
data.use <- data.use %>%
dplyr::mutate("mean" = ifelse(.data$mean < min.cutoff, min.cutoff, .data$mean))
}
if (!is.na(max.cutoff)){
data.use <- data.use %>%
dplyr::mutate("mean" = ifelse(.data$mean > max.cutoff, max.cutoff, .data$mean))
}
if (base::isTRUE(include_chr_arms)){
events <- c(as.character(seq(1, 22)), vapply(seq(1, 22), function(x){return(c(paste0(x, "p"), paste0(x, "q")))}, FUN.VALUE = character(2)))
} else {
events <- c(as.character(seq(1, 22)))
}
if (base::isFALSE(flip)){
factor.levels <- events[events %in% unique(data.use$Event)]
} else {
factor.levels <- rev(events[events %in% unique(data.use$Event)])
}
data.use <- data.use %>%
dplyr::mutate("Event" = factor(.data$Event, levels = factor.levels))
list.data[[group]][["data"]] <- data.use
}
# Compute limits.
min.vector <- NULL
max.vector <- NULL
for (group in group.by){
data.limits <- list.data[[group]][["data"]]
min.vector <- append(min.vector, min(data.limits$mean, na.rm = TRUE))
max.vector <- append(max.vector, max(data.limits$mean, na.rm = TRUE))
}
# Get the absolute limits of the datasets.
limits <- c(min(min.vector, na.rm = TRUE),
max(max.vector, na.rm = TRUE))
# Compute overarching scales for all heatmaps.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = assay,
reduction = NULL,
slot = "data",
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = TRUE,
from_data = TRUE,
limits.use = limits,
center_on_value = TRUE,
value_center = 1)
list.plots <- list()
if (base::isFALSE(flip)){
values.use <- rev(group.by)
} else {
values.use <- group.by
}
for (group in values.use){
data <- list.data[[group]][["data"]]
p <- data %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if(base::isFALSE(flip)){.data$Event} else {.data[[group]]},
y = if(base::isFALSE(flip)){.data[[group]]} else {.data$Event},
fill = .data$mean)) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5)
if (base::isTRUE(values.show)){
if (base::isTRUE(enforce_symmetry)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(abs(.data$mean) > values.threshold, "white", "black")),
size = values.size)
} else {
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(.data$mean > values.threshold, "white", "black")),
size = values.size)
}
p <- p + ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
# nocov start
ggplot2::guides(x.sec = guide_axis_label_trans(~paste0(levels(if(base::isFALSE(flip)){.data[[group]]} else {.data$Event}))),
y.sec = guide_axis_label_trans(~paste0(levels(if(base::isFALSE(flip)){.data[[group]]} else {.data$Event})))) +
# nocov end
ggplot2::coord_equal() +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = "CNV scores",
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
list.plots[[group]] <- p
}
# Modify legends.
for (name in names(list.plots)){
p <- list.plots[[name]]
p <- modify_continuous_legend(p = p,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
list.plots[[name]] <- p
}
# Add theme
counter <- 0
for (name in rev(names(list.plots))){
counter <- counter + 1
if (isTRUE(flip)){
if (counter == 1){
xlab <- name
ylab <- "CNV event"
} else if (counter == length(names(list.plots))){
xlab <- name
ylab <- NULL
} else {
xlab <- name
ylab <- NULL
}
} else {
if (counter == 1){
xlab <- NULL
ylab <- name
} else if (counter == length(names(list.plots))){
xlab <- "CNV event"
ylab <- name
} else {
xlab <- NULL
ylab <- name
}
}
p <- list.plots[[name]]
axis.parameters <- handle_axis(flip = flip,
group.by = rep("A", length(names(list.plots))),
group = name,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::labs(caption = if(base::isTRUE(skipped_chr)){if((base::isTRUE(include_chr_arms))){"Skipped arms with low number of genes."} else {"Skipped chromosomes with low number of genes."}} else {""}) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = legend.position,
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 5, r = 0, b = 0, l = 5),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.spacing.x = ggplot2::unit(0, "cm"))
list.plots[[name]] <- p
}
# Plot the combined plot
p <- patchwork::wrap_plots(list.plots[rev(group.by)],
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
face = plot.caption.face,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
if (isTRUE(return_object)){
return_list <- list("Plot" = p,
"Object" = sample)
} else {
return_list <- p
}
return(return_list)
}
================================================
FILE: R/do_CellularStatesPlot.R
================================================
#' Plot relationships between enrichment scores to infer cellular states.
#'
#' This plot aims to show the relationships between distinct enrichment scores. If 3 variables are provided, the relationship is between the Y axis and the dual X axis.
#' If 4 variables are provided, each corner of the plot represents how enriched the cells are in that given list. How to interpret this? In a 3-variable plot, the Y axis
#' just means one variable. The higher the cells are in the Y axis the more enriched they are in that given variable. The X axis is a dual parameter one. Cells falling
#' into each extreme of the axis are highly enriched for either x1 or x2, while cells falling in between are not enriched for any of the two. In a 4-variable plot, each corner
#' shows the enrichment for one of the 4 given features. Cells will tend to locate in either of the four corners, but there will be cases of cells locating mid-way between two
#' given corners (enriched in both features) or in the middle of the plot (not enriched for any).
#'
#' This plots are based on the following publications:
#' - Neftel, C. \emph{et al}. An Integrative Model of Cellular States, Plasticity, and Genetics for Glioblastoma. Cell 178, 835-849.e21 (2019). \doi{10.1016/j.cell.2019.06.024}
#' - Tirosh, I., Venteicher, A., Hebert, C. \emph{et al}. Single-cell RNA-seq supports a developmental hierarchy in human oligodendroglioma. Nature 539, 309–313 (2016). \doi{10.1038/nature20123}
#' @inheritParams doc_function
#' @param x1 \strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. First feature in the X axis. Will go on the right side of the X axis if y2 is not provided and top-right quadrant if provided.
#' @param x2 \strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. Second feature on the X axis. Will go on the left side of the X axis if y2 is not provided and top-left quadrant if provided.
#' @param y1 \strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. First feature on the Y axis. Will become the Y axis if y2 is not provided and bottom-right quadrant if provided.
#' @param y2 \strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. Second feature on the Y axis. Will become the bottom-left quadrant if provided.
#' @param axis.ticks \strong{\code{\link[base]{logical}}} | Whether to show axis ticks.
#' @param axis.text \strong{\code{\link[base]{logical}}} | Whether to show axis text.
#' @param enforce_symmetry \strong{\code{\link[base]{logical}}} | Whether to enforce the plot to follow a symmetry (3 variables, the X axis has 0 as center, 4 variables, all axis have the same range and the plot is squared).
#' @param plot_features \strong{\code{\link[base]{logical}}} | Whether to also report any other feature onto the primary plot.
#' @param features \strong{\code{\link[base]{character}}} | Additional features to plot.
#' @param plot_enrichment_scores \strong{\code{\link[base]{logical}}} | Whether to report enrichment scores for the input lists as plots.
#'
#' @return A ggplot2 object containing a butterfly plot.
#' @export
#' @example man/examples/examples_do_CellularStatesPlot.R
do_CellularStatesPlot <- function(sample,
input_gene_list,
x1,
y1,
x2 = NULL,
y2 = NULL,
group.by = NULL,
colors.use = NULL,
colorblind = FALSE,
legend.position = "bottom",
legend.icon.size = 4,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
font.size = 14,
font.type = "sans",
xlab = NULL,
ylab = NULL,
axis.ticks = TRUE,
axis.text = TRUE,
verbose = FALSE,
enforce_symmetry = FALSE,
plot_marginal_distributions = FALSE,
marginal.type = "density",
marginal.size = 5,
marginal.group = TRUE,
plot_cell_borders = TRUE,
plot_enrichment_scores = FALSE,
border.size = 2,
border.color = "black",
pt.size = 2,
raster = FALSE,
raster.dpi = 1024,
plot_features = FALSE,
features = NULL,
use_viridis = TRUE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = -1,
nbin = 24,
ctrl = 100,
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_CellularStatesPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("axis.ticks" = axis.ticks,
"axis.text" = axis.text,
"verbose" = verbose,
"enforce_symmetry" = enforce_symmetry,
"plot_marginal_distributions" = plot_marginal_distributions,
"marginal.group" = marginal.group,
"legend.byrow" = legend.byrow,
"plot_cell_borders" = plot_cell_borders,
"raster" = raster,
"plot_features" = plot_features,
"plot_enrichment_scores" = plot_enrichment_scores,
"use_viridis" = use_viridis,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"marginal.size" = marginal.size,
"legend.icon.size" = legend.icon.size,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow,
"pt.size" = pt.size,
"border.size" = border.size,
"raster.dpi" = raster.dpi,
"viridis.direction" = viridis.direction,
"nbin" = nbin,
"ctrl" = ctrl,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("input_gene_list" = input_gene_list,
"x1" = x1,
"x2" = x2,
"y1" = y1,
"y2" = y2,
"group.by" = group.by,
"ylab" = ylab,
"xlab" = xlab,
"legend.position" = legend.position,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"font.type" = font.type,
"marginal.type" = marginal.type,
"border.color" = border.color,
"features" = features,
"viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Define pipe operator internally.
`%>%` <- magrittr::`%>%`
# Check the colors provided.
if (is.null(colors.use)){
colors.use <- {
if (is.null(group.by)){
generate_color_scale(levels(sample), colorblind = colorblind)
} else if (!(is.null(group.by))){
data.use <- sample[[]][, group.by, drop = FALSE]
names.use <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
generate_color_scale(names.use, colorblind = colorblind)
}
}
} else {
check_colors(colors.use, parameter_name = "colors.use")
if (is.null(group.by)){
colors.use <- check_consistency_colors_and_names(sample = sample, colors = colors.use)
} else {
colors.use <- check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = group.by)
}
}
# Check border color.
check_colors(border.color, parameter_name = "border.color")
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = marginal.type, parameter_name = "marginal.type")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
# Compute the enrichment scores.
sample <- compute_enrichment_scores(sample = sample, input_gene_list = input_gene_list, verbose = verbose, nbin = nbin, ctrl = ctrl)
# 2-variable plot.
if (is.null(y2) & is.null(x2)){
# Check that the names provided are not repeated.
assertthat::assert_that(sum(duplicated(c(x1, y1))) == 0,
msg = paste0(add_cross(), crayon_body("The "),
crayon_key("names"),
crayon_body(" of the lists can not be "),
crayon_key("duplicated"),
crayon_body(".")))
# Check that the names provided match the marker genes.
assertthat::assert_that(x1 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(x1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
assertthat::assert_that(y1 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(y1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
# Retrieve metadata variables.
variables_to_retrieve <- c(x1, y1, group.by)
# And store them as a tibble.
scores <- sample@meta.data[, variables_to_retrieve]
scores[["cell"]] <- rownames(scores)
# Shuffle the cells so that we accomplish a random plotting, not sample by sample.
scores <- scores[sample(scores[["cell"]], nrow(scores)), ]
scores <- tidyr::tibble(scores)
# Compute scores for the X axis.
x <- scores %>% dplyr::pull(x1)
# Compute scores for the Y axis.
y <- scores %>% dplyr::pull(y1)
names(x) <- scores[["cell"]]
names(y) <- scores[["cell"]]
# Define titles.
x_lab <- ifelse(is.null(xlab), x1, xlab)
y_lab <- ifelse(is.null(ylab), y1, ylab)
# Plot
df <- data.frame("set_x" = x, "set_y" = y, "group.by" = scores[[group.by]])
p <- ggplot2::ggplot(data = df,
mapping = ggplot2::aes(x = .data[["set_x"]],
y = .data[["set_y"]],
color = .data[["group.by"]]))
if (base::isFALSE(raster)){
p <- p +
ggplot2::geom_point(size = pt.size)
} else if (isTRUE(raster)){
p <- p +
scattermore::geom_scattermore(size = pt.size,
pointsize = pt.size,
pixels = c(raster.dpi, raster.dpi))
}
p <- p +
ggplot2::geom_hline(yintercept = 0, linetype = "dashed") +
ggplot2::geom_vline(xintercept = 0, linetype = "dashed") +
ggplot2::scale_color_manual(values = colors.use) +
ggplot2::guides(color = ggplot2::guide_legend(title = "")) +
ggplot2::xlab(x_lab) +
ggplot2::ylab(y_lab) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption)
if (isTRUE(enforce_symmetry)){
# Define limits of polots.
lim1 <- min(min(x), min(y))
lim2 <- max(max(x), max(y))
lim_x <- c(lim1, lim2)
lim_y <- c(lim1, lim2)
p <- p +
ggplot2::coord_fixed(xlim = lim_x, ylim = lim_y)
}
# 3-variable plot.
} else if (is.null(y2) & !(is.null(x2))){
# Check that the names provided are not repeated.
assertthat::assert_that(sum(duplicated(c(x1, y1, x2))) == 0,
msg = paste0(add_cross(), crayon_body("The "),
crayon_key("names"),
crayon_body(" of the lists can not be "),
crayon_key("duplicated"),
crayon_body(".")))
# Check that the names provided match the marker genes.
assertthat::assert_that(x1 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(x1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
assertthat::assert_that(x2 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(x1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
assertthat::assert_that(y1 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(y1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
# Retrieve metadata variables.
variables_to_retrieve <- c(x1, x2, y1, group.by)
# And store them as a tibble.
scores <- sample@meta.data[, variables_to_retrieve]
scores[["cell"]] <- rownames(scores)
# Shuffle the cells so that we accomplish a random plotting, not sample by sample.
scores <- tidyr::tibble(scores)
# Compute the scores for the X axis.
x <- vapply(seq_len(nrow(scores)), function(x) {
score_1 <- scores[x, x1] + stats::runif(1, min=0, max=0.15)
score_2 <- scores[x, x2] + stats::runif(1, min=0, max=0.15)
d <- max(score_1, score_2, na.rm = TRUE)
output <- ifelse(score_1 > score_2, d, -d)
return(output)
}, FUN.VALUE = numeric(1))
# Compute the scores for the Y axis.
y <- vapply(seq_len(nrow(scores)), function(x) {
score_1 <- scores[x, x1] + stats::runif(1, min=0, max=0.15)
score_2 <- scores[x, x2] + stats::runif(1, min=0, max=0.15)
d <- max(score_1, score_2, na.rm = TRUE)
output <- as.data.frame(scores)[x, y1] - d
return(output)
}, FUN.VALUE = numeric(1))
names(x) <- scores[["cell"]]
names(y) <- scores[["cell"]]
# Define titles.
x_lab <- ifelse(is.null(xlab), paste0(x2, " <----> ", x1), xlab)
y_lab <- ifelse(is.null(ylab), y1, ylab)
# Plot.
df <- data.frame("set_x" = x, "set_y" = y, "group.by" = scores[[group.by]])
p <- ggplot2::ggplot(df, mapping = ggplot2::aes(x = .data[["set_x"]],
y = .data[["set_y"]],
color = .data[["group.by"]]))
if (base::isFALSE(raster)){
p <- p +
ggplot2::geom_point(size = pt.size)
} else if (isTRUE(raster)){
p <- p +
scattermore::geom_scattermore(size = pt.size,
pointsize = pt.size,
pixels = c(raster.dpi, raster.dpi))
}
p <- p +
ggplot2::geom_hline(yintercept = 0, linetype = "dashed") +
ggplot2::geom_vline(xintercept = 0, linetype = "dashed") +
ggplot2::scale_color_manual(values = colors.use) +
ggplot2::xlab(x_lab) +
ggplot2::ylab(y_lab) +
ggplot2::guides(color = ggplot2::guide_legend(title = "")) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption)
if (isTRUE(enforce_symmetry)){
# Define limits of polots.
lim <- max(abs(x))
lim_x <- c(-lim, lim)
lim <- max(abs(y))
lim_y <- c(-lim, lim)
p <- p +
ggplot2::xlim(lim_x) +
ggplot2::ylim(lim_y)
}
# 4-parameter plot.
} else if (!is.null(y2) & !(is.null(x2))){
# Check that the names provided are not repeated.
assertthat::assert_that(sum(duplicated(c(x1, y1, x2, y2))) == 0,
msg = paste0(add_cross(), crayon_body("The "),
crayon_key("names"),
crayon_body(" of the lists can not be "),
crayon_key("duplicated"),
crayon_body(".")))
# Check that the names provided match the marker genes.
assertthat::assert_that(x1 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(x1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
assertthat::assert_that(x2 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(x2),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
assertthat::assert_that(y1 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(y1),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
assertthat::assert_that(y2 %in% names(input_gene_list),
msg = paste0(add_cross(), crayon_body("The name "),
crayon_key(y2),
crayon_body(" is not a name of the lists of genes provided to "),
crayon_key("input_gene_list"),
crayon_body(".")))
# Retrieve metadata variables to plot.
variables_to_retrieve <- c(x1, x2, y1, y2)
# And store them as a tibble.
scores <- sample@meta.data[, variables_to_retrieve]
# Shuffle the cells so that we accomplish a random plotting, not sample by sample.
# Compute Y axis values.
d <- apply(scores, 1, function(x){max(x[c(x1, x2)]) - max(x[c(y1, y2)])})
# Compute X axis values.
x <- vapply(seq_along(d), function(x) {
if (d[x] > 0) {
d <- log2(abs(scores[x, x1] - scores[x, x2]) + 1)
ifelse(scores[x, x1] < scores[x, x2], d, -d)
} else {
d <- log2(abs(scores[x, y1] - scores[x, y2]) + 1)
ifelse(scores[x, y1] < scores[x, y2], d, -d)
}
}, FUN.VALUE = numeric(1))
names(x) <- rownames(scores)
# Define titles for the axis.
x_lab1 <- paste0(y1, " <----> ", y2)
x_lab2 <- paste0(x1, " <----> ", x2)
y_lab1 <- paste0(y1, " <----> ", x1)
y_lab2 <- paste0(x2, " <----> ", y2)
# Plot.
df <- data.frame(row.names = rownames(scores))
df[["set_x"]] <- x
df[["set_y"]] <- d
df[["group.by"]] <- sample@meta.data[, group.by]
p <- ggplot2::ggplot(df, mapping = ggplot2::aes(x = .data[["set_x"]],
y = .data[["set_y"]],
color = .data[["group.by"]]))
if (base::isFALSE(raster)){
p <- p +
ggplot2::geom_point(size = pt.size)
} else if (isTRUE(raster)){
p <- p +
scattermore::geom_scattermore(size = pt.size,
pointsize = pt.size,
pixels = c(raster.dpi, raster.dpi))
}
p <- p +
ggplot2::geom_hline(yintercept = 0, linetype = "dashed") +
ggplot2::geom_vline(xintercept = 0, linetype = "dashed") +
ggplot2::scale_color_manual(values = colors.use) +
ggplot2::xlab(x_lab1) +
ggplot2::ylab(y_lab1) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption)
suppressMessages({
p <- p +
ggplot2::scale_y_continuous(sec.axis = ggplot2::sec_axis(~., name = y_lab2)) +
ggplot2::scale_x_continuous(sec.axis = ggplot2::sec_axis(~., name = x_lab2))
})
if (isTRUE(enforce_symmetry)){
# Define limits of polots.
lim_1 <- min(min(d), min(x))
lim_2 <- max(max(d), max(x))
value <- max(abs(c(lim_1, lim_2)))
lim <- c(-value, value)
suppressMessages({
p <- p +
ggplot2::geom_hline(yintercept = 0, linetype = "dashed") +
ggplot2::geom_vline(xintercept = 0, linetype = "dashed") +
ggplot2::xlim(lim) +
ggplot2::ylim(lim) +
ggplot2::scale_y_continuous(sec.axis = ggplot2::sec_axis(~., name = y_lab2)) +
ggplot2::scale_x_continuous(sec.axis = ggplot2::sec_axis(~., name = x_lab2)) +
ggplot2::coord_fixed(xlim = c(-value, value), ylim = c(-value, value))
})
}
}
# Overall formatting for the plot.
p <- p &
ggplot2::theme_minimal(base_size = font.size) &
ggplot2::theme(axis.title = ggplot2::element_text(face = axis.title.face),
axis.line.y.right = ggplot2::element_line(color = "black"),
axis.ticks.y.right = ggplot2::element_line(color = "black"),
axis.line.x.top = ggplot2::element_line(color = "black"),
axis.ticks.x.top = ggplot2::element_line(color = "black"),
axis.text.x.top = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.text.y.right = ggplot2::element_text(face = axis.text.face, color = "black", hjust = 0),
axis.title.x.top = ggplot2::element_text(face = axis.title.face, color = "black"),
axis.title.y.right = ggplot2::element_text(face = axis.title.face, color = "black"),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white")) &
ggplot2::guides(color = ggplot2::guide_legend(title = "",
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size,
color = "black",
fill = colors.use,
shape = 21)))
# Add cell borders.
if (isTRUE(plot_cell_borders)){
if (base::isFALSE(raster)){
base_layer <- ggplot2::geom_point(data = df,
mapping = ggplot2::aes(x = .data[["set_x"]],
y = .data[["set_y"]]),
size = pt.size * border.size,
color = border.color,
show.legend = FALSE)
} else if (isTRUE(raster)){
base_layer <- scattermore::geom_scattermore(data = df,
mapping = ggplot2::aes(x = .data[["set_x"]],
y = .data[["set_y"]]),
size = pt.size * border.size,
stroke = pt.size / 2,
color = border.color,
pointsize = pt.size * border.size,
pixels = c(raster.dpi, raster.dpi),
show.legend = FALSE)
}
p[["layers"]] <- append(base_layer, p[["layers"]])
}
if (isTRUE(plot_features) | isTRUE(plot_enrichment_scores)){
if (isTRUE(plot_features)){
assertthat::assert_that(!is.null(features),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("features"),
crayon_body(" .")))
}
output_list <- list()
# Generate a mock DimRed object for the plots.
df.use <- df[, c("set_x", "set_y")]
colnames(df.use) <- c("DIM_1", "DIM_2")
sample@reductions[["test"]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(df.use), assay = "SCT")
if (isTRUE(plot_features) & isTRUE(plot_enrichment_scores)){
features <- c(features, names(input_gene_list))
} else if (base::isFALSE(plot_features) & isTRUE(plot_enrichment_scores)){
features <- names(input_gene_list)
}
for (feature in features){
p.feature <- do_FeaturePlot(sample = sample,
features = feature,
reduction = "test",
plot_cell_borders = plot_cell_borders,
pt.size = pt.size,
legend.position = legend.position,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
font.type = font.type,
font.size = font.size,
viridis.palette = viridis.palette,
viridis.direction = viridis.direction,
number.breaks = number.breaks,
use_viridis = use_viridis,
sequential.palette = sequential.palette,
sequential.direction = sequential.direction)
# Add back the missing aesthetics.
if (is.null(y2) & is.null(x2)){
# Define titles.
p.feature <- p.feature +
ggplot2::xlab(x_lab) +
ggplot2::ylab(y_lab)
if (isTRUE(enforce_symmetry)){
suppressMessages({
p.feature <- p.feature +
ggplot2::coord_fixed(xlim = lim_x, ylim = lim_y)
})
}
} else if (is.null(y2) & !(is.null(x2))){
# Define titles.
p.feature <- p.feature +
ggplot2::xlab(x_lab) +
ggplot2::ylab(y_lab)
if (isTRUE(enforce_symmetry)){
suppressMessages({
p.feature <- p.feature +
ggplot2::xlim(lim_x) +
ggplot2::ylim(lim_y)
})
}
} else if (!is.null(y2) & !(is.null(x2))){
p.feature <- p.feature +
ggplot2::xlab(x_lab1) +
ggplot2::ylab(y_lab1)
if (isTRUE(enforce_symmetry)){
suppressMessages({
p.feature <- p.feature +
ggplot2::xlim(lim) +
ggplot2::ylim(lim) +
ggplot2::scale_y_continuous(sec.axis = ggplot2::sec_axis(~., name = y_lab2)) +
ggplot2::scale_x_continuous(sec.axis = ggplot2::sec_axis(~., name = x_lab2)) +
ggplot2::coord_fixed(xlim = c(-value, value), ylim = c(-value, value))
})
}
}
p.feature <- p.feature +
ggplot2::theme_minimal(base_size = font.size) &
ggplot2::theme(axis.title = ggplot2::element_text(face = axis.title.face),
axis.text = ggplot2::element_text(face = axis.text.face, color = "black"),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
output_list[[feature]] <- p.feature
}
}
if (isTRUE(plot_marginal_distributions)){
# Remove annoying warnings when violin is used as marginal distribution.
if (marginal.type == "violin"){
p <- suppressWarnings({ggExtra::ggMarginal(p = p,
groupColour = ifelse(isTRUE(marginal.group), TRUE, FALSE),
groupFill = ifelse(isTRUE(marginal.group), TRUE, FALSE),
type = marginal.type,
size = marginal.size)})
} else {
p <- ggExtra::ggMarginal(p = p,
groupColour = ifelse(isTRUE(marginal.group), TRUE, FALSE),
groupFill = ifelse(isTRUE(marginal.group), TRUE, FALSE),
type = marginal.type,
size = marginal.size)
}
# Transform back to ggplot2 object.
p <- ggplotify::as.ggplot(p)
# Fix for the plot backgrounds after applying ggMarginal.
p[["theme"]][["plot.background"]] <- ggplot2::element_rect(fill = "white", color = "white")
p[["theme"]][["legend.background"]] <- ggplot2::element_rect(fill = "white", color = "white")
p[["theme"]][["panel.background"]] <- ggplot2::element_rect(fill = "white", color = "white")
}
# Remove axis ticks?
if (axis.ticks == FALSE){
p <- p +
ggplot2::theme(axis.ticks = ggplot2::element_blank())
}
# Remove axis text?
if (axis.text == FALSE){
p <- p +
ggplot2::theme(axis.text = ggplot2::element_blank())
}
if (isTRUE(plot_features) | isTRUE(plot_enrichment_scores)){
output_list[["main"]] <- p
return_object <- output_list
} else if (base::isFALSE(plot_features) & base::isFALSE(plot_enrichment_scores)){
return_object <- p
}
return(return_object)
}
================================================
FILE: R/do_ChordDiagramPlot.R
================================================
#' Generate a Chord diagram.
#'
#' @inheritParams doc_function
#' @inheritParams circlize::chordDiagram
#' @param from,to \strong{\code{\link[base]{character}}} | Categorical metadata variable to be used as origin and end points of the interactions.
#' @param big.gap \strong{\code{\link[base]{numeric}}} | Space between the groups in "from" and "to".
#' @param small.gap \strong{\code{\link[base]{numeric}}} | Space within the groups.
#' @param link.border.color \strong{\code{\link[base]{character}}} | Color for the border of the links. NA = no color.
#' @param link.border.width \strong{\code{\link[base]{numeric}}} | Width of the border line of the links.
#' @param highlight_group \strong{\code{\link[base]{character}}} | A value from from that will be used to highlight only the links coming from it.
#' @param alpha.highlight \strong{\code{\link[base]{numeric}}} | A value between 00 (double digits) and 99 to depict the alpha of the highlighted links. No transparency needs "FF"
#' @param z_index \strong{\code{\link[base]{logical}}} | Whether to bring the bigger links to the top.
#' @param self.link \strong{\code{\link[base]{numeric}}} | Behavior of the links. One of:
#' \itemize{
#' \item \emph{\code{1}}: Prevents self linking.
#' \item \emph{\code{2}}: Allows self linking.
#' }
#' @param directional \strong{\code{\link[base]{numeric}}} | Set the direction of the links. One of:
#' \itemize{
#' \item \emph{\code{0}}: Non-directional data.
#' \item \emph{\code{1}}: Links go from "from" to "to".
#' \item \emph{\code{-1}}: Links go from "to" to "from".
#' \item \emph{\code{2}}: Links go in both directions.
#' }
#' @param direction.type \strong{\code{\link[base]{character}}} | How to display the directions. One of:
#' \itemize{
#' \item \emph{\code{diffHeight}}: Sets a line at the origin of the group showing to how many groups and in which proportion this group is linked to.
#' \item \emph{\code{arrows}}: Sets the connection as arrows.
#' \item \emph{\code{both}}: Sets up both behaviors. Use as: \code{c("diffHeight", "arrows")}.
#' }
#' @param link.arr.type \strong{\code{\link[base]{character}}} | Sets the appearance of the arrows. One of:
#' \itemize{
#' \item \emph{\code{triangle}}: Arrow with a triangle tip at the end displayed on top of the link.
#' \item \emph{\code{big.arrow}}: The link itself ends in a triangle shape.
#' }
#' @param scale \strong{\code{\link[base]{logical}}} | Whether to put all nodes the same width.
#' @param alignment \strong{\code{\link[base]{character}}} | How to align the diagram. One of:
#' \itemize{
#' \item \emph{\code{default}}: Allows \pkg{circlize} to set up the plot as it sees fit.
#' \item \emph{\code{horizontal}}: Sets the break between "from" and "to" groups on the horizontal axis.
#' \item \emph{\code{vertical}}: Sets the break between "from" and "to" groups on the vertical axis.
#' }
#' @param padding_labels \strong{\code{\link[base]{numeric}}} | Number of extra padding (white spaces) of the labels so that they do not overlap with the scales.
#' @param colors.from,colors.to \strong{\code{\link[SCpubr]{named_vector}}} | Named vector of colors corresponding to the unique values of "from" and "to".
#'
#' @return A circlize plot.
#' @export
#'
#' @example /man/examples/examples_do_ChordDiagramPlot.R
do_ChordDiagramPlot <- function(sample = NULL,
from = NULL,
to = NULL,
colors.from = NULL,
colors.to = NULL,
colorblind = FALSE,
big.gap = 10,
small.gap = 1,
link.border.color = NA,
link.border.width = 1,
highlight_group = NULL,
alpha.highlight = 25,
link.sort = NULL,
link.decreasing = TRUE,
z_index = FALSE,
self.link = 1,
symmetric = FALSE,
directional = 1,
direction.type = c("diffHeight", "arrows"),
link.arr.type = "big.arrow",
scale = FALSE,
alignment = "default",
annotationTrack = c("grid", "axis"),
padding_labels = 4,
font.size = 1){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
`%>%` <- magrittr::`%>%`
check_suggests(function_name = "do_ChordDiagramPlot")
# Check logical parameters.
logical_list <- list("link.decreasing" = link.decreasing,
"z_index" = z_index,
"symmetric" = symmetric,
"scale" = scale,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("big.gap" = big.gap,
"small.gap" = small.gap,
"link.border.width" = link.border.width,
"alpha.highlight" = alpha.highlight,
"self.link" = self.link,
"directional" = directional,
"padding_labels" = padding_labels,
"font.size" = font.size)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("from" = from,
"to" = to,
"highlight_group" = highlight_group,
"direction.type" = direction.type,
"link.arr.type" = link.arr.type,
"alignment" = alignment,
"annotationTrack" = annotationTrack,
"colors.from" = colors.from,
"colors.to" = colors.to)
# Checks
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_parameters(parameter = direction.type, parameter_name = "direction.type")
check_parameters(parameter = self.link, parameter_name = "self.link")
check_parameters(parameter = directional, parameter_name = "directional")
check_parameters(parameter = link.arr.type, parameter_name = "link.arr.type")
check_parameters(parameter = alignment, parameter_name = "alignment")
check_parameters(parameter = alpha.highlight, parameter_name = "alpha.highlight")
circlize::circos.clear()
assertthat::assert_that(!is.null(sample),
msg = paste0(add_cross(), crayon_body("Please provide a "),
crayon_key("Seurat object"),
crayon_body(" to the parameter "),
crayon_key("sample"),
crayon_body(".")))
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
assertthat::assert_that(!is.null(from) | !is.null(to),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("from"),
crayon_body(" or "),
crayon_key("to"),
crayon_body(" parameters.")))
assertthat::assert_that(from %in% colnames(sample@meta.data) | to %in% colnames(sample@meta.data),
msg = paste0(add_cross(), crayon_body("Parameters "),
crayon_key("from"),
crayon_body(" and "),
crayon_key("to"),
crayon_body(" need to be present in the object "),
crayon_key("metadata"),
crayon_body(".")))
assertthat::assert_that(class(sample@meta.data[, from]) %in% c("factor", "character") | class(sample@meta.data[, to]) %in% c("factor", "character"),
msg = paste0(add_cross(), crayon_body("Parameters "),
crayon_key("from"),
crayon_body(" and "),
crayon_key("to"),
crayon_body(" need to be either a "),
crayon_key("factor"),
crayon_body(" or "),
crayon_key("character"),
crayon_body(" columns.")))
data <- sample@meta.data %>%
tibble::as_tibble() %>%
dplyr::select(dplyr::all_of(c(from, to))) %>%
dplyr::group_by(.data[[to]], .data[[from]]) %>%
dplyr::summarize(value = dplyr::n()) %>%
dplyr::rename("from" = dplyr::all_of(c(from)),
"to" = dplyr::all_of(c(to))) %>%
dplyr::select(dplyr::all_of(c("from", "to", "value")))
max_char <- max(c(max(nchar(as.character(data[["from"]]))), max(nchar(as.character(data[["to"]]))))) + padding_labels
if (is.factor(data[["to"]]) & is.factor(data[["from"]])){
levels_to <- stringr::str_pad(levels(data[["to"]]), width = max_char, side = "both")
levels_from <- stringr::str_pad(levels(data[["from"]]), width = max_char, side = "both")
data <- data %>%
dplyr::mutate("from" = factor(stringr::str_pad(.data[["from"]], width = max_char, side = "both"), levels = levels_from),
"to" = factor(stringr::str_pad(.data[["to"]], width = max_char, side = "both"), levels = levels_to))
} else if (is.factor(data[["to"]]) & is.character(data[["from"]])){
levels_to <- stringr::str_pad(levels(data[["to"]]), width = max_char, side = "both")
data <- data %>%
dplyr::mutate("from" = stringr::str_pad(.data[["from"]], width = max_char, side = "both"),
"to" = factor(stringr::str_pad(.data[["to"]], width = max_char, side = "both"), levels = levels_to))
} else if (is.character(data[["to"]]) & is.factor(data[["from"]])){
levels_from <- stringr::str_pad(levels(data[["from"]]), width = max_char, side = "both")
data <- data %>%
dplyr::mutate("from" = factor(stringr::str_pad(.data[["from"]], width = max_char, side = "both"), levels = levels_from),
"to" = stringr::str_pad(.data[["to"]], width = max_char, side = "both"))
} else if (is.character(data[["to"]]) & is.character(data[["from"]])){
data <- data %>%
dplyr::mutate("from" = stringr::str_pad(.data[["from"]], width = max_char, side = "both"),
"to" = stringr::str_pad(.data[["to"]], width = max_char, side = "both"))
}
if (!(is.null(colors.from))){
check_colors(colors.from, parameter_name = "colors.from")
check_consistency_colors_and_names(sample = sample,
colors = colors.from,
grouping_variable = from)
} else {
if (is.factor(data[["from"]])){
colors.from <- generate_color_scale(names_use = levels(data[["from"]]), colorblind = colorblind)
} else {
colors.from <- generate_color_scale(names_use = sort(unique(data[["from"]])), colorblind = colorblind)
}
}
names(colors.from) <- stringr::str_pad(names(colors.from), width = max_char, side = "both")
if (!(is.null(colors.to))){
check_colors(colors.to, parameter_name = "colors.to")
check_consistency_colors_and_names(sample = sample,
colors = colors.to,
grouping_variable = to)
} else {
colors.to <- viridis::viridis(n = length(unique(data[["to"]])), option = "G")
if (is.factor(data[["to"]])){
colors.to <- stats::setNames(colors.to, levels(data[["to"]]))
} else {
colors.to <- stats::setNames(colors.to, sort(unique(data[["to"]])))
}
}
names(colors.to) <- stringr::str_pad(names(colors.to), width = max_char, side = "both")
colors.use <- c(colors.from, colors.to)
if (is.null(link.sort)){link.sort <- "default"}
if (base::isFALSE(z_index)){link.zindex <- NULL} else {link.zindex <- rank(data[["value"]])}
if (alignment == "vertical"){
circlize::circos.par(start.degree = 0)
} else if (alignment == "horizontal"){
circlize::circos.par(start.degree = 90)
}
if (!is.na(link.border.color)){
check_colors(link.border.color)
}
if (!(is.null(highlight_group))){
alpha.colors <- NULL
highlight_group <- stringr::str_pad(highlight_group, width = max_char, side = "both")
for (color in names(colors.use)){
name <- color
color <- colors.use[name]
if (nchar(color) == 7){
if (name %!in% highlight_group){
color <- paste0(color, alpha.highlight)
names(color) <- name
} else {
names(color) <- name
}
} else if (nchar(color) == 9){
if (name %!in% highlight_group){
color <- paste0(stringr::str_sub(color, 1, 7), as.character(alpha.highlight))
names(color) <- name
} else {
names(color) <- name
}
}
alpha.colors <- append(alpha.colors, color)
}
colors.use <- alpha.colors
rm(alpha.colors)
}
circlize::chordDiagram(data,
big.gap = big.gap,
small.gap = small.gap,
grid.col = colors.use,
link.border = link.border.color,
link.lwd = link.border.width,
link.sort = link.sort,
link.decreasing = link.decreasing,
link.zindex = link.zindex,
self.link = self.link,
symmetric = symmetric,
directional = directional,
direction.type = direction.type,
link.arr.type = link.arr.type,
scale = scale,
annotationTrack = annotationTrack,
preAllocateTracks = list(track.height = max(graphics::strwidth(unlist(dimnames(data))))))
circlize::circos.track(track.index = 1,
panel.fun = function(x, y){circlize::circos.text(circlize::CELL_META$xcenter,
circlize::CELL_META$ylim[[1]],
circlize::CELL_META$sector.index,
facing = "clockwise",
niceFacing = TRUE,
adj = c(-0.15, 0.5),
font = 2,
cex = font.size)},
bg.border = NA)
p <- grDevices::recordPlot()
circlize::circos.clear()
grDevices::dev.off()
return(p)
}
================================================
FILE: R/do_ColorBlindCheck.R
================================================
#' Generate colorblind variations of a given color palette.
#'
#' This function generate colorblind variations of a provided color palette in order to check if it is colorblind friendly. Variations are generated using colorspace package.
#'
#' @inheritParams doc_function
#' @param colors.use \strong{\code{\link[base]{character}}} | One color upon which generate the color scale. Can be a name or a HEX code.
#' @return A character vector with the desired color scale.
#' @export
#' @example man/examples/examples_do_ColorBlindCheck.R
do_ColorBlindCheck <- function(colors.use,
flip = FALSE,
font.size = 14,
font.type = "sans",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.text.face = "plain",
legend.title.face = "bold",
grid.color = "white",
border.color = "black",
axis.text.x.angle = 45){
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_ColorPalette")
# Check logical parameters.
logical_list <- list("flip" = flip)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size", font.size,
"axis.text.x.angle" = axis.text.x.angle,
"font.size" = font.size)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("colors.use" = colors.use,
"font.type" = font.type,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.text.face" = legend.text.face,
"legend.title.face" = legend.title.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check that the color provided is a valid color representation.
check_colors(colors.use, parameter_name = "colors.use")
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
# Dicromatic view:
deutan.colors <- colorspace::deutan(colors.use) # Red-green (most common)
protan.colors <- colorspace::protan(colors.use) # Red-green (less common)
tritan.colors <- colorspace::tritan(colors.use) # Blue-yellow
colors.use <- list("Normal" = colors.use,
"Protanopia" = protan.colors,
"Deuteranopia" = deutan.colors,
"Tritanopia" = tritan.colors)
df <- as.data.frame(colors.use)
# df <- df[rev(seq(1, length(rownames(df)))),]
list.heatmaps <- list()
metadata <- if(base::isFALSE(flip)){rev(colnames(df))} else {colnames(df)}
group.by <- "Colors"
data.plot <- df %>%
dplyr::mutate("{group.by}" := .data$Normal) %>%
tidyr::pivot_longer(cols = -"Colors",
names_to = "Type",
values_to = "Color") %>%
dplyr::mutate("{group.by}" := factor(.data[[group.by]], levels = df$Normal))
# Get a list of predefined colors to then compute color wheels on for each metadata variable not covered.
counter <- 0
for (name in metadata){
counter <- counter + 1
# Colors
colors.use.name <- df[, name]
names(colors.use.name) <- df$Normal
# Handle axis
axis.parameters <- handle_axis(flip = flip,
group.by = rep("A", length(metadata)),
group = name,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = "bold",
legend.text.face = "plain")
p <- data.plot %>%
dplyr::filter(.data$Type == name) %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if(base::isFALSE(flip)){.data[[group.by]]} else {.data$Type},
y = if(base::isFALSE(flip)){.data$Type} else {.data[[group.by]]},
fill = .data[[group.by]])) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$Type))),
x.sec = guide_axis_label_trans(~paste0(levels(.data[[group.by]])))) +
ggplot2::coord_equal() +
ggplot2::scale_fill_manual(values = colors.use.name, name = name, na.value = "grey75") +
ggplot2::xlab(NULL) +
ggplot2::ylab(NULL) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = "none",
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = "plain", size = font.size),
legend.title = ggplot2::element_text(face = "bold", size = font.size),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0, unit = "mm"),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.spacing = ggplot2::unit(0, "cm"),
panel.spacing.x = ggplot2::unit(0, "cm"))
list.heatmaps[[name]] <- p
}
# Tweak Normal plot space.
list.heatmaps[["Normal"]] <- list.heatmaps[["Normal"]] +
ggplot2::theme(plot.margin = ggplot2::margin(t = 0,
r = if (base::isFALSE(flip)){0} else {5},
b = if (base::isFALSE(flip)){5} else {0},
l = 0, unit = "mm"))
p <- patchwork::wrap_plots(list.heatmaps[if(base::isFALSE(flip)){rev(metadata)} else {metadata}],
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
return(p)
}
================================================
FILE: R/do_ColorPalette.R
================================================
#' Generate color scales based on a value.
#'
#' This function is an adaptation of colortools package. As the package was removed from CRAN on 23-06-2022, this utility function came to existence in order to cover the gap. It is, on its basis,
#' an adaptation of the package into a single function. Original code, developed by Gaston Sanchez, can be found in:
#'
#' @inheritParams doc_function
#' @param colors.use \strong{\code{\link[base]{character}}} | One color upon which generate the color scale. Can be a name or a HEX code.
#' @param n \strong{\code{\link[base]{numeric}}} | Number of colors to include in the color wheel. Use it when all other options are FALSE, otherwise, it becomes 12.
#' @param opposite \strong{\code{\link[base]{logical}}} | Return the opposing color to the one provided.
#' @param adjacent \strong{\code{\link[base]{logical}}} | Return the adjacent colors to the one provided.
#' @param triadic \strong{\code{\link[base]{logical}}} | Return the triadic combination of colors to the one provided.
#' @param split_complementary \strong{\code{\link[base]{logical}}} | Return the split complementary combination of colors to the one provided.
#' @param tetradic \strong{\code{\link[base]{logical}}} | Return the tetradic combination of colors to the one provided.
#' @param square \strong{\code{\link[base]{logical}}} | Return the square combination of colors to the one provided.
#' @param complete_output \strong{\code{\link[base]{logical}}} | Runs all the previous options and returns all the outputs as a list that contains all color vectors, all plots and a combined plot with everything.
#' @param plot \strong{\code{\link[base]{logical}}} | Whether to also return a plot displaying the values instead of a vector with the color.
#' @return A character vector with the desired color scale.
#' @export
#' @example man/examples/examples_do_ColorPalette.R
do_ColorPalette <- function(colors.use,
n = 12,
opposite = FALSE,
adjacent = FALSE,
triadic = FALSE,
split_complementary = FALSE,
tetradic = FALSE,
square = FALSE,
complete_output = FALSE,
plot = FALSE,
font.size = 14,
font.type = "sans"){
`%>%` <- magrittr::`%>%`
`%*%` <- base::`%*%`
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_ColorPalette")
# Check logical parameters.
logical_list <- list("opposite" = opposite,
"adjacent" = adjacent,
"triadic" = triadic,
"split_complementary" = split_complementary,
"tetradic" = tetradic,
"square" = square,
"complete_output" = complete_output)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("n" = n,
"font.size", font.size)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("colors.use" = colors.use,
"font.type" = font.type)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check that the colors provided are only one.
assertthat::assert_that(length(colors.use) == 1,
msg = paste0(add_cross(), crayon_body("Please, provide a single "),
crayon_key("color"),
crayon_body(" to "),
crayon_key("colors.use")))
# Check that the color provided is a valid color representation.
check_colors(colors.use, parameter_name = "colors.use")
# Check that only one option is activated.
options_list <- c(opposite, adjacent, triadic, split_complementary, tetradic, square, complete_output)
if (sum(options_list) > 0){
assertthat::assert_that(sum(options_list) == 1,
msg = paste0(add_cross(), crayon_body("Please, select only "),
crayon_key("one option"),
crayon_body(" to form the color scale.\nIf you want more than "),
crayon_key("one output"),
crayon_body(", consider using the paramter"),
crayon_key("complete_output"),
crayon_body(".")))
}
# Check that n is actually positive.
assertthat::assert_that(n > 0,
msg = paste0(add_cross(), crayon_body("Please, provide a "),
crayon_key("positive value"),
crayon_body(" to the parameter "),
crayon_key("n"),
crayon_body(".")))
# If any option is set to TRUE, pal_length is 12
if (sum(options_list) >= 1 & n != 12){
warning(paste0(add_warning(), crayon_body("When a "),
crayon_key("color output"),
crayon_body(" option is selected, parameter "),
crayon_key("n"),
crayon_body(" becomes by default "),
crayon_key("12"),
crayon_body("\nPlease consider not using "),
crayon_key("n"),
crayon_body(" in such cases.")), call. = FALSE)
n <- 12
}
# Convert input to RGB colors: Input can be either color names, hex code.
RGB_colors <- grDevices::col2rgb(colors.use)
# Convert RGB values to HSV values.
HSV_colors <- grDevices::rgb2hsv(RGB_colors)[, 1]
# Get HSV components.
hue <- HSV_colors[[1]] # Hue
sat <- HSV_colors[[2]] # Saturation
val <- HSV_colors[[3]] # Value
# Generate a vector of hues that range a total of 1 unit, divided equally by n.
hue_vector <- seq(hue, hue + 1, by = 1 / n)
# Subset only the n colors.
hue_vector <- hue_vector[1:n]
# As this will generate hues over 1, anything over it, we deduct 1.
hue_vector[hue_vector > 1] <- hue_vector[hue_vector > 1] - 1
# Transform HSV values into HEX codes.
colors <- grDevices::hsv(hue_vector, sat, val)
# Add transparency value of the original color to the generated color scale.
# This only works in the case the original color has a transparency value.
if (substr(colors.use, 1, 1) == "#" && nchar(colors.use) == 9){
alpha <- substr(colors.use, 8, 9)
colors <- paste(colors, alpha, sep="")
}
# If opposite is TRUE, select the first and middle colors.
if (isTRUE(opposite)){
colors.mod <- colors[c(1, 7)]
# If adjacent is TRUE, select the hues next to the original color.
} else if (isTRUE(adjacent)){
colors.mod <- colors[c(1, 2, 12)]
# If triadic is TRUE, select the hues forming a triangle.
} else if (isTRUE(triadic)){
colors.mod <- colors[c(1, 5, 9)]
# If split_complementary is TRUE, select the hues forming a triangle.
} else if (isTRUE(split_complementary)){
colors.mod <- colors[c(1, 6, 8)]
# If tetradic is TRUE, select the hues forming a triangle.
} else if (isTRUE(tetradic)){
colors.mod <- colors[c(1, 3, 7, 9)]
# If square is TRUE, select the hues forming a triangle.
} else if (isTRUE(square)){
colors.mod <- colors[c(1, 4, 7, 10)]
# If complete_output is TRUE, report everything.
} else {
colors.mod <- colors
}
if (isTRUE(plot) & base::isFALSE(complete_output)){
# Dummy df to plot.
names(colors) <- colors
df <- data.frame("values" = rep(1, n), "names" = factor(colors, levels = names(colors)))
colors.use <- colors
limits <- c(-5, 1.35)
# Define name for the center of the plot.
if (isTRUE(opposite)){
name_center <- "Opposite"
colors.use[!(names(colors.use) %in% colors[c(1, 7)])] <- "grey75"
# If adjacent is TRUE, select the hues next to the original color.
} else if (isTRUE(adjacent)){
name_center <- "Adjacent"
colors.use[!(names(colors.use) %in% colors[c(1, 2, 12)])] <- "grey75"
# If triadic is TRUE, select the hues forming a triangle.
} else if (isTRUE(triadic)){
name_center <- "Triadic"
colors.use[!(names(colors.use) %in% colors[c(1, 5, 9)])] <- "grey75"
# If split_complementary is TRUE, select the hues forming a triangle.
} else if (isTRUE(split_complementary)){
name_center <- stringr::str_wrap("Split complementary", width = 5)
colors.use[!(names(colors.use) %in% colors[c(1, 6, 8)])] <- "grey75"
# If tetradic is TRUE, select the hues forming a triangle.
} else if (isTRUE(tetradic)){
name_center <- "Tetradic"
colors.use[!(names(colors.use) %in% colors[c(1, 3, 7, 9)])] <- "grey75"
# If square is TRUE, select the hues forming a triangle.
} else if (isTRUE(square)){
name_center <- "Square"
colors.use[!(names(colors.use) %in% colors[c(1, 4, 7, 10)])] <- "grey75"
# If complete_output is TRUE, report everything.
} else {
name_center <- stringr::str_wrap("Color wheel", width = 5)
}
# Define blank labels.
count <- 0
if ("grey75" %in% colors.use){
names.vector <- NULL
# Iterate over each color.
for (name in names(colors.use)){
if (colors.use[name] == "grey75"){
count <- count + 1
label.use <- paste0(rep(" ", count), collapse = "")
} else {
label.use <- name
}
names.vector <- append(names.vector, label.use)
}
names(colors.use) <- names.vector
df[["names"]] <- factor(names(colors.use), levels = names(colors.use))
}
p <- ggplot2::ggplot(data = df, mapping = ggplot2::aes(x = .data[["names"]],
y = .data[["values"]],
fill = .data[["names"]])) +
ggplot2::geom_col(color = "black", linewidth = 1) +
ggplot2::coord_polar(start = ifelse(sum(options_list) == 1, -0.275, 0), direction = 1, clip = "off") +
ggplot2::scale_fill_manual(values = colors.use, na.value = "grey75") +
ggplot2::ylim(limits) +
# Add X axis title in the center of the plot.
ggplot2::annotate(geom = "text",
x = df[["names"]][[1]],
y = limits[[1]],
angle = 0,
hjust = 0.5,
vjust = 0.5,
label = name_center,
size = 8,
fontface = "bold") +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.title = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.text.y = ggplot2::element_blank(),
axis.text.x = ggplot2::element_text(face = "bold", color = "black"),
panel.grid.major = ggplot2::element_blank(),
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = "bold", hjust = 0),
plot.subtitle = ggplot2::element_text(hjust = 0),
plot.caption = ggplot2::element_text(hjust = 1),
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = "bold"),
legend.position = "none",
legend.title = ggplot2::element_text(face = "bold"),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 40, b = 10, l = 40),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
} else if (isTRUE(plot) & isTRUE(complete_output)) {
stop(paste0(add_cross(), crayon_body("Parameter "),
crayon_key("plot"),
crayon_body(" only works when "),
crayon_key("complete_output"),
crayon_body(" is set to "),
crayon_key("FALSE"),
crayon_body(".")), call. = FALSE)
}
# Complete output.
# If plot = TRUE, return the plot, if not, colors. If complete_output = TRUE, return the report.
if (isTRUE(complete_output)){
# List of colors.
return_colors <- list("wheel" = do_ColorPalette(colors.use = colors.use,
n = n),
"opposite" = do_ColorPalette(colors.use = colors.use,
n = n,
opposite = TRUE),
"adjacent" = do_ColorPalette(colors.use = colors.use,
n = n,
adjacent = TRUE),
"triadic" = do_ColorPalette(colors.use = colors.use,
n = n,
triadic = TRUE),
"split_complementary" = do_ColorPalette(colors.use = colors.use,
n = n,
split_complementary = TRUE),
"tetradic" = do_ColorPalette(colors.use = colors.use,
n = n,
tetradic = TRUE),
"square" = do_ColorPalette(colors.use = colors.use,
n = n,
square = TRUE))
# List of plots.
return_plots <- list("wheel" = do_ColorPalette(colors.use = colors.use,
n = n,
plot = TRUE),
"opposite" = do_ColorPalette(colors.use = colors.use,
n = n,
opposite = TRUE,
plot = TRUE),
"adjacent" = do_ColorPalette(colors.use = colors.use,
n = n,
adjacent = TRUE,
plot = TRUE),
"triadic" = do_ColorPalette(colors.use = colors.use,
n = n,
triadic = TRUE,
plot = TRUE),
"split_complementary" = do_ColorPalette(colors.use = colors.use,
n = n,
split_complementary = TRUE,
plot = TRUE),
"tetradic" = do_ColorPalette(colors.use = colors.use,
n = n,
tetradic = TRUE,
plot = TRUE),
"square" = do_ColorPalette(colors.use = colors.use,
n = n,
square = TRUE,
plot = TRUE))
layout <- "ABCD
EFGH"
patch <- patchwork::wrap_plots(A = return_plots[["wheel"]],
B = return_plots[["opposite"]],
C = return_plots[["adjacent"]],
D = return_plots[["triadic"]],
E = return_plots[["split_complementary"]],
F = return_plots[["tetradic"]],
G = return_plots[["square"]],
H = patchwork::plot_spacer(),
design = layout)
# Build the output object.
return_object <- list("colors" = return_colors,
"plots" = return_plots,
"combined_plot" = patch)
} else {
if (isTRUE(plot)){
return_object <- p
} else {
return_object <- colors.mod
}
}
return(return_object)
}
================================================
FILE: R/do_CorrelationHeatmap.R
================================================
#' Create correlation matrix heatmaps.
#'
#' @inheritParams doc_function
#' @param mode \strong{\code{\link[base]{character}}} | Different types of correlation matrices can be computed. Right now, the only possible value is "hvg", standing for Highly Variable Genes. The sample is subset for the HVG and the data is re-scaled. Scale data is used for the correlation.
#' @param cluster \strong{\code{\link[base]{logical}}} | Whether to cluster the elements in the heatmap or not.
#' @param remove.diagonal \strong{\code{\link[base]{logical}}} | Whether to convert diagnoal to NA. Normally this value would be 1, heavily shifting the color scale.
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_CorrelationHeatmap.R
do_CorrelationHeatmap <- function(sample = NULL,
input_gene_list = NULL,
cluster = TRUE,
remove.diagonal = TRUE,
mode = "hvg",
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
assay = NULL,
group.by = NULL,
legend.title = "Pearson coef.",
enforce_symmetry = ifelse(mode == "hvg", TRUE, FALSE),
font.size = 14,
font.type = "sans",
na.value = "grey75",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
legend.position = "bottom",
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
diverging.palette = "RdBu",
diverging.direction = -1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
axis.text.x.angle = 45,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_CorrelationHeatmap")
`%>%` <- magrittr::`%>%`
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"cluster" = cluster,
"remove.diagonal" = remove.diagonal,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.tickwidth" = legend.tickwidth,
"legend.framewidth" = legend.framewidth,
"font.size" = font.size,
"axis.text.x.angle" = axis.text.x.angle,
"sequential.direction" = sequential.direction,
"viridis.direction" = viridis.direction,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("mode" = mode,
"assay" = assay,
"legend.title" = legend.title,
"group.by" = group.by,
"na.value" = na.value,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"font.type" = font.type,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"viridis.palette" = viridis.palette,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
if (mode == "hvg"){
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
out <- check_and_set_assay(sample = sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
# Generate a correlation matrix of the HVG.
variable_genes <- Seurat::VariableFeatures(sample)
# Sort them in order (for ATAC experiments).
if (utils::packageVersion("Seurat") < "5.0.0"){
genes <- rownames(SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = "data"))
} else {
genes <- rownames(SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = "data"))
}
genes <- data.frame("Genes" = genes) %>%
tibble::rowid_to_column(var = "Position") %>%
tibble::as_tibble() %>%
dplyr::filter(.data$Genes %in% variable_genes) %>%
dplyr::arrange(.data$Position) %>%
dplyr::pull(.data$Genes)
# Subset sample according to the variable genes.
sample <- sample[genes, ]
# Scale the data
sample <- Seurat::ScaleData(sample, features = genes, verbose = FALSE)
# Retrieve correlation matrix.
if (utils::packageVersion("Seurat") < "5.0.0"){
left_join_data <- SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = "scale.data")
} else {
left_join_data <- SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = "scale.data")
}
out <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c(group.by))) %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {left_join_data %>%
as.matrix() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
tidyr::pivot_longer(-"cell",
names_to = "gene",
values_to = "expression")},
by = "cell") %>%
dplyr::select(-"cell") %>%
dplyr::group_by(.data[[group.by]], .data[["gene"]]) %>%
dplyr::summarise(mean_expression = mean(.data[["expression"]])) %>%
tidyr::pivot_wider(names_from = dplyr::all_of(c(group.by)),
values_from = "mean_expression") %>%
as.data.frame() %>%
tibble::column_to_rownames(var = "gene") %>%
as.matrix() %>%
stats::cor() %>%
round(digits = 2)
# Compute hclust.
if (isTRUE(cluster)){
order <- rownames(out)[stats::hclust(stats::dist(out, method = "euclidean"), method = "ward.D")$order]
} else {
order <- rownames(out)
}
out.long <- out %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "x") %>%
tibble::as_tibble() %>%
tidyr::pivot_longer(cols = -"x",
names_to = "y",
values_to = "score") %>%
dplyr::mutate("x" = factor(.data$x, levels = order),
"y" = factor(.data$y, levels = rev(order))) %>%
dplyr::mutate("score" = ifelse(as.character(.data$x) == as.character(.data$y), ifelse(isTRUE(remove.diagonal), NA, .data$score), .data$score))
limits <- c(min(out.long$score, na.rm = TRUE),
max(out.long$score, na.rm = TRUE))
# Compute scale limits, breaks, etc.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "SCT",
reduction = NULL,
slot = "scale.data",
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Modify according to min.cutoff and max.cutoff.
if (!is.na(min.cutoff)){
out.long <- out.long %>%
dplyr::mutate("score" = ifelse(.data$score < min.cutoff, min.cutoff, .data$score))
}
if (!is.na(max.cutoff)){
out.long <- out.long %>%
dplyr::mutate("score" = ifelse(.data$score > max.cutoff, max.cutoff, .data$score))
}
p <- ggplot2::ggplot(out.long,
mapping = ggplot2::aes(x = .data$x,
y = .data$y,
fill = .data$score)) +
ggplot2::geom_tile(color = grid.color, linewidth = 0.5)
if (base::isTRUE(values.show)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$score, values.round),
color = ifelse(abs(.data$score) > values.threshold, "white", "black")),
size = values.size) +
ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$y))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$x)))) +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits) +
ggplot2::coord_equal() +
ggplot2::xlab(NULL) +
ggplot2::ylab(NULL) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption)
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
p <- p +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = ggplot2::element_line(color = "black"),
axis.ticks.x.top = ggplot2::element_blank(),
axis.ticks.y.left = ggplot2::element_blank(),
axis.ticks.y.right = ggplot2::element_line(color = "black"),
axis.text.y.left = ggplot2::element_blank(),
axis.text.y.right = ggplot2::element_text(color = "black",
face = axis.text.face,
hjust = 0),
axis.text.x.top = ggplot2::element_blank(),
axis.text.x.bottom = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["vjust"]]),
axis.title.x.bottom = ggplot2::element_blank(),
axis.title.x.top = ggplot2::element_text(color = "black",
face = axis.title.face),
axis.title.y.right = ggplot2::element_blank(),
axis.title.y.left = ggplot2::element_text(color = "black",
face = axis.title.face),
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 10, b = 0, l = 40),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
legend.position = legend.position,
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
} else if (mode == "jaccard"){
# Compute jaccard indext.
jaccard <- function(set_1, set_2) {
# Compute intersection.
intersection <- length(dplyr::intersect(set_1, set_2))
# Compute the union.
union <- length(set_1) + length(set_2) - intersection
# Jaccard index is just the number of shared genes divided by the number of non-shared genes.
jaccard_index <- intersection / union
return(jaccard_index)
}
jaccard_scores <- list()
for(listname_store in names(input_gene_list)){
vector_scores <- NULL
for(listname in names(input_gene_list)){
scores <- jaccard(set_1 = input_gene_list[[listname_store]], set_2 = input_gene_list[[listname]])
names(scores) <- listname
vector_scores <- append(vector_scores, round(scores, 2))
}
jaccard_scores[[listname_store]] <- vector_scores
}
jaccard_matrix <- as.matrix(as.data.frame(jaccard_scores))
colnames(jaccard_matrix) <- rownames(jaccard_matrix)
if (isTRUE(cluster)){
order <- rownames(jaccard_matrix)[stats::hclust(stats::dist(jaccard_matrix, method = "euclidean"), method = "ward.D")$order]
} else {
order <- rownames(jaccard_matrix)
}
jaccard_matrix <- jaccard_matrix[order, order]
if (isTRUE(remove.diagonal)){
jaccard_matrix[jaccard_matrix == 1] <- NA
}
data <- jaccard_matrix %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "x") %>%
tidyr::pivot_longer(cols = -dplyr::all_of("x"),
names_to = "y",
values_to = "score") %>%
dplyr::mutate("x" = factor(.data$x, levels = order),
"y" = factor(.data$y, levels = rev(order)))
limits <- c(min(data$score, na.rm = TRUE),
max(data$score, na.rm = TRUE))
assertthat::assert_that(limits[[1]] != limits[[2]],
msg = paste0(add_cross(), crayon_body("The "),
crayon_key(" jaccard similarity matrix "),
crayon_body(" has no different values. Try another gene set.")))
scale.setup <- compute_scales(sample = NULL,
feature = NULL,
assay = NULL,
reduction = NULL,
slot = NULL,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = FALSE,
from_data = TRUE,
limits.use = limits)
# Modify according to min.cutoff and max.cutoff.
if (!is.na(min.cutoff)){
data <- data %>%
dplyr::mutate("score" = ifelse(.data$score < min.cutoff, min.cutoff, .data$score))
}
if (!is.na(max.cutoff)){
data <- data %>%
dplyr::mutate("score" = ifelse(.data$score > max.cutoff, max.cutoff, .data$score))
}
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$x,
y = .data$y,
fill = .data$score)) +
ggplot2::geom_tile(color = grid.color, linewidth = 0.5, na.rm = TRUE)
if (base::isTRUE(values.show)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$score, values.round),
color = ifelse(abs(.data$score) > values.threshold, "white", "black")),
size = values.size) +
ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::coord_equal() +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$y))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$x))))
axis.parameters <- handle_axis(flip = FALSE,
group.by = "A",
group = "A",
counter = 1,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
p <- p +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p <- modify_continuous_legend(p = p,
legend.title = "Jaccard score",
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = 0.5,
legend.tickwidth = 0.5)
p <- p +
ggplot2::xlab("") +
ggplot2::ylab("") +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = "bottom",
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = "sans"),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10,
r = 0,
b = 0,
l = 40),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
}
return(p)
}
================================================
FILE: R/do_DimPlot.R
================================================
#' Generate dimensional reduction plots from a Seurat object.
#'
#' This function wraps \link[Seurat]{DimPlot}, adding publication-ready theming,
#' cell shuffling, rasterization, density contours, marginal distributions, and
#' cell border overlays.
#'
#' @inheritParams doc_function
#' @param idents.keep \strong{\code{\link[base]{character}}} | Vector of identities to keep. This will effectively set the rest of the cells that do not match the identities provided to NA, therefore coloring them according to na.value parameter.
#'
#' @param shuffle \strong{\code{\link[base]{logical}}} | Whether to shuffle the cells or not, so that they are not plotted cluster-wise. Recommended.
#' @param split.by.combined \strong{\code{\link[base]{logical}}} | Adds a combined view of the all the values before splitting them by \strong{\code{split.by}}. Think of this as a regular DimPlot added in front. This is set to \strong{\code{TRUE}} if \strong{\code{split.by}} is used in combination with \strong{\code{group.by}}.
#' @param legend.dot.border \strong{\code{\link[base]{logical}}} | Adds a black border around the dots in the legend.
#' @param order \strong{\code{\link[base]{character}}} | Vector of identities to be plotted. Either one with all identities or just some, which will be plotted last.
#' @param sizes.highlight \strong{\code{\link[base]{numeric}}} | Point size of highlighted cells using cells.highlight parameter.
#' @return A ggplot2 object containing a DimPlot.
#' @md
#' @export
#'
#' @example man/examples/examples_do_DimPlot.R
do_DimPlot <- function(sample,
reduction = NULL,
group.by = NULL,
split.by = NULL,
split.by.combined = TRUE,
colors.use = NULL,
colorblind = FALSE,
shuffle = TRUE,
order = NULL,
raster = FALSE,
pt.size = 1,
label = FALSE,
label.color = "black",
label.fill = "white",
label.size = 4,
label.box = TRUE,
repel = FALSE,
cells.highlight = NULL,
idents.highlight = NULL,
idents.keep = NULL,
sizes.highlight = 1,
ncol = NULL,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.title = NULL,
legend.position = "bottom",
legend.title.position = "top",
legend.ncol = NULL,
legend.nrow = NULL,
legend.icon.size = 4,
legend.byrow = FALSE,
legend.dot.border = TRUE,
raster.dpi = 2048,
dims = c(1, 2),
font.size = 14,
font.type = "sans",
na.value = "grey75",
plot_cell_borders = TRUE,
border.size = 2,
border.color = "black",
border.density = 1,
plot_marginal_distributions = FALSE,
marginal.type = "density",
marginal.size = 5,
marginal.group = TRUE,
plot.axes = FALSE,
plot_density_contour = FALSE,
contour.position = "bottom",
contour.color = "grey90",
contour.lineend = "butt",
contour.linejoin = "round",
contour_expand_axes = 0.25,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_DimPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
#sample <- check_Assay5(sample)
# Check the reduction.
reduction <- check_and_set_reduction(sample = sample, reduction = reduction)
# Check the dimensions.
dims <- check_and_set_dimensions(sample = sample, reduction = reduction, dims = dims)
# Check logical parameters.
logical_list <- list("label" = label,
"repel" = repel,
"shuffle" = shuffle,
"legend.byrow" = legend.byrow,
"raster" = raster,
"plot_marginal_distributions" = plot_marginal_distributions,
"marginal.group" = marginal.group,
"plot_cell_borders" = plot_cell_borders,
"plot.axes" = plot.axes,
"plot_density_contour" = plot_density_contour,
"label.box" = label.box,
"split.by.combined" = split.by.combined,
"legend.dot.border" = legend.dot.border,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pt.size" = pt.size,
"sizes.highlight" = sizes.highlight,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow,
"font.size" = font.size,
"legend.icon.size" = legend.icon.size,
"ncol" = ncol,
"raster.dpi" = raster.dpi,
"marginal.size" = marginal.size,
"border.size" = border.size,
"contour_expand_axes" = contour_expand_axes,
"label.size" = label.size,
"border.density" = border.density)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("legend.position" = legend.position,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"legend.title" = legend.title,
"cells.highlight" = cells.highlight,
"idents.keep" = idents.keep,
"order" = order,
"na.value" = na.value,
"idents.highlight" = idents.highlight,
"legend.title.position" = legend.title.position,
"font.type" = font.type,
"marginal.type" = marginal.type,
"border.color" = border.color,
"contour.position" = contour.position,
"contour.color" = contour.color,
"contour.lineend" = contour.lineend,
"contour.linejoin" = contour.linejoin,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Checks to ensure proper function.
group_by_and_split_by_used <- !(is.null(split.by)) & !(is.null(group.by))
group_by_and_highlighting_cells <- (!(is.null(cells.highlight)) | !(is.null(idents.highlight))) & !(is.null(group.by))
split_by_and_highlighting_cells <- (!(is.null(cells.highlight)) | !(is.null(idents.highlight))) & !(is.null(split.by))
order_and_shuffle_used <- !(is.null(order)) & isTRUE(shuffle)
assertthat::assert_that(!group_by_and_highlighting_cells,
msg = paste0(add_cross(), crayon_body("Either "),
crayon_key("group.by"),
crayon_body(" or "),
crayon_key("cells.highlight | idents.hightlight"),
crayon_body(" have to be set to "),
crayon_key("NULL"),
crayon_body(".")))
assertthat::assert_that(!split_by_and_highlighting_cells,
msg = paste0(add_cross(), crayon_body("Either "),
crayon_key("split.by"),
crayon_body(" or "),
crayon_key("cells.highlight | idents.hightlight"),
crayon_body(" have to be set to "),
crayon_key("NULL"),
crayon_body(".")))
if (base::isTRUE(group_by_and_split_by_used)){
assertthat::assert_that(base::isTRUE(split.by.combined),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("split.by.combined"),
crayon_body(" must be set to "),
crayon_key("TRUE"),
crayon_body(" when using a combination of "),
crayon_key("split.by"),
crayon_body(" and "),
crayon_key("group.by"),
crayon_body(".")))
}
if (order_and_shuffle_used){
warning(paste0(add_warning(), crayon_body("Setting up a custom order with paramter "),
crayon_key("order"),
crayon_body(" when "),
crayon_key("shuffle = TRUE"),
crayon_body(" might result in unexpected behaviors.\nPlease, consider using it alongside "),
crayon_key("shuffle = FALSE"),
crayon_body(".")), call. = FALSE)
}
# Check for label.color.
## Check for the colors assigned to the labels if label = TRUE.
check_colors(label.color, parameter_name = "label.color")
## Check the color assigned to NAs.
check_colors(na.value, parameter_name = "na.value")
## Check the color assigned to border.color.
check_colors(border.color, parameter_name = "border.color")
## Check the color assigned to contour.color.
check_colors(contour.color, parameter_name = "contour.color")
## If the user provides more than one color to na.value, stop the function.
assertthat::assert_that(length(na.value) == 1,
msg = paste0(add_cross(), crayon_body("Please, provide only "),
crayon_key("one color"),
crayon_body(" to parameter "),
crayon_key("na.value"),
crayon_body(".")))
## Check that the contour_expand_axes is between 0 and 1.
assertthat::assert_that(contour_expand_axes <= 1,
msg = paste0(add_cross(), crayon_body("Please, provide a value "),
crayon_key("lower or equal to 1"),
crayon_body(" to parameter "),
crayon_key("contour_expand_axes"),
crayon_body(".")))
assertthat::assert_that(contour_expand_axes >= 0,
msg = paste0(add_cross(), crayon_body("Please, provide a value "),
crayon_key("lower or equal to 1"),
crayon_body(" to parameter "),
crayon_key("contour_expand_axes"),
crayon_body(".")))
# If the user provides raster = TRUE but the pt.size is less than 1, warn it.
if (isTRUE(raster) & pt.size < 1){
warning(paste0(add_warning(), crayon_body("Setting "),
crayon_key("raster = TRUE"),
crayon_body(" and "),
crayon_key("pt.size < 1"),
crayon_body("will result in the cells being plotted as a "),
crayon_key("cross"),
crayon_body(" instead of dots.\nThis behaviour can not be modified, but can be avoided by using "),
crayon_key("pt.size >= 1"),
crayon_body(".")), call. = FALSE)
}
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = marginal.type, parameter_name = "marginal.type")
check_parameters(parameter = contour.lineend, parameter_name = "contour.lineend")
check_parameters(parameter = contour.linejoin, parameter_name = "contour.linejoin")
check_parameters(parameter = contour.position, parameter_name = "contour.position")
check_parameters(parameter = border.density, parameter_name = "border.density")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
# If the user has not provided colors.
if (is.null(colors.use)){
colors.use <- {
# Default parameters.
default_parameters <- is.null(group.by) & is.null(split.by) & is.null(cells.highlight) & is.null(idents.highlight)
# Group.by was used.
group_by_is_used <- !(is.null(group.by)) & is.null(split.by) & is.null(cells.highlight) & is.null(idents.highlight)
# Split.by was used.
split_by_is_used <- is.null(group.by) & !(is.null(split.by)) & is.null(cells.highlight) & is.null(idents.highlight)
# Cells.highlight or idents.highlight was used.
highlighting_cells <- is.null(group.by) & is.null(split.by) & (!(is.null(cells.highlight)) | !(is.null(idents.highlight)))
if (isTRUE(default_parameters)){
# Generate the color scale based on the levels assigned to the sample.
colors.use <- generate_color_scale(levels(sample), colorblind = colorblind)
colors.use <- colors.use[levels(sample)]
} else if (isTRUE(group_by_is_used) | isTRUE(group_by_and_split_by_used)){
# Retrieve the unique values in group.by metadata variable.
data.use <- sample[[]][, group.by, drop = FALSE]
# If the variable is a factor, use the levels as order. If not, order the values alphabetically.
names.use <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
# Generate the color scale to be used based on the unique values of group.by.
colors.use <- generate_color_scale(names.use, colorblind = colorblind)
colors.use <- colors.use[names.use]
} else if (isTRUE(split_by_is_used)){
# Retrieve the unique values in split.by metadata variable.
data.use <- sample[[]][, split.by, drop = FALSE]
# If the variable is a factor, use the levels as order. If not, order the values alphabetically.
names.use <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
# Generate the color scale based on the unique values of split.by
colors.use <- generate_color_scale(names.use, colorblind = colorblind)
colors.use <- colors.use[names.use]
} else if (isTRUE(highlighting_cells)){
# If the user wants to highlight some cells, use this color.
colors.use <- "#0A305F"
}
}
# For split.by + group.by cases.
colors.use.original <- colors.use
# But, if the user has provided a custom color palette.
} else {
# Check that the provided values are valid color representations.
check_colors(colors.use, parameter_name = "colors.use")
# If no further parameters are used.
default_parameters <- is.null(group.by) & is.null(split.by) & is.null(cells.highlight) & is.null(idents.highlight)
# Group.by was used.
group_by_is_used <- !(is.null(group.by)) & is.null(split.by) & is.null(cells.highlight) & is.null(idents.highlight)
# Split.by was used.
split_by_is_used <- is.null(group.by) & !(is.null(split.by)) & is.null(cells.highlight) & is.null(idents.highlight)
# When either cells.highlight or idents.highlight was used.
highlighting_cells <- is.null(group.by) & is.null(split.by) & (!(is.null(cells.highlight)) | !(is.null(idents.highlight)))
# For split.by + group.by cases.
colors.use.original <- colors.use
# When running under default parameters.
if (isTRUE(default_parameters)){
# Check that the color palette has the right amount of named colors with regards to the current identities.
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
idents.keep = idents.keep)
if (is.null(idents.keep)){
colors.use <- colors.use[levels(sample)]
} else {
colors.use <- colors.use[levels(sample)[idents.keep]]
}
# When using group.by or a combination of group.by and split.by.
} else if (isTRUE(group_by_is_used) | isTRUE(group_by_and_split_by_used)){
# Retrieve the unique values in group.by metadata variable.
data.use <- sample[[]][, group.by, drop = FALSE]
# Check that the color palette has the right amount of named colors with regards to group.by values.
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
grouping_variable = group.by,
idents.keep = idents.keep)
names.use <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
colors.use <- colors.use[names.use]
# When using split.by.
} else if (isTRUE(split_by_is_used)){
# Retrieve the unique values in split.by metadata variable.
data.use <- sample[[]][, split.by, drop = FALSE]
# Check that the color palette has the right amount of named colors with regards to split.by values.
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
grouping_variable = split.by,
idents.keep = idents.keep)
names.use <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
colors.use <- colors.use[names.use]
# When highlighting cells.
} else if (isTRUE(highlighting_cells)){
# Stop the execution if more than one color is provided to highlight the cells.
assertthat::assert_that(length(colors.use) == 1,
msg = paste0(add_cross(), crayon_body("Please, provide only "),
crayon_key("one color"),
crayon_body(" to "),
crayon_key("cells.highlight"),
crayon_body(" or "),
crayon_key("idents.highlight"),
crayon_body(".")))
}
}
# Compute the colors for the labels.
if (isTRUE(label)){
if (isTRUE(label.box)){
if (is.null(label.fill)){
colors.use.label.fill <- colors.use
} else {
# Check that only one color has been provided to label.fill.
assertthat::assert_that(length(label.fill) == 1,
msg = paste0(add_cross(), crayon_body("Please, provide only "),
crayon_key("one color"),
crayon_body(" to "),
crayon_key("label.fill"),
crayon_body(" or "),
crayon_key("NULL"),
crayon_body(".")))
# And check that is a valid color.
check_colors(label.fill, parameter_name = "label.fill")
colors.use.label.fill <- rep(label.fill, length(colors.use))
}
}
}
# Set cells to NA according to idents.keep.
# If the user does not want to highlight cells or split by identities but wants to remove some identities.
idents_keep_used <- is.null(cells.highlight) & is.null(idents.highlight) & !(is.null(idents.keep))
if (isTRUE(idents_keep_used)){
# CONDITION: both group.by and split.by are not used.
group_by_and_split_by_are_null <- is.null(group.by) & is.null(split.by)
# CONDITION: group.by is used.
group_by_is_used <- !(is.null(group.by)) & is.null(split.by)
# CONDITION: split.by is used.
split_by_is_used <- is.null(group.by) & !(is.null(split.by))
# When running under default parameters.
if (isTRUE(group_by_and_split_by_are_null)){
# Check that idents.keep matches the values and if not, stop the execution.
assertthat::assert_that(isTRUE(length(idents.keep) == sum(idents.keep %in% levels(sample))),
msg = paste0(add_cross(), crayon_body("All the values in "),
crayon_key("idents.keep"),
crayon_body(" must be in "),
crayon_key("levels(sample"),
crayon_body(".")))
# Set the identities that the user wants to exclude as NA.
Seurat::Idents(sample)[!(Seurat::Idents(sample) %in% idents.keep)] <- NA
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
idents.keep = idents.keep)
# If split.by is used instead.
} else if (group_by_and_split_by_used){
# Check that the values in idents.keep are in the unique values of split.by.
assertthat::assert_that(isTRUE(length(idents.keep) == sum(idents.keep %in% unique(sample@meta.data[, split.by]))),
msg = paste0(add_cross(), crayon_body("All the values in "),
crayon_key("idents.keep"),
crayon_body(" must be in the "),
crayon_key("split.by"),
crayon_body(" metadata provided.")))
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
grouping_variable = group.by)
} else if (split_by_is_used){
# Check that the values in idents.keep are in the unique values of split.by.
assertthat::assert_that(isTRUE(length(idents.keep) == sum(idents.keep %in% unique(sample@meta.data[, split.by]))),
msg = paste0(add_cross(), crayon_body("All the values in "),
crayon_key("idents.keep"),
crayon_body(" must be in the "),
crayon_key("split.by"),
crayon_body(" metadata provided.")))
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
grouping_variable = split.by,
idents.keep = idents.keep)
# When using group.by, check with the values in group.by.
} else if (group_by_is_used) {
# Check that idents.keep matches the values, if not, stop the execution.
assertthat::assert_that(isTRUE(length(idents.keep) == sum(idents.keep %in% unique(sample@meta.data[, group.by]))),
msg = paste0(add_cross(), crayon_body("All the values in "),
crayon_key("idents.keep"),
crayon_body(" must be in the "),
crayon_key("group.by"),
crayon_body(" metadata variable provided.")))
# Convert to NA values in group.by not included in the user's selected values.
sample@meta.data[, group.by][!(sample@meta.data[, group.by] %in% idents.keep)] <- NA
colors.use <- check_consistency_colors_and_names(sample = sample,
colors = colors.use,
grouping_variable = group.by,
idents.keep = idents.keep)
}
}
# Generate base layer.
out <- compute_umap_layer(sample = sample,
labels = colnames(sample@reductions[[reduction]][[]])[dims],
pt.size = pt.size,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
na.value = na.value,
n = 100)
base_layer <- out$base_layer
na_layer <- out$na_layer
# PLOTTING
# If raster = TRUE, add 1 to pt.size to keep consistency between plots.
# If the UMAP does not need to be split in multiple panes (default case).
# CONDITION: Not highligting cells and not using split.by.
not_highlighting_and_not_split_by <- is.null(cells.highlight) & is.null(idents.highlight) & is.null(split.by)
# CONDITION: Using split.by.
split_by_used <- is.null(cells.highlight) & is.null(idents.highlight) & !(is.null(split.by))
# CONDITION: highlighting cells.
highlighting_cells <- !(is.null(cells.highlight)) | !(is.null(idents.highlight))
# When running under default parameters or using group.by
if (not_highlighting_and_not_split_by){
if (utils::packageVersion("Seurat") >= "4.1.0"){
p <- Seurat::DimPlot(if (is.null(idents.keep)) {sample} else {if (is.null(group.by)) {sample[, Seurat::Idents(sample) %in% idents.keep]} else {sample[, sample@meta.data[, group.by] %in% idents.keep]}},
reduction = reduction,
label = label,
dims = dims,
repel = repel,
label.box = label.box,
label.color = label.color,
label.size = label.size,
na.value = na.value,
shuffle = shuffle,
order = order,
pt.size = pt.size,
group.by = group.by,
cols = colors.use,
raster = raster,
raster.dpi = c(raster.dpi, raster.dpi),
ncol = ncol)
} else { # nocov start
p <- Seurat::DimPlot(if (is.null(idents.keep)) {sample} else {if (is.null(group.by)) {sample[, Seurat::Idents(sample) %in% idents.keep]} else {sample[, sample@meta.data[, group.by] %in% idents.keep]}},
reduction = reduction,
label = label,
dims = dims,
repel = repel,
label.box = label.box,
label.color = label.color,
label.size = label.size,
na.value = na.value,
shuffle = shuffle,
order = order,
pt.size = pt.size,
group.by = group.by,
cols = colors.use,
raster = raster,
ncol = ncol)
} # nocov end
if (base::isTRUE(legend.dot.border)){
p <- p &
ggplot2::guides(color = ggplot2::guide_legend(ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size,
color = "black",
fill = colors.use,
shape = 21),
title = legend.title,
title.position = legend.title.position))
} else {
p <- p &
ggplot2::guides(color = ggplot2::guide_legend(ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size),
title = legend.title,
title.position = legend.title.position))
}
if (isTRUE(label)){
if (isTRUE(label.box)){
if (is.null(label.fill)){
colors.use.label.fill <- colors.use
} else {
colors.use.label.fill <- rep(label.fill, length(colors.use))
}
p <- add_scale(p = p,
function_use = ggplot2::scale_fill_manual(values = colors.use.label.fill),
scale = "fill")
}
p$layers[[length(p$layers)]]$aes_params$fontface <- "bold"
}
if (!(is.null(group.by))){
# Remove automatic title inserted by Seurat.
p <- p & ggplot2::ggtitle("")
}
# Add another layer of black dots to make the colored ones stand up.
if (!is.null(idents.keep)){
if (isTRUE(plot_cell_borders)){
sample.use <- if (is.null(group.by)) {sample[, Seurat::Idents(sample) %in% idents.keep]} else {sample[, sample@meta.data[, group.by] %in% idents.keep]}
out <- compute_umap_layer(sample = sample.use,
labels = colnames(sample.use@reductions[[reduction]][[]])[dims],
pt.size = pt.size,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
na.value = na.value,
n = 100)
base_layer.subset <- out$base_layer
p$layers <- append(base_layer.subset, p$layers)
}
# Add NA layer.
p$layers <- append(na_layer, p$layers)
}
# Add cell borders.
if (isTRUE(plot_cell_borders)){
p$layers <- append(base_layer, p$layers)
}
if (isTRUE(plot_density_contour)){
data <- ggplot2::ggplot_build(p)
density_layer <- ggplot2::stat_density_2d(data = data$data[[1]],
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = contour.color,
lineend = contour.lineend,
linejoin = contour.linejoin)
if (contour.position == "bottom"){
p$layers <- append(density_layer, p$layers)
} else if (contour.position == "top"){
p$layers <- append(p$layers, density_layer)
}
min_x <- min(data$data[[1]]$x) * (1 + contour_expand_axes)
max_x <- max(data$data[[1]]$x) * (1 + contour_expand_axes)
min_y <- min(data$data[[1]]$y) * (1 + contour_expand_axes)
max_y <- max(data$data[[1]]$y) * (1 + contour_expand_axes)
# Expand axes limits to allocate the new contours.
suppressMessages({
p <- p +
ggplot2::xlim(c(min_x, max_x)) +
ggplot2::ylim(c(min_y, max_y))
})
}
# Add theme settings to all plots.
p <- p &
ggplot2::theme_minimal(base_size = font.size) &
ggplot2::theme(plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.justification = "center",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = if (legend.position != "none") {ggplot2::element_text(face = legend.title.face)} else {ggplot2::element_blank()},
legend.position = legend.position,
panel.grid = ggplot2::element_blank(),
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
} else if (isTRUE(group_by_and_split_by_used) | isTRUE(split_by_used)){
list.plots <- list()
unique_values <- if(is.factor(sample@meta.data[, split.by])){levels(sample@meta.data[, split.by])} else {sort(unique(sample@meta.data[, split.by]))}
if (!is.null(idents.keep)){
unique_values <- unique_values[unique_values %in% idents.keep]
}
# If group.by and split.by are used, add a general view that will have a legend with all parameters.
p.extra <- do_DimPlot(sample = sample,
reduction = reduction,
group.by = ifelse(isTRUE(group_by_and_split_by_used), group.by, split.by),
split.by = NULL,
colors.use = colors.use.original,
shuffle = shuffle,
order = order,
raster = raster,
pt.size = pt.size,
label = label,
label.color = label.color,
label.fill = label.fill,
label.size = label.size,
label.box = label.box,
repel = repel,
cells.highlight = NULL,
idents.highlight = NULL,
idents.keep = NULL,
sizes.highlight = sizes.highlight,
ncol = ncol,
plot.title = ifelse(isTRUE(group_by_and_split_by_used), group.by, split.by),
plot.subtitle = NULL,
plot.caption = NULL,
legend.title = legend.title,
legend.position = legend.position,
legend.title.position = legend.title.position,
legend.ncol = legend.ncol,
legend.nrow = legend.nrow,
legend.icon.size = legend.icon.size,
legend.byrow = legend.byrow,
raster.dpi = raster.dpi,
dims = dims,
font.size = font.size,
font.type = font.type,
na.value = na.value,
plot_cell_borders = plot_cell_borders,
border.size = border.size,
border.color = border.color,
border.density = border.density,
plot_marginal_distributions = plot_marginal_distributions,
marginal.type = marginal.type,
marginal.size = marginal.size,
marginal.group = marginal.group,
plot.axes = plot.axes,
plot_density_contour = plot_density_contour,
contour.position = contour.position,
contour.color = contour.color,
contour.lineend = contour.lineend,
contour.linejoin = contour.linejoin,
contour_expand_axes = contour_expand_axes,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
p.extra <- p.extra + ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5, color = "black"))
# Add plot to list.
if (base::isTRUE(split.by.combined)){
list.plots[[1]] <- p.extra
}
num_values <- length(unique_values)
for (i in seq_len(num_values)){
value <- unique_values[i]
# Generate a middle layer for the missing values after split.by.
sample.use <- sample[, sample@meta.data[, split.by] == value]
group.by.value <- if (is.null(group.by)) {split.by} else {group.by}
if (utils::packageVersion("Seurat") >= "4.1.0"){
p.loop <- Seurat::DimPlot(sample.use,
reduction = reduction,
group.by = group.by.value,
label = label,
dims = dims,
repel = repel,
label.box = label.box,
label.color = label.color,
label.size = label.size,
na.value = na.value,
shuffle = shuffle,
order = order,
pt.size = pt.size,
cols = colors.use,
raster = raster,
raster.dpi = c(raster.dpi, raster.dpi))
} else { # nocov start
p.loop <- Seurat::DimPlot(sample.use,
reduction = reduction,
group.by = group.by.value,
label = label,
dims = dims,
repel = repel,
label.box = label.box,
label.color = label.color,
label.size = label.size,
na.value = na.value,
shuffle = shuffle,
order = order,
pt.size = pt.size,
cols = colors.use,
raster = raster)
} # nocov end
# Add plot.title.
p.loop <- p.loop +
ggplot2::labs(title = value)
used.values <- unique(sample.use@meta.data[ , group.by.value])
if (base::isTRUE(legend.dot.border)){
p.loop <- p.loop &
ggplot2::guides(color = ggplot2::guide_legend(ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size,
color = "black",
fill = colors.use[used.values],
shape = 21),
title = legend.title,
title.position = legend.title.position))
} else {
p.loop <- p.loop &
ggplot2::guides(color = ggplot2::guide_legend(ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size),
title = legend.title,
title.position = legend.title.position))
}
if (isTRUE(label)){
if (isTRUE(label.box)){
p.loop <- add_scale(p = p.loop,
function_use = ggplot2::scale_fill_manual(values = colors.use.label.fill),
scale = "fill")
}
p.loop$layers[[length(p.loop$layers)]]$aes_params$fontface <- "bold"
}
# Add another layer of black dots to make the colored ones stand up.
if (isTRUE(plot_cell_borders)){
out <- compute_umap_layer(sample = sample.use,
labels = colnames(sample.use@reductions[[reduction]][[]])[dims],
pt.size = pt.size,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
na.value = na.value,
n = 100)
base_layer.subset <- out$base_layer
p.loop$layers <- append(base_layer.subset, p.loop$layers)
}
# Add NA layer.
p.loop$layers <- append(na_layer, p.loop$layers)
# Add cell borders.
if (isTRUE(plot_cell_borders)){
p.loop$layers <- append(base_layer, p.loop$layers)
suppressMessages({
p.loop <- p.loop +
ggplot2::scale_x_continuous(limits = c(min(p.loop$layers[[1]]$data$x),
max(p.loop$layers[[1]]$data$x))) +
ggplot2::scale_y_continuous(limits = c(min(p.loop$layers[[1]]$data$y),
max(p.loop$layers[[1]]$data$y)))
})
}
if (isTRUE(plot_density_contour)){
data <- ggplot2::ggplot_build(p.loop)
density_layer <- ggplot2::stat_density_2d(data = data$data[[1]],
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = contour.color,
lineend = contour.lineend,
linejoin = contour.linejoin)
if (contour.position == "bottom"){
p.loop$layers <- append(density_layer, p.loop$layers)
} else if (contour.position == "top"){
p.loop$layers <- append(p.loop$layers, density_layer)
}
min_x <- min(data$data[[1]]$x) * (1 + contour_expand_axes)
max_x <- max(data$data[[1]]$x) * (1 + contour_expand_axes)
min_y <- min(data$data[[1]]$y) * (1 + contour_expand_axes)
max_y <- max(data$data[[1]]$y) * (1 + contour_expand_axes)
# Expand axes limits to allocate the new contours.
suppressMessages({
p.loop <- p.loop +
ggplot2::xlim(c(min_x, max_x)) +
ggplot2::ylim(c(min_y, max_y))
})
}
p.loop <- p.loop +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0.5),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.justification = "center",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = if (legend.position != "none") {ggplot2::element_text(face = legend.title.face)} else {ggplot2::element_blank()},
panel.grid = ggplot2::element_blank(),
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.position = "none")
list.plots[[value]] <- p.loop
}
p <- patchwork::wrap_plots(list.plots, ncol = ncol, guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position))
if (base::isTRUE(split.by.combined)){
p[[1]]$labels$title <- ifelse(isTRUE(group_by_and_split_by_used), group.by, split.by)
}
}
# If the user wants to highlight some of the cells.
else if (highlighting_cells){
# Compute the cells to highlight.
if (is.null(idents.highlight) & !(is.null(cells.highlight))){
# Only if cells.highlight parameters is used.
cells.use <- cells.highlight
} else if (!(is.null(idents.highlight)) & is.null(cells.highlight)){
# Only if idents.highlight parameter is used.
# Check if the provided identities are part of the active identities in the object.
check_identity(sample = sample, identities = idents.highlight)
cells.use <- names(Seurat::Idents(sample)[Seurat::Idents(sample) %in% idents.highlight])
} else if (!(is.null(idents.highlight)) & !(is.null(cells.highlight))){
# Check if the provided identities are part of the active identities in the object.
check_identity(sample = sample, identities = idents.highlight)
# Both idents.highlight and cells.highlight are used.
cells.1 <- cells.highlight
cells.2 <- names(Seurat::Idents(sample)[Seurat::Idents(sample) %in% idents.highlight])
cells.use <- unique(c(cells.1, cells.2))
}
sample$selected_cells <- ifelse(colnames(sample) %in% cells.use, "Selected cells", NA)
colors.use.highlight <- c("Selected cells" = colors.use)
if (utils::packageVersion("Seurat") >= "4.1.0"){
p <- Seurat::DimPlot(sample[, cells.use],
reduction = reduction,
group.by = "selected_cells",
dims = dims,
pt.size = pt.size,
raster = raster,
raster.dpi = c(raster.dpi, raster.dpi),
ncol = ncol,
cols = colors.use.highlight,
na.value = "#bfbfbf00")
} else { # nocov start
p <- Seurat::DimPlot(sample[, cells.use],
group.by = "selected_cells",
reduction = reduction,
dims = dims,
pt.size = pt.size,
raster = raster,
ncol = ncol,
cols = colors.use.highlight,
na.value = "#bfbfbf00")
} # nocov end
# Remove unwanted "selected_cells" title.
p <- p & ggplot2::labs(title = "")
if (base::isTRUE(legend.dot.border)){
p <- p &
ggplot2::guides(color = ggplot2::guide_legend(ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size,
color = "black",
fill = colors.use,
shape = 21),
title = legend.title,
title.position = legend.title.position))
} else {
p <- p &
ggplot2::guides(color = ggplot2::guide_legend(ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size),
title = legend.title,
title.position = legend.title.position))
}
# Add cell borders.
if (isTRUE(plot_cell_borders)){
# Compute extra layer for the highlighted cells.
out <- compute_umap_layer(sample = sample[, cells.use],
labels = colnames(sample[, cells.use]@reductions[[reduction]][[]])[dims],
pt.size = sizes.highlight,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
n = 100,
skip.density = TRUE)
base_layer_subset <- out$base_layer
p$layers <- append(base_layer_subset, p$layers)
p$layers <- append(na_layer, p$layers)
p$layers <- append(base_layer, p$layers)
suppressMessages({
p <- p +
ggplot2::scale_x_continuous(limits = c(min(p$layers[[1]]$data$x),
max(p$layers[[1]]$data$x))) +
ggplot2::scale_y_continuous(limits = c(min(p$layers[[1]]$data$y),
max(p$layers[[1]]$data$y)))
})
}
if (isTRUE(plot_density_contour)){
data <- ggplot2::ggplot_build(p)
density_layer <- ggplot2::stat_density_2d(data = data$data[[1]],
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = contour.color,
lineend = contour.lineend,
linejoin = contour.linejoin)
if (contour.position == "bottom"){
p$layers <- append(density_layer, p$layers)
} else if (contour.position == "top"){
p$layers <- append(p$layers, density_layer)
}
min_x <- min(data$data[[1]]$x) * (1 + contour_expand_axes)
max_x <- max(data$data[[1]]$x) * (1 + contour_expand_axes)
min_y <- min(data$data[[1]]$y) * (1 + contour_expand_axes)
max_y <- max(data$data[[1]]$y) * (1 + contour_expand_axes)
# Expand axes limits to allocate the new contours.
suppressMessages({
p <- p +
ggplot2::xlim(c(min_x, max_x)) +
ggplot2::ylim(c(min_y, max_y))
})
}
# Titles in split.by are centered by default.
hjust_use <- if(split_by_used){0.5} else {0}
# Add theme settings to all plots.
p <- p &
ggplot2::theme_minimal(base_size = font.size) &
ggplot2::theme(plot.title = ggplot2::element_text(face = plot.title.face, hjust = hjust_use),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.justification = "center",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = if (legend.position != "none") {ggplot2::element_text(face = legend.title.face)} else {ggplot2::element_blank()},
legend.position = legend.position,
panel.grid = ggplot2::element_blank(),
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
}
# Add font.family to geom_text and geom_label.
if (length(p$patches$plots) > 0){
num.plots <- length(p$patches$plots)
} else {
num.plots <- 1
}
for (plot.use in seq(1, num.plots)){
for (layer.use in seq(1, length(p[[plot.use]]$layers))){
if (sum(stringr::str_detect(class(p[[plot.use]]$layers[[layer.use]]$geom), "GeomText|GeomLabel"))){
p[[plot.use]]$layers[[layer.use]]$aes_params$family <- font.type
}
}
}
# Add plot title to the plots.
if (!is.null(plot.title)){
if (!(is.null(split.by))){
p <- p +
patchwork::plot_annotation(title = plot.title)
} else {
p <- p &
ggplot2::labs(title = plot.title)
}
}
# Add plot subtitle to the plots.
if (!is.null(plot.subtitle)){
if (!(is.null(split.by))){
p <- p +
patchwork::plot_annotation(subtitle = plot.subtitle)
} else {
p <- p +
ggplot2::labs(subtitle = plot.subtitle)
}
}
# Add plot caption to the plots.
if (!is.null(plot.caption)){
if (!(is.null(split.by))){
p <- p +
patchwork::plot_annotation(caption = plot.caption)
} else {
p <- p +
ggplot2::labs(caption = plot.caption)
}
}
if (base::isFALSE(plot.axes)){
p <- p &
ggplot2::theme(axis.title = ggplot2::element_blank(),
axis.text = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.line = ggplot2::element_blank())
} else {
p <- p &
ggplot2::theme(axis.title = ggplot2::element_text(face = axis.title.face),
axis.text = ggplot2::element_text(face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"))
}
# Add marginal plots.
if (not_highlighting_and_not_split_by & isTRUE(plot_marginal_distributions & base::isFALSE(plot_cell_borders))){
# Remove annoying warnings when violin is used as marginal distribution.
if (marginal.type == "violin"){
p <- suppressWarnings({ggExtra::ggMarginal(p = p,
groupColour = ifelse(isTRUE(marginal.group), TRUE, FALSE),
groupFill = ifelse(isTRUE(marginal.group), TRUE, FALSE),
type = marginal.type,
size = marginal.size)})
} else {
p <- ggExtra::ggMarginal(p = p,
groupColour = ifelse(isTRUE(marginal.group), TRUE, FALSE),
groupFill = ifelse(isTRUE(marginal.group), TRUE, FALSE),
type = marginal.type,
size = marginal.size)
}
# Transform back to ggplot2 object.
p <- ggplotify::as.ggplot(p)
# Fix for the plot backgrounds after applying ggMarginal.
p$theme$plot.background <- ggplot2::element_rect(fill = "white", color = "white")
p$theme$legend.background <- ggplot2::element_rect(fill = "white", color = "white")
p$theme$panel.background <- ggplot2::element_rect(fill = "white", color = "white")
} else if (isTRUE(plot_marginal_distributions)) {
stop(paste0(add_cross(),
crayon_body("Marginal distributions can not be used alongside when splitting by categories ("),
crayon_key("split.by"),
crayon_body("), highlighting cells ("),
crayon_key("cells.highlight/idents.highlight"),
crayon_body(") or plotting cell borders ("),
crayon_key("plot_cell_borders"),
crayon_body(").")), call. = FALSE)
}
# Return the final plot.
return(p)
}
================================================
FILE: R/do_DotPlot.R
================================================
#' Generate Dot plots of gene expression across cell groups.
#'
#' This function generates dot plots using ggplot2, displaying average
#' expression and percent of expressing cells per group, with optional
#' clustering of identities and features, and Z-score normalization.
#'
#' @inheritParams doc_function
#' @param cluster.identities \strong{\code{\link[base]{logical}}} | Whether to cluster the identities (groups) based on the expression of the features.
#' @param cluster.features \strong{\code{\link[base]{logical}}} | Whether to cluster the features (genes) based on their expression across identities.
#' @param zscore.data \strong{\code{\link[base]{logical}}} | Whether to compute Z-scores instead of showing average expression values. This allows to see, for each gene, which group has the highest average expression, but prevents you from comparing values across genes. Can not be used with slot = "scale.data" or with split.by.
#' @param dot.min \strong{\code{\link[base]{numeric}}} | Ranges from 0 to 100. Filter out dots whose Percent Expressed falls below this threshold.
#'
#' @return A ggplot2 object containing a Dot Plot.
#' @export
#'
#' @example man/examples/examples_do_DotPlot.R
do_DotPlot <- function(sample,
features,
assay = NULL,
slot = "data",
group.by = NULL,
split.by = NULL,
zscore.data = FALSE,
min.cutoff = NA,
max.cutoff = NA,
dot.min = 5,
enforce_symmetry = ifelse(base::isTRUE(zscore.data), TRUE, FALSE),
legend.title = NULL,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
dot.scale = 8,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
font.size = 14,
font.type = "sans",
cluster.identities = FALSE,
cluster.features = FALSE,
flip = FALSE,
axis.text.x.angle = 45,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
diverging.palette = "RdBu",
diverging.direction = -1,
na.value = "grey75",
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_DotPlot")
check_Seurat(sample = sample)
# Check the assay.
out <- check_and_set_assay(sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
# Check slot.
slot <- if(is.null(slot)){"data"} else {slot}
# Check logical parameters.
logical_list <- list("flip" = flip,
"cluster.identities" = cluster.identities,
"cluster.features" = cluster.features,
"use_viridis" = use_viridis,
"plot.grid" = plot.grid,
"enforce_symmetry" = enforce_symmetry,
"legend.byrow" = legend.byrow,
"zscore.data" = zscore.data)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("dot.scale" = dot.scale,
"font.size" = font.size,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"viridis.direction" = viridis.direction,
"axis.text.x.angle" = axis.text.x.angle,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow,
"dot.min" = dot.min)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("legend.position" = legend.position,
"plot.title" = plot.title,
"features" = unlist(features),
"xlab" = xlab,
"ylab" = ylab,
"group.by" = group.by,
"split.by" = split.by,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"viridis.palette" = viridis.palette,
"grid.color" = grid.color,
"grid.type" = grid.type,
"sequential.palette" = sequential.palette,
"diverging.palette" = diverging.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"legend.title" = legend.title,
"slot" = slot)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
`%>%` <- magrittr::`%>%`
# Check the features.
features <- check_feature(sample = sample, features = features, permissive = TRUE)
features <- remove_duplicated_features(features = features)
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(na.value, parameter_name = "na.value")
check_colors(grid.color, parameter_name = "grid.color")
if (base::isTRUE(zscore.data)){
assertthat::assert_that(base::isTRUE(enforce_symmetry),
msg = paste0(add_cross(), crayon_body("Please set "),
crayon_key("enforce_symmetry"),
crayon_body(" to "),
crayon_key("TRUE"),
crayon_body(" when scaling the data. This allows for a "),
crayon_key("centered"),
crayon_body(" color scale around "),
crayon_key("0"),
crayon_body(".")))
assertthat::assert_that(slot == "data",
msg = paste0(add_cross(), crayon_body("Please set "),
crayon_key("slot"),
crayon_body(" to "),
crayon_key('"data"'),
crayon_body(" when scaling the data. Performing Z-scaling over "),
crayon_key("already scaled"),
crayon_body(" data is "),
crayon_key("not advisable"),
crayon_body(".")))
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = TRUE)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
center_on_value <- FALSE
value_center <- NULL
}
if (is.list(features)){
assertthat::assert_that(!is.null(names(features)),
msg = paste0(add_cross(), crayon_body("Please provide features as a "),
crayon_key("named list"),
crayon_body(" and not as a "),
crayon_key("regular list"),
crayon_body(".")))
assertthat::assert_that(is.null(split.by),
msg = paste0(add_cross(), crayon_body("Please either provide features as a "),
crayon_key("named list"),
crayon_body(" or set up "),
crayon_key("split by"),
crayon_body(". A combination of both is not allowed.")))
}
if (!is.null(split.by)){
assertthat::assert_that(base::isFALSE(cluster.identities) & base::isFALSE(cluster.features),
msg = paste0(add_cross(), crayon_body("Please when using "),
crayon_key("split.by"),
crayon_body(" set both "),
crayon_key("cluster.identities"),
crayon_body(" and "),
crayon_key("cluster.features"),
crayon_body(" to "),
crayon_key("FALSE"),
crayon_body(".")))
assertthat::assert_that(base::isFALSE(zscore.data),
msg = paste0(add_cross(), crayon_body("Please when using "),
crayon_key("split.by"),
crayon_body(" set "),
crayon_key("zscore.data"),
crayon_body(" to "),
crayon_key("FALSE"),
crayon_body(".")))
}
# Workaround parameter depreciation.
# nocov start
if (base::isTRUE(utils::packageVersion("Seurat") < "4.9.9")){
data <- Seurat::GetAssayData(object = sample,
assay = assay,
slot = slot)
} else {
data <- SeuratObject::LayerData(object = sample,
assay = assay,
layer = slot)
}
# nocov end
# Select features.
if (is.list(features)){
genes.unique <- unique(unlist(features))
# Remove duplicates across lists.
features.use <- list()
start <- 1
# Add back in the original order
for (name in names(features)) {
len <- length(features[[name]])
features.use[[name]] <- genes.unique[start:(start + len - 1)]
start <- start + len
}
# Get the length of the longest list.
max_len <- max(lengths(features.use))
# Get a padded list
df.map <- as.data.frame(lapply(features.use, function(x) c(x, rep(NA, max_len - length(x)))), check.names = FALSE) %>%
tidyr::pivot_longer(cols = dplyr::everything(),
names_to = "Name",
values_to = "Gene") %>%
dplyr::mutate("Name" = factor(.data$Name, levels = names(features)))
features.use <- unique(unlist(unname(features)))[!duplicated(unique(unlist(unname(features))))]
} else {
features.use <- features
}
selection <- c(split.by, group.by, "Gene", "Avg.Exp", "P.Exp")
# Split features into gene features (in assay) and metadata features (in meta.data).
gene_features <- features.use[features.use %in% rownames(data)]
meta_features <- features.use[features.use %in% colnames(sample@meta.data)]
# Build long-format data from gene features (assay matrix).
if (length(gene_features) > 0) {
data_genes <- data[gene_features, , drop = FALSE] %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Gene") %>%
tidyr::pivot_longer(cols = -"Gene",
values_to = "Expression",
names_to = "Cell")
} else {
data_genes <- NULL
}
# Build long-format data from metadata features.
if (length(meta_features) > 0) {
data_meta <- sample@meta.data[, meta_features, drop = FALSE] %>%
tibble::rownames_to_column(var = "Cell") %>%
tidyr::pivot_longer(cols = -"Cell",
names_to = "Gene",
values_to = "Expression")
} else {
data_meta <- NULL
}
# Combine both sources.
data_combined <- dplyr::bind_rows(data_genes, data_meta)
data <- data_combined %>%
dplyr::left_join(y = {sample@meta.data[, c(group.by, split.by), drop = FALSE] %>%
tibble::rownames_to_column(var = "Cell")},
by = "Cell") %>%
dplyr::mutate("logical" = ifelse(.data$Expression == 0, 0, 1)) %>%
dplyr::group_by(dplyr::across(dplyr::all_of(c(split.by, group.by, "Gene")))) %>%
dplyr::summarise("Avg.Exp" = mean(.data$Expression, na.rm = TRUE),
"N.Exp" = sum(.data$logical),
"N" = dplyr::n(),
.groups = "drop") %>%
dplyr::mutate("P.Exp" = (.data$N.Exp / .data$N) * 100) %>%
dplyr::select(dplyr::all_of(selection))
if (is.null(split.by)){
data <- data %>% tidyr::complete(.data[[group.by]], .data$Gene, fill = list("Avg.Exp" = 0, "P.Exp" = 0))
} else {
data <- data %>% tidyr::complete(.data[[split.by]], .data[[group.by]], .data$Gene, fill = list("Avg.Exp" = 0, "P.Exp" = 0))
}
if (base::isTRUE(zscore.data)){
selection <- c(group.by, "Gene", "Avg.Exp")
data <- data %>%
dplyr::select(dplyr::all_of(selection)) %>%
tidyr::pivot_wider(names_from = dplyr::all_of(group.by),
values_from = "Avg.Exp") %>%
as.data.frame() %>%
tibble::column_to_rownames(var = "Gene") %>%
t() %>%
scale(center = TRUE, scale = TRUE) %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Gene") %>%
tidyr::pivot_longer(-dplyr::all_of("Gene"),
names_to = group.by,
values_to = "Avg.Exp") %>%
dplyr::left_join(y = data %>% dplyr::select(-dplyr::all_of("Avg.Exp")),
by = c(group.by, "Gene"))
}
# Add gene map.
if (is.list(features)){
data <- data %>% dplyr::left_join(y = df.map, by = "Gene")
}
# Define cutoffs.
range.data <- c(min(data[, "Avg.Exp"], na.rm = TRUE),
max(data[, "Avg.Exp"], na.rm = TRUE))
out <- check_cutoffs(min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
limits = range.data)
range.data <- out$limits
scale.setup <- compute_scales(sample = sample,
feature = NULL,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = range.data)
# Modify values
if (!is.na(min.cutoff)){
data$Avg.Exp <- ifelse(data$Avg.Exp <= min.cutoff, min.cutoff, data$Avg.Exp)
}
if (!is.na(max.cutoff)){
data$Avg.Exp <- ifelse(data$Avg.Exp >= max.cutoff, max.cutoff, data$Avg.Exp)
}
selection <- c("Groups", "Gene", "Avg.Exp")
data.cluster <- data %>%
dplyr::ungroup() %>%
dplyr::mutate("Groups" = .data[[group.by]]) %>%
dplyr::select(dplyr::all_of(selection)) %>%
tidyr::pivot_wider(names_from = "Groups",
values_from = "Avg.Exp",
values_fn = list) %>%
as.data.frame() %>%
tibble::column_to_rownames(var = "Gene") %>%
as.matrix()
# Set NAs to 0.
data.cluster[is.na(data.cluster)] <- 0
# Cluster rows (features).
if(length(rownames(data.cluster)) == 1){
row_order <- rownames(data.cluster)[1]
} else {
if (isTRUE(cluster.features)){
row_order <- rownames(data.cluster)[stats::hclust(stats::dist(data.cluster, method = "euclidean"), method = "ward.D")$order]
} else {
row_order <- features.use
}
}
# Cluster columns (identities).
if (length(colnames(data.cluster)) == 1){
col_order <- colnames(data.cluster)[1]
} else {
if (isTRUE(cluster.identities)){
col_order <- colnames(data.cluster)[stats::hclust(stats::dist(t(data.cluster), method = "euclidean"), method = "ward.D")$order]
} else {
if (is.factor(sample@meta.data[, group.by])){
col_order <- levels(sample@meta.data[, group.by])
} else {
col_order <- sort(unique(sample@meta.data[, group.by]))
}
}
}
# Apply clustering.
data <- data %>%
dplyr::ungroup() %>%
dplyr::mutate("Groups" = .data[[group.by]]) %>%
dplyr::mutate("Gene" = factor(.data$Gene, levels = row_order),
"Groups" = factor(.data$Groups, levels = rev(col_order)))
# Define legend title
if (is.null(legend.title)){
legend.title <- ifelse(base::isTRUE(zscore.data), "Z-Scored | Avg. Exp.", "Avg. Exp.")
}
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = if (base::isFALSE(flip)){.data$Gene} else {.data$Groups},
y = if (base::isFALSE(flip)){.data$Groups} else {.data$Gene},
fill = .data$Avg.Exp,
size = .data$P.Exp)) +
ggplot2::geom_point(color = "black", shape = 21) +
ggplot2::scale_size_continuous(range = c(0, dot.scale)) +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
# Facet grid.
if (!is.null(split.by)){
if (base::isFALSE(flip)){
p <- p +
ggplot2::facet_grid(cols = ggplot2::vars(.data[[split.by]]),
scales = "free",
space = "free")
} else {
p <- p +
ggplot2::facet_grid(rows = ggplot2::vars(.data[[split.by]]),
scales = "free",
space = "free")
}
} else {
if (is.list(features)){
if (base::isFALSE(flip)){
p <- p +
ggplot2::facet_grid(cols = ggplot2::vars(.data$Name),
scales = "free",
space = "free")
} else {
p <- p +
ggplot2::facet_grid(rows = ggplot2::vars(.data$Name),
scales = "free",
space = "free")
}
}
}
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"),
axis.title = ggplot2::element_text(face = axis.title.face),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)} else {ggplot2::element_blank()},
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Add leyend modifiers.
p <- modify_continuous_legend(p = p,
# nocov start
legend.title = if (is.null(legend.title)){"Avg. Expression"} else {legend.title},
# nocov end
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# Modify size legend.
p <- p +
ggplot2::guides(size = ggplot2::guide_legend(title = "Percent Expressed",
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = ggplot2::aes(fill = "black")))
# Filter out dots with low percent expressed.
p$data <- p$data %>% dplyr::filter(.data$P.Exp >= dot.min)
return(p)
}
================================================
FILE: R/do_EnrichmentHeatmap.R
================================================
#' Create enrichment scores heatmaps.
#'
#' This function computes the enrichment scores for the cells using \link[Seurat]{AddModuleScore} and then aggregates the scores by the metadata variables provided by the user and displays it as a heatmap, computed by \link[ComplexHeatmap]{Heatmap}.
#'
#' @inheritParams doc_function
#' @param enforce_symmetry \strong{\code{\link[base]{logical}}} | Whether the geyser and feature plot has a symmetrical color scale.
#' @param ncores \strong{\code{\link[base]{numeric}}} | Number of cores used to run UCell scoring.
#' @param storeRanks \strong{\code{\link[base]{logical}}} | Whether to store the ranks for faster UCell scoring computations. Might require large amounts of RAM.
#' @param scale_scores \strong{\code{\link[base]{logical}}} | Whether to transform the scores to a range of 0-1 for plotting.
#' @param return_object \strong{\code{\link[base]{logical}}} | Return the Seurat object with the enrichment scores stored.
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_EnrichmentHeatmap.R
do_EnrichmentHeatmap <- function(sample,
input_gene_list,
features.order = NULL,
groups.order = NULL,
cluster = TRUE,
scale_scores = FALSE,
assay = NULL,
slot = NULL,
reduction = NULL,
group.by = NULL,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
verbose = FALSE,
na.value = "grey75",
legend.position = "bottom",
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = FALSE,
nbin = 24,
ctrl = 100,
flavor = "Seurat",
legend.title = NULL,
ncores = 1,
storeRanks = TRUE,
min.cutoff = NA,
max.cutoff = NA,
pt.size = 1,
plot_cell_borders = TRUE,
border.size = 2,
return_object = FALSE,
number.breaks = 5,
sequential.palette = "YlGnBu",
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.direction = 1,
flip = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_EnrichmentHeatmap")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("use_viridis" = use_viridis,
"enforce_symmetry" = enforce_symmetry,
"plot_cell_borders" = plot_cell_borders,
"flip" = flip,
"cluster" = cluster,
"scale_scores" = scale_scores,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("viridis.direction" = viridis.direction,
"nbin" = nbin,
"ctrl" = ctrl,
"ncores" = ncores,
"pt.size" = pt.size,
"border.size" = border.size,
"font.size" = font.size,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"viridis.direction" = viridis.direction,
"axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("input_gene_list" = input_gene_list,
"legend.title" = legend.title,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"font.type" = font.type,
"group.by" = group.by,
"na.value" = na.value,
"legend.position" = legend.position,
"viridis.palette" = viridis.palette,
"flavor" = flavor,
"sequential.palette" = sequential.palette,
"diverging.palette" = diverging.palette,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = flavor, parameter_name = "flavor")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
if (!(is.null(assay)) & flavor == "UCell"){
warning(paste0(add_warning(), crayon_body("When using "),
crayon_key("flavor = UCell"),
crayon_body(" do not use the "),
crayon_key("assay"),
crayon_body(" parameter.\nInstead, make sure that the "),
crayon_key("assay"),
crayon_body(" you want to compute the scores with is set as the "),
crayon_key("default"),
crayon_body(" assay. Setting it to "),
crayon_key("NULL"),
crayon_body(".")), call. = FALSE)
}
if (!(is.null(slot)) & flavor == "Seurat"){
warning(paste0(add_warning(), crayon_body("When using "),
crayon_key("flavor = Seurat"),
crayon_body(" do not use the "),
crayon_key("slot"),
crayon_body(" parameter.\nThis is determiend by default in "),
crayon_key("Seurat"),
crayon_body(". Setting it to "),
crayon_key("NULL"),
crayon_body(".")), call. = FALSE)
}
if (is.null(assay)){assay <- check_and_set_assay(sample)$assay}
slot <- if(is.null(slot)){"data"} else {slot}
if (is.character(input_gene_list)){
stop(paste0(add_cross(),
crayon_body("You have provided a string of genes to "),
crayon_key("input_gene_list"),
crayon_body(". Please provide a "),
crayon_key("named list"),
crayon_body(" instead.")), call. = FALSE)
}
if (!is.null(features.order)){
assertthat::assert_that(sum(features.order %in% names(input_gene_list)) == length(names(input_gene_list)),
msg = paste0(add_cross(), crayon_body("The names provided to "),
crayon_key("features.order"),
crayon_body(" do not match the names of the gene sets in "),
crayon_key("input_gene_list"),
crayon_body(".")))
}
if (is.null(legend.title)){
if (flavor == "UCell"){
legend.title <- ifelse(isTRUE(scale_scores), "UCell score | Scaled", "UCell score")
} else if (flavor == "Seurat"){
legend.title <- ifelse(isTRUE(scale_scores), "Enrichment | Scaled", "Enrichment")
}
}
input_list <- input_gene_list
assertthat::assert_that(!is.null(names(input_list)),
msg = paste0(add_cross(), crayon_body("Please provide a "),
crayon_key("named list"),
crayon_body(" to "),
crayon_key("input_gene_list"),
crayon_body(".")))
if (length(unlist(stringr::str_match_all(names(input_list), "_"))) > 0){
warning(paste0(add_warning(), crayon_body("Found "),
crayon_key("underscores (_)"),
crayon_body(" in the name of the gene sets provided. Replacing them with "),
crayon_key("dots (.)"),
crayon_body(" to avoid conflicts when generating the Seurat assay.")), call. = FALSE)
names.use <- stringr::str_replace_all(names(input_list), "_", ".")
names(input_list) <- names.use
# nocov start
if (!is.null(features.order)){
features.order <- stringr::str_replace_all(features.order, "_", ".")
}
# nocov end
}
if (length(unlist(stringr::str_match_all(names(input_list), "-"))) > 0){
warning(paste0(add_warning(), crayon_body("Found "),
crayon_key("dashes (-)"),
crayon_body(" in the name of the gene sets provided. Replacing them with "),
crayon_key("dots (.)"),
crayon_body(" to avoid conflicts when generating the Seurat assay.")), call. = FALSE)
names.use <- stringr::str_replace_all(names(input_list), "-", ".")
names(input_list) <- names.use
# nocov start
if (!is.null(features.order)){
features.order <- stringr::str_replace_all(features.order, "-", ".")
}
# nocov end
}
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
# Compute the enrichment scores.
sample <- compute_enrichment_scores(sample = sample,
input_gene_list = input_list,
verbose = verbose,
nbin = nbin,
ctrl = ctrl,
flavor = flavor,
ncores = ncores,
storeRanks = storeRanks,
# nocov start
assay = if (flavor == "UCell"){NULL} else {assay},
slot = if (flavor == "Seurat"){NULL} else {slot},
norm_data = scale_scores)
# nocov end
out.list <- list()
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
matrix.list <- list()
names.use <- names(input_list)
for (group in group.by){
suppressMessages({
sample$group.by <- sample@meta.data[, group]
df <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c("group.by", names.use))) %>%
tidyr::pivot_longer(cols = -"group.by",
names_to = "gene_list",
values_to = "enrichment") %>%
dplyr::group_by(.data$group.by, .data$gene_list) %>%
dplyr::summarise(mean = mean(.data$enrichment, na.rm = TRUE))
df.order <- df
})
matrix.list[[group]][["df"]] <- df
matrix.list[[group]][["df.order"]] <- df.order
}
counter <- 0
for (group in group.by){
counter <- counter + 1
df <- matrix.list[[group]][["df"]]
df.order <- matrix.list[[group]][["df.order"]]
# Transform to wide to retrieve the hclust.
df.order <- df.order %>%
tidyr::pivot_wider(id_cols = "group.by",
names_from = 'gene_list',
values_from = 'mean') %>%
tibble::column_to_rownames("group.by") %>%
as.matrix()
df.order[is.na(df.order)] <- 0
if (length(rownames(df.order)) == 1){
row_order <- rownames(df.order)[1]
} else {
if (isTRUE(cluster)){
row_order <- rownames(df.order)[stats::hclust(stats::dist(df.order, method = "euclidean"), method = "ward.D")$order]
} else {
row_order <- rownames(df.order)
}
}
if (counter == 1){
if (length(colnames(df.order)) == 1){
col_order <- colnames(df.order)[1]
} else {
if (isTRUE(cluster)){
col_order <- colnames(df.order)[stats::hclust(stats::dist(t(df.order), method = "euclidean"), method = "ward.D")$order]
} else {
col_order <- colnames(df.order)
}
}
}
if (!is.null(groups.order)){
if (group %in% names(groups.order)){
groups.order.use <- groups.order[[group]]
} else {
groups.order.use <- groups.order
}
} else {
groups.order.use <- row_order
}
data <- df %>%
dplyr::mutate("gene_list" = factor(.data$gene_list, levels = if (is.null(features.order)){rev(col_order)} else {features.order}),
"group.by" = factor(.data$group.by, levels = groups.order.use))
if (!is.na(min.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean < min.cutoff, min.cutoff, .data$mean))
}
if (!is.na(max.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean > max.cutoff, max.cutoff, .data$mean))
}
matrix.list[[group]] <- NULL
matrix.list[[group]][["data"]] <- data
}
# Compute limits.
min.vector <- NULL
max.vector <- NULL
for (group in group.by){
data <- matrix.list[[group]][["data"]]
min.vector <- append(min.vector, min(data$mean, na.rm = TRUE))
max.vector <- append(max.vector, max(data$mean, na.rm = TRUE))
}
# Get the absolute limits of the datasets.
limits <- c(min(min.vector),
max(max.vector))
# Compute overarching scales for all heatmaps.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "SCT",
reduction = NULL,
slot = "scale.data",
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Plot individual heatmaps.
counter <- 0
list.heatmaps <- list()
for (group in group.by){
counter <- counter + 1
data <- matrix.list[[group]][["data"]]
p <- data %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if(base::isFALSE(flip)){.data$gene_list} else {.data$group.by},
y = if(base::isFALSE(flip)){.data$group.by} else {.data$gene_list},
fill = .data$mean)) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5)
if (base::isTRUE(values.show)){
if (base::isTRUE(enforce_symmetry)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(abs(.data$mean) > values.threshold, "white", "black")),
size = values.size)
} else {
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(.data$mean > values.threshold, "white", "black")),
size = values.size)
}
p <- p + ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$group.by))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$gene)))) +
ggplot2::coord_equal() +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# nocov start
# Set axis titles.
if(base::isFALSE(flip)){
if (counter == 1){
if (length(group.by) > 1){
xlab <- NULL
} else {
xlab <- "Gene set"
}
ylab <- group
} else {
if (length(group.by) > 1){
if (counter == length(group.by)){
xlab <- "Gene set"
} else {
xlab <- NULL
}
} else {
xlab <- NULL
}
ylab <- group
}
} else {
if (counter == 1){
ylab <- "Gene set"
xlab <- group
} else {
xlab <- group
ylab <- NULL
}
}
# nocov end
axis.parameters <- handle_axis(flip = flip,
group.by = group.by,
group = group,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
# Set theme
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
legend.position = legend.position,
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
list.heatmaps[[group]] <- p
}
# Plot the combined plot
input <- if(base::isFALSE(flip)){list.heatmaps[rev(group.by)]}else{list.heatmaps[group.by]}
p <- patchwork::wrap_plots(input,
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(size = font.size,
family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(size = font.size,
face = plot.subtitle.face,
family = font.type,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(size = font.size,
face = plot.caption.face,
family = font.type,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
out.list[["Heatmap"]] <- p
if (isTRUE(return_object)){
# Generate a Seurat assay.
sample[["Enrichment"]] <- sample@meta.data %>%
dplyr::select(dplyr::all_of(names(input_list))) %>%
t() %>%
as.data.frame() %>%
Seurat::CreateAssayObject(.)
sample@meta.data <- sample@meta.data %>%
dplyr::select(-dplyr::all_of(names(input_list)))
sample@assays$Enrichment@key <- "Enrichment_"
Seurat::DefaultAssay(sample) <- "Enrichment"
out.list[["Object"]] <- sample
}
if (base::isFALSE(return_object)){
return_me <- out.list[["Heatmap"]]
} else {
return_me <- out.list
}
return(return_me)
}
================================================
FILE: R/do_ExpressionHeatmap.R
================================================
#' Create heatmaps of averaged expression by groups.
#'
#' This function generates a heatmap with averaged expression values by the unique groups of the metadata variables provided by the user.
#'
#' @inheritParams doc_function
#'
#'
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_ExpressionHeatmap.R
do_ExpressionHeatmap <- function(sample,
features,
group.by = NULL,
assay = NULL,
cluster = TRUE,
features.order = NULL,
groups.order = NULL,
slot = "data",
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
legend.title = "Avg. Expression",
na.value = "grey75",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = FALSE,
min.cutoff = NA,
max.cutoff = NA,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
number.breaks = 5,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
flip = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_ExpressionHeatmap")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"use_viridis" = use_viridis,
"flip" = flip,
"cluster" = cluster,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"font.size" = font.size,
"number.breaks" = number.breaks,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("features" = features,
"legend.type" = legend.type,
"font.type" = font.type,
"legend.title" = legend.title,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"group.by" = group.by,
"na.value" = na.value,
"slot" = slot,
"assay" = assay,
"group.by" = group.by,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"viridis.palette" = viridis.palette,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value)
check_colors(legend.framecolor)
check_colors(legend.tickcolor)
check_colors(grid.color)
check_colors(border.color)
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
assay <- if (is.null(assay)){Seurat::DefaultAssay(sample)} else {assay}
Seurat::DefaultAssay(sample) <- assay
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (is.list(features)){
warning(paste0(add_warning(), crayon_body("You have provided a "),
crayon_key("list"),
crayon_body(" to the parameter "),
crayon_key("features"),
crayon_body("Transforming into a character vector.")), call. = FALSE)
features <- unname(unlist(features))
}
features <- remove_duplicated_features(features)
# Generate the heatmap data.
if (sum(!features %in% rownames(sample)) >= 1){
warning(paste0(add_warning(), crayon_body("The following features are not found in the "),
crayon_key("row names"),
crayon_body(" of the specified "),
crayon_key("assay"),
crayon_body(" (default assay if not):\n"),
paste(vapply(features[!features %in% rownames(sample)], crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")), "\n"), call. = FALSE)
}
features <- features[features %in% rownames(sample)]
assertthat::assert_that(length(features) >= 1,
msg = paste0(add_cross(), crayon_body("None of the provided "),
crayon_key("features"),
crayon_body(" are present in the "),
crayon_key("sample"),
crayon_body(".")))
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
matrix.list <- list()
for (group in group.by){
# Extract activities from object as a long dataframe
if (utils::packageVersion("Seurat") < "5.0.0"){
df <- SeuratObject::GetAssayData(sample,
assay = assay,
slot = slot)[features, , drop = FALSE]
} else {
df <- SeuratObject::GetAssayData(sample,
assay = assay,
layer = slot)[features, , drop = FALSE]
}
sample$group.by <- sample@meta.data[, group]
df <- df %>%
as.matrix() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data[, "group.by", drop = FALSE] %>%
tibble::rownames_to_column(var = "cell")},
by = "cell") %>%
dplyr::select(-"cell") %>%
tidyr::pivot_longer(cols = -"group.by",
names_to = "gene",
values_to = "expression") %>%
dplyr::group_by(.data$group.by, .data$gene) %>%
dplyr::summarise(mean = mean(.data$expression, na.rm = TRUE))
df.order <- df
matrix.list[[group]][["df"]] <- df
matrix.list[[group]][["df.order"]] <- df.order
}
counter <- 0
for (group in group.by){
counter <- counter + 1
df <- matrix.list[[group]][["df"]]
df.order <- matrix.list[[group]][["df.order"]]
# Transform to wide to retrieve the hclust.
df.order <- df.order %>%
tidyr::pivot_wider(id_cols = "group.by",
names_from = 'gene',
values_from = 'mean') %>%
tibble::column_to_rownames("group.by") %>%
as.matrix()
df.order[is.na(df.order)] <- 0
if(length(rownames(df.order)) == 1){
row_order <- rownames(df.order)[1]
} else {
if (isTRUE(cluster)){
row_order <- rownames(df.order)[stats::hclust(stats::dist(df.order, method = "euclidean"), method = "ward.D")$order]
} else {
row_order <- rownames(df.order)
}
}
if (counter == 1){
if (length(colnames(df.order)) == 1){
col_order <- colnames(df.order)[1]
} else {
if (isTRUE(cluster)){
col_order <- colnames(df.order)[stats::hclust(stats::dist(t(df.order), method = "euclidean"), method = "ward.D")$order]
} else {
col_order <- colnames(df.order)
}
}
}
if (!is.null(groups.order) & (group %in% names(groups.order))){
groups.order.use <- groups.order[[group]]
} else {
groups.order.use <- row_order
}
data <- df %>%
dplyr::mutate("gene" = factor(.data$gene, levels = if (is.null(features.order)){rev(col_order)} else {features.order}),
"group.by" = factor(.data$group.by, levels = groups.order.use))
if (!is.na(min.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean < min.cutoff, min.cutoff, .data$mean))
}
if (!is.na(max.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean > max.cutoff, max.cutoff, .data$mean))
}
matrix.list[[group]][["data"]] <- data
}
# Compute limits.
min.vector <- NULL
max.vector <- NULL
for (group in group.by){
data <- matrix.list[[group]][["data"]]
min.vector <- append(min.vector, min(data$mean, na.rm = TRUE))
max.vector <- append(max.vector, max(data$mean, na.rm = TRUE))
}
# Get the absolute limits of the datasets.
limits <- c(min(min.vector),
max(max.vector))
# Compute overarching scales for all heatmaps.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "SCT",
reduction = NULL,
slot = "scale.data",
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Plot individual heatmaps.
counter <- 0
list.heatmaps <- list()
for (group in group.by){
counter <- counter + 1
data <- matrix.list[[group]][["data"]]
p <- data %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if (base::isFALSE(flip)){.data$gene} else {.data$group.by},
y = if (base::isFALSE(flip)){.data$group.by} else {.data$gene},
fill = .data$mean)) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5)
if (base::isTRUE(values.show)){
if (base::isTRUE(enforce_symmetry)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(abs(.data$mean) > values.threshold, "white", "black")),
size = values.size)
} else {
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(.data$mean > values.threshold, "white", "black")),
size = values.size)
}
p <- p + ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$group.by))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$gene)))) +
ggplot2::coord_equal() +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
axis.parameters <- handle_axis(flip = flip,
group.by = group.by,
group = group,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
# nocov start
# Set axis titles.
if (base::isFALSE(flip)){
if (counter == 1){
if (length(group.by) > 1){
xlab <- NULL
} else {
xlab <- "Genes"
}
ylab <- group
} else {
if (length(group.by) > 1){
if (counter == length(group.by)){
xlab <- "Genes"
} else {
xlab <- NULL
}
} else {
xlab <- NULL
}
ylab <- group
}
} else {
if (counter == 1){
ylab <- "Genes"
xlab <- group
} else {
ylab <- NULL
xlab <- group
}
}
# nocov end
# Set theme
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
legend.position = legend.position,
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
list.heatmaps[[group]] <- p
}
# Plot the combined plot
input <- if(base::isFALSE(flip)){list.heatmaps[rev(group.by)]}else{list.heatmaps[group.by]}
p <- patchwork::wrap_plots(input,
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
face = plot.caption.face,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
return(p)
}
================================================
FILE: R/do_FeaturePlot.R
================================================
#' Plot gene expression on dimensional reduction embeddings.
#'
#' This function wraps \link[Seurat]{FeaturePlot}, adding publication-ready
#' theming, rasterization, density contours, marginal distributions, and
#' cell border overlays.
#'
#' @inheritParams doc_function
#' @param idents.keep \strong{\code{\link[base]{character}}} | Vector of identities to plot. The gradient scale will also be subset to only the values of such identities.
#' @param individual.titles,individual.subtitles,individual.captions \strong{\code{\link[base]{character}}} | Titles or subtitles. for each feature if needed. Either NULL or a vector of equal length of features.
#' @param order \strong{\code{\link[base]{logical}}} | Whether to order the cells based on expression.
#' @param group.by \strong{\code{\link[base]{character}}} | Metadata variable based on which cells are grouped. This will effectively introduce a big dot in the center of each cluster, colored using a categorical color scale or with the values provided by the user in \strong{\code{group.by.colors.use}}. It will also displays a legend.
#' @param group.by.legend \strong{\code{\link[base]{character}}} | Title for the legend when \strong{\code{group.by}} is used. Use \strong{\code{NA}} to disable it and \strong{\code{NULL}} to use the default column title provided in \strong{\code{group.by}}.
#' @param group.by.dot.size \strong{\code{\link[base]{numeric}}} | Size of the dots placed in the middle of the groups.
#' @param group.by.cell_borders \strong{\code{\link[base]{logical}}} | Plots another border around the cells displaying the same color code of the dots displayed with \strong{\code{group.by}}. Legend is shown always with alpha = 1 regardless of the alpha settings.
#' @param group.by.colors.use \strong{\code{\link[base]{character}}} | Colors to use for the group dots.
#' @param group.by.show.dots \strong{\code{\link[base]{logical}}} | Controls whether to place in the middle of the groups.
#' @param group.by.cell_borders.alpha \strong{\code{\link[base]{numeric}}} | Controls the transparency of the new borders drawn by \strong{\code{group.by.cell_borders}}.
#' @param scale.limits \strong{\code{\link[base]{numeric}}} | Vector of two values (i.e: \code{c(0, 1)}) to limit the scales. Particularly useful to extend the color scale beyond the values in the dataset, contrary to \code{min.cutoff} and \code{max.cutoff}.
#' @param symmetry.type \strong{\code{\link[base]{character}}} | Type of symmetry to be enforced. One of:
#' \itemize{
#' \item \emph{\code{absolute}}: The highest absolute value will be taken into a account to generate the color scale. Works after \strong{\code{min.cutoff}} and \strong{\code{max.cutoff}}.
#' \item \emph{\code{centered}}: Centers the scale around the provided value in \strong{\code{symmetry.center}}. Works after \strong{\code{min.cutoff}} and \strong{\code{max.cutoff}}.
#' }
#' @param symmetry.center \strong{\code{\link[base]{numeric}}} | Value upon which the scale will be centered.
#' @return A ggplot2 object containing a Feature Plot.
#' @export
#'
#' @example /man/examples/examples_do_FeaturePlot.R
do_FeaturePlot <- function(sample,
features,
assay = NULL,
reduction = NULL,
slot = NULL,
order = FALSE,
group.by = NULL,
group.by.colors.use = NULL,
colorblind = FALSE,
group.by.legend = NULL,
group.by.show.dots = TRUE,
group.by.dot.size = 8,
group.by.cell_borders = FALSE,
group.by.cell_borders.alpha = 0.1,
split.by = NULL,
idents.keep = NULL,
cells.highlight = NULL,
idents.highlight = NULL,
dims = c(1, 2),
enforce_symmetry = FALSE,
symmetry.type = "absolute",
symmetry.center = NA,
pt.size = 1,
font.size = 14,
font.type = "sans",
legend.title = NULL,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
individual.titles = NULL,
individual.subtitles = NULL,
individual.captions = NULL,
ncol = NULL,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
raster = FALSE,
raster.dpi = 1024,
plot_cell_borders = TRUE,
border.size = 2,
border.color = "black",
border.density = 1,
na.value = "grey75",
verbose = TRUE,
plot.axes = FALSE,
min.cutoff = rep(NA, length(features)),
max.cutoff = rep(NA, length(features)),
scale.limits = NULL,
plot_density_contour = FALSE,
contour.position = "bottom",
contour.color = "grey90",
contour.lineend = "butt",
contour.linejoin = "round",
contour_expand_axes = 0.25,
label = FALSE,
label.color = "black",
label.size = 4,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_FeaturePlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check the assay.
out <- check_and_set_assay(sample = sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
#sample <- check_Assay5(sample, assay = assay)
# Check the reduction.
reduction <- check_and_set_reduction(sample = sample, reduction = reduction)
# Check the dimensions.
dims <- check_and_set_dimensions(sample = sample, reduction = reduction, dims = dims)
# Check logical parameters.
logical_list <- list("verbose" = verbose,
"raster" = raster,
"plot_cell_borders" = plot_cell_borders,
"order" = order,
"enforce_symmetry" = enforce_symmetry,
"plot.axes" = plot.axes,
"plot_density_contour" = plot_density_contour,
"label" = label,
"legend.byrow" = legend.byrow,
"group.by.cell_borders" = group.by.cell_borders,
"group.by.show.dots" = group.by.show.dots,
"use_viridis" = use_viridis,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pt.size" = pt.size,
"ncol" = ncol,
"font.size" = font.size,
"raster.dpi" = raster.dpi,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"border.size" = border.size,
"viridis.direction" = viridis.direction,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"contour_expand_axes" = contour_expand_axes,
"label.size" = label.size,
"number.breaks" = number.breaks,
"border.density" = border.density,
"legend.nrow" = legend.nrow,
"legend.ncol" = legend.ncol,
"group.by.dot.size" = group.by.dot.size,
"group.by.cell_borders.alpha" = group.by.cell_borders.alpha,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"symmetry.center" = symmetry.center)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
# Workaround for features.
if (is.list(features)){
warning(paste0(add_warning(), crayon_body("Features provided as a list. Unlisting the list. Please use a character vector next time."), call. = FALSE))
features <- unique(unlist(features))
}
character_list <- list("legend.position" = legend.position,
"features" = features,
"cells.highlight" = cells.highlight,
"idents.highlight" = idents.highlight,
"slot" = slot,
"group.by" = group.by,
"split.by" = split.by,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"idents.keep" = idents.keep,
"viridis.palette" = viridis.palette,
"individual.titles" = individual.titles,
"individual.subtitles" = individual.subtitles,
"individual.captions" = individual.captions,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"border.color" = border.color,
"legend.title" = legend.title,
"na.value" = na.value,
"contour.position" = contour.position,
"contour.color" = contour.color,
"contour.lineend" = contour.lineend,
"contour.linejoin" = contour.linejoin,
"label.color" = label.color,
"group.by.colors.use" = group.by.colors.use,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"symmetry.type" = symmetry.type)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check slot.
slot <- if(is.null(slot)){"data"} else {slot}
# Check split.by is on metadata.
if (!(is.null(split.by))){check_feature(sample = sample, features = split.by, enforce_check = "metadata", enforce_parameter = "split.by")}
# Check individual titles.
if (length(features) > 1 & !is.null(individual.titles)){
assertthat::assert_that(length(features) == length(individual.titles),
msg = paste0(add_cross(), crayon_body("The total number of "),
crayon_key("individual titles"),
crayon_body(" does not match the number of "),
crayon_key("features"),
crayon_body(" provided.")))
}
if (length(features) > 1 & !is.null(individual.subtitles)){
assertthat::assert_that(length(features) == length(individual.subtitles),
msg = paste0(add_cross(), crayon_body("The total number of "),
crayon_key("individual subtitles"),
crayon_body(" does not match the number of "),
crayon_key("features"),
crayon_body(" provided.")))
}
if (length(features) > 1 & !is.null(individual.captions)){
assertthat::assert_that(length(features) == length(individual.captions),
msg = paste0(add_cross(), crayon_body("The total number of "),
crayon_key("individual captions"),
crayon_body(" does not match the number of "),
crayon_key("features"),
crayon_body(" provided.")))
}
## Check that the contour_expand_axes is between 0 and 1.
assertthat::assert_that(contour_expand_axes <= 1,
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("countour_expand_axes"),
crayon_body(" lower or equal than "),
crayon_key("1"),
crayon_body(".")))
assertthat::assert_that(contour_expand_axes >= 0,
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("countour_expand_axes"),
crayon_body(" higher or equal than "),
crayon_key("0"),
crayon_body(".")))
if (!is.null(scale.limits)){
assertthat::assert_that(length(scale.limits) == 2,
msg = paste0(add_cross(), crayon_body("Please provide a two values to "),
crayon_key("scale.limits"),
crayon_body(".")))
}
if (!is.null(scale.limits)){
comparison <- !is.na(min.cutoff)
for (item in comparison){
assertthat::assert_that(base::isFALSE(item),
msg = paste0(add_cross(), crayon_body("When using "),
crayon_key("scale.limits"),
crayon_body(" you can not provide values to "),
crayon_key("min.cutoff"),
crayon_body(".")))
}
comparison <- !is.na(max.cutoff)
for (item in comparison){
assertthat::assert_that(base::isFALSE(item),
msg = paste0(add_cross(), crayon_body("When using "),
crayon_key("scale.limits"),
crayon_body(" you can not provide values to "),
crayon_key("max.cutoff"),
crayon_body(".")))
}
}
check_colors(border.color, parameter_name = "border.color")
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(contour.color, parameter_name = "contour.color")
check_colors(label.color, parameter_name = "label.color")
if (!is.null(group.by)){
if (!is.null(group.by.colors.use)){
check_colors(group.by.colors.use, parameter_name = "group.by.colors.use")
check_consistency_colors_and_names(sample = sample,
colors = group.by.colors.use,
grouping_variable = group.by)
} else {
data.use <- sample@meta.data[, group.by, drop = FALSE]
# If the variable is a factor, use the levels as order. If not, order the values alphabetically.
names.use <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
# Generate the color scale to be used based on the unique values of group.by.
group.by.colors.use <- generate_color_scale(names.use, colorblind = colorblind)
}
}
# Check that the legend title match the length of features.
if (!is.null(legend.title)){
assertthat::assert_that(length(legend.title) == length(features),
msg = paste0(add_cross(), crayon_body("Please provide as many different "),
crayon_key("legend titles"),
crayon_body(" as number of "),
crayon_key("features"),
crayon_body(" queried.")))
}
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = contour.lineend, parameter_name = "contour.lineend")
check_parameters(parameter = contour.linejoin, parameter_name = "contour.linejoin")
check_parameters(parameter = contour.position, parameter_name = "contour.position")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = border.density, parameter_name = "border.density")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
check_parameters(parameter = symmetry.type, parameter_name = "symmetry.type")
if (length(min.cutoff) != length(features)){
warning(paste0(add_warning(), crayon_body("Please provide as many values to "),
crayon_key("min.cutoff"),
crayon_body(" as "),
crayon_key("features"),
crayon_body(" provided. The values will be used in order and, when outside of the range, no cutoffs will be applied.")), call. = FALSE)
}
if (length(max.cutoff) != length(features)){
warning(paste0(add_warning(), crayon_body("Please provide as many values to "),
crayon_key("max.cutoff"),
crayon_body(" as "),
crayon_key("features"),
crayon_body(" provided. The values will be used in order and, when outside of the range, no cutoffs will be applied.")), call. = FALSE)
}
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
# Generate base layer.
if (isTRUE(plot_cell_borders)){
out <- compute_umap_layer(sample = sample,
labels = colnames(sample@reductions[[reduction]][[]])[dims],
pt.size = pt.size,
dot.size = group.by.dot.size,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
na.value = na.value,
alpha = group.by.cell_borders.alpha,
n = 100)
base_layer <- out$base_layer
na_layer <- out$na_layer
if (!is.null(group.by)){
center_layers <- out$center_layers
center_layer_1 <- center_layers$center_layer_1
center_layer_2 <- center_layers$center_layer_2
color_layer <- out$color_layer
}
}
# CONDITION: Regular FeaturePlot, under default parameters.
default_parameters <- is.null(split.by) & is.null(cells.highlight) & is.null(idents.highlight)
# If only default parameters are used.
if (default_parameters){
# Check if the feature is actually in the object.
features <- check_feature(sample = sample,
features = features,
permissive = TRUE)
# Remove duplicated features.
features <- remove_duplicated_features(features = features)
if (utils::packageVersion("Seurat") >= "4.1.0"){
p <- Seurat::FeaturePlot(sample,
features,
slot = slot,
reduction = reduction,
order = order,
dims = dims,
pt.size = pt.size,
ncol = ncol,
raster = raster,
raster.dpi = c(raster.dpi, raster.dpi),
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
label = label,
label.size = label.size,
label.color = label.color)
} else { # nocov start
p <- Seurat::FeaturePlot(sample,
features,
slot = slot,
reduction = reduction,
order = order,
dims = dims,
pt.size = pt.size,
ncol = ncol,
raster = raster,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
label = label,
label.size = label.size,
label.color = label.color)
} # nocov end
p$layers[[length(p$layers)]]$aes_params$fontface <- "bold"
p <- p &
# Remove Seurat::FeaturePlot() default plot title.
ggplot2::ggtitle("")
# Add color scales.
num_plots <- length(features)
for (counter in seq(1, num_plots)){
if (num_plots == 1){
scale.setup <- compute_scales(sample = sample,
feature = features,
assay = assay,
reduction = NULL,
slot = slot,
limits.use = scale.limits,
from_data = if (is.null(scale.limits)){FALSE} else {TRUE},
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
center_on_value = if(symmetry.type == "absolute"){FALSE} else {TRUE},
value_center = symmetry.center)
p <- add_scale(p = p,
function_use = ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits),
scale = "color")
} else if (num_plots > 1){
feature.use <- features[counter]
scale.setup <- compute_scales(sample = sample,
feature = feature.use,
assay = assay,
reduction = NULL,
slot = slot,
limits.use = scale.limits,
from_data = if (is.null(scale.limits)){FALSE} else {TRUE},
number.breaks = number.breaks,
min.cutoff = min.cutoff[counter],
max.cutoff = max.cutoff[counter],
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
center_on_value = if(symmetry.type == "absolute"){FALSE} else {TRUE},
value_center = symmetry.center)
p[[counter]] <- add_scale(p = p[[counter]],
function_use = ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits),
scale = "color")
}
}
# Special patches for diffusion maps: Adding "DC" labels to the axis.
if (stringr::str_starts(reduction, "diff|DIFF")){
p <- p &
ggplot2::xlab(paste0("DC_", dims[1])) &
ggplot2::ylab(paste0("DC_", dims[2]))
}
# Add cell borders.
if (isTRUE(plot_cell_borders)){
counter <- 0
for (feature in features){
counter <- counter + 1
p[[counter]]$layers <- append(base_layer, p[[counter]]$layers)
if (!(is.null(group.by))){
if (isTRUE(group.by.show.dots)){
p[[counter]]$layers <- append(p[[counter]]$layers, c(center_layer_2, center_layer_1))
}
if (isTRUE(group.by.cell_borders)){
p[[counter]]$layers <- append(color_layer, p[[counter]]$layers)
}
if (is.null(group.by.legend)){
legend.name <- group.by
} else {
if (is.na(group.by.legend)){
legend.name <- ""
} else {
legend.name <- group.by.legend
}
}
p[[counter]] <- p[[counter]] +
ggplot2::scale_fill_manual(values = group.by.colors.use,
name = legend.name) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.name,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(alpha = 1)))
}
}
}
if (isTRUE(plot_density_contour)){
counter <- 0
for (feature in features){
counter <- counter + 1
data <- ggplot2::ggplot_build(p[[counter]])
density_layer <- ggplot2::stat_density_2d(data = data$data[[1]],
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = contour.color,
lineend = contour.lineend,
linejoin = contour.linejoin)
if (contour.position == "bottom"){
p[[counter]]$layers <- append(density_layer, p[[counter]]$layers)
} else if (contour.position == "top"){
p[[counter]]$layers <- append(p[[counter]]$layers, density_layer)
}
min_x <- min(data$data[[1]]$x) * (1 + contour_expand_axes)
max_x <- max(data$data[[1]]$x) * (1 + contour_expand_axes)
min_y <- min(data$data[[1]]$y) * (1 + contour_expand_axes)
max_y <- max(data$data[[1]]$y) * (1 + contour_expand_axes)
# Expand axes limits to allocate the new contours.
suppressMessages({
p[[counter]] <- p[[counter]] +
ggplot2::xlim(c(min_x, max_x)) +
ggplot2::ylim(c(min_y, max_y))
})
}
}
# Modified FeaturePlot including only a subset of cells.
} else {
# Check if the feature is actually in the object.
output_list <- check_feature(sample = sample,
features = features,
dump_reduction_names = TRUE,
permissive = TRUE)
features <- output_list[["features"]]
dim_colnames <- output_list[["reduction_names"]]
# Remove duplicated features.
features <- remove_duplicated_features(features = features)
# Get the subset of wanted cells according to the combination of idents.highlight and cells.highlight parameters.
if (is.null(idents.highlight) & !(is.null(cells.highlight))){
# Only if cells.highlight parameters is used.
cells.use <- cells.highlight
} else if (!(is.null(idents.highlight)) & is.null(cells.highlight)){
# Only if idents.highlight parameter is used.
# Check if the provided identities are part of the active identities in the object.
check_identity(sample = sample, identities = idents.highlight)
# Get the names of the cells to use.
cells.use <- names(Seurat::Idents(sample)[Seurat::Idents(sample) %in% idents.highlight])
} else if (!(is.null(idents.highlight)) & !(is.null(cells.highlight))){
# Check if the provided identities are part of the active identities in the object.
check_identity(sample = sample, identities = idents.highlight)
# Both idents.highlight and cells.highlight are used.
cells.1 <- cells.highlight
cells.2 <- names(Seurat::Idents(sample)[Seurat::Idents(sample) %in% idents.highlight])
# Get the names of the cells to use.
cells.use <- unique(c(cells.1, cells.2))
# If split.by is used.
} else if (!(is.null(split.by))){
# No identities selected by the user.
if (is.null(idents.keep)){
cells.use <- colnames(sample)
# Identitites selected by the user.
} else {
# Check if the identitites are duplicated. If so, remove them.
if (sum(duplicated(idents.keep)) != 0){
message(paste0(add_info(), crayon_body("Found and removed duplicated values in idents.keep.")))
idents.keep <- idents.keep[!duplicated(idents.keep)]
}
# Get the names of the cells to plot.
cells.use <- names(Seurat::Idents(sample)[Seurat::Idents(sample) %in% idents.keep])
}
}
# Plots are generated independently if more than one feature is provided.
list.plots <- list()
# Counter depicting the feature used. Will increase each feature used.
count_iteration <- 0
cutoff.counter <- 0
# Iterate over the features.
for (feature in features){
cutoff.counter <- cutoff.counter + 1
min.cutoff.use <- min.cutoff[cutoff.counter]
max.cutoff.use <- max.cutoff[cutoff.counter]
# A "dummy" metadata column is generated using the values of the selected feature.
## Based on whether the feature is in the metadata of the object.
if (feature %in% colnames(sample@meta.data)) {
sample$dummy <- sample@meta.data[, feature]
## Or is a gene in the object.
} else if (feature %in% rownames(sample)){
if (utils::packageVersion("Seurat") < "5.0.0"){
sample$dummy <- SeuratObject::GetAssayData(object = sample, slot = slot, assay = assay)[feature, ]
} else {
sample$dummy <- SeuratObject::GetAssayData(object = sample, layer = slot, assay = assay)[feature, ]
}
## Or is a dimensional reduction component.
} else if (feature %in% dim_colnames){
# Iterate over each dimensional reduction in the object.
for(red in Seurat::Reductions(object = sample)){
# If the feature to plot is one of the dimensional reduction components.
if (feature %in% colnames(sample@reductions[[red]][[]])){
red.feature <- red
sample$dummy <- sample@reductions[[red.feature]][[]][, feature]
}
}
}
# Assign NAs to the values corresponding to the cells not selected.
sample$dummy[!(names(sample$dummy) %in% cells.use)] <- NA
# If split.by is not used.
if (is.null(split.by)){
feature.use <- "dummy"
sample.use <- sample[, cells.use]
if (isTRUE(plot_cell_borders)){
out <- compute_umap_layer(sample = sample.use,
labels = colnames(sample.use@reductions[[reduction]][[]])[dims],
pt.size = pt.size,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
n = 100)
base_layer_subset <- out$base_layer
}
if (utils::packageVersion("Seurat") >= "4.1.0"){
p.loop <- Seurat::FeaturePlot(sample.use,
feature.use,
reduction = reduction,
slot = slot,
order = order,
dims = dims,
pt.size = pt.size,
raster = raster,
raster.dpi = c(raster.dpi, raster.dpi),
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
label = label,
label.size = label.size,
label.color = label.color)
} else { # nocov start
p.loop <- Seurat::FeaturePlot(sample.use,
feature.use,
reduction = reduction,
slot = slot,
order = order,
dims = dims,
pt.size = pt.size,
raster = raster,
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
label = label,
label.size = label.size,
label.color = label.color)
} # nocov end
p.loop$layers[[length(p.loop$layers)]]$aes_params$fontface <- "bold"
# Add scale.
scale.setup <- compute_scales(sample = sample,
feature = feature,
assay = assay,
reduction = NULL,
slot = slot,
limits.use = scale.limits,
from_data = if (is.null(scale.limits)){FALSE} else {TRUE},
number.breaks = number.breaks,
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
center_on_value = if(symmetry.type == "absolute"){FALSE} else {TRUE},
value_center = symmetry.center)
p.loop <- add_scale(p = p.loop,
function_use = ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits),
scale = "color")
p.loop <- p.loop +
ggplot2::ggtitle("")
# Add cell borders.
if (isTRUE(plot_cell_borders)){
p.loop$layers <- append(base_layer_subset, p.loop$layers)
p.loop$layers <- append(na_layer, p.loop$layers)
p.loop$layers <- append(base_layer, p.loop$layers)
suppressMessages({
p.loop <- p.loop +
ggplot2::scale_x_continuous(limits = c(min(p.loop$layers[[1]]$data$x),
max(p.loop$layers[[1]]$data$x))) +
ggplot2::scale_y_continuous(limits = c(min(p.loop$layers[[1]]$data$y),
max(p.loop$layers[[1]]$data$y)))
})
if (!(is.null(group.by))){
if (isTRUE(group.by.show.dots)){
p.loop$layers <- append(p.loop$layers, c(center_layer_2, center_layer_1))
}
if (isTRUE(group.by.cell_borders)){
p.loop$layers <- append(color_layer, p.loop$layers)
}
if (is.null(group.by.legend)){
legend.name <- group.by
} else {
if (is.na(group.by.legend)){
legend.name <- ""
} else {
legend.name <- group.by.legend
}
}
p.loop <- p.loop +
ggplot2::scale_fill_manual(values = group.by.colors.use,
name = legend.name) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.name,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(alpha = 1)))
}
}
if (isTRUE(plot_density_contour)){
data <- ggplot2::ggplot_build(p.loop)
density_layer <- ggplot2::stat_density_2d(data = data$data[[1]],
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = contour.color,
lineend = contour.lineend,
linejoin = contour.linejoin)
if (contour.position == "bottom"){
p.loop$layers <- append(density_layer, p.loop$layers)
} else if (contour.position == "top"){
p.loop$layers <- append(p.loop$layers, density_layer)
}
min_x <- min(data$data[[1]]$x) * (1 + contour_expand_axes)
max_x <- max(data$data[[1]]$x) * (1 + contour_expand_axes)
min_y <- min(data$data[[1]]$y) * (1 + contour_expand_axes)
max_y <- max(data$data[[1]]$y) * (1 + contour_expand_axes)
# Expand axes limits to allocate the new contours.
suppressMessages({
p.loop <- p.loop +
ggplot2::xlim(c(min_x, max_x)) +
ggplot2::ylim(c(min_y, max_y))
})
}
} else if (!(is.null(split.by))){
# Recover all metadata.
data <- sample[[]]
# Retrieve the metadata column belonging to the split.by parameter.
data.use <- data[, split.by, drop = FALSE]
# Retrieve the plotting order, keep factor levels if the column is a factor.
if (is.null(idents.keep)){
plot_order <- if (is.factor(data.use[, 1])){levels(data.use[, 1])} else {sort(unique(data.use[, 1]))}
} else {
plot_order <- sort(idents.keep)
}
list.plots.split.by <- list()
count_plot <- 0 # Will update for each unique value in split.by.
count_iteration <- count_iteration + 1 # Will update for each feature.
# Compute the limits of the variable.
## This should be replaced by a function in utils.R
limits <- c(min(sample$dummy[!is.na(sample$dummy)]), max(sample$dummy[!is.na(sample$dummy)]))
if (!is.na(min.cutoff.use)){
limits[1] <- min.cutoff.use
}
if (!is.na(max.cutoff.use)){
limits[2] <- max.cutoff.use
}
# For each value in split.by.
for (iteration in plot_order){
feature.use <- "dummy2"
count_plot <- count_plot + 1
# Create a second dummy variable storing the values of the feature but only for the selected subset.
sample$dummy2 <- sample$dummy
# Get the names of the cells used in this subset.
cells.iteration <- sample@meta.data[, split.by] == iteration
# Assign the cells that are not part of the iteration to NA.
sample$dummy2[!(cells.iteration)] <- NA
sample.use <- sample[, cells.iteration]
if (isTRUE(plot_cell_borders)){
out <- compute_umap_layer(sample = sample.use,
labels = colnames(sample.use@reductions[[reduction]][[]])[dims],
pt.size = pt.size,
border.density = border.density,
border.size = border.size,
border.color = border.color,
raster = raster,
raster.dpi = raster.dpi,
reduction = reduction,
group.by = group.by,
split.by = split.by,
n = 100)
base_layer_subset <- out$base_layer
}
if (utils::packageVersion("Seurat") >= "4.1.0"){
p.loop <- Seurat::FeaturePlot(sample.use,
feature.use,
slot = slot,
reduction = reduction,
order = order,
dims = dims,
pt.size = pt.size,
raster = raster,
raster.dpi = c(raster.dpi, raster.dpi),
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
label = label,
label.size = label.size,
label.color = label.color)
} else { # nocov start
p.loop <- Seurat::FeaturePlot(sample.use,
feature.use,
slot = slot,
reduction = reduction,
order = order,
dims = dims,
pt.size = pt.size,
raster = raster,
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
label = label,
label.size = label.size,
label.color = label.color)
} # nocov end
p.loop$layers[[length(p.loop$layers)]]$aes_params$fontface <- "bold"
scale.setup <- compute_scales(sample = sample,
feature = feature,
assay = assay,
reduction = NULL,
limits.use = scale.limits,
from_data = if (is.null(scale.limits)){FALSE} else {TRUE},
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
center_on_value = if(symmetry.type == "absolute"){FALSE} else {TRUE},
value_center = symmetry.center)
p.loop <- add_scale(p = p.loop,
function_use = ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits),
scale = "color")
p.loop <- p.loop +
ggplot2::ggtitle(iteration)
if (legend.position != "none"){
p.loop <- modify_continuous_legend(p = p.loop,
legend.title = if (is.null(legend.title)){feature} else {legend.title},
legend.aes = "color",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
}
if (iteration != plot_order[length(plot_order)]){
p.loop <- p.loop & Seurat::NoLegend()
}
# Add cell borders.
if (isTRUE(plot_cell_borders)){
p.loop$layers <- append(base_layer_subset, p.loop$layers)
p.loop$layers <- append(na_layer, p.loop$layers)
p.loop$layers <- append(base_layer, p.loop$layers)
suppressMessages({
p.loop <- p.loop +
ggplot2::scale_x_continuous(limits = c(min(p.loop$layers[[1]]$data$x),
max(p.loop$layers[[1]]$data$x))) +
ggplot2::scale_y_continuous(limits = c(min(p.loop$layers[[1]]$data$y),
max(p.loop$layers[[1]]$data$y)))
})
if (!(is.null(group.by))){
if (isTRUE(group.by.show.dots)){
p.loop$layers <- append(p.loop$layers, c(center_layer_2, center_layer_1))
}
if (isTRUE(group.by.cell_borders)){
p.loop$layers <- append(color_layer, p.loop$layers)
}
if (is.null(group.by.legend)){
legend.name <- group.by
} else {
if (is.na(group.by.legend)){
legend.name <- ""
} else {
legend.name <- group.by.legend
}
}
p.loop <- p.loop +
ggplot2::scale_fill_manual(values = group.by.colors.use,
name = legend.name) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.name,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(alpha = 1)))
}
}
if (isTRUE(plot_density_contour)){
data <- ggplot2::ggplot_build(p.loop)
density_layer <- ggplot2::stat_density_2d(data = data$data[[1]],
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = contour.color,
lineend = contour.lineend,
linejoin = contour.linejoin)
if (contour.position == "bottom"){
p.loop$layers <- append(density_layer, p.loop$layers)
} else if (contour.position == "top"){
p.loop$layers <- append(p.loop$layers, density_layer)
}
min_x <- min(data$data[[1]]$x) * (1 + contour_expand_axes)
max_x <- max(data$data[[1]]$x) * (1 + contour_expand_axes)
min_y <- min(data$data[[1]]$y) * (1 + contour_expand_axes)
max_y <- max(data$data[[1]]$y) * (1 + contour_expand_axes)
# Expand axes limits to allocate the new contours.
suppressMessages({
p.loop <- p.loop +
ggplot2::xlim(c(min_x, max_x)) +
ggplot2::ylim(c(min_y, max_y))
})
}
# Add label font customization.
for (layer.use in seq(1, length(p.loop$layers))){
if (sum(stringr::str_detect(class(p.loop$layers[[layer.use]]$geom), "GeomText|GeomLabel"))){
p.loop$layers[[layer.use]]$aes_params$family <- font.type
}
}
list.plots.split.by[[iteration]] <- p.loop
}
p.loop <- patchwork::wrap_plots(list.plots.split.by,
ncol = ncol,
guides = "collect") +
patchwork::plot_annotation(title = ifelse(typeof(individual.titles) == "character", individual.titles[[count_iteration]], ""),
subtitle = ifelse(typeof(individual.subtitles) == "character", individual.subtitles[[count_iteration]], ""),
caption = ifelse(typeof(individual.captions) == "character", individual.captions[[count_iteration]], ""))
}
# Patch for diffusion maps.
if (stringr::str_starts(reduction, "diff|DIFF")){
# Add "DC" labels.
p.loop <- p.loop &
ggplot2::xlab(paste0("DC_", dims[1])) &
ggplot2::ylab(paste0("DC_", dims[2]))
} else if (reduction == "pca"){
p.loop <- p.loop &
ggplot2::xlab(paste0("PC_", dims[1])) &
ggplot2::ylab(paste0("PC_", dims[2]))
}
# Add the plot to the list.
list.plots[[feature]] <- p.loop
}
# Generate the final plot with patchwork and use the "ncol" parameter value for the number of columns.
p <- patchwork::wrap_plots(list.plots, nrow = ncol)
}
# Fix the extra space and add theme parameters.
p <- p &
ggplot2::theme_minimal(base_size = font.size) &
ggplot2::theme(plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
plot.title = ggplot2::element_text(face = plot.title.face,
hjust = ifelse(!(is.null(split.by)), 0.5, 0)),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
panel.grid = ggplot2::element_blank(),
plot.title.position = "plot",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.position = legend.position,
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Add font.family to geom_text and geom_label.
if (is.null(split.by)){
if (length(p$patches$plots) > 0){
num.plots <- length(p$patches$plots)
} else {
num.plots <- 1
}
for (plot.use in seq(1, num.plots)){
for (layer.use in seq(1, length(p[[plot.use]]$layers))){
if (sum(stringr::str_detect(class(p[[plot.use]]$layers[[layer.use]]$geom), "GeomText|GeomLabel"))){
p[[plot.use]]$layers[[layer.use]]$aes_params$family <- font.type
}
}
}
}
if (is.null(split.by) & legend.position != "none"){
counter <- 0
for (feature in features){
counter <- counter + 1
if (is.null(legend.title)){
legend.title.use <- feature
} else {
legend.title.use <- legend.title[counter]
}
p[[counter]] <- modify_continuous_legend(p = p[[counter]],
legend.title = legend.title.use,
legend.aes = "color",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
}
}
# Add custom title.
if (!is.null(plot.title)){
if (length(features) > 1 | !(is.null(split.by)) | !(is.null(cells.highlight)) | !(is.null(idents.highlight))){
p <- p +
patchwork::plot_annotation(title = plot.title)
} else {
p <- p +
ggplot2::labs(title = plot.title)
}
}
# Add custom subtitle.
if (!is.null(plot.subtitle)){
if (length(features) > 1 | !(is.null(split.by)) | !(is.null(cells.highlight)) | !(is.null(idents.highlight))){
p <- p +
patchwork::plot_annotation(subtitle = plot.subtitle)
} else {
p <- p +
ggplot2::labs(subtitle = plot.subtitle)
}
}
# Add custom caption
if (!is.null(plot.caption)){
if (length(features) > 1 | !(is.null(split.by)) | !(is.null(cells.highlight)) | !(is.null(idents.highlight))){
p <- p +
patchwork::plot_annotation(caption = plot.caption)
} else {
p <- p +
ggplot2::labs(caption = plot.caption)
}
}
# Add individual titles.
if (!is.null(individual.titles)){
for (counter in seq(1, length(features))){
if (!(is.na(individual.titles[counter]))){
if (is.null(split.by)){
p[[counter]]$labels$title <- individual.titles[counter]
}
}
}
}
# Add individual subtitles.
if (!is.null(individual.subtitles)){
for (counter in seq(1, length(features))){
if (!(is.na(individual.subtitles[counter]))){
if (is.null(split.by)){
p[[counter]]$labels$subtitle <- individual.subtitles[counter]
}
}
}
}
# Add individual captions
if (!is.null(individual.captions)){
for (counter in seq(1, length(features))){
if (!(is.na(individual.captions[counter]))){
if (is.null(split.by)){
p[[counter]]$labels$caption <- individual.captions[counter]
}
}
}
}
if (base::isFALSE(plot.axes)){
p <- p &
ggplot2::theme(axis.title = ggplot2::element_blank(),
axis.text = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.line = ggplot2::element_blank())
} else {
p <- p &
ggplot2::theme(axis.title = ggplot2::element_text(face = axis.title.face),
axis.text = ggplot2::element_text(face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"))
}
# Further patch for diffusion maps.
if (stringr::str_starts(reduction, "diff|DIFF")){
labels <- colnames(sample@reductions[[reduction]][[]])[dims]
# Fix the axis scale so that the highest and lowest values are in the range of the DCs (previously was around +-1.5, while DCs might range to +-0.004 or so).
p <- suppressMessages({
p &
ggplot2::xlim(c(min(sample@reductions[[reduction]][[]][, labels[1]], na.rm = TRUE),
max(sample@reductions[[reduction]][[]][, labels[1]], na.rm = TRUE))) &
ggplot2::ylim(c(min(sample@reductions[[reduction]][[]][, labels[2]], na.rm = TRUE),
max(sample@reductions[[reduction]][[]][, labels[2]], na.rm = TRUE)))
})
}
# Return the plot.
return(p)
}
================================================
FILE: R/do_GroupwiseDEHeatmap.R
================================================
#' Compute a dotplot with the results of a group-wise DE analysis.
#'
#' @inheritParams doc_function
#' @param de_genes \strong{\code{\link[tibble]{tibble}}} | DE genes matrix resulting of running `Seurat::FindAllMarkers()`.
#' @param top_genes \strong{\code{\link[base]{numeric}}} | Top N differentially expressed (DE) genes by group to retrieve.
#' @param p.cutoff \strong{\code{\link[base]{numeric}}} | Cutoff to use for adjusted p.value to filter significant genes.
#'
#' @return A dotplot composed of 3 main panels: -log10(adjusted p-value), log2(FC) and mean expression by cluster.
#' @export
#'
#' @example /man/examples/examples_do_GroupwiseDEHeatmap.R
do_GroupwiseDEHeatmap <- function(sample,
de_genes,
group.by = NULL,
assay = NULL,
slot = "data",
number.breaks = 5,
dot.scale = 8,
top_genes = 5,
p.cutoff = 0.05,
flip = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
use_viridis = FALSE,
colors.use = NULL,
colorblind = FALSE,
viridis.direction = -1,
viridis.palette = "G",
sequential.direction = 1,
sequential.palette = "YlGnBu",
diverging.palette = "RdBu",
diverging.direction = -1,
legend.position = "bottom",
legend.title = NULL,
legend.width = 1,
legend.length = 7.5,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
min.cutoff = NA,
max.cutoff = NA,
enforce_symmetry = FALSE,
na.value = "grey75",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_GroupwiseDEHeatmap")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
logical_list <- list("use_viridis" = use_viridis,
"enforce_symmetry" = enforce_symmetry,
"flip" = flip,
"legend.byrow" = legend.byrow,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("number.breaks" = number.breaks,
"top_genes" = top_genes,
"viridis.direction" = viridis.direction,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"font.size" = font.size,
"axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"dot.scale" = dot.scale,
"legend.nrow" = legend.nrow,
"legend.ncol" = legend.ncol)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"slot" = slot,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"na.value" = na.value,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title" = legend.title,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"xlab" = xlab,
"ylab" = ylab,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(na.value, parameter_name = "na.value")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
# Check the assay.
out <- check_and_set_assay(sample = sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
values <- unique(sample@meta.data[, group.by])
data.values <- unique(de_genes$cluster)
# Check that group.by works with input de_genes.
assertthat::assert_that(sum(values %in% data.values) == length(data.values))
if (base::isFALSE(enforce_symmetry)){
colors.gradient.exp <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
colors.gradient.fc <- compute_continuous_palette(name = "YlOrRd",
use_viridis = FALSE,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
colors.gradient.pval <- compute_continuous_palette(name = "PuBuGn",
use_viridis = FALSE,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient.exp <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
colors.gradient.fc <- compute_continuous_palette(name = "BrBG",
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
colors.gradient.pval <- compute_continuous_palette(name = "PuOr",
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
}
if (is.null(colors.use)){
colors.use <- generate_color_scale(names_use = if (is.factor(sample@meta.data[, group.by])) {levels(sample@meta.data[, group.by])} else {sort(unique(sample@meta.data[, group.by]))}, colorblind = colorblind)
} else {
check_colors(colors.use, parameter_name = "colors.use")
check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = group.by)
colors.use <- colors.use[unique(sample@meta.data[, group.by])]
}
magnitude <- ifelse(slot == "data", "avg_log2FC", "avg_diff")
specificity <- "p_val_adj"
data.use <- de_genes %>%
dplyr::arrange(.data[[specificity]], dplyr::desc(.data[[magnitude]])) %>%
dplyr::group_by(.data$cluster) %>%
dplyr::filter(.data[[specificity]] <= p.cutoff) %>%
dplyr::slice_head(n = top_genes)
gene.order <- data.use$gene %>% unique()
data.use <- data.use %>%
dplyr::rename("{group.by}" := "cluster") %>%
dplyr::select(dplyr::all_of(c("gene", group.by, magnitude, specificity))) %>%
dplyr::group_by(.data$gene) %>%
dplyr::arrange(dplyr::desc(.data[[magnitude]])) %>%
dplyr::slice_head(n = 1) %>%
dplyr::ungroup() %>%
dplyr::mutate("p.adj.log10.minus" := -log10(.data[[specificity]])) %>%
dplyr::arrange(dplyr::desc(.data[[magnitude]]), dplyr::desc(.data$p.adj.log10.minus)) %>%
dplyr::select(-dplyr::all_of(c(specificity)))
data.use$p.adj.log10.minus[data.use$p.adj.log10.minus == Inf] <- .Machine$double.xmax
# Workaround parameter deprecation.
if (base::isTRUE(utils::packageVersion("Seurat") < "4.9.9")){
data <- Seurat::GetAssayData(object = sample,
assay = assay,
slot = slot)
} else {
data <- SeuratObject::LayerData(object = sample,
assay = assay,
layer = slot)
}
expr.data <- data[data.use$gene, , drop = FALSE] %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "gene") %>%
tidyr::pivot_longer(cols = -"gene",
names_to = "Cell",
values_to = "Expression") %>%
dplyr::left_join(y = {sample@meta.data %>%
dplyr::select(dplyr::all_of(c(group.by))) %>%
tibble::rownames_to_column(var = "Cell") %>%
dplyr::mutate("Groups.use" = .data[[group.by]]) %>%
dplyr::select(-dplyr::all_of(c(group.by)))},
by = "Cell")
data.use <- expr.data %>%
dplyr::mutate("logical" = ifelse(.data$Expression == 0, 0, 1)) %>%
dplyr::group_by(.data$gene, .data$Groups.use) %>%
dplyr::summarise("Avg.Exp" = mean(.data$Expression, na.rm = TRUE),
"N.Exp" = sum(.data$logical),
"N" = dplyr::n()) %>%
dplyr::mutate("P.Exp" = (.data$N.Exp / .data$N) * 100) %>%
dplyr::left_join(y = {data.use %>%
dplyr::mutate("Groups.use" = .data[[group.by]]) %>%
dplyr::select(-dplyr::all_of(c(group.by)))},
by = c("Groups.use", "gene")) %>%
dplyr::select(dplyr::all_of(c("gene", "Groups.use", "Avg.Exp", "P.Exp", magnitude, "p.adj.log10.minus")))
if (is.factor(sample@meta.data[, group.by])){
order.use <- rev(levels(sample@meta.data[, group.by]))
} else {
order.use <- rev(sort(unique(sample@meta.data[, group.by])))
}
data.use <- data.use %>%
dplyr::mutate("gene" = factor(.data$gene, levels = gene.order)) %>%
dplyr::mutate("Groups.use" = factor(.data$Groups.use, levels = order.use))
# Define cutoffs.
range.data.exp <- c(min(data.use[, "Avg.Exp"], na.rm = TRUE),
max(data.use[, "Avg.Exp"], na.rm = TRUE))
out <- check_cutoffs(min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
limits = range.data.exp)
range.data.exp <- out$limits
scale.setup.exp <- compute_scales(sample = sample,
feature = NULL,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = range.data.exp)
range.data.fc <- c(min(data.use[, magnitude], na.rm = TRUE),
max(data.use[, magnitude], na.rm = TRUE))
scale.setup.fc <- compute_scales(sample = sample,
feature = NULL,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = range.data.fc)
range.data.pval <- c(-log10(p.cutoff),
max(data.use[, "p.adj.log10.minus"], na.rm = TRUE))
scale.setup.pval <- compute_scales(sample = sample,
feature = NULL,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = range.data.pval)
# Modify values
if (!is.na(min.cutoff)){
data.use$Avg.Exp <- ifelse(data.use$Avg.Exp <= min.cutoff, min.cutoff, data.use$Avg.Exp)
}
if (!is.na(max.cutoff)){
data.use$Avg.Exp <- ifelse(data.use$Avg.Exp >= max.cutoff, max.cutoff, data.use$Avg.Exp)
}
# Plot
p1 <- data.use %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = if (base::isFALSE(flip)){.data$gene} else {.data$Groups.use},
y = if (base::isFALSE(flip)){.data$Groups.use} else {.data$gene},
fill = .data$Avg.Exp,
size = .data$P.Exp)) +
ggplot2::geom_point(color = "black", shape = 21) +
ggplot2::scale_size_continuous(range = c(0, dot.scale)) +
ggplot2::scale_fill_gradientn(colors = colors.gradient.exp,
na.value = na.value,
name = if (is.null(legend.title)){"Avg. Expression"} else {legend.title},
breaks = scale.setup.exp$breaks,
labels = scale.setup.exp$labels,
limits = scale.setup.exp$limits) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption,
x = ifelse(is.null(xlab), "Genes", xlab),
y = ifelse(is.null(ylab), "", ylab)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"),
axis.title = ggplot2::element_text(face = axis.title.face),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 20, r = 0, b = 0, l = 0),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white")) +
ggplot2::guides(size = ggplot2::guide_legend(title = "Pct. Exp.",
title.position = "top",
title.hjust = 0.5,
ncol = 1,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = ggplot2::aes(fill = "black")))
# Add leyend modifiers.
p1 <- modify_continuous_legend(p = p1,
# nocov start
legend.title = if (is.null(legend.title)){"Avg. Exp."} else {legend.title},
# nocov end
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
p2 <- data.use %>%
dplyr::mutate("X_mask" = "X_label") %>%
dplyr::filter(!is.na(.data$p.adj.log10.minus)) %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = if (base::isFALSE(flip)){.data$gene} else {.data$X_mask},
y = if (base::isFALSE(flip)){.data$X_mask} else {.data$gene},
fill = .data$avg_log2FC)) +
ggplot2::geom_point(color = "black", shape = 22, na.rm = TRUE, size = dot.scale) +
ggplot2::scale_fill_gradientn(colors = colors.gradient.fc,
na.value = na.value,
name = magnitude,
breaks = scale.setup.fc$breaks,
labels = scale.setup.fc$labels,
limits = scale.setup.fc$limits) +
ggplot2::labs(title = NULL,
subtitle = NULL,
caption = NULL,
x = NULL,
y = NULL) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title = ggplot2::element_text(face = axis.title.face),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0, unit = "null"),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Add leyend modifiers.
p2 <- modify_continuous_legend(p = p2,
# nocov start
legend.title = expression(bold(paste("avg_", log["2"], "(FC)"))),
# nocov end
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
p3 <- data.use %>%
dplyr::mutate("X_mask" = "X_label") %>%
dplyr::filter(!is.na(.data$p.adj.log10.minus)) %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = if (base::isFALSE(flip)){.data$gene} else {.data$X_mask},
y = if (base::isFALSE(flip)){.data$X_mask} else {.data$gene},
fill = .data$p.adj.log10.minus)) +
ggplot2::geom_point(color = "black", shape = 22, na.rm = TRUE, size = dot.scale) +
ggplot2::scale_fill_gradientn(colors = colors.gradient.pval,
na.value = na.value,
name = magnitude,
breaks = scale.setup.pval$breaks,
labels = scale.setup.pval$labels,
limits = scale.setup.pval$limits) +
ggplot2::labs(title = NULL,
subtitle = NULL,
caption = NULL,
x = NULL,
y = NULL) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title = ggplot2::element_text(face = axis.title.face),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0, unit = "null"),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Add leyend modifiers.
p3 <- modify_continuous_legend(p = p3,
# nocov start
legend.title = expression(bold(paste("-", log["10"], "(p.adj.)"))),
# nocov end
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
p4 <- data.use %>%
dplyr::mutate("X_mask" = "X_label",
"Groups.use" = factor(.data$Groups.use, levels = rev(order.use))) %>%
dplyr::filter(!is.na(.data$p.adj.log10.minus)) %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = if (base::isFALSE(flip)){.data$gene} else {.data$X_mask},
y = if (base::isFALSE(flip)){.data$X_mask} else {.data$gene},
fill = .data$Groups.use)) +
ggplot2::geom_point(color = "black", shape = 22, na.rm = TRUE, size = dot.scale) +
ggplot2::scale_size_continuous(range = c(dot.scale, dot.scale)) +
ggplot2::scale_fill_manual(values = colors.use,
na.value = na.value,
name = group.by) +
ggplot2::labs(title = NULL,
subtitle = NULL,
caption = NULL,
x = NULL,
y = NULL) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title = ggplot2::element_text(face = axis.title.face),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0, unit = "null"),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white")) +
ggplot2::guides(fill = ggplot2::guide_legend(title = group.by,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow))
if (base::isFALSE(flip)){
layout <- paste(c(paste(rep("A", 1), collapse = "\n"),
paste(rep("B", 1), collapse = "\n"),
paste(rep("C", 1), collapse = "\n"),
paste(rep("D", length(order.use)), collapse = "\n"),
paste(rep("D", length(order.use)), collapse = "\n"),
paste(rep("D", length(order.use)), collapse = "\n"),
paste(rep("E", 2), collapse = "\n"),
paste(rep("E", 2), collapse = "\n"),
paste(rep("E", 2), collapse = "\n")), collapse = "\n")
} else {
first <- paste(c(rep("D", length(order.use)), "C", "B", "A"), collapse = "")
layout <- paste(c(first, first, first, first, first, paste(rep("E", nchar(first)), collapse = "")), collapse = "\n")
}
p <- patchwork::wrap_plots(A = p4,
B = p3,
C = p2,
D = p1,
E = patchwork::guide_area(),
design = layout,
guides = "collect") &
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position))
# Return the final heatmap.
return(p)
}
================================================
FILE: R/do_LigandReceptorPlot.R
================================================
#' Visualize Ligand-Receptor analysis output.
#'
#' This function takes a tibble produced by the liana package and generates a dot-plot visualization according to the user's specifications.
#'
#' @inheritParams doc_function
#' @param liana_output \strong{\code{\link[tibble]{tibble}}} | Object resulting from running the liana functions \code{liana_wrap} and \code{liana_aggregate}.
#' @param split.by \strong{\code{\link[base]{character}}} | Whether to further facet the plot on the y axis by common ligand.complex or receptor.complex. Values to provide: NULL, ligand.complex, receptor.complex.
#' @param keep_source,keep_target \strong{\code{\link[base]{character}}} | Identities to keep for the source/target of the interactions. NULL otherwise.
#' @param top_interactions \strong{\code{\link[base]{numeric}}} | Number of unique interactions to retrieve ordered by magnitude and specificity. It does not necessarily mean that the output will contain as many, but rather an approximate value.
#' @param top_interactions_by_group \strong{\code{\link[base]{logical}}} | Enforce the value on \strong{\code{top_interactions}} to be applied to each group in \strong{\code{source}} column.
#' @param dot_border \strong{\code{\link[base]{logical}}} | Whether to draw a black border in the dots.
#' @param dot.size \strong{\code{\link[base]{numeric}}} | Size aesthetic for the dots.
#' @param sort.by \strong{\code{\link[base]{character}}} | How to arrange the top interactions. Interactions are sorted and then the top N are retrieved and displayed. This takes place after subsetting for \strong{\code{keep_source}} and \strong{\code{keep_target}} One of:
#' \itemize{
#' \item \emph{\code{A}}: Sorts by specificity.
#' \item \emph{\code{B}}: Sorts by magnitude.
#' \item \emph{\code{C}}: Sorts by specificity, then magnitude (gives extra weight to specificity).
#' \item \emph{\code{D}}: Sorts by magnitude, then specificity (gives extra weight to magnitude). Might lead to the display of non-significant results.
#' \item \emph{\code{E}}: Sorts by specificity and magnitude equally.
#' }
#' @param specificity,magnitude \strong{\code{\link[base]{character}}} | Which columns to use for \strong{\code{specificity}} and \strong{\code{magnitude}}.
#' @param invert_specificity,invert_magnitude \strong{\code{\link[base]{logical}}} | Whether to \strong{\code{-log10}} transform \strong{\code{specificity}} and \strong{\code{magnitude}} columns.
#' @param sorting.type.specificity,sorting.type.magnitude \strong{\code{\link[base]{character}}} | Whether the sorting of e \strong{\code{magnitude}} or \strong{\code{specificity}} columns is done in ascending or descending order. This synergises with the value of e \strong{\code{invert_specificity}} and e \strong{\code{invert_magnitude}} parameters.
#' @param compute_ChordDiagrams \strong{\code{\link[base]{logical}}} | Whether to also compute Chord Diagrams for both the number of interactions between source and target but also between ligand.complex and receptor.complex.
#' @param sort_interactions_alphabetically \strong{\code{\link[base]{logical}}} | Sort the interactions to be plotted alphabetically (\strong{\code{TRUE}}) or keep them in their original order in the matrix (\strong{\code{FALSE}}).
#' @param return_interactions \strong{\code{\link[base]{logical}}} | Whether to return the data.frames with the interactions so that they can be plotted as chord plots using other package functions.
#'
#' @return A ggplot2 plot with the results of the Ligand-Receptor analysis.
#' @export
#'
#' @example /man/examples/examples_do_LigandReceptorPlot.R
do_LigandReceptorPlot <- function(liana_output,
split.by = NULL,
keep_source = NULL,
keep_target = NULL,
top_interactions = 25,
top_interactions_by_group = FALSE,
dot_border = TRUE,
magnitude = "sca.LRscore",
specificity = "aggregate_rank",
sort.by = "E",
sorting.type.specificity = "descending",
sorting.type.magnitude = "descending",
border.color = "black",
axis.text.x.angle = 45,
legend.position = "bottom",
legend.type = "colorbar",
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
font.size = 14,
dot.size = 1,
font.type = "sans",
plot.grid = TRUE,
grid.color = "grey90",
grid.type = "dotted",
compute_ChordDiagrams = FALSE,
sort_interactions_alphabetically = FALSE,
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
return_interactions = FALSE,
invert_specificity = TRUE,
invert_magnitude = FALSE,
verbose = TRUE){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
# Checks for packages.
check_suggests(function_name = "do_LigandReceptorPlot")
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
# Check logical parameters.
logical_list <- list("dot_border" = dot_border,
"plot.grid" = plot.grid,
"sort_interactions_alphabetically" = sort_interactions_alphabetically,
"use_viridis" = use_viridis,
"return_interactions" = return_interactions,
"invert_specificity" = invert_specificity,
"invert_magnitude" = invert_magnitude,
"verbose" = verbose,
"top_interactions_by_group" = top_interactions_by_group)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"top_interactions" = top_interactions,
"legend.length" = legend.length,
"legend.width" = legend.width,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"dot.size" = dot.size,
"axis.text.x.angle" = axis.text.x.angle,
"viridis.direction" = viridis.direction,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("split.by" = split.by,
"keep_source" = keep_source,
"keep_target" = keep_target,
"border.color" = border.color,
"legend.position" = legend.position,
"legend.type" = legend.type,
"legend.framecolor" = legend.framecolor,
"viridis.palette" = viridis.palette,
"legend.tickcolor" = legend.tickcolor,
"font.type" = font.type,
"grid.color" = grid.color,
"grid.type" = grid.type,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"sort.by" = sort.by,
"sorting.type.specificity" = sorting.type.specificity,
"sorting.type.magnitude" = sorting.type.magnitude)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check border color.
check_colors(border.color, parameter_name = "border.color")
# Check the colors provided to legend.framecolor and legend.tickcolor.
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(grid.color, parameter_name = "grid.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
if (!is.null(split.by)){
assertthat::assert_that(split.by %in% c("receptor.complex", "ligand.complex"),
msg = paste0(add_cross,
crayon_body("Please select one of the following for "),
crayon_key("split.by"),
crayon_body(": "),
crayon_key("ligand.complex"),
crayon_body(", "),
crayon_key("receptor.complex"),
crayon_body(".")))
}
# Define legend parameters. Width and height values will change depending on the legend orientation.
if (legend.position %in% c("top", "bottom")){
size_title <- "Interaction specificity"
fill.title <- "Expression Magnitude"
} else if (legend.position %in% c("left", "right")){
size_title <- stringr::str_wrap("Interaction specificity", width = 10)
fill.title <- stringr::str_wrap("Expression Magnitude", width = 10)
}
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Column for specificity: "),
crayon_key(specificity)))
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Column for magnitude: "),
crayon_key(magnitude)))
}
liana_output <- liana_output %>%
dplyr::mutate("magnitude" = .data[[magnitude]]) %>%
dplyr::mutate("specificity" = .data[[specificity]])
invert_function <- function(x){-log10(x + 1e-10)}
if (isTRUE(invert_specificity)){
liana_output <- liana_output %>%
dplyr::mutate("specificity" := invert_function(x = .data$specificity))
}
if (isTRUE(invert_magnitude)){
liana_output <- liana_output %>%
dplyr::mutate("magnitude" := invert_function(.data$magnitude))
}
# Differential arrangement of the interactions.
liana_output <- liana_output %>%
# Merge ligand.complex and receptor.complex columns into one, that will be used for the Y axis.
tidyr::unite(c("ligand.complex", "receptor.complex"),
col = "interaction",
sep = " | ",
remove = FALSE) %>%
# Merge source and target column into one, for future filtering.
tidyr::unite(c("source", "target"),
col = "interacting_clusters",
remove = FALSE)
# For Chord diagrams.
output_copy <- liana_output %>% dplyr::filter(.data$aggregate_rank <= 0.05)
# If the user wants to trim the matrix and subset interacting entities.
if (!(is.null(keep_source))){
liana_output <- liana_output %>%
dplyr::filter(.data$source %in% keep_source)
output_copy <- output_copy %>%
dplyr::filter(.data$source %in% keep_source)
}
if (!(is.null(keep_target))){
liana_output <- liana_output %>%
dplyr::filter(.data$target %in% keep_target)
output_copy <- output_copy %>%
dplyr::filter(.data$target %in% keep_target)
}
# Sort interactions according to user's preference.
if (sort.by == "A"){
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting interactions by: "),
crayon_key("specificify")))
}
if (sorting.type.specificity == "descending"){
liana_output <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$specificity))
} else {
liana_output <- liana_output %>%
dplyr::arrange(.data$specificity)
}
} else if (sort.by == "B"){
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting interactions by: "),
crayon_key("magnitude")))
}
if (sorting.type.magnitude == "descending"){
liana_output <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$magnitude))
} else {
liana_output <- liana_output %>%
dplyr::arrange(.data$magnitude)
}
} else if (sort.by == "C"){
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting interactions by: "),
crayon_key("specificify"),
crayon_body(" then "),
crayon_key("magnitude"),
crayon_body(".")))
}
if (sorting.type.magnitude == "ascending" & sorting.type.specificity == "ascending"){
liana_output <- liana_output %>%
dplyr::arrange(.data$specificity, .data$magnitude)
} else if (sorting.type.magnitude == "descending" & sorting.type.specificity == "ascending"){
liana_output <- liana_output %>%
dplyr::arrange(.data$specificity, dplyr::desc(.data$magnitude))
} else if (sorting.type.magnitude == "ascending" & sorting.type.specificity == "descending"){
liana_output <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$specificity), .data$magnitude)
} else if (sorting.type.magnitude == "descending" & sorting.type.specificity == "descending"){
liana_output <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$specificity), dplyr::desc(.data$magnitude))
}
} else if (sort.by == "D"){
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting interactions by: "),
crayon_key("magnitude"),
crayon_body(" then "),
crayon_key("specificity"),
crayon_body(".")))
}
if (sorting.type.magnitude == "ascending" & sorting.type.specificity == "ascending"){
liana_output <- liana_output %>%
dplyr::arrange(.data$magnitude, .data$specificity)
} else if (sorting.type.magnitude == "descending" & sorting.type.specificity == "ascending"){
liana_output <- liana_output %>%
dplyr::arrange(.data$magnitude, dplyr::desc(.data$specificity))
} else if (sorting.type.magnitude == "ascending" & sorting.type.specificity == "descending"){
liana_output <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$magnitude), .data$specificity)
} else if (sorting.type.magnitude == "descending" & sorting.type.specificity == "descending"){
liana_output <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$magnitude), dplyr::desc(.data$specificity))
}
} else if (sort.by == "E"){
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting interactions by: "),
crayon_key("magnitude"),
crayon_body(" and "),
crayon_key("specificity"),
crayon_body(" with equal weights.")))
}
if (sorting.type.magnitude == "ascending"){
liana_output_magnitude <- liana_output %>%
dplyr::arrange(.data$magnitude) %>%
tibble::rowid_to_column(var = "magnitude_rank")
} else {
liana_output_magnitude <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$magnitude)) %>%
tibble::rowid_to_column(var = "magnitude_rank")
}
if (sorting.type.specificity == "ascending"){
liana_output_specificity <- liana_output %>%
dplyr::arrange(.data$specificity) %>%
tibble::rowid_to_column(var = "specificity_rank")
} else {
liana_output_specificity <- liana_output %>%
dplyr::arrange(dplyr::desc(.data$specificity)) %>%
tibble::rowid_to_column(var = "specificity_rank")
}
liana_output <- liana_output %>%
dplyr::left_join(y = liana_output_specificity %>% dplyr::select(dplyr::all_of(c("interaction", "specificity_rank"))),
by = "interaction",
relationship = "many-to-many") %>%
dplyr::left_join(y = liana_output_magnitude %>% dplyr::select(dplyr::all_of(c("interaction", "magnitude_rank"))),
by = "interaction",
relationship = "many-to-many") %>%
dplyr::mutate("rank" = .data$magnitude_rank + .data$specificity_rank) %>%
dplyr::arrange(.data$rank) %>%
dplyr::select(!dplyr::all_of(c("rank", "magnitude_rank", "specificity_rank")))
rm(liana_output_magnitude)
rm(liana_output_specificity)
}
if (isTRUE(verbose)){
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting type specificity: "),
crayon_key(sorting.type.specificity)))
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Sorting type magnitude: "),
crayon_key(sorting.type.magnitude)))
rlang::inform(paste0(add_info(initial_newline = FALSE),
crayon_body("Plotting the following top interanctions: "),
crayon_key(top_interactions)))
}
if (base::isFALSE(top_interactions_by_group)){
liana_output <- liana_output %>%
# Filter based on the top X interactions of ascending sensibilities.
dplyr::inner_join(y = {liana_output %>%
dplyr::distinct_at(c("ligand.complex", "receptor.complex")) %>%
dplyr::slice_head(n = top_interactions)},
by = c("ligand.complex", "receptor.complex"),
relationship = "many-to-many")
} else {
liana_output <- liana_output %>%
# Filter based on the top X interactions of ascending sensibilities.
dplyr::inner_join(y = {liana_output %>%
dplyr::group_by(.data$source, .data$target) %>%
dplyr::slice_head(n = top_interactions)},
by = c("ligand.complex", "receptor.complex"),
relationship = "many-to-many")
}
assertthat::assert_that(nrow(liana_output) > 0,
msg = paste0(add_cross(), crayon_body("Whith the current presets of "),
crayon_key("keep_source"),
crayon_body(" and "),
crayon_key("keep_target"),
crayon_body(" there are no interactions left.")))
# Make source and target factors, so that they do not get dropped by the plot.
if (isTRUE(sort_interactions_alphabetically)){
liana_output$source <- factor(liana_output$source, levels = sort(unique(liana_output$source)))
liana_output$target <- factor(liana_output$target, levels = sort(unique(liana_output$target)))
liana_output$interaction <- factor(liana_output$interaction, levels = rev(sort(unique(liana_output$interaction))))
} else if (base::isFALSE(sort_interactions_alphabetically)){
liana_output$source <- factor(liana_output$source, levels = sort(unique(liana_output$source)))
liana_output$target <- factor(liana_output$target, levels = sort(unique(liana_output$target)))
liana_output$interaction <- factor(liana_output$interaction, levels = rev(unique(liana_output$interaction)))
}
# Plot.
if (isTRUE(dot_border)){
p <- liana_output %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$target,
y = .data$interaction,
fill = .data$magnitude,
size = .data$specificity,
group = .data$interacting_clusters)) +
ggplot2::geom_point(shape = 21,
na.rm = TRUE)
} else if (base::isFALSE(dot_border)){
p <- liana_output %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$target,
y = .data$interaction,
size = .data$specificity,
group = .data$interacting_clusters)) +
ggplot2::geom_point(mapping = ggplot2::aes(color = .data$magnitude),
shape = 19,
na.rm = TRUE)
}
p <- p +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$interaction)))) +
ggplot2::scale_size_continuous(name = size_title,
range = c(2 * dot.size, 10 * dot.size))
# Settings for bordered dots.
limits <- c(min(liana_output$magnitude, na.rm = TRUE),
max(liana_output$magnitude, na.rm = TRUE))
scale.setup <- compute_scales(sample = NULL,
feature = NULL,
assay = NULL,
reduction = NULL,
slot = NULL,
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = FALSE,
from_data = TRUE,
limits.use = limits)
if (isTRUE(dot_border)){
# Add color to aesthetics.
p$layers[[1]]$aes_params$color <- border.color
p <- p +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = NA,
name = fill.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
} else {
p <- p +
ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = NA,
name = fill.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
}
# Continue plotting.
if (is.null(split.by)){
p <- p +
ggplot2::facet_grid(. ~ .data$source,
space = "free",
scales = "free",
drop = FALSE)
} else if (split.by == "ligand.complex"){
p <- p +
ggplot2::facet_grid(.data$ligand.complex ~ .data$source,
space = "free",
scales = "free",
drop = FALSE)
} else if (split.by == "receptor.complex"){
p <- p +
ggplot2::facet_grid(.data$receptor.complex ~ .data$source,
space = "free",
scales = "free",
drop = FALSE)
}
p <- p +
ggplot2::labs(title = "Source") +
ggplot2::xlab("Target") +
ggplot2::ylab(paste("Ligand", "|", "Receptor", sep = " ")) +
ggplot2::guides(size = ggplot2::guide_legend(title.position = "top",
title.hjust = 0.5,
override.aes = ggplot2::aes(fill = "black"))) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(plot.title = ggplot2::element_text(face = plot.title.face,
hjust = 0.5,
vjust = 0,
size = font.size),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "panel",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.justification = "center",
legend.position = legend.position,
axis.title.x = ggplot2::element_text(color = "black", face = axis.title.face, hjust = 0.5),
axis.title.y.left = ggplot2::element_text(color = "black", face = axis.title.face, angle = 90),
axis.title.y.right = ggplot2::element_blank(),
axis.text.y.right = ggplot2::element_text(color = "black",
face = axis.text.face),
axis.text.y.left = ggplot2::element_blank(),
axis.ticks.x = ggplot2::element_line(color = "black"),
axis.ticks.y.left = ggplot2::element_blank(),
axis.ticks.y.right = ggplot2::element_line(color = "black"),
axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["vjust"]]),
strip.text.x = ggplot2::element_text(face = "bold",
color = "black"),
strip.text.y = ggplot2::element_blank(),
panel.border = ggplot2::element_rect(color = "black", fill = NA),
panel.grid = if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)} else {ggplot2::element_blank()},
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "black", linetype = "solid"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Adjust for the type of legend and whether it is fill or color.
p <- modify_continuous_legend(p = p,
legend.aes = ifelse(isTRUE(dot_border), "fill", "color"),
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
if (isTRUE(return_interactions)){
data_interactions <- output_copy %>%
dplyr::select(dplyr::all_of(c("source", "target"))) %>%
dplyr::group_by(.data$target, .data$source) %>%
dplyr::summarise(value = dplyr::n()) %>%
dplyr::rename("from" = "source",
"to" = "target") %>%
dplyr::select(dplyr::all_of(c("from", "to", "value")))
data_LF <- liana_output %>%
dplyr::filter(!(is.na(.data$magnitude))) %>%
dplyr::select(dplyr::all_of(c("ligand.complex", "receptor.complex"))) %>%
dplyr::group_by(.data$ligand.complex, .data$receptor.complex) %>%
dplyr::summarise(value = dplyr::n()) %>%
dplyr::rename("from" = "ligand.complex",
"to" = "receptor.complex") %>%
dplyr::select(dplyr::all_of(c("from", "to", "value")))
return(list("Plot" = p,
"Group Interactions" = data_interactions,
"LR Interactions" = data_LF))
} else {
return(p)
}
}
================================================
FILE: R/do_LoadingsHeatmap.R
================================================
#' Compute a heatmap summary of the top and bottom genes in the PCA loadings for the desired PCs in a Seurat object.
#'
#' @inheritParams doc_function
#' @param subsample \strong{\code{\link[base]{numeric}}} | Number of cells to subsample the Seurat object to increase computational speed. Use NA to include the Seurat object as is.
#' @param dims \strong{\code{\link[base]{numeric}}} | PCs to include in the analysis.
#' @param top_loadings \strong{\code{\link[base]{numeric}}} | Number of top and bottom scored genes in the PCA Loadings for each PC.
#' @param min.cutoff.loadings,max.cutoff.loadings \strong{\code{\link[base]{numeric}}} | Cutoff to subset the scale of the Loading score heatmap. NA will use quantiles 0.05 and 0.95.
#' @param min.cutoff.expression,max.cutoff.expression \strong{\code{\link[base]{numeric}}} | Cutoff to subset the scale of the expression heatmap. NA will use 0 (no quantile) and quantile 0.95.
#'
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_LoadingsHeatmap.R
do_LoadingsHeatmap <- function(sample,
group.by = NULL,
subsample = NA,
dims = 1:10,
top_loadings = 5,
assay = NULL,
slot = "data",
grid.color = "white",
border.color = "black",
number.breaks = 5,
na.value = "grey75",
legend.position = "bottom",
legend.title = "Expression",
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
use_viridis = FALSE,
sequential.direction = 1,
sequential.palette = "YlGnBu",
viridis.palette = "G",
viridis.direction = -1,
diverging.palette = "RdBu",
diverging.direction = -1,
min.cutoff.loadings = NA,
max.cutoff.loadings = NA,
min.cutoff.expression = NA,
max.cutoff.expression = NA,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests("do_LoadingsHeatmap")
# Check logical parameters.
logical_list <- list("use_viridis" = use_viridis)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("axis.text.x.angle" = axis.text.x.angle,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"font.size" = font.size,
"number.breaks" = number.breaks,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"min.cutoff.loadings" = min.cutoff.loadings,
"max.cutoff.loadings" = max.cutoff.loadings,
"min.cutoff.expression" = min.cutoff.expression,
"max.cutoff.expression" = max.cutoff.expression)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("legend.type" = legend.type,
"font.type" = font.type,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"na.value" = na.value,
"slot" = slot,
"assay" = assay,
"group.by" = group.by,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"viridis.palette" = viridis.palette,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value)
check_colors(legend.framecolor)
check_colors(legend.tickcolor)
check_colors(grid.color)
check_colors(border.color)
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
colors.gradient.loading <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = TRUE)
colors.gradient.expression <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
# Check assay.
assay <- if (is.null(assay)){Seurat::DefaultAssay(sample)} else {assay}
Seurat::DefaultAssay(sample) <- assay
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (!is.na(subsample)){
sample <- sample[, sample(colnames(sample), subsample, replace = FALSE)]
}
loadings <- Seurat::Loadings(sample)[, dims] %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Gene") %>%
tidyr::pivot_longer(cols = -dplyr::all_of(dplyr::all_of("Gene")),
values_to = "Loading_Score",
names_to = "PC")
top_loadings.up <- loadings %>%
dplyr::group_by(.data$PC) %>%
dplyr::arrange(dplyr::desc(.data$Loading_Score)) %>%
dplyr::slice_head(n = top_loadings) %>%
dplyr::pull(.data$Gene)
top_loadings.down <- loadings %>%
dplyr::group_by(.data$PC) %>%
dplyr::arrange(.data$Loading_Score) %>%
dplyr::slice_head(n = top_loadings) %>%
dplyr::pull(.data$Gene)
genes.use <- NULL
for (i in seq(1, length(dims) * top_loadings, by = top_loadings)){
range <- seq(i, i + (top_loadings - 1))
genes.add <- c(top_loadings.up[range], top_loadings.down[range])
genes.add <- genes.add[!(genes.add %in% genes.use)]
genes.use <- append(genes.use, genes.add)
}
loadings <- loadings %>%
dplyr::filter(.data$Gene %in% genes.use)
embeddings <- Seurat::Embeddings(sample, reduction = "pca")[, dims] %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
tidyr::pivot_longer(cols = -dplyr::all_of(dplyr::all_of("Cell")),
values_to = "Embedding_Score",
names_to = "PC")
metadata <- sample@meta.data %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
dplyr::select(dplyr::all_of(c("Cell", group.by))) %>%
tibble::as_tibble()
data.use <- metadata %>%
dplyr::left_join(y = embeddings,
by = "Cell") %>%
dplyr::left_join(y = loadings,
by = "PC",
relationship = "many-to-many")
if (utils::packageVersion("Seurat") < "5.0.0"){
left_join_data <- SeuratObject::GetAssayData(sample,
assay = assay,
slot = slot)[unique(data.use$Gene), ]
} else {
left_join_data <- SeuratObject::GetAssayData(sample,
assay = assay,
layer = slot)[unique(data.use$Gene), ]
}
data.use <- data.use %>%
dplyr::left_join(y = {left_join_data %>%
as.matrix() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
tidyr::pivot_longer(cols = -dplyr::all_of("Cell"),
names_to = "Gene",
values_to = "Expression")},
by = c("Gene", "Cell")) %>%
dplyr::mutate("Gene" = factor(.data$Gene, levels = genes.use))
data.loading <- data.use %>%
dplyr::group_by(.data$Gene, .data$PC) %>%
dplyr::reframe("mean_Loading_Score" = mean(.data$Loading_Score, na.rm = TRUE))
data.expression <- data.use %>%
dplyr::group_by(.data[[group.by]], .data$Gene) %>%
dplyr::reframe("mean_Expression" = mean(.data$Expression, na.rm = TRUE))
data.expression.wide <- data.expression %>%
tidyr::pivot_wider(names_from = "Gene",
values_from = "mean_Expression") %>%
as.data.frame() %>%
tibble::column_to_rownames(var = group.by)
data.loadings.wide <- data.loading %>%
tidyr::pivot_wider(names_from = "Gene",
values_from = "mean_Loading_Score") %>%
as.data.frame() %>%
tibble::column_to_rownames(var = "PC")
# Cluster items.
gene.order <- genes.use[stats::hclust(stats::dist(t(data.expression.wide), method = "euclidean"), method = "ward.D")$order]
# nocov start
group.order <- if(is.factor(data.expression[[group.by]])){levels(data.expression[[group.by]])} else {sort(unique(data.expression[[group.by]]))}
# nocov end
group.order <- group.order[stats::hclust(stats::dist(data.expression.wide, method = "euclidean"), method = "ward.D")$order]
pc.order <- as.character(sort(unique(data.loading[["PC"]])))
pc.order <- pc.order[stats::hclust(stats::dist(data.loadings.wide, method = "euclidean"), method = "ward.D")$order]
# Reorder items.
data.loading <- data.loading %>%
dplyr::mutate("PC" = factor(.data$PC, levels = pc.order),
"Gene" = factor(.data$Gene, levels = gene.order))
data.expression <- data.expression %>%
dplyr::mutate("{group.by}" := factor(.data[[group.by]], levels = group.order),
"Gene" = factor(.data$Gene, levels = gene.order))
# Apply cutoffs.
# nocov start
if (!is.na(min.cutoff.loadings)){
data.loading <- data.loading %>%
dplyr::mutate("mean_Loading_Score" = ifelse(.data$mean_Loading_Score < min.cutoff.loadings, min.cutoff.loadings, .data$mean_Loading_Score))
} else {
data.loading <- data.loading %>%
dplyr::mutate("mean_Loading_Score" = ifelse(.data$mean_Loading_Score < stats::quantile(.data$mean_Loading_Score, 0.05), stats::quantile(.data$mean_Loading_Score, 0.05), .data$mean_Loading_Score))
}
if (!is.na(max.cutoff.loadings)){
data.loading <- data.loading %>%
dplyr::mutate("mean_Loading_Score" = ifelse(.data$mean_Loading_Score > max.cutoff.loadings, max.cutoff.loadings, .data$mean_Loading_Score))
} else {
data.loading <- data.loading %>%
dplyr::mutate("mean_Loading_Score" = ifelse(.data$mean_Loading_Score > stats::quantile(.data$mean_Loading_Score, 0.95), stats::quantile(.data$mean_Loading_Score, 0.95), .data$mean_Loading_Score))
}
# nocov end
if (!is.na(min.cutoff.expression)){
data.expression <- data.expression %>%
dplyr::mutate("mean_Expression" = ifelse(.data$mean_Expression < min.cutoff.expression, min.cutoff.expression, .data$mean_Expression))
}
if (!is.na(max.cutoff.expression)){
data.expression <- data.expression %>%
dplyr::mutate("mean_Expression" = ifelse(.data$mean_Expression > max.cutoff.expression, max.cutoff.expression, .data$mean_Expression))
} else {
data.expression <- data.expression %>%
dplyr::mutate("mean_Expression" = ifelse(.data$mean_Expression > stats::quantile(.data$mean_Expression, 0.95), stats::quantile(.data$mean_Expression, 0.95), .data$mean_Expression))
}
# Compute scales.
limits <- c(min(data.loading$mean_Loading_Score, na.rm = TRUE),
max(data.loading$mean_Loading_Score, na.rm = TRUE))
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "SCT",
reduction = NULL,
slot = "scale.data",
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = TRUE,
from_data = TRUE,
limits.use = limits)
p.loading <- data.loading %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$Gene,
y = .data$PC,
fill = .data$mean_Loading_Score)) +
ggplot2::geom_tile(color = grid.color, linewidth = 0.5) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$PC))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$Gene)))) +
ggplot2::scale_fill_gradientn(colors = colors.gradient.loading,
na.value = na.value,
name = "Avg. Loading score",
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits) +
ggplot2::coord_equal() +
ggplot2::xlab("Top genes") +
ggplot2::ylab("PC")
limits <- c(min(data.expression$mean_Expression, na.rm = TRUE),
max(data.expression$mean_Expression, na.rm = TRUE))
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "SCT",
reduction = NULL,
slot = "scale.data",
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = FALSE,
from_data = TRUE,
limits.use = limits)
p.expression <- data.expression %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$Gene,
y = .data[[group.by]],
fill = .data$mean_Expression)) +
ggplot2::geom_tile(color = grid.color, linewidth = 0.5) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data[[group.by]]))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$Gene)))) +
ggplot2::coord_equal() +
ggplot2::xlab(NULL) +
ggplot2::ylab(group.by) +
ggplot2::scale_fill_gradientn(colors = colors.gradient.expression,
na.value = na.value,
name = "Avg. Expression",
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p.loading <- modify_continuous_legend(p = p.loading,
legend.title = "Avg. Loading score",
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
p.expression <- modify_continuous_legend(p = p.expression,
legend.title = "Avg. Expression",
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
list.plots <- list("Loadings" = p.loading,
"Expression" = p.expression)
counter <- 0
for (name in rev(names(list.plots))){
counter <- counter + 1
axis.parameters <- handle_axis(flip = FALSE,
group.by = "A",
group = "A",
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
list.plots[[name]] <- list.plots[[name]] +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
legend.position = legend.position,
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
}
p <- patchwork::wrap_plots(A = list.plots$Loadings,
B = list.plots$Expression,
design = "A
B",
guides = "collect") +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
face = plot.caption.face,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
return(p)
}
================================================
FILE: R/do_MetadataHeatmap.R
================================================
#' Compute a heatmap of categorical variables.
#'
#' The main use of this function is to generate a metadata heatmap of your categorical data,
#' normally targeted to the different patient samples one has in the Seurat object. It requires
#' that the metadata columns chosen have one and only one possible value for each of the values in
#' group.by.
#'
#' @inheritParams doc_function
#' @param group.by \strong{\code{\link[base]{character}}} | Metadata column to use as basis for the plot.
#' @param metadata \strong{\code{\link[base]{character}}} | Metadata columns that will be used to plot the heatmap on the basis of the variable provided to group.by.
#' @param colors.use \strong{\code{\link[SCpubr]{named_list}}} | A named list of named vectors. The names of the list correspond to the names of the values provided to metadata and the names of the items in the named vectors correspond to the unique values of that specific metadata variable. The values are the desired colors in HEX code for the values to plot. The used are pre-defined by the pacakge but, in order to get the most out of the plot, please provide your custom set of colors for each metadata column!
#' @param heatmap.gap \strong{\code{\link[base]{numeric}}} | Size of the gap between heatmaps in mm.
#' @param from_df \strong{\code{\link[base]{logical}}} | Whether to provide a data frame with the metadata instead.
#' @param df \strong{\code{\link[base]{data.frame}}} | Data frame containing the metadata to plot. Rows contain the unique values common to all columns (metadata variables). The columns must be named.
#' @param legend.font.size \strong{\code{\link[base]{numeric}}} | Size of the font size of the legend. NULL uses default theme font size for legend according to the \strong{\code{font.size}} parameter.
#' @param legend.symbol.size \strong{\code{\link[base]{numeric}}} | Size of symbols in the legend in mm. NULL uses the default size.
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_MetadataHeatmap.R
do_MetadataHeatmap <- function(sample = NULL,
group.by = NULL,
metadata = NULL,
from_df = FALSE,
df = NULL,
colors.use = NULL,
colorblind = FALSE,
cluster = FALSE,
flip = TRUE,
heatmap.gap = 1,
axis.text.x.angle = 45,
legend.position = "bottom",
font.size = 14,
legend.font.size = NULL,
legend.symbol.size = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
na.value = "grey75",
font.type = "sans",
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
xlab = "",
ylab = ""){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_MetadataHeatmap")
# Check logical parameters.
logical_list <- list("flip" = flip,
"from_df" = from_df,
"legend.byrow" = legend.byrow,
"cluster" = cluster,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("heatmap.gap" = heatmap.gap,
"axis.text.x.angle" = axis.text.x.angle,
"font.size" = font.size,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"metadata" = metadata,
"legend.position" = legend.position,
"font.type" = font.type,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"xlab" = xlab,
"ylab" = ylab)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
if (base::isFALSE(from_df)){
check_Seurat(sample = sample)
for (meta in metadata){
assertthat::assert_that(meta %in% colnames(sample@meta.data),
msg = paste0(add_cross(), crayon_body("Metadata column "),
crayon_key(meta),
crayon_body(" is not in the sample "),
crayon_key("metadata"),
crayon_body(". Please check.")))
}
assertthat::assert_that(!is.null(sample) & !is.null(metadata) & !is.null(group.by),
msg = paste0(add_cross(), crayon_body("If "),
crayon_key("from_df = FALSE"),
crayon_body(" you need to use the "),
crayon_key("sample"),
crayon_body(", "),
crayon_key("group.by"),
crayon_body(", and "),
crayon_key("metadata"),
crayon_body(" parameters.")))
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
data.plot <- sample@meta.data %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::select(dplyr::all_of(c(group.by, metadata))) %>%
dplyr::group_by(.data[[group.by]]) %>%
dplyr::reframe(dplyr::across(.cols = dplyr::all_of(c(metadata)), unique))
assertthat::assert_that(length(unique(data.plot %>% dplyr::pull(.data[[group.by]]))) == nrow(data.plot),
msg = paste0(add_cross(), crayon_body("Please provide only metadata column that have a "),
crayon_key("one to one assignment"),
crayon_body(" to the unique values in "),
crayon_key("group.by"),
crayon_body(".")))
data.order <- data.plot %>%
tibble::column_to_rownames(var = group.by) %>%
dplyr::mutate(dplyr::across(dplyr::everything(), as.factor))
} else {
assertthat::assert_that(!is.null(df),
msg = paste0(add_cross(), crayon_body("If "),
crayon_key("from_df = TRUE"),
crayon_body(" you need to use the "),
crayon_key("df"),
crayon_body(" parameter.")))
group.by <- "Groups"
if (base::isFALSE(flip)){
metadata <- colnames(df)
} else {
metadata <- rev(colnames(df))
}
data.plot <- df %>%
tibble::rownames_to_column(var = group.by)
data.order <- data.plot %>%
tibble::column_to_rownames(var = group.by) %>%
dplyr::mutate(dplyr::across(dplyr::everything(), as.factor))
}
if (isTRUE(cluster)){
order.use <- suppressWarnings({rownames(data.order)[stats::hclust(cluster::daisy(data.order, metric = "gower"), method = "ward.D")$order]})
} else {
order.use <- rev(rownames(data.order))
}
list.heatmaps <- list()
# Get a list of predefined colors to then compute color wheels on for each metadata variable not covered.
colors.pool <- if (base::isFALSE(colorblind)){get_SCpubr_colors()} else {get_Colorblind_colors()[["Collection"]]}
counter <- 0
for (name in metadata){
# Colors
colors.use.name <- colors.use[[name]]
if (is.null(colors.use.name)){
counter <- counter + 1
values <- unique(data.plot %>% dplyr::pull(name))
if (base::isFALSE(colorblind)){
colors.use.name <- stats::setNames(do_ColorPalette(n = length(values), colors.use = colors.pool[counter]),
values)
} else {
colors.use.name <- stats::setNames(colors.pool[1:length(values)], values)
}
}
data.use <- data.plot %>%
dplyr::select(dplyr::all_of(c(group.by, name))) %>%
dplyr::mutate("{name}_fill" := factor(.data[[name]]),
"{name}" := .env$name,
"{group.by}" := factor(.data[[group.by]], levels = order.use)) %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if(base::isFALSE(flip)){.data[[group.by]]} else {.data[[name]]},
y = if(base::isFALSE(flip)){.data[[name]]} else {.data[[group.by]]},
fill = .data[[paste0(name, "_fill")]])) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data[[name]]))),
x.sec = guide_axis_label_trans(~paste0(levels(.data[[group.by]])))) +
ggplot2::coord_equal() +
ggplot2::scale_fill_manual(values = colors.use.name, name = name, na.value = na.value)
list.heatmaps[[name]] <- data.use
}
# Modify legends.
for (name in names(list.heatmaps)){
p <- list.heatmaps[[name]]
p <- p +
ggplot2::guides(fill = ggplot2::guide_legend(position = legend.position,
title.position = "top",
title.hjust = ifelse(legend.position %in% c("top", "bottom"), 0.5, 0),
override.aes = list(color = "black",
shape = 22),
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow))
list.heatmaps[[name]] <- p
}
# Add theme
counter <- 0
for (name in rev(names(list.heatmaps))){
counter <- counter + 1
# Set axis titles.
if (base::isFALSE(flip)){
if (counter == 1){
xlab.use <- NULL
ylab.use <- NULL
} else if (counter == length(metadata)){
xlab.use <- ifelse(is.null(xlab), group.by, xlab)
ylab.use <- ifelse(is.null(ylab), "", ylab)
} else {
xlab.use <- NULL
ylab.use <- NULL
}
} else {
if (counter == 1){
xlab.use <- ifelse(is.null(xlab), "", xlab)
ylab.use <- ifelse(is.null(ylab), group.by, ylab)
} else {
xlab.use <- NULL
ylab.use <- NULL
}
}
p <- list.heatmaps[[name]]
axis.parameters <- handle_axis(flip = flip,
group.by = rep("A", length(names(list.heatmaps))),
group = name,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
p <- p +
ggplot2::xlab(xlab.use) +
ggplot2::ylab(ylab.use) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = legend.position,
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face, size = legend.font.size),
legend.title = ggplot2::element_text(face = legend.title.face, size = legend.font.size),
legend.justification = "center",
plot.margin = ggplot2::margin(t = heatmap.gap, r = 0, b = 0, l = heatmap.gap, unit = "mm"),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.spacing = ggplot2::unit(0, "cm"),
panel.spacing.x = ggplot2::unit(0, "cm"))
if (!is.null(legend.symbol.size)){
p <- p + ggplot2::theme(legend.key.size = ggplot2::unit(legend.symbol.size, "mm"))
}
list.heatmaps[[name]] <- p
}
if (isTRUE(flip)){
names.use <- rev(metadata)
} else {
names.use <- metadata
}
p <- patchwork::wrap_plots(list.heatmaps[names.use],
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
legend.spacing = ggplot2::unit(0, "cm"),
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face,
family = font.type,
color = "black",
hjust = 1),
plot.caption.position = "plot"),
)
return(p)
}
================================================
FILE: R/do_NebulosaPlot.R
================================================
#' Plot kernel density estimates of gene expression on dimensional reduction embeddings.
#'
#' This function wraps \link[Nebulosa]{plot_density}, adding publication-ready
#' theming and joint density visualization for multiple features.
#'
#' @inheritParams doc_function
#' @inheritParams Nebulosa::plot_density
#' @param combine \strong{\code{\link[base]{logical}}} | Whether to create a single plot out of multiple features.
#' @param joint \strong{\code{\link[base]{logical}}} | Whether to plot different features as joint density.
#' @param return_only_joint \strong{\code{\link[base]{logical}}} | Whether to only return the joint density panel.
#'
#' @return A ggplot2 object containing a Nebulosa plot.
#' @export
#'
#' @example /man/examples/examples_do_NebulosaPlot.R
do_NebulosaPlot <- function(sample,
features,
slot = NULL,
dims = c(1, 2),
pt.size = 1,
reduction = NULL,
combine = TRUE,
method = c("ks", "wkde"),
joint = FALSE,
return_only_joint = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
font.size = 14,
font.type = "sans",
legend.position = "bottom",
plot_cell_borders = TRUE,
border.size = 2,
border.color = "black",
viridis.palette = "G",
viridis.direction = 1,
verbose = TRUE,
na.value = "grey75",
plot.axes = FALSE,
number.breaks = 5,
use_viridis = FALSE,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
`%>%` <- magrittr::`%>%`
check_suggests(function_name = "do_NebulosaPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check the reduction.
reduction <- check_and_set_reduction(sample = sample, reduction = reduction)
# Check the dimensions.
dims <- check_and_set_dimensions(sample = sample, reduction = reduction, dims = dims)
# Check logical parameters.
logical_list <- list("combine" = combine,
"joint" = joint,
"return_only_joint" = return_only_joint,
"plot_cell_borders" = plot_cell_borders,
"plot.axes" = plot.axes,
"use_viridis" = use_viridis)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pt.size" = pt.size,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"dims" = dims,
"border.size" = border.size,
"viridis.direction" = viridis.direction,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
if (is.list(features)){
warning(paste0(add_warning(), crayon_key("Features"),
crayon_body(" provided as a "),
crayon_key("list"),
crayon_body(". Unlisting it. Please use a "),
crayon_key("character vector")), call. = FALSE)
features <- unique(unlist(features))
}
character_list <- list("legend.position" = legend.position,
"features" = features,
"method" = method,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"slot" = slot,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"border.color" = border.color,
"na.value" = na.value,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check slot.
slot <- if(is.null(slot)){"data"} else {slot}
# Check if the feature is actually in the object.
features <- check_feature(sample = sample, features = features, permissive = TRUE)
features <- remove_duplicated_features(features = features)
# Check the colors provided to legend.framecolor and legend.tickcolor and border.color.
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(border.color, parameter_name = "border.color")
check_colors(na.value, parameter_name = "na.value")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
# Plot a density plot using Nebulosa package.
# Use compatibility wrapper for SeuratObject 5.0.0+
p <- .nebulosa_compat_wrapper(object = sample,
features = features,
joint = joint,
reduction = reduction,
dims = dims,
slot = slot,
verbose = verbose)
# If NULL is returned, Nebulosa is not compatible - fall back to do_FeaturePlot
if (is.null(p)) {
return(do_FeaturePlot(sample = sample,
features = features,
reduction = reduction,
dims = dims,
pt.size = pt.size,
order = TRUE,
font.size = font.size,
font.type = font.type,
legend.type = legend.type,
legend.position = legend.position,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.length = legend.length,
legend.width = legend.width,
border.color = border.color,
border.size = border.size,
plot_cell_borders = plot_cell_borders,
plot.title = plot.title,
plot.subtitle = plot.subtitle,
plot.caption = plot.caption,
na.value = na.value,
use_viridis = use_viridis,
viridis.palette = viridis.palette,
viridis.direction = viridis.direction,
sequential.palette = sequential.palette,
sequential.direction = sequential.direction,
verbose = FALSE,
plot.axes = plot.axes,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face))
}
# Continue with Nebulosa plotting
p <- p &
ggplot2::theme_minimal(base_size = font.size) &
ggplot2::theme(plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 0, b = 0, l = 0),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Compute the total number of plots according to whether joint is set to TRUE or not.
if (isTRUE(joint)){
num_plots <- length(features) + 1
} else {
num_plots <- length(features)
}
for (counter in seq_len(num_plots)){
if (counter > length(features)){
name.use <- "Joint Density"
} else {
name.use <- "Density"
}
if (num_plots == 1){
limits <- c(p$data[, "feature", drop = FALSE] %>% dplyr::arrange(.data$feature) %>% utils::head(1) %>% dplyr::pull(.data$feature),
p$data[, "feature", drop = FALSE] %>% dplyr::arrange(.data$feature) %>% utils::tail(1) %>% dplyr::pull(.data$feature))
scale.setup <- compute_scales(sample = sample,
feature = features,
assay = NULL,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = FALSE,
from_data = TRUE,
limits.use = limits)
p <- add_scale(p = p,
function_use = ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = name.use,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits),
scale = "color")
} else {
limits <- c(p[[counter]]$data[, "feature", drop = FALSE] %>% dplyr::arrange(.data$feature) %>% utils::head(1) %>% dplyr::pull(.data$feature),
p[[counter]]$data[, "feature", drop = FALSE] %>% dplyr::arrange(.data$feature) %>% utils::tail(1) %>% dplyr::pull(.data$feature))
scale.setup <- compute_scales(sample = sample,
feature = features,
assay = NULL,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = FALSE,
from_data = TRUE,
limits.use = limits)
p[[counter]] <- add_scale(p = p[[counter]],
function_use = ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = name.use,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits),
scale = "color")
}
# Set size of dots.
p[[counter]]$layers[[1]]$aes_params$size <- pt.size
if (legend.position != "none"){
if (num_plots == 1){
p <- modify_continuous_legend(p = p,
legend.aes = "color",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
} else {
p[[counter]] <- modify_continuous_legend(p = p[[counter]],
legend.aes = "color",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
}
}
}
if (base::isFALSE(plot.axes)){
p <- p &
ggplot2::theme(axis.title = ggplot2::element_blank(),
axis.text = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
axis.line = ggplot2::element_blank())
} else {
p <- p &
ggplot2::theme(axis.title = ggplot2::element_text(face = axis.title.face),
axis.text = ggplot2::element_text(face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"))
}
# Further patch for diffusion maps.
if (stringr::str_starts(reduction, "diff|DIFF")){
labels <- colnames(sample@reductions[["diffusion"]][[]])[dims]
# Fix the axis scale so that the highest and lowest values are in the range of the DCs (previously was around +-1.5, while DCs might range to +-0.004 or so).
p <- suppressMessages({
p &
ggplot2::xlim(c(min(sample@reductions$diffusion[[]][, labels[1]]),
max(sample@reductions$diffusion[[]][, labels[1]]))) &
ggplot2::ylim(c(min(sample@reductions$diffusion[[]][, labels[2]]),
max(sample@reductions$diffusion[[]][, labels[2]])))
})
}
# Add cell borders.
if (isTRUE(plot_cell_borders)){
# Generate base layer.
labels <- colnames(sample@reductions[[reduction]][[]])[dims]
df <- data.frame(x = Seurat::Embeddings(sample, reduction = reduction)[, labels[1]],
y = Seurat::Embeddings(sample, reduction = reduction)[, labels[2]])
base_layer <- ggplot2::geom_point(data = df, mapping = ggplot2::aes(x = .data$x,
y = .data$y),
colour = border.color,
size = pt.size * border.size,
show.legend = FALSE)
if (num_plots > 1){
for (plot_num in seq(1, num_plots)){
# Add cell borders.
if (isTRUE(plot_cell_borders)){
p[[plot_num]]$layers <- append(base_layer, p[[plot_num]]$layers)
}
}
} else {
p$layers <- append(base_layer, p$layers)
}
}
if (isTRUE(return_only_joint)){
p <- p[[length(features) + 1]]
}
# Add a title.
if (!(is.null(plot.title))){
if (length(features) == 1 | (isTRUE(return_only_joint))){
p <- p +
ggplot2::labs(title = plot.title)
} else {
p <- p & patchwork::plot_annotation(title = plot.title)
}
}
# Add a subtitle.
if (!(is.null(plot.subtitle))){
if (length(features) == 1 | (isTRUE(return_only_joint))){
p <- p &
ggplot2::labs(subtitle = plot.subtitle)
} else {
p <- p & patchwork::plot_annotation(subtitle = plot.subtitle)
}
}
# Add a caption
if (!(is.null(plot.caption))){
if (length(features) == 1 | (isTRUE(return_only_joint))){
p <- p &
ggplot2::labs(caption = plot.caption)
} else {
p <- p & patchwork::plot_annotation(caption = plot.caption)
}
}
return(p)
}
================================================
FILE: R/do_PathwayActivityHeatmap.R
================================================
#' Plot Pathway Activities from decoupleR using Progeny prior knowledge.
#'
#' @inheritParams doc_function
#' @param activities \strong{\code{\link[tibble]{tibble}}} | Result of running decoupleR method with progeny regulon prior knowledge.
#'
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_PathwayActivityHeatmap.R
do_PathwayActivityHeatmap <- function(sample,
activities,
group.by = NULL,
split.by = NULL,
slot = "scale.data",
statistic = "norm_wmean",
pt.size = 1,
border.size = 2,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
na.value = "grey75",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = TRUE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
flip = FALSE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_PathwayActivityHeatmap")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"flip" = flip,
"return_object" = return_object,
"use_viridis" = use_viridis,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pt.size" = pt.size,
"border.size" = border.size,
"font.size" = font.size,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"slot" = slot,
"split.by" = split.by,
"na.value" = na.value,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"font.type" = font.type,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"diverging.palette" = diverging.palette,
"viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"statistic" = statistic,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(na.value, parameter_name = "na.value")
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
sample[["progeny"]] <- activities %>%
dplyr::filter(.data$statistic == .env$statistic) %>%
tidyr::pivot_wider(id_cols = "source",
names_from = "condition",
values_from = "score") %>%
tibble::column_to_rownames("source") %>%
Seurat::CreateAssayObject()
Seurat::DefaultAssay(sample) <- "progeny"
sample@assays$progeny@key <- "progeny_"
# Scale the data.
sample <- Seurat::ScaleData(sample, verbose = FALSE)
list.out <- list()
if (!is.null(split.by) & !is.null(group.by)){
assertthat::assert_that(length(group.by) == 1,
msg = paste0(add_cross(), crayon_body("When using "),
crayon_key("split.by"),
crayon_body(" make sure you only provide a single value to "),
crayon_key("group.by"),
crayon_body(". Otherwise, the prot will not keep the proportions. This is a design choice. Thanks!")))
}
if (is.null(group.by)) {
sample$Groups <- Seurat::Idents(sample)
sample$group.by <- sample$Groups
group.by <- "Groups"
}
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
# Plotting
list.out <- list()
matrix.list <- list()
for (group in group.by){
# Extract activities from object as a long dataframe
suppressMessages({
sample$group.by <- sample@meta.data[, group]
if (utils::packageVersion("Seurat") < "5.0.0"){
df <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "progeny",
slot = slot)))
} else {
df <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "progeny",
layer = slot)))
}
df <- df %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data[, "group.by", drop = FALSE] %>%
tibble::rownames_to_column(var = "cell")},
by = "cell") %>%
dplyr::select(-"cell") %>%
tidyr::pivot_longer(cols = -"group.by",
names_to = "source",
values_to = "score") %>%
dplyr::group_by(.data$group.by, .data$source) %>%
dplyr::summarise(mean = mean(.data$score, na.rm = TRUE))
df.order <- df
df.order[is.na(df.order)] <- 0
matrix.list[[group]][["df"]] <- df
matrix.list[[group]][["df.order"]] <- df.order
if (!is.null(split.by)){
sample$split.by <- sample@meta.data[, split.by]
if (utils::packageVersion("Seurat") < "5.0.0"){
df.split <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "progeny",
slot = slot)))
} else {
df.split <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "progeny",
layer = slot)))
}
df.split <- df.split %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data[, c("group.by", "split.by"), drop = FALSE] %>%
tibble::rownames_to_column(var = "cell")},
by = "cell") %>%
dplyr::select(-"cell") %>%
tidyr::pivot_longer(cols = -c("group.by", "split.by"),
names_to = "source",
values_to = "score") %>%
dplyr::group_by(.data$split.by, .data$group.by, .data$source) %>%
dplyr::summarise(mean = mean(.data$score, na.rm = TRUE))
matrix.list[[group]][["df.split"]] <- df.split
}
})
}
counter <- 0
for (group in group.by){
counter <- counter + 1
df <- matrix.list[[group]][["df"]]
df.order <- matrix.list[[group]][["df.order"]]
data <- df
if (!is.null(split.by)){
data <- matrix.list[[group]][["df.split"]]
}
# Transform to wide to retrieve the hclust.
df.order <- df.order %>%
tidyr::pivot_wider(id_cols = "group.by",
names_from = 'source',
values_from = 'mean') %>%
tibble::column_to_rownames("group.by") %>%
as.matrix()
if(length(rownames(df.order)) == 1){
row_order <- rownames(df.order)[1]
} else {
row_order <- rownames(df.order)[stats::hclust(stats::dist(df.order, method = "euclidean"), method = "ward.D")$order]
}
if (counter == 1){
# nocov start
if (length(colnames(df.order)) == 1){
col_order <- colnames(df.order)[1]
# nocov end
} else {
col_order <- colnames(df.order)[stats::hclust(stats::dist(t(df.order), method = "euclidean"), method = "ward.D")$order]
}
}
data <- data %>%
dplyr::mutate("source" = factor(.data$source, levels = rev(col_order)),
"group.by" = factor(.data$group.by, levels = row_order))
matrix.list[[group]][["data.mean"]] <- data
if (!is.na(min.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean < min.cutoff, min.cutoff, .data$mean))
}
if (!is.na(max.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean > max.cutoff, max.cutoff, .data$mean))
}
matrix.list[[group]][["data"]] <- data
}
# Compute limits.
min.vector <- NULL
max.vector <- NULL
for (group in group.by){
data <- matrix.list[[group]][["data.mean"]]
min.vector <- append(min.vector, min(data$mean, na.rm = TRUE))
max.vector <- append(max.vector, max(data$mean, na.rm = TRUE))
}
# Get the absolute limits of the datasets.
limits <- c(min(min.vector),
max(max.vector))
# Compute overarching scales for all heatmaps.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "progeny",
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Plot individual heatmaps.
counter <- 0
list.heatmaps <- list()
for (group in group.by){
counter <- counter + 1
data <- matrix.list[[group]][["data"]]
p <- data %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if(base::isFALSE(flip)){.data$source} else {.data$group.by},
y = if(base::isFALSE(flip)){.data$group.by} else {.data$source},
fill = .data$mean)) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5)
if (base::isTRUE(values.show)){
if (base::isTRUE(enforce_symmetry)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(abs(.data$mean) > values.threshold, "white", "black")),
size = values.size)
} else {
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(.data$mean > values.threshold, "white", "black")),
size = values.size)
}
p <- p + ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$group.by))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$source)))) +
ggplot2::coord_equal() +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = paste0(ifelse(slot == "scale.data", "Z-scored | ", ""), statistic, " score"),
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
if (!is.null(split.by)){
p <- p +
ggplot2::facet_grid(~ .data$split.by,
drop = FALSE)
}
p <- modify_continuous_legend(p = p,
legend.title = paste0(ifelse(slot == "scale.data", "Z-scored | ", ""), statistic, " score"),
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# nocov start
# Set axis titles.
if (base::isFALSE(flip)){
if (counter == 1){
if (length(group.by) > 1){
xlab <- NULL
} else {
xlab <- "Pathway"
}
ylab <- group
} else {
if (length(group.by) > 1){
if (counter == length(group.by)){
xlab <- "Pathway"
} else {
xlab <- NULL
}
} else {
xlab <- NULL
}
ylab <- group
}
} else {
if (counter == 1){
ylab <- "Pathway"
xlab <- group
} else {
ylab <- NULL
xlab <- group
}
}
# nocov end
axis.parameters <- handle_axis(flip = flip,
group.by = group.by,
group = group,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
# Set theme
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = if (is.null(split.by)) {legend.position} else {"bottom"},
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 10, b = 0, l = 10),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
list.heatmaps[[group]] <- p
}
# Plot the combined plot
input <- if(base::isFALSE(flip)){list.heatmaps[rev(group.by)]}else{list.heatmaps[group.by]}
p <- patchwork::wrap_plots(input,
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(color = "black",
face = plot.caption.face,
hjust = 1,
family = font.type),
plot.caption.position = "plot"))
list.out[["Heatmap"]] <- p
if (isTRUE(return_object)){
list.out[["Object"]] <- sample
return_me <- list.out
} else{
return_me <- list.out[["Heatmap"]]
}
return(return_me)
}
================================================
FILE: R/do_RankedEnrichmentHeatmap.R
================================================
#' Compute a heatmap of enrichment of gene sets on the context of a dimensional reduction component.
#'
#' @inheritParams doc_function
#' @param colors.use \strong{\code{\link[base]{list}}} | A named list of named vectors. The names of the list correspond to the names of the values provided to metadata and the names of the items in the named vectors correspond to the unique values of that specific metadata variable. The values are the desired colors in HEX code for the values to plot. The used are pre-defined by the package but, in order to get the most out of the plot, please provide your custom set of colors for each metadata column!
#' @param main.heatmap.size \strong{\code{\link[base]{numeric}}} | A number from 0 to 1 corresponding to how big the main heatmap plot should be with regards to the rest (corresponds to the proportion in size).
#' @param scale.enrichment \strong{\code{\link[base]{logical}}} | Should the enrichment scores be scaled (z-scored) for better comparison in between gene sets? Setting this to TRUE should make intra- gene set comparisons easier at the cost ot not being able to compare inter- gene sets in absolute values.
#' @return A list of ggplot2 objects, one per dimensional reduction component, and a Seurat object if desired.
#' @export
#'
#' @example /man/examples/examples_do_RankedEnrichmentHeatmap.R
do_RankedEnrichmentHeatmap <- function(sample,
input_gene_list,
assay = NULL,
slot = NULL,
scale.enrichment = TRUE,
dims = 1:2,
subsample = 2500,
reduction = NULL,
group.by = NULL,
colors.use = NULL,
colorblind = FALSE,
raster = FALSE,
interpolate = FALSE,
nbin = 24,
ctrl = 100,
flavor = "Seurat",
main.heatmap.size = 0.95,
enforce_symmetry = ifelse(isTRUE(scale.enrichment), TRUE, FALSE),
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
font.size = 14,
font.type = "sans",
na.value = "grey75",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
legend.position = "bottom",
legend.nrow = NULL,
legend.ncol = NULL,
legend.byrow = FALSE,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
axis.text.x.angle = 45,
border.color = "black",
return_object = FALSE,
verbose = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests("do_RankedEnrichmentHeatmap")
check_Seurat(sample = sample)
# Check the reduction.
reduction <- check_and_set_reduction(sample = sample, reduction = reduction)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"legend.byrow" = legend.byrow,
"return_object" = return_object,
"scale.enrichment" = scale.enrichment,
"use_viridis" = use_viridis,
"verbose" = verbose,
"interpolate" = interpolate,
"raster" = raster,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("dims" = dims,
"subsample" = subsample,
"nbin" = nbin,
"ctrl" = ctrl,
"font.size" = font.size,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"number.breaks" = number.breaks,
"axis.text.x.angle" = axis.text.x.angle,
"legend.nrow" = legend.nrow,
"legend.ncol" = legend.ncol,
"main.heatmap.size" = main.heatmap.size,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("assay" = assay,
"reduction" = reduction,
"slot" = slot,
"group.by" = group.by,
"flavor" = flavor,
"font.type" = font.type,
"na.value" = na.value,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"legend.position" = legend.position,
"viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = flavor, parameter_name = "flavor")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
# nocov start
if (is.null(sample@reductions[[reduction]]@key) | is.na(sample@reductions[[reduction]]@key)){
stop(paste0(add_cross(),
crayon_body("Assay "),
crayon_key("key"),
crayon_body(" not found for the provided"),
crayon_key(" assay"),
crayon_body(". Please set a key. \n\nYou can do it as: "),
cli::style_italic(paste0(crayon_key('sample@reductions[['), cli::col_yellow("reduction"), crayon_key(']]@key <- "DC_"')))), call. = FALSE)
}
# nocov end
if (!is.na(subsample)){
# Perform subsampling.
sample <- sample[, sample(colnames(sample), subsample)]
}
key <- sample@reductions[[reduction]]@key
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
genes.use <- unlist(input_gene_list) %>% unname() %>% unique()
genes.use <- genes.use[genes.use %in% rownames(sample)]
if (isTRUE(verbose)){message(paste0(add_info(initial_newline = FALSE), crayon_body("Computing "), crayon_key("enrichment scores"), crayon_body("...")))}
if (!(is.null(assay)) & flavor == "UCell"){
warning(paste0(add_warning(), crayon_body("When using "),
crayon_key("flavor = UCell"),
crayon_body(" do not use the "),
crayon_key("assay"),
crayon_body(" parameter.\nInstead, make sure that the "),
crayon_key("assay"),
crayon_body(" you want to compute the scores with is set as the "),
crayon_key("default"),
crayon_body(" assay. Setting it to "),
crayon_key("NULL"),
crayon_body(".")), call. = FALSE)
}
if (!(is.null(slot)) & flavor == "Seurat"){
warning(paste0(add_warning(), crayon_body("When using "),
crayon_key("flavor = Seurat"),
crayon_body(" do not use the "),
crayon_key("slot"),
crayon_body(" parameter.\nThis is determiend by default in "),
crayon_key("Seurat"),
crayon_body(". Setting it to "),
crayon_key("NULL"),
crayon_body(".")), call. = FALSE)
}
if (is.null(assay)){assay <- check_and_set_assay(sample)$assay}
slot <- if(is.null(slot)){"data"} else {slot}
# nocov start
sample <- compute_enrichment_scores(sample,
input_gene_list = input_gene_list,
nbin = nbin,
ctrl = ctrl,
flavor = flavor,
assay = if (flavor == "UCell"){NULL} else {assay},
slot = if (flavor == "Seurat"){NULL} else {slot})
# nocov end
if (isTRUE(verbose)){message(paste0(add_info(initial_newline = FALSE), crayon_body("Plotting "), crayon_key("heatmaps"), crayon_body("...")))}
key_col <- stringr::str_remove_all(key, "_")
# Obtain the DC embeddings, together with the enrichment scores.
data.use <- sample@reductions[[reduction]]@cell.embeddings %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
as.data.frame() %>%
tibble::as_tibble() %>%
tidyr::pivot_longer(cols = -dplyr::all_of("Cell"),
names_to = key_col,
values_to = "Score") %>%
dplyr::filter(.data[[key_col]] %in% vapply(dims, function(x){paste0(key, x)}, FUN.VALUE = character(1))) %>%
dplyr::group_by(.data[[key_col]]) %>%
dplyr::reframe("rank" = rank(.data$Score),
"Cell" = .data$Cell,
"Score" = .data$Score) %>%
dplyr::mutate("{key_col}" := factor(.data[[key_col]], levels = rev(vapply(dims, function(x){paste0(key, x)}, FUN.VALUE = character(1))))) %>%
dplyr::left_join(y = {sample@meta.data %>%
tibble::rownames_to_column(var = "Cell") %>%
tibble::as_tibble() %>%
dplyr::select(dplyr::all_of(c("Cell", group.by, names(input_gene_list))))},
by = "Cell")
if (isTRUE(scale.enrichment)){
# Scale the enrichment scores as we are just interested in where they are enriched the most and not to compare across them.
for (name in names(input_gene_list)){
data.use[, name] <- scale(data.use[, name])[, 1]
}
}
# Prepare the data to plot.
data.use <- data.use %>%
tidyr::pivot_longer(cols = dplyr::all_of(c(names(input_gene_list))),
names_to = "Gene_Set",
values_to = "Enrichment")
# Generate DC-based heatmaps.
list.out <- list()
for (dc.use in vapply(dims, function(x){paste0(key, x)}, FUN.VALUE = character(1))){
# Filter for the DC.
data.plot <- data.use %>%
dplyr::filter(.data[[key_col]] == dc.use)
# Limit the scale to quantiles 0.1 and 0.9 to avoid extreme outliers.
limits <- c(stats::quantile(data.plot$Enrichment, 0.05, na.rm = TRUE),
stats::quantile(data.plot$Enrichment, 0.95, na.rm = TRUE))
# Bring extreme values to the cutoffs.
data.plot <- data.plot %>%
dplyr::mutate("Enrichment" = ifelse(.data$Enrichment <= limits[1], limits[1], .data$Enrichment)) %>%
dplyr::mutate("Enrichment" = ifelse(.data$Enrichment >= limits[2], limits[2], .data$Enrichment))
# Compute scale limits, breaks etc.
scale.setup <- compute_scales(sample = NULL,
feature = NULL,
assay = NULL,
reduction = NULL,
slot = NULL,
number.breaks = 5,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Generate the plot.
p <- data.plot %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$rank,
y = .data$Gene_Set,
fill = .data$Enrichment))
if (base::isTRUE(raster)){
p <- p +
ggplot2::geom_raster(interpolate = interpolate)
} else {
p <- p +
ggplot2::geom_tile()
}
legend.name <- if (flavor == "Seurat"){"Enrichment"} else if (flavor == "UCell"){"UCell score"}
legend.name.use <- ifelse(isTRUE(scale.enrichment), paste0("Z-scored | ", legend.name), legend.name)
p <- p +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.name.use,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits) +
ggplot2::xlab(paste0("Ordering of cells along ", dc.use)) +
ggplot2::ylab("Gene set") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$Gene_Set))))
# Modify the appearance of the plot.
p <- modify_continuous_legend(p = p,
legend.title = legend.name.use,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# Generate metadata plots to use on top of the main heatmap.
list.plots <- list()
list.plots[["main"]] <- p
for (name in group.by){
# Select color palette for metadata.
if (name %in% names(colors.use)){
colors.use.iteration <- colors.use[[name]]
} else {
names.use <- if(is.factor(sample@meta.data[, name])){levels(sample@meta.data[, name])} else {sort(unique(sample@meta.data[, name]))}
colors.use.iteration <- generate_color_scale(names_use = names.use, colorblind = colorblind)
}
# Generate the metadata heatmap.
p <- data.use %>%
dplyr::filter(.data[[key_col]] == dc.use) %>%
dplyr::mutate("grouped.var" = .env$name) %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$rank,
y = .data$grouped.var,
fill = .data[[name]]))
if (base::isTRUE(raster)){
p <- p +
ggplot2::geom_raster(interpolate = interpolate)
} else {
p <- p +
ggplot2::geom_tile()
}
p <- p +
ggplot2::scale_fill_manual(values = colors.use.iteration) +
ggplot2::guides(fill = ggplot2::guide_legend(title = name,
title.position = "top",
title.hjust = 0.5,
override.aes = list(color = "black",
shape = 22),
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow)) +
ggplot2::xlab(NULL) +
ggplot2::ylab(NULL) +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$grouped.var))))
list.plots[[name]] <- p
}
# Add theme to all plots.
for (name in names(list.plots)){
list.plots[[name]] <- list.plots[[name]] +
ggplot2::scale_x_discrete(expand = c(0, 0)) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y.right = ggplot2::element_text(face = axis.text.face,
color = "black",
hjust = 0),
axis.text.y.left = ggplot2::element_blank(),
axis.ticks.y.right = ggplot2::element_line(color = "black"),
axis.ticks.y.left = ggplot2::element_blank(),
axis.ticks.x = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title.y = ggplot2::element_text(face = axis.title.face, color = "black", angle = 90, hjust = 0.5, vjust = 0.5),
axis.title.x = ggplot2::element_text(face = axis.title.face, color = "black", angle = 0),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white"),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = ifelse(name == "main", 15, 10), r = 10, b = 0, l = 10),
panel.border = ggplot2::element_rect(color = border.color, fill = NA),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
}
# Reorder heatmaps for correct plotting.
list.plots <- list.plots[c(group.by, "main")]
height_unit <- c(rep((1 - main.heatmap.size) / length(group.by), length(group.by)), main.heatmap.size)
# Assemble the final heatmap.
p <- patchwork::wrap_plots(list.plots,
ncol = 1,
guides = "collect",
heights = height_unit) +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position))
list.out[[dc.use]] <- p
}
# Return the object.
if (isTRUE(return_object)){
list.out[["Object"]] <- sample
}
return(list.out)
}
================================================
FILE: R/do_RankedExpressionHeatmap.R
================================================
#' Compute a heatmap of expression of genes on the context of a dimensional reduction component.
#'
#' @inheritParams doc_function
#' @param colors.use \strong{\code{\link[base]{list}}} | A named list of named vectors. The names of the list correspond to the names of the values provided to metadata and the names of the items in the named vectors correspond to the unique values of that specific metadata variable. The values are the desired colors in HEX code for the values to plot. The used are pre-defined by the package but, in order to get the most out of the plot, please provide your custom set of colors for each metadata column!
#' @param main.heatmap.size \strong{\code{\link[base]{numeric}}} | A number from 0 to 1 corresponding to how big the main heatmap plot should be with regards to the rest (corresponds to the proportion in size).
#' @return A list of ggplot2 objects, one per dimensional reduction component, and a Seurat object if desired.
#' @export
#'
#' @example /man/examples/examples_do_RankedExpressionHeatmap.R
do_RankedExpressionHeatmap <- function(sample,
features,
assay = NULL,
slot = NULL,
dims = 1:2,
subsample = 2500,
reduction = NULL,
group.by = NULL,
colors.use = NULL,
colorblind = FALSE,
raster = FALSE,
interpolate = FALSE,
nbin = 24,
ctrl = 100,
main.heatmap.size = 0.95,
enforce_symmetry = TRUE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
font.size = 14,
font.type = "sans",
na.value = "grey75",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
legend.position = "bottom",
legend.nrow = NULL,
legend.ncol = NULL,
legend.byrow = FALSE,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
axis.text.x.angle = 45,
border.color = "black",
return_object = FALSE,
verbose = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests("do_RankedExpressionHeatmap")
check_Seurat(sample = sample)
# Check the reduction.
reduction <- check_and_set_reduction(sample = sample, reduction = reduction)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"legend.byrow" = legend.byrow,
"return_object" = return_object,
"use_viridis" = use_viridis,
"verbose" = verbose,
"interpolate" = interpolate,
"raster" = raster,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("dims" = dims,
"subsample" = subsample,
"nbin" = nbin,
"ctrl" = ctrl,
"font.size" = font.size,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"number.breaks" = number.breaks,
"axis.text.x.angle" = axis.text.x.angle,
"legend.nrow" = legend.nrow,
"legend.ncol" = legend.ncol,
"main.heatmap.size" = main.heatmap.size,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("assay" = assay,
"reduction" = reduction,
"slot" = slot,
"group.by" = group.by,
"font.type" = font.type,
"na.value" = na.value,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"legend.position" = legend.position,
"viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
`:=` <- rlang::`:=`
# nocov start
if (is.null(sample@reductions[[reduction]]@key) | is.na(sample@reductions[[reduction]]@key)){
stop(paste0(add_cross(),
crayon_body("Assay "),
crayon_key("key"),
crayon_body(" not found for the provided"),
crayon_key(" assay"),
crayon_body(". Please set a key. \n\nYou can do it as: "),
cli::style_italic(paste0(crayon_key('sample@reductions[['), cli::col_yellow("reduction"), crayon_key(']]@key <- "DC_"')))), call. = FALSE)
}
# nocov end
key <- sample@reductions[[reduction]]@key
if (!is.na(subsample)){
# Perform subsampling.
sample <- sample[, sample(colnames(sample), subsample)]
}
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
genes.use <- features %>% unique()
genes.use <- genes.use[genes.use %in% rownames(sample)]
if (is.null(assay)){assay <- check_and_set_assay(sample)$assay}
slot <- if(is.null(slot)){"data"} else {slot}
if (isTRUE(verbose)){message(paste0(add_info(initial_newline = FALSE), crayon_body("Plotting "), crayon_key("heatmaps"), crayon_body("...")))}
key_col <- stringr::str_remove_all(key, "_")
# Obtain the DC embeddings, together with the enrichment scores.
suppressWarnings({
# Workaround parameter depreciation.
if (base::isTRUE(utils::packageVersion("Seurat") < "4.9.9")){
data <- Seurat::GetAssayData(object = sample,
assay = assay,
slot = slot)
} else {
data <- SeuratObject::LayerData(object = sample,
assay = assay,
layer = slot)
}
data.use <- sample@reductions[[reduction]]@cell.embeddings %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
as.data.frame() %>%
tibble::as_tibble() %>%
tidyr::pivot_longer(cols = -dplyr::all_of("Cell"),
names_to = key_col,
values_to = "Score") %>%
dplyr::mutate("{key_col}" := stringr::str_to_upper(.data[[key_col]])) %>%
dplyr::filter(.data[[key_col]] %in% vapply(dims, function(x){paste0(key, x)}, FUN.VALUE = character(1))) %>%
dplyr::group_by(.data[[key_col]]) %>%
dplyr::reframe("rank" = rank(.data$Score),
"Cell" = .data$Cell,
"Score" = .data$Score) %>%
dplyr::mutate("{key_col}" := factor(.data[[key_col]], levels = rev(vapply(dims, function(x){paste0(key, x)}, FUN.VALUE = character(1))))) %>%
dplyr::left_join(y = {sample@meta.data %>%
tibble::rownames_to_column(var = "Cell") %>%
tibble::as_tibble() %>%
dplyr::select(dplyr::all_of(c("Cell", group.by))) %>%
dplyr::left_join(y = {data[features, , drop = FALSE] %>%
as.data.frame() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "Cell") %>%
tibble::as_tibble()},
by = "Cell")},
by = "Cell")
})
data.use <- as.data.frame(data.use)
if (isTRUE(enforce_symmetry)){
# Scale the enrichment scores as we are just interested in where they are enriched the most and not to compare across them.
for (name in features){
data.use[, name] <- scale(data.use[, name])[, 1]
}
}
# Prepare the data to plot.
data.use <- data.use %>%
tidyr::pivot_longer(cols = dplyr::all_of(c(features)),
names_to = "Feature",
values_to = "Expression") %>%
dplyr::mutate("Feature" = factor(.data$Feature, levels = genes.use))
# Generate DC-based heatmaps.
list.out <- list()
for (dc.use in vapply(dims, function(x){paste0(key, x)}, FUN.VALUE = character(1))){
# Filter for the DC.
data.plot <- data.use %>%
dplyr::filter(.data[[key_col]] == dc.use)
# Limit the scale to quantiles 0.1 and 0.9 to avoid extreme outliers.
limits <- c(stats::quantile(data.plot$Expression, 0.05, na.rm = TRUE),
stats::quantile(data.plot$Expression, 0.95, na.rm = TRUE))
# Bring extreme values to the cutoffs.
data.plot <- data.plot %>%
dplyr::mutate("Expression" = ifelse(.data$Expression <= limits[1], limits[1], .data$Expression)) %>%
dplyr::mutate("Expression" = ifelse(.data$Expression >= limits[2], limits[2], .data$Expression))
# Compute scale limits, breaks etc.
scale.setup <- compute_scales(sample = NULL,
feature = NULL,
assay = NULL,
reduction = NULL,
slot = NULL,
number.breaks = 5,
min.cutoff = NA,
max.cutoff = NA,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Generate the plot.
p <- data.plot %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$rank,
y = .data$Feature,
fill = .data$Expression))
if (base::isTRUE(raster)){
p <- p +
ggplot2::geom_raster(interpolate = interpolate)
} else {
p <- p +
ggplot2::geom_tile()
}
legend.name.use <- ifelse(isTRUE(enforce_symmetry), "Z-scored | Expression", "Expression")
p <- p +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.name.use,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits) +
ggplot2::xlab(paste0("Ordering of cells along ", dc.use)) +
ggplot2::ylab("Features") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$Features))))
# Modify the appearance of the plot.
p <- modify_continuous_legend(p = p,
legend.title = legend.name.use,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# Generate metadata plots to use on top of the main heatmap.
list.plots <- list()
list.plots[["main"]] <- p
for (name in group.by){
# Select color palette for metadata.
if (name %in% names(colors.use)){
colors.use.iteration <- colors.use[[name]]
} else {
names.use <- if(is.factor(sample@meta.data[, name])){levels(sample@meta.data[, name])} else {sort(unique(sample@meta.data[, name]))}
colors.use.iteration <- generate_color_scale(names_use = names.use, colorblind = colorblind)
}
# Generate the metadata heatmap.
p <- data.use %>%
dplyr::filter(.data[[key_col]] == dc.use) %>%
dplyr::mutate("grouped.var" = .env$name) %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$rank,
y = .data$grouped.var,
fill = .data[[name]]))
if (base::isTRUE(raster)){
p <- p +
ggplot2::geom_raster(interpolate = interpolate)
} else {
p <- p +
ggplot2::geom_tile()
}
p <- p +
ggplot2::scale_fill_manual(values = colors.use.iteration) +
ggplot2::guides(fill = ggplot2::guide_legend(title = name,
title.position = "top",
title.hjust = 0.5,
override.aes = list(color = "black",
shape = 22),
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow)) +
ggplot2::xlab(NULL) +
ggplot2::ylab(NULL) +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$grouped.var))))
list.plots[[name]] <- p
}
# Add theme to all plots.
for (name in names(list.plots)){
list.plots[[name]] <- list.plots[[name]] +
ggplot2::scale_x_discrete(expand = c(0, 0)) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y.right = ggplot2::element_text(face = axis.text.face,
color = "black",
hjust = 0),
axis.text.y.left = ggplot2::element_blank(),
axis.ticks.y.right = ggplot2::element_line(color = "black"),
axis.ticks.y.left = ggplot2::element_blank(),
axis.ticks.x = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title.y = ggplot2::element_text(face = axis.title.face, color = "black", angle = 90, hjust = 0.5, vjust = 0.5),
axis.title.x = ggplot2::element_text(face = axis.title.face, color = "black", angle = 0),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white"),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = ifelse(name == "main", 15, 10), r = 10, b = 0, l = 10),
panel.border = ggplot2::element_rect(color = border.color, fill = NA),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
}
# Reorder heatmaps for correct plotting.
list.plots <- list.plots[c(group.by, "main")]
height_unit <- c(rep((1 - main.heatmap.size) / length(group.by), length(group.by)), main.heatmap.size)
# Assemble the final heatmap.
p <- patchwork::wrap_plots(list.plots,
ncol = 1,
guides = "collect",
heights = height_unit) +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position))
list.out[[dc.use]] <- p
}
# Return the object.
if (isTRUE(return_object)){
list.out[["Object"]] <- sample
}
return(list.out)
}
================================================
FILE: R/do_RidgePlot.R
================================================
#' Create ridge plots.
#'
#' This function computes ridge plots based on the \pkg{ggridges} package.
#'
#' @inheritParams doc_function
#' @param colors.use \strong{\code{\link[base]{character}}} | Named vector of colors to use. Has to match the unique values of group.by or color.by (if used) when scale_type is set to categorical.
#' @param continuous_scale \strong{\code{\link[base]{logical}}} | Whether to color the ridges depending on a categorical or continuous scale.
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_RidgePlot.R
do_RidgePlot <- function(sample,
feature,
group.by = NULL,
split.by = NULL,
assay = "SCT",
slot = "data",
continuous_scale = FALSE,
legend.title = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
colors.use = NULL,
colorblind = FALSE,
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
flip = FALSE,
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_RidgePlot")
`%>%` <- magrittr::`%>%`
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("continuous_scale" = continuous_scale,
"plot.grid" = plot.grid,
"flip" = flip,
"legend.nrow" = legend.nrow,
"use_viridis" = use_viridis,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"font.size" = font.size,
"viridis.direction" = viridis.direction,
"axis.text.x.angle" = axis.text.x.angle,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("feature" = feature,
"group.by" = group.by,
"split.by" = split.by,
"assay" = assay,
"slot" = slot,
"legend.title" = legend.title,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"colors.use" = colors.use,
"font.type" = font.type,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"xlab" = xlab,
"ylab" = ylab,
"viridis.palette" = viridis.palette,
"grid.color" = grid.color,
"grid.type" = grid.type,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
if (!is.null(legend.position)){check_parameters(parameter = legend.position, parameter_name = "legend.position")}
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
if (!is.null(colors.use)){
check_colors(colors.use, parameter_name = "colors.use")
}
if (is.null(legend.position)){
legend.position <- if(isTRUE(continuous_scale)){"bottom"} else {"none"}
}
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (is.null(legend.title)){
legend.title = group.by
}
data <- get_data_column_in_context(sample = sample,
feature = feature,
assay = assay,
slot = slot,
group.by = group.by,
split.by = split.by)
if (isTRUE(continuous_scale)){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$feature,
y = .data$group.by,
fill = ggplot2::after_stat(x))) +
ggridges::geom_density_ridges_gradient(color = "black") +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = "grey75",
name = feature,
breaks = scales::extended_breaks(n = number.breaks))
p <- modify_continuous_legend(p = p,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
} else if (base::isFALSE(continuous_scale)){
if (is.null(colors.use)){
if (is.null(group.by)){
values.use <- generate_color_scale(levels(sample), colorblind = colorblind)
} else {
if (is.factor(sample@meta.data[, group.by])){
values.use <- generate_color_scale(levels(sample@meta.data[, group.by]), colorblind = colorblind)
} else {
values.use <- generate_color_scale(unique(sample@meta.data[, group.by]), colorblind = colorblind)
}
}
} else {
values.use <- colors.use
}
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$feature,
y = .data$group.by,
fill = .data$group.by)) +
ggridges::geom_density_ridges(color = "black") +
ggplot2::scale_fill_manual(values = values.use,
name = legend.title) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.title,
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol))
}
if (!is.null(split.by)){
# Facet.
p <- p +
ggplot2::facet_grid(~ .data$split.by)
}
p <- p +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::xlab(if (is.null(xlab)) {feature} else (xlab)) +
ggplot2::ylab(if (is.null(ylab)) {"Groups"} else (ylab)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.title = ggplot2::element_text(color = "black",
face = axis.title.face),
axis.line.y = if (base::isFALSE(flip)) {ggplot2::element_line(color = "black")} else if (isTRUE(flip)) {ggplot2::element_blank()},
axis.line.x = if (isTRUE(flip)) {ggplot2::element_line(color = "black")} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(color = "black", face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
panel.grid.major = ggplot2::element_blank(),
panel.grid.minor = ggplot2::element_blank(),
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
panel.grid.major.y = if(base::isFALSE(flip)){ggplot2::element_blank()} else {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)} else {ggplot2::element_blank()}},
panel.grid.major.x = if(base::isFALSE(flip)){if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)} else {ggplot2::element_blank()}} else {ggplot2::element_blank()},
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
strip.text = ggplot2::element_text(color = "black", face = "bold"))
if (isTRUE(flip)){
p <- p +
ggplot2::coord_flip()
}
return(p)
}
================================================
FILE: R/do_SCEnrichmentHeatmap.R
================================================
#' Perform a single-cell-based heatmap showing the enrichment in a list of gene sets.
#'
#' This function is heavily inspired by \strong{\code{\link[Seurat]{DoHeatmap}}}.
#'
#' @inheritParams doc_function
#' @param proportional.size \strong{\code{\link[base]{logical}}} | Whether the groups should take the same space in the plot or not.
#' @param main.heatmap.size \strong{\code{\link[base]{numeric}}} | Controls the size of the main heatmap (proportion-wise, defaults to 0.95).
#' @param metadata \strong{\code{\link[base]{character}}} | Categorical metadata variables to plot alongside the main heatmap.
#' @param metadata.colors \strong{\code{\link[SCpubr]{named_list}}} | Named list of valid colors for each of the variables defined in \strong{\code{metadata}}.
#' @param flavor \strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.
#' @param ncores \strong{\code{\link[base]{numeric}}} | Number of cores used to run UCell scoring.
#' @param storeRanks \strong{\code{\link[base]{logical}}} | Whether to store the ranks for faster UCell scoring computations. Might require large amounts of RAM.
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_SCEnrichmentHeatmap.R
do_SCEnrichmentHeatmap <- function(sample,
input_gene_list,
assay = NULL,
slot = NULL,
group.by = NULL,
features.order = NULL,
metadata = NULL,
metadata.colors = NULL,
colorblind = FALSE,
subsample = NA,
cluster = TRUE,
flavor = "Seurat",
return_object = FALSE,
ncores = 1,
storeRanks = TRUE,
interpolate = FALSE,
nbin = 24,
ctrl = 100,
xlab = "Cells",
ylab = "Gene set",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.position = "bottom",
legend.title = NULL,
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
strip.text.color = "black",
strip.text.angle = 0,
strip.spacing = 10,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
main.heatmap.size = 0.95,
enforce_symmetry = FALSE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
na.value = "grey75",
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
proportional.size = TRUE,
verbose = FALSE,
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_SCEnrichmentHeatmap")
check_Seurat(sample)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"proportional.size" = proportional.size,
"verbose" = verbose,
"legend.byrow" = legend.byrow,
"use_viridis" = use_viridis,
"cluster" = cluster,
"storeRanks" = storeRanks,
"return_object" = return_object,
"interpolate" = interpolate,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"viridis.direction" = viridis.direction,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.ncol,
"strip.spacing" = strip.spacing,
"strip.text.angle" = strip.text.angle,
"main.heatmap.size" = main.heatmap.size,
"sequential.direction" = sequential.direction,
"nbin" = nbin,
"ctrl" = ctrl,
"ncores" = ncores,
"diverging.direction" = diverging.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("input_gene_list" = input_gene_list,
"assay" = assay,
"slot" = slot,
"group.by" = group.by,
"xlab" = xlab,
"ylab" = ylab,
"font.type" = font.type,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"legend.position" = legend.position,
"legend.title" = legend.title,
"legend.type" = legend.type,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"strip.text.color" = strip.text.color,
"viridis.palette" = viridis.palette,
"na.value" = na.value,
"metadata" = metadata,
"metadata.colors" = metadata.colors,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"flavor" = flavor,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
if (!(is.null(assay)) & flavor == "UCell"){
warning(paste0(add_warning(), crayon_body("When using "),
crayon_key("flavor = UCell"),
crayon_body(" do not use the "),
crayon_key("assay"),
crayon_body(" parameter.\nInstead, make sure that the "),
crayon_key("assay"),
crayon_body(" you want to compute the scores with is set as the "),
crayon_key("default"),
crayon_body(" assay. Setting it to "),
crayon_key("NULL"),
crayon_body(".")), call. = FALSE)
}
if (!(is.null(slot)) & flavor == "Seurat"){
warning(paste0(add_warning(), crayon_body("When using "),
crayon_key("flavor = Seurat"),
crayon_body(" do not use the "),
crayon_key("slot"),
crayon_body(" parameter.\nThis is determiend by default in "),
crayon_key("Seurat"),
crayon_body(". Setting it to "),
crayon_key("NULL"),
crayon_body(".")), call. = FALSE)
}
if (is.null(assay)){assay <- check_and_set_assay(sample)$assay}
slot <- if(is.null(slot)){"data"} else {slot}
if (is.character(input_gene_list)){
stop(paste0(add_cross(),
crayon_body("You have provided a string of genes to "),
crayon_key("input_gene_list"),
crayon_body(". Please provide a "),
crayon_key("named list"),
crayon_body(" instead.")), call. = FALSE)
}
if (!is.null(features.order)){
assertthat::assert_that(sum(features.order %in% names(input_gene_list)) == length(names(input_gene_list)),
msg = paste0(add_cross(), crayon_body("The names provided to "),
crayon_key("features.order"),
crayon_body(" do not match the names of the gene sets in "),
crayon_key("input_gene_list"),
crayon_body(".")))
}
# nocov start
if (!is.null(features.order)){
features.order <- stringr::str_replace_all(features.order, "_", ".")
}
# nocov end
if (is.null(legend.title)){
if (flavor == "UCell"){
legend.title <- "UCell score"
} else if (flavor == "Seurat"){
legend.title <- "Enrichment"
}
}
input_list <- input_gene_list
assertthat::assert_that(!is.null(names(input_list)),
msg = paste0(add_cross(), crayon_body("Please provide a "),
crayon_key("named list"),
crayon_body(" to "),
crayon_key("input_gene_list"),
crayon_body(".")))
if (length(unlist(stringr::str_match_all(names(input_list), "_"))) > 0){
warning(paste0(add_warning(), crayon_body("Found "),
crayon_key("underscores (_)"),
crayon_body(" in the name of the gene sets provided. Replacing them with "),
crayon_key("dots (.)"),
crayon_body(" to avoid conflicts when generating the Seurat assay.")), call. = FALSE)
names.use <- stringr::str_replace_all(names(input_list), "_", ".")
names(input_list) <- names.use
}
if (length(unlist(stringr::str_match_all(names(input_list), "-"))) > 0){
warning(paste0(add_warning(), crayon_body("Found "),
crayon_key("dashes (-)"),
crayon_body(" in the name of the gene sets provided. Replacing them with "),
crayon_key("dots (.)"),
crayon_body(" to avoid conflicts when generating the Seurat assay.")), call. = FALSE)
names.use <- stringr::str_replace_all(names(input_list), "-", ".")
names(input_list) <- names.use
}
assertthat::assert_that(sum(names(input_list) %in% colnames(sample@meta.data)) == 0,
msg = paste0(add_cross(), crayon_body("Please make sure you do not provide a list of gene sets whose "),
crayon_key("names"),
crayon_body(" match any of the "),
crayon_key("metadata columns"),
crayon_body(" of the Seurat object.")))
# Compute the enrichment scores.
sample <- compute_enrichment_scores(sample = sample,
input_gene_list = input_list,
verbose = verbose,
nbin = nbin,
ctrl = ctrl,
flavor = flavor,
ncores = ncores,
storeRanks = storeRanks,
# nocov start
assay = if (flavor == "UCell"){NULL} else {assay},
slot = if (flavor == "Seurat"){NULL} else {slot})
# nocov end
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
assertthat::assert_that(length(group.by) == 1,
msg = paste0(add_cross(), crayon_body("Please provide only a single value to "),
crayon_key("group.by"),
crayon_body(".")))
# nocov start
# Perform hierarchical clustering cluster-wise
order.use <- if (is.factor(sample@meta.data[, group.by])){levels(sample@meta.data[, group.by])} else {sort(unique(sample@meta.data[, group.by]))}
# nocov end
matrix <- sample@meta.data[, c(names(input_list), group.by)] %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::group_by(.data[[group.by]])
if (!is.na(subsample)){
matrix <- matrix %>%
dplyr::slice_sample(n = subsample)
}
if (isTRUE(cluster)){
# Retrieve the order median-wise to cluster heatmap bodies.
median.matrix <- matrix %>%
dplyr::summarise(dplyr::across(dplyr::all_of(names(input_list)), function(x){stats::median(x, na.rm = TRUE)})) %>%
dplyr::mutate("group.by" = as.character(.data[[group.by]])) %>%
dplyr::select(-dplyr::all_of(group.by)) %>%
as.data.frame() %>%
tibble::column_to_rownames(var = "group.by") %>%
as.matrix() %>%
t()
group_order <- stats::hclust(stats::dist(t(median.matrix), method = "euclidean"), method = "ward.D")$order
order.use <- order.use[group_order]
}
# Retrieve the order median-wise for the genes.
if (length(names(input_list)) == 1) {
row_order <- names(input_list)[1]
} else {
if (isTRUE(cluster)){
row_order <- names(input_list)[stats::hclust(stats::dist(median.matrix, method = "euclidean"), method = "ward.D")$order]
} else {
row_order <- names(input_list)
}
}
# Compute cell order to group cells withing heatmap bodies.
# nocov start
if (isTRUE(cluster)){
if (sum(matrix %>% dplyr::pull(.data[[group.by]]) %>% table() > 65536)){
warning(paste0(add_warning(), crayon_body("A given group in "),
crayon_key("group.by"),
crayon_body(" has more than "),
crayon_key("65536"),
crayon_body(" cells. Disabling clustering of the cells.")))
cluster <- FALSE
}
}
# nocov end
if (isTRUE(cluster)){
col_order <- list()
for (item in order.use){
cells.use <- matrix %>%
dplyr::filter(.data[[group.by]] == item) %>%
dplyr::pull(.data$cell)
matrix.subset <- matrix %>%
dplyr::ungroup() %>%
dplyr::select(-dplyr::all_of(c(group.by))) %>%
tibble::column_to_rownames(var = "cell") %>%
as.data.frame() %>%
as.matrix() %>%
t()
matrix.subset <- matrix.subset[, cells.use]
if (length(names(input_list)) == 1){
matrix.use <- as.matrix(matrix.subset)
} else {
matrix.use <- t(matrix.subset)
}
col_order.use <- stats::hclust(stats::dist(matrix.use, method = "euclidean"), method = "ward.D")$order
col_order[[item]] <- cells.use[col_order.use]
}
col_order <- unlist(unname(col_order))
} else {
col_order <- matrix %>% dplyr::pull("cell")
}
# Retrieve metadata matrix.
metadata_plots <- list()
if (!is.null(metadata)){
metadata.matrix <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c(metadata, group.by))) %>%
dplyr::mutate("group.by" = .data[[group.by]]) %>%
as.matrix() %>%
t()
metadata.matrix <- metadata.matrix[, col_order]
counter <- 0
for (name in metadata){
counter <- counter + 1
if (counter == 1){
name_labels <- name
}
plot_data <- metadata.matrix[c(name, "group.by"), ] %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::mutate("group.by" = factor(.data$group.by, levels = order.use),
"y" = .data[[name]],
"y_row" = name,
"cell" = factor(.data$cell, levels = col_order)) %>%
dplyr::select(-dplyr::all_of(name)) %>%
tibble::as_tibble()
if (name %in% names(metadata.colors)){
colors.use <- metadata.colors[[name]]
} else {
names.use <- if(is.factor(sample@meta.data[, name])){levels(sample@meta.data[, name])} else {sort(unique(sample@meta.data[, name]))}
colors.use <- generate_color_scale(names_use = names.use, colorblind = colorblind)
}
p <- plot_data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$cell,
y = .data$y_row,
fill = .data$y)) +
ggplot2::geom_tile() +
ggplot2::facet_grid(~ .data$group.by,
scales = "free_x",
# nocov start
space = if(isTRUE(proportional.size)) {"fixed"} else {"free"}) +
# nocov end
ggplot2::scale_fill_manual(values = colors.use) +
ggplot2::guides(fill = ggplot2::guide_legend(title = name,
title.position = "top",
title.hjust = 0.5,
override.aes = list(color = "black",
shape = 22),
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow)) +
ggplot2::xlab(NULL) +
ggplot2::ylab(NULL)
metadata_plots[[name]] <- p
}
}
# Generate the plotting data.
plot_data <- matrix %>%
dplyr::ungroup() %>%
as.data.frame() %>%
tidyr::pivot_longer(cols = -dplyr::all_of(c(group.by, "cell")),
names_to = "gene",
values_to = "expression") %>%
dplyr::rename("group.by" = dplyr::all_of(c(group.by))) %>%
dplyr::mutate("group.by" = factor(.data$group.by, levels = order.use),
"gene" = factor(.data$gene, levels = if (is.null(features.order)){rev(row_order)} else {features.order}),
"cell" = factor(.data$cell, levels = col_order))
# Modify data to fit the cutoffs selected.
plot_data_limits <- plot_data
if (!is.na(min.cutoff)){
plot_data <- plot_data %>%
dplyr::mutate("expression" = ifelse(.data$expression < min.cutoff, min.cutoff, .data$expression))
}
if (!is.na(max.cutoff)){
plot_data <- plot_data %>%
dplyr::mutate("expression" = ifelse(.data$expression > max.cutoff, max.cutoff, .data$expression))
}
p <- plot_data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$cell,
y = .data$gene,
fill = .data$expression)) +
ggplot2::geom_raster(interpolate = interpolate)
p <- p + ggplot2::facet_grid(~ .data$group.by,
scales = "free_x",
space = if(isTRUE(proportional.size)) {"fixed"} else {"free"})
limits.use <- c(min(plot_data_limits$expression, na.rm = TRUE),
max(plot_data_limits$expression, na.rm = TRUE))
scale.setup <- compute_scales(sample = sample,
feature = NULL,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits.use)
p <- p +
ggplot2::ylab(ylab) +
ggplot2::xlab(xlab) +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# Theme setup.
metadata_plots[["main"]] <- p
# Configure plot margins.
for (name in names(metadata_plots)){
metadata_plots[[name]] <- metadata_plots[[name]] +
ggplot2::scale_x_discrete(expand = c(0, 0)) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y = ggplot2::element_text(face = axis.text.face,
color = "black"),
axis.ticks.y = ggplot2::element_line(color = "black"),
axis.ticks.x = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title = ggplot2::element_text(face = axis.title.face, color = "black"),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white"),
strip.background = ggplot2::element_blank(),
strip.clip = "off",
panel.spacing = ggplot2::unit(strip.spacing, units = "pt"),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 10, b = 0, l = 10),
panel.border = ggplot2::element_rect(color = border.color, fill = NA),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
if (!is.null(metadata)){
if (name == name_labels){
metadata_plots[[name]] <- metadata_plots[[name]] + ggplot2::theme(strip.text.x = ggplot2::element_text(family = font.type,
face = "bold",
color = strip.text.color,
angle = strip.text.angle))
} else {
metadata_plots[[name]] <- metadata_plots[[name]] + ggplot2::theme(strip.text.x = ggplot2::element_blank())
}
} else {
metadata_plots[[name]] <- metadata_plots[[name]] + ggplot2::theme(strip.text.x = ggplot2::element_text(family = font.type,
face = "bold",
color = strip.text.color,
angle = strip.text.angle))
}
}
if (!is.null(metadata)){
plots_wrap <- c(metadata_plots[c(metadata, "main")])
main_body_size <- main.heatmap.size
height_unit <- c(rep((1 - main_body_size) / length(metadata), length(metadata)), main_body_size)
out <- patchwork::wrap_plots(plots_wrap,
ncol = 1,
guides = "collect",
heights = height_unit) +
patchwork::plot_annotation(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption,
theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
face = plot.caption.face,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
} else {
out <- metadata_plots[["main"]]
}
out.list <- list()
out.list[["Heatmap"]] <- out
if (isTRUE(return_object)){
sample[["Enrichment"]] <- sample@meta.data %>%
dplyr::select(dplyr::all_of(names(input_list))) %>%
t() %>%
as.data.frame() %>%
Seurat::CreateAssayObject(.)
sample@meta.data <- sample@meta.data %>%
dplyr::select(-dplyr::all_of(names(input_list)))
sample@assays$Enrichment@key <- "Enrichment_"
out.list[["Object"]] <- sample
return(out.list)
} else {
return(out.list[["Heatmap"]])
}
}
================================================
FILE: R/do_SCExpressionHeatmap.R
================================================
#' Perform a single-cell-based heatmap showing the expression of genes.
#'
#' This function is heavily inspired by \strong{\code{\link[Seurat]{DoHeatmap}}}.
#'
#' @inheritParams doc_function
#' @param proportional.size \strong{\code{\link[base]{logical}}} | Whether the groups should take the same space in the plot or not.
#' @param main.heatmap.size \strong{\code{\link[base]{numeric}}} | Controls the size of the main heatmap (proportion-wise, defaults to 0.95).
#' @param metadata \strong{\code{\link[base]{character}}} | Categorical metadata variables to plot alongside the main heatmap.
#' @param metadata.colors \strong{\code{\link[SCpubr]{named_list}}} | Named list of valid colors for each of the variables defined in \strong{\code{metadata}}.
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_SCExpressionHeatmap.R
do_SCExpressionHeatmap <- function(sample,
features,
assay = NULL,
slot = NULL,
group.by = NULL,
features.order = NULL,
metadata = NULL,
metadata.colors = NULL,
colorblind = FALSE,
subsample = NA,
cluster = TRUE,
interpolate = FALSE,
xlab = "Cells",
ylab = "Genes",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.position = "bottom",
legend.title = "Expression",
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
strip.text.color = "black",
strip.text.angle = 0,
strip.spacing = 10,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
main.heatmap.size = 0.95,
enforce_symmetry = FALSE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
na.value = "grey75",
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
proportional.size = TRUE,
verbose = TRUE,
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_SCExpressionHeatmap")
check_Seurat(sample)
if (is.null(assay)){assay <- check_and_set_assay(sample)$assay}
slot <- if(is.null(slot)){"data"} else {slot}
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"proportional.size" = proportional.size,
"verbose" = verbose,
"legend.byrow" = legend.byrow,
"use_viridis" = use_viridis,
"cluster" = cluster,
"interpolate" = interpolate,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("font.size" = font.size,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"viridis.direction" = viridis.direction,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.ncol,
"strip.spacing" = strip.spacing,
"strip.text.angle" = strip.text.angle,
"main.heatmap.size" = main.heatmap.size,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("features" = features,
"assay" = assay,
"slot" = slot,
"group.by" = group.by,
"xlab" = xlab,
"ylab" = ylab,
"font.type" = font.type,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"legend.position" = legend.position,
"legend.title" = legend.title,
"legend.type" = legend.type,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"strip.text.color" = strip.text.color,
"viridis.palette" = viridis.palette,
"na.value" = na.value,
"metadata" = metadata,
"metadata.colors" = metadata.colors,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(na.value, parameter_name = "na.value")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
`%>%` <- magrittr::`%>%`
if (utils::packageVersion("Seurat") < "5.0.0"){
genes.avail <- rownames(SeuratObject::GetAssayData(sample, slot = slot, assay = assay))
} else {
genes.avail <- rownames(SeuratObject::GetAssayData(sample, layer = slot, assay = assay))
}
assertthat::assert_that(sum(features %in% genes.avail) > 0,
msg = paste0(add_cross(), crayon_body("None of the features are present in the row names of the assay "),
crayon_key(assay),
crayon_body(" using the slot "),
crayon_key(slot),
crayon_body(".\nPlease make sure that you only provide "),
crayon_key("genes"),
crayon_body(" as input.\nIf you select the slot "),
crayon_key("scale.data"),
crayon_body(", sometimes some of the features are missing.")))
missing_features <- features[!(features %in% genes.avail)]
if (length(missing_features) > 0){
if (isTRUE(verbose)){
warning(paste0(add_warning(), crayon_body("Some features are missing in the following assay "),
crayon_key(assay),
crayon_body(" using the slot "),
crayon_key(slot),
crayon_body(":\n"),
paste(vapply(missing_features, crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", "))), call. = FALSE)
}
}
features <- features[features %in% genes.avail]
if (!is.null(features.order)){
features.order <- features.order[features.order %in% genes.avail]
assertthat::assert_that(sum(features.order %in% features) == length(features),
msg = paste0(add_cross(), crayon_body("The names provided to "),
crayon_key("features.order"),
crayon_body(" do not match the names of the gene sets in "),
crayon_key("input_gene_list"),
crayon_body(".")))
}
if (utils::packageVersion("Seurat") < "5.0.0"){
matrix <- SeuratObject::GetAssayData(sample,
assay = assay,
slot = slot)[features, , drop = FALSE] %>%
as.matrix()
} else {
matrix <- SeuratObject::GetAssayData(sample,
assay = assay,
layer = slot)[features, , drop = FALSE] %>%
as.matrix()
}
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = TRUE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
assertthat::assert_that(length(group.by) == 1,
msg = paste0(add_cross(), crayon_body("Please provide only a single value to "),
crayon_key("group.by"),
crayon_body(".")))
# nocov start
# Perform hierarchical clustering cluster-wise
order.use <- if (is.factor(sample@meta.data[, group.by])){levels(sample@meta.data[, group.by])} else {sort(unique(sample@meta.data[, group.by]))}
# nocov end
matrix <- matrix %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::select(dplyr::all_of(c("cell", group.by)))},
by = "cell") %>%
dplyr::group_by(.data[[group.by]])
if (!is.na(subsample)){
matrix <- matrix %>%
dplyr::slice_sample(n = subsample)
}
# Retrieve the order median-wise to cluster heatmap bodies.
if (isTRUE(cluster)){
median.matrix <- matrix %>%
dplyr::summarise(dplyr::across(dplyr::all_of(features), function(x){stats::median(x, na.rm = TRUE)})) %>%
dplyr::mutate("group.by" = as.character(.data[[group.by]])) %>%
dplyr::select(-dplyr::all_of(group.by)) %>%
as.data.frame() %>%
tibble::column_to_rownames(var = "group.by") %>%
as.matrix() %>%
t()
group_order <- stats::hclust(stats::dist(t(median.matrix), method = "euclidean"), method = "ward.D")$order
order.use <- order.use[group_order]
}
# Retrieve the order median-wise for the genes.
if (length(features) == 1) {
row_order <- features[1]
} else {
if (isTRUE(cluster)){
row_order <- features[stats::hclust(stats::dist(median.matrix, method = "euclidean"), method = "ward.D")$order]
} else {
row_order <- features
}
}
# Compute cell order to group cells withing heatmap bodies.
# nocov start
if (isTRUE(cluster)){
if (sum(matrix %>% dplyr::pull(dplyr::all_of(c(group.by))) %>% table() > 65536)){
warning(paste0(add_warning(), crayon_body("A given group in "),
crayon_key("group.by"),
crayon_body(" has more than "),
crayon_key("65536"),
crayon_body(" cells. Disabling clustering of the cells.")), call. = FALSE)
cluster <- FALSE
}
}
# nocov end
if (isTRUE(cluster)){
col_order <- list()
for (item in order.use){
cells.use <- matrix %>%
dplyr::filter(.data[[group.by]] == item) %>%
dplyr::pull(dplyr::all_of("cell"))
matrix.subset <- matrix %>%
dplyr::ungroup() %>%
dplyr::select(-dplyr::all_of(c(group.by))) %>%
tibble::column_to_rownames(var = "cell") %>%
as.data.frame() %>%
as.matrix() %>%
t()
matrix.subset <- matrix.subset[, cells.use]
# nocov start
if (sum(is.na(matrix.subset)) > 0){
warning(paste0(add_warning(), crayon_key("NA"), crayon_body("found in the "),
crayon_key("expression matrix"),
crayon_body(". Replacing them with "),
crayon_key("0"),
crayon_body(".")), call. = FALSE)
matrix.subset[is.na(matrix.subset)] <- 0
}
# nocov end
if (length(features) == 1){
matrix.use <- as.matrix(matrix.subset)
} else {
matrix.use <- t(matrix.subset)
}
col_order.use <- stats::hclust(stats::dist(matrix.use, method = "euclidean"), method = "ward.D")$order
col_order[[item]] <- cells.use[col_order.use]
}
col_order <- unlist(unname(col_order))
} else {
col_order <- matrix %>% dplyr::pull("cell")
}
# Retrieve metadata matrix.
metadata_plots <- list()
if (!is.null(metadata)){
metadata.matrix <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c(metadata, group.by))) %>%
dplyr::mutate("group.by" = .data[[group.by]]) %>%
as.matrix() %>%
t()
metadata.matrix <- metadata.matrix[, col_order]
counter <- 0
for (name in metadata){
counter <- counter + 1
if (counter == 1){
name_labels <- name
}
plot_data <- metadata.matrix[c(name, "group.by"), ] %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::mutate("group.by" = factor(.data$group.by, levels = order.use),
"y" = .data[[name]],
"y_row" = name,
"cell" = factor(.data$cell, levels = col_order)) %>%
dplyr::select(-dplyr::all_of(name)) %>%
tibble::as_tibble()
if (name %in% names(metadata.colors)){
colors.use <- metadata.colors[[name]]
} else {
names.use <- if(is.factor(sample@meta.data[, name])){levels(sample@meta.data[, name])} else {sort(unique(sample@meta.data[, name]))}
colors.use <- generate_color_scale(names_use = names.use, colorblind = colorblind)
}
p <- plot_data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$cell,
y = .data$y_row,
fill = .data$y)) +
ggplot2::geom_tile() +
ggplot2::facet_grid(~ .data$group.by,
scales = "free_x",
space = if(isTRUE(proportional.size)) {"fixed"} else {"free"}) +
ggplot2::scale_fill_manual(values = colors.use) +
ggplot2::guides(fill = ggplot2::guide_legend(title = name,
title.position = "top",
title.hjust = 0.5,
override.aes = list(color = "black",
shape = 22),
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow)) +
ggplot2::xlab(NULL) +
ggplot2::ylab(NULL)
metadata_plots[[name]] <- p
}
}
# Generate the plotting data.
plot_data <- matrix %>%
dplyr::ungroup() %>%
as.data.frame() %>%
tidyr::pivot_longer(cols = -dplyr::all_of(c(group.by, "cell")),
names_to = "gene",
values_to = "expression") %>%
dplyr::rename("group.by" = dplyr::all_of(c(group.by))) %>%
dplyr::mutate("group.by" = factor(.data$group.by, levels = order.use),
"gene" = factor(.data$gene, levels = if (is.null(features.order)){rev(row_order)} else {features.order}),
"cell" = factor(.data$cell, levels = col_order))
# Modify data to fit the cutoffs selected.
plot_data_limits <- plot_data
if (!is.na(min.cutoff)){
plot_data <- plot_data %>%
dplyr::mutate("expression" = ifelse(.data$expression < min.cutoff, min.cutoff, .data$expression))
}
if (!is.na(max.cutoff)){
plot_data <- plot_data %>%
dplyr::mutate("expression" = ifelse(.data$expression > max.cutoff, max.cutoff, .data$expression))
}
p <- plot_data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$cell,
y = .data$gene,
fill = .data$expression)) +
ggplot2::geom_raster(interpolate = interpolate)
p <- p + ggplot2::facet_grid(~ .data$group.by,
scales = "free_x",
space = if(isTRUE(proportional.size)) {"fixed"} else {"free"})
limits.use <- c(min(plot_data_limits$expression, na.rm = TRUE),
max(plot_data_limits$expression, na.rm = TRUE))
scale.setup <- compute_scales(sample = sample,
feature = NULL,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits.use)
p <- p +
ggplot2::ylab(ylab) +
ggplot2::xlab(xlab) +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# Theme setup.
metadata_plots[["main"]] <- p
# Configure plot margins.
for (name in names(metadata_plots)){
metadata_plots[[name]] <- metadata_plots[[name]] +
ggplot2::scale_x_discrete(expand = c(0, 0)) +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_blank(),
axis.text.y = ggplot2::element_text(face = axis.text.face,
color = "black"),
axis.ticks.y = ggplot2::element_line(color = "black"),
axis.ticks.x = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.title = ggplot2::element_text(face = axis.title.face, color = "black"),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white"),
strip.background = ggplot2::element_blank(),
strip.clip = "off",
panel.spacing = ggplot2::unit(strip.spacing, units = "pt"),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 10, b = 0, l = 10),
panel.border = ggplot2::element_rect(color = border.color, fill = NA),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
if (!is.null(metadata)){
if (name == name_labels){
metadata_plots[[name]] <- metadata_plots[[name]] + ggplot2::theme(strip.text.x = ggplot2::element_text(family = font.type,
face = "bold",
color = strip.text.color,
angle = strip.text.angle))
} else {
metadata_plots[[name]] <- metadata_plots[[name]] + ggplot2::theme(strip.text.x = ggplot2::element_blank())
}
} else {
metadata_plots[[name]] <- metadata_plots[[name]] + ggplot2::theme(strip.text.x = ggplot2::element_text(family = font.type,
face = "bold",
color = strip.text.color,
angle = strip.text.angle))
}
}
if (!is.null(metadata)){
plots_wrap <- c(metadata_plots[c(metadata, "main")])
main_body_size <- main.heatmap.size
height_unit <- c(rep((1 - main_body_size) / length(metadata), length(metadata)), main_body_size)
out <- patchwork::wrap_plots(plots_wrap,
ncol = 1,
guides = "collect",
heights = height_unit) +
patchwork::plot_annotation(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption,
theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
color = "black",
face = plot.subtitle.face,
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
color = "black",
face = plot.caption.face,
hjust = 1),
plot.caption.position = "plot"))
} else {
out <- metadata_plots[["main"]]
}
return(out)
}
================================================
FILE: R/do_StripPlot.R
================================================
#' Generate a Strip plot.
#'
#' A strip plot is a scatter plot in which we plot continuous values on the Y axis grouped by a categorical value in the X. This is plotted as a dot plot, jittered so that the dots span
#' all the way to the other groups. On top of this, the mean and .66 and .95 of the data is plotted, depicting the overall distribution of the dots. The cells can, then, be colored by
#' a continuous variable (same as Y axis or different) or a categorical one (same as X axis or different).
#'
#'
#' @inheritParams doc_function
#' @param scale_type \strong{\code{\link[base]{character}}} | Type of color scale to use. One of:
#' \itemize{
#' \item \emph{\code{categorical}}: Use a categorical color scale based on the values of "group.by".
#' \item \emph{\code{continuous}}: Use a continuous color scale based on the values of "feature".
#' }
#' @param order \strong{\code{\link[base]{logical}}} | Whether to order the groups by the median of the data (highest to lowest).
#' @param jitter \strong{\code{\link[base]{numeric}}} | Amount of jitter in the plot along the X axis. The lower the value, the more compacted the dots are.
#' @param colors.use \strong{\code{\link[base]{character}}} | Named vector of colors to use. Has to match the unique values of group.by when scale_type is set to categorical.
#'
#' @return Either a plot of a list of plots, depending on the number of features provided.
#' @export
#' @example /man/examples/examples_do_StripPlot.R
do_StripPlot <- function(sample,
features,
assay = NULL,
slot = "data",
group.by = NULL,
split.by = NULL,
enforce_symmetry = FALSE,
scale_type = "continuous",
order = TRUE,
plot_cell_borders = TRUE,
jitter = 0.45,
pt.size = 1,
border.size = 2,
border.color = "black",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
viridis.palette = "G",
viridis.direction = 1,
colors.use = NULL,
colorblind = FALSE,
na.value = "grey75",
legend.ncol = NULL,
legend.nrow = NULL,
legend.icon.size = 4,
legend.byrow = FALSE,
legend.title = NULL,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = "Groups",
ylab = feature,
flip = FALSE,
min.cutoff = rep(NA, length(features)),
max.cutoff = rep(NA, length(features)),
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
use_viridis = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_StripPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"order" = order,
"plot_cell_borders" = plot_cell_borders,
"flip" = flip,
"use_viridis" = use_viridis,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pt.size" = pt.size,
"jitter" = jitter,
"font.size" = font.size,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"border.size" = border.size,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow,
"legend.icon.size" = legend.icon.size,
"viridis.direction" = viridis.direction,
"axis.text.x.angle" = axis.text.x.angle,
"number.breaks" = number.breaks,
"sequential.direction" = sequential.direction)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("legend.position" = legend.position,
"features" = features,
"assay" = assay,
"group.by" = group.by,
"slot" = slot,
"split.by" = split.by,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"scale_type" = scale_type,
"viridis.palette" = viridis.palette,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"border.color" = border.color,
"na.value" = na.value,
"diverging.palette" = diverging.palette,
"sequential.palette" = sequential.palette,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
# Checks
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(border.color, parameter_name = "border.color")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(na.value, parameter_name = "na.value")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = scale_type, parameter_name = "scale_type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
`%>%` <- magrittr::`%>%`
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
# Check the assay.
out <- check_and_set_assay(sample = sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
rm(out)
# Check that split.by is in metadata variables.
if (!is.null(split.by)){
assertthat::assert_that(split.by %in% colnames(sample@meta.data),
msg = paste0(add_cross(), crayon_body("The variable for "),
crayon_key("split.by"),
crayon_body(" has to be on the "),
crayon_key("metadata"),
crayon_body(" of the Seurat object.")))
}
# Check that group.by is in metadata variables.
if (!is.null(group.by)){
assertthat::assert_that(group.by %in% colnames(sample@meta.data),
msg = paste0(add_cross(), crayon_body("The variable for "),
crayon_key("group.by"),
crayon_body(" has to be on the "),
crayon_key("metadata"),
crayon_body(" of the Seurat object.")))
}
# Check that jitter is in range.
assertthat::assert_that(jitter > 0 & jitter < 0.5,
msg = paste0(add_cross(), crayon_body("The value for "),
crayon_key("jitter"),
crayon_body(" has to be between "),
crayon_key("0"),
crayon_body(" and "),
crayon_key("0.49"),
crayon_body(".")))
assertthat::assert_that(length(min.cutoff) == length(features),
msg = paste0(add_cross(), crayon_body("Please provide "),
crayon_key("as many values"),
crayon_body(" to "),
crayon_key("min.cutoff"),
crayon_body(" than provided "),
crayon_key("features"),
crayon_body(". Use"),
crayon_key("NA"),
crayon_body(" if you want to skip a given feature.")))
assertthat::assert_that(length(max.cutoff) == length(features),
msg = paste0(add_cross(), crayon_body("Please provide "),
crayon_key("as many values"),
crayon_body(" to "),
crayon_key("max.cutoff"),
crayon_body(" than provided "),
crayon_key("features"),
crayon_body(". Use"),
crayon_key("NA"),
crayon_body(" if you want to skip a given feature.")))
# Will contain the output.
list.out <- list()
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
if (is.null(colors.use)){
colors.use <- generate_color_scale(names_use = if (is.factor(sample@meta.data[, group.by])) {
levels(sample@meta.data[, group.by])
} else {
sort(unique(sample@meta.data[, group.by]))
}, colorblind = colorblind)
} else {
check_colors(colors.use)
check_consistency_colors_and_names(sample, colors = colors.use, grouping_variable = group.by)
}
# Iterate for each feature.
counter <- 0
for (feature in features){
counter <- counter + 1
max.cutoff.use <- max.cutoff[counter]
min.cutoff.use <- min.cutoff[counter]
# Check the feature.
check_feature(sample = sample,
features = feature)
# Get a vector of all dimensional reduction components.
dim_colnames <- NULL
for(red in Seurat::Reductions(object = sample)){
col.names <- colnames(sample@reductions[[red]][[]])
dim_colnames <- append(dim_colnames, col.names)
if (feature %in% col.names){
# Get the reduction in which the feature is, if this is the case.
reduction <- red
}
}
# Depending on where the feature is, generate a tibble accordingly.
if (isTRUE(feature %in% colnames(sample@meta.data))){
data <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c(group.by, feature))) %>%
tibble::rownames_to_column(var = "cell") %>%
tibble::as_tibble()
} else if (isTRUE(feature %in% rownames(sample))){
if (utils::packageVersion("Seurat") < "5.0.0"){
data <- SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = slot)[feature, , drop = FALSE]
} else {
data <- SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = slot)[feature, , drop = FALSE]
}
data <- data %>%
as.matrix() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
tibble::tibble() %>%
dplyr::left_join(y = {sample@meta.data %>%
dplyr::select(dplyr::all_of(c(group.by))) %>%
tibble::rownames_to_column(var = "cell")},
by = "cell")
} else if (isTRUE(feature %in% dim_colnames)){
data <- sample@reductions[[reduction]][[]][, feature, drop = FALSE] %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
tibble::tibble() %>%
dplyr::left_join(y = {sample@meta.data %>%
dplyr::select(dplyr::all_of(c(group.by))) %>%
tibble::rownames_to_column(var = "cell")},
by = "cell")
}
# If we also want additional split.by.
if (!(is.null(split.by))){
data <- data %>%
dplyr::left_join(y = {sample@meta.data %>%
dplyr::select(dplyr::all_of(c(split.by))) %>%
tibble::rownames_to_column(var = "cell")},
by = "cell") %>%
dplyr::mutate("split.by" = .data[[split.by]]) %>%
dplyr::select(-dplyr::all_of(c(split.by)))
}
# Proceed with the regular plot.
if (isTRUE(order)){
data <- data %>%
dplyr::mutate("group.by" = factor(.data[[group.by]], levels = {data %>%
dplyr::group_by(.data[[group.by]]) %>%
dplyr::summarise("mean" = stats::median(.data[[feature]]), na.rm = TRUE) %>%
dplyr::arrange(dplyr::desc(.data$mean)) %>%
dplyr::pull(.data[[group.by]]) %>%
as.character()}),
"values" = .data[[feature]])
} else if (base::isFALSE(order)){
data <- data %>%
dplyr::mutate("group.by" = .data[[group.by]],
"values" = .data[[feature]])
}
# Get the final column names.
cols.use <- c("values", "group.by")
if (!(is.null(split.by))){
cols.use <- append(cols.use, "split.by")
}
data <- data %>%
dplyr::select(dplyr::all_of(cols.use))
# Define cutoffs.
range.data <- c(min(data[, "values"], na.rm = TRUE),
max(data[, "values"], na.rm = TRUE))
out <- check_cutoffs(min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
feature = feature,
limits = range.data)
range.data <- out$limits
# Plot.
if (scale_type == "categorical"){
p <- ggplot2::ggplot(data = data,
mapping = ggplot2::aes(x = .data[["group.by"]],
y = .data[["values"]],
color = .data[["group.by"]]))
} else if (scale_type == "continuous"){
p <- ggplot2::ggplot(data = data,
mapping = ggplot2::aes(x = .data[["group.by"]],
y = .data[["values"]],
color = .data[["values"]]))
}
if (isTRUE(plot_cell_borders)){
p <- p +
ggplot2::geom_point(position = ggplot2::position_jitter(width = jitter,
seed = 0),
size = pt.size * border.size,
color = border.color,
na.rm = TRUE)
}
scale.setup <- compute_scales(sample = sample,
feature = feature,
assay = assay,
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff.use,
max.cutoff = max.cutoff.use,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = range.data)
limits <- c(min(data[, "values"], na.rm = TRUE),
max(data[, "values"], na.rm = TRUE))
if (limits[1] != range.data[1]){
limits <- c(range.data[1], limits[2])
}
if (limits[2] != range.data[2]){
limits <- c(limits[1], range.data[2])
}
end_value <- max(abs(limits))
if (isTRUE(scale_type == "continuous")){
p <- p +
ggplot2::scale_color_gradientn(colors = colors.gradient,
na.value = na.value,
name = legend.title,
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
} else if (isTRUE(scale_type == "categorical")){
p <- p +
ggplot2::scale_color_manual(values = colors.use,
na.value = na.value)
}
p <- p +
ggplot2::geom_point(position = ggplot2::position_jitter(width = jitter,
seed = 0),
size = pt.size,
na.rm = TRUE) +
ggdist::stat_pointinterval(interval_size_range = c(2, 3),
fatten_point = 1.5,
interval_color = "white",
point_color = "white",
position = ggplot2::position_dodge(width = 1),
na.rm = TRUE,
show.legend = FALSE) +
ggdist::stat_pointinterval(interval_size_range = c(1, 2),
interval_color = "black",
point_color = "black",
position = ggplot2::position_dodge(width = 1),
na.rm = TRUE,
show.legend = FALSE)
if (!(is.null(split.by))){
p <- p +
ggplot2::facet_grid(. ~ split.by)
}
p <- p +
ggplot2::scale_y_continuous(labels = scales::label_number(),
limits = if (isTRUE(enforce_symmetry)) {c(-end_value, end_value)} else {range.data}) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.title = ggplot2::element_text(color = "black",
face = axis.title.face),
axis.line.x = if (base::isFALSE(flip)) {ggplot2::element_line(color = "black")} else if (isTRUE(flip)) {ggplot2::element_blank()},
axis.line.y = if (isTRUE(flip)) {ggplot2::element_line(color = "black")} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(color = "black", face = axis.text.face),
axis.ticks = ggplot2::element_line(color = "black"),
panel.grid.major = ggplot2::element_blank(),
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
strip.text =ggplot2::element_text(color = "black", face = "bold"))
if (isTRUE(scale_type == "continuous")){
if (is.null(legend.title)){
legend.title <- feature
}
p <- modify_continuous_legend(p = p,
legend.title = legend.title,
legend.aes = "color",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
} else if (isTRUE(scale_type == "categorical")){
if (is.null(legend.title)){
legend.title <- ""
}
p <- p +
ggplot2::guides(color = ggplot2::guide_legend(title = legend.title,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
override.aes = list(size = legend.icon.size),
title.position = "top",
title.hjust = 0.5))
}
list.out[[feature]] <- p
}
if (isTRUE(flip)){
p <- p +
ggplot2::coord_flip()
}
return(if (length(features) > 1) {list.out} else {p})
}
================================================
FILE: R/do_TFActivityHeatmap.R
================================================
#' Plot TF Activities from decoupleR using Dorothea prior knowledge.
#'
#'
#' @inheritParams doc_function
#' @param activities \strong{\code{\link[tibble]{tibble}}} | Result of running decoupleR method with dorothea regulon prior knowledge.
#' @param n_tfs \strong{\code{\link[base]{numeric}}} | Number of top regulons to consider for downstream analysis.
#' @param tfs.use \strong{\code{\link[base]{character}}} | Restrict the analysis to given regulons.
#' @param enforce_symmetry \strong{\code{\link[base]{logical}}} | Whether the geyser and feature plot has a symmetrical color scale.
#'
#' @return A ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_TFActivityHeatmap.R
do_TFActivityHeatmap <- function(sample,
activities,
n_tfs = 25,
slot = "scale.data",
statistic = "norm_wmean",
tfs.use = NULL,
group.by = NULL,
split.by = NULL,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
na.value = "grey75",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = TRUE,
diverging.palette = "RdBu",
diverging.direction = -1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
flip = FALSE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_TFActivityHeatmap")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("enforce_symmetry" = enforce_symmetry,
"flip" = flip,
"return_object" = return_object,
"use_viridis" = use_viridis,
"values.show" = values.show)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("n_tfs" = n_tfs,
"font.size" = font.size,
"legend.width" = legend.width,
"legend.length" = legend.length,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"axis.text.x.angle" = axis.text.x.angle,
"min.cutoff" = min.cutoff,
"max.cutoff" = max.cutoff,
"number.breaks" = number.breaks,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"diverging.direction" = diverging.direction,
"values.threshold" = values.threshold,
"values.size" = values.size,
"values.round" = values.round)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"slot" = slot,
"split.by" = split.by,
"na.value" = na.value,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"font.type" = font.type,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"tfs.use" = tfs.use,
"viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"statistic" = statistic,
"grid.color" = grid.color,
"border.color" = border.color,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
`%>%` <- magrittr::`%>%`
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(na.value, parameter_name = "na.value")
check_colors(grid.color, parameter_name = "grid.color")
check_colors(border.color, parameter_name = "border.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(parameter = number.breaks, parameter_name = "number.breaks")
check_parameters(parameter = diverging.palette, parameter_name = "diverging.palette")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
check_parameters(viridis.direction, parameter_name = "viridis.direction")
check_parameters(sequential.direction, parameter_name = "sequential.direction")
check_parameters(diverging.direction, parameter_name = "diverging.direction")
# Generate the continuous color palette.
if (isTRUE(enforce_symmetry)){
colors.gradient <- compute_continuous_palette(name = diverging.palette,
use_viridis = FALSE,
direction = diverging.direction,
enforce_symmetry = enforce_symmetry)
} else {
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = enforce_symmetry)
}
sample[['dorothea']] <- activities %>%
dplyr::filter(.data$statistic == .env$statistic) %>%
tidyr::pivot_wider(id_cols = 'source',
names_from = 'condition',
values_from = 'score') %>%
tibble::column_to_rownames('source') %>%
Seurat::CreateAssayObject()
Seurat::DefaultAssay(sample) <- "dorothea"
sample@assays$dorothea@key <- "dorothea_"
# Scale the data.
sample <- Seurat::ScaleData(sample, verbose = FALSE)
if (!is.null(split.by) & !is.null(group.by)){
assertthat::assert_that(length(group.by) == 1,
msg = paste0(add_cross(), crayon_body("When using "),
crayon_key("split.by"),
crayon_body(" make sure you only provide a single value to "),
crayon_key("group.by"),
crayon_body(". Otherwise, the prot will not keep the proportions. This is a design choice. Thanks!")))
}
if (is.null(group.by)) {
sample$Groups <- Seurat::Idents(sample)
sample$group.by <- sample$Groups
group.by <- "Groups"
}
if (base::isTRUE(values.show)){
assertthat::assert_that(is.numeric(values.threshold),
msg = paste0(add_cross(), crayon_body("Please provide a value to "),
crayon_key("values.threshold"),
crayon_body(" when setting "),
crayon_key("values.show = TRUE"),
crayon_body(".")))
}
# Plotting
list.out <- list()
matrix.list <- list()
list.tfs <- list()
for (group in group.by){
# Extract activities from object as a long dataframe
suppressMessages({
sample$group.by <- sample@meta.data[, group]
if (utils::packageVersion("Seurat") < "5.0.0"){
df <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "dorothea",
slot = slot)))
} else {
df <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "dorothea",
layer = slot)))
}
df <- df %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data[, "group.by", drop = FALSE] %>%
tibble::rownames_to_column(var = "cell")},
by = "cell") %>%
dplyr::select(-"cell") %>%
tidyr::pivot_longer(cols = -"group.by",
names_to = "source",
values_to = "score") %>%
dplyr::group_by(.data$group.by, .data$source) %>%
dplyr::summarise(mean = mean(.data$score, na.rm = TRUE))
df.order <- df
if (!is.null(split.by)){
sample$split.by <- sample@meta.data[, split.by]
if (utils::packageVersion("Seurat") < "5.0.0"){
df.split <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "dorothea",
slot = slot)))
} else {
df.split <- t(as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "dorothea",
layer = slot)))
}
df.split <- df.split %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = {sample@meta.data[, c("group.by", "split.by"), drop = FALSE] %>%
tibble::rownames_to_column(var = "cell")},
by = "cell") %>%
dplyr::select(-"cell") %>%
tidyr::pivot_longer(cols = -c("group.by", "split.by"),
names_to = "source",
values_to = "score") %>%
dplyr::group_by(.data$split.by, .data$group.by, .data$source) %>%
dplyr::summarise(mean = mean(.data$score, na.rm = TRUE))
matrix.list[[group]][["df.split"]] <- df.split
}
})
# Get top tfs with more variable means across clusters
tfs <- df.order %>%
dplyr::group_by(.data$source) %>%
dplyr::summarise(std = stats::sd(.data$mean, na.rm = TRUE)) %>%
dplyr::arrange(-abs(.data$std)) %>%
dplyr::slice_head(n = n_tfs) %>%
dplyr::pull(.data$source)
matrix.list[[group]][["df"]] <- df
matrix.list[[group]][["df.order"]] <- df.order
list.tfs[[group]] <- tfs
}
shared_tfs <- NULL
if (is.null(tfs.use)){
for (group in group.by){
shared_tfs <- append(shared_tfs, list.tfs[[group]])
}
shared_tfs <- unique(shared_tfs)
} else {
shared_tfs <- unique(tfs.use[tfs.use %in% rownames(sample)])
}
counter <- 0
for (group in group.by){
counter <- counter + 1
df <- matrix.list[[group]][["df"]]
df.order <- matrix.list[[group]][["df.order"]]
# Subset long data frame to top tfs and transform to wide matrix
data <- df %>%
dplyr::filter(.data$source %in% shared_tfs)
if (!is.null(split.by)){
df.split <- matrix.list[[group]][["df.split"]]
data <- df.split %>%
dplyr::filter(.data$source %in% shared_tfs)
}
# Transform to wide to retrieve the hclust.
df.order <- df.order %>%
dplyr::filter(.data$source %in% shared_tfs) %>%
tidyr::pivot_wider(id_cols = "group.by",
names_from = 'source',
values_from = 'mean') %>%
tibble::column_to_rownames("group.by") %>%
as.matrix()
df.order[is.na(df.order)] <- 0
if(length(rownames(df.order)) == 1){
row_order <- rownames(df.order)[1]
} else {
row_order <- rownames(df.order)[stats::hclust(stats::dist(df.order, method = "euclidean"), method = "ward.D")$order]
}
if (counter == 1){
# nocov start
if (length(colnames(df.order)) == 1){
col_order <- colnames(df.order)[1]
# nocov end
} else {
col_order <- colnames(df.order)[stats::hclust(stats::dist(t(df.order), method = "euclidean"), method = "ward.D")$order]
}
}
data <- data %>%
dplyr::mutate("source" = factor(.data$source, levels = rev(col_order)),
"group.by" = factor(.data$group.by, levels = row_order))
matrix.list[[group]][["data.mean"]] <- data
if (!is.na(min.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean < min.cutoff, min.cutoff, .data$mean))
}
if (!is.na(max.cutoff)){
data <- data %>%
dplyr::mutate("mean" = ifelse(.data$mean > max.cutoff, max.cutoff, .data$mean))
}
matrix.list[[group]][["data"]] <- data
}
# Compute limits.
min.vector <- NULL
max.vector <- NULL
for (group in group.by){
data <- matrix.list[[group]][["data.mean"]]
min.vector <- append(min.vector, min(data$mean, na.rm = TRUE))
max.vector <- append(max.vector, max(data$mean, na.rm = TRUE))
}
# Get the absolute limits of the datasets.
limits <- c(min(min.vector),
max(max.vector))
# Compute overarching scales for all heatmaps.
scale.setup <- compute_scales(sample = sample,
feature = " ",
assay = "dorothea",
reduction = NULL,
slot = slot,
number.breaks = number.breaks,
min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
flavor = "Seurat",
enforce_symmetry = enforce_symmetry,
from_data = TRUE,
limits.use = limits)
# Plot individual heatmaps.
counter <- 0
list.heatmaps <- list()
for (group in group.by){
counter <- counter + 1
data <- matrix.list[[group]][["data"]]
p <- data %>%
# nocov start
ggplot2::ggplot(mapping = ggplot2::aes(x = if(base::isFALSE(flip)){.data$source} else {.data$group.by},
y = if(base::isFALSE(flip)){.data$group.by} else {.data$source},
fill = .data$mean)) +
# nocov end
ggplot2::geom_tile(color = grid.color, linewidth = 0.5)
if (base::isTRUE(values.show)){
if (base::isTRUE(enforce_symmetry)){
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(abs(.data$mean) > values.threshold, "white", "black")),
size = values.size)
} else {
p <- p +
ggplot2::geom_text(ggplot2::aes(label = round(.data$mean, values.round),
color = ifelse(.data$mean > values.threshold, "white", "black")),
size = values.size)
}
p <- p + ggplot2::scale_color_identity()
}
p <- p +
ggplot2::scale_y_discrete(expand = c(0, 0)) +
ggplot2::scale_x_discrete(expand = c(0, 0),
position = "top") +
ggplot2::guides(y.sec = guide_axis_label_trans(~paste0(levels(.data$group.by))),
x.sec = guide_axis_label_trans(~paste0(levels(.data$source)))) +
ggplot2::coord_equal() +
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = paste0(ifelse(slot == "scale.data", "Z-scored | ", ""), statistic, " score"),
breaks = scale.setup$breaks,
labels = scale.setup$labels,
limits = scale.setup$limits)
if (!is.null(split.by)){
p <- p +
ggplot2::facet_grid(.data$split.by ~ .,
drop = FALSE,
switch = "y")
}
p <- modify_continuous_legend(p = p,
legend.title = paste0(ifelse(slot == "scale.data", "Z-scored | ", ""), statistic, " score"),
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# nocov start
# Set axis titles.
if (base::isFALSE(flip)){
if (counter == 1){
if (length(group.by) > 1){
xlab <- NULL
} else {
xlab <- "Regulon"
}
ylab <- group
} else {
if (length(group.by) > 1){
if (counter == length(group.by)){
xlab <- "Regulon"
} else {
xlab <- NULL
}
} else {
xlab <- NULL
}
ylab <- group
}
} else {
if (counter == 1){
ylab <- "Regulon"
xlab <- group
} else {
ylab <- NULL
xlab <- group
}
}
# nocov end
axis.parameters <- handle_axis(flip = flip,
group.by = group.by,
group = group,
counter = counter,
axis.text.x.angle = axis.text.x.angle,
plot.title.face = plot.title.face,
plot.subtitle.face = plot.subtitle.face,
plot.caption.face = plot.caption.face,
axis.title.face = axis.title.face,
axis.text.face = axis.text.face,
legend.title.face = legend.title.face,
legend.text.face = legend.text.face)
# Set theme
p <- p +
ggplot2::xlab(xlab) +
ggplot2::ylab(ylab) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.ticks.x.bottom = axis.parameters$axis.ticks.x.bottom,
axis.ticks.x.top = axis.parameters$axis.ticks.x.top,
axis.ticks.y.left = axis.parameters$axis.ticks.y.left,
axis.ticks.y.right = axis.parameters$axis.ticks.y.right,
axis.text.y.left = axis.parameters$axis.text.y.left,
axis.text.y.right = axis.parameters$axis.text.y.right,
axis.text.x.top = axis.parameters$axis.text.x.top,
axis.text.x.bottom = axis.parameters$axis.text.x.bottom,
axis.title.x.bottom = axis.parameters$axis.title.x.bottom,
axis.title.x.top = axis.parameters$axis.title.x.top,
axis.title.y.right = axis.parameters$axis.title.y.right,
axis.title.y.left = axis.parameters$axis.title.y.left,
strip.background = axis.parameters$strip.background,
strip.clip = axis.parameters$strip.clip,
strip.text = axis.parameters$strip.text,
legend.position = if (is.null(split.by)) {legend.position} else {"bottom"},
axis.line = ggplot2::element_blank(),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid = ggplot2::element_blank(),
panel.grid.minor.y = ggplot2::element_line(color = "white", linewidth = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.justification = "center",
plot.margin = ggplot2::margin(t = 0, r = 10, b = 0, l = 10),
panel.border = ggplot2::element_rect(fill = NA, color = border.color, linewidth = 1),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.spacing.x = ggplot2::unit(0, "cm"))
list.heatmaps[[group]] <- p
}
# Plot the combined plot
input <- if(base::isFALSE(flip)){list.heatmaps[rev(group.by)]}else{list.heatmaps[group.by]}
p <- patchwork::wrap_plots(input,
ncol = if (base::isFALSE(flip)){1} else {NULL},
nrow = if(isTRUE(flip)) {1} else {NULL},
guides = "collect")
p <- p +
patchwork::plot_annotation(theme = ggplot2::theme(legend.position = legend.position,
plot.title = ggplot2::element_text(family = font.type,
color = "black",
face = plot.title.face,
hjust = 0),
plot.subtitle = ggplot2::element_text(family = font.type,
face = plot.subtitle.face,
color = "black",
hjust = 0),
plot.caption = ggplot2::element_text(family = font.type,
face = plot.caption.face,
color = "black",
hjust = 1),
plot.caption.position = "plot"))
list.out[["Heatmap"]] <- p
if (isTRUE(return_object)){
list.out[["Object"]] <- sample
return_me <- list.out
} else{
return_me <- list.out[["Heatmap"]]
}
return(return_me)
}
================================================
FILE: R/do_TermEnrichmentPlot.R
================================================
#' Display the enriched terms for a given list of genes.
#'
#' @inheritParams doc_function
#' @param mat \strong{\code{\link[base]{list}}} | Result of over-representation test with clusterProfiler. Accepts only one result, be aware of that if you compute the test for all GO ontologies. Accessed through \strong{\code{mat@result}}.
#' @param n.chars \strong{\code{\link[base]{numeric}}} | Number of characters to use as a limit to wrap the term names. The higher this value, the longer the lines would be for each term in the plots. Defaults to 40.
#' @param n.terms \strong{\code{\link[base]{numeric}}} | Number of terms to display. Defaults to 25.
#' @return A dotplot object with enriched terms.
#' @export
#'
#' @example man/examples/examples_do_TermEnrichmentPlot.R
do_TermEnrichmentPlot <- function(mat,
n.chars = 40,
n.terms = 25,
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
dot.scale = 8,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
number.breaks = 5,
xlab = NULL,
ylab = NULL,
na.value = "grey75",
grid.color = "grey90",
grid.type = "dashed",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
axis.text.x.angle = 45,
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_TermEnrichmentPlot")
# Define pipe operator internally.
`%>%` <- magrittr::`%>%`
# Check logical parameters
logical_list <- list("use_viridis" = use_viridis)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("n.chars" = n.chars,
"n.terms" = n.terms,
"font.size" = font.size,
"legend.framewidth" = legend.framewidth,
"legend.tickwidth" = legend.tickwidth,
"legend.length" = legend.length,
"legend.width" = legend.width,
"viridis.direction" = viridis.direction,
"sequential.direction" = sequential.direction,
"number.breaks" = number.breaks,
"axis.text.x.angle" = axis.text.x.angle)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("viridis.palette" = viridis.palette,
"sequential.palette" = sequential.palette,
"legend.position" = legend.position,
"legend.framecolor" = legend.framecolor,
"legend.tickcolor" = legend.tickcolor,
"legend.type" = legend.type,
"font.type" = font.type,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"xlab" = xlab,
"ylab" = ylab,
"na.value" = na.value)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.type, parameter_name = "legend.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = plot.title.face, parameter_name = "plot.title.face")
check_parameters(parameter = plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(parameter = plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(parameter = axis.title.face, parameter_name = "axis.title.face")
check_parameters(parameter = axis.text.face, parameter_name = "axis.text.face")
check_parameters(parameter = legend.title.face, parameter_name = "legend.title.face")
check_parameters(parameter = legend.text.face, parameter_name = "legend.text.face")
check_parameters(parameter = viridis.palette, parameter_name = "viridis.palette")
check_parameters(parameter = sequential.palette, parameter_name = "sequential.palette")
check_parameters(parameter = viridis.direction, parameter_name = "viridis.direction")
check_parameters(parameter = sequential.direction, parameter_name = "sequential.direction")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
# Check the colors provided to legend.framecolor and legend.tickcolor.
check_colors(legend.framecolor, parameter_name = "legend.framecolor")
check_colors(legend.tickcolor, parameter_name = "legend.tickcolor")
check_colors(na.value, parameter_name = "na.value")
check_colors(grid.color, parameter_name = "grid.color")
# Check correct colnames.
for (col_name in c("Description", "GeneRatio", "p.adjust", "Count")){
assertthat::assert_that(col_name %in% colnames(mat),
msg = paste0(add_cross(),
crayon_body("Missing column "),
crayon_key(col_name),
crayon_body(" in "),
crayon_key("mat"),
crayon_body(".")))
}
# Generate color gradient.
colors.gradient <- compute_continuous_palette(name = ifelse(isTRUE(use_viridis), viridis.palette, sequential.palette),
use_viridis = use_viridis,
direction = ifelse(isTRUE(use_viridis), viridis.direction, sequential.direction),
enforce_symmetry = FALSE)
# PLOT
# Start processing the matrix.
data_processed <- mat %>%
dplyr::select(dplyr::all_of(c("Description", "GeneRatio", "p.adjust", "Count"))) %>%
# Turn character column GeneRatio into actual numeric GeneRatio.
# -log10 transform p.adjust column.
dplyr::mutate("GeneRatio" = unname(vapply(X = sapply(X = .data$GeneRatio,
FUN = function(x){stringr::str_split(x, "/")}),
FUN = function(x){as.numeric(x[1]) / as.numeric(x[2])},
FUN.VALUE = numeric(1))),
"p.adjust" = -log10(.data$p.adjust)) %>%
tibble::rownames_to_column(var = "Term") %>%
# Retrieve most significant ones.
dplyr::arrange(dplyr::desc(.data$Count), dplyr::desc(.data$p.adjust)) %>%
# Turn Description column into a factor to get the values ordered.
dplyr::mutate("Description" = factor(.data$Description, levels = rev(.data$Description))) %>%
tibble::as_tibble() %>%
dplyr::slice_head(n = n.terms)
p <- data_processed %>%
# Start plotting.
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$GeneRatio,
y = .data$Description,
fill = .data$p.adjust,
size = .data$Count)) +
# Geom point.
ggplot2::geom_point(shape = 21,
color = "black") +
# Color scale.
ggplot2::scale_fill_gradientn(colors = colors.gradient,
na.value = na.value,
name = expression(bold(paste("-", log["10"], "(p.adj)"))),
breaks = scales::extended_breaks(n = number.breaks)) +
# Add wrapping around Y labels.
ggplot2::scale_y_discrete(labels = stringr::str_wrap(as.character(rev(data_processed$Description)),
width = n.chars)) +
# Add a size scale.
ggplot2::scale_size_continuous(range = c(3, dot.scale)) +
# Add labs.
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption,
x = ifelse(is.null(xlab), "Gene Ratio", xlab),
y = ifelse(is.null(ylab), "", ylab)) +
# Modify the legend aesthetics of size.
ggplot2::guides(size = ggplot2::guide_legend(title = "Count",
title.position = "top",
title.hjust = 0.5,
ncol = 2,
override.aes = ggplot2::aes(fill = "black"))) +
# Add a base theme.
ggplot2::theme_minimal(base_size = font.size) +
# Add theme customization.
ggplot2::theme(axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = TRUE)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = TRUE)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = TRUE)[["vjust"]]),
axis.text.y = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line.y = ggplot2::element_line(color = "black"),
axis.line.x = ggplot2::element_blank(),
axis.title = ggplot2::element_text(face = axis.title.face),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
plot.title.position = "plot",
panel.grid.major.y = ggplot2::element_line(color = grid.color, linetype = grid.type),
panel.grid.major.x = ggplot2::element_blank(),
panel.grid = ggplot2::element_blank(),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
panel.grid.major = ggplot2::element_blank(),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
# Modify fill legend to look nice.
p <- modify_continuous_legend(p = p,
# nocov start
legend.title = expression(bold(paste("-", log["10"], "(p.adj)"))),
# nocov end
legend.aes = "fill",
legend.type = legend.type,
legend.position = legend.position,
legend.length = legend.length,
legend.width = legend.width,
legend.framecolor = legend.framecolor,
legend.tickcolor = legend.tickcolor,
legend.framewidth = legend.framewidth,
legend.tickwidth = legend.tickwidth)
# Return the plot.
return(p)
}
================================================
FILE: R/do_ViolinPlot.R
================================================
#' Generate Violin plots from a Seurat object.
#'
#' This function generates violin plots using ggplot2, with publication-ready
#' theming, optional box plot overlay, and extended customization options.
#'
#' @inheritParams doc_function
#' @param plot_boxplot \strong{\code{\link[base]{logical}}} | Whether to plot a Box plot inside the violin or not.
#' @param pt.size \strong{\code{\link[base]{numeric}}} | Size of points in the Violin plot.
#' @param y_cut \strong{\code{\link[base]{numeric}}} | Vector with the values in which the Violins should be cut. Only works for one feature.
#' @param line_width \strong{\code{\link[base]{numeric}}} | Width of the lines drawn in the plot. Defaults to 1.
#' @param boxplot_width \strong{\code{\link[base]{numeric}}} | Width of the boxplots. Defaults to 0.2.
#' @param share.y.lims \strong{\code{\link[base]{logical}}} | When querying multiple features, force the Y axis of all of them to be on the same range of values (this being the max and min of all features combined).
#' @return A ggplot2 object containing a Violin Plot.
#' @export
#'
#' @example man/examples/examples_do_ViolinPlot.R
do_ViolinPlot <- function(sample,
features,
assay = NULL,
slot = NULL,
group.by = NULL,
split.by = NULL,
colors.use = NULL,
colorblind = FALSE,
pt.size = 0,
line_width = 0.5,
y_cut = rep(NA, length(features)),
plot_boxplot = TRUE,
boxplot_width = 0.2,
legend.position = "bottom",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = rep(NA, length(features)),
ylab = rep(NA, length(features)),
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
order = TRUE,
flip = FALSE,
ncol = NULL,
share.y.lims = FALSE,
legend.title = NULL,
legend.title.position = "top",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_ViolinPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check the assay.
out <- check_and_set_assay(sample = sample, assay = assay)
sample <- out[["sample"]]
assay <- out[["assay"]]
# Check slot.
slot <- if(is.null(slot)){"data"} else {slot}
# Check logical parameters.
logical_list <- list("plot_boxplot" = plot_boxplot,
"plot.grid" = plot.grid,
"flip" = flip,
"share.y.lims" = share.y.lims,
"legend.byrow" = legend.byrow,
"order" = order,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pt.size" = pt.size,
"y_cut" = y_cut,
"font.size" = font.size,
"line_width" = line_width,
"boxplot_width" = boxplot_width,
"axis.text.x.angle" = axis.text.x.angle,
"ncol" = ncol,
"legend.ncol" = legend.ncol,
"legend.nrow" = legend.nrow)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("legend.position" = legend.position,
"features" = features,
"group.by" = group.by,
"colors.use" = colors.use,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"xlab" = xlab,
"ylab" = ylab,
"font.type" = font.type,
"grid.color" = grid.color,
"grid.type" = grid.color,
"split.by" = split.by,
"legend.title" = legend.title,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"legend.title.position" = legend.title.position)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
`%>%` <- magrittr::`%>%`
# Check X and Y labels.
if (sum(is.na(xlab)) == length(features)){
xlab <- rep("Groups", length(features))
} else {
assertthat::assert_that(length(xlab) == length(features),
msg = paste0(add_cross(), crayon_body("Please provide "),
crayon_key("as many values"),
crayon_body(" to "),
crayon_key("xlab"),
crayon_body(" than provided "),
crayon_key("features"),
crayon_body(". Use"),
crayon_key("NA"),
crayon_body(" if you want to skip a given feature.")))
}
if (sum(is.na(ylab)) == length(features)){
ylab <- features
} else {
assertthat::assert_that(length(ylab) == length(features),
msg = paste0(add_cross(), crayon_body("Please provide "),
crayon_key("as many values"),
crayon_body(" to "),
crayon_key("ylab"),
crayon_body(" than provided "),
crayon_key("features"),
crayon_body(". Use"),
crayon_key("NA"),
crayon_body(" if you want to skip a given feature.")))
}
if (sum(is.na(y_cut)) != length(features)){
assertthat::assert_that(length(y_cut) == length(features),
msg = paste0(add_cross(), crayon_body("Please provide "),
crayon_key("as many values"),
crayon_body(" to "),
crayon_key("y_cut"),
crayon_body(" than provided "),
crayon_key("features"),
crayon_body(". Use"),
crayon_key("NA"),
crayon_body(" if you want to skip a given feature.")))
}
# Check the feature.
features <- check_feature(sample = sample, features = features, permissive = TRUE)
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
# Assign legend title.
if (is.null(legend.title)){
legend.title <- group.by
}
if (is.null(colors.use)){
if (is.null(split.by)){
if (is.factor(sample@meta.data[, group.by])){
names.use <- levels(sample@meta.data[, group.by])
} else {
names.use <- sort(unique(sample@meta.data[, group.by]))
}
} else {
if (is.factor(sample@meta.data[, split.by])){
names.use <- levels(sample@meta.data[, split.by])
} else {
names.use <- sort(unique(sample@meta.data[, split.by]))
}
}
colors.use <- generate_color_scale(names.use, colorblind = colorblind)
} else {
if (is.null(split.by)){
colors.use <- check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = group.by)
} else {
colors.use <- check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = split.by)
}
}
check_colors(grid.color, parameter_name = "grid.color")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(parameter = grid.type, parameter_name = "grid.type")
check_parameters(parameter = axis.text.x.angle, parameter_name = "axis.text.x.angle")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
list.plots <- list()
counter <- 0
# Get the feature limits.
max_values <- NULL
min_values <- NULL
for(feature in features){
max_values <- append(max_values, max(get_data_column(sample = sample, feature = feature, assay = assay, slot = slot)[, "feature"], na.rm = TRUE))
min_values <- append(min_values, min(get_data_column(sample = sample, feature = feature, assay = assay, slot = slot)[, "feature"], na.rm = TRUE))
}
limits <- c(min(min_values), max(max_values))
for (feature in features){
counter <- counter + 1
data <- get_data_column_in_context(sample = sample,
feature = feature,
assay = assay,
slot = slot,
group.by = group.by,
split.by = split.by)
# Sort the groups.
if (isTRUE(order) & is.null(split.by)){
data <- data %>%
dplyr::mutate("group.by" = factor(as.character(.data[["group.by"]]),
levels = {data %>%
tibble::as_tibble() %>%
dplyr::group_by(.data[["group.by"]]) %>%
dplyr::summarise("median" = stats::median(.data[["feature"]], na.rm = TRUE)) %>%
dplyr::arrange(if(base::isFALSE(flip)){dplyr::desc(.data[["median"]])} else {.data[["median"]]}) %>%
dplyr::pull(.data[["group.by"]]) %>%
as.character()}))
}
if (isTRUE(order)){
assertthat::assert_that(is.null(split.by),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("split.by"),
crayon_body(" cannot be used alonside "),
crayon_key("order"),
crayon_body(". Please set "),
crayon_key("order = FALSE"),
crayon_body(".")))
}
if (!is.null(split.by)){
assertthat::assert_that(base::isFALSE(order),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("split.by"),
crayon_body(" cannot be used alonside "),
crayon_key("order"),
crayon_body(". Please set "),
crayon_key("order = FALSE"),
crayon_body(".")))
}
if (!is.null(split.by)){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$group.by,
y = .data$feature,
fill = .data$split.by))
} else {
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$group.by,
y = .data$feature,
fill = .data$group.by))
}
p <- p +
ggplot2::geom_violin(color = "black",
linewidth = line_width,
na.rm = TRUE) +
ggplot2::scale_fill_manual(values = colors.use)
if (isTRUE(plot_boxplot)){
assertthat::assert_that(is.null(split.by),
msg = paste0(add_cross(), crayon_key("Boxplots"),
crayon_body(" are not implemented when "),
crayon_key("split.by"),
crayon_body(" is set. Set "),
crayon_key("plot_boxplot = FALSE"),
crayon_body(".")))
p <- p +
ggplot2::geom_boxplot(fill = "white",
color = "black",
linewidth = line_width,
width = boxplot_width,
outlier.shape = NA,
fatten = 1,
na.rm = TRUE)
}
if (is.na(xlab[counter])){
xlab.use <- "Groups"
} else {
xlab.use <- xlab[counter]
}
if (is.na(ylab[counter])){
ylab.use <- feature
} else {
ylab.use <- ylab[counter]
}
p <- p +
ggplot2::xlab(xlab.use) +
ggplot2::ylab(ylab.use) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::guides(fill = ggplot2::guide_legend(title = legend.title,
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow,
title.position = legend.title.position)) +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(axis.text.x = ggplot2::element_text(color = "black",
face = axis.text.face,
angle = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = flip)[["vjust"]]),
axis.text.y = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.title.y = ggplot2::element_text(face = axis.title.face),
axis.title.x = ggplot2::element_text(face = axis.title.face),
axis.line.x = if (base::isFALSE(flip)) {ggplot2::element_line(color = "black")} else if (isTRUE(flip)) {ggplot2::element_blank()},
axis.line.y = if (isTRUE(flip)) {ggplot2::element_line(color = "black")} else if (base::isFALSE(flip)) {ggplot2::element_blank()},
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
plot.title.position = "plot",
panel.grid.minor = ggplot2::element_blank(),
panel.grid.major.x = if(base::isFALSE(flip)){ggplot2::element_blank()} else {if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)} else {ggplot2::element_blank()}},
panel.grid.major.y = if(base::isFALSE(flip)){if (isTRUE(plot.grid)){ggplot2::element_line(color = grid.color, linetype = grid.type)} else {ggplot2::element_blank()}} else {ggplot2::element_blank()},
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.position = legend.position,
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
axis.ticks = ggplot2::element_line(color = "black"),
axis.line = ggplot2::element_line(color = "black"),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
if (isTRUE(share.y.lims)){
p <- p +
ggplot2::ylim(limits)
}
if (!is.na(y_cut[counter])){
p <- p +
ggplot2::geom_hline(yintercept = y_cut[counter],
linetype = "longdash",
colour = "black",
linewidth = 1,
na.rm = TRUE)
}
if (isTRUE(flip)){
p <- p +
ggplot2::coord_flip()
}
list.plots[[feature]] <- p
}
if (length(features) > 1){
p <- patchwork::wrap_plots(list.plots, ncol = ncol)
}
return(p)
}
================================================
FILE: R/do_VolcanoPlot.R
================================================
#' Compute a Volcano plot out of DE genes.
#'
#' @inheritParams doc_function
#' @param de_genes \strong{\code{\link[tibble]{tibble}}} | Output of `Seurat::FindMarkers()`.
#' @param pval_cutoff \strong{\code{\link[base]{numeric}}} | Cutoff for the p-value.
#' @param FC_cutoff \strong{\code{\link[base]{numeric}}} | Cutoff for the avg_log2FC.
#' @param plot_lines \strong{\code{\link[base]{logical}}} | Whether to plot the division lines.
#' @param line_color \strong{\code{\link[base]{character}}} | Color for the lines.
#' @param line_size \strong{\code{\link[base]{numeric}}} | Size of the lines in the plot.
#' @param add_gene_tags \strong{\code{\link[base]{logical}}} | Whether to plot the top genes.
#' @param add_tag_side \strong{\code{\link[base]{logical}}} | Either "both", "positive" or "negative" to indicate which side of genes to tag
#' @param order_tags_by \strong{\code{\link[base]{character}}} | Either "both", "pvalue" or "logfc".
#' @param tag_size \strong{\code{\link[base]{numeric}}} | Size of the text/label for the tags.
#' @param n_genes \strong{\code{\link[base]{numeric}}} | Number of top genes to plot.
#' @param use_labels \strong{\code{\link[base]{logical}}} | Whether to use labels instead of text for the tags.
#' @param colors.use \strong{\code{\link[base]{character}}} | Color to generate a tetradic color scale with. If NULL, default colors are used.
#'
#' @return A volcano plot as a ggplot2 object.
#' @export
#'
#' @example /man/examples/examples_do_VolcanoPlot.R
do_VolcanoPlot <- function(sample,
de_genes,
pval_cutoff = 0.05,
FC_cutoff = 2,
pt.size = 1,
border.size = 1.5,
border.color = "black",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
plot_lines = TRUE,
line_color = "grey75",
line_size = 0.5,
add_gene_tags = TRUE,
add_tag_side = "both",
order_tags_by = "both",
tag_size = 6,
n_genes = 5,
use_labels = FALSE,
colors.use = NULL,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_VolcanoPlot")
# Check if the sample provided is a Seurat object.
check_Seurat(sample = sample)
# Check logical parameters.
logical_list <- list("add_gene_tags" = add_gene_tags,
"plot_lines" = plot_lines,
"use_labels" = use_labels)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("pval_cutoff" = pval_cutoff,
"FC_cutoff" = FC_cutoff,
"pt.size" = pt.size,
"border.size" = border.size,
"font.size" = font.size,
"line_size" = line_size,
"n_genes" = n_genes,
"tag_size" = tag_size)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("border.color" = border.color,
"font.type" = font.type,
"line_color" = line_color,
"plot.title" = plot.title,
"plot.subtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"add_tag_side" = add_tag_side,
"order_tags_by" = order_tags_by,
"colors.use" = colors.use,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
check_colors(border.color, parameter_name = "border.color")
check_colors(line_color, parameter_name = "line_color")
check_colors(colors.use, parameter_name = "colors.use")
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
assertthat::assert_that(order_tags_by %in% c("both", "pvalue", "logfc"),
msg = "Please use either both, pvalue or logfc in order_tags_by.")
assertthat::assert_that(add_tag_side %in% c("both", "positive", "negative"),
msg = "Please use either both, positive or negative in add_tag_side")
`%>%` <- magrittr::`%>%`
if (!is.null(colors.use)){
colors <- do_ColorPalette(colors.use, tetradic = TRUE)
names(colors) <- c("A", "C", "B", "D")
} else {
colors <- c("A" = "#385f71",
"B" = "#d7b377",
"C" = "#f5f0f6",
"D" = "grey75")
}
if (!("gene" %in% colnames(de_genes))){
data <- de_genes %>%
tibble::rownames_to_column(var = "gene")
} else {
data <- de_genes
}
data <- data %>%
tibble::as_tibble() %>%
dplyr::select(c("p_val_adj", "avg_log2FC", "gene")) %>%
dplyr::mutate("p_val_adj" = replace(.data$p_val_adj, .data$p_val_adj == 0, .Machine$double.xmin)) %>%
dplyr::mutate(log_p = -log10(.data$p_val_adj)) %>%
dplyr::select(-"p_val_adj")
pval_cutoff <- -log10(pval_cutoff)
data$color <- NA
data$color[abs(data$avg_log2FC) >= FC_cutoff & data$log_p >= pval_cutoff] <- "A"
data$color[abs(data$avg_log2FC) < FC_cutoff & data$log_p >= pval_cutoff] <- "B"
data$color[abs(data$avg_log2FC) < FC_cutoff & data$log_p < pval_cutoff] <- "C"
data$color[abs(data$avg_log2FC) >= FC_cutoff & data$log_p < pval_cutoff] <- "D"
max_value <- max(abs(c(min(data$avg_log2FC), max(data$avg_log2FC))))
x_lims <- c(-max_value, max_value)
# Shuffle the data.
data <- data[sample(rownames(data), nrow(data)), ]
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(x = .data$avg_log2FC,
y = .data$log_p)) +
ggplot2::geom_point(size = pt.size * border.size,
color = border.color) +
ggplot2::geom_point(mapping = ggplot2::aes(color = .data$color),
size = pt.size) +
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = plot.caption) +
ggplot2::scale_color_manual(values = colors) +
ggplot2::guides(color = ggplot2::guide_legend(override.aes = list(size = 4),
title.position = "top",
title.hjust = 0.5)) +
ggplot2::xlim(x_lims) +
ggplot2::xlab(expression(bold(paste("Avg. ", log["2"], "(FC)")))) +
ggplot2::ylab(expression(bold(paste("-", log["10"], "(p.adj.)"))))
if (isTRUE(plot_lines)){
p <- p +
ggplot2::geom_hline(yintercept = pval_cutoff,
color = line_color,
linewidth = line_size,
linetype = "dashed") +
ggplot2::geom_vline(xintercept = FC_cutoff,
color = line_color,
linewidth = line_size,
linetype = "dashed") +
ggplot2::geom_vline(xintercept = -FC_cutoff,
color = line_color,
linewidth = line_size,
linetype = "dashed")
}
if (isTRUE(add_gene_tags)){
if (order_tags_by == "both"){
data.label <- data %>%
dplyr::mutate("abs_avg_log2FC" = abs(.data$avg_log2FC)) %>%
dplyr::arrange(dplyr::desc(.data$log_p),
dplyr::desc(.data$abs_avg_log2FC)) %>%
as.data.frame()
data.up <- data.label %>%
dplyr::filter(.data$avg_log2FC > 0) %>%
utils::head(n_genes)
data.down <- data.label %>%
dplyr::filter(.data$avg_log2FC < 0) %>%
utils::head(n_genes)
data.label <- dplyr::bind_rows(data.up, data.down)
} else if (order_tags_by == "pvalue"){
data.up <- data %>%
dplyr::filter(.data$avg_log2FC > 0) %>%
dplyr::arrange(dplyr::desc(.data$log_p),
dplyr::desc(.data$avg_log2FC)) %>%
as.data.frame() %>%
utils::head(n_genes)
data.down <- data %>%
dplyr::filter(.data$avg_log2FC < 0) %>%
dplyr::arrange(dplyr::desc(.data$log_p)) %>%
as.data.frame() %>%
utils::head(n_genes)
data.label <- dplyr::bind_rows(data.up, data.down)
} else if (order_tags_by == "logfc"){
data.up <- data %>%
dplyr::arrange(dplyr::desc(.data$avg_log2FC)) %>%
as.data.frame() %>%
utils::head(n_genes)
data.down <- data %>%
dplyr::arrange(.data$avg_log2FC) %>%
as.data.frame() %>%
utils::head(n_genes)
data.label <- dplyr::bind_rows(data.up, data.down)
}
if (add_tag_side == "positive") {
data.label <- data.up
} else if (add_tag_side == "negative") {
data.label <- data.down
}
if (base::isFALSE(use_labels)){
p <- p +
ggrepel::geom_text_repel(data = data.label,
mapping = ggplot2::aes(label = .data$gene),
max.overlaps = 1000,
color = "black",
fontface = "bold",
size = tag_size)
} else if (isTRUE(use_labels)){
p <- p +
ggrepel::geom_label_repel(data = data.label,
mapping = ggplot2::aes(label = .data$gene),
max.overlaps = 1000,
color = "black",
fontface = "bold",
size = tag_size)
}
}
p <- p +
ggplot2::theme_minimal(base_size = font.size) +
ggplot2::theme(plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
legend.text = ggplot2::element_text(face = legend.text.face),
legend.title = ggplot2::element_text(face = legend.title.face),
panel.grid = ggplot2::element_blank(),
plot.title.position = "plot",
plot.caption.position = "plot",
text = ggplot2::element_text(family = font.type),
legend.position = "none",
legend.justification = "center",
axis.title.x = ggplot2::element_text(face = axis.title.face, color = "black"),
axis.title.y = ggplot2::element_text(face = axis.title.face, angle = 90, color = "black"),
axis.text = ggplot2::element_text(face = axis.text.face, color = "black"),
axis.line = ggplot2::element_line(color = "black"),
axis.ticks = ggplot2::element_line(color = "black"),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"))
return(p)
}
================================================
FILE: R/do_WafflePlot.R
================================================
#' Generate Waffle plots to display cell group proportions.
#'
#' This function displays the proportional composition of cell groups as a
#' waffle chart, where each tile represents a fixed number of cells.
#'
#' @inheritParams doc_function
#' @param waffle.size \strong{\code{\link[base]{numeric}}} | Tile border size.
#'
#' @return A ggplot2 object with a Waffle Plot.
#' @export
#'
#' @example man/examples/examples_do_WafflePlot.R
do_WafflePlot <- function(sample,
group.by,
waffle.size = 2,
flip = FALSE,
colors.use = NULL,
colorblind = FALSE,
na.value = "grey75",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.title = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
legend.position = "bottom",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
strip.text.face = "bold"){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
check_suggests(function_name = "do_WafflePlot")
check_Seurat(sample)
# Define pipe operator internally.
`%>%` <- magrittr::`%>%`
# Check logical parameters
logical_list <- list("flip" = flip,
"legend.byrow" = legend.byrow,
"colorblind" = colorblind)
check_type(parameters = logical_list, required_type = "logical", test_function = is.logical)
# Check numeric parameters.
numeric_list <- list("waffle.size" = waffle.size,
"font.size" = font.size)
check_type(parameters = numeric_list, required_type = "numeric", test_function = is.numeric)
# Check character parameters.
character_list <- list("group.by" = group.by,
"na.value" = na.value,
"font.type" = font.type,
"plot.title" = plot.title,
"plot.suybtitle" = plot.subtitle,
"plot.caption" = plot.caption,
"legend.title" = legend.title,
"plot.title.face" = plot.title.face,
"plot.subtitle.face" = plot.subtitle.face,
"plot.caption.face" = plot.caption.face,
"axis.title.face" = axis.title.face,
"axis.text.face" = axis.text.face,
"legend.title.face" = legend.title.face,
"legend.text.face" = legend.text.face,
"legend.position" = legend.position)
check_type(parameters = character_list, required_type = "character", test_function = is.character)
# Check group.by.
out <- check_group_by(sample = sample,
group.by = group.by,
is.heatmap = FALSE)
sample <- out[["sample"]]
group.by <- out[["group.by"]]
check_parameters(parameter = font.type, parameter_name = "font.type")
check_parameters(parameter = legend.position, parameter_name = "legend.position")
check_parameters(plot.title.face, parameter_name = "plot.title.face")
check_parameters(plot.subtitle.face, parameter_name = "plot.subtitle.face")
check_parameters(plot.caption.face, parameter_name = "plot.caption.face")
check_parameters(axis.title.face, parameter_name = "axis.title.face")
check_parameters(axis.text.face, parameter_name = "axis.text.face")
check_parameters(legend.title.face, parameter_name = "legend.title.face")
check_parameters(legend.text.face, parameter_name = "legend.text.face")
# Check the colors provided.
check_colors(na.value, parameter_name = "na.value")
if (is.null(colors.use)){
if (is.factor(sample@meta.data[, group.by])){
names.use <- levels(sample@meta.data[, group.by])
} else {
names.use <- sort(unique(sample@meta.data[, group.by]))
}
colors.use <- generate_color_scale(names_use = names.use, colorblind = colorblind)
} else {
check_colors(colors.use, parameter_name = "colors.use")
check_consistency_colors_and_names(sample = sample, colors = colors.use, grouping_variable = group.by)
if (is.factor(sample@meta.data[, group.by])){
colors.use <- colors.use[levels(sample@meta.data[, group.by])]
} else {
colors.use <- colors.use[sort(unique(sample@meta.data[, group.by]))]
}
}
# Get data
data <- sample@meta.data %>%
tibble::rownames_to_column(var = "cell") %>%
tibble::as_tibble() %>%
dplyr::select(dplyr::all_of(c("cell", group.by))) %>%
dplyr::group_by(.data[[group.by]]) %>%
dplyr::summarise("n" = dplyr::n()) %>%
dplyr::mutate("freq" = (.data$n / sum(.data$n)) * 100,
"Groups" = .data[[group.by]])
# Add rounded percentages.
data$Totals <- round_percent(x = data,
group.by = group.by)
# Build waffle grid manually to avoid depending on the 'waffle' package.
# Expand each group into tiles summing to 100 (10x10 grid).
tile_df <- data %>%
dplyr::mutate(tiles = .data$Totals) %>%
dplyr::select(.data$Groups, .data$tiles) %>%
tidyr::uncount(weights = .data$tiles, .remove = FALSE) %>%
dplyr::group_by(.data$Groups) %>%
dplyr::mutate(idx = dplyr::row_number()) %>%
dplyr::ungroup() %>%
dplyr::mutate(global_idx = dplyr::row_number())
# Calculate x/y positions for a 10x10 grid.
tile_df <- tile_df %>%
dplyr::mutate(x = (global_idx - 1) %% 10 + 1,
y = 10 - ((global_idx - 1) %/% 10))
# If flip requested, swap axes.
if (isTRUE(flip)){
tile_df <- tile_df %>% dplyr::mutate(tmp = x, x = y, y = tmp) %>% dplyr::select(-tmp)
}
p <- tile_df %>%
ggplot2::ggplot(ggplot2::aes(x = .data$x, y = .data$y, fill = .data$Groups)) +
ggplot2::geom_tile(color = "white", linewidth = waffle.size) +
ggplot2::geom_tile(color = "black", linewidth = 0.35, alpha = 0.25, fill = NA) +
ggplot2::coord_fixed() +
ggplot2::scale_fill_manual(values = colors.use, na.value = na.value) +
# Add plot labels.
ggplot2::labs(title = plot.title,
subtitle = plot.subtitle,
caption = ifelse(is.null(plot.caption), paste0("Grid: 100 tiles | Each: 1% | Cells: ", sum(data$n)), plot.caption)) +
# Customise legend.
ggplot2::guides(fill = ggplot2::guide_legend(title = ifelse(is.null(legend.title), group.by, legend.title),
title.position = "top",
title.hjust = 0.5,
ncol = legend.ncol,
nrow = legend.nrow,
byrow = legend.byrow)) +
# Add theme.
ggplot2::theme_minimal(base_size = font.size) +
# Customise theme.
ggplot2::theme(axis.title = ggplot2::element_blank(),
panel.grid = ggplot2::element_blank(),
axis.line = ggplot2::element_blank(),
axis.text = ggplot2::element_blank(),
axis.ticks = ggplot2::element_blank(),
plot.title.position = "plot",
plot.title = ggplot2::element_text(face = plot.title.face, hjust = 0),
plot.subtitle = ggplot2::element_text(face = plot.subtitle.face, hjust = 0),
plot.caption = ggplot2::element_text(face = plot.caption.face, hjust = 1),
text = ggplot2::element_text(family = font.type),
plot.caption.position = "plot",
legend.text = ggplot2::element_text(face = legend.text.face),
legend.position = legend.position,
legend.title = ggplot2::element_text(face = legend.title.face),
legend.justification = "center",
plot.margin = ggplot2::margin(t = 10, r = 10, b = 10, l = 10),
plot.background = ggplot2::element_rect(fill = "white", color = "white"),
panel.background = ggplot2::element_rect(fill = "white", color = "white"),
legend.background = ggplot2::element_rect(fill = "white", color = "white"),
strip.text = ggplot2::element_text(color = "black", face = strip.text.face),
strip.background = ggplot2::element_blank())
# Return the plot.
return(p)
}
================================================
FILE: R/globals.R
================================================
# Declare .data as global variable to avoid R CMD checks.
utils::globalVariables(c(".data",
".env",
".",
"x",
"quantile",
"ecdf",
"summarise",
"stratum",
"global_idx",
"tmp",
"y"))
================================================
FILE: R/plot_density_patch.R
================================================
#' Compatibility wrapper for Nebulosa with SeuratObject 5.0.0+
#'
#' Nebulosa is not compatible with SeuratObject >= 5.0.0 due to deprecated parameters.
#' This wrapper gracefully falls back to do_FeaturePlot() when needed.
#'
#' @keywords internal
#' @noRd
.nebulosa_compat_wrapper <- function(object, features, reduction, dims, joint, slot = "data",
verbose = TRUE, ...) {
# Check if we need the SeuratObject 5.0.0+ workaround
if (utils::packageVersion("SeuratObject") >= "5.0.0") {
# Check for global option to suppress message (useful for testing)
quiet_mode <- isTRUE(getOption("SCpubr.nebulosa.quiet", default = FALSE))
if (isTRUE(verbose) && !quiet_mode) {
message(paste0(add_info(), crayon_body("Nebulosa is not yet compatible with "),
crayon_key("SeuratObject >= 5.0.0"),
crayon_body(". Falling back to "),
crayon_key("do_FeaturePlot()"),
crayon_body(" instead.")))
}
# Return NULL to signal fallback is needed
return(NULL)
} else {
# SeuratObject < 5.0.0, suppress warnings for aes_string()
return(suppressWarnings({
Nebulosa::plot_density(object = object,
features = features,
joint = joint,
reduction = reduction,
dims = dims)
}))
}
}
================================================
FILE: R/utils.R
================================================
#' Mock function used to document all main function.
#'
#' @param sample \strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.
#' @param font.size \strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.
#' @param font.type \strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
#' \itemize{
#' \item \emph{\code{mono}}: Mono spaced font.
#' \item \emph{\code{serif}}: Serif font family.
#' \item \emph{\code{sans}}: Default font family.
#' }
#' @param legend.type \strong{\code{\link[base]{character}}} | Type of legend to display. One of:
#' \itemize{
#' \item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
#' \item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
#' }
#' @param legend.position \strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
#' \itemize{
#' \item \emph{\code{top}}: Top of the figure.
#' \item \emph{\code{bottom}}: Bottom of the figure.
#' \item \emph{\code{left}}: Left of the figure.
#' \item \emph{\code{right}}: Right of the figure.
#' \item \emph{\code{none}}: No legend is displayed.
#' }
#' @param legend.title \strong{\code{\link[base]{character}}} | Title for the legend.
#' @param legend.title.position \strong{\code{\link[base]{character}}} | Position for the title of the legend. One of:
#' \itemize{
#' \item \emph{\code{top}}: Top of the legend.
#' \item \emph{\code{bottom}}: Bottom of the legend.
#' \item \emph{\code{left}}: Left of the legend.
#' \item \emph{\code{right}}: Right of the legend.
#' }
#' @param legend.framewidth,legend.tickwidth \strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.
#' @param legend.framecolor \strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.
#' @param legend.tickcolor \strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.
#' @param legend.length,legend.width \strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.
#' @param legend.icon.size \strong{\code{\link[base]{numeric}}} | Size of the icons in legend.
#' @param legend.ncol \strong{\code{\link[base]{numeric}}} | Number of columns in the legend.
#' @param legend.nrow \strong{\code{\link[base]{numeric}}} | Number of rows in the legend.
#' @param legend.byrow \strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.
#' @param plot.title,plot.subtitle,plot.caption \strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.
#' @param individual.titles,individual.subtitles,individual.captions \strong{\code{\link[base]{character}}} | Vector. Title, subtitle or caption to use in the plot when multiple features are passed on. Use NA to keep the original title.
#' @param reduction \strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use `Seurat::Reductions(sample)`. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.
#' @param assay \strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.
#' @param slot \strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".
#' @param viridis.palette \strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.
#' @param viridis.palette.pvalue,viridis.palette.logfc,viridis.palette.expression \strong{\code{\link[base]{character}}} | Viridis color palettes for the p-value, logfc and expression heatmaps. A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.
#' @param raster \strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.
#' @param raster.dpi \strong{\code{\link[base]{numeric}}} | Pixel resolution for rasterized plots. Defaults to 1024. Only activates on Seurat versions higher or equal than 4.1.0.
#' @param plot_cell_borders \strong{\code{\link[base]{logical}}} | Whether to plot border around cells.
#' @param border.size \strong{\code{\link[base]{numeric}}} | Width of the border of the cells.
#' @param border.color \strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.
#' @param na.value \strong{\code{\link[base]{character}}} | Color value for NA.
#' @param axis.text.x.angle \strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.
#' @param xlab,ylab \strong{\code{\link[base]{character}}} | Titles for the X and Y axis.
#' @param pt.size \strong{\code{\link[base]{numeric}}} | Size of the dots.
#' @param flip \strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.
#' @param verbose \strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.
#' @param group.by \strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.
#' @param split.by \strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.
#' @param colors.use \strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.
#' @param plot_marginal_distributions \strong{\code{\link[base]{logical}}} | Whether to plot marginal distributions on the figure or not.
#' @param marginal.type \strong{\code{\link[base]{character}}} | One of:
#' \itemize{
#' \item \emph{\code{density}}: Compute density plots on the margins.
#' \item \emph{\code{histogram}}: Compute histograms on the margins.
#' \item \emph{\code{boxplot}}: Compute boxplot on the margins.
#' \item \emph{\code{violin}}: Compute violin plots on the margins.
#' \item \emph{\code{densigram}}: Compute densigram plots on the margins.
#' }
#' @param marginal.size \strong{\code{\link[base]{numeric}}} | Size ratio between the main and marginal plots. A value of 5 means that the main plot is 5 times bigger than the marginal plots.
#' @param marginal.group \strong{\code{\link[base]{logical}}} | Whether to group the marginal distribution by group.by or current identities.
#' @param enforce_symmetry \strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.
#' @param column_title \strong{\code{\link[base]{character}}} | Title for the columns of the heatmaps. Only works with single heatmaps.
#' @param row_title \strong{\code{\link[base]{character}}} | Title for the rows of the heatmaps. Only works with single heatmaps.
#' @param cluster_cols \strong{\code{\link[base]{logical}}} | Cluster the columns or rows of the heatmaps.
#' @param cluster_rows \strong{\code{\link[base]{logical}}} | Cluster the rows or rows of the heatmaps.
#' @param column_names_rot \strong{\code{\link[base]{numeric}}} | Degree in which to rotate the column labels.
#' @param row_names_rot \strong{\code{\link[base]{numeric}}} | Degree in which to rotate the row labels.
#' @param cell_size \strong{\code{\link[base]{numeric}}} | Size of each cell in the heatmap.
#' @param input_gene_list \strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.
#' @param column_title_rot \strong{\code{\link[base]{numeric}}} | Degree in which to rotate the column titles.
#' @param row_title_rot \strong{\code{\link[base]{numeric}}} | Degree in which to rotate the row titles.
#' @param column_names_side \strong{\code{\link[base]{character}}} | Side to put the column names. Either left or right.
#' @param row_names_side \strong{\code{\link[base]{character}}} | Side to put the row names. Either left or right.
#' @param column_title_side \strong{\code{\link[base]{character}}} | Side to put the column titles Either left or right.
#' @param row_title_side \strong{\code{\link[base]{character}}} | Side to put the row titles Either left or right.
#' @param heatmap.legend.length,heatmap.legend.width \strong{\code{\link[base]{numeric}}} | Width and length of the legend in the heatmap.
#' @param heatmap.legend.framecolor \strong{\code{\link[base]{character}}} | Color of the edges and ticks of the legend in the heatmap.
#' @param scale_direction \strong{\code{\link[base]{numeric}}} | Direction of the viridis scales. Either -1 or 1.
#' @param heatmap_gap \strong{\code{\link[base]{numeric}}} | Gap in cm between heatmaps.
#' @param legend_gap \strong{\code{\link[base]{numeric}}} | Gap in cm between legends.
#' @param cells.highlight,idents.highlight \strong{\code{\link[base]{character}}} | Vector of cells/identities to focus into. The identities have to much those in \code{Seurat::Idents(sample)} The rest of the cells will be grayed out. Both parameters can be used at the same time.
#' @param dims \strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.
#' @param ncol \strong{\code{\link[base]{numeric}}} | Number of columns used in the arrangement of the output plot using "split.by" parameter.
#' @param features \strong{\code{\link[base]{character}}} | Features to represent.
#' @param feature \strong{\code{\link[base]{character}}} | Feature to represent.
#' @param use_viridis \strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.
#' @param viridis.direction \strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.
#' @param plot.grid \strong{\code{\link[base]{logical}}} | Whether to plot grid lines.
#' @param grid.color \strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.
#' @param grid.type \strong{\code{\link[base]{character}}} | One of the possible linetype options:
#' \itemize{
#' \item \emph{\code{blank}}.
#' \item \emph{\code{solid}}.
#' \item \emph{\code{dashed}}.
#' \item \emph{\code{dotted}}.
#' \item \emph{\code{dotdash}}.
#' \item \emph{\code{longdash}}.
#' \item \emph{\code{twodash}}.
#' }
#' @param plot.axes \strong{\code{\link[base]{logical}}} | Whether to plot axes or not.
#' @param nbin \strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.
#' @param ctrl \strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.
#' @param repel \strong{\code{\link[base]{logical}}} | Whether to repel the text labels.
#' @param plot_density_contour \strong{\code{\link[base]{logical}}} | Whether to plot density contours in the UMAP.
#' @param contour.position \strong{\code{\link[base]{character}}} | Whether to plot density contours on top or at the bottom of the visualization layers, thus overlapping the clusters/cells or not.
#' @param contour.color \strong{\code{\link[base]{character}}} | Color of the density lines.
#' @param contour.lineend \strong{\code{\link[base]{character}}} | Line end style (round, butt, square).
#' @param contour.linejoin \strong{\code{\link[base]{character}}} | Line join style (round, mitre, bevel).
#' @param contour_expand_axes \strong{\code{\link[base]{numeric}}} | To make the contours fit the plot, the limits of the X and Y axis are expanding a given percentage from the min and max values for each axis. This controls such percentage.
#' @param min.cutoff,max.cutoff \strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.
#' @param label \strong{\code{\link[base]{logical}}} | Whether to plot the cluster labels in the UMAP. The cluster labels will have the same color as the cluster colors.
#' @param label.color \strong{\code{\link[base]{character}}} | Color of the labels in the plot.
#' @param label.fill \strong{\code{\link[base]{character}}} | Color to fill the labels. Has to be a single color, that will be used for all labels. If \strong{\code{NULL}}, the colors of the clusters will be used instead.
#' @param label.size \strong{\code{\link[base]{numeric}}} | Size of the labels in the plot.
#' @param label.box \strong{\code{\link[base]{logical}}} | Whether to plot the plot labels as \strong{\code{\link[ggplot2]{geom_text}}} (FALSE) or \strong{\code{\link[ggplot2]{geom_label}}} (TRUE).
#' @param min.overlap \strong{\code{\link[base]{numeric}}} | Filter the output result to the terms which are supported by this many genes.
#' @param GO_ontology \strong{\code{\link[base]{character}}} | GO ontology to use. One of:
#' \itemize{
#' \item \emph{\code{BP}}: For \strong{B}iological \strong{P}rocess.
#' \item \emph{\code{MF}}: For \strong{M}olecular \strong{F}unction.
#' \item \emph{\code{CC}}: For \strong{C}ellular \strong{C}omponent.
#' }
#' @param genes \strong{\code{\link[base]{character}}} | Vector of gene symbols to query for functional annotation.
#' @param org.db \strong{\code{OrgDB}} | Database object to use for the query.
#' @param disable_white_in_viridis \strong{\code{\link[base]{logical}}} | Remove the white in viridis color scale when \strong{\code{viridis.direction}} is set to -1.
#' @param number.breaks \strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.
#' @param border.density \strong{\code{\link[base]{numeric}}} | Controls the number of cells used when \strong{\code{plot_cell_borders = TRUE}}. Value between 0 and 1. It computes a 2D kernel density and based on this cells that have a density below the specified quantile will be used to generate the cluster contour. The lower this number, the less cells will be selected, thus reducing the overall size of the plot but also potentially preventing all the contours to be properly drawn.
#' @param strip.spacing \strong{\code{\link[base]{numeric}}} | Controls the size between the different facets.
#' @param strip.text.color \strong{\code{\link[base]{character}}} | Color of the strip text.
#' @param strip.text.angle \strong{\code{\link[base]{numeric}}} | Rotation of the strip text (angles).
#' @param diverging.palette \strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.
#' @param diverging.direction \strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.
#' @param sequential.palette \strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.
#' @param sequential.palette.pvalue,sequential.palette.expression,sequential.palette.logfc \strong{\code{\link[base]{character}}} | Sequential palettes for p-value, logfc and expression heatmaps. Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.
#' @param sequential.direction \strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.
#' @param return_object \strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.
#' @param statistic \strong{\code{\link[base]{character}}} | DecoupleR statistic to use. One of:
#' \itemize{
#' \item \emph{\code{wmean}}: For weighted mean.
#' \item \emph{\code{norm_wmean}}: For normalized weighted mean.
#' \item \emph{\code{corr_wmean}}: For corrected weighted mean.
#' }
#' @param subsample \strong{\code{\link[base]{numeric}}} | Number of cells to randomly select from the Seurat object to enhance performance. Selecting NA will disable this but might lead to function breaks if the sample size is too large.
#' @param cluster \strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.
#' @param subsample \strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.
#' @param plot.title.face,plot.subtitle.face,plot.caption.face,axis.title.face,axis.text.face,legend.title.face,legend.text.face \strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
#' \itemize{
#' \item \emph{\code{plain}}: For normal text.
#' \item \emph{\code{italic}}: For text in itallic.
#' \item \emph{\code{bold}}: For text in bold.
#' \item \emph{\code{bold.italic}}: For text both in itallic and bold.
#' }
#' @param strip.text.face \strong{\code{\link[base]{character}}} | Controls the style of the font for the strip text. One of:
#' \itemize{
#' \item \emph{\code{plain}}: For normal text.
#' \item \emph{\code{italic}}: For text in itallic.
#' \item \emph{\code{bold}}: For text in bold.
#' \item \emph{\code{bold.italic}}: For text both in itallic and bold.
#' }
#' @param flavor \strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.
#' @param features.order \strong{\code{\link[base]{character}}} | Should the gene sets be ordered in a specific way? Provide it as a vector of characters with the same names as the names of the gene sets.
#' @param groups.order \strong{\code{\link[SCpubr]{named_list}}} | Should the groups in theheatmaps be ordered in a specific way? Provide it as a named list (as many lists as values in \strong{\code{group.by}}) with the order for each of the elements in the groups.
#' @param interpolate \strong{\code{\link[base]{logical}}} | Smoothes the output heatmap, saving space on disk when saving the image. However, the image is not as crisp.
#' @param order \strong{\code{\link[base]{logical}}} | Whether to order the boxplots by average values. Can not be used alongside split.by.
#' @param dot.scale \strong{\code{\link[base]{numeric}}} | Scale the size of the dots.
#' @param colorblind \strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.
#' @param values.show \strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.
#' @param values.threshold \strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.
#' @param values.size \strong{\code{\link[base]{numeric}}} | Size of the text labels.
#' @param values.round \strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.
#' @usage NULL
#' @return Nothing. This is a mock function.
#' @keywords internal
#' @examples
#'
#' # This a mock function that stores the documentation for many other functions.
#' # It is not intended for user usage.
doc_function <- function(sample,
font.size,
font.type,
legend.type,
legend.position,
legend.framewidth,
legend.tickwidth,
legend.framecolor,
legend.tickcolor,
legend.length,
legend.width,
plot.title,
plot.subtitle,
plot.caption,
assay,
slot,
reduction,
viridis.palette,
raster,
raster.dpi,
plot_cell_borders,
border.size,
border.color,
na.value,
axis.text.x.angle,
xlab,
ylab,
pt.size,
verbose,
flip,
group.by,
split.by,
colors.use,
legend.title,
legend.icon.size,
legend.byrow,
legend.ncol,
legend.nrow,
plot_marginal_distributions,
marginal.type,
marginal.size,
marginal.group,
enforce_symmetry,
column_title,
row_title,
cluster_cols,
cluster_rows,
column_names_rot,
row_names_rot,
cell_size,
input_gene_list,
column_title_rot,
row_title_rot,
column_names_side,
row_names_side,
column_title_side,
row_title_side,
heatmap.legend.length,
heatmap.legend.width,
heatmap.legend.framecolor,
scale_direction,
heatmap_gap,
legend_gap,
cells.highlight,
idents.highlight,
ncol,
dims,
feature,
features,
use_viridis,
viridis.direction,
plot.grid,
grid.color,
grid.type,
plot.axes,
individual.titles,
individual.subtitles,
individual.captions,
legend.title.position,
repel,
plot_density_contour,
contour.position,
contour.color,
contour.lineend,
contour.linejoin,
contour_expand_axes,
label,
label.color,
label.fill,
label.size,
label.box,
min.overlap,
GO_ontology,
genes,
org.db,
disable_white_in_viridis,
number.breaks,
strip.spacing,
strip.text.color,
strip.text.angle,
diverging.palette,
diverging.direction,
subsample,
plot.title.face,
plot.subtitle.face,
plot.caption.face,
axis.title.face,
axis.text.face,
legend.title.face,
legend.text.face,
flavor,
features.order,
groups.order,
interpolate,
order,
dot.scale,
values.show,
values.threshold,
values.size,
values.round){}
#' Named vector.
#'
#' @return Nothing. This is a mock function.
#' @keywords internal
#' @usage NULL
#' @examples
#' # This is a named vector.
#' x <- c("first_element" = 3,
#' "second_element" = TRUE)
#' print(x)
#'
named_vector <- function(){}
#' Named list.
#'
#' @return Nothing. This is a mock function.
#' @keywords internal
#' @usage NULL
#' @examples
#' # This is a named vector.
#' x <- list("first_element" = c("GENE A", "GENE B"),
#' "second_element" = c("GENE C", "GENE D"))
#' print(x)
#'
named_list <- function(){}
# Operators.
# Not in operator.
`%!in%` <- function(x, y) {return(!(x %in% y))}
# nocov start
crayon_body <- function(text){
return(cli::col_none(text))
}
add_star <- function(initial_newline = TRUE){
if (isTRUE(requireNamespace("cli", quietly = TRUE))){
return(paste0(ifelse(isTRUE(initial_newline), "\n\n", ""), cli::col_yellow(cli::style_bold(cli::symbol$star)), " "))
} else {
return("* ")
}
}
add_info <- function(initial_newline = TRUE){
if (isTRUE(requireNamespace("cli", quietly = TRUE))){
return(paste0(ifelse(isTRUE(initial_newline), "\n\n", ""), cli::col_cyan(cli::style_bold(cli::symbol$info)), " "))
} else {
return("i ")
}
}
add_cross <- function(initial_newline = TRUE){
if (isTRUE(requireNamespace("cli", quietly = TRUE))){
return(paste0(ifelse(isTRUE(initial_newline), "\n\n", ""), cli::col_red(cli::style_bold(cli::symbol$cross)), " "))
} else {
return("x ")
}
}
add_warning <- function(initial_newline = TRUE){
if (isTRUE(requireNamespace("cli", quietly = TRUE))){
return(paste0(ifelse(isTRUE(initial_newline), "\n", ""), cli::col_yellow(cli::style_bold("!")), " "))
} else {
return("! ")
}
}
add_tick <- function(initial_newline = TRUE){
if (isTRUE(requireNamespace("cli", quietly = TRUE))){
return(paste0(ifelse(isTRUE(initial_newline), "\n\n", ""), cli::col_green(cli::style_bold(cli::symbol$tick)), " "))
} else {
return("")
}
}
crayon_key <- function(text){
return(cli::col_cyan(text))
}
# nocov end
#' Return a list of SCpubr dependencies.
#'
#' @noRd
#' @return None
#' @examples
#' \donttest{
#' TBD
#' }
return_dependencies <- function(){
pkg_list <- list("Essentials" = c("Seurat",
"SeuratObject",
"rlang",
"dplyr",
"magrittr",
"dplyr",
"tidyr",
"tibble",
"stringr",
"ggplot2",
"patchwork",
"plyr",
"viridis",
"forcats",
"scales",
"assertthat",
"RColorBrewer",
"labeling",
"withr"),
"do_ActivityHeatmap" = "decoupleR",
"do_AlluvialPlot" = "ggalluvial",
"do_BarPlot" = c("colorspace", "ggrepel"),
"do_BeeSwarmPlot" = c("colorspace", "ggbeeswarm", "ggrastr"),
"do_BoxPlot" = "ggsignif",
"do_CellularStatesPlot" = c("pbapply", "ggExtra", "ggplotify", "scattermore"),
"do_ChordDiagramPlot" = "circlize",
"do_ColorPalette" = NULL,
"do_ColorBlindCheck" = c("colorspace"),
"do_CNVHeatmap" = "ggdist",
"do_CorrelationHeatmap" = NULL,
"do_DimPlot" = c("colorspace", "ggplotify", "scattermore"),
"do_DotPlot" = NULL,
"do_EnrichmentHeatmap" = c("UCell"),
"do_ExpressionHeatmap" = NULL,
"do_FeaturePlot" = c("scattermore", "MASS"),
"do_StripPlot" = "ggdist",
"do_GroupwiseDEHeatmap" = NULL,
"do_MetadataHeatmap" = "cluster",
"do_LigandReceptorPlot" = NULL,
"do_LoadingsHeatmap" = NULL,
"do_RankedEnrichmentHeatmap" = "Matrix",
"do_RankedExpressionHeatmap" = NULL,
"do_NebulosaPlot" = "Nebulosa",
"do_PathwayActivityHeatmap" = NULL,
"do_RidgePlot" = "ggridges",
"do_SCExpressionHeatmap" = NULL,
"do_SCEnrichmentHeatmap" = c("UCell"),
"do_TermEnrichmentPlot" = c("enrichplot"),
"do_TFActivityHeatmap" = NULL,
"do_ViolinPlot" = NULL,
"do_VolcanoPlot" = "ggrepel",
"do_WafflePlot" = NULL,
"do_SavePlot" = "svglite")
return(pkg_list)
}
#' Checks for Suggests.
#'
#' @noRd
#' @return None
#' @examples
#' \donttest{
#' TBD
#' }
check_suggests <- function(function_name, passive = FALSE){
pkg_list <- return_dependencies()
# The function is not in the current list of possibilities.
if (function_name %!in% names(pkg_list)){
stop(paste0(add_cross(), crayon_key(function_name), crayon_body(" is not an accepted function name.")), call. = FALSE)
}
pkgs <- c(pkg_list[[function_name]], pkg_list[["Essentials"]])
non_seurat_functions <- c("do_SavePlot",
"do_VolcanoPlot",
"do_LigandReceptorPlot",
"do_ColorPalette",
"do_ColorBlindPalette")
if (function_name %in% non_seurat_functions){
pkgs <- pkgs[!(pkgs %in% c("Seurat", "SeuratObject"))]
}
pkgs <- vapply(pkgs, requireNamespace, quietly = TRUE, FUN.VALUE = logical(1))
# nocov start
if(sum(!pkgs) > 0){
missing_pkgs <- names(pkgs[vapply(pkgs, function(x){base::isFALSE(x)}, FUN.VALUE = logical(1))])
if (base::isFALSE(passive)){
stop(paste0(add_cross(), crayon_body("Packages "),
paste(vapply(missing_pkgs, crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(" must be installed to use "),
crayon_key(function_name),
crayon_body(".")), call. = FALSE)
}
}
value <- if(sum(pkgs) != length(pkgs)){FALSE} else {TRUE}
if (isTRUE(passive)) {return(value)}
# nocov end
}
#' Generate a status report of SCpubr and its dependencies.
#'
#' This function generates a summary report of the installation status of SCpubr, which packages are still missing and which functions can or can not currently be used.
#'
#' @param startup \strong{\code{\link[base]{logical}}} | Whether the message should be displayed at startup, therefore, also containing welcoming messages and tips. If \strong{\code{FALSE}}, only the report itself will be printed.
#' @param extended \strong{\code{\link[base]{logical}}} | Whether the message should also include installed packages, current and available version, and which \strong{\code{SCpubr}} functions can be used with the currently installed packages.
#' @return None
#' @export
#'
#' @examples
#'
#' \donttest{
#' # Print a package report.
#' SCpubr::do_PackageReport(startup = FALSE, extended = FALSE)
#' }
do_PackageReport <- function(startup = FALSE,
extended = FALSE){
# nocov start
if (base::isFALSE(requireNamespace("cli", quietly = TRUE)) | base::isFALSE(requireNamespace("rlang", quietly = TRUE))){
if (base::isFALSE(startup)){
message(paste(rep("-", 63), collapse = ""))
message('This is a placeholder message. Please install "cli" and "rlang" packages to have an optimal experience using the package.')
message(paste(rep("-", 63), collapse = ""))
} else if(isTRUE(startup)){
packageStartupMessage(paste(rep("-", 63), collapse = ""))
packageStartupMessage('This is a placeholder message. Please install "cli" and "rlang" packages to have an optimal experience using the package.')
packageStartupMessage(paste(rep("-", 63), collapse = ""))
packageStartupMessage("\n\n\nSCpubr")
packageStartupMessage("\nIf you use SCpubr in your research, please cite it accordingly: \nBlanco-Carmona, E. Generating publication ready visualizations for Single Cell transcriptomics using SCpubr. bioRxiv (2022) doi:10.1101/2022.02.28.482303.\n")
packageStartupMessage("If the package is useful to you, consider leaving a Star in the GitHub repo: https://github.com/enblacar/SCpubr/stargazers \n")
packageStartupMessage("Keep track of the package updates on Twitter (@Enblacar) or in https://github.com/enblacar/SCpubr/blob/main/NEWS.md \n")
packageStartupMessage("To suppress this startup message, use: \nsuppressPackageStartupMessages(library('SCpubr'))")
packageStartupMessage(paste(rep("-", 63), collapse = ""))
}
} else {
# nocov end
tip_rule <- cli::rule(left = "General", width = nchar("General") + 6)
tutorials <- paste0(add_info(initial_newline = FALSE),
crayon_body("Have a look at extensive tutorials in "),
crayon_key(cli::style_hyperlink(text = "SCpubr's book",
url = "https://enblacar.github.io/SCpubr-book/")),
crayon_body("."))
cite <- paste0(add_tick(initial_newline = FALSE),
crayon_body("If you use "),
crayon_key("SCpubr"),
crayon_body(" in your research, please "),
crayon_key(cli::style_hyperlink(text = "cite it accordingly",
url = "https://www.biorxiv.org/content/10.1101/2022.02.28.482303v1")),
crayon_body("."))
stars <- paste0(add_star(initial_newline = FALSE),
crayon_body("If the package is useful to you, consider leaving a "),
crayon_key("Star"),
crayon_body(" in the "),
crayon_key(cli::style_hyperlink(text = "GitHub repository",
url = "https://github.com/enblacar/SCpubr")),
crayon_body("."))
updates <- paste0(cli::style_bold(cli::col_blue("!")),
crayon_body(" Keep track of the package "),
crayon_key("updates"),
crayon_body(" on Twitter ("),
crayon_key(cli::style_hyperlink(text = "@Enblacar",
url = "https://twitter.com/Enblacar")),
crayon_body(") or in the "),
crayon_key(cli::style_hyperlink(text = "Official NEWS website",
url = "https://github.com/enblacar/SCpubr/blob/main/NEWS.md")),
crayon_body("."))
plotting <- paste0(cli::style_bold(cli::col_red(cli::symbol$heart)), " ", crayon_body("Happy plotting!"))
header <- cli::rule(left = paste0(crayon_body("SCpubr "),
crayon_key(utils::packageVersion("SCpubr"))), line_col = "cadetblue")
if (isTRUE(extended)){
format_package_name <- function(package,
max_length_packages){
length.use <- max_length_packages - nchar(package)
package.use <- paste0(package, paste(rep(" ", length.use), collapse = ""))
if (isTRUE(requireNamespace(package, quietly = TRUE))){
if ((package == "ggplot2") & (utils::packageVersion(package) < "3.4.0")){
name <- paste0(cli::col_yellow(cli::style_bold("!")),
" ",
cli::col_magenta(package.use))
} else if ((package == "dplyr") & (utils::packageVersion(package) < "1.1.0")){
name <- paste0(cli::col_yellow(cli::style_bold("!")),
" ",
cli::col_magenta(package.use))
} else {
name <- paste0(cli::col_green(cli::symbol$tick),
crayon_body(" "),
crayon_body(package.use))
}
return(name)
} else {
return(paste0(cli::col_red(cli::symbol$cross),
crayon_body(" "),
cli::col_red(package.use)))
}
}
packages <- sort(unique(unlist(return_dependencies())))
max_length_packages <- max(vapply(packages, nchar, FUN.VALUE = numeric(1)))
packages_mod <- vapply(packages, function(x){format_package_name(x,
max_length_packages = max_length_packages)}, FUN.VALUE = character(1))
functions <- sort(unique(names(return_dependencies())))
if (rev(strsplit(as.character( as.character(utils::packageVersion("SCpubr"))), split = "\\.")[[1]])[1] >= 9000){
names.use <- unname(vapply(functions, function(x){if (x %in% c("do_SavePlot")){x <- paste0(x, cli::col_cyan(" | DEV"))} else {x}}, FUN.VALUE = character(1)))
functions <- vapply(functions, check_suggests, passive = TRUE, FUN.VALUE = logical(1))
names(functions) <- names.use
# nocov start
} else {
functions <- functions[!(functions %in% c("do_SavePlot"))]
functions <- vapply(functions, check_suggests, passive = TRUE, FUN.VALUE = logical(1))
}
# nocov end
functions <- functions[names(functions) != "Essentials"]
max_length_functions <- max(vapply(names(functions), nchar, FUN.VALUE = numeric(1)))
format_functions <- function(name, value, max_length){
func_use <- ifelse(isTRUE(value), cli::col_green(cli::symbol$tick), cli::col_red(cli::symbol$cross))
name_use <- ifelse(isTRUE(value),
cli::ansi_align(crayon_body(name), max_length, align = "left"),
cli::ansi_align(cli::col_red(name), max_length, align = "left"))
paste0(func_use, " ", name_use)
}
functions.use <- NULL
for(item in names(functions)){
functions.use <- append(functions.use, format_functions(name = item, value = functions[[item]], max_length = max_length_functions))
}
counter <- 0
print.list <- list()
print.list.functions <- list()
print.vector <- NULL
print.vector.functions <- NULL
for(item in packages_mod){
counter <- counter + 1
if (counter %% 4 != 0){
print.vector <- append(print.vector, item)
if (counter == length(packages)){
print.list[[item]] <- paste(print.vector, collapse = " ")
print.vector <- NULL
}
} else {
print.vector <- append(print.vector, item)
print.list[[item]] <- paste(print.vector, collapse = " ")
print.vector <- NULL
}
}
counter <- 0
for(item in functions.use){
counter <- counter + 1
if (counter %% 3 != 0){
print.vector.functions <- append(print.vector.functions, item)
if (counter == length(functions.use)){
print.list.functions[[item]] <- paste(print.vector.functions, collapse = " ")
}
} else {
print.vector.functions <- append(print.vector.functions, item)
print.list.functions[[item]] <- paste(print.vector.functions, collapse = " ")
print.vector.functions <- NULL
}
}
packages_check <- cli::rule(left = "Required packages", width = nchar("Required packages") + 6)
packages_tip1 <- paste0(cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" Installed packages are denoted by a "),
crayon_key("tick"),
crayon_body(" ("),
cli::style_bold(cli::col_green(cli::symbol$tick)),
crayon_body(") and missing packages by a "),
cli::col_red("cross"),
crayon_body(" ("),
cli::style_bold(cli::col_red(cli::symbol$cross)),
crayon_body(")."))
packages_tip2 <- paste0(cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" Installed packages that still require an update to correctly run "),
crayon_key("SCpubr"),
crayon_body(" have an "),
crayon_key("exclamation mark"),
crayon_body(" ("),
cli::style_bold(cli::col_yellow("!")),
crayon_body(")."))
functions_check <- cli::rule(left = "Available functions", width = nchar("Available functions") + 6)
functions_tip1 <- paste0(cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" Functions tied to "),
crayon_key("development"),
crayon_body(" builds of "),
crayon_key("SCpubr"),
crayon_body(" are marked by the ("),
cli::col_cyan("| DEV"),
crayon_body(") tag."))
functions_tip2 <- paste0(cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" You can install development builds of "),
crayon_key("SCpubr"),
crayon_body(" by following the instructions in the "),
crayon_key(cli::style_hyperlink(text = "Releases",
url = "https://github.com/enblacar/SCpubr/releases")),
crayon_body(" page."))
}
tip_rule <- cli::rule(left = "Tips!", width = nchar("Tips!") + 6)
ins_message <- paste0(cli::style_bold(cli::col_blue("!")),
crayon_body(" Check missing dependencies with: "),
cli::style_italic(crayon_key('SCpubr::do_PackageReport(extended = TRUE)')))
tip_message <- paste0(cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" To remove the white and black end from continuous palettes, use: "),
cli::style_italic(crayon_key('options("SCpubr.ColorPaletteEnds" = FALSE)')))
tip_message2 <- paste0(cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" Colorblind-safe continuous/divergent color palettes are used by default.\n"),
cli::style_bold(cli::col_cyan(cli::symbol$info)),
crayon_body(" For categorical variables, you can use: "),
cli::style_italic(crayon_key('colorblind = TRUE')))
disable_message <- paste0(cli::style_bold(cli::col_red(cli::symbol$cross)),
crayon_body(" To suppress this startup message, use: "),
cli::style_italic(crayon_key('suppressPackageStartupMessages(library(SCpubr))\n')),
cli::style_bold(cli::col_red(cli::symbol$cross)),
crayon_body(" Alternatively, you can also set the following option: "),
cli::style_italic(crayon_key('options("SCpubr.verbose" = FALSE)\n')),
crayon_body(" And then load the package normally (and faster) as: "),
cli::style_italic(crayon_key('library(SCpubr)')))
end_rule <- cli::rule(col = "cadetblue")
# Mount all individual messages into a big one that will be then be printed as a packageStartupMessage.
if (isTRUE(startup)){
if (isTRUE(extended)){
msg_wrap <- paste0("\n", "\n",
header, "\n", "\n",
tutorials, "\n", "\n",
cite, "\n", "\n",
stars, "\n", "\n",
updates, "\n", "\n",
plotting, "\n", "\n", "\n", "\n",
packages_check, "\n", "\n",
paste(print.list, collapse = "\n"), "\n", "\n",
packages_tip1, "\n",
packages_tip2, "\n", "\n", "\n", "\n",
functions_check, "\n", "\n",
paste(print.list.functions, collapse = "\n"), "\n", "\n",
functions_tip1, "\n",
functions_tip2, "\n", "\n", "\n", "\n",
tip_rule, "\n", "\n",
ins_message, "\n", "\n",
tip_message, "\n", "\n",
tip_message2, "\n", "\n",
disable_message, "\n", "\n",
end_rule)
} else {
msg_wrap <- paste0("\n", "\n",
header, "\n", "\n",
tutorials, "\n", "\n",
cite, "\n", "\n",
stars, "\n", "\n",
updates, "\n", "\n",
plotting, "\n", "\n", "\n", "\n",
tip_rule, "\n", "\n",
ins_message, "\n", "\n",
tip_message, "\n", "\n",
tip_message2, "\n", "\n",
disable_message, "\n", "\n",
end_rule)
}
rlang::inform(msg_wrap, class = "packageStartupMessage")
} else if (base::isFALSE(startup)){
if (isTRUE(extended)){
msg_wrap <- paste0("\n", "\n",
header, "\n", "\n",
packages_check, "\n", "\n",
paste(print.list, collapse = "\n"), "\n", "\n",
packages_tip1, "\n",
packages_tip2, "\n", "\n", "\n", "\n",
functions_check, "\n", "\n",
paste(print.list.functions, collapse = "\n"), "\n", "\n",
functions_tip1, "\n",
functions_tip2, "\n", "\n", "\n", "\n",
tip_rule, "\n", "\n",
ins_message, "\n", "\n",
tip_message, "\n", "\n",
tip_message2, "\n", "\n",
disable_message, "\n", "\n",
end_rule)
} else {
msg_wrap <- paste0("\n", "\n",
header, "\n", "\n",
tutorials, "\n", "\n",
cite, "\n", "\n",
stars, "\n", "\n",
updates, "\n", "\n",
plotting, "\n", "\n", "\n", "\n",
tip_rule, "\n", "\n",
ins_message, "\n", "\n",
tip_message, "\n", "\n",
tip_message2, "\n", "\n",
disable_message, "\n", "\n",
end_rule)
}
rlang::inform(msg_wrap)
}
}
}
#' Check for Seurat class.
#'
#' @param sample Seurat object.
#'
#' @noRd
#' @return None
#'
#' @examples
#' \donttest{
#' TBD
#' }
check_Seurat <- function(sample){
assertthat::assert_that("Seurat" %in% class(sample),
msg = paste0(add_cross(), crayon_body("The provided "),
crayon_key("object"),
crayon_body(" is not a "),
crayon_key("Seurat"),
crayon_body(" object.")))
}
#' Internal check for colors.
#'
#' Adapted from: https://stackoverflow.com/a/13290832.
#
#' @param colors Vector of colors.
#' @param parameter_name The name of the parameter for which we are testing the colors.
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_colors <- function(colors, parameter_name = "") {
check <- vapply(colors, function(color) {
tryCatch(is.matrix(grDevices::col2rgb(colors)),
error = function(e) FALSE)
}, FUN.VALUE = logical(1))
# Check for cols.highlight.
assertthat::assert_that(sum(check) == length(colors),
msg = paste0(add_cross(), crayon_body("The colors provided to "),
crayon_key(parameter_name),
crayon_body(" are not valid color representations.\nCheck whether they are accepted "),
crayon_key("R nammes"),
crayon_body(" or "),
crayon_key("HEX codes"),
crayon_body(".")))
}
#' Internal check for named colors and unique values of the grouping variable.
#'
#' @param sample Seurat object.
#' @param colors Named vector of colors.
#' @param grouping_variable Metadata variable in sample to obtain its unique values.
#' @param idents.keep Identities to keep from the grouping_variable.
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_consistency_colors_and_names <- function(sample, colors, grouping_variable = NULL, idents.keep = NULL){
# Add lengthy error messages.
withr::local_options(.new = list("warning.length" = 8170))
if (is.null(grouping_variable)){
check_values <- levels(sample)
} else {
if (is.factor(sample@meta.data[, grouping_variable])){
check_values <- levels(sample@meta.data[, grouping_variable])
} else {
check_values <- as.character(unique(sample@meta.data[, grouping_variable]))
}
}
if (!is.null(idents.keep)){
# Remove unwanted idents.
check_values <- check_values[check_values %in% idents.keep]
}
# Remove NAs.
check_values <- check_values[!(is.na(check_values))]
# Remove values that are not in the vector.
if (sum(names(colors) %in% check_values) == length(check_values) & length(names(colors)) > length(check_values)){
colors <- colors[names(colors) %in% check_values]
}
if (base::isFALSE(length(colors) == length(check_values)) | base::isFALSE(sum(names(colors) %in% check_values) == length(check_values))){
format_colors <- function(name, value, colors, max_length){
if (name %in% names(colors)){
name <- paste(c(name, crayon_body(" | "), cli::col_cyan(paste0(colors[[name]]))), collapse = "")
}
func_use <- ifelse(isTRUE(value), cli::col_green(cli::symbol$tick), cli::col_red(cli::symbol$cross))
name_use <- ifelse(isTRUE(value),
cli::ansi_align(crayon_key(name), max_length, align = "left"),
cli::ansi_align(cli::col_red(name), max_length, align = "left"))
paste0(func_use, " ", name_use)
}
color_check <- vapply(check_values, function(x){ifelse(x %in% names(colors), TRUE, FALSE)}, FUN.VALUE = logical(1))
max_length <- max(vapply(check_values, nchar, FUN.VALUE = numeric(1)))
max_length_colors <- max(vapply(unname(colors), nchar, FUN.VALUE = numeric(1)))
length.use <- max_length + 3 + max_length_colors
colors.print <- NULL
for(item in sort(names(color_check))){
colors.print <- append(colors.print, format_colors(name = item, colors = colors, value = color_check[[item]], max_length = length.use))
}
msg <- paste0("\n", "\n",
add_cross(),
crayon_body("The "),
crayon_key("number"),
crayon_body(" or "),
crayon_key("names"),
crayon_body(" of the provided "),
crayon_key("colors"),
crayon_body(" is lower than the "),
crayon_key("number of unique values"),
crayon_body(" in "),
crayon_key("group.by"),
crayon_body(" (which defaults to "),
cli::style_italic(crayon_key("Seurat::Idents(sample)")),
crayon_body(" if "),
crayon_key("NULL"),
crayon_body(")."),
"\n",
add_cross(),
crayon_body("Please check that the "),
crayon_key("colors provided"),
crayon_body(" are a "),
crayon_key("named vector"),
crayon_body(" where the names are the "),
crayon_key("unique values"),
crayon_body(" to which you then assign the "),
crayon_key("colors"),
crayon_body(" to."),
"\n", "\n",
add_warning(),
crayon_body("Example: "),
cli::style_italic(crayon_key('colors.use = c("A" = "red", "B" = "blue")')),
"\n",
"\n", "\n",
crayon_body(cli::rule(left = paste0(crayon_key("Values"), crayon_body(" with an "), cli::col_cyan("assigned color")), width = nchar("Values with an assigned color") + 6)),
"\n", "\n",
paste(colors.print, collapse = "\n"), "\n", "\n")
stop(msg, call. = FALSE)
}
return(colors)
}
#' Generate custom color scale.
#'
#' @param names_use Vector of the names that will go alongside the color scale.
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
generate_color_scale <- function(names_use, colorblind = FALSE){
if (base::isFALSE(colorblind)){
# Generate a vector of colors equal to the number of identities in the sample.
colors <- colorspace::qualitative_hcl(length(names_use), palette = "Dark 3")
colors <- grDevices::col2rgb(colors)
colors <- grDevices::rgb2hsv(colors)
colors["v", ] <- colors["v", ] - 0.1
colors["s", ] <- colors["s", ] + 0.2
colors["s", ][colors["s", ] > 1] <- 1
colors <- grDevices::hsv(h = colors["h", ],
s = colors["s", ],
v = colors["v", ],
alpha = 1)
names(colors) <- names_use
return(colors)
} else {
colors.use <- get_Colorblind_colors()
wong.colors <- colors.use[["Wong"]]
tol.bright.colors <- colors.use[["Tol_Bright"]]
tol.muted.colors <- colors.use[["Tol_Muted"]]
okabe.colors <- colors.use[["Okabe"]]
krz.8 <- colors.use[["Krz8"]]
krz.12 <- colors.use[["Krz12"]]
krz.15 <- colors.use[["Krz15"]]
krz.24 <- colors.use[["Krz24"]]
collection <- colors.use[["Collection"]]
assertthat::assert_that(length(names_use) < length(collection),
msg = paste0(add_cross(), crayon_body("Please, select another variable that has less than "),
crayon_key(as.character(length(collection))),
crayon_body(" classes when using "),
crayon_key("colorblind = TRUE"),
crayon_body(".")))
# N = 7
if (length(names_use) == length(tol.bright.colors)){
colors <- tol.bright.colors
# N = 8
} else if (length(names_use) == length(wong.colors)){
colors <- wong.colors
# N = 9
} else if (length(names_use) == length(tol.muted.colors)){
colors <- tol.muted.colors
# N = 12
} else if (length(names_use) == length(krz.12)){
colors <- krz.12
# N = 15
} else if (length(names_use) == length(krz.15)){
colors <- krz.15
# N = 24
} else if (length(names_use) == length(krz.24)){
colors <- krz.24
# Less than 7
} else if (length(names_use) < 7){
colors <- wong.colors[1:length(names_use)]
# Remaining cases
} else {
length.use <- length(names_use)
colors <- collection[1:length.use]
}
names(colors) <- names_use
return(colors)
}
}
#' Compute the max and min value of a variable provided to FeaturePlot.
#'
#' @param sample Seurat object.
#' @param feature Feature to plot.
#' @param assay Assay used.
#' @param reduction Reduction used.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
compute_scale_limits <- function(sample, feature, assay = NULL, reduction = NULL, slot = NULL){
if (is.null(assay)){
assay <- Seurat::DefaultAssay(sample)
}
if (is.null(reduction)){
for(red in Seurat::Reductions(object = sample)){
if (feature %in% colnames(sample@reductions[[red]][[]])){
reduction <- red
}
}
}
if (is.null(slot)){
slot <- "data"
}
if (feature %in% rownames(sample)){
if (utils::packageVersion("Seurat") < "5.0.0"){
data.check <- SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = slot)[feature, ]
} else {
data.check <- SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = slot)[feature, ]
}
scale.begin <- min(data.check, na.rm = TRUE)
scale.end <- max(data.check, na.rm = TRUE)
} else if (feature %in% colnames(sample@meta.data)){
if (is.factor(sample@meta.data[, feature])){
sample@meta.data[, feature] <- as.character(sample@meta.data[, feature])
}
scale.begin <- min(sample@meta.data[, feature], na.rm = TRUE)
scale.end <- max(sample@meta.data[, feature], na.rm = TRUE)
} else if (feature %in% colnames(sample@reductions[[reduction]][[]])){
scale.begin <- min(sample@reductions[[reduction]][[]][, feature], na.rm = TRUE)
scale.end <- max(sample@reductions[[reduction]][[]][, feature], na.rm = TRUE)
}
return(list("scale.begin" = scale.begin,
"scale.end" = scale.end))
}
#' Check cutoffs
#'
#' @param min.cutoff Min cutoff.
#' @param max.cutoff Max cutoff.
#' @param limits Computed range.
#' @param feature Feature name, if any.
#' @return A list.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_cutoffs <- function(min.cutoff,
max.cutoff,
limits,
feature = ""){
outlier.data <- FALSE
if (!is.na(min.cutoff) & !is.na(max.cutoff)){
assertthat::assert_that(min.cutoff < max.cutoff,
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key("min.cutoff"),
crayon_body(" ("),
crayon_key(min.cutoff),
crayon_body(") for the feature ("),
crayon_key(feature),
crayon_body(") has to be lower than the value provided to "),
crayon_key("max.cutoff"),
crayon_body(" ("),
crayon_key(max.cutoff),
crayon_body(").")))
}
if (!is.na(min.cutoff)){
assertthat::assert_that(min.cutoff >= limits[1],
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key("min.cutoff"),
crayon_body(" ("),
crayon_key(min.cutoff),
crayon_body(") is lower than the minimum value ("),
crayon_key(limits[1]),
crayon_body(") for the feature ("),
crayon_key(feature),
crayon_body(").")))
assertthat::assert_that(min.cutoff <= limits[2],
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key("min.cutoff"),
crayon_body(" ("),
crayon_key(min.cutoff),
crayon_body(") is higher than the maximum value ("),
crayon_key(limits[2]),
crayon_body(") for the feature ("),
crayon_key(feature),
crayon_body(").")))
limits <- c(min.cutoff, limits[2])
outlier.data <- TRUE
}
if (!is.na(max.cutoff)){
assertthat::assert_that(max.cutoff <= limits[2],
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key("max.cutoff"),
crayon_body(" ("),
crayon_key(max.cutoff),
crayon_body(") is higher than the maximum value ("),
crayon_key(limits[2]),
crayon_body(") for the feature ("),
crayon_key(feature),
crayon_body(").")))
assertthat::assert_that(max.cutoff >= limits[1],
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key("max.cutoff"),
crayon_body(" ("),
crayon_key(max.cutoff),
crayon_body(") is lower than the minimum value ("),
crayon_key(limits[1]),
crayon_body(") for the feature ("),
crayon_key(feature),
crayon_body(").")))
limits <- c(limits[1], max.cutoff)
outlier.data <- TRUE
}
return.list <- list("outlier.data" = outlier.data,
"limits" = limits)
return(return.list)
}
#' Compute the scales for a given ggplot2-based plot.
#'
#' @param sample Seurat object.
#' @param feature Feature to compute scales to.
#' @param assay Assay to retrieve data from.
#' @param reduction Reduction to use if the feature is a dimred component.
#' @param slot Slot to retrieve the values from if feature is a gene.
#' @param flavor Whether it is a seurat plot or ggplot2-based plots.
#' @param number.breaks Number of desired breaks in the scale.
#' @param min.cutoff Minimum cutoff for the scale.
#' @param max.cutoff Maximum cutoff for the scale.
#' @param from_data Provide a matrix already.
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
compute_scales <- function(sample,
feature = "",
assay = NULL,
reduction = NULL,
slot,
flavor,
number.breaks,
min.cutoff,
max.cutoff,
enforce_symmetry,
from_data = FALSE,
limits.use = NULL,
center_on_value = FALSE,
value_center = NULL){
if (base::isFALSE(from_data)){
limits <- compute_scale_limits(sample = sample,
feature = feature,
assay = assay,
reduction = reduction,
slot = slot)
limits <- c(limits$scale.begin, limits$scale.end)
} else {
limits <- limits.use
}
out <- check_cutoffs(min.cutoff = min.cutoff,
max.cutoff = max.cutoff,
limits = limits,
feature = feature)
limits <- out$limits
if (isTRUE(enforce_symmetry)){
if (base::isFALSE(center_on_value)){
end_value <- max(abs(limits))
limits <- c(-end_value, end_value)
} else {
low_end <- value_center - limits[1]
high_end <- limits[2] - value_center
value.use <- max(c(abs(low_end), abs(high_end)))
limits <- c(value_center - value.use, value_center + value.use)
}
}
if (is.na(limits[1]) || is.na(limits[2])) {
stop("Invalid axis limits: dmin or dmax is NA.")
}
breaks <- labeling::extended(dmin = limits[1],
dmax = limits[2],
m = number.breaks)
labels <- as.character(breaks)
if (!is.na(min.cutoff)){
if (isTRUE(min.cutoff == breaks[1])){
breaks[1] <- min.cutoff
labels[1] <- paste0(as.character(expression("\u2264")), " ", min.cutoff)
}
}
if (!is.na(max.cutoff)){
if (isTRUE(max.cutoff == breaks[length(breaks)])){
breaks[length(breaks)] <- max.cutoff
labels[length(labels)] <- paste0(as.character(expression("\u2265")), " ", max.cutoff)
}
}
# Fix for the one value limit.
if(limits[[1]] == limits[[2]]){
breaks <- limits[[1]]
labels <- as.character(limits[[1]])
}
return.obj <- list("limits" = limits,
"breaks" = breaks,
"labels" = labels)
return(return.obj)
}
#' Check if a value is in the range of the values.
#'
#' @param sample Seurat object.
#' @param feature Feature to plot.
#' @param assay Assay used.
#' @param reduction Reduction used.
#' @param value Value to check.
#' @param value_name Name of the value.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_limits <- function(sample, feature, value_name, value, assay = NULL, reduction = NULL){
limits <- compute_scale_limits(sample = sample, feature = feature, assay = assay, reduction = reduction)
assertthat::assert_that(limits[["scale.begin"]] <= value & limits[["scale.end"]] >= value,
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key(value_name),
crayon_body(" ("),
crayon_key(value),
crayon_body(") is not in the range of values of "),
crayon_key(feature),
crayon_body(", whis is:\nMin: "),
crayon_key(limits[["scale.begin"]]),
crayon_body(".\nMax:"),
crayon_key(limits[["scale.end"]]),
crayon_body(".")))
}
#' Check if the feature to plot is in the Seurat object.
#'
#' @param sample Seurat object.
#' @param features Feature to plot.
#' @param dump_reduction_names Whether to return the reduction colnames.
#' @param permissive Throw a warning or directly stops if the feature is not found.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_feature <- function(sample, features, permissive = FALSE, dump_reduction_names = FALSE, enforce_check = NULL, enforce_parameter = NULL){
if (is.list(features)){
features_check <- unlist(features)
} else {
features_check <- features
}
check_enforcers <- list() # Store the results of the checks.
not_found_features <- NULL # Store the features not found.
# Check each of the features.
for (feature in features_check){
check <- 0
if (!(feature %in% rownames(sample))){
check <- check + 1
check_enforcers[["gene"]] <- FALSE
} else {
check_enforcers[["gene"]] <- TRUE
}
if (!(feature %in% colnames(sample@meta.data))){
check <- check + 1
check_enforcers[["metadata"]] <- FALSE
} else {
check_enforcers[["metadata"]] <- TRUE
}
dim_colnames <- NULL
for(red in Seurat::Reductions(object = sample)){
dim_colnames <- append(dim_colnames, colnames(sample@reductions[[red]][[]]))
}
if (!(feature %in% dim_colnames)){
check <- check + 1
check_enforcers[["reductions"]] <- FALSE
} else {
check_enforcers[["reductions"]] <- TRUE
}
if (check == 3) {
not_found_features <- append(not_found_features, feature)
}
}
# Return the error logs if there were features not found.
if (length(not_found_features) > 0){
if (isTRUE(permissive)){
# Stop if neither of the features are found.
assertthat::assert_that(length(unlist(not_found_features)) != length(unlist(features)),
msg = "Neither of the provided features are found.")
warning(paste0(add_warning(), crayon_body("The following "),
crayon_key("features"),
crayon_body(" were not be found:"),
paste(vapply(not_found_features, crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(".")), call. = FALSE)
features_out <- remove_not_found_features(features = features, not_found_features = not_found_features)
} else if (base::isFALSE(permissive)){
assertthat::assert_that(length(not_found_features) == 0,
msg = paste0(add_cross(), crayon_body("The following "),
crayon_key("features"),
crayon_body(" were not be found:"),
paste(vapply(not_found_features, crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(".")))
}
} else {
features_out <- features
}
# If we are enforcing a given check (i.e: the feature being in the metadata).
if (!(is.null(enforce_check))){
assertthat::assert_that(enforce_check %in% names(check_enforcers),
msg = "The variable enforcer is not in the current list of checked variable types.")
assertthat::assert_that(isTRUE(check_enforcers[[enforce_check]]),
msg = paste0(add_cross(), crayon_body("Feature "),
crayon_key(enforce_parameter),
crayon_key(" = "),
crayon_key(feature),
crayon_body(" not found in "),
crayon_key(enforce_check),
crayon_body(".")))
}
# Return options.
if (isTRUE(dump_reduction_names) & base::isFALSE(permissive)){return(dim_colnames)}
if (isTRUE(permissive) & base::isFALSE(dump_reduction_names)){return(features_out)}
if (isTRUE(dump_reduction_names) & isTRUE(permissive)){return(list("features" = features_out, "reduction_names" = dim_colnames))}
}
#' Remove not found features
#'
#' @param features Features to check.
#' @param not_found_features Features to exclude.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
remove_not_found_features <- function(features, not_found_features){
if (is.character(features)){
features_out <- features[!(features %in% not_found_features)]
} else if (is.list(features)){
features_out <- list()
for (list_name in names(features)){
genes <- features[[list_name]]
genes_out <- genes[!(genes %in% not_found_features)]
features_out[[list_name]] <- genes_out
}
}
return(features_out)
}
#' Remove duplicated features.
#'
#' @param features Features to check.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
remove_duplicated_features <- function(features){
if (is.character(features)){
check <- sum(duplicated(features))
if (check > 0){
warning(paste0(add_warning(), crayon_body("Found duplicated features:\n"),
crayon_key(paste(features[duplicated(features)])),
crayon_body(".\nExcluding them from the analysis.")), call. = FALSE)
features <- features[!(duplicated(features))]
}
} else if (is.list(features)){
features_out <- list()
all_genes <- NULL # Will update with the genes as they iterate to check duplicates.
for (list_name in names(features)){
genes <- features[[list_name]]
# Remove genes duplicated within the list.
if (sum(duplicated(genes)) > 0){
warning(paste0(add_warning(), crayon_body("Found duplicated features:\n"),
crayon_key(paste(genes[duplicated(genes)], collapse = ", ")),
crayon_body("\nIn the list named: "),
crayon_key(list_name),
crayon_body(".\nExcluding them from the analysis.")), call. = FALSE)
}
genes <- genes[!(duplicated(genes))]
# Remove genes duplicated in the vector of all genes.
duplicated_features <- genes[genes %in% all_genes]
all_genes <- append(all_genes, genes[!(genes %in% all_genes)])
genes <- genes[!(genes %in% duplicated_features)]
if (length(duplicated_features) > 0){
warning(paste0(add_warning(), crayon_body("Found duplicated features:\n"),
crayon_key(paste(duplicated_features, collapse = ", ")),
crayon_body("\nIn the list named: "),
crayon_key(list_name),
crayon_body(" with regards to the other lists. \nExcluding them from the analysis.")), call. = FALSE)
}
features_out[[list_name]] <- genes
}
features <- features_out
}
return(features)
}
#' Check if the identity provided is in the current Seurat identities.
#'
#' @param sample Seurat object.
#' @param identities Identities to test.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_identity <- function(sample, identities){
for (identity in identities){
assertthat::assert_that(identity %in% levels(sample),
msg = paste0(add_cross(), crayon_body("Could not find identity "),
crayon_key(identity),
crayon_body(" in the current active identities of the object.")))
}
}
#' Check the reduction provided and set it up.
#'
#' @param sample Seurat sample.
#' @param reduction Reduction.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_and_set_reduction <- function(sample, reduction = NULL){
# Check if the object has a reduction computed.
assertthat::assert_that(length(Seurat::Reductions(sample)) != 0,
msg = paste0(add_cross(), crayon_body("The Seurat object has no "),
crayon_key("reductions"),
crayon_body(" computed.")))
# If no reduction was provided by the user.
if (is.null(reduction)){
# Select umap if computed.
if ("umap" %in% Seurat::Reductions(sample)){
reduction <- "umap"
} else {
# Select the last computed one.
reduction <- Seurat::Reductions(sample)[length(Seurat::Reductions(sample))]
}
# If the user provided a value for reduction.
} else if (!(is.null(reduction))){
# Check if the provided reduction is in the list.
assertthat::assert_that(reduction %in% Seurat::Reductions(sample),
msg = paste0(add_cross(), crayon_body("The provided "),
crayon_key("reduction"),
crayon_body(" could not be found in the object: "),
crayon_key(reduction),
crayon_body(".")))
}
return(reduction)
}
#' Check the provided dimensions and set them up.
#'
#' @param sample Seurat object.
#' @param reduction Provided reduction.
#' @param dims Provided dimensions.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_and_set_dimensions <- function(sample, reduction = NULL, dims = NULL){
# If reduction is null, select the last computed one.
if (is.null(reduction)){
reduction <- Seurat::Reductions(sample)[length(Seurat::Reductions(sample))]
}
# Check that the dimensions is a 2 item vector.
if (!is.null(dims)){
assertthat::assert_that(length(dims) == 2,
msg = paste0(add_cross(), crayon_body("You need to provide a vector of "),
crayon_key("two values"),
crayon_body(" to "),
crayon_key("dims"),
crayon_body(".")))
# Check that at least 2 dimensions are present.
aval_dims <- length(colnames(Seurat::Embeddings(sample[[reduction]])))
assertthat::assert_that(aval_dims >= 2,
msg = paste0(add_cross(), crayon_body("There need to be at least "),
crayon_key("two available dimensions"),
crayon_body(" computed.")))
# Check that the dimensions are integers.
null_check <- is.null(dims[1]) & is.null(dims[2])
integer_check <- is.numeric(dims[1]) & is.numeric(dims[1])
assertthat::assert_that(base::isFALSE(null_check) & isTRUE(integer_check),
msg = paste0(add_cross(), crayon_body("The dimensions provided to "),
crayon_key("dims"),
crayon_body(" need to be of class "),
crayon_key("numeric"),
crayon_body(".")))
# Check that the dimensions are in the requested embedding.
assertthat::assert_that(dims[1] %in% seq_len(aval_dims) & dims[2] %in% seq_len(aval_dims),
msg = paste0(add_cross(), crayon_body("The dimensions provided to "),
crayon_key("dims"),
crayon_body(" could not be found in the following reduction: "),
crayon_key(reduction),
crayon_body(".")))
} else {
# If no dimensions were provided, fall back to first and second.
dims <- c(1, 2)
}
return(dims)
}
#' Check and set the provided assay.
#'
#' @param sample Seurat object.
#' @param assay Provided assay.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_and_set_assay <- function(sample, assay = NULL){
# Check that at least one assay is computed.
assertthat::assert_that(length(Seurat::Assays(sample)) != 0,
msg = paste0(add_cross(), crayon_body("There must be at least "),
crayon_key("one computed assay"),
crayon_body(" in the Seurat object.")))
# If assay is null, set it to the active one.
if (is.null(assay)){
assay <- Seurat::DefaultAssay(sample)
} else {
# Check if the assay is a character.
assertthat::assert_that(is.character(assay),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("assay"),
crayon_body(" needs to of class "),
crayon_key("character"),
crayon_body(".")))
# Check that the assay is in the available assays.
aval_assays <- Seurat::Assays(sample)
assertthat::assert_that(assay %in% aval_assays,
msg = paste0(add_cross(), crayon_body("The following "),
crayon_key("assay"),
crayon_body(" was not found: "),
crayon_key(assay),
crayon_body(".")))
}
# Set up the assay the user has defined.
if (assay != Seurat::DefaultAssay(sample)){
Seurat::DefaultAssay(sample) <- assay
}
return(list("sample" = sample,
"assay" = assay))
}
#' Check a parameter for a given class.
#'
#' @param parameters List of named parameters to test.
#' @param required_type Name of the required class.
#' @param test_function Testing function.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_type <- function(parameters, required_type, test_function){
for(parameter_name in names(parameters)){
# Get each individual parameter from the list.
parameter <- parameters[[parameter_name]]
# Cases in which the user has to provide a vector.
# Check if the parameter is not NULL already.
if (!(is.null(parameter))){
# For each parameter in the vector.
for (item in parameter){
# If not null.
if (!(is.null(item))){
# If not NA, if the testing function fails, report it.
if (sum(!(is.na(item))) > 0){
assertthat::assert_that(sum(test_function(item)) > 0,
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key(parameter_name),
crayon_body(" needs to be of class "),
crayon_key(required_type),
crayon_body(".")))
}
}
}
}
}
}
#' Check the slots.
#'
#' @param slot Slot provided.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_and_set_slot <- function(slot){
if (is.null(slot)){
slot <- "data"
} else {
assertthat::assert_that(slot %in% c("counts", "data", "scale.data"),
msg = paste0(crayon_body("Parameter "),
crayon_key("slots"),
crayon_body(" needs to be either "),
crayon_key("counts"),
crayon_body(", "),
crayon_key("data"),
crayon_body(", or "),
crayon_key("scale.data"),
crayon_body(".")))
}
return(slot)
}
#' Compute the order of the plotted bars for do_BarPlot.
#'
#' @param sample Seurat object.
#' @param feature Feature to plot.
#' @param group.by Feature to group the output by.
#' @param order Whether to arrange the values.
#' @param order.by Unique value in group.by to reorder labels in descending order.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
compute_factor_levels <- function(sample, feature, position, group.by = NULL, order = FALSE, order.by = FALSE, assay = "SCT", slot = "data"){
`%>%` <- magrittr::`%>%`
assertthat::assert_that(position %in% c("stack", "fill"),
msg = paste0(add_cross(), crayon_body("Parameter "),
crayon_key("position"),
crayon_body(" needs to be either "),
crayon_key("stack"),
crayon_body(" or "),
crayon_key("fill"),
crayon_body(".")))
if (is.null(group.by)){
sample@meta.data[, "group.by"] <- sample@active.ident
} else {
sample@meta.data[, "group.by"] <- sample@meta.data[, group.by]
}
group.by <- "group.by"
if (base::isFALSE(order)){
factor_levels <- as.character(rev(sort(unique(sample@meta.data[, group.by]))))
} else if (isTRUE(order)){
factor_levels <- get_data_column_in_context(sample = sample,
feature = feature,
group.by = group.by,
assay = assay,
slot = slot) %>%
dplyr::group_by(.data$group.by) %>%
dplyr::summarise("value" = if(is.double(.data$feature)){dplyr::across(.cols = dplyr::all_of("feature"), mean)} else {"feature" <- dplyr::n()}) %>%
dplyr::mutate("feature" = if (position == "fill") {.data$value / sum(.data$value)} else {.data$value}) %>%
dplyr::arrange(dplyr::desc(.data$feature)) %>%
dplyr::pull(.data$group.by) %>%
as.character()
}
return(factor_levels)
}
#' Check length of parameters compared to features.
#'
#' @param vector_of_parameters Vector of parameters to test.
#' @param vector_of_features Vector of features to test against.
#' @param parameters_name Name of the parameters variable.
#' @param features_name Name of the features variable.
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_length <- function(vector_of_parameters,
vector_of_features,
parameters_name,
features_name){
assertthat::assert_that(length(vector_of_parameters) == length(vector_of_features),
msg = paste0(add_cross(), crayon_body("The length of "),
crayon_key(parameters_name),
crayon_body(" is not equal to the length of "),
crayon_key(features_name),
crayon_body(".")))
}
#' Add viridis color scale while suppressing the warning that comes with adding a second scale.
#'
#' @param p GGplot2 plot.
#' @param num_plots Number of plots.
#' @param function_use Coloring function to use.
#' @param scale Name of the scale. Either fill or color.
#' @param limits Whether to put limits.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
add_scale <- function(p, scale, function_use, num_plots = 1, limits = NULL){
if (scale == "color"){scale <- "colour"}
# Compute the number of plots in this object (maybe a more efficient solution exists).
if (num_plots == 1){
# Find the index in which the scale is stored.
# Adapted from: https://stackoverflow.com/a/46003178
x <- which(vapply(p$scales$scales, function(x){scale %in% x$aesthetics}, FUN.VALUE = logical(1)))
# Remove it only if it exists.
if (!identical(x, integer(0))) {
p$scales$scales[[x]] <- NULL
}
} else {
for (i in seq(1, num_plots)){
# Find the index in which the scale is stored.
# Adapted from: https://stackoverflow.com/a/46003178
x <- which(vapply(p[[i]]$scales$scales, function(x){scale %in% x$aesthetics}, FUN.VALUE = logical(1)))
# Remove it only if it exists.
if (!identical(x, integer(0))) {
p[[i]]$scales$scales[[x]] <- NULL
}
}
}
# Add the scale and now it will now show up a warning since we removed the previous scale.
p <- p & function_use
return(p)
}
#' Modify a string to wrap it around the middle point.
#'
#' @param string_to_modify
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
modify_string <- function(string_to_modify){
words <- stringr::str_split(string_to_modify, " ")[[1]]
num_words <- length(words)
middle_point <- round(num_words / 2, 0)
string_to_modify <- paste(paste(words[1:middle_point], collapse = " "), "\n",
paste(words[(middle_point + 1):num_words], collapse = " "))
return(string_to_modify)
}
#' Compute Enrichment scores using Seurat::AddModuleScore()
#'
#' @param sample Seurat object.
#' @param input_gene_list Named list of genes to compute enrichment for.
#' @param verbose Verbose output.
#' @param nbin Number of bins.
#' @param ctrl Number of control genes.
#' @param norm_data Whether to 0-1 normalize the data
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
compute_enrichment_scores <- function(sample,
input_gene_list,
verbose = FALSE,
nbin = 24,
ctrl = 100,
assay = NULL,
slot = NULL,
flavor = "Seurat",
ncores = 1,
storeRanks = TRUE,
norm_data = FALSE){
`%>%` <- magrittr::`%>%`
# Checks for UCell.
if (flavor == "UCell"){
R_version <- paste0(R.version$major, ".", R.version$minor)
assertthat::assert_that(R_version >= "4.2.0",
msg = paste0(crayon_body("To run "),
crayon_key("UCell scoring"),
crayon_body(", R version "),
crayon_key("4.2.0"),
crayon_body(" is required. Please select "),
crayon_key("flavor = 'Seurat'"),
crayon_body(" if you are running a lower version.")))
if (!requireNamespace("UCell", quietly = TRUE)) {
# nocov start
stop(paste0(add_cross(), crayon_body("Package "), crayon_key("UCell"), crayon_body(" must be installed to run UCell scoring.")), call. = FALSE)
# nocov end
}
}
if (!is.list(input_gene_list) & is.character(input_gene_list)){
input_gene_list <- list("Input" = input_gene_list)
}
for (celltype in names(input_gene_list)){
list_markers <- list(input_gene_list[[celltype]])
if (flavor == "Seurat"){
# Compute Seurat AddModuleScore as well.
if (verbose){
sample <- Seurat::AddModuleScore(sample,
list_markers,
name = celltype,
search = TRUE,
verbose = TRUE,
nbin = nbin,
ctrl = ctrl,
assay = assay)
} else {
sample <- suppressMessages(suppressWarnings(Seurat::AddModuleScore(sample,
list_markers,
name = celltype,
search = TRUE,
verbose = FALSE,
nbin = nbin,
ctrl = ctrl,
assay = assay)))
}
# Retrieve the scores.
col_name <- stringr::str_replace_all(paste0(celltype, "1"), " ", ".")
col_name <- stringr::str_replace_all(col_name, "-", ".")
col_name <- stringr::str_replace_all(col_name, "\\+", ".")
# Modify the name that Seurat::AddModuleScore gives by default.
sample@meta.data[, celltype] <- sample@meta.data[, col_name]
# Remove old metadata.
sample@meta.data[, col_name] <- NULL
}
}
if (flavor == "UCell"){
list.names <- NULL
for (celltype in names(input_gene_list)){
col_name <- celltype
col_name <- stringr::str_replace_all(col_name, "-", ">")
col_name <- stringr::str_replace_all(col_name, " ", "_")
col_name <- stringr::str_replace_all(col_name, "\\+", ".")
list.names <- append(list.names, col_name)
}
list.originals <- names(input_gene_list)
names(input_gene_list) <- list.names
sample <- UCell::AddModuleScore_UCell(obj = sample,
features = input_gene_list,
assay = assay,
slot = if (is.null(slot)){"data"} else {slot},
name = "",
ncores = ncores,
storeRanks = storeRanks)
for (i in seq_along(list.names)){
old.name <- list.originals[i]
mod.name <- list.names[i]
# Modify the name that Seurat::AddModuleScore gives by default.
sample@meta.data[, old.name] <- sample@meta.data[, mod.name]
# Remove old metadata.
if (old.name != mod.name){
# nocov start
sample@meta.data[, mod.name] <- NULL
# nocov end
}
}
}
if (isTRUE(norm_data)){
# Compute a 0-1 normalization.
for (name in names(input_gene_list)){
sample@meta.data[, name] <- zero_one_norm(sample@meta.data[, name])
}
}
return(sample)
}
#' Modify the aspect of the legend.
#'
#' @param p Plot.
#' @param legend.aes Character. Either color or fill.
#' @param legend.type Character. Type of legend to display. One of: normal, colorbar.
#' @param legend.position Position of the legend in the plot. Will only work if legend is set to TRUE.
#' @param legend.framewidth,legend.tickwidth Width of the lines of the box in the legend.
#' @param legend.framecolor,legend.tickcolor Color of the lines of the box in the legend.
#' @param legend.length,legend.width Length and width of the legend. Will adjust automatically depending on legend side.
#' @param legend.title Character. Title for the legend.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
modify_continuous_legend <- function(p,
legend.aes,
legend.type,
legend.position,
legend.length,
legend.width,
legend.framecolor,
legend.tickcolor,
legend.tickwidth,
legend.framewidth,
legend.title = NULL){
# Define legend parameters. Width and height values will change depending on the legend orientation.
if (legend.position %in% c("top", "bottom", "none")){
legend.barwidth <- legend.length
legend.barheight <- legend.width
} else if (legend.position %in% c("left", "right")){
legend.barwidth <- legend.width
legend.barheight <- legend.length
}
legend.title <- if (is.null(legend.title)){ggplot2::waiver()} else {legend.title}
if (legend.aes == "color" | legend.aes == "colour"){
if (legend.type == "normal"){
p <- p +
ggplot2::guides(color = ggplot2::guide_colorbar(title = legend.title,
title.position = "top",
title.hjust = 0.5))
} else if (legend.type == "colorbar"){
p <- p +
ggplot2::guides(color = ggplot2::guide_colorbar(title = legend.title,
title.position = "top",
barwidth = legend.barwidth,
barheight = legend.barheight,
title.hjust = 0.5,
ticks.linewidth = legend.tickwidth,
frame.linewidth = legend.framewidth,
frame.colour = legend.framecolor,
ticks.colour = legend.tickcolor))
}
} else if (legend.aes == "fill"){
if (legend.type == "normal"){
p <- p +
ggplot2::guides(fill = ggplot2::guide_colorbar(title = legend.title,
title.position = "top",
title.hjust = 0.5))
} else if (legend.type == "colorbar"){
p <- p +
ggplot2::guides(fill = ggplot2::guide_colorbar(title = legend.title,
title.position = "top",
barwidth = legend.barwidth,
barheight = legend.barheight,
title.hjust = 0.5,
ticks.linewidth = legend.tickwidth,
frame.linewidth = legend.framewidth,
frame.colour = legend.framecolor,
ticks.colour = legend.tickcolor))
}
}
return(p)
}
#' Return a column with the desired values of a feature per cell.
#'
#' @param sample Seurat object.
#' @param feature Feature to retrieve data.
#' @param assay Assay to pull data from.
#' @param slot Slot from the assay to pull data from.
#'
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
get_data_column <- function(sample,
feature,
assay,
slot){
`%>%` <- magrittr::`%>%`
dim_colnames <- NULL
for(red in Seurat::Reductions(object = sample)){
col.names <- colnames(sample@reductions[[red]][[]])
dim_colnames <- append(dim_colnames, col.names)
if (feature %in% col.names){
# Get the reduction in which the feature is, if this is the case.
reduction <- red
}
}
if (isTRUE(feature %in% colnames(sample@meta.data))){
feature_column <- sample@meta.data %>%
dplyr::select(dplyr::all_of(c(feature))) %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::rename("feature" = dplyr::all_of(c(feature)))
} else if (isTRUE(feature %in% rownames(sample))){
# Patch for New Seurat versions.
if (utils::packageVersion("Seurat") < "5.0.0"){
feature_column <- SeuratObject::GetAssayData(object = sample,
assay = assay,
slot = slot)[feature, , drop = FALSE]
} else {
feature_column <- SeuratObject::GetAssayData(object = sample,
assay = assay,
layer = slot)[feature, , drop = FALSE]
}
feature_column <- feature_column %>%
as.matrix() %>%
t() %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::rename("feature" = dplyr::all_of(c(feature)))
} else if (isTRUE(feature %in% dim_colnames)){
feature_column <- sample@reductions[[reduction]][[]][, feature, drop = FALSE] %>%
as.data.frame() %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::rename("feature" = dplyr::all_of(c(feature)))
}
return(feature_column)
}
#' Return a column with the desired values of a feature per cell.
#'
#' @param sample Seurat object.
#' @param feature Feature to retrieve data.
#' @param assay Assay to pull data from.
#' @param group.by Parameter used later on for grouping.
#' @param split.by Parameter used later on for splitting.
#' @param slot Slot from the assay to pull data from.
#'
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
get_data_column_in_context <- function(sample,
feature,
assay,
slot,
group.by = NULL,
split.by = NULL){
`%>%` <- magrittr::`%>%`
if (is.null(group.by)){
sample@meta.data[, "group.by"] <- sample@active.ident
} else {
sample@meta.data[, "group.by"] <- sample@meta.data[, group.by]
}
group.by <- "group.by"
vars <- c("cell", "group.by")
if (!is.null(split.by)){
sample@meta.data[, "split.by"] <- sample@meta.data[, split.by]
vars <- c(vars, "split.by")
}
data <- sample@meta.data %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::select(dplyr::all_of(vars)) %>%
dplyr::left_join(y = get_data_column(sample = sample,
feature = feature,
assay = assay,
slot = slot),
by = "cell") %>%
tibble::as_tibble()
return(data)
}
#' Check parameters.
#'
#' @param parameter Parameter to check
#' @param parameter_name Name of the parameter.
#'
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_parameters <- function(parameter,
parameter_name){
if (parameter_name == "font.type"){
# Check font.type.
assertthat::assert_that(parameter %in% c("sans", "serif", "mono"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("sans"),
crayon_body(", "),
crayon_key("serif"),
crayon_body(", "),
crayon_key("mono"),
crayon_body(".")))
} else if (parameter_name == "legend.type"){
# Check the legend.type.
assertthat::assert_that(parameter %in% c("normal", "colorbar"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("normal"),
crayon_body(", "),
crayon_key("colorbar"),
crayon_body(".")))
} else if (parameter_name == "legend.position"){
# Check the legend.position.
assertthat::assert_that(parameter %in% c("top", "bottom", "left", "right", "none"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("top"),
crayon_body(", "),
crayon_key("bottom"),
crayon_body(", "),
crayon_key("left"),
crayon_body(", "),
crayon_key("right"),
crayon_body(", "),
crayon_key("none"),
crayon_body(".")))
} else if (parameter_name == "marginal.type"){
# Check marginal.type.
assertthat::assert_that(parameter %in% c("density", "histogram", "boxplot", "violin", "densigram"),
msg = paste0(crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("density"),
crayon_body(", "),
crayon_key("histogram"),
crayon_body(", "),
crayon_key("boxplot"),
crayon_body(", "),
crayon_key("violin"),
crayon_body(", "),
crayon_key("densigram"),
crayon_body(".")))
} else if (parameter_name == "viridis.direction"){
assertthat::assert_that(parameter %in% c(1, -1),
msg = paste0(crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("1"),
crayon_body(", "),
crayon_key("-1"),
crayon_body(".")))
} else if (parameter_name == "sequential.direction"){
assertthat::assert_that(parameter %in% c(1, -1),
msg = paste0(crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("1"),
crayon_body(", "),
crayon_key("-1"),
crayon_body(".")))
} else if (parameter_name == "diverging.direction"){
assertthat::assert_that(parameter %in% c(1, -1),
msg = paste0(crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("1"),
crayon_body(", "),
crayon_key("-1"),
crayon_body(".")))
} else if (parameter_name == "viridis.palette"){
viridis_options <- c("A", "B", "C", "D", "E", "F", "G", "H", "magma", "inferno", "plasma", "viridis", "cividis", "rocket", "mako", "turbo")
assertthat::assert_that(parameter %in% viridis_options,
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("A"),
crayon_body(", "),
crayon_key("B"),
crayon_body(", "),
crayon_key("C"),
crayon_body(", "),
crayon_key("D"),
crayon_body(", "),
crayon_key("E"),
crayon_body(", "),
crayon_key("F"),
crayon_body(", "),
crayon_key("G"),
crayon_body(", "),
crayon_key("H"),
crayon_body(", "),
crayon_key("magma"),
crayon_body(", "),
crayon_key("inferno"),
crayon_body(", "),
crayon_key("plasma"),
crayon_body(", "),
crayon_key("viridis"),
crayon_body(", "),
crayon_key("cividis"),
crayon_body(", "),
crayon_key("rocket"),
crayon_body(", "),
crayon_key("mako"),
crayon_body(", "),
crayon_key("turbo"),
crayon_body(".")))
} else if (parameter_name == "grid.type"){
assertthat::assert_that(parameter %in% c("blank", "solid", "dashed", "dotted", "dotdash", "longdash", "twodash"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("blank"),
crayon_body(", "),
crayon_key("solid"),
crayon_body(", "),
crayon_key("dashed"),
crayon_body(", "),
crayon_key("dotted"),
crayon_body(", "),
crayon_key("dotdash"),
crayon_body(", "),
crayon_key("longdash"),
crayon_body(", "),
crayon_key("twodash"),
crayon_body(".")))
} else if (parameter_name == "direction.type"){
for (item in parameter){
assertthat::assert_that(item %in% c("diffHeight", "arrows"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("diffHeight"),
crayon_body(", "),
crayon_key("arrows"),
crayon_body(", "),
crayon_key("both"),
crayon_body(".")))
}
} else if (parameter_name == "self.link"){
assertthat::assert_that(parameter %in% c(1, 2),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("1"),
crayon_body(", "),
crayon_key("2"),
crayon_body(".")))
} else if (parameter_name == "directional"){
assertthat::assert_that(parameter %in% c(0, 1, 2, -1),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("0"),
crayon_body(", "),
crayon_key("1"),
crayon_body(", "),
crayon_key("2"),
crayon_body(", "),
crayon_key("-1"),
crayon_body(".")))
} else if (parameter_name == "link.arr.type"){
assertthat::assert_that(parameter %in% c("big.arrow", "triangle"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("big.arrow"),
crayon_body(", "),
crayon_key("triangle"),
crayon_body(".")))
} else if (parameter_name == "alignment"){
assertthat::assert_that(parameter %in% c("default", "vertical", "horizontal"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("vertical"),
crayon_body(", "),
crayon_key("horizontal"),
crayon_body(".")))
} else if (parameter_name == "alpha.highlight"){
assertthat::assert_that(parameter %in% c(seq(1, 99), "FF"),
msg = paste0(add_cross(), crayon_body("Please provide either "),
crayon_key("FF"),
crayon_body(" or a number between "),
crayon_key("1"),
crayon_body(" and "),
crayon_key("99"),
crayon_body(" to "),
crayon_key(parameter_name),
crayon_body(".")))
} else if (parameter_name == "scale_type"){
assertthat::assert_that(parameter %in% c("categorical", "continuous"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("categorical"),
crayon_body(", "),
crayon_key("continuous"),
crayon_body(".")))
} else if (parameter_name == "axis.text.x.angle"){
assertthat::assert_that(parameter %in% c(0, 45, 90),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("0"),
crayon_body(", "),
crayon_key("45"),
crayon_body(", "),
crayon_key("90"),
crayon_body(".")))
} else if (parameter_name == "contour.lineend"){
assertthat::assert_that(parameter %in% c("round", "butt", "square"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("round"),
crayon_body(", "),
crayon_key("butt"),
crayon_body(", "),
crayon_key("square"),
crayon_body(".")))
} else if (parameter_name == "contour.linejoin"){
assertthat::assert_that(parameter %in% c("round", "mitre", "bevel"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("round"),
crayon_body(", "),
crayon_key("mitre"),
crayon_body(", "),
crayon_key("bevel"),
crayon_body(".")))
} else if (parameter_name == "contour.position"){
assertthat::assert_that(parameter %in% c("bottom", "top"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("top"),
crayon_body(", "),
crayon_key("bottom"),
crayon_body(".")))
} else if (parameter_name == "flavor"){
assertthat::assert_that(parameter %in% c("Seurat", "UCell"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("Seurat"),
crayon_body(", "),
crayon_key("UCell"),
crayon_body(".")))
} else if (parameter_name == "database"){
assertthat::assert_that(parameter %in% c("GO", "KEGG"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("GO"),
crayon_body(", "),
crayon_key("KEGG"),
crayon_body(".")))
} else if (parameter_name == "GO_ontology"){
assertthat::assert_that(parameter %in% c("BP", "MF", "CC"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("BP"),
crayon_body(", "),
crayon_key("MF"),
crayon_body(", "),
crayon_key("CC"),
crayon_body(".")))
} else if (parameter_name == "pAdjustMethod"){
assertthat::assert_that(parameter %in% c("holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
crayon_key("holm"),
crayon_body(", "),
crayon_key("hochberg"),
crayon_body(", "),
crayon_key("bonferroni"),
crayon_body(", "),
crayon_key("BH"),
crayon_body(", "),
crayon_key("BY"),
crayon_body(", "),
crayon_key("fdr"),
crayon_body(", "),
crayon_key("none"),
crayon_body(".")))
} else if (parameter_name == "number.breaks"){
assertthat::assert_that(parameter >= 2,
msg = paste0(add_cross(), crayon_body("Please provide a value higher or equal to "),
crayon_key("2"),
crayon_body(" to "),
crayon_key(parameter_name),
crayon_body(".")))
} else if (parameter_name == "border.density"){
assertthat::assert_that(parameter >= 0 & parameter <= 1,
msg = paste0(add_cross(), crayon_body("Please provide a value between "),
crayon_key("0"),
crayon_body(" and "),
crayon_key("1"),
crayon_body(" to "),
crayon_key(parameter_name),
crayon_body(".")))
} else if (parameter_name == "diverging.palette"){
assertthat::assert_that(parameter %in% c("BrBG", "PiYG", "PRGn", "PuOr", "RdBu", "RdGy", "RdYlBu", "RdYlGn", "Spectral"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
paste(vapply(c("BrBG", "PiYG", "PRGn", "PuOr", "RdBu", "RdGy", "RdYlBu", "RdYlGn", "Spectral"), crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(".")))
} else if (parameter_name == "sequential.palette"){
assertthat::assert_that(parameter %in% c("Blues", "BuGn", "BuPu", "GnBu", "Greens", "Greys", "Oranges", "OrRd", "PuBu", "PuBuGn", "PuRd", "Purples", "RdPu", "Reds", "YlGn", "YlGnBu", "YlOrBr", "YlOrRd"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
paste(vapply(c("Blues", "BuGn", "BuPu", "GnBu", "Greens", "Greys", "Oranges", "OrRd", "PuBu", "PuBuGn", "PuRd", "Purples", "RdPu", "Reds", "YlGn", "YlGnBu", "YlOrBr", "YlOrRd"), crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(".")))
} else if (parameter_name %in% c("plot.title.face", "plot.subtitle.face", "plot.caption.face", "axis.title.face", "axis.text.face", "legend.title.face", "legend.text.face", "strip.text.face")){
assertthat::assert_that(parameter %in% c("plain", "italic", "bold", "bold.italic"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
paste(vapply(c("plain", "italic", "bold", "bold.italic"), crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(".")))
} else if (parameter_name %in% c("symmetry.type")){
assertthat::assert_that(parameter %in% c("absolute", "centered"),
msg = paste0(add_cross(), crayon_body("Please provide one of the following to "),
crayon_key(parameter_name),
crayon_body(": "),
paste(vapply(c("absolute", "centered"), crayon_key, FUN.VALUE = character(1)), collapse = crayon_body(", ")),
crayon_body(".")))
}
}
#' Helper for do_AlluvialPlot.
#'
#' @param data Data to plot.
#' @param vars.use Names of the variables.
#'
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
prepare_ggplot_alluvial_plot <- function(data,
vars.use){
items <- length(vars.use)
`%>%` <- magrittr::`%>%`
assertthat::assert_that(items <= 10,
msg = paste0(add_cross(), crayon_body("Please provide, in between "),
crayon_key("first_group"),
crayon_body(", "),
crayon_key("middle_groups"),
crayon_body(" and "),
crayon_key("last_group"),
crayon_body(" only up to "),
crayon_key("ten"),
crayon_body("different unique elements.")))
if (items == 2){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]]))
} else if (items == 3){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]]))
} else if (items == 4){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]]))
} else if (items == 5){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]],
axis5 = data[[vars.use[5]]]))
} else if (items == 6){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]],
axis5 = data[[vars.use[5]]],
axis6 = data[[vars.use[6]]]))
} else if (items == 7){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]],
axis5 = data[[vars.use[5]]],
axis6 = data[[vars.use[6]]],
axis7 = data[[vars.use[7]]]))
} else if (items == 8) {
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]],
axis5 = data[[vars.use[5]]],
axis6 = data[[vars.use[6]]],
axis7 = data[[vars.use[7]]],
axis8 = data[[vars.use[8]]]))
} else if (items == 9){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]],
axis5 = data[[vars.use[5]]],
axis6 = data[[vars.use[6]]],
axis7 = data[[vars.use[7]]],
axis8 = data[[vars.use[8]]],
axis9 = data[[vars.use[9]]]))
} else if (items == 10){
p <- data %>%
ggplot2::ggplot(mapping = ggplot2::aes(y = data$n,
axis1 = data[[vars.use[1]]],
axis2 = data[[vars.use[2]]],
axis3 = data[[vars.use[3]]],
axis4 = data[[vars.use[4]]],
axis5 = data[[vars.use[5]]],
axis6 = data[[vars.use[6]]],
axis7 = data[[vars.use[7]]],
axis8 = data[[vars.use[8]]],
axis9 = data[[vars.use[9]]],
axis10 = data[[vars.use[10]]]))
}
return(p)
}
#' Helper for axis.text.x.angle.
#'
#' @param angle Angle of rotation.
#' @param flip Whether the plot if flipped or not.
#'
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
get_axis_parameters <- function(angle,
flip){
if (isTRUE(flip)){
if (angle == 0){
out <- list("angle" = angle,
"hjust" = 0.5,
"vjust" = 0.5)
} else if (angle == 45){
out <- list("angle" = angle,
"hjust" = 1,
"vjust" = 1)
} else if (angle == 90){
out <- list("angle" = angle,
"hjust" = 0.5,
"vjust" = 0.5)
}
} else if (base::isFALSE(flip)){
if (angle == 0){
out <- list("angle" = angle,
"hjust" = 0.5,
"vjust" = 0)
} else if (angle == 45){
out <- list("angle" = angle,
"hjust" = 1,
"vjust" = 1)
} else if (angle == 90){
out <- list("angle" = angle,
"hjust" = 0.5,
"vjust" = 0.5)
}
}
return(out)
}
#' Compute UMAP layers.
#'
#' @param sample TBD
#' @param labels TBD
#' @param pt.size TBD
#' @param dot.size TBD
#' @param alpha TBD
#' @param na.value TBD
#' @param border.density TBD
#' @param border.size TBD
#' @param border.color TBD
#' @param raster TBD
#' @param raster.dpi TBD
#' @param reduction TBD
#' @param group.by TBD
#' @param split.by TBD
#' @param n TBD
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
compute_umap_layer <- function(sample,
labels,
pt.size,
dot.size = 7.5,
alpha = 1,
na.value = "grey75",
border.density = 1,
border.size,
border.color,
raster = FALSE,
raster.dpi = 1024,
reduction = "umap",
group.by = NULL,
split.by = NULL,
n = 100,
skip.density = FALSE) {
`%>%` <- magrittr::`%>%`
embeddings <- Seurat::Embeddings(sample,
reduction = reduction)[, labels, drop = FALSE] %>%
as.data.frame()
colnames(embeddings) <- c("x", "y")
# Code adapted from: https://slowkow.com/notes/ggplot2-color-by-density/
# Licensed under: CC BY-SA (compatible with GPL-3).
# Author: Kamil Slowikowski - https://slowkow.com/
# Obtain density.
if (base::isFALSE(skip.density)){
density <- MASS::kde2d(x = embeddings$x,
y = embeddings$y,
n = n)
# Find the intervals.
x.intervals <- findInterval(embeddings$x, density$x)
y.intervals <- findInterval(embeddings$y, density$y)
# Generate density vector to add to metadata.
interval_matrix <- cbind(x.intervals, y.intervals)
density_vector <- density$z[interval_matrix]
embeddings$density <- density_vector
}
# Add the group.by and split.by layers.
if (!is.null(group.by)){
embeddings <- embeddings %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = sample@meta.data %>%
dplyr::select(dplyr::all_of(c(group.by))) %>%
tibble::rownames_to_column(var = "cell"),
by = "cell") %>%
tibble::column_to_rownames(var = "cell")
colnames(embeddings) <- c(colnames(embeddings)[seq(1, (length(colnames(embeddings)) - 1))], "group.by")
if (base::isFALSE(skip.density)){
density.center.group.by <- embeddings %>%
dplyr::select(dplyr::all_of(c("x", "y", "group.by", "density"))) %>%
dplyr::group_by(.data$group.by) %>%
dplyr::mutate("filt_x_up" = stats::quantile(.data$x, 0.66),
"filt_x_down" = stats::quantile(.data$x, 0.33),
"filt_y_up" = stats::quantile(.data$y, 0.66),
"filt_y_down" = stats::quantile(.data$y, 0.33)) %>%
dplyr::filter(.data$x >= .data$filt_x_down & .data$x <= .data$filt_x_up,
.data$y >= .data$filt_y_down & .data$y <= .data$filt_y_up) %>%
dplyr::summarize("x" = mean(.data$x),
"y" = mean(.data$y))
}
}
if (!is.null(split.by)){
embeddings <- embeddings %>%
tibble::rownames_to_column(var = "cell") %>%
dplyr::left_join(y = sample@meta.data %>%
dplyr::select(dplyr::all_of(c(split.by))) %>%
tibble::rownames_to_column(var = "cell"),
by = "cell") %>%
tibble::column_to_rownames(var = "cell")
colnames(embeddings) <- c(colnames(embeddings)[seq(1, (length(colnames(embeddings)) - 1))], "split.by")
}
# Apply filtering criteria:
if (base::isFALSE(skip.density)){
embeddings <- embeddings %>%
dplyr::filter(.data$density <= stats::quantile(embeddings$density, border.density))
}
# Generate base layer.
if (base::isFALSE(raster)){
base_layer <- ggplot2::geom_point(data = embeddings,
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
colour = border.color,
size = pt.size * border.size,
show.legend = FALSE,
na.rm = TRUE)
} else {
base_layer <- scattermore::geom_scattermore(data = embeddings,
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = border.color,
size = pt.size * border.size,
stroke = pt.size / 2,
show.legend = FALSE,
pointsize = pt.size * border.size,
pixels = c(raster.dpi, raster.dpi),
na.rm = TRUE)
}
# Generate NA layer.
if (base::isFALSE(raster)){
na_layer <- ggplot2::geom_point(data = embeddings,
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
colour = na.value,
size = pt.size,
show.legend = FALSE,
na.rm = TRUE)
} else {
na_layer <- scattermore::geom_scattermore(data = embeddings,
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = na.value,
size = pt.size,
stroke = pt.size / 2,
show.legend = FALSE,
pointsize = pt.size,
pixels = c(raster.dpi, raster.dpi),
na.rm = TRUE)
}
# Generate center points layer.
out <- list()
if (!is.null(group.by) & base::isFALSE(skip.density)){
# Generate colored based layer.
if (base::isFALSE(raster)){
color_layer <- ggplot2::geom_point(data = embeddings,
mapping = ggplot2::aes(x = .data$x,
y = .data$y,
fill = .data$group.by),
color = "white",
shape = 21,
alpha = alpha,
size = (pt.size * border.size) + 4,
stroke = 0,
show.legend = TRUE,
na.rm = TRUE)
} else {
color_layer <- scattermore::geom_scattermore(data = embeddings,
mapping = ggplot2::aes(x = .data$x,
y = .data$y,
fill = .data$group.by),
size = (pt.size * border.size) + 4,
alpha = alpha,
stroke = pt.size / 2,
show.legend = TRUE,
pointsize = pt.size * border.size,
pixels = c(raster.dpi, raster.dpi),
na.rm = TRUE)
}
out[["color_layer"]] <- color_layer
center_layer_2 <- ggplot2::geom_point(data = density.center.group.by,
mapping = ggplot2::aes(x = .data$x,
y = .data$y),
color = "black",
size = pt.size * dot.size)
center_layer <- ggplot2::geom_point(data = density.center.group.by,
mapping = ggplot2::aes(x = .data$x,
y = .data$y,
fill = .data$group.by),
color = "white",
shape = 21,
size = pt.size * (dot.size - 2),
stroke = 1.5)
center_layers <- list("center_layer_2" = center_layer_2,
"center_layer_1" = center_layer)
out[["center_layers"]] <- center_layers
}
out[["base_layer"]] <- base_layer
out[["na_layer"]] <- na_layer
out[["embeddings"]] <- embeddings
return(out)
}
#
#
#' Duplicate secondary categorical axis.
#' From: https://github.com/tidyverse/ggplot2/issues/3171
#' @param label_trans Labels to send to the secondary axis.
#' @param ... Other
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
guide_axis_label_trans <- function(label_trans = identity, ...) {
axis_guide <- ggplot2::guide_axis(...)
axis_guide$label_trans <- rlang::as_function(label_trans)
class(axis_guide) <- c("guide_axis_trans", class(axis_guide))
axis_guide
}
#' Handle axis theme parameters
#'
#' @param flip TBD
#' @param counter TBD
#' @param group.by TBD
#' @param group TBD
#' @param xlab TBD
#' @param ylab TBD
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
handle_axis <- function(flip,
counter,
group.by,
group,
axis.text.x.angle,
plot.title.face,
plot.subtitle.face,
plot.caption.face,
axis.title.face,
axis.text.face,
legend.title.face,
legend.text.face){
# Set axis theme parameters.
if (base::isFALSE(flip)){
# Strips
if (counter == length(group.by)){
strip.background <- ggplot2::element_blank()
strip.clip <- "off"
strip.text <- ggplot2::element_text(face = "bold", color = "black")
legend.position <- "none"
} else if (counter == 1) {
legend.position <- "bottom"
strip.background <- ggplot2::element_blank()
strip.clip <- "off"
strip.text <- ggplot2::element_blank()
} else {
strip.background <- ggplot2::element_blank()
strip.clip <- "off"
strip.text <- ggplot2::element_blank()
legend.position <- "none"
}
if (counter == 1){
axis.ticks.x.bottom <- ggplot2::element_line(color = "black")
axis.ticks.x.top <- ggplot2::element_blank()
axis.ticks.y.right <- ggplot2::element_line(color = "black")
axis.ticks.y.left <- ggplot2::element_blank()
axis.text.x.bottom <- ggplot2::element_text(face = axis.text.face, color = "black",
angle = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["vjust"]])
axis.text.x.top <- ggplot2::element_blank()
axis.text.y.right <- ggplot2::element_text(face = axis.text.face, color = "black", hjust = 0)
axis.text.y.left <- ggplot2::element_blank()
if (length(group.by) > 1){
axis.title.x.top <- ggplot2::element_blank()
axis.title.x.bottom <- ggplot2::element_blank()
} else {
axis.title.x.top <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 0,
vjust = 0.5,
hjust = 0.5)
axis.title.x.bottom <- ggplot2::element_blank()
}
axis.title.y.left <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 90,
hjust = 0.5,
vjust = 0.5)
axis.title.y.right <- ggplot2::element_blank()
} else {
axis.ticks.x.bottom <- ggplot2::element_blank()
axis.ticks.x.top <- ggplot2::element_blank()
axis.ticks.y.right <- ggplot2::element_line(color = "black")
axis.ticks.y.left <- ggplot2::element_blank()
axis.text.x.top <- ggplot2::element_blank()
axis.text.x.bottom <- ggplot2::element_blank()
axis.text.y.right <- ggplot2::element_text(face = axis.text.face, color = "black", hjust = 0)
axis.text.y.left <- ggplot2::element_blank()
if (length(group.by) > 1){
axis.title.x.top <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 0,
vjust = 0.5,
hjust = 0.5)
axis.title.x.bottom <- ggplot2::element_blank()
} else {
axis.title.x.top <- ggplot2::element_blank()
axis.title.x.bottom <- ggplot2::element_blank()
}
axis.title.y.left <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 90,
hjust = 0.5,
vjust = 0.5)
axis.title.y.right <- ggplot2::element_blank()
}
} else {
# Strips and legend.
if (counter == 1){
strip.background <- ggplot2::element_blank()
strip.clip <- "off"
strip.text <- ggplot2::element_text(face = "bold", color = "black")
legend.position <- "none"
} else if (counter == length(group.by)){
legend.position <- "right"
strip.background <- ggplot2::element_blank()
strip.clip <- "off"
strip.text <- ggplot2::element_blank()
} else {
strip.background <- ggplot2::element_blank()
strip.clip <- "off"
strip.text <- ggplot2::element_blank()
legend.position <- "none"
}
if (counter == 1){
axis.ticks.x.bottom <- ggplot2::element_line(color = "black")
axis.ticks.x.top <- ggplot2::element_blank()
axis.text.x.bottom <- ggplot2::element_text(face = axis.text.face, color = "black",
angle = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["vjust"]])
axis.text.x.top <- ggplot2::element_blank()
axis.title.x.top <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 0,
hjust = 0.5,
vjust = 0.5)
axis.title.x.bottom <- ggplot2::element_blank()
if (length(group.by) == 1){
axis.ticks.y.left <- ggplot2::element_blank()
axis.ticks.y.right <- ggplot2::element_line(color = "black")
axis.text.y.left <- ggplot2::element_blank()
axis.text.y.right <- ggplot2::element_text(color = "black", face = axis.text.face, hjust = 0)
axis.title.y.left <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 90,
vjust = 0.5,
hjust = 0.5)
axis.title.y.right <- ggplot2::element_blank()
} else {
axis.ticks.y.left <- ggplot2::element_blank()
axis.ticks.y.right <- ggplot2::element_blank()
axis.text.y.left <- ggplot2::element_blank()
axis.text.y.right <- ggplot2::element_blank()
axis.title.y.left <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 90,
vjust = 0.5,
hjust = 0.5)
axis.title.y.right <- ggplot2::element_blank()
}
} else {
axis.ticks.x.bottom <- ggplot2::element_line(color = "black")
axis.ticks.x.top <- ggplot2::element_blank()
axis.text.x.bottom <- ggplot2::element_text(face = axis.text.face, color = "black",
angle = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["angle"]],
hjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["hjust"]],
vjust = get_axis_parameters(angle = axis.text.x.angle, flip = FALSE)[["vjust"]])
axis.text.x.top <- ggplot2::element_blank()
axis.title.x.top <- ggplot2::element_text(face = axis.title.face, color = "black",
angle = 0,
hjust = 0.5,
vjust = 0.5)
axis.title.x.bottom <- ggplot2::element_blank()
if (length(group.by) == counter){
axis.ticks.y.left <- ggplot2::element_blank()
axis.ticks.y.right <- ggplot2::element_line(color = "black")
axis.text.y.left <- ggplot2::element_blank()
axis.text.y.right <- ggplot2::element_text(color = "black", face = axis.text.face, hjust = 0)
axis.title.y.right <- ggplot2::element_blank()
axis.title.y.left <- ggplot2::element_blank()
} else {
axis.ticks.y.left <- ggplot2::element_blank()
axis.ticks.y.right <- ggplot2::element_blank()
axis.text.y.left <- ggplot2::element_blank()
axis.text.y.right <- ggplot2::element_blank()
axis.title.y.left <- ggplot2::element_blank()
axis.title.y.right <- ggplot2::element_blank()
}
}
}
out_list <- list("axis.ticks.x.top" = axis.ticks.x.top,
"axis.ticks.x.bottom" = axis.ticks.x.bottom,
"axis.ticks.y.left" = axis.ticks.y.left,
"axis.ticks.y.right" = axis.ticks.y.right,
"axis.text.x.bottom" = axis.text.x.bottom,
"axis.text.x.top" = axis.text.x.top,
"axis.text.y.left" = axis.text.y.left,
"axis.text.y.right" = axis.text.y.right,
"axis.title.x.bottom" = axis.title.x.bottom,
"axis.title.x.top" = axis.title.x.top,
"axis.title.y.left" = axis.title.y.left,
"axix.title.y.right" = axis.title.y.right,
"strip.background" = strip.background,
"strip.clip" = strip.clip,
"strip.text" = strip.text,
"legend.position" = legend.position)
return(out_list)
}
#' Generate a list of colors that will be used for metadata plots.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
get_SCpubr_colors <- function(){
colors <- c("#457b9d",
"#b5838d",
"#d4a276",
"#31572c",
"#354f52",
"#006d77",
"#bcb8b1",
"#d88c9a",
"#d8315b",
"#ee6c4d",
"#0c5460",
"#065a60",
"#d6ce93",
"#A88D21",
"#9a8c98",
"#6c757d",
"#00afb9",
"#38a3a5",
"#adc178",
"#bfd7b5")
return(colors)
}
#' Generate a list of colorblind-friendly colors that will be used for colorblind = TRUE plots.
#'
#' @return None
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
get_Colorblind_colors <- function(){
# Colorblind palettes from literature:
# Wong: https://www.nature.com/articles/nmeth.1618
wong.colors <- c("#000000",
"#E69F00",
"#56B4E9",
"#009E73",
"#F0E442",
"#0072B2",
"#D55E00",
"#CC79A7")
# Tol: https://personal.sron.nl/~pault/
tol.muted.colors <- c("#dddddd",
"#332288",
"#117733",
"#44AA99",
"#88CCEE",
"#DDCC77",
"#CC6677",
"#AA4499",
"#882255")
tol.bright.colors <- c("#bbbbbb",
"#4477aa",
"#218833",
"#66ccee",
"#cbbb45",
"#ee6577",
"#aa3377")
okabe.colors <- c("#000000",
"#009e73",
"#0071b2",
"#55b4e9",
"#efe441",
"#e69f00",
"#d55d00",
"#cb79a7")
# Krzywinski: https://mk.bcgsc.ca/colorblind/palettes.mhtml#projecthome
krz.8 <- c("#000000",
"#2271B2",
"#3DB7E9",
"#F748A5",
"#359B73",
"#d55e00",
"#e69f00",
"#f0e442")
krz.12 <- c("#9F0162",
"#009F81",
"#FF5AAF",
"#00FCCF",
"#8400CD",
"#008DF9",
"#00C2F9",
"#FFB2FD",
"#A40122",
"#E20134",
"#FF6E3A",
"#FFC33B")
krz.15 <- c("#68023F",
"#008169",
"#EF0096",
"#00DCB5",
"#FFCFE2",
"#003C86",
"#9400E6",
"#009FFA",
"#FF71FD",
"#7CFFFA",
"#6A0213",
"#008607",
"#F60239",
"#00E307",
"#FFDC3D")
krz.24 <- c("#003D30",
"#005745",
"#00735C",
"#009175",
"#00AF8E",
"#00CBA7",
"#00EBC1",
"#86FFDE",
"#00306F",
"#00489E",
"#005FCC",
"#0079FA",
"#009FFA",
"#00C2F9",
"#00E5F8",
"#7CFFFA",
"#004002",
"#005A01",
"#007702",
"#009503",
"#00B408",
"#00D302",
"#00F407",
"#AFFF2A")
collection <- c(wong.colors,
tol.muted.colors,
tol.bright.colors,
okabe.colors,
krz.8,
krz.12,
krz.15,
krz.24)
collection <- collection[!duplicated(collection)]
out.colors <- list("Wong" = wong.colors,
"Tol_Muted" = tol.muted.colors,
"Tol_Bright" = tol.bright.colors,
"Okabe" = okabe.colors,
"Krz8" = krz.8,
"Krz12" = krz.12,
"Krz15" = krz.15,
"Krz24" = krz.24,
"Collection" = collection)
return(out.colors)
}
#' Check the group.by parameter
#'
#' @param sample Seurat object.
#' @param group.by group.by parameter.
#' @param is.heatmap Whether the function computes a heatmap.
#'
#' @return The Seurat object.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
check_group_by <- function(sample,
group.by,
is.heatmap){
group.by.return <- NULL
if (is.null(group.by)){
assertthat::assert_that(!("Groups" %in% colnames(sample@meta.data)),
msg = paste0(add_cross(), crayon_body("Please, make sure you provide a value for "),
crayon_key("group.by"),
crayon_body(". The metadata column "),
crayon_key("Groups"),
crayon_body(" is used instead, but there is already such column in your metadata.")))
sample@meta.data[, "Groups"] <- sample@active.ident
group.by <- "Groups"
}
for (group in group.by){
assertthat::assert_that(group %in% colnames(sample@meta.data),
msg = paste0(add_cross(), crayon_body("The value provided to "),
crayon_key(paste0("group.by (", group, " | defaults to Seurat::Idents(sample) if NULL)")),
crayon_body(" is not part of the Seurat object "),
crayon_key("meta.data"),
crayon_body(".")))
assertthat::assert_that(class(sample@meta.data[, group]) %in% c("character", "factor"),
msg = paste0(add_cross(), crayon_body("The value provided to"),
crayon_key(paste0("group.by (", group, " | defaults to Seurat::Idents(sample) if NULL)")),
crayon_body(" is not a "),
crayon_key("character"),
crayon_body( "or "),
crayon_key("factor"),
crayon_body(" column in the sample"),
crayon_key("metadata of the Seurat object"),
crayon_body(".")))
if (isTRUE(is.heatmap)){
assertthat::assert_that(sum(is.na(sample@meta.data[, group])) == 0,
msg = paste0(add_warning(), crayon_body("Found "),
crayon_key("NAs"),
crayon_body(" in the metadata variable provided to "),
crayon_key(paste0("group.by (", group, " | defaults to Seurat::Idents(sample) if NULL)")),
crayon_body(". Please remove them before running the function.")))
}
group.by.return <- append(group.by.return, group)
}
return(list("sample" = sample,
"group.by" = group.by.return))
}
#' Temporal fix for DimPlots/FeaturePlots when using Assay5 and split.by
#'
#' @param sample Seurat object.
#' @param assay assay to use.
#'
#' @return The Seurat object.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
#check_Assay5 <- function(sample,
# assay = Seurat::DefaultAssay(sample)){
# if (isTRUE(methods::is(sample@assays[[assay]], "Assay5"))){
# suppressWarnings(sample@assays[[assay]] <- methods::as(sample@assays[[assay]], "Assay"))
# }
# return(sample)
#}
#' Handles the generation of continuous color palettes for the plots.
#'
#' @param name Name of the palette.
#' @param use_viridis Whether it is a viridis palette or not.
#' @param direction Direction of the color scale.
#' @param enforce_symmetry Whether it is a diverging palette or not.
#'
#' @return The colors to use.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
compute_continuous_palette <- function(name = "YlGnBu",
use_viridis = FALSE,
direction = ifelse(isTRUE(use_viridis), -1, 1),
enforce_symmetry = FALSE){
light_end <- "grey95"
dark_end <- "grey5"
if (base::isFALSE(enforce_symmetry)){
if (base::isFALSE(getOption("SCpubr.ColorPaletteEnds"))){
if (isTRUE(use_viridis)){
if (direction == 1){
colors <- c(viridis::viridis(n = 9, direction = direction, option = name))
} else if (direction == -1){
colors <- c(viridis::viridis(n = 9, direction = direction, option = name))
}
} else if (isFALSE(use_viridis)){
if (direction == 1){
colors <- c(RColorBrewer::brewer.pal(n = 9, name = name))
} else if (direction == -1){
colors <- c(rev(RColorBrewer::brewer.pal(n = 9, name = name)))
}
}
} else {
if (isTRUE(use_viridis)){
if (direction == 1){
colors <- c(dark_end, viridis::viridis(n = 9, direction = direction, option = name), light_end)
} else if (direction == -1){
colors <- c(light_end, viridis::viridis(n = 9, direction = direction, option = name), dark_end)
}
} else if (isFALSE(use_viridis)){
if (direction == 1){
colors <- c(light_end, RColorBrewer::brewer.pal(n = 9, name = name), dark_end)
} else if (direction == -1){
colors <- c(dark_end, rev(RColorBrewer::brewer.pal(n = 9, name = name)), light_end)
}
}
}
} else {
if (direction == 1){
colors <- RColorBrewer::brewer.pal(n = 11, name = name)
} else if (direction == -1){
colors <- rev(RColorBrewer::brewer.pal(n = 11, name = name))
}
}
return(colors)
}
#' Normalizes a continuous variable to comprise it between 0 to 1.
#'
#' @param x Continuous variable.
#'
#' @return A normalized variable.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
zero_one_norm <- function(x){
y <- (x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))
return(y)
}
#' Normalizes a continuous variable to comprise it between -1 to 1.
#'
#' @param x Continuous variable.
#'
#' @return A normalized variable.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
one_one_norm <- function(x){
y <- 2 * ((x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))) - 1
return(y)
}
#' Normalizes a continuous variable to comprise it between a to b.
#'
#' @param x Continuous variable.
#' @param a,b Ends of the range.
#'
#' @return A normalized variable.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
range_norm <- function(x, a, b){
y <- (b - a) * ((x - (min(x, na.rm = TRUE))) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))) + a
return(y)
}
#' Rounds up a vector of percentages to ensure they add up to 100.
#'
#' First, truncates the values and keeps the truncated values and discarded decimals stored.
#' Then, it orders the discarded decimals and adds a unit to the correspondent truncated value
#' until the summ of truncated values reaches 100.
#'
#' For exclusive use in do_WafflePlot().
#'
#' @param x Data Frame of frequencies.
#' @param group.by The grouping variable used.
#'
#' @return A rounded up vector of percentages.
#' @noRd
#' @examples
#' \donttest{
#' TBD
#' }
round_percent <- function(x,
group.by){
# Generate named vector of freqs.
x <- as.data.frame(x)
names.use <- x[, group.by]
freqs <- x$freq
names(freqs) <- names.use
# Get trunctaed values and the removed percentages.
trimmed <- trunc(freqs)
cut.percent <- rev(sort(freqs - trimmed))
# Now, order the removed percentages and, in descending order, add a unit to the trimmed values until they add up to 100.
index <- 0
while(sum(trimmed) != 100){
index <- index + 1
trimmed[names(trimmed[index])] <- trimmed[index] + 1
}
# Return the new vector of rounded percentages.
return(trimmed)
}
================================================
FILE: R/zzz.R
================================================
# Add Start-Up message.
.onAttach <- function(...) {
# nocov start
if (base::isFALSE(getOption("SCpubr.verbose"))){
return()
}
# nocov end
# Print startup message.
do_PackageReport(startup = TRUE,
extended = FALSE)
}
================================================
FILE: README.md
================================================
# SCpubr
[](https://CRAN.R-project.org/package=SCpubr)
[](https://github.com/enblacar/SCpubr/actions/workflows/R-CMD-check.yaml)
[](https://app.codecov.io/gh/enblacar/SCpubr/)
[](https://www.codefactor.io/repository/github/enblacar/scpubr/overview/main)
[](https://cran.r-project.org/package=SCpubr)
**SCpubr** provides a streamlined way of generating publication ready plots for known **S**ingle-**C**ell visualizations in a "**pub**lication **r**eady" format (**SCpubr**). This is, the aim is to automatically generate plots with the highest quality possible, that can be used right away or with minimal modifications for a research article.
## Installation
**SCpubr** can be installed via:
```r
# From CRAN - Official release:
install.packages("SCpubr")
# From GitHub - Latest stable development version:
if(!requireNamespace("devtools", quietly = TRUE)){
install.packages("devtools") # If not installed.
}
devtools::install_github("enblacar/SCpubr", ref = "v2.0.0-dev-stable")
```
By default, **SCpubr** downloads without installing any of the required dependencies. A comprehensive report of which dependencies are still missing and which functions can be run is available through:
```r
SCpubr::package_report(extended = TRUE)
```
For tutorials, check **SCpubr**'s [reference manual](https://enblacar.github.io/SCpubr-book/).
## Project Status
> **SCpubr** is now in **maintenance mode**. No new features are planned, but bug fixes and compatibility updates will continue to be provided.
Contributions from the community are very welcome! Whether it's a bug fix, documentation improvement, or a new idea — feel free to open an [issue](https://github.com/enblacar/SCpubr/issues) or submit a [pull request](https://github.com/enblacar/SCpubr/pulls). Check the [contributing guide](https://enblacar.github.io/SCpubr-book/08_appendix/02_contributing.html) for more details.
Keep track of past updates in the [NEWS page](https://github.com/enblacar/SCpubr/blob/main/NEWS.md).
## Citation
To cite `SCpubr` in your publications, please use:
```
Blanco-Carmona, E. Generating publication ready visualizations
for Single Cell transcriptomics using SCpubr. bioRxiv (2022)
doi:10.1101/2022.02.28.482303.
```
## Contact
`scpubr@gmail.com`
================================================
FILE: cran-comments.md
================================================
# Resubmission version 3.0.1
Fixed notes resulting from the previous CRAN submission.
# Submission version 3.0.1
CRAN R CMD error fixes due to deprecation of parameter in Seurat.
## `devtools` R CMD check results
There were no ERRORs, WARNINGs or NOTEs.
## `devtools` R CMD check results `_R_CHECK_DEPENDS_ONLY_` = TRUE
There were no ERRORs, WARNINGs or NOTEs.
## Using `devtools::test()`
When using first in the session, two tests return a deprecation warning:
## Downstream dependencies
No errors associated with SCpubr in downstream dependencies:
- DOtools
================================================
FILE: inst/CITATION
================================================
citHeader("To cite SCpubr in publications use:")
bibentry(
bibtype = "Article",
title = "Generating publication ready visualizations for Single Cell transcriptomics using {SCpubr}",
author = c(person("Enrique", "Blanco-Carmona")),
doi = "10.1101/2022.02.28.482303",
journal = "bioRxiv",
year = "2022",
url = "https://www.biorxiv.org/content/10.1101/2022.02.28.482303v1",
textVersion = paste(
"Blanco-Carmona, E. Generating publication ready visualizations for Single Cell transcriptomics using SCpubr. bioRxiv (2022) doi:10.1101/2022.02.28.482303."
)
)
================================================
FILE: man/do_ActivityHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_ActivityHeatmap.R
\name{do_ActivityHeatmap}
\alias{do_ActivityHeatmap}
\title{Compute affinity of gene sets to cell populations using decoupleR.}
\usage{
do_ActivityHeatmap(
sample,
input_gene_list,
subsample = 2500,
group.by = NULL,
assay = NULL,
slot = NULL,
statistic = "ulm",
number.breaks = 5,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
diverging.palette = "RdBu",
diverging.direction = -1,
enforce_symmetry = TRUE,
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
na.value = "grey75",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
flip = FALSE,
colors.use = NULL,
min.cutoff = NA,
max.cutoff = NA,
verbose = FALSE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
flavor = "Seurat",
nbin = 24,
ctrl = 100,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{statistic}{\strong{\code{\link[base]{character}}} | DecoupleR statistic to use for the analysis.
values in the Idents of the Seurat object are reported, assessing how specific a given gene set is for a given cell population compared to other gene sets of equal expression.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{flavor}{\strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A list containing different plots.
}
\description{
Major contributions to this function:
\itemize{
\item \href{https://github.com/MarcElosua}{Marc Elosua Bayés} for the core concept code and idea.
\item \href{https://github.com/paubadiam}{Pau Badia i Mompel} for the network generation.
}
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ActivityHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
# Default parameters.
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 5,
flavor = "Seurat",
subsample = NA,
verbose = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_AlluvialPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_AlluvialPlot.R
\name{do_AlluvialPlot}
\alias{do_AlluvialPlot}
\title{Generate Alluvial plots.}
\usage{
do_AlluvialPlot(
sample,
first_group,
last_group,
middle_groups = NULL,
colors.use = NULL,
colorblind = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
font.size = 14,
font.type = "sans",
xlab = NULL,
ylab = "Number of cells",
repel = FALSE,
fill.by = last_group,
use_labels = FALSE,
stratum.color = "black",
stratum.fill = "white",
stratum.width = 1/3,
stratum.fill.conditional = FALSE,
use_geom_flow = FALSE,
alluvium.color = "white",
flow.color = "white",
flip = FALSE,
label.color = "black",
curve_type = "sigmoid",
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.grid = FALSE,
grid.color = "grey75",
grid.type = "dashed",
na.value = "white",
legend.position = "bottom",
legend.title = NULL,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{first_group}{\strong{\code{\link[base]{character}}} | Categorical metadata variable. First group of nodes of the alluvial plot.}
\item{last_group}{\strong{\code{\link[base]{character}}} | Categorical metadata variable. Last group of nodes of the alluvial plot.}
\item{middle_groups}{\strong{\code{\link[base]{character}}} | Categorical metadata variable. Vector of groups of nodes of the alluvial plot.}
\item{colors.use}{\strong{\code{\link[base]{character}}} | Named list of colors corresponding to the unique values in fill.by (which defaults to last_group).}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{repel}{\strong{\code{\link[base]{logical}}} | Whether to repel the text labels.}
\item{fill.by}{\strong{\code{\link[base]{character}}} | One of first_group, middle_groups (one of the values, if multiple mid_groups) or last_group. These values will be used to color the alluvium/flow.}
\item{use_labels}{\strong{\code{\link[base]{logical}}} | Whether to use labels instead of text for the stratum.}
\item{stratum.color, alluvium.color, flow.color}{\strong{\code{\link[base]{character}}} | Color for the border of the alluvium (and flow) and stratum.}
\item{stratum.fill}{\strong{\code{\link[base]{character}}} | Color to fill the stratum.}
\item{stratum.width}{\strong{\code{\link[base]{logical}}} | Width of the stratum.}
\item{stratum.fill.conditional}{\strong{\code{\link[base]{logical}}} | Whether to fill the stratum with the same colors as the alluvium/flow.}
\item{use_geom_flow}{\strong{\code{\link[base]{logical}}} | Whether to use \code{\link[ggalluvial]{geom_flow}} instead of \code{\link[ggalluvial]{geom_alluvium}}. Visual results might differ.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{label.color}{\strong{\code{\link[base]{character}}} | Color for the text labels.}
\item{curve_type}{\strong{\code{\link[base]{character}}} | Type of curve used in \code{\link[ggalluvial]{geom_alluvium}}. One of:
\itemize{
\item \emph{\code{linear}}.
\item \emph{\code{cubic}}.
\item \emph{\code{quintic}}.
\item \emph{\code{sine}}.
\item \emph{\code{arctangent}}.
\item \emph{\code{sigmoid}}.
\item \emph{\code{xspline}}.
}}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
This function is based on the \pkg{ggalluvial} package. It allows you to generate alluvial plots from a given Seurat object.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_AlluvialPlot", passive = TRUE)
message(value)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Compute basic sankey plot.
p <- SCpubr::do_AlluvialPlot(sample = sample,
first_group = "orig.ident",
last_group = "seurat_clusters")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_BarPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_BarPlot.R
\name{do_BarPlot}
\alias{do_BarPlot}
\title{Create Bar Plots.}
\usage{
do_BarPlot(
sample,
group.by,
order = FALSE,
add.n = FALSE,
add.n.face = "bold",
add.n.expand = c(0, 1.15),
add.n.size = 4,
order.by = NULL,
split.by = NULL,
facet.by = NULL,
position = "stack",
font.size = 14,
font.type = "sans",
legend.position = "bottom",
legend.title = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
axis.text.x.angle = 45,
xlab = NULL,
ylab = NULL,
colors.use = NULL,
colorblind = FALSE,
flip = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
plot.grid = FALSE,
grid.color = "grey75",
grid.type = "dashed",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
strip.text.face = "bold",
return_data = FALSE
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata column to compute the counts of. Has to be either a character or factor column.}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to order the results in descending order of counts.}
\item{add.n}{\strong{\code{\link[base]{logical}}} | Whether to add the total counts on top of each bar.}
\item{add.n.face}{\strong{\code{\link[base]{character}}} | Font face of the labels added by \strong{\code{add.n}}.}
\item{add.n.expand}{\strong{\code{\link[base]{numeric}}} | Vector of two numerics representing the start and end of the scale. Minimum should be 0 and max should be above 1. This basically expands the Y axis so that the labels fit when \strong{\code{flip = TRUE}}.
\itemize{
\item \emph{\code{stack}}: Set the bars side by side, displaying the total number of counts. Uses \link[ggplot2]{position_stack}.
\item \emph{\code{fill}}: Set the bars on top of each other, displaying the proportion of counts from the total that each group represents. Uses \link[ggplot2]{position_fill}.
}}
\item{add.n.size}{\strong{\code{\link[base]{numeric}}} | Size of the labels}
\item{order.by}{\strong{\code{\link[base]{character}}} | When \strong{\code{split.by}} is used, value of \strong{\code{group.by}} to reorder the columns based on its value.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Metadata column to split the values of group.by by. If not used, defaults to the active idents.}
\item{facet.by}{\strong{\code{\link[base]{character}}} | Metadata column to gather the columns by. This is useful if you have other overarching metadata.}
\item{position}{\strong{\code{\link[base]{character}}} | Position function from \pkg{ggplot2}. Either stack or fill.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{strip.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the strip text. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{return_data}{\strong{\code{\link[base]{logical}}} | Returns a data.frame with the count and proportions displayed in the plot.}
}
\value{
A ggplot2 object containing a Bar plot.
}
\description{
Create Bar Plots.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_BarPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic bar plot, horizontal.
p1 <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
legend.position = "none",
plot.title = "Number of cells per cluster")
# Split by a second variable.
sample$modified_orig.ident <- sample(x = c("Sample_A", "Sample_B", "Sample_C"),
size = ncol(sample),
replace = TRUE,
prob = c(0.2, 0.7, 0.1))
p <- SCpubr::do_BarPlot(sample,
group.by = "seurat_clusters",
split.by = "modified_orig.ident",
plot.title = "Number of cells per cluster in each sample",
position = "stack")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_BeeSwarmPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_BeeSwarmPlot.R
\name{do_BeeSwarmPlot}
\alias{do_BeeSwarmPlot}
\title{Generate BeeSwarm plots of ranked cells colored by gene expression or metadata.}
\usage{
do_BeeSwarmPlot(
sample,
feature_to_rank,
group.by = NULL,
assay = NULL,
reduction = NULL,
slot = NULL,
continuous_feature = FALSE,
order = FALSE,
colors.use = NULL,
colorblind = FALSE,
legend.title = NULL,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.icon.size = 4,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
font.size = 14,
font.type = "sans",
remove_x_axis = FALSE,
remove_y_axis = FALSE,
flip = FALSE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
verbose = TRUE,
raster = FALSE,
raster.dpi = 300,
plot_cell_borders = TRUE,
border.size = 1.5,
border.color = "black",
pt.size = 2,
min.cutoff = NA,
max.cutoff = NA,
na.value = "grey75",
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{feature_to_rank}{\strong{\code{\link[base]{character}}} | Feature for which the cells are going to be ranked. Ideal case is that this feature is stored as a metadata column.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{continuous_feature}{\strong{\code{\link[base]{logical}}} | Is the feature to rank and color for continuous? I.e: an enrichment score.}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to reorder the groups based on the median of the ranking.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.icon.size}{\strong{\code{\link[base]{numeric}}} | Size of the icons in legend.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{remove_x_axis, remove_y_axis}{\strong{\code{\link[base]{logical}}} | Remove X axis labels and ticks from the plot.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{raster.dpi}{\strong{\code{\link[base]{numeric}}} | Pixel resolution for rasterized plots. Defaults to 1024. Only activates on Seurat versions higher or equal than 4.1.0.}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a Bee Swarm plot.
}
\description{
This function ranks cells along a continuous feature and displays them as a
bee swarm, colored by a second variable. Useful for visualizing continuous
enrichment scores across cell populations.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_BeeSwarmPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Bee Swarm plot - categorical coloring.
# This will color based on the unique values of seurat_clusters.
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = FALSE)
# Basic Bee Swarm plot - continuous coloring.
# This will color based on the PC_1 values.
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_BoxPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_BoxPlot.R
\name{do_BoxPlot}
\alias{do_BoxPlot}
\title{Generate Box Plots.}
\usage{
do_BoxPlot(
sample,
feature,
group.by = NULL,
split.by = NULL,
assay = NULL,
slot = "data",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
colors.use = NULL,
colorblind = FALSE,
na.value = "grey75",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
legend.title = NULL,
legend.title.position = "top",
legend.position = "bottom",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
boxplot.line.color = "black",
outlier.color = "black",
outlier.alpha = 0.5,
boxplot.linewidth = 0.5,
boxplot.width = NULL,
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
flip = FALSE,
order = FALSE,
use_silhouette = FALSE,
use_test = FALSE,
comparisons = NULL,
test = "wilcox.test",
map_signif_level = c(`***` = 0.001, `**` = 0.01, `*` = 0.05),
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{feature}{\strong{\code{\link[base]{character}}} | Feature to represent.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.title.position}{\strong{\code{\link[base]{character}}} | Position for the title of the legend. One of:
\itemize{
\item \emph{\code{top}}: Top of the legend.
\item \emph{\code{bottom}}: Bottom of the legend.
\item \emph{\code{left}}: Left of the legend.
\item \emph{\code{right}}: Right of the legend.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{boxplot.line.color}{\strong{\code{\link[base]{character}}} | Color of the borders of the boxplots if use_silhouette is FALSE.}
\item{outlier.color}{\strong{\code{\link[base]{character}}} | Color of the outlier dots.}
\item{outlier.alpha}{\strong{\code{\link[base]{numeric}}} | Alpha applied to the outliers.}
\item{boxplot.linewidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines in the boxplots. Also controls the lines of the tests applied if use_test is set to true.}
\item{boxplot.width}{\strong{\code{\link[base]{numeric}}} | Width of the boxplots.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to order the boxplots by average values. Can not be used alongside split.by.}
\item{use_silhouette}{\strong{\code{\link[base]{logical}}} | Whether to color the borders of the boxplots instead of the inside area.}
\item{use_test}{\strong{\code{\link[base]{logical}}} | Whether to apply a statistical test to a given pair of elements. Can not be used alongside split.by.}
\item{comparisons}{A list of length-2 vectors. The entries in the vector are
either the names of 2 values on the x-axis or the 2 integers that
correspond to the index of the columns of interest.}
\item{test}{the name of the statistical test that is applied to the values of
the 2 columns (e.g. \code{t.test}, \code{wilcox.test} etc.). If you implement a
custom test make sure that it returns a list that has an entry called
\code{p.value}.}
\item{map_signif_level}{Boolean value, if the p-value are directly written as
annotation or asterisks are used instead. Alternatively one can provide a
named numeric vector to create custom mappings from p-values to annotation:
For example: \code{c("***"=0.001, "**"=0.01, "*"=0.05)}.
Alternatively, one can provide a function that takes a numeric argument
(the p-value) and returns a string.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
Generate Box Plots.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_BoxPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic box plot.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA")
p
# Use silhouette style.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_silhouette = TRUE)
p
# Order by mean values.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
order = TRUE)
p
# Apply second grouping.
sample$orig.ident <- ifelse(sample$seurat_clusters \%in\% c("0", "1", "2", "3"), "A", "B")
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
p
# Apply statistical tests.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident",
use_test = TRUE,
comparisons = list(c("A", "B")))
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_CNVHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_CNVHeatmap.R
\name{do_CNVHeatmap}
\alias{do_CNVHeatmap}
\title{Display CNV scores from inferCNV as Feature Plots.}
\usage{
do_CNVHeatmap(
sample,
infercnv_object,
chromosome_locations,
group.by = NULL,
using_metacells = FALSE,
metacell_mapping = NULL,
include_chr_arms = FALSE,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
legend.type = "colorbar",
legend.position = "bottom",
legend.length = 20,
legend.width = 1,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
font.size = 14,
pt.size = 1,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = TRUE,
legend.title = NULL,
na.value = "grey75",
viridis.palette = "G",
viridis.direction = 1,
verbose = FALSE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = -1,
use_viridis = TRUE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
flip = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{infercnv_object}{\strong{\code{\link[infercnv]{infercnv}}} | Output inferCNV object run on the same Seurat object.}
\item{chromosome_locations}{\strong{\code{\link[tibble]{tibble}}} | Tibble containing the chromosome regions to use. Can be obtained using \strong{\code{utils::data("human_chr_locations", package = "SCpubr")}}.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{using_metacells}{\strong{\code{\link[base]{logical}}} | Whether inferCNV was run using metacells or not.}
\item{metacell_mapping}{\strong{\code{\link[SCpubr]{named_vector}}} | Vector or cell - metacell mapping.}
\item{include_chr_arms}{\strong{\code{\link[base]{logical}}} | Whether the output heatmap should also include chromosome arms or just whole chromosomes.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A list containing Feature Plots for different chromosome regions and corresponding dot plots by groups..
}
\description{
Display CNV scores from inferCNV as Feature Plots.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_CNVHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# This function expects that you have run inferCNV on your
# own and you have access to the output object.
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds",
package = "SCpubr"))
# Define your inferCNV object.
infercnv_object <- readRDS(system.file("extdata/infercnv_object_example.rds",
package = "SCpubr"))
# Get human chromosome locations.
chromosome_locations = SCpubr::human_chr_locations
# Compute for a all chromosomes.
p <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = chromosome_locations)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_CellularStatesPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_CellularStatesPlot.R
\name{do_CellularStatesPlot}
\alias{do_CellularStatesPlot}
\title{Plot relationships between enrichment scores to infer cellular states.}
\usage{
do_CellularStatesPlot(
sample,
input_gene_list,
x1,
y1,
x2 = NULL,
y2 = NULL,
group.by = NULL,
colors.use = NULL,
colorblind = FALSE,
legend.position = "bottom",
legend.icon.size = 4,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
font.size = 14,
font.type = "sans",
xlab = NULL,
ylab = NULL,
axis.ticks = TRUE,
axis.text = TRUE,
verbose = FALSE,
enforce_symmetry = FALSE,
plot_marginal_distributions = FALSE,
marginal.type = "density",
marginal.size = 5,
marginal.group = TRUE,
plot_cell_borders = TRUE,
plot_enrichment_scores = FALSE,
border.size = 2,
border.color = "black",
pt.size = 2,
raster = FALSE,
raster.dpi = 1024,
plot_features = FALSE,
features = NULL,
use_viridis = TRUE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = -1,
nbin = 24,
ctrl = 100,
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{x1}{\strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. First feature in the X axis. Will go on the right side of the X axis if y2 is not provided and top-right quadrant if provided.}
\item{y1}{\strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. First feature on the Y axis. Will become the Y axis if y2 is not provided and bottom-right quadrant if provided.}
\item{x2}{\strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. Second feature on the X axis. Will go on the left side of the X axis if y2 is not provided and top-left quadrant if provided.}
\item{y2}{\strong{\code{\link[base]{character}}} | A name of a list from input_gene_list. Second feature on the Y axis. Will become the bottom-left quadrant if provided.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.icon.size}{\strong{\code{\link[base]{numeric}}} | Size of the icons in legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{axis.ticks}{\strong{\code{\link[base]{logical}}} | Whether to show axis ticks.}
\item{axis.text}{\strong{\code{\link[base]{logical}}} | Whether to show axis text.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Whether to enforce the plot to follow a symmetry (3 variables, the X axis has 0 as center, 4 variables, all axis have the same range and the plot is squared).}
\item{plot_marginal_distributions}{\strong{\code{\link[base]{logical}}} | Whether to plot marginal distributions on the figure or not.}
\item{marginal.type}{\strong{\code{\link[base]{character}}} | One of:
\itemize{
\item \emph{\code{density}}: Compute density plots on the margins.
\item \emph{\code{histogram}}: Compute histograms on the margins.
\item \emph{\code{boxplot}}: Compute boxplot on the margins.
\item \emph{\code{violin}}: Compute violin plots on the margins.
\item \emph{\code{densigram}}: Compute densigram plots on the margins.
}}
\item{marginal.size}{\strong{\code{\link[base]{numeric}}} | Size ratio between the main and marginal plots. A value of 5 means that the main plot is 5 times bigger than the marginal plots.}
\item{marginal.group}{\strong{\code{\link[base]{logical}}} | Whether to group the marginal distribution by group.by or current identities.}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{plot_enrichment_scores}{\strong{\code{\link[base]{logical}}} | Whether to report enrichment scores for the input lists as plots.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{raster.dpi}{\strong{\code{\link[base]{numeric}}} | Pixel resolution for rasterized plots. Defaults to 1024. Only activates on Seurat versions higher or equal than 4.1.0.}
\item{plot_features}{\strong{\code{\link[base]{logical}}} | Whether to also report any other feature onto the primary plot.}
\item{features}{\strong{\code{\link[base]{character}}} | Additional features to plot.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a butterfly plot.
}
\description{
This plot aims to show the relationships between distinct enrichment scores. If 3 variables are provided, the relationship is between the Y axis and the dual X axis.
If 4 variables are provided, each corner of the plot represents how enriched the cells are in that given list. How to interpret this? In a 3-variable plot, the Y axis
just means one variable. The higher the cells are in the Y axis the more enriched they are in that given variable. The X axis is a dual parameter one. Cells falling
into each extreme of the axis are highly enriched for either x1 or x2, while cells falling in between are not enriched for any of the two. In a 4-variable plot, each corner
shows the enrichment for one of the 4 given features. Cells will tend to locate in either of the four corners, but there will be cases of cells locating mid-way between two
given corners (enriched in both features) or in the middle of the plot (not enriched for any).
}
\details{
This plots are based on the following publications:
\itemize{
\item Neftel, C. \emph{et al}. An Integrative Model of Cellular States, Plasticity, and Genetics for Glioblastoma. Cell 178, 835-849.e21 (2019). \doi{10.1016/j.cell.2019.06.024}
\item Tirosh, I., Venteicher, A., Hebert, C. \emph{et al}. Single-cell RNA-seq supports a developmental hierarchy in human oligodendroglioma. Nature 539, 309–313 (2016). \doi{10.1038/nature20123}
}
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_CellularStatesPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Define some gene sets to query. It has to be a named list.
gene_set <- list("A" = rownames(sample)[1:10],
"B" = rownames(sample)[11:20],
"C" = rownames(sample)[21:30],
"D" = rownames(sample)[31:40])
# Using two variables: A scatter plot X vs Y.
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = gene_set,
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
p
# Using three variables. Figure from: https://www.nature.com/articles/nature20123.
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = gene_set,
x1 = "A",
y1 = "B",
x2 = "C",
nbin = 1,
ctrl = 10)
p
# Using four variables. Figure from: https://pubmed.ncbi.nlm.nih.gov/31327527/
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = gene_set,
x1 = "A",
y1 = "C",
x2 = "B",
y2 = "D",
nbin = 1,
ctrl = 10)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_ChordDiagramPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_ChordDiagramPlot.R
\name{do_ChordDiagramPlot}
\alias{do_ChordDiagramPlot}
\title{Generate a Chord diagram.}
\usage{
do_ChordDiagramPlot(
sample = NULL,
from = NULL,
to = NULL,
colors.from = NULL,
colors.to = NULL,
colorblind = FALSE,
big.gap = 10,
small.gap = 1,
link.border.color = NA,
link.border.width = 1,
highlight_group = NULL,
alpha.highlight = 25,
link.sort = NULL,
link.decreasing = TRUE,
z_index = FALSE,
self.link = 1,
symmetric = FALSE,
directional = 1,
direction.type = c("diffHeight", "arrows"),
link.arr.type = "big.arrow",
scale = FALSE,
alignment = "default",
annotationTrack = c("grid", "axis"),
padding_labels = 4,
font.size = 1
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{from, to}{\strong{\code{\link[base]{character}}} | Categorical metadata variable to be used as origin and end points of the interactions.}
\item{colors.from, colors.to}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of colors corresponding to the unique values of "from" and "to".}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{big.gap}{\strong{\code{\link[base]{numeric}}} | Space between the groups in "from" and "to".}
\item{small.gap}{\strong{\code{\link[base]{numeric}}} | Space within the groups.}
\item{link.border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the links. NA = no color.}
\item{link.border.width}{\strong{\code{\link[base]{numeric}}} | Width of the border line of the links.}
\item{highlight_group}{\strong{\code{\link[base]{character}}} | A value from from that will be used to highlight only the links coming from it.}
\item{alpha.highlight}{\strong{\code{\link[base]{numeric}}} | A value between 00 (double digits) and 99 to depict the alpha of the highlighted links. No transparency needs "FF"}
\item{link.sort}{pass to \code{\link[circlize]{chordDiagramFromMatrix}} or \code{\link[circlize]{chordDiagramFromDataFrame}}
}
\item{link.decreasing}{pass to \code{\link[circlize]{chordDiagramFromMatrix}} or \code{\link[circlize]{chordDiagramFromDataFrame}}
}
\item{z_index}{\strong{\code{\link[base]{logical}}} | Whether to bring the bigger links to the top.}
\item{self.link}{\strong{\code{\link[base]{numeric}}} | Behavior of the links. One of:
\itemize{
\item \emph{\code{1}}: Prevents self linking.
\item \emph{\code{2}}: Allows self linking.
}}
\item{symmetric}{pass to \code{\link[circlize]{chordDiagramFromMatrix}}
}
\item{directional}{\strong{\code{\link[base]{numeric}}} | Set the direction of the links. One of:
\itemize{
\item \emph{\code{0}}: Non-directional data.
\item \emph{\code{1}}: Links go from "from" to "to".
\item \emph{\code{-1}}: Links go from "to" to "from".
\item \emph{\code{2}}: Links go in both directions.
}}
\item{direction.type}{\strong{\code{\link[base]{character}}} | How to display the directions. One of:
\itemize{
\item \emph{\code{diffHeight}}: Sets a line at the origin of the group showing to how many groups and in which proportion this group is linked to.
\item \emph{\code{arrows}}: Sets the connection as arrows.
\item \emph{\code{both}}: Sets up both behaviors. Use as: \code{c("diffHeight", "arrows")}.
}}
\item{link.arr.type}{\strong{\code{\link[base]{character}}} | Sets the appearance of the arrows. One of:
\itemize{
\item \emph{\code{triangle}}: Arrow with a triangle tip at the end displayed on top of the link.
\item \emph{\code{big.arrow}}: The link itself ends in a triangle shape.
}}
\item{scale}{\strong{\code{\link[base]{logical}}} | Whether to put all nodes the same width.}
\item{alignment}{\strong{\code{\link[base]{character}}} | How to align the diagram. One of:
\itemize{
\item \emph{\code{default}}: Allows \pkg{circlize} to set up the plot as it sees fit.
\item \emph{\code{horizontal}}: Sets the break between "from" and "to" groups on the horizontal axis.
\item \emph{\code{vertical}}: Sets the break between "from" and "to" groups on the vertical axis.
}}
\item{annotationTrack}{pass to \code{\link[circlize]{chordDiagramFromMatrix}} or \code{\link[circlize]{chordDiagramFromDataFrame}}
}
\item{padding_labels}{\strong{\code{\link[base]{numeric}}} | Number of extra padding (white spaces) of the labels so that they do not overlap with the scales.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
}
\value{
A circlize plot.
}
\description{
Generate a Chord diagram.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ChordDiagramPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic chord diagram.
sample$assignment <- ifelse(sample$seurat_clusters \%in\% c("0", "4", "7"), "A", "B")
sample$assignment[sample$seurat_clusters \%in\% c("1", "2")] <- "C"
sample$assignment[sample$seurat_clusters \%in\% c("10", "5")] <- "D"
sample$assignment[sample$seurat_clusters \%in\% c("8", "9")] <- "E"
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "assignment")
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_ColorBlindCheck.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_ColorBlindCheck.R
\name{do_ColorBlindCheck}
\alias{do_ColorBlindCheck}
\title{Generate colorblind variations of a given color palette.}
\usage{
do_ColorBlindCheck(
colors.use,
flip = FALSE,
font.size = 14,
font.type = "sans",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.text.face = "plain",
legend.title.face = "bold",
grid.color = "white",
border.color = "black",
axis.text.x.angle = 45
)
}
\arguments{
\item{colors.use}{\strong{\code{\link[base]{character}}} | One color upon which generate the color scale. Can be a name or a HEX code.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
}
\value{
A character vector with the desired color scale.
}
\description{
This function generate colorblind variations of a provided color palette in order to check if it is colorblind friendly. Variations are generated using colorspace package.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ColorBlindCheck", passive = TRUE)
if (isTRUE(value)){
# Generate a color wheel based on a single value.
colors <- c("red", "green", "blue")
p <- SCpubr::do_ColorBlindCheck(colors.use = colors)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_ColorPalette.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_ColorPalette.R
\name{do_ColorPalette}
\alias{do_ColorPalette}
\title{Generate color scales based on a value.}
\usage{
do_ColorPalette(
colors.use,
n = 12,
opposite = FALSE,
adjacent = FALSE,
triadic = FALSE,
split_complementary = FALSE,
tetradic = FALSE,
square = FALSE,
complete_output = FALSE,
plot = FALSE,
font.size = 14,
font.type = "sans"
)
}
\arguments{
\item{colors.use}{\strong{\code{\link[base]{character}}} | One color upon which generate the color scale. Can be a name or a HEX code.}
\item{n}{\strong{\code{\link[base]{numeric}}} | Number of colors to include in the color wheel. Use it when all other options are FALSE, otherwise, it becomes 12.}
\item{opposite}{\strong{\code{\link[base]{logical}}} | Return the opposing color to the one provided.}
\item{adjacent}{\strong{\code{\link[base]{logical}}} | Return the adjacent colors to the one provided.}
\item{triadic}{\strong{\code{\link[base]{logical}}} | Return the triadic combination of colors to the one provided.}
\item{split_complementary}{\strong{\code{\link[base]{logical}}} | Return the split complementary combination of colors to the one provided.}
\item{tetradic}{\strong{\code{\link[base]{logical}}} | Return the tetradic combination of colors to the one provided.}
\item{square}{\strong{\code{\link[base]{logical}}} | Return the square combination of colors to the one provided.}
\item{complete_output}{\strong{\code{\link[base]{logical}}} | Runs all the previous options and returns all the outputs as a list that contains all color vectors, all plots and a combined plot with everything.}
\item{plot}{\strong{\code{\link[base]{logical}}} | Whether to also return a plot displaying the values instead of a vector with the color.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
}
\value{
A character vector with the desired color scale.
}
\description{
This function is an adaptation of colortools package. As the package was removed from CRAN on 23-06-2022, this utility function came to existence in order to cover the gap. It is, on its basis,
an adaptation of the package into a single function. Original code, developed by Gaston Sanchez, can be found in: \url{https://github.com/gastonstat/colortools}
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ColorPalette", passive = TRUE)
if (isTRUE(value)){
# Generate a color wheel based on a single value.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue")
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
plot = TRUE)
# Generate a pair of opposite colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
opposite = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
opposite = TRUE,
plot = TRUE)
# Generate a trio of adjacent colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
adjacent = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
adjacent = TRUE,
plot = TRUE)
# Generate a trio of triadic colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
triadic = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
triadic = TRUE,
plot = TRUE)
# Generate a trio of split complementary colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
split_complementary = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
split_complementary = TRUE,
plot = TRUE)
# Generate a group of tetradic colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
tetradic = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
tetradic = TRUE,
plot = TRUE)
# Generate a group of square colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
square = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
square = TRUE,
plot = TRUE)
# Retrieve the output of all options.
out <- SCpubr::do_ColorPalette(colors.use = "steelblue",
complete_output = TRUE)
## Retrieve the colors.
colors <- out$colors
## Retrieve the plots.
plots <- out$plots
## Retrieve a combined plot with all the options.
p <- out$combined_plot
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_CorrelationHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_CorrelationHeatmap.R
\name{do_CorrelationHeatmap}
\alias{do_CorrelationHeatmap}
\title{Create correlation matrix heatmaps.}
\usage{
do_CorrelationHeatmap(
sample = NULL,
input_gene_list = NULL,
cluster = TRUE,
remove.diagonal = TRUE,
mode = "hvg",
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
assay = NULL,
group.by = NULL,
legend.title = "Pearson coef.",
enforce_symmetry = ifelse(mode == "hvg", TRUE, FALSE),
font.size = 14,
font.type = "sans",
na.value = "grey75",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
legend.position = "bottom",
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
diverging.palette = "RdBu",
diverging.direction = -1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
axis.text.x.angle = 45,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to cluster the elements in the heatmap or not.}
\item{remove.diagonal}{\strong{\code{\link[base]{logical}}} | Whether to convert diagnoal to NA. Normally this value would be 1, heavily shifting the color scale.}
\item{mode}{\strong{\code{\link[base]{character}}} | Different types of correlation matrices can be computed. Right now, the only possible value is "hvg", standing for Highly Variable Genes. The sample is subset for the HVG and the data is re-scaled. Scale data is used for the correlation.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
Create correlation matrix heatmaps.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_CorrelationHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Default values.
p <- SCpubr::do_CorrelationHeatmap(sample = sample)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_DimPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_DimPlot.R
\name{do_DimPlot}
\alias{do_DimPlot}
\title{Generate dimensional reduction plots from a Seurat object.}
\usage{
do_DimPlot(
sample,
reduction = NULL,
group.by = NULL,
split.by = NULL,
split.by.combined = TRUE,
colors.use = NULL,
colorblind = FALSE,
shuffle = TRUE,
order = NULL,
raster = FALSE,
pt.size = 1,
label = FALSE,
label.color = "black",
label.fill = "white",
label.size = 4,
label.box = TRUE,
repel = FALSE,
cells.highlight = NULL,
idents.highlight = NULL,
idents.keep = NULL,
sizes.highlight = 1,
ncol = NULL,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.title = NULL,
legend.position = "bottom",
legend.title.position = "top",
legend.ncol = NULL,
legend.nrow = NULL,
legend.icon.size = 4,
legend.byrow = FALSE,
legend.dot.border = TRUE,
raster.dpi = 2048,
dims = c(1, 2),
font.size = 14,
font.type = "sans",
na.value = "grey75",
plot_cell_borders = TRUE,
border.size = 2,
border.color = "black",
border.density = 1,
plot_marginal_distributions = FALSE,
marginal.type = "density",
marginal.size = 5,
marginal.group = TRUE,
plot.axes = FALSE,
plot_density_contour = FALSE,
contour.position = "bottom",
contour.color = "grey90",
contour.lineend = "butt",
contour.linejoin = "round",
contour_expand_axes = 0.25,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{split.by.combined}{\strong{\code{\link[base]{logical}}} | Adds a combined view of the all the values before splitting them by \strong{\code{split.by}}. Think of this as a regular DimPlot added in front. This is set to \strong{\code{TRUE}} if \strong{\code{split.by}} is used in combination with \strong{\code{group.by}}.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{shuffle}{\strong{\code{\link[base]{logical}}} | Whether to shuffle the cells or not, so that they are not plotted cluster-wise. Recommended.}
\item{order}{\strong{\code{\link[base]{character}}} | Vector of identities to be plotted. Either one with all identities or just some, which will be plotted last.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{label}{\strong{\code{\link[base]{logical}}} | Whether to plot the cluster labels in the UMAP. The cluster labels will have the same color as the cluster colors.}
\item{label.color}{\strong{\code{\link[base]{character}}} | Color of the labels in the plot.}
\item{label.fill}{\strong{\code{\link[base]{character}}} | Color to fill the labels. Has to be a single color, that will be used for all labels. If \strong{\code{NULL}}, the colors of the clusters will be used instead.}
\item{label.size}{\strong{\code{\link[base]{numeric}}} | Size of the labels in the plot.}
\item{label.box}{\strong{\code{\link[base]{logical}}} | Whether to plot the plot labels as \strong{\code{\link[ggplot2]{geom_text}}} (FALSE) or \strong{\code{\link[ggplot2]{geom_label}}} (TRUE).}
\item{repel}{\strong{\code{\link[base]{logical}}} | Whether to repel the text labels.}
\item{cells.highlight, idents.highlight}{\strong{\code{\link[base]{character}}} | Vector of cells/identities to focus into. The identities have to much those in \code{Seurat::Idents(sample)} The rest of the cells will be grayed out. Both parameters can be used at the same time.}
\item{idents.keep}{\strong{\code{\link[base]{character}}} | Vector of identities to keep. This will effectively set the rest of the cells that do not match the identities provided to NA, therefore coloring them according to na.value parameter.}
\item{sizes.highlight}{\strong{\code{\link[base]{numeric}}} | Point size of highlighted cells using cells.highlight parameter.}
\item{ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns used in the arrangement of the output plot using "split.by" parameter.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title.position}{\strong{\code{\link[base]{character}}} | Position for the title of the legend. One of:
\itemize{
\item \emph{\code{top}}: Top of the legend.
\item \emph{\code{bottom}}: Bottom of the legend.
\item \emph{\code{left}}: Left of the legend.
\item \emph{\code{right}}: Right of the legend.
}}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.icon.size}{\strong{\code{\link[base]{numeric}}} | Size of the icons in legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{legend.dot.border}{\strong{\code{\link[base]{logical}}} | Adds a black border around the dots in the legend.}
\item{raster.dpi}{\strong{\code{\link[base]{numeric}}} | Pixel resolution for rasterized plots. Defaults to 1024. Only activates on Seurat versions higher or equal than 4.1.0.}
\item{dims}{\strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{border.density}{\strong{\code{\link[base]{numeric}}} | Controls the number of cells used when \strong{\code{plot_cell_borders = TRUE}}. Value between 0 and 1. It computes a 2D kernel density and based on this cells that have a density below the specified quantile will be used to generate the cluster contour. The lower this number, the less cells will be selected, thus reducing the overall size of the plot but also potentially preventing all the contours to be properly drawn.}
\item{plot_marginal_distributions}{\strong{\code{\link[base]{logical}}} | Whether to plot marginal distributions on the figure or not.}
\item{marginal.type}{\strong{\code{\link[base]{character}}} | One of:
\itemize{
\item \emph{\code{density}}: Compute density plots on the margins.
\item \emph{\code{histogram}}: Compute histograms on the margins.
\item \emph{\code{boxplot}}: Compute boxplot on the margins.
\item \emph{\code{violin}}: Compute violin plots on the margins.
\item \emph{\code{densigram}}: Compute densigram plots on the margins.
}}
\item{marginal.size}{\strong{\code{\link[base]{numeric}}} | Size ratio between the main and marginal plots. A value of 5 means that the main plot is 5 times bigger than the marginal plots.}
\item{marginal.group}{\strong{\code{\link[base]{logical}}} | Whether to group the marginal distribution by group.by or current identities.}
\item{plot.axes}{\strong{\code{\link[base]{logical}}} | Whether to plot axes or not.}
\item{plot_density_contour}{\strong{\code{\link[base]{logical}}} | Whether to plot density contours in the UMAP.}
\item{contour.position}{\strong{\code{\link[base]{character}}} | Whether to plot density contours on top or at the bottom of the visualization layers, thus overlapping the clusters/cells or not.}
\item{contour.color}{\strong{\code{\link[base]{character}}} | Color of the density lines.}
\item{contour.lineend}{\strong{\code{\link[base]{character}}} | Line end style (round, butt, square).}
\item{contour.linejoin}{\strong{\code{\link[base]{character}}} | Line join style (round, mitre, bevel).}
\item{contour_expand_axes}{\strong{\code{\link[base]{numeric}}} | To make the contours fit the plot, the limits of the X and Y axis are expanding a given percentage from the min and max values for each axis. This controls such percentage.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a DimPlot.
}
\description{
This function wraps \link[Seurat]{DimPlot}, adding publication-ready theming,
cell shuffling, rasterization, density contours, marginal distributions, and
cell border overlays.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_DimPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic DimPlot.
p <- SCpubr::do_DimPlot(sample = sample)
# Restrict the amount of identities displayed.
p <- SCpubr::do_DimPlot(sample = sample,
idents.keep = c("1", "3", "5"))
# Group by another variable rather than `Seurat::Idents(sample)`
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters")
# Split the output in as many plots as unique identities.
p <- SCpubr::do_DimPlot(sample = sample,
split.by = "seurat_clusters")
# Highlight given identities
p <- SCpubr::do_DimPlot(sample,
idents.highlight = c("1", "3"))
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_DotPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_DotPlot.R
\name{do_DotPlot}
\alias{do_DotPlot}
\title{Generate Dot plots of gene expression across cell groups.}
\usage{
do_DotPlot(
sample,
features,
assay = NULL,
slot = "data",
group.by = NULL,
split.by = NULL,
zscore.data = FALSE,
min.cutoff = NA,
max.cutoff = NA,
dot.min = 5,
enforce_symmetry = ifelse(base::isTRUE(zscore.data), TRUE, FALSE),
legend.title = NULL,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
dot.scale = 8,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
font.size = 14,
font.type = "sans",
cluster.identities = FALSE,
cluster.features = FALSE,
flip = FALSE,
axis.text.x.angle = 45,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
diverging.palette = "RdBu",
diverging.direction = -1,
na.value = "grey75",
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{zscore.data}{\strong{\code{\link[base]{logical}}} | Whether to compute Z-scores instead of showing average expression values. This allows to see, for each gene, which group has the highest average expression, but prevents you from comparing values across genes. Can not be used with slot = "scale.data" or with split.by.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{dot.min}{\strong{\code{\link[base]{numeric}}} | Ranges from 0 to 100. Filter out dots whose Percent Expressed falls below this threshold.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{dot.scale}{\strong{\code{\link[base]{numeric}}} | Scale the size of the dots.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{cluster.identities}{\strong{\code{\link[base]{logical}}} | Whether to cluster the identities (groups) based on the expression of the features.}
\item{cluster.features}{\strong{\code{\link[base]{logical}}} | Whether to cluster the features (genes) based on their expression across identities.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a Dot Plot.
}
\description{
This function generates dot plots using ggplot2, displaying average
expression and percent of expressing cells per group, with optional
clustering of identities and features, and Z-score normalization.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_DotPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
# sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Dot plot.
# genes <- rownames(sample)[1:14]
# p <- SCpubr::do_DotPlot(sample = sample,
# features = genes)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_EnrichmentHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_EnrichmentHeatmap.R
\name{do_EnrichmentHeatmap}
\alias{do_EnrichmentHeatmap}
\title{Create enrichment scores heatmaps.}
\usage{
do_EnrichmentHeatmap(
sample,
input_gene_list,
features.order = NULL,
groups.order = NULL,
cluster = TRUE,
scale_scores = FALSE,
assay = NULL,
slot = NULL,
reduction = NULL,
group.by = NULL,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
verbose = FALSE,
na.value = "grey75",
legend.position = "bottom",
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = FALSE,
nbin = 24,
ctrl = 100,
flavor = "Seurat",
legend.title = NULL,
ncores = 1,
storeRanks = TRUE,
min.cutoff = NA,
max.cutoff = NA,
pt.size = 1,
plot_cell_borders = TRUE,
border.size = 2,
return_object = FALSE,
number.breaks = 5,
sequential.palette = "YlGnBu",
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.direction = 1,
flip = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{features.order}{\strong{\code{\link[base]{character}}} | Should the gene sets be ordered in a specific way? Provide it as a vector of characters with the same names as the names of the gene sets.}
\item{groups.order}{\strong{\code{\link[SCpubr]{named_list}}} | Should the groups in theheatmaps be ordered in a specific way? Provide it as a named list (as many lists as values in \strong{\code{group.by}}) with the order for each of the elements in the groups.}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.}
\item{scale_scores}{\strong{\code{\link[base]{logical}}} | Whether to transform the scores to a range of 0-1 for plotting.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Whether the geyser and feature plot has a symmetrical color scale.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{flavor}{\strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{ncores}{\strong{\code{\link[base]{numeric}}} | Number of cores used to run UCell scoring.}
\item{storeRanks}{\strong{\code{\link[base]{logical}}} | Whether to store the ranks for faster UCell scoring computations. Might require large amounts of RAM.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Return the Seurat object with the enrichment scores stored.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
This function computes the enrichment scores for the cells using \link[Seurat]{AddModuleScore} and then aggregates the scores by the metadata variables provided by the user and displays it as a heatmap, computed by \link[ComplexHeatmap]{Heatmap}.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_EnrichmentHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
# Default parameters.
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_ExpressionHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_ExpressionHeatmap.R
\name{do_ExpressionHeatmap}
\alias{do_ExpressionHeatmap}
\title{Create heatmaps of averaged expression by groups.}
\usage{
do_ExpressionHeatmap(
sample,
features,
group.by = NULL,
assay = NULL,
cluster = TRUE,
features.order = NULL,
groups.order = NULL,
slot = "data",
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
legend.title = "Avg. Expression",
na.value = "grey75",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = FALSE,
min.cutoff = NA,
max.cutoff = NA,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
number.breaks = 5,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
flip = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.}
\item{features.order}{\strong{\code{\link[base]{character}}} | Should the gene sets be ordered in a specific way? Provide it as a vector of characters with the same names as the names of the gene sets.}
\item{groups.order}{\strong{\code{\link[SCpubr]{named_list}}} | Should the groups in theheatmaps be ordered in a specific way? Provide it as a named list (as many lists as values in \strong{\code{group.by}}) with the order for each of the elements in the groups.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
This function generates a heatmap with averaged expression values by the unique groups of the metadata variables provided by the user.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ExpressionHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Define list of genes.
genes <- rownames(sample)[1:10]
# Default parameters.
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = genes,
viridis.direction = -1)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_FeaturePlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_FeaturePlot.R
\name{do_FeaturePlot}
\alias{do_FeaturePlot}
\title{Plot gene expression on dimensional reduction embeddings.}
\usage{
do_FeaturePlot(
sample,
features,
assay = NULL,
reduction = NULL,
slot = NULL,
order = FALSE,
group.by = NULL,
group.by.colors.use = NULL,
colorblind = FALSE,
group.by.legend = NULL,
group.by.show.dots = TRUE,
group.by.dot.size = 8,
group.by.cell_borders = FALSE,
group.by.cell_borders.alpha = 0.1,
split.by = NULL,
idents.keep = NULL,
cells.highlight = NULL,
idents.highlight = NULL,
dims = c(1, 2),
enforce_symmetry = FALSE,
symmetry.type = "absolute",
symmetry.center = NA,
pt.size = 1,
font.size = 14,
font.type = "sans",
legend.title = NULL,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
individual.titles = NULL,
individual.subtitles = NULL,
individual.captions = NULL,
ncol = NULL,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
raster = FALSE,
raster.dpi = 1024,
plot_cell_borders = TRUE,
border.size = 2,
border.color = "black",
border.density = 1,
na.value = "grey75",
verbose = TRUE,
plot.axes = FALSE,
min.cutoff = rep(NA, length(features)),
max.cutoff = rep(NA, length(features)),
scale.limits = NULL,
plot_density_contour = FALSE,
contour.position = "bottom",
contour.color = "grey90",
contour.lineend = "butt",
contour.linejoin = "round",
contour_expand_axes = 0.25,
label = FALSE,
label.color = "black",
label.size = 4,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to order the cells based on expression.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable based on which cells are grouped. This will effectively introduce a big dot in the center of each cluster, colored using a categorical color scale or with the values provided by the user in \strong{\code{group.by.colors.use}}. It will also displays a legend.}
\item{group.by.colors.use}{\strong{\code{\link[base]{character}}} | Colors to use for the group dots.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{group.by.legend}{\strong{\code{\link[base]{character}}} | Title for the legend when \strong{\code{group.by}} is used. Use \strong{\code{NA}} to disable it and \strong{\code{NULL}} to use the default column title provided in \strong{\code{group.by}}.}
\item{group.by.show.dots}{\strong{\code{\link[base]{logical}}} | Controls whether to place in the middle of the groups.}
\item{group.by.dot.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots placed in the middle of the groups.}
\item{group.by.cell_borders}{\strong{\code{\link[base]{logical}}} | Plots another border around the cells displaying the same color code of the dots displayed with \strong{\code{group.by}}. Legend is shown always with alpha = 1 regardless of the alpha settings.}
\item{group.by.cell_borders.alpha}{\strong{\code{\link[base]{numeric}}} | Controls the transparency of the new borders drawn by \strong{\code{group.by.cell_borders}}.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{idents.keep}{\strong{\code{\link[base]{character}}} | Vector of identities to plot. The gradient scale will also be subset to only the values of such identities.}
\item{cells.highlight, idents.highlight}{\strong{\code{\link[base]{character}}} | Vector of cells/identities to focus into. The identities have to much those in \code{Seurat::Idents(sample)} The rest of the cells will be grayed out. Both parameters can be used at the same time.}
\item{dims}{\strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{symmetry.type}{\strong{\code{\link[base]{character}}} | Type of symmetry to be enforced. One of:
\itemize{
\item \emph{\code{absolute}}: The highest absolute value will be taken into a account to generate the color scale. Works after \strong{\code{min.cutoff}} and \strong{\code{max.cutoff}}.
\item \emph{\code{centered}}: Centers the scale around the provided value in \strong{\code{symmetry.center}}. Works after \strong{\code{min.cutoff}} and \strong{\code{max.cutoff}}.
}}
\item{symmetry.center}{\strong{\code{\link[base]{numeric}}} | Value upon which the scale will be centered.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{individual.titles, individual.subtitles, individual.captions}{\strong{\code{\link[base]{character}}} | Titles or subtitles. for each feature if needed. Either NULL or a vector of equal length of features.}
\item{ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns used in the arrangement of the output plot using "split.by" parameter.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{raster.dpi}{\strong{\code{\link[base]{numeric}}} | Pixel resolution for rasterized plots. Defaults to 1024. Only activates on Seurat versions higher or equal than 4.1.0.}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{border.density}{\strong{\code{\link[base]{numeric}}} | Controls the number of cells used when \strong{\code{plot_cell_borders = TRUE}}. Value between 0 and 1. It computes a 2D kernel density and based on this cells that have a density below the specified quantile will be used to generate the cluster contour. The lower this number, the less cells will be selected, thus reducing the overall size of the plot but also potentially preventing all the contours to be properly drawn.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{plot.axes}{\strong{\code{\link[base]{logical}}} | Whether to plot axes or not.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{scale.limits}{\strong{\code{\link[base]{numeric}}} | Vector of two values (i.e: \code{c(0, 1)}) to limit the scales. Particularly useful to extend the color scale beyond the values in the dataset, contrary to \code{min.cutoff} and \code{max.cutoff}.}
\item{plot_density_contour}{\strong{\code{\link[base]{logical}}} | Whether to plot density contours in the UMAP.}
\item{contour.position}{\strong{\code{\link[base]{character}}} | Whether to plot density contours on top or at the bottom of the visualization layers, thus overlapping the clusters/cells or not.}
\item{contour.color}{\strong{\code{\link[base]{character}}} | Color of the density lines.}
\item{contour.lineend}{\strong{\code{\link[base]{character}}} | Line end style (round, butt, square).}
\item{contour.linejoin}{\strong{\code{\link[base]{character}}} | Line join style (round, mitre, bevel).}
\item{contour_expand_axes}{\strong{\code{\link[base]{numeric}}} | To make the contours fit the plot, the limits of the X and Y axis are expanding a given percentage from the min and max values for each axis. This controls such percentage.}
\item{label}{\strong{\code{\link[base]{logical}}} | Whether to plot the cluster labels in the UMAP. The cluster labels will have the same color as the cluster colors.}
\item{label.color}{\strong{\code{\link[base]{character}}} | Color of the labels in the plot.}
\item{label.size}{\strong{\code{\link[base]{numeric}}} | Size of the labels in the plot.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a Feature Plot.
}
\description{
This function wraps \link[Seurat]{FeaturePlot}, adding publication-ready
theming, rasterization, density contours, marginal distributions, and
cell border overlays.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_FeaturePlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Regular FeaturePlot.
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA")
# FeaturePlot with a subset of identities
# (in Seurat::Idents(sample)) maintaining the original UMAP shape.
idents.use <- levels(sample)[!(levels(sample) \%in\% c("2", "5", "8"))]
p <- SCpubr::do_FeaturePlot(sample = sample,
idents.highlight = idents.use,
features = c("EPC1"))
# Splitting the FeaturePlot by a variable and
# maintaining the color scale and the UMAP shape.
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "EPC1",
split.by = "seurat_clusters")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_GroupwiseDEHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_GroupwiseDEHeatmap.R
\name{do_GroupwiseDEHeatmap}
\alias{do_GroupwiseDEHeatmap}
\title{Compute a dotplot with the results of a group-wise DE analysis.}
\usage{
do_GroupwiseDEHeatmap(
sample,
de_genes,
group.by = NULL,
assay = NULL,
slot = "data",
number.breaks = 5,
dot.scale = 8,
top_genes = 5,
p.cutoff = 0.05,
flip = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
use_viridis = FALSE,
colors.use = NULL,
colorblind = FALSE,
viridis.direction = -1,
viridis.palette = "G",
sequential.direction = 1,
sequential.palette = "YlGnBu",
diverging.palette = "RdBu",
diverging.direction = -1,
legend.position = "bottom",
legend.title = NULL,
legend.width = 1,
legend.length = 7.5,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
min.cutoff = NA,
max.cutoff = NA,
enforce_symmetry = FALSE,
na.value = "grey75",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{de_genes}{\strong{\code{\link[tibble]{tibble}}} | DE genes matrix resulting of running \code{Seurat::FindAllMarkers()}.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{dot.scale}{\strong{\code{\link[base]{numeric}}} | Scale the size of the dots.}
\item{top_genes}{\strong{\code{\link[base]{numeric}}} | Top N differentially expressed (DE) genes by group to retrieve.}
\item{p.cutoff}{\strong{\code{\link[base]{numeric}}} | Cutoff to use for adjusted p.value to filter significant genes.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A dotplot composed of 3 main panels: -log10(adjusted p-value), log2(FC) and mean expression by cluster.
}
\description{
Compute a dotplot with the results of a group-wise DE analysis.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_GroupwiseDEHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Compute DE genes and transform to a tibble.
de_genes <- readRDS(system.file("extdata/de_genes_example.rds", package = "SCpubr"))
# Default output.
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_LigandReceptorPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_LigandReceptorPlot.R
\name{do_LigandReceptorPlot}
\alias{do_LigandReceptorPlot}
\title{Visualize Ligand-Receptor analysis output.}
\usage{
do_LigandReceptorPlot(
liana_output,
split.by = NULL,
keep_source = NULL,
keep_target = NULL,
top_interactions = 25,
top_interactions_by_group = FALSE,
dot_border = TRUE,
magnitude = "sca.LRscore",
specificity = "aggregate_rank",
sort.by = "E",
sorting.type.specificity = "descending",
sorting.type.magnitude = "descending",
border.color = "black",
axis.text.x.angle = 45,
legend.position = "bottom",
legend.type = "colorbar",
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
font.size = 14,
dot.size = 1,
font.type = "sans",
plot.grid = TRUE,
grid.color = "grey90",
grid.type = "dotted",
compute_ChordDiagrams = FALSE,
sort_interactions_alphabetically = FALSE,
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
return_interactions = FALSE,
invert_specificity = TRUE,
invert_magnitude = FALSE,
verbose = TRUE
)
}
\arguments{
\item{liana_output}{\strong{\code{\link[tibble]{tibble}}} | Object resulting from running the liana functions \code{liana_wrap} and \code{liana_aggregate}.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Whether to further facet the plot on the y axis by common ligand.complex or receptor.complex. Values to provide: NULL, ligand.complex, receptor.complex.}
\item{keep_source, keep_target}{\strong{\code{\link[base]{character}}} | Identities to keep for the source/target of the interactions. NULL otherwise.}
\item{top_interactions}{\strong{\code{\link[base]{numeric}}} | Number of unique interactions to retrieve ordered by magnitude and specificity. It does not necessarily mean that the output will contain as many, but rather an approximate value.}
\item{top_interactions_by_group}{\strong{\code{\link[base]{logical}}} | Enforce the value on \strong{\code{top_interactions}} to be applied to each group in \strong{\code{source}} column.}
\item{dot_border}{\strong{\code{\link[base]{logical}}} | Whether to draw a black border in the dots.}
\item{specificity, magnitude}{\strong{\code{\link[base]{character}}} | Which columns to use for \strong{\code{specificity}} and \strong{\code{magnitude}}.}
\item{sort.by}{\strong{\code{\link[base]{character}}} | How to arrange the top interactions. Interactions are sorted and then the top N are retrieved and displayed. This takes place after subsetting for \strong{\code{keep_source}} and \strong{\code{keep_target}} One of:
\itemize{
\item \emph{\code{A}}: Sorts by specificity.
\item \emph{\code{B}}: Sorts by magnitude.
\item \emph{\code{C}}: Sorts by specificity, then magnitude (gives extra weight to specificity).
\item \emph{\code{D}}: Sorts by magnitude, then specificity (gives extra weight to magnitude). Might lead to the display of non-significant results.
\item \emph{\code{E}}: Sorts by specificity and magnitude equally.
}}
\item{sorting.type.specificity, sorting.type.magnitude}{\strong{\code{\link[base]{character}}} | Whether the sorting of e \strong{\code{magnitude}} or \strong{\code{specificity}} columns is done in ascending or descending order. This synergises with the value of e \strong{\code{invert_specificity}} and e \strong{\code{invert_magnitude}} parameters.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{dot.size}{\strong{\code{\link[base]{numeric}}} | Size aesthetic for the dots.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{compute_ChordDiagrams}{\strong{\code{\link[base]{logical}}} | Whether to also compute Chord Diagrams for both the number of interactions between source and target but also between ligand.complex and receptor.complex.}
\item{sort_interactions_alphabetically}{\strong{\code{\link[base]{logical}}} | Sort the interactions to be plotted alphabetically (\strong{\code{TRUE}}) or keep them in their original order in the matrix (\strong{\code{FALSE}}).}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{return_interactions}{\strong{\code{\link[base]{logical}}} | Whether to return the data.frames with the interactions so that they can be plotted as chord plots using other package functions.}
\item{invert_specificity, invert_magnitude}{\strong{\code{\link[base]{logical}}} | Whether to \strong{\code{-log10}} transform \strong{\code{specificity}} and \strong{\code{magnitude}} columns.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
}
\value{
A ggplot2 plot with the results of the Ligand-Receptor analysis.
}
\description{
This function takes a tibble produced by the liana package and generates a dot-plot visualization according to the user's specifications.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_LigandReceptorPlot", passive = TRUE)
if (isTRUE(value)){
liana_output <- readRDS(system.file("extdata/liana_output_example.rds", package = "SCpubr"))
# Ligand Receptor analysis plot.
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_LoadingsHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_LoadingsHeatmap.R
\name{do_LoadingsHeatmap}
\alias{do_LoadingsHeatmap}
\title{Compute a heatmap summary of the top and bottom genes in the PCA loadings for the desired PCs in a Seurat object.}
\usage{
do_LoadingsHeatmap(
sample,
group.by = NULL,
subsample = NA,
dims = 1:10,
top_loadings = 5,
assay = NULL,
slot = "data",
grid.color = "white",
border.color = "black",
number.breaks = 5,
na.value = "grey75",
legend.position = "bottom",
legend.title = "Expression",
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
use_viridis = FALSE,
sequential.direction = 1,
sequential.palette = "YlGnBu",
viridis.palette = "G",
viridis.direction = -1,
diverging.palette = "RdBu",
diverging.direction = -1,
min.cutoff.loadings = NA,
max.cutoff.loadings = NA,
min.cutoff.expression = NA,
max.cutoff.expression = NA,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subsample the Seurat object to increase computational speed. Use NA to include the Seurat object as is.}
\item{dims}{\strong{\code{\link[base]{numeric}}} | PCs to include in the analysis.}
\item{top_loadings}{\strong{\code{\link[base]{numeric}}} | Number of top and bottom scored genes in the PCA Loadings for each PC.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{min.cutoff.loadings, max.cutoff.loadings}{\strong{\code{\link[base]{numeric}}} | Cutoff to subset the scale of the Loading score heatmap. NA will use quantiles 0.05 and 0.95.}
\item{min.cutoff.expression, max.cutoff.expression}{\strong{\code{\link[base]{numeric}}} | Cutoff to subset the scale of the expression heatmap. NA will use 0 (no quantile) and quantile 0.95.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
Compute a heatmap summary of the top and bottom genes in the PCA loadings for the desired PCs in a Seurat object.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_LoadingsHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:2)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_MetadataHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_MetadataHeatmap.R
\name{do_MetadataHeatmap}
\alias{do_MetadataHeatmap}
\title{Compute a heatmap of categorical variables.}
\usage{
do_MetadataHeatmap(
sample = NULL,
group.by = NULL,
metadata = NULL,
from_df = FALSE,
df = NULL,
colors.use = NULL,
colorblind = FALSE,
cluster = FALSE,
flip = TRUE,
heatmap.gap = 1,
axis.text.x.angle = 45,
legend.position = "bottom",
font.size = 14,
legend.font.size = NULL,
legend.symbol.size = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
na.value = "grey75",
font.type = "sans",
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
xlab = "",
ylab = ""
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata column to use as basis for the plot.}
\item{metadata}{\strong{\code{\link[base]{character}}} | Metadata columns that will be used to plot the heatmap on the basis of the variable provided to group.by.}
\item{from_df}{\strong{\code{\link[base]{logical}}} | Whether to provide a data frame with the metadata instead.}
\item{df}{\strong{\code{\link[base]{data.frame}}} | Data frame containing the metadata to plot. Rows contain the unique values common to all columns (metadata variables). The columns must be named.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_list}}} | A named list of named vectors. The names of the list correspond to the names of the values provided to metadata and the names of the items in the named vectors correspond to the unique values of that specific metadata variable. The values are the desired colors in HEX code for the values to plot. The used are pre-defined by the pacakge but, in order to get the most out of the plot, please provide your custom set of colors for each metadata column!}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{heatmap.gap}{\strong{\code{\link[base]{numeric}}} | Size of the gap between heatmaps in mm.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{legend.font.size}{\strong{\code{\link[base]{numeric}}} | Size of the font size of the legend. NULL uses default theme font size for legend according to the \strong{\code{font.size}} parameter.}
\item{legend.symbol.size}{\strong{\code{\link[base]{numeric}}} | Size of symbols in the legend in mm. NULL uses the default size.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
}
\value{
A ggplot2 object.
}
\description{
The main use of this function is to generate a metadata heatmap of your categorical data,
normally targeted to the different patient samples one has in the Seurat object. It requires
that the metadata columns chosen have one and only one possible value for each of the values in
group.by.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_MetadataHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Can also use a Seurat object.
df <- data.frame(row.names = letters[1:5],
"A" = as.character(seq(1, 5)),
"B" = rev(as.character(seq(1, 5))))
p <- SCpubr::do_MetadataHeatmap(from_df = TRUE,
df = df)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_NebulosaPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_NebulosaPlot.R
\name{do_NebulosaPlot}
\alias{do_NebulosaPlot}
\title{Plot kernel density estimates of gene expression on dimensional reduction embeddings.}
\usage{
do_NebulosaPlot(
sample,
features,
slot = NULL,
dims = c(1, 2),
pt.size = 1,
reduction = NULL,
combine = TRUE,
method = c("ks", "wkde"),
joint = FALSE,
return_only_joint = FALSE,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
font.size = 14,
font.type = "sans",
legend.position = "bottom",
plot_cell_borders = TRUE,
border.size = 2,
border.color = "black",
viridis.palette = "G",
viridis.direction = 1,
verbose = TRUE,
na.value = "grey75",
plot.axes = FALSE,
number.breaks = 5,
use_viridis = FALSE,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{dims}{\strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{combine}{\strong{\code{\link[base]{logical}}} | Whether to create a single plot out of multiple features.}
\item{method}{Kernel density estimation method:
\itemize{
\item \code{ks}: Computes density using the \code{kde} function from the
\code{ks} package.
\item \code{wkde}: Computes density using a modified version of the
\code{kde2d} function from the \code{MASS}
package to allow weights. Bandwidth selection from the \code{ks} package
is used instead.
}}
\item{joint}{\strong{\code{\link[base]{logical}}} | Whether to plot different features as joint density.}
\item{return_only_joint}{\strong{\code{\link[base]{logical}}} | Whether to only return the joint density panel.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{plot.axes}{\strong{\code{\link[base]{logical}}} | Whether to plot axes or not.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a Nebulosa plot.
}
\description{
This function wraps \link[Nebulosa]{plot_density}, adding publication-ready
theming and joint density visualization for multiple features.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_NebulosaPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Nebulosa plot.
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1")
# Compute joint density.
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
joint = TRUE)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_PackageReport.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
\name{do_PackageReport}
\alias{do_PackageReport}
\title{Generate a status report of SCpubr and its dependencies.}
\usage{
do_PackageReport(startup = FALSE, extended = FALSE)
}
\arguments{
\item{startup}{\strong{\code{\link[base]{logical}}} | Whether the message should be displayed at startup, therefore, also containing welcoming messages and tips. If \strong{\code{FALSE}}, only the report itself will be printed.}
\item{extended}{\strong{\code{\link[base]{logical}}} | Whether the message should also include installed packages, current and available version, and which \strong{\code{SCpubr}} functions can be used with the currently installed packages.}
}
\value{
None
}
\description{
This function generates a summary report of the installation status of SCpubr, which packages are still missing and which functions can or can not currently be used.
}
\examples{
\donttest{
# Print a package report.
SCpubr::do_PackageReport(startup = FALSE, extended = FALSE)
}
}
================================================
FILE: man/do_PathwayActivityHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_PathwayActivityHeatmap.R
\name{do_PathwayActivityHeatmap}
\alias{do_PathwayActivityHeatmap}
\title{Plot Pathway Activities from decoupleR using Progeny prior knowledge.}
\usage{
do_PathwayActivityHeatmap(
sample,
activities,
group.by = NULL,
split.by = NULL,
slot = "scale.data",
statistic = "norm_wmean",
pt.size = 1,
border.size = 2,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
na.value = "grey75",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = TRUE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
flip = FALSE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{activities}{\strong{\code{\link[tibble]{tibble}}} | Result of running decoupleR method with progeny regulon prior knowledge.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{statistic}{\strong{\code{\link[base]{character}}} | DecoupleR statistic to use. One of:
\itemize{
\item \emph{\code{wmean}}: For weighted mean.
\item \emph{\code{norm_wmean}}: For normalized weighted mean.
\item \emph{\code{corr_wmean}}: For corrected weighted mean.
}}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
Plot Pathway Activities from decoupleR using Progeny prior knowledge.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_PathwayActivityHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds",
package = "SCpubr"))
# Define your activities object.
progeny_activities <- readRDS(system.file("extdata/progeny_activities_example.rds",
package = "SCpubr"))
# General heatmap.
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities)
p <- out$heatmaps$average_scores
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_RankedEnrichmentHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_RankedEnrichmentHeatmap.R
\name{do_RankedEnrichmentHeatmap}
\alias{do_RankedEnrichmentHeatmap}
\title{Compute a heatmap of enrichment of gene sets on the context of a dimensional reduction component.}
\usage{
do_RankedEnrichmentHeatmap(
sample,
input_gene_list,
assay = NULL,
slot = NULL,
scale.enrichment = TRUE,
dims = 1:2,
subsample = 2500,
reduction = NULL,
group.by = NULL,
colors.use = NULL,
colorblind = FALSE,
raster = FALSE,
interpolate = FALSE,
nbin = 24,
ctrl = 100,
flavor = "Seurat",
main.heatmap.size = 0.95,
enforce_symmetry = ifelse(isTRUE(scale.enrichment), TRUE, FALSE),
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
font.size = 14,
font.type = "sans",
na.value = "grey75",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
legend.position = "bottom",
legend.nrow = NULL,
legend.ncol = NULL,
legend.byrow = FALSE,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
axis.text.x.angle = 45,
border.color = "black",
return_object = FALSE,
verbose = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{scale.enrichment}{\strong{\code{\link[base]{logical}}} | Should the enrichment scores be scaled (z-scored) for better comparison in between gene sets? Setting this to TRUE should make intra- gene set comparisons easier at the cost ot not being able to compare inter- gene sets in absolute values.}
\item{dims}{\strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{colors.use}{\strong{\code{\link[base]{list}}} | A named list of named vectors. The names of the list correspond to the names of the values provided to metadata and the names of the items in the named vectors correspond to the unique values of that specific metadata variable. The values are the desired colors in HEX code for the values to plot. The used are pre-defined by the package but, in order to get the most out of the plot, please provide your custom set of colors for each metadata column!}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{interpolate}{\strong{\code{\link[base]{logical}}} | Smoothes the output heatmap, saving space on disk when saving the image. However, the image is not as crisp.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{flavor}{\strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.}
\item{main.heatmap.size}{\strong{\code{\link[base]{numeric}}} | A number from 0 to 1 corresponding to how big the main heatmap plot should be with regards to the rest (corresponds to the proportion in size).}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A list of ggplot2 objects, one per dimensional reduction component, and a Seurat object if desired.
}
\description{
Compute a heatmap of enrichment of gene sets on the context of a dimensional reduction component.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_RankedEnrichmentHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
# This will query, for the provided components, the enrichment of the gene
# sets for all cells and plot them in the context of the cells reordered by
# the position alongside each dimensional reduction component.
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 5,
flavor = "Seurat",
subsample = NA,
dims = 1:2,
verbose = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_RankedExpressionHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_RankedExpressionHeatmap.R
\name{do_RankedExpressionHeatmap}
\alias{do_RankedExpressionHeatmap}
\title{Compute a heatmap of expression of genes on the context of a dimensional reduction component.}
\usage{
do_RankedExpressionHeatmap(
sample,
features,
assay = NULL,
slot = NULL,
dims = 1:2,
subsample = 2500,
reduction = NULL,
group.by = NULL,
colors.use = NULL,
colorblind = FALSE,
raster = FALSE,
interpolate = FALSE,
nbin = 24,
ctrl = 100,
main.heatmap.size = 0.95,
enforce_symmetry = TRUE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
font.size = 14,
font.type = "sans",
na.value = "grey75",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
legend.position = "bottom",
legend.nrow = NULL,
legend.ncol = NULL,
legend.byrow = FALSE,
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
axis.text.x.angle = 45,
border.color = "black",
return_object = FALSE,
verbose = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{dims}{\strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{colors.use}{\strong{\code{\link[base]{list}}} | A named list of named vectors. The names of the list correspond to the names of the values provided to metadata and the names of the items in the named vectors correspond to the unique values of that specific metadata variable. The values are the desired colors in HEX code for the values to plot. The used are pre-defined by the package but, in order to get the most out of the plot, please provide your custom set of colors for each metadata column!}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{interpolate}{\strong{\code{\link[base]{logical}}} | Smoothes the output heatmap, saving space on disk when saving the image. However, the image is not as crisp.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{main.heatmap.size}{\strong{\code{\link[base]{numeric}}} | A number from 0 to 1 corresponding to how big the main heatmap plot should be with regards to the rest (corresponds to the proportion in size).}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A list of ggplot2 objects, one per dimensional reduction component, and a Seurat object if desired.
}
\description{
Compute a heatmap of expression of genes on the context of a dimensional reduction component.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_RankedExpressionHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- rownames(sample)[1:15]
# This will query, for the provided components, the expression of the genes
# for all cells and plot them in the context of the cells reordered by
# the position alongside each dimensional reduction component.
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
nbin = 1,
ctrl = 5,
subsample = NA,
dims = 1:2,
verbose = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_RidgePlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_RidgePlot.R
\name{do_RidgePlot}
\alias{do_RidgePlot}
\title{Create ridge plots.}
\usage{
do_RidgePlot(
sample,
feature,
group.by = NULL,
split.by = NULL,
assay = "SCT",
slot = "data",
continuous_scale = FALSE,
legend.title = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
colors.use = NULL,
colorblind = FALSE,
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = NULL,
ylab = NULL,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = 1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
flip = FALSE,
number.breaks = 5,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{feature}{\strong{\code{\link[base]{character}}} | Feature to represent.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{continuous_scale}{\strong{\code{\link[base]{logical}}} | Whether to color the ridges depending on a categorical or continuous scale.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{colors.use}{\strong{\code{\link[base]{character}}} | Named vector of colors to use. Has to match the unique values of group.by or color.by (if used) when scale_type is set to categorical.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
This function computes ridge plots based on the \pkg{ggridges} package.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_RidgePlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Compute the most basic ridge plot.
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nFeature_RNA")
p
# Use continuous color scale.
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nFeature_RNA",
continuous_scale = TRUE,
viridis.direction = 1)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_SCEnrichmentHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_SCEnrichmentHeatmap.R
\name{do_SCEnrichmentHeatmap}
\alias{do_SCEnrichmentHeatmap}
\title{Perform a single-cell-based heatmap showing the enrichment in a list of gene sets.}
\usage{
do_SCEnrichmentHeatmap(
sample,
input_gene_list,
assay = NULL,
slot = NULL,
group.by = NULL,
features.order = NULL,
metadata = NULL,
metadata.colors = NULL,
colorblind = FALSE,
subsample = NA,
cluster = TRUE,
flavor = "Seurat",
return_object = FALSE,
ncores = 1,
storeRanks = TRUE,
interpolate = FALSE,
nbin = 24,
ctrl = 100,
xlab = "Cells",
ylab = "Gene set",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.position = "bottom",
legend.title = NULL,
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
strip.text.color = "black",
strip.text.angle = 0,
strip.spacing = 10,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
main.heatmap.size = 0.95,
enforce_symmetry = FALSE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
na.value = "grey75",
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
proportional.size = TRUE,
verbose = FALSE,
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{features.order}{\strong{\code{\link[base]{character}}} | Should the gene sets be ordered in a specific way? Provide it as a vector of characters with the same names as the names of the gene sets.}
\item{metadata}{\strong{\code{\link[base]{character}}} | Categorical metadata variables to plot alongside the main heatmap.}
\item{metadata.colors}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of valid colors for each of the variables defined in \strong{\code{metadata}}.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.}
\item{flavor}{\strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{ncores}{\strong{\code{\link[base]{numeric}}} | Number of cores used to run UCell scoring.}
\item{storeRanks}{\strong{\code{\link[base]{logical}}} | Whether to store the ranks for faster UCell scoring computations. Might require large amounts of RAM.}
\item{interpolate}{\strong{\code{\link[base]{logical}}} | Smoothes the output heatmap, saving space on disk when saving the image. However, the image is not as crisp.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{strip.text.color}{\strong{\code{\link[base]{character}}} | Color of the strip text.}
\item{strip.text.angle}{\strong{\code{\link[base]{numeric}}} | Rotation of the strip text (angles).}
\item{strip.spacing}{\strong{\code{\link[base]{numeric}}} | Controls the size between the different facets.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{main.heatmap.size}{\strong{\code{\link[base]{numeric}}} | Controls the size of the main heatmap (proportion-wise, defaults to 0.95).}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{proportional.size}{\strong{\code{\link[base]{logical}}} | Whether the groups should take the same space in the plot or not.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
This function is heavily inspired by \strong{\code{\link[Seurat]{DoHeatmap}}}.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_SCEnrichmentHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 5,
flavor = "Seurat",
subsample = NA)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_SCExpressionHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_SCExpressionHeatmap.R
\name{do_SCExpressionHeatmap}
\alias{do_SCExpressionHeatmap}
\title{Perform a single-cell-based heatmap showing the expression of genes.}
\usage{
do_SCExpressionHeatmap(
sample,
features,
assay = NULL,
slot = NULL,
group.by = NULL,
features.order = NULL,
metadata = NULL,
metadata.colors = NULL,
colorblind = FALSE,
subsample = NA,
cluster = TRUE,
interpolate = FALSE,
xlab = "Cells",
ylab = "Genes",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.position = "bottom",
legend.title = "Expression",
legend.type = "colorbar",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
strip.text.color = "black",
strip.text.angle = 0,
strip.spacing = 10,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
main.heatmap.size = 0.95,
enforce_symmetry = FALSE,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
na.value = "grey75",
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
proportional.size = TRUE,
verbose = TRUE,
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{features.order}{\strong{\code{\link[base]{character}}} | Should the gene sets be ordered in a specific way? Provide it as a vector of characters with the same names as the names of the gene sets.}
\item{metadata}{\strong{\code{\link[base]{character}}} | Categorical metadata variables to plot alongside the main heatmap.}
\item{metadata.colors}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of valid colors for each of the variables defined in \strong{\code{metadata}}.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.}
\item{interpolate}{\strong{\code{\link[base]{logical}}} | Smoothes the output heatmap, saving space on disk when saving the image. However, the image is not as crisp.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{strip.text.color}{\strong{\code{\link[base]{character}}} | Color of the strip text.}
\item{strip.text.angle}{\strong{\code{\link[base]{numeric}}} | Rotation of the strip text (angles).}
\item{strip.spacing}{\strong{\code{\link[base]{numeric}}} | Controls the size between the different facets.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{main.heatmap.size}{\strong{\code{\link[base]{numeric}}} | Controls the size of the main heatmap (proportion-wise, defaults to 0.95).}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{proportional.size}{\strong{\code{\link[base]{logical}}} | Whether the groups should take the same space in the plot or not.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
This function is heavily inspired by \strong{\code{\link[Seurat]{DoHeatmap}}}.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_SCExpressionHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:2],
subsample = NA)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_StripPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_StripPlot.R
\name{do_StripPlot}
\alias{do_StripPlot}
\title{Generate a Strip plot.}
\usage{
do_StripPlot(
sample,
features,
assay = NULL,
slot = "data",
group.by = NULL,
split.by = NULL,
enforce_symmetry = FALSE,
scale_type = "continuous",
order = TRUE,
plot_cell_borders = TRUE,
jitter = 0.45,
pt.size = 1,
border.size = 2,
border.color = "black",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
viridis.palette = "G",
viridis.direction = 1,
colors.use = NULL,
colorblind = FALSE,
na.value = "grey75",
legend.ncol = NULL,
legend.nrow = NULL,
legend.icon.size = 4,
legend.byrow = FALSE,
legend.title = NULL,
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = "Groups",
ylab = feature,
flip = FALSE,
min.cutoff = rep(NA, length(features)),
max.cutoff = rep(NA, length(features)),
number.breaks = 5,
diverging.palette = "RdBu",
diverging.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
use_viridis = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{scale_type}{\strong{\code{\link[base]{character}}} | Type of color scale to use. One of:
\itemize{
\item \emph{\code{categorical}}: Use a categorical color scale based on the values of "group.by".
\item \emph{\code{continuous}}: Use a continuous color scale based on the values of "feature".
}}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to order the groups by the median of the data (highest to lowest).}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{jitter}{\strong{\code{\link[base]{numeric}}} | Amount of jitter in the plot along the X axis. The lower the value, the more compacted the dots are.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{colors.use}{\strong{\code{\link[base]{character}}} | Named vector of colors to use. Has to match the unique values of group.by when scale_type is set to categorical.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.icon.size}{\strong{\code{\link[base]{numeric}}} | Size of the icons in legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
Either a plot of a list of plots, depending on the number of features provided.
}
\description{
A strip plot is a scatter plot in which we plot continuous values on the Y axis grouped by a categorical value in the X. This is plotted as a dot plot, jittered so that the dots span
all the way to the other groups. On top of this, the mean and .66 and .95 of the data is plotted, depicting the overall distribution of the dots. The cells can, then, be colored by
a continuous variable (same as Y axis or different) or a categorical one (same as X axis or different).
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_StripPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Geyser plot with categorical color scale.
p <- SCpubr::do_StripPlot(sample = sample,
features = "nCount_RNA",
scale_type = "categorical")
p
# Geyser plot with continuous color scale.
p <- SCpubr::do_StripPlot(sample = sample,
features = "nCount_RNA",
scale_type = "continuous")
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_TFActivityHeatmap.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_TFActivityHeatmap.R
\name{do_TFActivityHeatmap}
\alias{do_TFActivityHeatmap}
\title{Plot TF Activities from decoupleR using Dorothea prior knowledge.}
\usage{
do_TFActivityHeatmap(
sample,
activities,
n_tfs = 25,
slot = "scale.data",
statistic = "norm_wmean",
tfs.use = NULL,
group.by = NULL,
split.by = NULL,
values.show = FALSE,
values.threshold = NULL,
values.size = 3,
values.round = 1,
na.value = "grey75",
legend.position = "bottom",
legend.width = 1,
legend.length = 20,
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.framecolor = "grey50",
legend.tickcolor = "white",
legend.type = "colorbar",
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
enforce_symmetry = TRUE,
diverging.palette = "RdBu",
diverging.direction = -1,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
min.cutoff = NA,
max.cutoff = NA,
number.breaks = 5,
flip = FALSE,
return_object = FALSE,
grid.color = "white",
border.color = "black",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{activities}{\strong{\code{\link[tibble]{tibble}}} | Result of running decoupleR method with dorothea regulon prior knowledge.}
\item{n_tfs}{\strong{\code{\link[base]{numeric}}} | Number of top regulons to consider for downstream analysis.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{statistic}{\strong{\code{\link[base]{character}}} | DecoupleR statistic to use. One of:
\itemize{
\item \emph{\code{wmean}}: For weighted mean.
\item \emph{\code{norm_wmean}}: For normalized weighted mean.
\item \emph{\code{corr_wmean}}: For corrected weighted mean.
}}
\item{tfs.use}{\strong{\code{\link[base]{character}}} | Restrict the analysis to given regulons.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Whether the geyser and feature plot has a symmetrical color scale.}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object.
}
\description{
Plot TF Activities from decoupleR using Dorothea prior knowledge.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_TFActivityHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds",
package = "SCpubr"))
# Define your activities object.
dorothea_activities <- readRDS(system.file("extdata/dorothea_activities_example.rds",
package = "SCpubr"))
# General heatmap.
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities)
p <- out$heatmaps$average_scores
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_TermEnrichmentPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_TermEnrichmentPlot.R
\name{do_TermEnrichmentPlot}
\alias{do_TermEnrichmentPlot}
\title{Display the enriched terms for a given list of genes.}
\usage{
do_TermEnrichmentPlot(
mat,
n.chars = 40,
n.terms = 25,
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
use_viridis = FALSE,
viridis.palette = "G",
viridis.direction = -1,
sequential.palette = "YlGnBu",
sequential.direction = 1,
dot.scale = 8,
legend.type = "colorbar",
legend.position = "bottom",
legend.framewidth = 0.5,
legend.tickwidth = 0.5,
legend.length = 20,
legend.width = 1,
legend.framecolor = "grey50",
legend.tickcolor = "white",
number.breaks = 5,
xlab = NULL,
ylab = NULL,
na.value = "grey75",
grid.color = "grey90",
grid.type = "dashed",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
axis.text.x.angle = 45,
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{mat}{\strong{\code{\link[base]{list}}} | Result of over-representation test with clusterProfiler. Accepts only one result, be aware of that if you compute the test for all GO ontologies. Accessed through \strong{\code{mat@result}}.}
\item{n.chars}{\strong{\code{\link[base]{numeric}}} | Number of characters to use as a limit to wrap the term names. The higher this value, the longer the lines would be for each term in the plots. Defaults to 40.}
\item{n.terms}{\strong{\code{\link[base]{numeric}}} | Number of terms to display. Defaults to 25.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{dot.scale}{\strong{\code{\link[base]{numeric}}} | Scale the size of the dots.}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
}
\value{
A dotplot object with enriched terms.
}
\description{
Display the enriched terms for a given list of genes.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_TermEnrichmentPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your enriched terms.
enriched_terms <- readRDS(system.file("extdata/enriched_terms_example.rds", package = "SCpubr"))
# Default plot.
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_ViolinPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_ViolinPlot.R
\name{do_ViolinPlot}
\alias{do_ViolinPlot}
\title{Generate Violin plots from a Seurat object.}
\usage{
do_ViolinPlot(
sample,
features,
assay = NULL,
slot = NULL,
group.by = NULL,
split.by = NULL,
colors.use = NULL,
colorblind = FALSE,
pt.size = 0,
line_width = 0.5,
y_cut = rep(NA, length(features)),
plot_boxplot = TRUE,
boxplot_width = 0.2,
legend.position = "bottom",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
xlab = rep(NA, length(features)),
ylab = rep(NA, length(features)),
font.size = 14,
font.type = "sans",
axis.text.x.angle = 45,
plot.grid = TRUE,
grid.color = "grey75",
grid.type = "dashed",
order = TRUE,
flip = FALSE,
ncol = NULL,
share.y.lims = FALSE,
legend.title = NULL,
legend.title.position = "top",
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of points in the Violin plot.}
\item{line_width}{\strong{\code{\link[base]{numeric}}} | Width of the lines drawn in the plot. Defaults to 1.}
\item{y_cut}{\strong{\code{\link[base]{numeric}}} | Vector with the values in which the Violins should be cut. Only works for one feature.}
\item{plot_boxplot}{\strong{\code{\link[base]{logical}}} | Whether to plot a Box plot inside the violin or not.}
\item{boxplot_width}{\strong{\code{\link[base]{numeric}}} | Width of the boxplots. Defaults to 0.2.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to order the boxplots by average values. Can not be used alongside split.by.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns used in the arrangement of the output plot using "split.by" parameter.}
\item{share.y.lims}{\strong{\code{\link[base]{logical}}} | When querying multiple features, force the Y axis of all of them to be on the same range of values (this being the max and min of all features combined).}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.title.position}{\strong{\code{\link[base]{character}}} | Position for the title of the legend. One of:
\itemize{
\item \emph{\code{top}}: Top of the legend.
\item \emph{\code{bottom}}: Bottom of the legend.
\item \emph{\code{left}}: Left of the legend.
\item \emph{\code{right}}: Right of the legend.
}}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object containing a Violin Plot.
}
\description{
This function generates violin plots using ggplot2, with publication-ready
theming, optional box plot overlay, and extended customization options.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ViolinPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic violin plot.
p <- SCpubr::do_ViolinPlot(sample = sample,
feature = "nCount_RNA")
p
# Remove the box plots.
p <- SCpubr::do_ViolinPlot(sample = sample,
feature = "nCount_RNA",
plot_boxplot = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_VolcanoPlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_VolcanoPlot.R
\name{do_VolcanoPlot}
\alias{do_VolcanoPlot}
\title{Compute a Volcano plot out of DE genes.}
\usage{
do_VolcanoPlot(
sample,
de_genes,
pval_cutoff = 0.05,
FC_cutoff = 2,
pt.size = 1,
border.size = 1.5,
border.color = "black",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
plot_lines = TRUE,
line_color = "grey75",
line_size = 0.5,
add_gene_tags = TRUE,
add_tag_side = "both",
order_tags_by = "both",
tag_size = 6,
n_genes = 5,
use_labels = FALSE,
colors.use = NULL,
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{de_genes}{\strong{\code{\link[tibble]{tibble}}} | Output of \code{Seurat::FindMarkers()}.}
\item{pval_cutoff}{\strong{\code{\link[base]{numeric}}} | Cutoff for the p-value.}
\item{FC_cutoff}{\strong{\code{\link[base]{numeric}}} | Cutoff for the avg_log2FC.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{plot_lines}{\strong{\code{\link[base]{logical}}} | Whether to plot the division lines.}
\item{line_color}{\strong{\code{\link[base]{character}}} | Color for the lines.}
\item{line_size}{\strong{\code{\link[base]{numeric}}} | Size of the lines in the plot.}
\item{add_gene_tags}{\strong{\code{\link[base]{logical}}} | Whether to plot the top genes.}
\item{add_tag_side}{\strong{\code{\link[base]{logical}}} | Either "both", "positive" or "negative" to indicate which side of genes to tag}
\item{order_tags_by}{\strong{\code{\link[base]{character}}} | Either "both", "pvalue" or "logfc".}
\item{tag_size}{\strong{\code{\link[base]{numeric}}} | Size of the text/label for the tags.}
\item{n_genes}{\strong{\code{\link[base]{numeric}}} | Number of top genes to plot.}
\item{use_labels}{\strong{\code{\link[base]{logical}}} | Whether to use labels instead of text for the tags.}
\item{colors.use}{\strong{\code{\link[base]{character}}} | Color to generate a tetradic color scale with. If NULL, default colors are used.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A volcano plot as a ggplot2 object.
}
\description{
Compute a Volcano plot out of DE genes.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_VolcanoPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Retrieve DE genes.
de_genes <- readRDS(system.file("extdata/de_genes_example.rds", package = "SCpubr"))
# Generate a volcano plot.
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/do_WafflePlot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/do_WafflePlot.R
\name{do_WafflePlot}
\alias{do_WafflePlot}
\title{Generate Waffle plots to display cell group proportions.}
\usage{
do_WafflePlot(
sample,
group.by,
waffle.size = 2,
flip = FALSE,
colors.use = NULL,
colorblind = FALSE,
na.value = "grey75",
font.size = 14,
font.type = "sans",
plot.title = NULL,
plot.subtitle = NULL,
plot.caption = NULL,
legend.title = NULL,
legend.ncol = NULL,
legend.nrow = NULL,
legend.byrow = FALSE,
legend.position = "bottom",
plot.title.face = "bold",
plot.subtitle.face = "plain",
plot.caption.face = "italic",
axis.title.face = "bold",
axis.text.face = "plain",
legend.title.face = "bold",
legend.text.face = "plain",
strip.text.face = "bold"
)
}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{waffle.size}{\strong{\code{\link[base]{numeric}}} | Tile border size.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{strip.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the strip text. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
}
\value{
A ggplot2 object with a Waffle Plot.
}
\description{
This function displays the proportional composition of cell groups as a
waffle chart, where each tile represents a fixed number of cells.
}
\examples{
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_WafflePlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Waffle plot.
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "seurat_clusters")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
}
================================================
FILE: man/doc_function.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
\name{doc_function}
\alias{doc_function}
\title{Mock function used to document all main function.}
\arguments{
\item{sample}{\strong{\code{\link[SeuratObject]{Seurat}}} | A Seurat object, generated by \link[Seurat]{CreateSeuratObject}.}
\item{font.size}{\strong{\code{\link[base]{numeric}}} | Overall font size of the plot. All plot elements will have a size relationship with this font size.}
\item{font.type}{\strong{\code{\link[base]{character}}} | Base font family for the plot. One of:
\itemize{
\item \emph{\code{mono}}: Mono spaced font.
\item \emph{\code{serif}}: Serif font family.
\item \emph{\code{sans}}: Default font family.
}}
\item{legend.type}{\strong{\code{\link[base]{character}}} | Type of legend to display. One of:
\itemize{
\item \emph{\code{normal}}: Default legend displayed by \pkg{ggplot2}.
\item \emph{\code{colorbar}}: Redefined colorbar legend, using \link[ggplot2]{guide_colorbar}.
}}
\item{legend.position}{\strong{\code{\link[base]{character}}} | Position of the legend in the plot. One of:
\itemize{
\item \emph{\code{top}}: Top of the figure.
\item \emph{\code{bottom}}: Bottom of the figure.
\item \emph{\code{left}}: Left of the figure.
\item \emph{\code{right}}: Right of the figure.
\item \emph{\code{none}}: No legend is displayed.
}}
\item{legend.framewidth, legend.tickwidth}{\strong{\code{\link[base]{numeric}}} | Width of the lines of the box in the legend.}
\item{legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the lines of the box in the legend.}
\item{legend.tickcolor}{\strong{\code{\link[base]{character}}} | Color of the ticks of the box in the legend.}
\item{legend.length, legend.width}{\strong{\code{\link[base]{numeric}}} | Length and width of the legend. Will adjust automatically depending on legend side.}
\item{plot.title, plot.subtitle, plot.caption}{\strong{\code{\link[base]{character}}} | Title, subtitle or caption to use in the plot.}
\item{assay}{\strong{\code{\link[base]{character}}} | Assay to use. Defaults to the current assay.}
\item{slot}{\strong{\code{\link[base]{character}}} | Data slot to use. Only one of: counts, data, scale.data. Defaults to "data".}
\item{reduction}{\strong{\code{\link[base]{character}}} | Reduction to use. Can be the canonical ones such as "umap", "pca", or any custom ones, such as "diffusion". If you are unsure about which reductions you have, use \code{Seurat::Reductions(sample)}. Defaults to "umap" if present or to the last computed reduction if the argument is not provided.}
\item{viridis.palette}{\strong{\code{\link[base]{character}}} | A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{raster}{\strong{\code{\link[base]{logical}}} | Whether to raster the resulting plot. This is recommendable if plotting a lot of cells.}
\item{raster.dpi}{\strong{\code{\link[base]{numeric}}} | Pixel resolution for rasterized plots. Defaults to 1024. Only activates on Seurat versions higher or equal than 4.1.0.}
\item{plot_cell_borders}{\strong{\code{\link[base]{logical}}} | Whether to plot border around cells.}
\item{border.size}{\strong{\code{\link[base]{numeric}}} | Width of the border of the cells.}
\item{border.color}{\strong{\code{\link[base]{character}}} | Color for the border of the heatmap body.}
\item{na.value}{\strong{\code{\link[base]{character}}} | Color value for NA.}
\item{axis.text.x.angle}{\strong{\code{\link[base]{numeric}}} | Degree to rotate the X labels. One of: 0, 45, 90.}
\item{xlab, ylab}{\strong{\code{\link[base]{character}}} | Titles for the X and Y axis.}
\item{pt.size}{\strong{\code{\link[base]{numeric}}} | Size of the dots.}
\item{verbose}{\strong{\code{\link[base]{logical}}} | Whether to show extra comments, warnings,etc.}
\item{flip}{\strong{\code{\link[base]{logical}}} | Whether to invert the axis of the displayed plot.}
\item{group.by}{\strong{\code{\link[base]{character}}} | Metadata variable to group the output by. Has to be a character of factor column.}
\item{split.by}{\strong{\code{\link[base]{character}}} | Secondary metadata variable to further group (split) the output by. Has to be a character of factor column.}
\item{colors.use}{\strong{\code{\link[SCpubr]{named_vector}}} | Named vector of valid color representations (either name of HEX codes) with as many named colors as unique values of group.by. If group.by is not provided, defaults to the unique values of \link[Seurat]{Idents}. If not provided, a color scale will be set by default.}
\item{legend.title}{\strong{\code{\link[base]{character}}} | Title for the legend.}
\item{legend.icon.size}{\strong{\code{\link[base]{numeric}}} | Size of the icons in legend.}
\item{legend.byrow}{\strong{\code{\link[base]{logical}}} | Whether the legend is filled by row or not.}
\item{legend.ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns in the legend.}
\item{legend.nrow}{\strong{\code{\link[base]{numeric}}} | Number of rows in the legend.}
\item{plot_marginal_distributions}{\strong{\code{\link[base]{logical}}} | Whether to plot marginal distributions on the figure or not.}
\item{marginal.type}{\strong{\code{\link[base]{character}}} | One of:
\itemize{
\item \emph{\code{density}}: Compute density plots on the margins.
\item \emph{\code{histogram}}: Compute histograms on the margins.
\item \emph{\code{boxplot}}: Compute boxplot on the margins.
\item \emph{\code{violin}}: Compute violin plots on the margins.
\item \emph{\code{densigram}}: Compute densigram plots on the margins.
}}
\item{marginal.size}{\strong{\code{\link[base]{numeric}}} | Size ratio between the main and marginal plots. A value of 5 means that the main plot is 5 times bigger than the marginal plots.}
\item{marginal.group}{\strong{\code{\link[base]{logical}}} | Whether to group the marginal distribution by group.by or current identities.}
\item{enforce_symmetry}{\strong{\code{\link[base]{logical}}} | Return a symmetrical plot axes-wise or continuous color scale-wise, when applicable.}
\item{column_title}{\strong{\code{\link[base]{character}}} | Title for the columns of the heatmaps. Only works with single heatmaps.}
\item{row_title}{\strong{\code{\link[base]{character}}} | Title for the rows of the heatmaps. Only works with single heatmaps.}
\item{cluster_cols}{\strong{\code{\link[base]{logical}}} | Cluster the columns or rows of the heatmaps.}
\item{cluster_rows}{\strong{\code{\link[base]{logical}}} | Cluster the rows or rows of the heatmaps.}
\item{column_names_rot}{\strong{\code{\link[base]{numeric}}} | Degree in which to rotate the column labels.}
\item{row_names_rot}{\strong{\code{\link[base]{numeric}}} | Degree in which to rotate the row labels.}
\item{cell_size}{\strong{\code{\link[base]{numeric}}} | Size of each cell in the heatmap.}
\item{input_gene_list}{\strong{\code{\link[SCpubr]{named_list}}} | Named list of lists of genes to be used as input.}
\item{column_title_rot}{\strong{\code{\link[base]{numeric}}} | Degree in which to rotate the column titles.}
\item{row_title_rot}{\strong{\code{\link[base]{numeric}}} | Degree in which to rotate the row titles.}
\item{column_names_side}{\strong{\code{\link[base]{character}}} | Side to put the column names. Either left or right.}
\item{row_names_side}{\strong{\code{\link[base]{character}}} | Side to put the row names. Either left or right.}
\item{column_title_side}{\strong{\code{\link[base]{character}}} | Side to put the column titles Either left or right.}
\item{row_title_side}{\strong{\code{\link[base]{character}}} | Side to put the row titles Either left or right.}
\item{heatmap.legend.length, heatmap.legend.width}{\strong{\code{\link[base]{numeric}}} | Width and length of the legend in the heatmap.}
\item{heatmap.legend.framecolor}{\strong{\code{\link[base]{character}}} | Color of the edges and ticks of the legend in the heatmap.}
\item{scale_direction}{\strong{\code{\link[base]{numeric}}} | Direction of the viridis scales. Either -1 or 1.}
\item{heatmap_gap}{\strong{\code{\link[base]{numeric}}} | Gap in cm between heatmaps.}
\item{legend_gap}{\strong{\code{\link[base]{numeric}}} | Gap in cm between legends.}
\item{cells.highlight, idents.highlight}{\strong{\code{\link[base]{character}}} | Vector of cells/identities to focus into. The identities have to much those in \code{Seurat::Idents(sample)} The rest of the cells will be grayed out. Both parameters can be used at the same time.}
\item{ncol}{\strong{\code{\link[base]{numeric}}} | Number of columns used in the arrangement of the output plot using "split.by" parameter.}
\item{dims}{\strong{\code{\link[base]{numeric}}} | Vector of 2 numerics indicating the dimensions to plot out of the selected reduction. Defaults to c(1, 2) if not specified.}
\item{feature}{\strong{\code{\link[base]{character}}} | Feature to represent.}
\item{features}{\strong{\code{\link[base]{character}}} | Features to represent.}
\item{use_viridis}{\strong{\code{\link[base]{logical}}} | Whether to use viridis color scales.}
\item{viridis.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Controls how the gradient of viridis scale is formed.}
\item{plot.grid}{\strong{\code{\link[base]{logical}}} | Whether to plot grid lines.}
\item{grid.color}{\strong{\code{\link[base]{character}}} | Color of the grid in the plot. In heatmaps, color of the border of the cells.}
\item{grid.type}{\strong{\code{\link[base]{character}}} | One of the possible linetype options:
\itemize{
\item \emph{\code{blank}}.
\item \emph{\code{solid}}.
\item \emph{\code{dashed}}.
\item \emph{\code{dotted}}.
\item \emph{\code{dotdash}}.
\item \emph{\code{longdash}}.
\item \emph{\code{twodash}}.
}}
\item{plot.axes}{\strong{\code{\link[base]{logical}}} | Whether to plot axes or not.}
\item{individual.titles, individual.subtitles, individual.captions}{\strong{\code{\link[base]{character}}} | Vector. Title, subtitle or caption to use in the plot when multiple features are passed on. Use NA to keep the original title.}
\item{legend.title.position}{\strong{\code{\link[base]{character}}} | Position for the title of the legend. One of:
\itemize{
\item \emph{\code{top}}: Top of the legend.
\item \emph{\code{bottom}}: Bottom of the legend.
\item \emph{\code{left}}: Left of the legend.
\item \emph{\code{right}}: Right of the legend.
}}
\item{repel}{\strong{\code{\link[base]{logical}}} | Whether to repel the text labels.}
\item{plot_density_contour}{\strong{\code{\link[base]{logical}}} | Whether to plot density contours in the UMAP.}
\item{contour.position}{\strong{\code{\link[base]{character}}} | Whether to plot density contours on top or at the bottom of the visualization layers, thus overlapping the clusters/cells or not.}
\item{contour.color}{\strong{\code{\link[base]{character}}} | Color of the density lines.}
\item{contour.lineend}{\strong{\code{\link[base]{character}}} | Line end style (round, butt, square).}
\item{contour.linejoin}{\strong{\code{\link[base]{character}}} | Line join style (round, mitre, bevel).}
\item{contour_expand_axes}{\strong{\code{\link[base]{numeric}}} | To make the contours fit the plot, the limits of the X and Y axis are expanding a given percentage from the min and max values for each axis. This controls such percentage.}
\item{label}{\strong{\code{\link[base]{logical}}} | Whether to plot the cluster labels in the UMAP. The cluster labels will have the same color as the cluster colors.}
\item{label.color}{\strong{\code{\link[base]{character}}} | Color of the labels in the plot.}
\item{label.fill}{\strong{\code{\link[base]{character}}} | Color to fill the labels. Has to be a single color, that will be used for all labels. If \strong{\code{NULL}}, the colors of the clusters will be used instead.}
\item{label.size}{\strong{\code{\link[base]{numeric}}} | Size of the labels in the plot.}
\item{label.box}{\strong{\code{\link[base]{logical}}} | Whether to plot the plot labels as \strong{\code{\link[ggplot2]{geom_text}}} (FALSE) or \strong{\code{\link[ggplot2]{geom_label}}} (TRUE).}
\item{min.overlap}{\strong{\code{\link[base]{numeric}}} | Filter the output result to the terms which are supported by this many genes.}
\item{GO_ontology}{\strong{\code{\link[base]{character}}} | GO ontology to use. One of:
\itemize{
\item \emph{\code{BP}}: For \strong{B}iological \strong{P}rocess.
\item \emph{\code{MF}}: For \strong{M}olecular \strong{F}unction.
\item \emph{\code{CC}}: For \strong{C}ellular \strong{C}omponent.
}}
\item{genes}{\strong{\code{\link[base]{character}}} | Vector of gene symbols to query for functional annotation.}
\item{org.db}{\strong{\code{OrgDB}} | Database object to use for the query.}
\item{disable_white_in_viridis}{\strong{\code{\link[base]{logical}}} | Remove the white in viridis color scale when \strong{\code{viridis.direction}} is set to -1.}
\item{number.breaks}{\strong{\code{\link[base]{numeric}}} | Controls the number of breaks in continuous color scales of ggplot2-based plots.}
\item{strip.spacing}{\strong{\code{\link[base]{numeric}}} | Controls the size between the different facets.}
\item{strip.text.color}{\strong{\code{\link[base]{character}}} | Color of the strip text.}
\item{strip.text.angle}{\strong{\code{\link[base]{numeric}}} | Rotation of the strip text (angles).}
\item{diverging.palette}{\strong{\code{\link[base]{character}}} | Type of symmetrical color palette to use. Out of the diverging palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{diverging.direction}{\strong{\code{\link[base]{numeric}}} | Either 1 or -1. Direction of the divering palette. This basically flips the two ends.}
\item{subsample}{\strong{\code{\link[base]{numeric}}} | Number of cells to subset for the analysis. NA will use all. Cells are selected at random.}
\item{plot.title.face, plot.subtitle.face, plot.caption.face, axis.title.face, axis.text.face, legend.title.face, legend.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the corresponding theme element. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{flavor}{\strong{\code{\link[base]{character}}} | One of: Seurat, UCell. Compute the enrichment scores using \link[Seurat]{AddModuleScore} or \link[UCell]{AddModuleScore_UCell}.}
\item{features.order}{\strong{\code{\link[base]{character}}} | Should the gene sets be ordered in a specific way? Provide it as a vector of characters with the same names as the names of the gene sets.}
\item{groups.order}{\strong{\code{\link[SCpubr]{named_list}}} | Should the groups in theheatmaps be ordered in a specific way? Provide it as a named list (as many lists as values in \strong{\code{group.by}}) with the order for each of the elements in the groups.}
\item{interpolate}{\strong{\code{\link[base]{logical}}} | Smoothes the output heatmap, saving space on disk when saving the image. However, the image is not as crisp.}
\item{order}{\strong{\code{\link[base]{logical}}} | Whether to order the boxplots by average values. Can not be used alongside split.by.}
\item{dot.scale}{\strong{\code{\link[base]{numeric}}} | Scale the size of the dots.}
\item{values.show}{\strong{\code{\link[base]{logical}}} | Whether to add values as text in the heatmap.}
\item{values.threshold}{\strong{\code{\link[base]{numeric}}} | Value from which the text color turns from black to white. If mode = "hvg", this is applied to both ends of the color scale.}
\item{values.size}{\strong{\code{\link[base]{numeric}}} | Size of the text labels.}
\item{values.round}{\strong{\code{\link[base]{numeric}}} | Decimal to which round the values to.}
\item{viridis.palette.pvalue, viridis.palette.logfc, viridis.palette.expression}{\strong{\code{\link[base]{character}}} | Viridis color palettes for the p-value, logfc and expression heatmaps. A capital letter from A to H or the scale name as in \link[viridis]{scale_fill_viridis}.}
\item{nbin}{\strong{\code{\link[base]{numeric}}} | Number of bins to use in \link[Seurat]{AddModuleScore}.}
\item{ctrl}{\strong{\code{\link[base]{numeric}}} | Number of genes in the control set to use in \link[Seurat]{AddModuleScore}.}
\item{min.cutoff, max.cutoff}{\strong{\code{\link[base]{numeric}}} | Set the min/max ends of the color scale. Any cell/group with a value lower than min.cutoff will turn into min.cutoff and any cell with a value higher than max.cutoff will turn into max.cutoff. In FeaturePlots, provide as many values as features. Use NAs to skip a feature.}
\item{border.density}{\strong{\code{\link[base]{numeric}}} | Controls the number of cells used when \strong{\code{plot_cell_borders = TRUE}}. Value between 0 and 1. It computes a 2D kernel density and based on this cells that have a density below the specified quantile will be used to generate the cluster contour. The lower this number, the less cells will be selected, thus reducing the overall size of the plot but also potentially preventing all the contours to be properly drawn.}
\item{sequential.palette}{\strong{\code{\link[base]{character}}} | Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.palette.pvalue, sequential.palette.expression, sequential.palette.logfc}{\strong{\code{\link[base]{character}}} | Sequential palettes for p-value, logfc and expression heatmaps. Type of sequential color palette to use. Out of the sequential palettes defined in \strong{\code{\link[RColorBrewer]{brewer.pal}}}.}
\item{sequential.direction}{\strong{\code{\link[base]{numeric}}} | Direction of the sequential color scale. Either 1 or -1.}
\item{return_object}{\strong{\code{\link[base]{logical}}} | Returns the Seurat object with the modifications performed in the function. Nomally, this contains a new assay with the data that can then be used for any other visualization desired.}
\item{statistic}{\strong{\code{\link[base]{character}}} | DecoupleR statistic to use. One of:
\itemize{
\item \emph{\code{wmean}}: For weighted mean.
\item \emph{\code{norm_wmean}}: For normalized weighted mean.
\item \emph{\code{corr_wmean}}: For corrected weighted mean.
}}
\item{cluster}{\strong{\code{\link[base]{logical}}} | Whether to perform clustering of rows and columns.}
\item{strip.text.face}{\strong{\code{\link[base]{character}}} | Controls the style of the font for the strip text. One of:
\itemize{
\item \emph{\code{plain}}: For normal text.
\item \emph{\code{italic}}: For text in itallic.
\item \emph{\code{bold}}: For text in bold.
\item \emph{\code{bold.italic}}: For text both in itallic and bold.
}}
\item{colorblind}{\strong{\code{\link[base]{logical}}} | Whether to use colorblind-friendly colors for categorical variables. In place when \code{colors.use} is not used. Allows for a maximum of 85 different classes within a categorical variable.}
}
\value{
Nothing. This is a mock function.
}
\description{
Mock function used to document all main function.
}
\examples{
# This a mock function that stores the documentation for many other functions.
# It is not intended for user usage.
}
\keyword{internal}
================================================
FILE: man/examples/examples_do_ActivityHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ActivityHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
# Default parameters.
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 5,
flavor = "Seurat",
subsample = NA,
verbose = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_AlluvialPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_AlluvialPlot", passive = TRUE)
message(value)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Compute basic sankey plot.
p <- SCpubr::do_AlluvialPlot(sample = sample,
first_group = "orig.ident",
last_group = "seurat_clusters")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_BarPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_BarPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic bar plot, horizontal.
p1 <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
legend.position = "none",
plot.title = "Number of cells per cluster")
# Split by a second variable.
sample$modified_orig.ident <- sample(x = c("Sample_A", "Sample_B", "Sample_C"),
size = ncol(sample),
replace = TRUE,
prob = c(0.2, 0.7, 0.1))
p <- SCpubr::do_BarPlot(sample,
group.by = "seurat_clusters",
split.by = "modified_orig.ident",
plot.title = "Number of cells per cluster in each sample",
position = "stack")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_BeeSwarmPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_BeeSwarmPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Bee Swarm plot - categorical coloring.
# This will color based on the unique values of seurat_clusters.
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = FALSE)
# Basic Bee Swarm plot - continuous coloring.
# This will color based on the PC_1 values.
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_BoxPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_BoxPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic box plot.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA")
p
# Use silhouette style.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_silhouette = TRUE)
p
# Order by mean values.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
order = TRUE)
p
# Apply second grouping.
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("0", "1", "2", "3"), "A", "B")
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
p
# Apply statistical tests.
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident",
use_test = TRUE,
comparisons = list(c("A", "B")))
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_CNVHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_CNVHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# This function expects that you have run inferCNV on your
# own and you have access to the output object.
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds",
package = "SCpubr"))
# Define your inferCNV object.
infercnv_object <- readRDS(system.file("extdata/infercnv_object_example.rds",
package = "SCpubr"))
# Get human chromosome locations.
chromosome_locations = SCpubr::human_chr_locations
# Compute for a all chromosomes.
p <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = chromosome_locations)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_CellularStatesPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_CellularStatesPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Define some gene sets to query. It has to be a named list.
gene_set <- list("A" = rownames(sample)[1:10],
"B" = rownames(sample)[11:20],
"C" = rownames(sample)[21:30],
"D" = rownames(sample)[31:40])
# Using two variables: A scatter plot X vs Y.
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = gene_set,
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
p
# Using three variables. Figure from: https://www.nature.com/articles/nature20123.
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = gene_set,
x1 = "A",
y1 = "B",
x2 = "C",
nbin = 1,
ctrl = 10)
p
# Using four variables. Figure from: https://pubmed.ncbi.nlm.nih.gov/31327527/
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = gene_set,
x1 = "A",
y1 = "C",
x2 = "B",
y2 = "D",
nbin = 1,
ctrl = 10)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_ChordDiagramPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ChordDiagramPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic chord diagram.
sample$assignment <- ifelse(sample$seurat_clusters %in% c("0", "4", "7"), "A", "B")
sample$assignment[sample$seurat_clusters %in% c("1", "2")] <- "C"
sample$assignment[sample$seurat_clusters %in% c("10", "5")] <- "D"
sample$assignment[sample$seurat_clusters %in% c("8", "9")] <- "E"
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "assignment")
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_ColorBlindCheck.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ColorBlindCheck", passive = TRUE)
if (isTRUE(value)){
# Generate a color wheel based on a single value.
colors <- c("red", "green", "blue")
p <- SCpubr::do_ColorBlindCheck(colors.use = colors)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_ColorPalette.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ColorPalette", passive = TRUE)
if (isTRUE(value)){
# Generate a color wheel based on a single value.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue")
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
plot = TRUE)
# Generate a pair of opposite colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
opposite = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
opposite = TRUE,
plot = TRUE)
# Generate a trio of adjacent colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
adjacent = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
adjacent = TRUE,
plot = TRUE)
# Generate a trio of triadic colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
triadic = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
triadic = TRUE,
plot = TRUE)
# Generate a trio of split complementary colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
split_complementary = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
split_complementary = TRUE,
plot = TRUE)
# Generate a group of tetradic colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
tetradic = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
tetradic = TRUE,
plot = TRUE)
# Generate a group of square colors based on a given one.
colors <- SCpubr::do_ColorPalette(colors.use = "steelblue",
square = TRUE)
p <- SCpubr::do_ColorPalette(colors.use = "steelblue",
square = TRUE,
plot = TRUE)
# Retrieve the output of all options.
out <- SCpubr::do_ColorPalette(colors.use = "steelblue",
complete_output = TRUE)
## Retrieve the colors.
colors <- out$colors
## Retrieve the plots.
plots <- out$plots
## Retrieve a combined plot with all the options.
p <- out$combined_plot
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_CorrelationHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_CorrelationHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Default values.
p <- SCpubr::do_CorrelationHeatmap(sample = sample)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_DimPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_DimPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic DimPlot.
p <- SCpubr::do_DimPlot(sample = sample)
# Restrict the amount of identities displayed.
p <- SCpubr::do_DimPlot(sample = sample,
idents.keep = c("1", "3", "5"))
# Group by another variable rather than `Seurat::Idents(sample)`
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters")
# Split the output in as many plots as unique identities.
p <- SCpubr::do_DimPlot(sample = sample,
split.by = "seurat_clusters")
# Highlight given identities
p <- SCpubr::do_DimPlot(sample,
idents.highlight = c("1", "3"))
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_DotPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_DotPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
# sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Dot plot.
# genes <- rownames(sample)[1:14]
# p <- SCpubr::do_DotPlot(sample = sample,
# features = genes)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_EnrichmentHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_EnrichmentHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
# Default parameters.
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_ExpressionHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ExpressionHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Define list of genes.
genes <- rownames(sample)[1:10]
# Default parameters.
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = genes,
viridis.direction = -1)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_FeaturePlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_FeaturePlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Regular FeaturePlot.
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA")
# FeaturePlot with a subset of identities
# (in Seurat::Idents(sample)) maintaining the original UMAP shape.
idents.use <- levels(sample)[!(levels(sample) %in% c("2", "5", "8"))]
p <- SCpubr::do_FeaturePlot(sample = sample,
idents.highlight = idents.use,
features = c("EPC1"))
# Splitting the FeaturePlot by a variable and
# maintaining the color scale and the UMAP shape.
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "EPC1",
split.by = "seurat_clusters")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_GroupwiseDEHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_GroupwiseDEHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Compute DE genes and transform to a tibble.
de_genes <- readRDS(system.file("extdata/de_genes_example.rds", package = "SCpubr"))
# Default output.
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_LigandReceptorPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_LigandReceptorPlot", passive = TRUE)
if (isTRUE(value)){
liana_output <- readRDS(system.file("extdata/liana_output_example.rds", package = "SCpubr"))
# Ligand Receptor analysis plot.
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_LoadingsHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_LoadingsHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:2)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_MetadataHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_MetadataHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Can also use a Seurat object.
df <- data.frame(row.names = letters[1:5],
"A" = as.character(seq(1, 5)),
"B" = rev(as.character(seq(1, 5))))
p <- SCpubr::do_MetadataHeatmap(from_df = TRUE,
df = df)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_NebulosaPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_NebulosaPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Nebulosa plot.
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1")
# Compute joint density.
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
joint = TRUE)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_PathwayActivityHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_PathwayActivityHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds",
package = "SCpubr"))
# Define your activities object.
progeny_activities <- readRDS(system.file("extdata/progeny_activities_example.rds",
package = "SCpubr"))
# General heatmap.
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities)
p <- out$heatmaps$average_scores
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_RankedEnrichmentHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_RankedEnrichmentHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
# This will query, for the provided components, the enrichment of the gene
# sets for all cells and plot them in the context of the cells reordered by
# the position alongside each dimensional reduction component.
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 5,
flavor = "Seurat",
subsample = NA,
dims = 1:2,
verbose = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_RankedExpressionHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_RankedExpressionHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- rownames(sample)[1:15]
# This will query, for the provided components, the expression of the genes
# for all cells and plot them in the context of the cells reordered by
# the position alongside each dimensional reduction component.
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
nbin = 1,
ctrl = 5,
subsample = NA,
dims = 1:2,
verbose = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_RidgePlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_RidgePlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Compute the most basic ridge plot.
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nFeature_RNA")
p
# Use continuous color scale.
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nFeature_RNA",
continuous_scale = TRUE,
viridis.direction = 1)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_SCEnrichmentHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_SCEnrichmentHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Genes have to be unique.
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 5,
flavor = "Seurat",
subsample = NA)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_SCExpressionHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_SCExpressionHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:2],
subsample = NA)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_StripPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_StripPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Geyser plot with categorical color scale.
p <- SCpubr::do_StripPlot(sample = sample,
features = "nCount_RNA",
scale_type = "categorical")
p
# Geyser plot with continuous color scale.
p <- SCpubr::do_StripPlot(sample = sample,
features = "nCount_RNA",
scale_type = "continuous")
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_TFActivityHeatmap.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_TFActivityHeatmap", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds",
package = "SCpubr"))
# Define your activities object.
dorothea_activities <- readRDS(system.file("extdata/dorothea_activities_example.rds",
package = "SCpubr"))
# General heatmap.
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities)
p <- out$heatmaps$average_scores
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_TermEnrichmentPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_TermEnrichmentPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your enriched terms.
enriched_terms <- readRDS(system.file("extdata/enriched_terms_example.rds", package = "SCpubr"))
# Default plot.
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms)
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_ViolinPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_ViolinPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic violin plot.
p <- SCpubr::do_ViolinPlot(sample = sample,
feature = "nCount_RNA")
p
# Remove the box plots.
p <- SCpubr::do_ViolinPlot(sample = sample,
feature = "nCount_RNA",
plot_boxplot = FALSE)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_VolcanoPlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_VolcanoPlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Retrieve DE genes.
de_genes <- readRDS(system.file("extdata/de_genes_example.rds", package = "SCpubr"))
# Generate a volcano plot.
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes)
p
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/examples/examples_do_WafflePlot.R
================================================
\donttest{
# Check Suggests.
value <- SCpubr:::check_suggests(function_name = "do_WafflePlot", passive = TRUE)
if (isTRUE(value)){
# Consult the full documentation in https://enblacar.github.io/SCpubr-book/
# Define your Seurat object.
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
# Basic Waffle plot.
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "seurat_clusters")
} else if (base::isFALSE(value)){
message("This function can not be used without its suggested packages.")
message("Check out which ones are needed using `SCpubr::state_dependencies()`.")
}
}
================================================
FILE: man/human_chr_locations.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/data.R
\docType{data}
\name{human_chr_locations}
\alias{human_chr_locations}
\title{Chromosome arm locations for human genome GRCh38.}
\format{
A tibble with 48 rows and 4 columns:
\describe{
\item{chr}{Chromosome.}
\item{arm}{Chromosome arm.}
\item{start}{Start coordinates.}
\item{end}{End coordinates.}
}
}
\usage{
data(human_chr_locations)
}
\description{
A tibble containing the chromosome, arm and start and end coordinates.
}
\keyword{datasets}
================================================
FILE: man/named_list.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
\name{named_list}
\alias{named_list}
\title{Named list.}
\value{
Nothing. This is a mock function.
}
\description{
Named list.
}
\examples{
# This is a named vector.
x <- list("first_element" = c("GENE A", "GENE B"),
"second_element" = c("GENE C", "GENE D"))
print(x)
}
\keyword{internal}
================================================
FILE: man/named_vector.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
\name{named_vector}
\alias{named_vector}
\title{Named vector.}
\value{
Nothing. This is a mock function.
}
\description{
Named vector.
}
\examples{
# This is a named vector.
x <- c("first_element" = 3,
"second_element" = TRUE)
print(x)
}
\keyword{internal}
================================================
FILE: revdep/.gitignore
================================================
checks
library
checks.noindex
library.noindex
cloud.noindex
data.sqlite
*.html
================================================
FILE: revdep/email.yml
================================================
release_date: ???
rel_release_date: ???
my_news_url: ???
release_version: ???
release_details: ???
================================================
FILE: tests/testthat/setup.R
================================================
de_genes <- readRDS(system.file("extdata/de_genes_example.rds", package = "SCpubr"))
# nolint start
if (requireNamespace("Seurat", quietly = TRUE)) {
suppressMessages(library("Seurat"))
}
if (requireNamespace("magrittr", quietly = TRUE)) {
suppressMessages(library("magrittr"))
}
if (requireNamespace("dplyr", quietly = TRUE)) {
suppressMessages(library("dplyr"))
de_genes_scaled <- dplyr::rename(.data = de_genes,
"avg_diff" = "avg_log2FC")
}
# nolint end
# Suppress Nebulosa compatibility messages during testing
options(SCpubr.nebulosa.quiet = TRUE)
if (requireNamespace("Seurat", quietly = TRUE)) {
sample <- readRDS(system.file("extdata/seurat_dataset_example.rds", package = "SCpubr"))
sample@assays$SCT$counts <- sample@assays$SCT$data
if (isTRUE(getOption("SCpubr.v5"))){
suppressWarnings(sample[["SCT"]] <- as(object = sample[["SCT"]], Class = "Assay5"))
}
}
metacell_mapping <- readRDS(system.file("extdata/metacell_mapping_example.rds", package = "SCpubr"))
infercnv_object <- readRDS(system.file("extdata/infercnv_object_example.rds", package = "SCpubr"))
infercnv_object_metacells <- readRDS(system.file("extdata/infercnv_object_metacells_example.rds", package = "SCpubr"))
human_chr_locations <- SCpubr::human_chr_locations
progeny_activities <- readRDS(system.file("extdata/progeny_activities_example.rds", package = "SCpubr"))
dorothea_activities <- readRDS(system.file("extdata/dorothea_activities_example.rds", package = "SCpubr"))
enriched_terms <- readRDS(system.file("extdata/enriched_terms_example.rds", package = "SCpubr"))
# Get packages.
dependencies <- SCpubr:::return_dependencies()
dependencies[["utils"]] <- c("Seurat",
"rlang",
"dplyr",
"magrittr",
"dplyr",
"tidyr",
"tibble",
"stringr",
"plyr",
"grDevices",
"stats",
"grid",
"assertthat",
"ComplexHeatmap")
# Check them.
dep_check <- list()
for (func in names(dependencies)){
packages <- c(dependencies[[func]], dependencies[["Essentials"]])
value <- FALSE
for (pkg in packages){
if (!requireNamespace(pkg, quietly = TRUE)) {
value <- TRUE
}
}
dep_check[[func]] <- value
}
liana_output <- readRDS(system.file("extdata/liana_output_example.rds", package = "SCpubr"))
if (base::isFALSE(dep_check[["do_DimPlot"]]) &
base::isFALSE(dep_check[["do_CorrelationHeatmap"]]) &
base::isFALSE(dep_check[["do_ChordDiagramPlot"]]) &
isTRUE(requireNamespace(pkg, quietly = TRUE)) &
base::isFALSE(dep_check[["do_SavePlot"]])){
p <- SCpubr::do_DimPlot(sample)
data <- data.frame("A" = stats::runif(n = 10),
"B" = stats::runif(n = 10),
"C" = stats::runif(n = 10),
"D" = stats::runif(n = 10))
data <- as.matrix(data)
p.pheatmap <- pheatmap::pheatmap(data, cluster_rows = FALSE, cluster_cols = FALSE)
p.heatmap <- ComplexHeatmap::Heatmap(data, cluster_rows = FALSE, cluster_columns = FALSE)
p.chord <- SCpubr::do_ChordDiagramPlot(sample = sample, from = "seurat_clusters", to = "orig.ident")
figure_path <- getwd()
}
#monocle_sample <- sample
#monocle_cds <- test.data$monocle_cds
================================================
FILE: tests/testthat/test-do_ActivityHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_ActivityHeatmap"]])){
testthat::test_that("do_ActivityHeatmap: CRAN essentials", {
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = NA,
nbin = 1,
ctrl = 5,
verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = NA,
nbin = 1,
ctrl = 5,
enforce_symmetry = FALSE,
verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - default", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:11],
"C" = rownames(sample)[12:24])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = TRUE,
statistic = "wmean",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
group.by = "orig.ident",
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
min.cutoff = 0,
max.cutoff = 0.1,
verbose = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
values.show = TRUE,
values.threshold = 0.1,
enforce_symmetry = TRUE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
values.show = TRUE,
values.threshold = 0.1,
enforce_symmetry = FALSE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = FALSE,
values.show = TRUE,
values.threshold = 0.2,
return_object = TRUE)
testthat::expect_type(p, "list")
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
group.by = c("seurat_clusters", "orig.ident"),
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
group.by = c("seurat_clusters", "orig.ident"),
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
group.by = c("seurat_clusters", "orig.ident"),
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
group.by = c("seurat_clusters", "orig.ident"),
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = TRUE,
return_object = TRUE)
testthat::expect_type(p, "list")
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - robustness", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages({testthat::expect_message({p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = TRUE,
flip = TRUE)})})
testthat::expect_true(ggplot2::is_ggplot(p))
genes <- list("A" = rownames(sample)[1:3],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[9:15])
testthat::expect_error({SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE)})
genes <- list("A" = rownames(sample)[1:15],
"B" = rownames(sample)[16:40],
"C" = rownames(sample)[41:80])
SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - symmetry", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
enforce_symmetry = FALSE,
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
enforce_symmetry = FALSE,
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - add enrichment", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
use_viridis = TRUE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
use_viridis = TRUE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages({testthat::expect_message({ p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = TRUE,
use_viridis = TRUE)})})
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
use_viridis = TRUE,
flavor = "UCell")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - flip", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - cutoffs", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE,
min.cutoff = -0.15,
max.cutoff = 0.15)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - multiple group.by", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - verbose", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
testthat::expect_message({p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = TRUE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - underscores", {
testthat::skip_on_cran()
genes <- list("_A" = rownames(sample)[1:5],
"_B" = rownames(sample)[6:10],
"_C" = rownames(sample)[11:15])
testthat::expect_warning({p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ActivityHeatmap: PASS - different length of gene sets", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:15],
"C" = rownames(sample)[15:30])
p <- SCpubr::do_ActivityHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_AlluvialPlot.R
================================================
if (base::isFALSE(dep_check[["do_AlluvialPlot"]])){
testthat::test_that("do_AlluvialPlot: CRAN essential tests", {
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
last_group = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_EnrichmentHeatmap: PASS - normal", {
testthat::skip_on_cran()
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_labels = TRUE,
repel = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_labels = TRUE,
repel = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_viridis = TRUE,
colors.use = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_labels = FALSE,
repel = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = TRUE,
use_labels = TRUE,
repel = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = TRUE,
use_labels = TRUE,
repel = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = TRUE,
use_labels = FALSE,
repel = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
flip = TRUE,
use_labels = FALSE,
repel = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_AlluvialPlot: factors", {
sample$orig.ident <- as.factor(sample$orig.ident)
sample$seurat_clusters <- as.factor(sample$seurat_clusters)
sample$annotation <- as.factor(sample$annotation)
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- as.character(sample$orig.ident)
sample$seurat_clusters <- as.character(sample$seurat_clusters)
sample$annotation <- as.character(sample$annotation)
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_AlluvialPlot: geom_flow", {
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_geom_flow = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_geom_flow = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_AlluvialPlot: stratum.fill.conditional", {
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_geom_flow = FALSE,
stratum.fill.conditional = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_geom_flow = FALSE,
stratum.fill.conditional = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_AlluvialPlot: use_viridis", {
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = "annotation",
last_group = "seurat_clusters",
use_geom_flow = FALSE,
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_AlluvialPlot: colors.use", {
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "seurat_clusters",
last_group = "orig.ident",
colors.use = c("Cell" = "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_AlluvialPlot: test_numbers", {
sample$annotation2 <- sample$annotation
sample$annotation3 <- sample$annotation
sample$annotation4 <- sample$annotation
sample$annotation5 <- sample$annotation
sample$annotation6 <- sample$annotation
sample$annotation7 <- sample$annotation
sample$annotation8 <- sample$annotation
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2",
"annotation3"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2",
"annotation3",
"annotation4"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2",
"annotation3",
"annotation4",
"annotation5"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2",
"annotation3",
"annotation4",
"annotation5",
"annotation6"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2",
"annotation3",
"annotation4",
"annotation5",
"annotation6",
"annotation7"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_AlluvialPlot(sample,
first_group = "orig.ident",
middle_groups = c("annotation",
"annotation2",
"annotation3",
"annotation4",
"annotation5",
"annotation6",
"annotation7",
"annotation8"),
last_group = "seurat_clusters",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_BarPlot.R
================================================
if (base::isFALSE(dep_check[["do_BarPlot"]])){
testthat::test_that("do_BarPlot: CRAN essential tests", {
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
position = "stack")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
position = "stack",
colors.use = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
position = "stack",
order = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "stack")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "fill")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = NULL,
position = "stack")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = NULL,
position = "stack",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "fill",
add.n = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "fill",
order = TRUE,
order.by = "0")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "fill",
add.n = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
facet.by = "orig.ident",
position = "fill",
add.n = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
facet.by = "orig.ident",
position = "fill",
add.n = TRUE,
return_data = TRUE)
testthat::expect_type(p, "list")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
facet.by = "orig.ident",
position = "fill",
add.n = TRUE,
return_data = TRUE,
flip = TRUE)
testthat::expect_type(p, "list")
})
testthat::test_that("do_BarPlot: PASS - one variable - stack", {
testthat::skip_on_cran()
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
position = "stack")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - two variables - fill - flip", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "fill",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - two variables - stack - flip", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "orig.ident",
position = "stack",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - two variables - stack - flip - ordered", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
split.by = "seurat_clusters",
position = "stack",
flip = TRUE,
order = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: FAIL - wrong position", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
testthat::expect_error(SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
position = "wrong"))
})
testthat::test_that("do_BarPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
testthat::expect_error(SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
font.type = "wrong"))
})
testthat::test_that("do_BarPlot: FAIL - column not a factor or character", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
testthat::expect_error(SCpubr::do_BarPlot(sample = sample,
group.by = "nCount_RNA"))
})
testthat::test_that("do_BarPlot: PASS - rotate x labels", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
axis.text.x.angle = 0)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - rotate x labels", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
sample$seurat.clusters.factor <- factor(sample$seurat_clusters)
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat.clusters.factor")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - rotate x labels with group.by", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
sample$seurat.clusters.factor <- factor(sample$seurat_clusters)
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat.clusters.factor",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - colors.use and group.by", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
sample$seurat.clusters.factor <- factor(sample$seurat_clusters)
colors <- c("0" = "#001219",
"1" = "#005f73",
"2" = "#0a9396",
"3" = "#94d2bd",
"4" = "#e9d8a6",
"5" = "#ee9b00",
"6" = "#ca6702",
"7" = "#bb3e03",
"8" = "#ae2012")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat.clusters.factor",
split.by = "seurat_clusters",
colors.use = colors)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat.clusters.factor",
split.by = "seurat_clusters",
colors.use = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - colors.use ", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
sample$seurat.clusters.factor <- factor(sample$seurat_clusters)
colors <- c("0" = "#001219",
"1" = "#005f73",
"2" = "#0a9396",
"3" = "#94d2bd",
"4" = "#e9d8a6",
"5" = "#ee9b00",
"6" = "#ca6702",
"7" = "#bb3e03",
"8" = "#ae2012")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat.clusters.factor",
colors.use = colors)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - one variable - rotate x labels", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
position = "stack",
axis.text.x.angle = 0)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - one variable - xlab, ylab and title", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
position = "stack",
xlab = "A",
ylab = "B",
plot.title = "C",
plot.subtitle = "D",
plot.caption = "E")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - one variable - no legend", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "orig.ident",
position = "stack",
legend.position = "none")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - group.by factor", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
sample$factor_seurat_clusters <- factor(sample$seurat_clusters)
p <- SCpubr::do_BarPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "factor_seurat_clusters",
position = "stack",
legend.position = "none")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - labs", {
testthat::skip_on_cran()
p <- SCpubr::do_BarPlot(sample = sample,
xlab = NULL,
ylab = NULL,
group.by = "seurat_clusters",
split.by = NULL,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = NULL,
ylab = NULL,
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = NULL,
ylab = NULL,
group.by = "seurat_clusters",
split.by = NULL,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = "A",
ylab = "B",
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = NULL,
ylab = NULL,
group.by = "seurat_clusters",
split.by = NULL,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = NULL,
ylab = NULL,
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = NULL,
ylab = NULL,
group.by = "seurat_clusters",
split.by = NULL,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = "A",
ylab = "B",
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = "A",
ylab = "B",
legend.title = NULL,
position = "fill",
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = "A",
ylab = "B",
legend.title = NULL,
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = "A",
ylab = "B",
legend.title = "C",
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BarPlot(sample = sample,
xlab = "A",
ylab = "B",
legend.title = "C",
group.by = "seurat_clusters",
split.by = "orig.ident",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_BeeSwarmPlot.R
================================================
if (base::isFALSE(dep_check[["do_BeeSwarmPlot"]])){
testthat::test_that("do_BeeSwarmPlot: CRAN essentials", {
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - categorical variable dimred component", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
legend.title = NULL)
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
legend.title = "A")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - cell_borders", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample, feature_to_rank = "EPC1", group.by = "seurat_clusters", plot_cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample, feature_to_rank = "EPC1", group.by = "seurat_clusters", plot_cell_borders = TRUE, raster = TRUE, pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - categorical variable gene", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
remove_x_axis = TRUE,
remove_y_axis = TRUE,
flip = TRUE,
raster = TRUE,
ylab = "Ylab")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
remove_x_axis = TRUE,
remove_y_axis = TRUE,
flip = TRUE,
raster = TRUE,
ylab = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
order = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
raster = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "orig.ident",
continuous_feature = FALSE,
colors.use = c("Cell" = "red"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
legend.title = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
order = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
order = TRUE,
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - legend position = right", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "EPC1",
group.by = "seurat_clusters",
continuous_feature = FALSE,
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - categorical variable metadata", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "nCount_RNA",
group.by = "seurat_clusters",
continuous_feature = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - continuous variable", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - continuous variable legend normal", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
legend.type = "normal")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - continuous variable legend colorbar", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
legend.type = "colorbar")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: FAIL - wrong legend type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
legend.type = "wrong"))
})
testthat::test_that("do_BeeSwarmPlot: FAIL - more than one feature", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = c("PC_1", "PC_2"),
group.by = "seurat_clusters",
continuous_feature = TRUE))
})
testthat::test_that("do_BeeSwarmPlot: FAIL - wrong legend position", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
legend.position = "wrong"))
})
testthat::test_that("do_BeeSwarmPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
font.type = "wrong"))
})
testthat::test_that("do_BeeSwarmPlot: PASS - continuous variable viridis scale", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
viridis.palette = "F")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - continuous variable legend position = top", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
continuous_feature = TRUE,
legend.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: FAIL - feature not found", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "not_found",
group.by = "seurat_clusters",
continuous_feature = TRUE,
viridis.palette = "F"))
})
testthat::test_that("do_BeeSwarmPlot: PASS - raster", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
raster = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - colors.use", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
colors.use = c("0" = "#001219",
"1" = "#005f73",
"2" = "#0a9396",
"3" = "#94d2bd",
"4" = "#e9d8a6",
"5" = "#ee9b00",
"6" = "#ca6702",
"7" = "#bb3e03",
"8" = "#ae2012"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - remove x axis", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
remove_x_axis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - remove y axis", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
remove_y_axis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - flip", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - all NULL", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = NULL,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - labs", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = NULL,
xlab = "A",
ylab = "B",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = NULL,
xlab = "A",
ylab = "B",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BeeSwarmPlot: PASS - continuous feature cutoffs", {
testthat::skip_on_cran()
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE,
continuous_feature = TRUE,
min.cutoff = -1,
max.cutoff = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE,
continuous_feature = TRUE,
min.cutoff = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE,
continuous_feature = TRUE,
max.cutoff = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
testthat::expect_error({
SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE,
continuous_feature = TRUE,
max.cutoff = 2328443)
})
testthat::expect_error({
SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE,
continuous_feature = TRUE,
min.cutoff = -2328443)
})
testthat::expect_error({
SCpubr::do_BeeSwarmPlot(sample = sample,
feature_to_rank = "PC_1",
group.by = "seurat_clusters",
flip = TRUE,
continuous_feature = TRUE,
min.cutoff = 2328443,
max.cutoff = -2328443)
})
})
}
================================================
FILE: tests/testthat/test-do_BoxPlot.R
================================================
if (base::isFALSE(dep_check[["do_BoxPlot"]])){
testthat::test_that("do_BoxPlot: CRAN essentials", {
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$group.by <- as.character(sample$seurat_clusters)
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "group.by",
split.by = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - default", {
testthat::skip_on_cran()
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident",
colors.use = c("Cell" = "red"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
order = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_silhouette = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
sample$group.by <- as.character(sample$seurat_clusters)
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "group.by",
split.by = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - custom_grouping", {
testthat::skip_on_cran()
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- factor(sample$orig.ident)
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident",
colors.use = c("Cell" = "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - split.by", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters == "0", "C", "B")
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - silhouette", {
testthat::skip_on_cran()
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_silhouette = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - silhouette", {
testthat::skip_on_cran()
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_test = TRUE,
comparisons = list(c("0", "1")))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - order", {
testthat::skip_on_cran()
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
order = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
order = TRUE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: PASS - flip", {
testthat::skip_on_cran()
p <- SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BoxPlot: FAILS ", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_test = TRUE,
split.by = "orig.ident")})
testthat::expect_error({SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_silhouette = TRUE,
split.by = "orig.ident")})
testthat::expect_error({SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_test = TRUE)})
testthat::expect_error({SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
order = TRUE,
split.by = "orig.ident")})
testthat::expect_error({SCpubr::do_BoxPlot(sample = sample,
feature = "nCount_RNA",
use_silhouette = TRUE,
order = FALSE,
split.by = "orig.ident")})
})
}
================================================
FILE: tests/testthat/test-do_CNVHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_CNVHeatmap"]])){
testthat::test_that("do_BarPlot: CRAN essentials", {
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_BarPlot: PASS - normal cells all chromosomes", {
testthat::skip_on_cran()
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE,
min.cutoff = 0.99,
max.cutoff = 1.01)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE,
include_chr_arms = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE,
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE,
values.show = TRUE,
values.threshold = 1)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = TRUE,
group.by = c("seurat_clusters", "orig.ident", "annotation"))
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = FALSE,
group.by = c("seurat_clusters", "orig.ident", "annotation"))
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations,
flip = FALSE,
return_object = TRUE)
testthat::expect_type(out, "list")
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
group.by = c("seurat_clusters", "orig.ident"),
chromosome_locations = human_chr_locations,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
group.by = c("seurat_clusters", "orig.ident"),
chromosome_locations = human_chr_locations,
flip = FALSE,
return_object = TRUE)
testthat::expect_type(out, "list")
})
testthat::test_that("do_CNVHeatmap: PASS - normal cells one chromosome", {
testthat::skip_on_cran()
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object,
using_metacells = FALSE,
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_CNVHeatmap: PASS - metacells all chromosomes", {
testthat::skip_on_cran()
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object_metacells,
using_metacells = TRUE,
metacell_mapping = metacell_mapping,
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_CNVHeatmap: PASS - group.by", {
testthat::skip_on_cran()
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object_metacells,
using_metacells = TRUE,
metacell_mapping = metacell_mapping,
group.by = "orig.ident",
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_CNVHeatmap: PASS - legend.position", {
testthat::skip_on_cran()
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object_metacells,
using_metacells = TRUE,
metacell_mapping = metacell_mapping,
legend.position = "right",
legend.title = "test",
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object_metacells,
using_metacells = TRUE,
metacell_mapping = metacell_mapping,
legend.position = "bottom",
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_CNVHeatmap: PASS - legend.position", {
testthat::skip_on_cran()
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object_metacells,
using_metacells = TRUE,
metacell_mapping = metacell_mapping,
legend.type = "normal",
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_CNVHeatmap(sample = sample,
infercnv_object = infercnv_object_metacells,
using_metacells = TRUE,
metacell_mapping = metacell_mapping,
legend.type = "colorbar",
chromosome_locations = human_chr_locations)
testthat::expect_true(ggplot2::is_ggplot(out))
})
}
================================================
FILE: tests/testthat/test-do_CellularStatesPlot.R
================================================
if (base::isFALSE(dep_check[["do_CellularStatesPlot"]])){
testthat::test_that("do_CellularStatesPlot: CRAN essentials", {
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
plot_enrichment_scores = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
raster = TRUE,
pt.size = 1,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - cell_borders", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_cell_borders = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
raster = TRUE,
pt.size = 1,
plot_cell_borders = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
plot_cell_borders = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
raster = TRUE,
pt.size = 1,
plot_cell_borders = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_cell_borders = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
raster = TRUE,
pt.size = 1,
plot_cell_borders = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - continuous feature", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
enforce_symmetry = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
plot_enrichment_scores = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
enforce_symmetry = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
plot_enrichment_scores = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
enforce_symmetry = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_cell_borders = TRUE,
plot_features = TRUE,
features = "EPC1",
plot_enrichment_scores = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_cell_borders = TRUE,
plot_features = FALSE,
plot_enrichment_scores = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_type(p, "list")
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables marginal", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables marginal marginal.size", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.size = 8,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables marginal marginal.group FALSE", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.group = FALSE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables marginal distribution types", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.type = "density",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.type = "histogram",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.type = "boxplot",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.type = "violin",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
#p <- SCpubr::do_CellularStatesPlot(sample = sample,
# input_gene_list = genes,
# x1 = "A",
# y1 = "B",
# plot_marginal_distributions = TRUE,
# plot_cell_borders = FALSE,
# marginal.type = "densigram",
# nbin = 1,
# ctrl = 10)
#testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 2 variables marginal wrong marginal.type", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error({SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_marginal_distributions = TRUE,
marginal.type = "wrong",
nbin = 1,
ctrl = 10)})
})
testthat::test_that("do_CellularStatesPlot: PASS - title, subtitle and caption", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot.title = "A",
plot.subtitle = "B",
plot.caption = "C",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables enforce symmetry", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
enforce_symmetry = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables, colors.use", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
Seurat::Idents(sample) <- sample$orig.ident
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
colors.use = c("A" = "black", "B" = "red"),
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables, group.by", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
group.by = "orig.ident",
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables remove axis ticks", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
axis.ticks = FALSE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables remove axis text", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
axis.text = FALSE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 2 variables, group.by and colors.use", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
group.by = "orig.ident",
colors.use = c("A" = "black", "B" = "red"),
x1 = "A",
y1 = "B",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 2 variables same parameters", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "A",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 2 variables x1 not in the list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "Not in list",
y1 = "A",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 2 variables y1 not in the list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "Not in list",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 2 variables provide features", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
plot_features = TRUE,
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: PASS - 3 variables", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
raster = TRUE,
pt.size = 1,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 3 variables marginal", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 3 variables enforce symmetry", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
enforce_symmetry = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 3 variables duplicated parameters", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "A",
x2 = "B",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 3 variables x1 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "Not in list",
y1 = "A",
x2 = "B",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 3 variables x2 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "B",
y1 = "A",
x2 = "Not in list",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 3 variables y1 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "Not in list",
x2 = "B",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: PASS - 4 variables", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
raster = TRUE,
pt.size = 1,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 4 variables marginal", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: PASS - 4 variables enforce symmetry", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
p <- SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "D",
enforce_symmetry = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 4 variables repeated parameters", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "A",
x2 = "A",
y2 = "A",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 4 variables x1 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "Not in list",
y1 = "B",
x2 = "C",
y2 = "D",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 4 variables y1 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "Not in list",
x2 = "C",
y2 = "D",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 4 variables x2 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "Not in list",
y2 = "D",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - 4 variables y2 not in list", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "B",
x2 = "C",
y2 = "Not in list",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_CellularStatesPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15],
"D" = Seurat::VariableFeatures(sample)[16:20])
testthat::expect_error(SCpubr::do_CellularStatesPlot(sample = sample,
input_gene_list = genes,
x1 = "A",
y1 = "Not in list",
x2 = "B",
font.type = "wrong",
nbin = 1,
ctrl = 10))
})
}
================================================
FILE: tests/testthat/test-do_ChordDiagramPlot.R
================================================
if (base::isFALSE(dep_check[["do_ChordDiagramPlot"]])){
testthat::test_that("do_ChordDiagramPlot: CRAN essentials", {
sample$seurat_clusters_char <- as.character(sample$seurat_clusters)
sample$orig.ident_char <- sample$orig.ident
sample$orig.ident <- factor(sample$orig.ident)
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters_char",
to = "orig.ident_char")
testthat::expect_true(inherits(p, "recordedplot"))
})
testthat::test_that("do_ChordDiagramPlot: PASS - default", {
testthat::skip_on_cran()
sample$seurat_clusters_char <- as.character(sample$seurat_clusters)
sample$orig.ident_char <- sample$orig.ident
sample$orig.ident <- factor(sample$orig.ident)
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
z_index = TRUE)
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters_char",
to = "orig.ident_char",
z_index = FALSE)
testthat::expect_true(inherits(p, "recordedplot"))
})
testthat::test_that("do_ChordDiagramPlot: PASS - colors", {
testthat::skip_on_cran()
sample$seurat_clusters_char <- as.character(sample$seurat_clusters)
sample$orig.ident_char <- as.character(sample$orig.ident)
sample$orig.ident <- factor(sample$orig.ident)
sample$seurat_clusters <- factor(sample$seurat_clusters)
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident_char",
to = "seurat_clusters_char")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident_char",
to = "seurat_clusters")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters_char")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters",
colors.from = c("Cell" = "blue"))
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident_char",
to = "seurat_clusters",
colors.from = c("Cell" = "blue"))
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident_char",
to = "seurat_clusters")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
colors.to = c("Cell" = "blue"))
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident_char",
colors.to = c("Cell" = "blue"))
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident_char")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters",
colors.from = c("Cell" = "#345211"))
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters",
colors.from = c("Cell" = "#345211FF"))
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters",
colors.from = c("Cell" = "#345211FF"),
highlight_group = "Cell")
testthat::expect_true(inherits(p, "recordedplot"))
sample$orig.ident <- ifelse(sample$seurat_clusters == "0", "A", "B")
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "orig.ident",
to = "seurat_clusters",
colors.from = c("A" = "#345211", "B" = "#345222"),
highlight_group = "A")
testthat::expect_true(inherits(p, "recordedplot"))
})
testthat::test_that("do_ChordDiagramPlot: PASS - link border color", {
testthat::skip_on_cran()
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
link.border.color = "black")
testthat::expect_true(inherits(p, "recordedplot"))
})
testthat::test_that("do_ChordDiagramPlot: PASS - alignment", {
testthat::skip_on_cran()
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
alignment = "vertical")
testthat::expect_true(inherits(p, "recordedplot"))
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
alignment = "horizontal")
testthat::expect_true(inherits(p, "recordedplot"))
})
testthat::test_that("do_ChordDiagramPlot: PASS - highlight group", {
testthat::skip_on_cran()
p <- SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
highlight_group = "0")
testthat::expect_true(inherits(p, "recordedplot"))
})
testthat::test_that("do_ChordDiagramPlot: FAILS", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
alignment = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
link.arr.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
highlight_group = "0",
alpha.highlight = 120)})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = NULL,
from = "seurat_clusters",
to = "orig.ident")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = NULL,
to = "orig.ident")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = NULL)})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
directional = 4)})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
direction.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
self.link = 3)})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "CD14",
to = "orig.ident",
direction.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "CD14",
direction.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "nCount_RNA",
to = "orig.ident",
direction.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "nCount_RNA",
direction.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
link.arr.type = "wrong")})
testthat::expect_error({SCpubr::do_ChordDiagramPlot(sample = sample,
from = "seurat_clusters",
to = "orig.ident",
highlight_group = "0",
alpha.highlight = 120)})
})
}
================================================
FILE: tests/testthat/test-do_ColorBlindCheck.R
================================================
if (base::isFALSE(dep_check[["do_ColorBlindCheck"]])){
testthat::test_that("do_ColorBlindCheck: PASS - color vectors", {
p <- SCpubr::do_ColorBlindCheck(colors.use = c("red", "blue", "green"), flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorBlindCheck(colors.use = c("red", "blue", "green"), flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_ColorPalette.R
================================================
if (base::isFALSE(dep_check[["do_ColorPalette"]])){
testthat::test_that("do_BarPlot: PASS - color vectors", {
out <- SCpubr::do_ColorPalette(colors.use = "steelblue")
testthat::expect_length(out, 12)
out <- SCpubr::do_ColorPalette(colors.use = "#440154FF")
testthat::expect_length(out, 12)
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", opposite = TRUE)
testthat::expect_length(out, 2)
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", adjacent = TRUE)
testthat::expect_length(out, 3)
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", triadic = TRUE)
testthat::expect_length(out, 3)
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", split_complementary = TRUE)
testthat::expect_length(out, 3)
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", tetradic = TRUE)
testthat::expect_length(out, 4)
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", square = TRUE)
testthat::expect_length(out, 4)
})
testthat::test_that("do_BarPlot: PASS - color vectors using n", {
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", n = 4)
testthat::expect_length(out, 4)
})
testthat::test_that("do_BarPlot: PASS - color vectors plot = TRUERUE", {
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", opposite = TRUE, plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", adjacent = TRUE, plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", triadic = TRUE, plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", split_complementary = TRUE, plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", tetradic = TRUE, plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ColorPalette(colors.use = "steelblue", square = TRUE, plot = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: PASS - complete output = TRUE", {
out <- SCpubr::do_ColorPalette(colors.use = "steelblue", complete_output = TRUE)
testthat::expect_length(names(out), 3)
testthat::expect_type(out, "list")
})
testthat::test_that("do_BarPlot: FAIL - more than one color", {
testthat::expect_error({SCpubr::do_ColorPalette(colors.use = c("red", "blue"))})
})
testthat::test_that("do_BarPlot: FAIL - not a color", {
testthat::expect_error({SCpubr::do_ColorPalette(colors.use = 3)})
})
testthat::test_that("do_BarPlot: FAIL - negative n", {
testthat::expect_error({SCpubr::do_ColorPalette(colors.use = "steelblue", n = -8)})
})
testthat::test_that("do_BarPlot: FAIL - more than one option", {
testthat::expect_error({SCpubr::do_ColorPalette(colors.use = "steelblue", opposite = TRUE, tetradic = TRUE)})
})
testthat::test_that("do_BarPlot: FAIL - not a number", {
testthat::expect_error({SCpubr::do_ColorPalette(colors.use = "steelblue", n = "wrong")})
})
testthat::test_that("do_BarPlot: WARNING - n set when an option is used", {
testthat::expect_warning({SCpubr::do_ColorPalette(colors.use = "steelblue", n = 8, opposite = TRUE)})
})
testthat::test_that("do_BarPlot: FAIL - complete output and plot are TRUE", {
testthat::expect_error({SCpubr::do_ColorPalette(colors.use = "steelblue", complete_output = TRUE, plot = TRUE)})
})
}
================================================
FILE: tests/testthat/test-do_CorrelationHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_CorrelationHeatmap"]])){
testthat::test_that("do_CorrelationHeatmap: CRAN essentials", {
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15])
p <- SCpubr::do_CorrelationHeatmap(sample = sample, legend.position = "top")
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_CorrelationHeatmap: PASS - normal", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
p <- SCpubr::do_CorrelationHeatmap(sample = sample, legend.position = "top", group.by = "orig.ident")
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample, legend.position = "right")
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample, legend.position = "right", cluster = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample, legend.position = "right", cluster = FALSE)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_CorrelationHeatmap: PASS - jaccard", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[3:8],
"C" = rownames(sample)[5:13])
p <- SCpubr::do_CorrelationHeatmap(input_gene_list = genes, mode = "jaccard", legend.position = "top", cluster = FALSE, use_viridis = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(input_gene_list = genes, mode = "jaccard", legend.position = "top", cluster = TRUE, use_viridis = FALSE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(input_gene_list = genes, mode = "jaccard", legend.position = "top", remove.diagonal = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(input_gene_list = genes, mode = "jaccard", legend.position = "top", remove.diagonal = FALSE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(input_gene_list = genes, mode = "jaccard", legend.position = "right")
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_CorrelationHeatmap: PASS - group.by", {
testthat::skip_on_cran()
genes <- list("A" = Seurat::VariableFeatures(sample)[1:50],
"B" = Seurat::VariableFeatures(sample)[25:75],
"C" = Seurat::VariableFeatures(sample)[50:101])
p <- SCpubr::do_CorrelationHeatmap(sample = sample,
group.by = "seurat_clusters")
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample,
input_gene_list = genes,
group.by = "seurat_clusters",
mode = "jaccard")
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample,
input_gene_list = genes,
group.by = "seurat_clusters",
mode = "jaccard",
min.cutoff = 0.01,
max.cutoff = 0.02)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample,
input_gene_list = genes,
group.by = "seurat_clusters",
mode = "jaccard",
cluster = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_CorrelationHeatmap(sample = sample,
input_gene_list = genes,
group.by = "seurat_clusters",
mode = "jaccard",
values.show = TRUE,
values.threshold = 0.01)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_CorrelationHeatmap: PASS - group.by - rotate axis labels", {
testthat::skip_on_cran()
genes <- list("A" = Seurat::VariableFeatures(sample)[1:5],
"B" = Seurat::VariableFeatures(sample)[6:10],
"C" = Seurat::VariableFeatures(sample)[11:15])
p <- SCpubr::do_CorrelationHeatmap(sample = sample,
group.by = "seurat_clusters",
axis.text.x.angle = 0)
testthat::expect_true("ggplot" %in% class(p))
})
}
================================================
FILE: tests/testthat/test-do_DimPlot.R
================================================
if (base::isFALSE(dep_check[["do_DimPlot"]])){
testthat::test_that("do_DimPlot: CRAN essentials", {
p <- SCpubr::do_DimPlot(sample = sample)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, idents.highlight = "0")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- sample(c("A", "B"), ncol(sample), replace = TRUE)
p <- SCpubr::do_DimPlot(sample = sample, group.by = "seurat_clusters", split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - contour", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
plot_density_contour = TRUE,
contour.position = "bottom")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE,
label = TRUE,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE,
label = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
split.by = "annotation",
raster = TRUE,
label = TRUE,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
split.by = "annotation",
raster = TRUE,
label = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
idents.highlight = "0",
raster = TRUE,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
idents.highlight = "0",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
idents.highlight = "0",
raster = TRUE,
label = TRUE,
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
idents.highlight = "0",
raster = TRUE,
label = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - group.by + split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
label = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE,
label = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
split.by = "annotation",
raster = TRUE,
label = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - plot axis", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, plot.axes = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, reduction = "pca", plot.axes = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, dims = c(2, 1), plot.axes = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
sample@reductions$diffusion <- sample@reductions$umap
p <- SCpubr::do_DimPlot(sample = sample,
reduction = "diffusion",
plot.axes = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample cell_borders", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, plot_cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, plot_cell_borders = TRUE, raster = TRUE, pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, plot_cell_borders = TRUE, idents.highlight = "1")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, plot_cell_borders = TRUE, raster = TRUE, idents.highlight = "1", pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, plot_cell_borders = TRUE, split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, plot_cell_borders = TRUE, raster = TRUE, split.by = "seurat_clusters", pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample marginal", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
marginal.type = "density",
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
marginal.type = "histogram",
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- suppressWarnings({SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.type = "violin")})
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
marginal.type = "boxplot",
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
#p <- SCpubr::do_DimPlot(sample = sample,
# plot_marginal_distributions = TRUE,
# marginal.type = "densigram",
# plot_cell_borders = FALSE)
#testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample marginal size", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
marginal.size = 9,
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample marginal group", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
marginal.group = FALSE,
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: FAIL - sample marginal wrong marginal.type", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
marginal.type = "wrong")})
})
testthat::test_that("do_DimPlot: FAIL - sample marginal used alongside split.by or cells.highlight", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
split.by = "seurat_clusters")})
testthat::expect_error({SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
cells.highlight = colnames(sample))})
testthat::expect_error({SCpubr::do_DimPlot(sample = sample,
plot_marginal_distributions = TRUE,
plot_cell_borders = FALSE,
idents.highlight = "1")})
})
testthat::test_that("do_DimPlot: PASS - title", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot.title = "My awesome SC data set")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - subtitle", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot.subtitle = "My awesome SC data set")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - caption", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
plot.caption = "My awesome SC data set")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample + group.by", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, group.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample + split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - sample + split.by + idents.keep", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters", idents.keep = c("1", "3", "5"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters", group.by = "annotation", idents.keep = c("1", "3", "5"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - dims", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, dims = c(1, 2))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - legend.position", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, legend.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - legend.ncol", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, legend.ncol = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - legend.nrow", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, legend.nrow = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - label", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, label = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - order", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, order = "5", shuffle = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - colors.use", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, colors.use = c("0" = "#001219",
"1" = "#005f73",
"2" = "#0a9396",
"3" = "#94d2bd",
"4" = "#e9d8a6",
"5" = "#ee9b00",
"6" = "#ca6702",
"7" = "#bb3e03",
"8" = "#ae2012"))
p <- SCpubr::do_DimPlot(sample = sample, colors.use = c("Cell" = "#001219"),
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DimPlot(sample = sample, colors.use = c("Cell" = "#001219"),
group.by = "orig.ident",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - cells.highlight", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, cells.highlight = sample(colnames(sample), 50))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - idents.highlight", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, idents.highlight = "5")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - cells.highlight and idents.highlight", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, cells.highlight = sample(colnames(sample), 50), idents.highlight = "2")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - idents.keep", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, idents.keep = "5")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: FAIL - group.by and cells.highlights used", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, group.by = "seurat_clusters", cells.highlight = colnames(sample)))
})
testthat::test_that("do_DimPlot: FAIL - split.by and cells.highlights used", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters", cells.highlight = colnames(sample)))
})
testthat::test_that("do_DimPlot: WARNING - order and shuffle used", {
testthat::skip_on_cran()
testthat::expect_warning(SCpubr::do_DimPlot(sample = sample, order = "4", shuffle = TRUE))
})
testthat::test_that("do_DimPlot: FAIL - more than one NA values", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, na.value = c("red", "blue")))
})
testthat::test_that("do_DimPlot: WARNING - raster = TRUE and pt.size lower than 1", {
testthat::skip_on_cran()
testthat::expect_warning(SCpubr::do_DimPlot(sample = sample, raster = TRUE, pt.size = 0.5))
})
colors <- c("0" = "#001219",
"1" = "#005f73",
"2" = "#0a9396",
"3" = "#94d2bd",
"4" = "#e9d8a6",
"5" = "#ee9b00",
"6" = "#ca6702",
"7" = "#bb3e03",
"8" = "#ae2012")
testthat::test_that("do_DimPlot: PASS - group.by + colors", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, group.by = "seurat_clusters", colors.use = colors)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - split.by + colors", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters", colors.use = colors)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: FAIL - more than 1 color with cells highlight", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, colors.use = colors, idents.highlight = "4"))
})
testthat::test_that("do_DimPlot: FAIL - idents.keep not in the levels of the sample", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, idents.keep = c("4", "Not an ident")))
})
testthat::test_that("do_DimPlot: FAIL - idents.keep not in the unique values of group.by", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, group.by = "orig.ident", idents.keep = c("4", "Not an ident")))
})
testthat::test_that("do_DimPlot: FAIL - idents.keep not in the unique values of split.by", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, split.by = "orig.ident", idents.keep = c("4", "Not an ident")))
})
testthat::test_that("do_DimPlot: PASS - split.by + plot.title, subtitle and caption", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample, split.by = "orig.ident",
plot.title = "Plot title",
plot.subtitle = "Plot subtitle",
plot.caption = "Plot caption")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - legend.position none", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
legend.position = "none")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - dims different", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
dims = c(2, 1))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - diffusion maps", {
testthat::skip_on_cran()
sample@reductions$diffusion <- sample@reductions$umap
p <- SCpubr::do_DimPlot(sample = sample,
reduction = "diffusion")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - group.by + idents.keep", {
testthat::skip_on_cran()
p <- SCpubr::do_DimPlot(sample = sample,
group.by = "seurat_clusters",
idents.keep = "4")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - split.by + factor", {
testthat::skip_on_cran()
sample$seurat_clusters <- factor(sample$seurat_clusters)
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters", colors.use = colors)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: PASS - split.by + factor + idents.keep", {
testthat::skip_on_cran()
sample$seurat_clusters <- factor(sample$seurat_clusters)
p <- SCpubr::do_DimPlot(sample = sample, split.by = "seurat_clusters", colors.use = colors, idents.keep = "4")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DimPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_DimPlot(sample = sample, font.type = "wrong"))
})
}
================================================
FILE: tests/testthat/test-do_DotPlot.R
================================================
if (isFALSE(dep_check[["do_DotPlot"]])){
testthat::test_that("do_DotPlot: CRAN essentials", {
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - one variable", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1", flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1", flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
max.cutoff = 0.5,
min.cutoff = 0.4)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
zscore.data = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
split.by = "annotation",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
split.by = "annotation",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
zscore.data = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = list("A" = "EPC1"),
zscore.data = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = list("A" = "EPC1"),
zscore.data = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.position = "none")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.position = "none",
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.position = "none",
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - plot grid", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
plot.grid = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
plot.grid = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - use_viridis", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - one variable legend normal", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.type = "normal")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - one variable legend colorbar", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
legend.type = "colorbar")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: FAIL - wrong legend type", {
testthat::skip_on_cran()
testthat::expect_error(suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
flip = TRUE,
legend.type = "wrong")}))
})
testthat::test_that("do_DotPlot: FAIL - wrong legend position", {
testthat::skip_on_cran()
testthat::expect_error(suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
flip = TRUE,
legend.position = "wrong")}))
})
testthat::test_that("do_DotPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
flip = TRUE,
font.type = "wrong")}))
})
testthat::test_that("do_DotPlot: PASS - one variable flip", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - multiple features", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
p <- suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = genes)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - multiple features flip", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
p <- suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = genes,
flip = TRUE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - multiple features flip rotate x labels", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
p <- suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = genes,
flip = TRUE,
axis.text.x.angle = 45)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - one variable xlab, ylab, title, subtitle, caption", {
testthat::skip_on_cran()
p <- SCpubr::do_DotPlot(sample = sample,
features = "EPC1",
xlab = "A",
ylab = "B",
plot.title = "C",
plot.subtitle = "D",
plot.caption = "E")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - cluster.identities", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
p <- suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = genes,
cluster.identities = TRUE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - cluster.features", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
p <- suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = genes,
cluster.features = TRUE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: PASS - cluster both", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
p <- suppressWarnings({SCpubr::do_DotPlot(sample = sample,
features = genes,
cluster.identities = TRUE,
cluster.features = TRUE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_DotPlot: FAIL - cluster with split.by", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:10]
testthat::expect_error({SCpubr::do_DotPlot(sample = sample,
features = genes,
split.by = "annotation",
cluster.identities = TRUE)})
testthat::expect_error({SCpubr::do_DotPlot(sample = sample,
features = genes,
split.by = "annotation",
cluster.features = TRUE)})
})
}
================================================
FILE: tests/testthat/test-do_EnrichmentHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_EnrichmentHeatmap"]])){
testthat::test_that("do_EnrichmentHeatmap: CRAN essential", {
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: PASS -flavors", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
cluster = TRUE)
testthat::expect_true("ggplot" %in% class(p))
genes <- list("A-A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
testthat::expect_warning(p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
cluster = TRUE,
values.show = TRUE,
values.threshold = 0.2))
testthat::expect_true("ggplot" %in% class(p))
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
cluster = FALSE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
cluster = TRUE,
features.order = c("B", "A", "C"))
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
cluster = TRUE,
features.order = c("B", "A", "C"),
groups.order = list("Groups" = c("1", "3", "5", "7", "0", "2", "4", "6", "8")))
testthat::expect_true("ggplot" %in% class(p))
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10,
enforce_symmetry = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10,
enforce_symmetry = FALSE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10,
enforce_symmetry = FALSE,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10,
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10,
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true("ggplot" %in% class(p))
genes <- list("A" = rownames(sample)[1:5])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
flip = FALSE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
flip = TRUE)
testthat::expect_true("ggplot" %in% class(p))
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
features.order = c("A", "B", "C"))
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
assay = "SCT",
nbin = 1,
ctrl = 10,
viridis.direction = 1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
assay = "SCT",
nbin = 1,
ctrl = 10,
viridis.direction = -1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "UCell",
slot = "data",
nbin = 1,
ctrl = 10,
viridis.direction = 1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "UCell",
slot = "data",
nbin = 1,
ctrl = 10,
viridis.direction = -1)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: PASS - normal", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
legend.position = "top",
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
legend.position = "right",
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: PASS - group.by", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = "orig.ident",
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: PASS - group.by and flip", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("orig.ident", "seurat_clusters"),
flip = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = "orig.ident",
flip = TRUE,
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: PASS - character list of genes + group by only has 1 entity", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = "orig.ident",
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = c("seurat_clusters", "orig.ident"),
nbin = 1,
ctrl = 10,
return_object = TRUE)
testthat::expect_true("list" %in% class(p))
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
nbin = 1,
ctrl = 10,
return_object = TRUE)
testthat::expect_true("list" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: FAIL - list of genes without name", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
testthat::expect_error(SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = list("EPC1"),
group.by = "orig.ident",
nbin = 1,
ctrl = 10))
testthat::expect_error(SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = list("A" = "EPC1"),
group.by = "wrong",
nbin = 1,
ctrl = 10))
})
testthat::test_that("do_EnrichmentHeatmap: PASS - group by factor", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
sample$seurat_clusters.factor <- factor(sample$seurat_clusters)
p <- SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
group.by = "seurat_clusters.factor",
nbin = 1,
ctrl = 10)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_EnrichmentHeatmap: ERROR - wrong arguments", {
testthat::skip_on_cran()
sample$orig.ident <- ifelse(sample$seurat_clusters %in% c("1", "2"), "A", "B")
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
testthat::expect_warning({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
slot = "data",
nbin = 1,
ctrl = 10)})
testthat::expect_warning({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "UCell",
assay = "SCT",
nbin = 1,
ctrl = 10)})
testthat::expect_error({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
min.cutoff = -10,
nbin = 1,
ctrl = 10)})
testthat::expect_error({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
max.cutoff = 200,
nbin = 1,
ctrl = 10)})
testthat::expect_error({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = genes,
max.cutoff = 1,
min.cutoff = 2,
nbin = 1,
ctrl = 10)})
testthat::expect_error({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = list("A" = "EPC1"),
group.by = c("seurat_clusters", "annotation"),
nbin = 1,
ctrl = 10,
flip = FALSE,
features.order = "wrong")})
testthat::expect_warning({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = list("A_A" = "EPC1"),
group.by = c("seurat_clusters", "annotation"),
nbin = 1,
ctrl = 10,
flip = FALSE)})
testthat::expect_error({SCpubr::do_EnrichmentHeatmap(sample = sample,
input_gene_list = "EPC1",
nbin = 1,
ctrl = 10)})
})
}
================================================
FILE: tests/testthat/test-do_ExpressionHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_ExpressionHeatmap"]])){
testthat::test_that("do_ExpressionHeatmap: CRAN essential tests", {
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5])
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_ExpressionHeatmap: PASS - normal", {
testthat::skip_on_cran()
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
cluster = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
cluster = TRUE,
values.show = TRUE,
values.threshold = 0.2)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
cluster = FALSE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
cluster = TRUE,
features.order = rownames(sample)[c(2, 1, 5, 3, 4)])
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
cluster = TRUE,
features.order = rownames(sample)[c(2, 1, 5, 3, 4)],
groups.order = list("Groups" = c("1", "3", "5", "7", "0", "2", "4", "6", "8")))
testthat::expect_true("ggplot" %in% class(p))
testthat::expect_warning({ p <- SCpubr::do_ExpressionHeatmap(sample,
features = list("A" = rownames(sample)[1:5]),
group.by = "orig.ident",
flip = TRUE)})
testthat::expect_true("ggplot" %in% class(p))
testthat::expect_warning({ p <- SCpubr::do_ExpressionHeatmap(sample,
features = list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10]),
group.by = "orig.ident",
flip = TRUE)})
testthat::expect_true("ggplot" %in% class(p))
testthat::expect_warning({ p <- SCpubr::do_ExpressionHeatmap(sample,
features = c("TOX2", "Wront"),
group.by = "orig.ident",
flip = TRUE)})
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
flip = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
flip = FALSE)
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = c("orig.ident", "seurat_clusters"),
flip = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = c("orig.ident", "seurat_clusters"),
flip = FALSE)
testthat::expect_true("ggplot" %in% class(p))
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
enforce_symmetry = TRUE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
enforce_symmetry = FALSE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
enforce_symmetry = FALSE,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
flip = FALSE)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = c("orig.ident", "seurat_clusters"),
flip = TRUE)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_ExpressionHeatmap: PASS - assay", {
testthat::skip_on_cran()
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
assay = NULL)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
assay = "SCT")
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_ExpressionHeatmap: PASS - legend.position", {
testthat::skip_on_cran()
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
legend.position = "bottom")
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
legend.position = "right")
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_ExpressionHeatmap: PASS - cutoffs", {
testthat::skip_on_cran()
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
assay = NULL,
min.cutoff = 0.7)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
assay = "SCT",
max.cutoff = 0.72)
testthat::expect_true("ggplot" %in% class(p))
p <- SCpubr::do_ExpressionHeatmap(sample,
features = rownames(sample)[1:5],
group.by = "orig.ident",
assay = "SCT",
min.cutoff = 0.7,
max.cutoff = 0.72)
testthat::expect_true("ggplot" %in% class(p))
})
testthat::test_that("do_ExpressionHeatmap: FAIL", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_ExpressionHeatmap(sample = sample,
features = "EPC1",
min.cutoff = -10)})
testthat::expect_error({SCpubr::do_ExpressionHeatmap(sample = sample,
features = "EPC1",
max.cutoff = 200)})
testthat::expect_error({SCpubr::do_ExpressionHeatmap(sample = sample,
features = "EPC1",
max.cutoff = 1,
min.cutoff = 2)})
})
}
================================================
FILE: tests/testthat/test-do_FeaturePlot.R
================================================
if (base::isFALSE(dep_check[["do_FeaturePlot"]])){
testthat::test_that("do_FeaturePlot: CRAN essential", {
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - single feature", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
slot = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - group.by", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = TRUE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = TRUE,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = TRUE,
use_viridis = TRUE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = TRUE,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = NA)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = "Test")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = NULL,
group.by.colors.use = c("Cell" = "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = NULL,
group.by.colors.use = c("Cell" = "blue"),
group.by.cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
idents.highlight = "0",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = NULL,
group.by.colors.use = c("Cell" = "blue"),
group.by.cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("TOX2", "EPC1"),
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("TOX2", "EPC1"),
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
use_viridis = FALSE,
sequential.direction = 1,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
use_viridis = FALSE,
sequential.direction = -1,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("TOX2", "EPC1"),
use_viridis = FALSE,
sequential.direction = 1,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("TOX2", "EPC1"),
use_viridis = FALSE,
sequential.direction = -1,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
group.by = "seurat_clusters",
group.by.show.dots = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
group.by = "seurat_clusters",
group.by.show.dots = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = NA)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = "Test")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = "Test",
group.by.colors.use = c("Cell" = "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "seurat_clusters",
group.by.show.dots = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "seurat_clusters",
group.by.show.dots = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = NA)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "seurat_clusters",
group.by.show.dots = TRUE,
group.by.legend = "Test")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = "Test",
group.by.colors.use = c("Cell" = "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = "Test",
group.by.colors.use = c("Cell" = "blue"),
group.by.cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = "Test",
group.by.colors.use = c("Cell" = "blue"),
group.by.cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- as.factor(sample$orig.ident)
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "orig.ident",
use_viridis = FALSE,
enforce_symmetry = FALSE,
group.by = "orig.ident",
group.by.show.dots = TRUE,
group.by.legend = "Test")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - cutoffs", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
min.cutoff = 19500,
max.cutoff = 20000)
testthat::expect_true(ggplot2::is_ggplot(p))
testthat::expect_warning({p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("TOX2", "EPC1"),
min.cutoff = 1)})
testthat::expect_true(ggplot2::is_ggplot(p))
testthat::expect_warning({p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("TOX2", "EPC1"),
max.cutoff = 1)})
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "seurat_clusters",
min.cutoff = 19500,
max.cutoff = 20000)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("nCount_RNA", "EPC1"),
min.cutoff = c(19500, 1),
max.cutoff = c(20000, 2))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
split.by = "annotation",
features = c("nCount_RNA", "EPC1"),
min.cutoff = c(19500, 1),
max.cutoff = c(20000, 2))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - contour", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
plot_density_contour = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
plot_density_contour = TRUE,
contour.position = "bottom")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
plot_density_contour = TRUE,
contour.position = "bottom",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
plot_density_contour = TRUE,
contour.position = "top",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "bottom")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
split.by = "annotation",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "bottom",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
idents.highlight = "0",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
idents.highlight = "0",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "bottom")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
idents.highlight = "0",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "top",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
feature = "nCount_RNA",
idents.highlight = "0",
raster = TRUE,
plot_density_contour = TRUE,
contour.position = "bottom",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - legend.title", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
legend.title = "pepe")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
legend.title = "pepe",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - cell_borders", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE, raster = TRUE, pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE, idents.highlight = "1")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE, raster = TRUE, idents.highlight = "1", pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE, split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE, raster = TRUE, split.by = "seurat_clusters", pt.size = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - enforce_symmetry", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = c("EPC1", "nCount_RNA"), enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", enforce_symmetry = TRUE, idents.highlight = c("1", "3"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, features = "EPC1", enforce_symmetry = TRUE, split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - multiple features", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("nCount_RNA", "nFeature_RNA"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - title", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
plot.title = "Feature Plot")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - subtitle", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
plot.subtitle = "Feature Plot")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - caption", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
plot.caption = "Feature Plot")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - individual titles", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("nCount_RNA", "nFeature_RNA"),
individual.titles = c("A", NA))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - individual subtitles ", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("nCount_RNA", "nFeature_RNA"),
individual.subtitles = c("A", NA))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - individual captions", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = c("nCount_RNA", "nFeature_RNA"),
individual.captions = c("A", NA))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - dims", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
dims = c(2, 1))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - subset of cells", {
testthat::skip_on_cran()
cells.plot <- colnames(sample[, !(sample$seurat_clusters %in% c("2", "5", "8"))])
p <- SCpubr::do_FeaturePlot(sample,
features = "EPC1",
cells.highlight = cells.plot)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - subset of identities", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "EPC1",
idents.highlight = c("1", "2"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - subset of cells and identities", {
testthat::skip_on_cran()
cells.plot <- colnames(sample[, !(sample$seurat_clusters %in% c("2", "5", "8"))])
p <- SCpubr::do_FeaturePlot(sample,
features = "EPC1",
cells.highlight = cells.plot,
idents.highlight = c("1", "2"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "EPC1",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by and idents.keep", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "EPC1",
split.by = "seurat_clusters",
idents.keep = c("1", "2"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by and idents.keep multiple features", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = c("EPC1", "nCount_RNA"),
split.by = "seurat_clusters",
idents.keep = c("1", "2"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - modify color maps", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "nCount_RNA",
viridis.palette = "F")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: WARNING - features as a list", {
testthat::skip_on_cran()
testthat::expect_warning(SCpubr::do_FeaturePlot(sample,
features = list("A" = "nCount_RNA")))
})
testthat::test_that("do_FeaturePlot: FAIL - individual titles, subtitles or captions do not match with number of features", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_FeaturePlot(sample,
features = c("nCount_RNA", "EPC1"),
individual.titles = "A"))
testthat::expect_error(SCpubr::do_FeaturePlot(sample,
features = c("nCount_RNA", "EPC1"),
individual.subtitles = "A"))
testthat::expect_error(SCpubr::do_FeaturePlot(sample,
features = c("nCount_RNA", "EPC1"),
individual.captions = "A"))
})
testthat::test_that("do_FeaturePlot: PASS - legend position = right", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "nCount_RNA",
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - ussing diffusion reduction", {
testthat::skip_on_cran()
test <- sample@reductions$umap[[]]
colnames(test) <- c("DC_1", "DC_2")
obj <- Seurat::CreateDimReducObject(test, assay = "SCT", key = "DC_")
sample@reductions$diffusion <- obj
p <- SCpubr::do_FeaturePlot(sample,
features = "nCount_RNA",
reduction = "diffusion")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - duplicated idents.keep", {
testthat::skip_on_cran()
testthat::expect_message(SCpubr::do_FeaturePlot(sample,
features = "nCount_RNA",
split.by = "seurat_clusters",
idents.keep = c("2", "2")))
})
testthat::test_that("do_FeaturePlot: PASS - plotting a Dimensional reduction component", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by factor", {
testthat::skip_on_cran()
sample$factor_seurat_clusters <- factor(sample$seurat_clusters, levels = c("2", "0", "1", "3", "4", "5", "6", "7", "8"))
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
split.by = "factor_seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by and plot.title", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
split.by = "seurat_clusters",
plot.title = "Title",
plot.subtitle = "Subtitle",
plot.caption = "Caption")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by and pca", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
split.by = "seurat_clusters",
reduction = "pca")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - split.by and diffusion", {
testthat::skip_on_cran()
test <- sample@reductions$umap[[]]
colnames(test) <- c("DC_1", "DC_2")
obj <- Seurat::CreateDimReducObject(test, assay = "SCT", key = "DC_")
sample@reductions$diffusion <- obj
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
split.by = "seurat_clusters",
reduction = "diffusion")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - remove legend", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.position = "none")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - normal legend", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.type = "normal")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - colorbar legend", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.type = "colorbar")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - normal legend - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.type = "normal",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - colorbar legend - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.type = "colorbar",
split.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: FAIL - wrong legend type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.type = "wrong"))
})
testthat::test_that("do_FeaturePlot: FAIL - wrong legend position", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_FeaturePlot(sample,
features = "PC_1",
legend.position = "wrong"))
})
testthat::test_that("do_FeaturePlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_FeaturePlot(sample,
features = "PC_1",
font.type = "wrong"))
})
testthat::test_that("do_FeaturePlot: PASS - plot axis", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample, plot.axes = TRUE, features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, reduction = "pca", plot.axes = TRUE, features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_FeaturePlot(sample = sample, dims = c(2, 1), plot.axes = TRUE, features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
sample@reductions$diffusion <- sample@reductions$umap
p <- SCpubr::do_FeaturePlot(sample = sample,
reduction = "diffusion",
plot.axes = TRUE,
features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - scale limits", {
testthat::skip_on_cran()
p <- SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
scale.limits = c(0, 1))
testthat::expect_true(ggplot2::is_ggplot(p))
testthat::expect_error(SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
scale.limits = c(0, 1),
min.cutoff = 0.2))
testthat::expect_error(SCpubr::do_FeaturePlot(sample = sample,
features = "nCount_RNA",
scale.limits = c(0, 1),
max.cutoff = 0.2))
})
}
================================================
FILE: tests/testthat/test-do_GroupwiseDEHeatmap.R
================================================
if(base::isFALSE(dep_check[["do_GroupwiseDEHeatmap"]])){
testthat::test_that("do_GroupwiseDEHeatmap: CRAN essentials", {
if (utils::packageVersion("Seurat") < "5.0.0"){
sample <- SeuratObject::SetAssayData(object = sample,
assay = "SCT",
slot = "scale.data",
new.data = as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "SCT",
slot = "data")))
} else {
sample <- SeuratObject::SetAssayData(object = sample,
assay = "SCT",
layer = "scale.data",
new.data = as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "SCT",
layer = "data")))
}
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes_scaled,
assay = "SCT",
slot = "scale.data")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_GroupwiseDEHeatmap: PASS - default", {
testthat::skip_on_cran()
if (utils::packageVersion("Seurat") < "5.0.0"){
sample <- SeuratObject::SetAssayData(object = sample,
assay = "SCT",
slot = "scale.data",
new.data = as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "SCT",
slot = "data")))
} else {
sample <- SeuratObject::SetAssayData(object = sample,
assay = "SCT",
layer = "scale.data",
new.data = as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "SCT",
layer = "data")))
}
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = FALSE,
sequential.direction = 1,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = FALSE,
sequential.direction = 1,
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = FALSE,
sequential.direction = -1,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = FALSE,
sequential.direction = -1,
flip = FALSE,
legend.title = "Test")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes_scaled,
assay = "SCT",
slot = "scale.data")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes_scaled,
assay = "SCT",
slot = "scale.data",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes_scaled,
assay = "SCT",
slot = "scale.data",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 1,
max.cutoff = 1.2,
min.cutoff = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 1,
min.cutoff = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 1,
max.cutoff = 1.2)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_GroupwiseDEHeatmap: PASS - heatmap legend side", {
testthat::skip_on_cran()
if (utils::packageVersion("Seurat") < "5.0.0"){
sample <- SeuratObject::SetAssayData(object = sample,
assay = "SCT",
slot = "scale.data",
new.data = as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "SCT",
slot = "data")))
} else {
sample <- SeuratObject::SetAssayData(object = sample,
assay = "SCT",
layer = "scale.data",
new.data = as.matrix(SeuratObject::GetAssayData(object = sample,
assay = "SCT",
layer = "data")))
}
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes_scaled,
assay = "SCT",
slot = "scale.data",
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_GroupwiseDEHeatmap: FAIL - wrong direction", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 0)})
})
testthat::test_that("do_ExpressionHeatmap: FAIL", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 1,
min.cutoff = -10)})
testthat::expect_error({SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 1,
max.cutoff = 200)})
testthat::expect_error({SCpubr::do_GroupwiseDEHeatmap(sample = sample,
de_genes = de_genes,
assay = "SCT",
slot = "data",
viridis.direction = 1,
max.cutoff = 1,
min.cutoff = 2)})
})
}
================================================
FILE: tests/testthat/test-do_LigandReceptorPlot.R
================================================
if(base::isFALSE(dep_check[["do_LigandReceptorPlot"]])){
testthat::test_that("do_LigandReceptorPlot: CRAN essentials", {
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: PASS - from output", {
testthat::skip_on_cran()
suppressMessages({testthat::expect_message({p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = TRUE)})})
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages(p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, sort.by = "A", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending", verbose = TRUE))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "A", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages(p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, sort.by = "B", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending", verbose = TRUE))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "B", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages(p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, sort.by = "C", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending", verbose = TRUE))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "C", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages(p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, sort.by = "D", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending", verbose = TRUE))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "D", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
suppressMessages(p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, sort.by = "E", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending", verbose = TRUE))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = TRUE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = TRUE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "ascending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "ascending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending")
testthat::expect_true(ggplot2::is_ggplot(p))
out <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE, sort.by = "E", invert_specificity = FALSE, invert_magnitude = FALSE, sorting.type.specificity = "descending", sorting.type.magnitude = "descending", return_interactions = TRUE)
testthat::expect_type(out, "list")
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = TRUE, use_viridis = TRUE, viridis.direction = 1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = TRUE, use_viridis = TRUE, viridis.direction = -1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = TRUE, use_viridis = FALSE, sequential.direction = -1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = TRUE, use_viridis = FALSE, sequential.direction = 1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = FALSE, use_viridis = TRUE, viridis.direction = 1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = FALSE, use_viridis = TRUE, viridis.direction = -1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = FALSE, use_viridis = FALSE, sequential.direction = -1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, dot_border = FALSE, use_viridis = FALSE, sequential.direction = 1, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, plot.grid = TRUE, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, plot.grid = FALSE, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, plot.grid = TRUE, dot_border = FALSE, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
keep_source = c("NK", "B"),
keep_target = "CD8 T", verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: PASS - from output different n", {
testthat::skip_on_cran()
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
top_interactions = 50, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: PASS - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
split.by = "ligand.complex", verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
split.by = "receptor.complex", verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: PASS - from output, angle ", {
testthat::skip_on_cran()
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
axis.text.x.angle = 0, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
axis.text.x.angle = 45, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
axis.text.x.angle = 90, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: PASS - from output legend.position", {
testthat::skip_on_cran()
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
top_interactions = 50,
legend.position = "bottom", verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
top_interactions = 50,
legend.position = "right", verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: PASS - sort interactions", {
testthat::skip_on_cran()
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
top_interactions = 50,
sort_interactions_alphabetically = TRUE, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
top_interactions = 50,
sort_interactions_alphabetically = FALSE, verbose = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LigandReceptorPlot: FAIL - wrong parameters", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
font.type = "wrong", verbose = FALSE)})
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
legend.type = "wrong", verbose = FALSE)})
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
axis.text.x.angle = 10, verbose = FALSE)})
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
font.type = "wrong", verbose = FALSE)})
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
legend.position = "wrong", verbose = FALSE)})
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
grid.type = "wrong", verbose = FALSE)})
testthat::expect_error({SCpubr::do_LigandReceptorPlot(liana_output = liana_output,
split.by = "wrong", verbose = FALSE)})
})
}
================================================
FILE: tests/testthat/test-do_LoadingsHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_LoadingsHeatmap"]])){
testthat::test_that("do_LoadingsHeatmap: CRAN essentials", {
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:5)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_LoadingsHeatmap: PASS - default", {
testthat::skip_on_cran()
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
min.cutoff.loadings = 0.5)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
max.cutoff.loadings = 0.5)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
min.cutoff.expression = 0.5)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
max.cutoff.expression = 0.5)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
subsample = 100)
testthat::expect_true(ggplot2::is_ggplot(p))
sample$test <- as.factor(sample$seurat_clusters)
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
group.by = "test")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
min.cutoff.loadings = -0.01,
max.cutoff.loadings = 0.01,
min.cutoff.expression = 0,
max.cutoff.expression = 0.75)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_LoadingsHeatmap(sample = sample,
dims = 1:10,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_MetadataHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_MetadataHeatmap"]])){
testthat::test_that("do_MetadataHeatmap: CRAN essentials", {
df <- data.frame(row.names = letters[1:5],
"A" = as.character(seq(1, 5)),
"B" = rev(as.character(seq(1, 5))))
p <- SCpubr::do_MetadataHeatmap(from_df = TRUE,
df = df)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_MetadataHeatmap: PASS - default", {
testthat::skip_on_cran()
df <- data.frame(row.names = letters[1:5],
"A" = as.character(seq(1, 5)),
"B" = rev(as.character(seq(1, 5))),
"C" = c("1", "2", "3", "5", "7"))
p <- SCpubr::do_MetadataHeatmap(from_df = TRUE,
df = df,
flip = FALSE,
legend.symbol.size = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_MetadataHeatmap(from_df = TRUE,
df = df,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
sample$labelling <- sample(c("A", "B"), ncol(sample), replace = TRUE)
p <- SCpubr::do_MetadataHeatmap(sample = sample,
group.by = "labelling",
metadata = "orig.ident",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_MetadataHeatmap(sample = sample,
group.by = "labelling",
metadata = "orig.ident",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_NebulosaPlot.R
================================================
if(base::isFALSE(dep_check[["do_NebulosaPlot"]])){
testthat::test_that("do_NebulosaPlot: CRAN essentials", {
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - single feature", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = TRUE,
viridis.direction = 1,
joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = TRUE,
viridis.direction = -1,
joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = FALSE,
sequential.direction = 1,
joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "TOX2"),
use_viridis = FALSE,
sequential.direction = -1,
joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - cell_borders", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample, features = "EPC1", plot_cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- suppressWarnings({SCpubr::do_NebulosaPlot(sample = sample, features = c("EPC1", "PC_1"), plot_cell_borders = TRUE)})
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - single feature legend normal", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.type = "normal")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - single feature legend colorbar", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.type = "colorbar")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: FAIL - wrong legend type ", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.type = "wrong"))
})
testthat::test_that("do_NebulosaPlot: FAIL - wrong legend position ", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.position = "wrong"))
})
testthat::test_that("do_NebulosaPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
font.type = "wrong"))
})
testthat::test_that("do_NebulosaPlot: PASS - single feature distinct dims", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
dims = c(2, 1))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_FeaturePlot: PASS - diffusion", {
testthat::skip_on_cran()
test <- sample@reductions$umap[[]]
colnames(test) <- c("DC_1", "DC_2")
obj <- Seurat::CreateDimReducObject(test, assay = "SCT", key = "DC_")
sample@reductions$diffusion <- obj
p <- suppressWarnings(SCpubr::do_NebulosaPlot(sample,
features = "PC_1",
reduction = "diffusion"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - several", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - several, joint", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"),
joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - several, joint only joint", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"),
joint = TRUE,
return_only_joint = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - title", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"),
joint = TRUE,
return_only_joint = TRUE,
plot.title = "Title")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - subtitle", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"),
joint = TRUE,
return_only_joint = TRUE,
plot.subtitle = "Subtitle")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - caption", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"),
joint = TRUE,
return_only_joint = TRUE,
plot.caption = "Caption")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - color map", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
viridis.palette = "F")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - legend top", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.position = "left")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - legend top", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.position = "top")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: WARNING - features as list", {
testthat::skip_on_cran()
testthat::expect_warning(SCpubr::do_NebulosaPlot(sample = sample,
features = list("EPC1"),
viridis.palette = "F"))
})
testthat::test_that("do_NebulosaPlot: PASS - no legend", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = "EPC1",
legend.position = "none")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - patchwork title, subtitle and caption", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample,
features = c("EPC1", "LTV1"),
plot.title = "A",
plot.subtitle = "B",
plot.caption = "C")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_NebulosaPlot: PASS - plot axis", {
testthat::skip_on_cran()
p <- SCpubr::do_NebulosaPlot(sample = sample, plot.axes = TRUE, features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample, reduction = "pca", plot.axes = TRUE, features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_NebulosaPlot(sample = sample, dims = c(2, 1), plot.axes = TRUE, features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
sample@reductions$diffusion <- sample@reductions$umap
p <- SCpubr::do_NebulosaPlot(sample = sample,
reduction = "diffusion",
plot.axes = TRUE,
features = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_PathwayActivityHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_PathwayActivityHeatmap"]])){
testthat::test_that("do_PathwayActivityHeatmap: CRAN essentials", {
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_PathwayActivityHeatmap: PASS - minimal input", {
testthat::skip_on_cran()
sample$annotation <- sample(c("A", "B"), ncol(sample), replace = TRUE)
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
values.show = TRUE,
values.threshold = 0.2)
testthat::expect_true(ggplot2::is_ggplot(out))
sample$annotation <- sample(c("A", "B"), ncol(sample), replace = TRUE)
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
sample$annotation <- sample(c("A", "B"), ncol(sample), replace = TRUE)
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
group.by = c("orig.ident", "seurat_clusters", "annotation"))
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
split.by = "annotation")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
legend.position = "right",
return_object = TRUE)
testthat::expect_type(out, "list")
})
testthat::test_that("do_PathwayActivityHeatmap: PASS - all group.by", {
testthat::skip_on_cran()
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_PathwayActivityHeatmap: PASS - all split.by 2", {
testthat::skip_on_cran()
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
min.cutoff = -0.1,
max.cutoff = NA)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
min.cutoff = NA,
max.cutoff = 0.1)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
min.cutoff = -0.1)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
max.cutoff = 0.1)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
max.cutoff = 0.1,
min.cutoff = -0.1)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_PathwayActivityHeatmap: FAIL", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
min.cutoff = -10)})
testthat::expect_error({SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
max.cutoff = 200)})
testthat::expect_error({SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
max.cutoff = 1,
min.cutoff = 2)})
sample$annotation <- sample(c("A", "B"), ncol(sample), replace = TRUE)
testthat::expect_error({SCpubr::do_PathwayActivityHeatmap(sample = sample,
activities = progeny_activities,
group.by = c("seurat_clusters", "orig.ident"),
split.by = "annotation")})
})
}
================================================
FILE: tests/testthat/test-do_RankedEnrichmentHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_RankedEnrichmentHeatmap"]])){
testthat::test_that("do_RankedEnrichmentHeatmap: CRAN essentials", {
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = NA,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
verbose = FALSE)
testthat::expect_type(p, "list")
})
testthat::test_that("do_RankedEnrichmentHeatmap: PASS - default", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = NA,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "Seurat",
use_viridis = TRUE,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = NA,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "Seurat",
use_viridis = FALSE,
sequential.direction = 1,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = NA,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "Seurat",
use_viridis = FALSE,
sequential.direction = -1,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = 120,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "UCell",
use_viridis = FALSE,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
testthat::expect_warning({SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "UCell",
assay = "SCT",
use_viridis = FALSE,
enforce_symmetry = FALSE)})
testthat::expect_warning({SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "Seurat",
slot = "data",
use_viridis = FALSE,
enforce_symmetry = FALSE)})
suppressMessages({testthat::expect_message({p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = TRUE)})})
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
subsample = 100,
group.by = c("orig.ident", "seurat_clusters"),
colors.use = list("orig.ident" = c("Cell" = "red")),
nbin = 1,
ctrl = 5,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
flavor = "UCell",
use_viridis = FALSE,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
})
}
================================================
FILE: tests/testthat/test-do_RankedExpressionHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_RankedExpressionHeatmap"]])){
testthat::test_that("do_RankedExpressionHeatmap: CRAN essentials", {
genes <- Seurat::VariableFeatures(sample)[1:30]
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = NA,
reduction = "umap",
dims = 1:2,
verbose = FALSE)
testthat::expect_type(p, "list")
})
testthat::test_that("do_RankedExpressionHeatmap: PASS - default", {
testthat::skip_on_cran()
genes <- Seurat::VariableFeatures(sample)[1:30]
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = NA,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
use_viridis = TRUE,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = NA,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
use_viridis = FALSE,
sequential.direction = 1,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = NA,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
use_viridis = FALSE,
sequential.direction = -1,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = 120,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
use_viridis = FALSE,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = 100,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
assay = "SCT",
use_viridis = FALSE,
enforce_symmetry = FALSE)
SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = 100,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
slot = "data",
use_viridis = FALSE,
enforce_symmetry = FALSE)
suppressMessages({testthat::expect_message({p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = 100,
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = TRUE)})})
testthat::expect_type(p, "list")
p <- SCpubr::do_RankedExpressionHeatmap(sample = sample,
features = genes,
subsample = 100,
group.by = c("orig.ident", "seurat_clusters"),
colors.use = list("orig.ident" = c("Cell" = "red")),
reduction = "umap",
dims = 1:2,
return_object = TRUE,
verbose = FALSE,
use_viridis = FALSE,
enforce_symmetry = FALSE)
testthat::expect_type(p, "list")
})
}
================================================
FILE: tests/testthat/test-do_RidgePlot.R
================================================
if(base::isFALSE(dep_check[["do_RidgePlot"]])){
testthat::test_that("do_RidgePlot: CRAN essentials", {
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_RidgePlot: PASS - default", {
testthat::skip_on_cran()
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = FALSE,
group.by = "annotation",
colors.use = c("A" = "red", "B" = "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
split.by = "annotation",
continuous_scale = TRUE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- factor(sample$orig.ident)
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
legend.position = "bottom")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident",
legend.position = "bottom",
colors.use = c("Cell" = "red"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_RidgePlot: PASS - plot.grid", {
testthat::skip_on_cran()
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
plot.grid = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
plot.grid = TRUE,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
plot.grid = TRUE,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
plot.grid = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_RidgePlot: PASS - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_RidgePlot: PASS - continuous scale", {
testthat::skip_on_cran()
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
continuous_scale = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_RidgePlot: PASS - group.by", {
testthat::skip_on_cran()
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nCount_RNA",
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_RidgePlot: PASS - flip", {
testthat::skip_on_cran()
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nFeature_RNA",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_RidgePlot(sample = sample,
feature = "nFeature_RNA",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_SCEnrichmentHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_SCEnrichmentHeatmap"]])){
testthat::test_that("do_SCEnrichmentHeatmap: CRAN essentials", {
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
assay = "SCT",
nbin = 1,
ctrl = 5)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_SCEnrichmentHeatmap: PASS - default", {
testthat::skip_on_cran()
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
assay = "SCT",
nbin = 1,
ctrl = 5,
cluster = FALSE,
features.order = c("B", "C", "A"))
testthat::expect_true(ggplot2::is_ggplot(p))
genes <- list("A_A" = rownames(sample)[1:5],
"B_A" = rownames(sample)[6:10],
"C_A" = rownames(sample)[11:15])
suppressWarnings({testthat::expect_warning({p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
assay = "SCT",
slot = "data",
nbin = 1,
ctrl = 5)})})
testthat::expect_true(ggplot2::is_ggplot(p))
genes <- list("A" = rownames(sample)[1:5],
"B" = rownames(sample)[6:10],
"C" = rownames(sample)[11:15])
testthat::expect_error({p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = "EPC1",
flavor = "Seurat",
assay = "SCT",
nbin = 1,
ctrl = 5)})
sample$test <- as.factor(sample$seurat_clusters)
genes <- list("A" = rownames(sample)[1:5])
testthat::expect_warning({p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
assay = "SCT",
slot = "data",
nbin = 1,
ctrl = 5)})
testthat::expect_true(ggplot2::is_ggplot(p))
testthat::expect_warning({p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "UCell",
assay = "SCT",
nbin = 1,
ctrl = 5)})
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5,
use_viridis = TRUE,
viridis.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5,
use_viridis = TRUE,
viridis.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
metadata = c("seurat_clusters", "orig.ident"),
min.cutoff = 0,
max.cutoff = 0.5,
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCEnrichmentHeatmap(sample = sample,
input_gene_list = genes,
flavor = "Seurat",
nbin = 1,
ctrl = 5,
return_object = TRUE)
testthat::expect_type(p, "list")
})
}
================================================
FILE: tests/testthat/test-do_SCExpressionHeatmap.R
================================================
if (base::isFALSE(dep_check[["do_SCExpressionHeatmap"]])){
testthat::test_that("do_SCExpressionHeatmap: CRAN essentials", {
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5])
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_SCExpressionHeatmap: PASS - default", {
testthat::skip_on_cran()
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
features.order = rownames(sample)[c(4, 2, 1, 3, 5)],
cluster = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5])
testthat::expect_true(ggplot2::is_ggplot(p))
testthat::expect_warning({p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = c(rownames(sample)[1:5], "pepe"))})
testthat::expect_true(ggplot2::is_ggplot(p))
sample$test <- as.factor(sample$seurat_clusters)
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
group.by = "test")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
subsample = 100)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1])
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
cluster = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"),
metadata.colors = list("orig.ident" = c("Cell" = "blue")))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"),
min.cutoff = 1,
max.cutoff = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"),
min.cutoff = 1,
max.cutoff = 2,
proportional.size = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"),
min.cutoff = 1,
max.cutoff = 2,
proportional.size = FALSE,
enforce_symmetry = FALSE,
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"),
min.cutoff = 1,
max.cutoff = 2,
proportional.size = FALSE,
enforce_symmetry = FALSE,
use_viridis = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_SCExpressionHeatmap(sample = sample,
features = rownames(sample)[1:5],
metadata = c("orig.ident", "seurat_clusters"),
min.cutoff = 1,
max.cutoff = 2,
proportional.size = FALSE,
enforce_symmetry = TRUE,
use_viridis = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-do_StripPlot.R
================================================
if(base::isFALSE(dep_check[["do_StripPlot"]])){
testthat::test_that("do_StripPlot: CRAN essentials", {
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- sample(c("A", "B"), ncol(sample), replace = TRUE)
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
split.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - default parameters", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "nCount_RNA",
scale_type = "categorical",
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "nCount_RNA",
scale_type = "categorical",
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
sample$seurat_clusters <- as.character(sample$seurat_clusters)
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - flip", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - cutoffs", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
min.cutoff = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
enforce_symmetry = FALSE,
use_viridis = FALSE,
sequential.direction = -1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
min.cutoff = 1)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
max.cutoff = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
max.cutoff = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
min.cutoff = 1,
max.cutoff = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
min.cutoff = 1,
max.cutoff = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - default parameters = symmetrical scale", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
enforce_symmetry = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - default parameters = categorical scale", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$seurat_clusters_character <- as.character(sample$seurat_clusters)
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
group.by = "seurat_clusters_character",
colors.use = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - categorical colors.use", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
group.by = "orig.ident",
colors.use = c("Cell" = "green"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "categorical",
group.by = "orig.ident",
colors.use = NULL)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - order by mean", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
order = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
order = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - plot cell borders", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
plot_cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
split.by = "seurat_clusters",
plot_cell_borders = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "continuous",
split.by = "seurat_clusters",
plot_cell_borders = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_BarPlot: FAIL - wrong paramters", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
scale_type = "wrong"))
testthat::expect_error(SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
split.by = "wrong"))
testthat::expect_error(SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
group.by = "wrong"))
testthat::expect_error(SCpubr::do_StripPlot(sample = sample,
features = "EPC1",
jitter = 1))
})
testthat::test_that("do_StripPlot: PASS - show legend", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_StripPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_StripPlot: PASS - several features", {
testthat::skip_on_cran()
p <- SCpubr::do_StripPlot(sample = sample,
features = c("EPC1", "PC_1"))
testthat::expect_type(p, "list")
testthat::expect_length(p, 2)
})
}
================================================
FILE: tests/testthat/test-do_TFActivityHeatmap.R
================================================
if(base::isFALSE(dep_check[["do_TFActivityHeatmap"]])){
testthat::test_that("do_TFActivityHeatmap: PASS - minimal input", {
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_TFActivityHeatmap: PASS - minimal input", {
testthat::skip_on_cran()
sample$annotation <- sample(c("A", "B"), ncol(sample), replace = TRUE)
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
enforce_symmetry = FALSE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
enforce_symmetry = FALSE,
values.show = TRUE,
values.threshold = 0.5)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
group.by = c("orig.ident", "seurat_clusters", "annotation"))
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
tfs.use = c("PDX1", "E2F1"))
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
split.by = "annotation")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(out))
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
legend.position = "right",
return_object = TRUE)
testthat::expect_type(out, "list")
})
testthat::test_that("do_TFActivityHeatmap: PASS - minimal input", {
testthat::skip_on_cran()
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_TFActivityHeatmap: PASS - all group.by", {
testthat::skip_on_cran()
out <- SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(out))
})
testthat::test_that("do_TFActivityHeatmap: FAIL", {
testthat::skip_on_cran()
testthat::expect_error({SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
min.cutoff = -10)})
testthat::expect_error({SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
max.cutoff = 200)})
testthat::expect_error({SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
max.cutoff = 1,
min.cutoff = 2)})
sample$annotation <- sample(c("A", "B"), ncol(sample), replace = TRUE)
testthat::expect_error({SCpubr::do_TFActivityHeatmap(sample = sample,
activities = dorothea_activities,
group.by = c("seurat_clusters", "orig.ident"),
split.by = "annotation")})
})
}
================================================
FILE: tests/testthat/test-do_TermEnrichmentPlot.R
================================================
if(base::isFALSE(dep_check[["do_TermEnrichmentPlot"]])){
testthat::test_that("do_TermEnrichmentPlot: CRAN essentials", {
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
n.terms = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_TermEnrichmentPlot: PASS - legend position = right", {
testthat::skip_on_cran()
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
legend.position = "right")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_TermEnrichmentPlot: PASS - number of terms", {
testthat::skip_on_cran()
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
n.terms = 20)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_TermEnrichmentPlot: PASS - length of terms", {
testthat::skip_on_cran()
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
n.terms = 2,
n.chars = 20)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_TermEnrichmentPlot: PASS - modify colors", {
testthat::skip_on_cran()
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
n.terms = 2,
sequential.palette = "YlOrRd")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_TermEnrichmentPlot: PASS - single database legend types", {
testthat::skip_on_cran()
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
n.terms = 2,
legend.type = "normal")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_TermEnrichmentPlot(mat = enriched_terms,
n.terms = 2,
legend.type = "colorbar")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_TermEnrichmentPlot: FAIL - wrong legend.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_TermEnrichmentPlot(enriched_terms = enriched_terms,
n.terms = 2,
legend.type = "wrong"))
})
testthat::test_that("do_TermEnrichmentPlot: FAIL - wrong legend.position", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_TermEnrichmentPlot(enriched_terms = enriched_terms,
n.terms = 2,
legend.position = "wrong"))
})
testthat::test_that("do_TermEnrichmentPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_TermEnrichmentPlot(enriched_terms = enriched_terms,
n.terms = 2,
font.type = "wrong"))
})
}
================================================
FILE: tests/testthat/test-do_ViolinPlot.R
================================================
if(base::isFALSE(dep_check[["do_ViolinPlot"]])){
testthat::test_that("do_ViolinPlot: CRAN essentials", {
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
order = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - one variable", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot.grid = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot.grid = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - split.by", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
split.by = "annotation",
plot_boxplot = FALSE,
order = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - xlab and ylab", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
xlab = "Hi",
ylab = "Hi")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - flip", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - two variable", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = c("EPC1", "TOX2"),
plot.grid = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = c("EPC1", "TOX2"),
plot.grid = TRUE,
share.y.lims = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = c("EPC1", "TOX2"),
plot.grid = TRUE,
xlab = c("A", "A"),
ylab = c("B", "B"),
y_cut = c(400, 400))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = c("EPC1", "TOX2"),
plot.grid = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - group.by", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot.grid = TRUE,
group.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
sample$seurat_clusters <- as.character(sample$seurat_clusters)
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot.grid = FALSE,
group.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - without boxplot", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot_boxplot = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - rotate axis", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
axis.text.x.angle = 45)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - plot.grid", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot.grid = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - one features ycut", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
axis.text.x.angle = 45,
y_cut = 2)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - one features line width", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
axis.text.x.angle = 45,
y_cut = 2,
line_width = 3)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - one features boxplot width", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
axis.text.x.angle = 45,
y_cut = 2,
boxplot_width = 0.1)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - change colors", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
axis.text.x.angle = 45,
y_cut = 2,
boxplot_width = 0.1,
colors.use = c("0" = "#001219",
"1" = "#005f73",
"2" = "#0a9396",
"3" = "#94d2bd",
"4" = "#e9d8a6",
"5" = "#ee9b00",
"6" = "#ca6702",
"7" = "#bb3e03",
"8" = "#ae2012"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: FAIL - split.by", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
split.by = "orig.ident",
order = FALSE))
})
testthat::test_that("do_ViolinPlot: PASS - one variable, group by", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
group.by = "orig.ident")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
split.by = "orig.ident",
group.by = "annotation",
plot_boxplot = FALSE,
order = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
split.by = "seurat_clusters",
plot_boxplot = FALSE,
order = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - one variable, xlab y lab", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
xlab = "y",
ylab = "x")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = c("EPC1", "TOX2"),
xlab = c("A", "B"),
ylab = c("C", "D"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_ViolinPlot(sample = sample,
features = c("EPC1", "TOX2"),
xlab = c(NA, "B"),
ylab = c("C", NA))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - one variable, plot.title, subtitle and caption", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
plot.title = "A",
plot.subtitle = "B",
plot.caption = "C")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: PASS - multiple variables plot.title, subtitle and caption", {
testthat::skip_on_cran()
p <- SCpubr::do_ViolinPlot(sample = sample,
"EPC1",
group.by = "orig.ident",
colors.use = c("Cell" = "red"))
testthat::expect_true(ggplot2::is_ggplot(p))
sample$orig.ident <- factor(sample$orig.ident)
p <- SCpubr::do_ViolinPlot(sample = sample,
"EPC1",
group.by = "orig.ident",
colors.use = c("Cell" = "red"))
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_ViolinPlot: FAIL - wrong font.type", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
font.type = "wrong"))
})
testthat::test_that("do_ViolinPlot: FAIL - split.by with boxplots", {
testthat::skip_on_cran()
testthat::expect_error(SCpubr::do_ViolinPlot(sample = sample,
features = "EPC1",
split.by = "annotation",
order = FALSE))
})
}
================================================
FILE: tests/testthat/test-do_VolcanoPlot.R
================================================
if(base::isFALSE(dep_check[["do_VolcanoPlot"]])){
testthat::test_that("do_VolcanoPlot: CRAN essentials", {
`%>%` <- magrittr::`%>%`
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_VolcanoPlot: PASS - default", {
testthat::skip_on_cran()
`%>%` <- magrittr::`%>%`
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes)
testthat::expect_true(ggplot2::is_ggplot(p))
de_genes[1, "p_val_adj"] <- 1
de_genes[2, "avg_log2FC"] <- 0.001
de_genes[3, "avg_log2FC"] <- 3
de_genes[3, "p_val_adj"] <- 0.003
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes)
testthat::expect_true(ggplot2::is_ggplot(p))
de_genes <- de_genes %>%
tibble::as_tibble() %>%
dplyr::distinct(.data$gene, .keep_all = TRUE) %>%
tibble::column_to_rownames(var = "gene")
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_VolcanoPlot: PASS - n_genes", {
testthat::skip_on_cran()
`%>%` <- magrittr::`%>%`
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
n_genes = 15)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_VolcanoPlot: PASS - use_labels", {
testthat::skip_on_cran()
`%>%` <- magrittr::`%>%`
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
use_labels = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
use_labels = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_VolcanoPlot: PASS - gene tags", {
testthat::skip_on_cran()
`%>%` <- magrittr::`%>%`
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
add_gene_tags = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
add_gene_tags = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_VolcanoPlot: PASS - gene tags order by", {
testthat::skip_on_cran()
`%>%` <- magrittr::`%>%`
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
add_gene_tags = TRUE,
order_tags_by = "both")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
add_gene_tags = TRUE,
order_tags_by = "pvalue")
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
add_gene_tags = TRUE,
order_tags_by = "logfc")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_VolcanoPlot: FAIL - wrong parameters", {
testthat::skip_on_cran()
`%>%` <- magrittr::`%>%`
testthat::expect_error(SCpubr::do_VolcanoPlot(sample = sample,
de_genes = de_genes,
add_gene_tags = TRUE,
order_tags_by = "wrong"))
})
}
================================================
FILE: tests/testthat/test-do_WafflePlot.R
================================================
if (base::isFALSE(dep_check[["do_WafflePlot"]])){
testthat::test_that("do_WafflePlot: CRAN essential tests", {
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "seurat_clusters")
testthat::expect_true(ggplot2::is_ggplot(p))
})
testthat::test_that("do_WafflePlot: PASS - flip", {
testthat::skip_on_cran()
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "annotation",
flip = FALSE,
colors.use = c("A" = "red", "B"= "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
sample$annotation <- factor(sample$annotation)
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "annotation",
flip = FALSE,
colors.use = c("A" = "red", "B"= "blue"))
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "annotation",
flip = FALSE)
testthat::expect_true(ggplot2::is_ggplot(p))
p <- SCpubr::do_WafflePlot(sample = sample,
group.by = "seurat_clusters",
flip = TRUE)
testthat::expect_true(ggplot2::is_ggplot(p))
})
}
================================================
FILE: tests/testthat/test-utils.R
================================================
if (base::isFALSE(dep_check[["utils"]])){
# CHECK SUGGESTS
testthat::test_that("utils: check_suggests - FAIL - Wrong function", {
testthat::skip_on_cran()
testthat::expect_error(check_suggests("wrong_name"))
})
testthat::test_that("utils: check_suggests - FAIL - Package not installed", {
testthat::skip_on_cran()
testthat::expect_error(check_suggests("testing"))
})
testthat::test_that("utils: check_suggests - PASS - Correct function", {
testthat::skip_on_cran()
testthat::expect_silent(check_suggests("do_DimPlot"))
})
testthat::test_that("utils: check_suggests - PASS - Correct function", {
testthat::skip_on_cran()
testthat::expect_silent(check_suggests("do_DimPlot", passive = TRUE))
testthat::expect_silent(check_suggests("do_DimPlot", passive = FALSE))
})
# STATE DEPENDENCIES
# PACKAGE REPORT
testthat::test_that("utils: do_PackageReport - PASS - general", {
testthat::skip_on_cran()
suppressMessages({testthat::expect_message(SCpubr::do_PackageReport(startup = FALSE))})
suppressMessages({testthat::expect_message(SCpubr::do_PackageReport(startup = TRUE))})
suppressMessages({testthat::expect_message(SCpubr::do_PackageReport(extended = FALSE))})
suppressMessages({testthat::expect_message(SCpubr::do_PackageReport(extended = TRUE))})
})
# CHECK SEURAT
# CHECK SUGGESTS
testthat::test_that("utils: check_Seurat - FAIL - Not Seurat object", {
testthat::skip_on_cran()
testthat::expect_error(check_Seurat("not a Seurat object"))
})
testthat::test_that("utils: check_suggests - PASS - Seurat object", {
testthat::skip_on_cran()
testthat::expect_silent(check_Seurat(sample))
})
# CHECK COLORS
testthat::test_that("utils: check_colors - FAIL - wrong color", {
testthat::skip_on_cran()
testthat::expect_error(check_colors("not_a_color"))
})
testthat::test_that("utils: check_colors - FAIL - wrong color in a vector of colors", {
testthat::skip_on_cran()
testthat::expect_error(check_colors(c("not_a_color", "red", "blue")))
})
testthat::test_that("utils: check_colors - PASS - One color", {
testthat::skip_on_cran()
testthat::expect_silent(check_colors("red"))
})
testthat::test_that("utils: check_colors - PASS - Several colors", {
testthat::skip_on_cran()
testthat::expect_silent(check_colors(c("red", "blue")))
})
# CHECK CONSISTENCY COLORS AND NAMES
testthat::test_that("utils: check_consistency_colors_and_names - FAIL - more colors provided", {
testthat::skip_on_cran()
testthat::expect_error(check_consistency_colors_and_names(sample = sample,
colors = c("a" = "red", "b" = "blue"),
grouping_variable = "orig.ident"))
})
testthat::test_that("utils: check_consistency_colors_and_names - FAIL - names of colors not matching", {
testthat::skip_on_cran()
testthat::expect_error(check_consistency_colors_and_names(sample = sample,
colors = c("a" = "red"),
grouping_variable = "orig.ident"))
})
testthat::test_that("utils: check_consistency_colors_and_names - FAIL - less colors provided", {
testthat::skip_on_cran()
testthat::expect_error(check_consistency_colors_and_names(sample = sample,
colors = c("1" = "red"),
grouping_variable = "seurat_clusters"))
})
testthat::test_that("utils: check_consistency_colors_and_names - PASS - Colors matching", {
testthat::skip_on_cran()
testthat::expect_silent(check_consistency_colors_and_names(sample = sample,
colors = c("0" = "red",
"1" = "red",
"2" = "red",
"3" = "red",
"4" = "red",
"5" = "red",
"6" = "red",
"7" = "red",
"8" = "red")))
})
testthat::test_that("utils: check_consistency_colors_and_names - PASS - Colors matching, grouping variable", {
testthat::skip_on_cran()
testthat::expect_silent(check_consistency_colors_and_names(sample = sample,
colors = c("Cell" = "red"),
grouping_variable = "orig.ident"))
})
# GENERATE COLOR SCALE
testthat::test_that("utils: generate_color_scale - PASS - equal length of output", {
testthat::skip_on_cran()
names_use <- c("a", "b", "c")
colors <- colorspace::qualitative_hcl(length(names_use), palette = "Dark 3")
testthat::expect_length(colors, length(names_use))
colors <- colorspace::qualitative_hcl(length(names_use), palette = "Dark 3")
testthat::expect_length(colors, length(names_use))
colors <- generate_color_scale(names_use = names_use, colorblind = FALSE)
testthat::expect_length(colors, length(names_use))
colors <- generate_color_scale(names_use = names_use, colorblind = TRUE)
testthat::expect_length(colors, length(names_use))
})
# COMPUTE SCALES LIMITS
testthat::test_that("utils: compute_scale_limits - PASS - using a gene", {
testthat::skip_on_cran()
output <- compute_scale_limits(sample = sample,
feature = "EPC1")
testthat::expect_length(output, 2)
})
testthat::test_that("utils: compute_scale_limits - PASS - using a metadata variable", {
testthat::skip_on_cran()
output <- compute_scale_limits(sample = sample,
feature = "orig.ident")
testthat::expect_length(output, 2)
})
testthat::test_that("utils: compute_scale_limits - PASS - using dimensional reduction variable", {
testthat::skip_on_cran()
output <- compute_scale_limits(sample = sample,
feature = "PC_1")
testthat::expect_length(output, 2)
})
# CHECK FEATURE
testthat::test_that("utils: check_feature - FAIL - using the wrong gene", {
testthat::skip_on_cran()
testthat::expect_error(check_feature(sample = sample,
features = "NOTEPC1"))
})
testthat::test_that("utils: check_feature - FAIL - using the wrong metadata", {
testthat::skip_on_cran()
testthat::expect_error(check_feature(sample = sample,
features = "oris.ident"))
})
testthat::test_that("utils: check_feature - FAIL - using the wrong dimensional reduction variable", {
testthat::skip_on_cran()
testthat::expect_error(check_feature(sample = sample,
features = "UMAP_38"))
})
testthat::test_that("utils: check_feature - FAIL - all features failing while in permissive mode", {
testthat::skip_on_cran()
testthat::expect_error(check_feature(sample = sample,
features = c("NOTEPC1", "UMAP_38"),
permissive = TRUE))
})
testthat::test_that("utils: check_feature - WARNING - using one wrong gene and one good", {
testthat::skip_on_cran()
testthat::expect_warning(check_feature(sample = sample,
features = c("NOTEPC1", "EPC1"),
permissive = TRUE))
})
testthat::test_that("utils: check_feature - WARNING - using one wrong metadata variable and one good", {
testthat::skip_on_cran()
testthat::expect_warning(check_feature(sample = sample,
features = c("oris.ident", "orig.ident"),
permissive = TRUE))
})
testthat::test_that("utils: check_feature - WARNING - using one wrong dimensional reduction variable and one good", {
testthat::skip_on_cran()
testthat::expect_warning(check_feature(sample = sample,
features = c("UMAP_38", "PC_1"),
permissive = TRUE))
})
testthat::test_that("utils: check_feature - PASS - dump reduction names", {
testthat::skip_on_cran()
dim_names <- check_feature(sample = sample,
features = "PC_1",
dump_reduction_names = TRUE)
expected_output <- 0
for (dim_red in names(sample@reductions)){
expected_output <- expected_output + length(colnames(sample@reductions[[dim_red]][[]]))
}
testthat::expect_length(dim_names, expected_output)
})
testthat::test_that("utils: check_feature - PASS - permissive check length of output", {
testthat::skip_on_cran()
testthat::expect_warning({
features <- check_feature(sample = sample,
features = c("PC_1", "PC_99"),
permissive = TRUE)
testthat::expect_length(features, 1)
})
})
testthat::test_that("utils: check_feature - PASS - permissive check length of output when both permissive and dump_reduction_names are present.", {
testthat::skip_on_cran()
output <- check_feature(sample = sample,
features = "PC_1",
dump_reduction_names = TRUE,
permissive = TRUE)
testthat::expect_length(output, 2)
})
testthat::test_that("utils: check_feature - ERROR - using the wrong enforcer", {
testthat::skip_on_cran()
testthat::expect_error(check_feature(sample = sample,
features = "EPC1",
enforce_check = "Gene",
enforce_parameter = "group.by"))
})
testthat::test_that("utils: check_feature - ERROR - using the wrong feature for the selected enforcer", {
testthat::skip_on_cran()
testthat::expect_error(check_feature(sample = sample,
features = "EPC1",
enforce_check = "reductions",
enforce_parameter = "group.by"))
})
# REMOVE NOT FOUND FEATURES
testthat::test_that("utils: remove_not_found_features - PASS - 0 features removed - character", {
testthat::skip_on_cran()
features <- c("a", "b")
not_found_features <- ""
output <- remove_not_found_features(features = features, not_found_features = not_found_features)
testthat::expect_length(output, 2)
testthat::expect_type(output, "character")
})
testthat::test_that("utils: remove_not_found_features - PASS - 1 features removed - character", {
testthat::skip_on_cran()
features <- c("a", "b")
not_found_features <- "a"
output <- remove_not_found_features(features = features, not_found_features = not_found_features)
testthat::expect_length(output, 1)
testthat::expect_type(output, "character")
})
testthat::test_that("utils: remove_not_found_features - PASS - 2 features removed - character", {
testthat::skip_on_cran()
features <- c("a", "b")
not_found_features <- c("a", "b")
output <- remove_not_found_features(features = features, not_found_features = not_found_features)
testthat::expect_length(output, 0)
testthat::expect_type(output, "character")
})
testthat::test_that("utils: remove_not_found_features - PASS - 0 features removed - list", {
testthat::skip_on_cran()
features <- list("A" = "a",
"B" = "b")
not_found_features <- ""
output <- remove_not_found_features(features = features, not_found_features = not_found_features)
testthat::expect_length(output$A, 1)
testthat::expect_length(output$B, 1)
testthat::expect_type(output, "list")
})
testthat::test_that("utils: remove_not_found_features - PASS - 1 features removed - list", {
testthat::skip_on_cran()
features <- list("A" = "a",
"B" = "b")
not_found_features <- "a"
output <- remove_not_found_features(features = features, not_found_features = not_found_features)
testthat::expect_length(output$A, 0)
testthat::expect_length(output$B, 1)
testthat::expect_type(output, "list")
})
testthat::test_that("utils: remove_not_found_features - PASS - 2 features removed - list", {
testthat::skip_on_cran()
features <- list("A" = "a",
"B" = "b")
not_found_features <- c("a", "b")
output <- remove_not_found_features(features = features, not_found_features = not_found_features)
testthat::expect_length(output$A, 0)
testthat::expect_length(output$B, 0)
testthat::expect_type(output, "list")
})
# REMOVE DUPLICATED FEATURES
testthat::test_that("utils: remove_duplicated_features - WARNING - having duplicated features - character", {
testthat::skip_on_cran()
features <- c("a", "a")
testthat::expect_warning(remove_duplicated_features(features))
output <- suppressWarnings({remove_duplicated_features(features)})
testthat::expect_type(output, "character")
})
testthat::test_that("utils: remove_duplicated_features - WARNING - having duplicated features across lists - list", {
testthat::skip_on_cran()
features <- list("A" = "a",
"B" = "a")
testthat::expect_warning(remove_duplicated_features(features))
output <- suppressWarnings({remove_duplicated_features(features)})
testthat::expect_type(output, "list")
})
testthat::test_that("utils: remove_duplicated_features - WARNING - having duplicated features within lists - list", {
testthat::skip_on_cran()
features <- list("A" = c("a", "a"),
"B" = "b")
testthat::expect_warning(remove_duplicated_features(features))
output <- suppressWarnings({remove_duplicated_features(features)})
testthat::expect_type(output, "list")
})
testthat::test_that("utils: remove_duplicated_features - WARNING - having duplicated features across and between lists - list", {
testthat::skip_on_cran()
features <- list("A" = c("a", "a"),
"B" = "a")
suppressWarnings({testthat::expect_warning(remove_duplicated_features(features))})
output <- suppressWarnings({remove_duplicated_features(features)})
testthat::expect_type(output, "list")
})
# CHECK IDENTITY
testthat::test_that("utils: check_identity - FAIL - wrong identity", {
testthat::skip_on_cran()
testthat::expect_error(check_identity(sample, "wrong_identity"))
})
testthat::test_that("utils: check_identity - PASS - right identity", {
testthat::skip_on_cran()
testthat::expect_silent(check_identity(sample, "0"))
})
# CHECK AND SET REDUCTION
testthat::test_that("utils: check_and_set_reduction - FAIL - no reductions", {
testthat::skip_on_cran()
test <- sample
test@reductions[["pca"]] <- NULL
test@reductions[["umap"]] <- NULL
testthat::expect_error(check_and_set_reduction(sample = test, reduction = "umap"))
})
testthat::test_that("utils: check_and_set_reduction - FAIL - wrong reductions", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_reduction(sample = sample, reduction = "wrong_reduction"))
})
testthat::test_that("utils: check_and_set_reduction - PASS - null reduction, check that the output is the last computed reduction", {
testthat::skip_on_cran()
sample@reductions$ref.umap <- NULL
sample@reductions$umap <- NULL
output <- check_and_set_reduction(sample = sample)
last_reduction <- names(sample@reductions)[length(names(sample@reductions))]
testthat::expect_identical(output, last_reduction)
})
testthat::test_that("utils: check_and_set_reduction - PASS - provide a reduction", {
testthat::skip_on_cran()
sample@reductions$ref.umap <- NULL
output <- check_and_set_reduction(sample = sample, reduction = "umap")
reduction_check <- "umap"
testthat::expect_identical(output, reduction_check)
})
testthat::test_that("utils: check_and_set_reduction - PASS - umap not in reductions", {
testthat::skip_on_cran()
sample@reductions$umap <- NULL
sample@reductions$ref.umap <- NULL
sample@reductions$diffusion <- NULL
output <- check_and_set_reduction(sample = sample)
reduction_check <- "pca"
testthat::expect_identical(output, reduction_check)
})
# CHECK AND SET DIMENSIONS
testthat::test_that("utils: check_and_set_dimensions - FAIL - dims not being a pair of values", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_dimensions(sample = sample, reduction = "umap", dims = "wrong_input"))
})
testthat::test_that("utils: check_and_set_dimensions - FAIL - dims not being a pair of integers", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_dimensions(sample = sample, reduction = "umap", dims = c(1, "wrong_input")))
})
testthat::test_that("utils: check_and_set_dimensions - FAIL - dims not being in the available list of dims", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_dimensions(sample = sample, reduction = "umap", dims = c(1, 20)))
})
testthat::test_that("utils: check_and_set_dimensions - FAIL - reduction only having 1 dim", {
testthat::skip_on_cran()
test <- sample
obj <- Seurat::CreateDimReducObject(test@reductions$umap[[]][, "UMAP_1", drop = FALSE], key = "UMAP_", assay = "SCT")
test@reductions$umap <- obj
testthat::expect_error(check_and_set_dimensions(sample = test, reduction = "umap", dims = c(1, 2)))
})
testthat::test_that("utils: check_and_set_dimensions - PASS - NULL parameters", {
testthat::skip_on_cran()
output <- check_and_set_dimensions(sample = sample)
testthat::expect_identical(output, c(1, 2))
})
testthat::test_that("utils: check_and_set_dimensions - PASS - NULL dimension but provided dims", {
testthat::skip_on_cran()
output <- check_and_set_dimensions(sample = sample, dims = c(2, 1))
testthat::expect_identical(output, c(2, 1))
})
testthat::test_that("utils: check_and_set_dimensions - PASS - provided dimension and dims", {
testthat::skip_on_cran()
output <- check_and_set_dimensions(sample = sample, reduction = "pca", dims = c(20, 11))
testthat::expect_identical(output, c(20, 11))
})
# CHECK AND SET ASSAY
testthat::test_that("utils: check_and_set_assay - FAIL - wrong assay type", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_assay(sample = sample, assay = FALSE))
})
testthat::test_that("utils: check_and_set_assay - FAIL - no assays in object", {
testthat::skip_on_cran()
test <- sample
test@assays$RNA <- NULL
test@assays$SCT <- NULL
testthat::expect_error(check_and_set_assay(sample = test))
})
testthat::test_that("utils: check_and_set_assay - FAIL - assay not present", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_assay(sample = sample, assay = "ATAC"))
})
testthat::test_that("utils: check_and_set_assay - PASS - null parameters", {
testthat::skip_on_cran()
output <- check_and_set_assay(sample = sample)
testthat::expect_identical(output$assay, Seurat::DefaultAssay(sample))
})
testthat::test_that("utils: check_and_set_assay - PASS - providing assay", {
testthat::skip_on_cran()
output <- check_and_set_assay(sample = sample, assay = "SCT")
testthat::expect_identical(output$assay, "SCT")
})
testthat::test_that("utils: check_and_set_assay - PASS - providing non defaultassay", {
testthat::skip_on_cran()
sample@assays$RNA <- sample@assays$SCT
output <- check_and_set_assay(sample = sample, assay = "RNA")
testthat::expect_identical(output$assay, "RNA")
})
# CHECK TYPE
testthat::test_that("utils: check_type - FAIL - wrong type", {
testthat::skip_on_cran()
parameters <- c("first" = 1,
"second" = 2,
"third" = "a")
testthat::expect_error(check_type(parameters = parameters, required_type = "numeric", test_function = is.numeric))
})
testthat::test_that("utils: check_type - PASS - numeric", {
testthat::skip_on_cran()
parameters <- c("first" = 1,
"second" = 2)
testthat::expect_silent(check_type(parameters = parameters, required_type = "numeric", test_function = is.numeric))
})
testthat::test_that("utils: check_type - PASS - numeric with NULL", {
testthat::skip_on_cran()
parameters <- c("first" = 1,
"second" = 2,
"third" = NULL)
testthat::expect_silent(check_type(parameters = parameters, required_type = "numeric", test_function = is.numeric))
})
testthat::test_that("utils: check_type - PASS - character", {
testthat::skip_on_cran()
parameters <- c("first" = "a",
"second" = "b")
testthat::expect_silent(check_type(parameters = parameters, required_type = "character", test_function = is.character))
})
testthat::test_that("utils: check_type - PASS - character with NULL", {
testthat::skip_on_cran()
parameters <- c("first" = "a",
"second" = "b",
"third" = NULL)
testthat::expect_silent(check_type(parameters = parameters, required_type = "character", test_function = is.character))
})
testthat::test_that("utils: check_type - PASS - logical", {
testthat::skip_on_cran()
parameters <- c("first" = TRUE,
"second" = FALSE)
testthat::expect_silent(check_type(parameters = parameters, required_type = "logical", test_function = is.logical))
})
testthat::test_that("utils: check_type - PASS - logical with NULL", {
testthat::skip_on_cran()
parameters <- c("first" = TRUE,
"second" = FALSE,
"third" = NULL)
testthat::expect_silent(check_type(parameters = parameters, required_type = "logical", test_function = is.logical))
})
testthat::test_that("utils: check_type - PASS - list", {
testthat::skip_on_cran()
parameters <- c("first" = list(),
"second" = list())
testthat::expect_silent(check_type(parameters = parameters, required_type = "list", test_function = is.list))
})
testthat::test_that("utils: check_type - PASS - list with NULL", {
testthat::skip_on_cran()
parameters <- c("first" = list(),
"second" = list(),
"third" = NULL)
testthat::expect_silent(check_type(parameters = parameters, required_type = "list", test_function = is.list))
})
# CHECK AND SET THE SLOT
testthat::test_that("utils: check_and_set_slot - FAIL - wrong slot", {
testthat::skip_on_cran()
testthat::expect_error(check_and_set_slot("wrong_slot"))
})
testthat::test_that("utils: check_and_set_slot - PASS - counts", {
testthat::skip_on_cran()
output <- check_and_set_slot("counts")
testthat::expect_identical(output, "counts")
})
testthat::test_that("utils: check_and_set_slot - PASS - data", {
output <- check_and_set_slot("data")
testthat::expect_identical(output, "data")
})
testthat::test_that("utils: check_and_set_slot - PASS - scale.data", {
testthat::skip_on_cran()
output <- check_and_set_slot("scale.data")
testthat::expect_identical(output, "scale.data")
})
# CHECK LIMITS
testthat::test_that("utils: check_and_set_slot - FAIL - wrong limit", {
testthat::skip_on_cran()
testthat::expect_error(check_limits(sample = sample, feature = "EPC1", value_name = "scale.end", value = 30))
})
testthat::test_that("utils: check_and_set_slot - PASS - good limit", {
testthat::skip_on_cran()
testthat::expect_silent(check_limits(sample = sample, feature = "EPC1", value_name = "scale.end", value = 2))
})
# COMPUTE FACTOR LEVELS
testthat::test_that("utils: compute_factor_levels - FAIL - wrong position", {
testthat::skip_on_cran()
testthat::expect_error(compute_factor_levels(sample = sample, feature = "seurat_clusters", position = "upper"))
})
testthat::test_that("utils: compute_factor_levels - PASS - order.by and group.by", {
testthat::skip_on_cran()
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "seurat_clusters",
position = "fill",
group.by = NULL), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "seurat_clusters",
position = "fill",
group.by = "orig.ident",
order = TRUE), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "seurat_clusters",
position = "fill",
group.by = "orig.ident"), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "EPC1",
position = "fill",
group.by = "orig.ident",
order = TRUE), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "EPC1",
position = "fill",
group.by = "orig.ident"), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "seurat_clusters",
position = "stack",
group.by = "orig.ident",
order = TRUE), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "seurat_clusters",
position = "stack",
group.by = "orig.ident"), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "EPC1",
position = "stack",
group.by = "orig.ident",
order = TRUE), "character")
testthat::expect_type(compute_factor_levels(sample = sample,
feature = "EPC1",
position = "stack",
group.by = "orig.ident"), "character")
})
# CHECK LENGTH
testthat::test_that("utils: check_length - FAIL - distinct length", {
testthat::skip_on_cran()
vector_parameters <- c(1, 2)
vector_features <- 1
parameters_name <- "A"
features_name <- "B"
testthat::expect_error(check_length(vector_of_parameters = vector_parameters,
vector_of_features = vector_features,
parameters_name = parameters_name,
features_name = features_name))
})
testthat::test_that("utils: check_length - PASS - correct length", {
testthat::skip_on_cran()
vector_parameters <- c(1, 2)
vector_features <- c(1, 2)
parameters_name <- "A"
features_name <- "B"
testthat::expect_silent(check_length(vector_of_parameters = vector_parameters,
vector_of_features = vector_features,
parameters_name = parameters_name,
features_name = features_name))
})
# ADD SCALE
testthat::test_that("utils: add_scale - PASS - checks", {
p <- SCpubr::do_FeaturePlot(sample, features = "EPC1")
output <- add_scale(p = p, scale = "color", function_use = ggplot2::scale_color_viridis_b())
testthat::expect_true("ggplot" %in% class(output))
p <- SCpubr::do_FeaturePlot(sample, features = rownames(sample)[1:5])
output <- add_scale(p = p, scale = "color", function_use = ggplot2::scale_color_viridis_b(), num_plots = 5)
testthat::expect_true("ggplot" %in% class(output))
})
# MODIFY STRING
testthat::test_that("utils: modify_string - PASS - checks", {
testthat::skip_on_cran()
output <- modify_string("This is a string to cut")
testthat::expect_type(output, "character")
})
# COMPUTE ENRICHMENT SCORES
testthat::test_that("utils: compute_enrichment_scores - PASS - checks", {
testthat::skip_on_cran()
output <- compute_enrichment_scores(sample = sample, input_gene_list = list("test" = "EPC1"), nbin = 1, ctrl = 10)
testthat::expect_true("Seurat" %in% class(output))
testthat::expect_true("test" %in% colnames(output@meta.data))
output <- compute_enrichment_scores(sample = sample, input_gene_list = list("test" = "EPC1"), nbin = 1, ctrl = 10, flavor = "UCell")
testthat::expect_true("Seurat" %in% class(output))
testthat::expect_true("test" %in% colnames(output@meta.data))
output <- compute_enrichment_scores(sample = sample, input_gene_list = list("test" = "EPC1"), verbose = TRUE, nbin = 1, ctrl = 10)
testthat::expect_true("Seurat" %in% class(output))
testthat::expect_true("test" %in% colnames(output@meta.data))
output <- compute_enrichment_scores(sample = sample, input_gene_list = "EPC1", nbin = 1, ctrl = 10)
testthat::expect_true("Seurat" %in% class(output))
testthat::expect_true("Input" %in% colnames(output@meta.data))
})
# GET DATA COLUMN
testthat::test_that("utils: get data column - PASS ", {
testthat::skip_on_cran()
data <- get_data_column(sample = sample, feature = "EPC1", assay = "SCT", slot = "data")
testthat::expect_true("data.frame" %in% class(data))
testthat::expect_true("feature" %in% colnames(data))
data <- get_data_column(sample = sample, feature = "nCount_RNA", assay = "SCT", slot = "data")
testthat::expect_true("data.frame" %in% class(data))
testthat::expect_true("feature" %in% colnames(data))
data <- get_data_column(sample = sample, feature = "PC_1", assay = "SCT", slot = "data")
testthat::expect_true("data.frame" %in% class(data))
testthat::expect_true("feature" %in% colnames(data))
})
# CHECK PARAMETERS
testthat::test_that("utils: check parameters - FAIL ", {
testthat::skip_on_cran()
testthat::expect_error({check_parameters(parameter = -2, parameter_name = "viridis.direction")})
testthat::expect_error({check_parameters(parameter = "ERROR", parameter_name = "viridis.palette")})
testthat::expect_error({check_parameters(parameter = "ERROR", parameter_name = "database")})
testthat::expect_error({check_parameters(parameter = "ERROR", parameter_name = "GO_ontology")})
testthat::expect_error({check_parameters(parameter = "ERROR", parameter_name = "pAdjustMethod")})
})
# GET AXIS PARAMETERS
testthat::test_that("utils: check get_axis_parameters - PASS ", {
testthat::skip_on_cran()
out <- get_axis_parameters(angle = 0, flip = FALSE)
testthat::expect_type(out, "list")
out <- get_axis_parameters(angle = 0, flip = TRUE)
testthat::expect_type(out, "list")
out <- get_axis_parameters(angle = 45, flip = FALSE)
testthat::expect_type(out, "list")
out <- get_axis_parameters(angle = 45, flip = TRUE)
testthat::expect_type(out, "list")
out <- get_axis_parameters(angle = 90, flip = FALSE)
testthat::expect_type(out, "list")
out <- get_axis_parameters(angle = 90, flip = TRUE)
testthat::expect_type(out, "list")
})
# GET COLORBLIND COLORS
testthat::test_that("utils: check get_axis_parameters - PASS ", {
testthat::skip_on_cran()
out <- get_Colorblind_colors()
testthat::expect_type(out, "list")
})
testthat::test_that("utils: check compute_continuous_palette - PASS ", {
testthat::skip_on_cran()
out <- compute_continuous_palette(name = "YlGnBu", use_viridis = FALSE)
testthat::expect_type(out, "character")
out <- compute_continuous_palette(name = "YlGnBu", use_viridis = FALSE)
testthat::expect_type(out, "character")
out <- compute_continuous_palette(name = "YlGnBu", use_viridis = FALSE, direction = 1)
testthat::expect_type(out, "character")
out <- compute_continuous_palette(name = "YlGnBu", use_viridis = FALSE, direction = -1)
testthat::expect_type(out, "character")
out <- compute_continuous_palette(name = "YlGnBu", use_viridis = FALSE, enforce_symmetry = FALSE)
testthat::expect_type(out, "character")
out <- compute_continuous_palette(name = "RdBu", use_viridis = FALSE, enforce_symmetry = TRUE)
testthat::expect_type(out, "character")
})
}
================================================
FILE: tests/testthat.R
================================================
# nolint start
library(testthat)
library(SCpubr)
# nolint end
test_check("SCpubr")
================================================
FILE: vignettes/.gitignore
================================================
*.html
*.R
================================================
FILE: vignettes/reference_manual.Rmd
================================================
---
title: "reference_manual"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{reference_manual}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
For a detailed guide on how to use **SCpubr**, please visit the [reference book](https://enblacar.github.io/SCpubr-book/).