#' S4 class - AbSeqRepertoire analysis object
#'
#' @import methods
#'
#' @description The AbSeqRep object contains all metadata associated with
#' the AbSeq (python backend) run conducted on it. This S4 class represents
#' a single sample(repertoire) and it can be "combined" with other samples
#' by using the \code{+} operator to create an \linkS4class{AbSeqCRep} object.
#' This value, in turn, can be used as the first argument to
#' \link{report} which generates a comparison between all samples included
#' in the \code{+} operation.
#'
#' Users do not manually construct this class, but rather indirectly
#' obtain this class object as a return value
#' from the \link{abseqReport} and \link{report} functions.
#'
#' @slot f1 character. Path to FASTA/FASTQ file 1.
#' @slot f2 character. Path to FASTA/FASTQ file 2.
#' @slot chain character. Type of chain, possible values:
#' \itemize{
#' \item{hv}
#' \item{lv}
#' \item{kv}
#' \item{klv}
#' }
#' each representing \bold{H}eavy, \bold{L}ambda and \bold{K}appa respectively.
#' @slot task character. Type of analysis conducted, possible values:
#' \itemize{
#' \item{all}
#' \item{annotate}
#' \item{abundance}
#' \item{diversity}
#' \item{productivity}
#' \item{fastqc}
#' \item{primer}
#' \item{5utr}
#' \item{rsasimple}
#' \item{seqlen}
#' \item{secretion}
#' \item{seqlenclass}
#' }
#' @slot name character. Name of analysis.
#' @slot bitscore numeric. Part of filtering criteria: V gene bitscore filter value.
#' @slot qstart numeric. Part of filtering criteria: V gene query start filter value.
#' @slot sstart numeric. Part of filtering criteria: V gene subject start filter value.
#' @slot alignlen numeric. Part of filtering criteria: V gene alignment length filter value.
#' @slot clonelimit numeric. Number of clones to export into csv file. This is
#' only relevant in \code{-t all} or \code{-t diversity} where clonotypes
#' are exported into \code{<outdir>/<name>/diversity/clonotypes}
#' @slot detailedComposition logical. Plots composition logo by IGHV families if
#' set to true, otherwise, plots logos by FR/CDRs.
#' @slot log character. Path to log file.
#' @slot merger character. Merger used to merge paired-end reads.
#' @slot fmt character. File format of \code{file1} and (if present) \code{file2}.
#' Possible values are FASTA or FASTQ.
#' @slot sites character. Path to restriction sites \code{txt} file.
#' This option is only used if \code{-t rsasimple}
#' @slot primer5end ANY. Path to 5' end primer FASTA file.
#' @slot primer3end ANY. Path to 3' end primer FASTA file.
#' @slot trim5 numeric. Number of nucleotides to trimd at the 5' end;
#' @slot trim3 numeric. Number of nucleotides to trimd at the 3' end;
#' @slot outdir character. Path to output directory
#' @slot primer5endoffset numeric. Number of nucleotides to offset before aligning
#' 5' end primers in \code{primer5end} FASTA file.
#' @slot threads numeric. Number of threads to run.
#' @slot upstream character. Index (range) of upstream nucleotides to analyze.
#' This option is only used if \code{-t 5utr} or \code{-t secretion}.
#' @slot seqtype character. Sequence type, possible values are either \code{dna}
#' or \code{protein}.
#' @slot database character. Path to IgBLAST database.
#' @slot actualqstart numeric. Query sequence's starting index (indexing starts from 1).
#' This value overrides the inferred query start position by AbSeq.
#' @slot fr4cut logical. The end of FR4 is marked as the end of the sequence if
#' set to TRUE, otherwise the end of the sequence is either the end of the read
#' itself, or trimmed to \code{--trim3 <num>}.
#' @slot domainSystem character. Domain system to use in IgBLAST, possible
#' values are either \code{imgt} or \code{kabat}.
#'
#' @seealso \code{\link{abseqReport}} returns a \code{list} of \code{AbSeqRep}
#' objects.
#' @return AbSeqRep
#' @export
#'
#' @examples
#' # this class is not directly constructed by users, but as a return
#' # value from the abseqReport method.
#'
#' # Use example data from abseqR as abseqPy's output, substitute this
#' # with your own abseqPy output directory
#' abseqPyOutput <- tempdir()
#' file.copy(system.file("extdata", "ex", package = "abseqR"), abseqPyOutput, recursive=TRUE)
#' samples <- abseqReport(file.path(abseqPyOutput, "ex"), report = 0)
AbSeqRep <- setClass(
"AbSeqRep",
slots = c(
f1 = "character",
f2 = "character",
chain = "character",
task = "character",
name = "character",
bitscore = "numeric",
qstart = "numeric",
sstart = "numeric",
alignlen = "numeric",
clonelimit = "numeric",
detailedComposition = "logical",
log = "character",
merger = "character",
fmt = "character",
sites = "character",
primer5end = "ANY",
primer3end = "ANY",
trim5 = "numeric",
trim3 = "numeric",
outdir = "character",
primer5endoffset = "numeric",
threads = "numeric",
upstream = "ANY",
seqtype = "character",
database = "character",
actualqstart = "numeric",
fr4cut = "logical",
domainSystem = "character"
)
)
.loadAbSeqRepFromParams <- function(analysisParams) {
con <- file(analysisParams, "r")
lines <- readLines(con)
close(con)
params <- list(Class = "AbSeqRep")
# parameters that do not provide any information - ignore them so they
# wont be added as slots
skip <- c("yaml")
for (line in lines) {
# read in parameters
if (startsWith(line, "Parameter")) {
tokens <- unlist(strsplit(line, "\t"))
parameter <- trimws(strsplit(tokens[1], ":")[[1]][2])
value <- trimws(strsplit(tokens[2], ":")[[1]][2])
if (!(parameter %in% skip)) {
if (!is.na(as.logical(value))) {
params[[parameter]] <- as.logical(value)
} else if (!is.na(suppressWarnings(as.numeric(value)))) {
params[[parameter]] <- as.numeric(value)
} else if (grepl("[", value, fixed = TRUE)) {
# value = [start, end]
newValue <- gsub("\\[|\\]", "", value)
# to -> c(start, end)
params[[parameter]] <-
as.numeric(unlist(strsplit(newValue, ",")))
} else {
params[[parameter]] <- value
}
}
}
}
return(do.call("new", params))
}
#' Combines 2 \linkS4class{AbSeqRep} objects together for comparison
#'
#' @include AbSeqCRep.R
#'
#' @param e1 AbSeqRep object.
#' @param e2 AbSeqRep object.
#'
#' @return \linkS4class{AbSeqCRep} object. Calling \code{abseqR}'s
#' functions on this object will always result in a comparison.
#'
#' @export
#'
#' @seealso \code{\link{abseqReport}} returns a \code{list} of \code{AbSeqRep}s
#'
#' @examples
#' # Use example data from abseqR as abseqPy's output, substitute this
#' # with your own abseqPy output directory
#' abseqPyOutput <- tempdir()
#' file.copy(system.file("extdata", "ex", package = "abseqR"), abseqPyOutput, recursive=TRUE)
#' samples <- abseqReport(file.path(abseqPyOutput, "ex"), report = 0)
#'
#' # The provided example data has PCR1, PCR2, and PCR3 samples contained within
#' # pcr1 and pcr2 are instances of AbSeqRep
#' pcr1 <- samples[["PCR1"]]
#' pcr2 <- samples[["PCR2"]]
#'
#' # pcr12 is an instance of AbSeqCRep
#' pcr12 <- pcr1 + pcr2
#'
#' # you can now call the report function on this object
#' # report(pcr12) # uncomment this line to execute report
setMethod("+", signature(e1 = "AbSeqRep", e2 = "AbSeqRep"), function(e1, e2) {
new("AbSeqCRep", repertoires = list(e1, e2))
})
#' Combines a \linkS4class{AbSeqCRep} object with
#' a \linkS4class{AbSeqRep} object together for comparison
#'
#' @include AbSeqCRep.R
#' @include accessors-AbSeq.R
#'
#' @param e1 AbSeqCRep.
#' @param e2 AbSeqRep.
#'
#' @return \linkS4class{AbSeqCRep} object. Calling \code{abseqR}'s
#' functions on this object will always result in a comparison.
#'
#' @export
#'
#' @seealso \code{\link{abseqReport}} returns a \code{list} of \code{AbSeqRep}s
#'
#' @examples
#' # Use example data from abseqR as abseqPy's output, substitute this
#' # with your own abseqPy output directory
#' abseqPyOutput <- tempdir()
#' file.copy(system.file("extdata", "ex", package = "abseqR"), abseqPyOutput, recursive=TRUE)
#' samples <- abseqReport(file.path(abseqPyOutput, "ex"), report = 0)
#'
#' # The provided example data has PCR1, PCR2, and PCR3 samples contained within
#' # pcr12 is an instance of AbSeqCRep
#' pcr12 <- samples[["PCR1"]] + samples[["PCR2"]]
#' # pcr3 is instance of AbSeqRep
#' pcr3 <- samples[["PCR3"]]
#'
#' # pcr123 is an instance of AbSeqCRep
#' pcr123 <- pcr12 + pcr3
#'
#' # you can now call the report function on this object
#' # report(pcr123) # uncomment this line to execute report
setMethod("+", signature(e1 = "AbSeqCRep", e2 = "AbSeqRep"), function(e1, e2) {
new("AbSeqCRep", repertoires = unique(c(.asRepertoireList(e1), e2)))
})
#' Combines a \linkS4class{AbSeqRep} object with
#' a \linkS4class{AbSeqCRep} object together for comparison
#'
#' @include AbSeqCRep.R
#' @include accessors-AbSeq.R
#'
#' @param e1 AbSeqRep.
#' @param e2 AbSeqCRep.
#'
#' @return \linkS4class{AbSeqCRep} object. Calling \code{abseqR}'s
#' functions on this object will always result in a comparison.
#'
#' @export
#'
#' @seealso \code{\link{abseqReport}} returns a \code{list} of \code{AbSeqRep}s
#'
#' @examples
#' # Use example data from abseqR as abseqPy's output, substitute this
#' # with your own abseqPy output directory
#' abseqPyOutput <- tempdir()
#' file.copy(system.file("extdata", "ex", package = "abseqR"), abseqPyOutput, recursive=TRUE)
#' samples <- abseqReport(file.path(abseqPyOutput, "ex"), report = 0)
#'
#' # The provided example data has PCR1, PCR2, and PCR3 samples contained within
#' # pcr1 is an instance of AbSeqRep
#' pcr1 <- samples[["PCR1"]]
#' # pcr23 is instance of AbSeqCRep
#' pcr23 <- samples[["PCR2"]] + samples[["PCR3"]]
#'
#' # pcr123 is an instance of AbSeqCRep
#' pcr123 <- pcr1 + pcr23
#'
#' # you can now call the report function on this object
#' # report(pcr123) # uncomment this line to execute report
setMethod("+", signature(e1 = "AbSeqRep", e2 = "AbSeqCRep"), function(e1, e2) {
new("AbSeqCRep", repertoires = unique(c(e1, .asRepertoireList(e2))))
})
#' Plots \linkS4class{AbSeqRep} or
#' \linkS4class{AbSeqCRep} object to the specfied directory
#'
#' @description Plots all samples in the \code{object} argument
#' and saves the analysis in \code{outputDir}.
#' Users can optionally specify which samples
#' in \code{object} should be compared. Doing so generates
#' additional plots for clonotype comparison and
#' the usual plots will also conveniently include these samples
#' using additional \code{aes}thetics.
#'
#' This method is analogous to \code{\link{abseqReport}}.
#' The only difference is that this method accepts \linkS4class{AbSeqRep} or
#' \linkS4class{AbSeqCRep} objects as its first parameter, and the
#' \code{outputDir} specifies where to store the result.
#'
#'
#' @include util.R
#' @include plotter.R
#' @include accessors-AbSeq.R
#' @include AbSeqCRep.R
#'
#' @param object AbSeqRep or AbSeqCRep object to plot.
#' @param outputDir string type. Directory where analysis will be saved to.
#' @param report (optional) integer type. The possible values are:
#' \itemize{
#' \item{0 - does nothing (returns named list of \linkS4class{AbSeqRep} objects)}
#' \item{1 - generates plots for csv files}
#' \item{2 - generates a report that collates all plots}
#' \item{3 - generates interactive plots in report} (default)
#' }
#' each value also does what the previous values do. For example, \code{report = 2}
#' will return a named list of \linkS4class{AbSeqRep} objects, plot csv files,
#' and generate a (non-interactive)HTML report that collates all the plots together.
#' @return named list. List of \linkS4class{AbSeqRep} objects. The names of
#' the list elements are taken directly from the repertoire object itself.
#' This return value is consistent with the return value of \code{\link{abseqReport}}.
#'
#' @export
#'
#' @seealso \code{\link{abseqReport}}. Analogus function, but takes input from
#' a string that signifies the output directory of abseqPy as the first
#' arugment instead.
#'
#' @seealso \linkS4class{AbSeqRep}
#' @seealso \linkS4class{AbSeqCRep}
#'
#' @rdname report
#'
#' @examples
#' # Use example data from abseqR as abseqPy's output, substitute this
#' # with your own abseqPy output directory
#' abseqPyOutput <- tempdir()
#' file.copy(system.file("extdata", "ex", package = "abseqR"), abseqPyOutput, recursive=TRUE)
#' samples <- abseqReport(file.path(abseqPyOutput, "ex"), report = 0)
#'
#'
#' # The provided example data has PCR1, PCR2, and PCR3 samples contained within
#' # We can use the + operator to combine samples, thus requesting the
#' # report function to compare them:
#' pcr12 <- samples[["PCR1"]] + samples[["PCR2"]]
#'
#' # generate plots and report for this new comparison
#' # report(pcr12, "PCR1_vs_PCR2")
#'
#' # generate plots only
#' # report(pcr12, "PCR1_vs_PCR2", report = 1)
#'
#' # generate plots, and a non-interactive report
#' # report(pcr12, "PCR1_vs_PCR2", report = 2)
#'
#' # generate plots, and an interactive report
#' # report(pcr12, "PCR1_vs_PCR2", report = 3) # this is the default
setGeneric(
name = "report",
def = function(object, outputDir, report = 3) {
standardGeneric("report")
}
)
#' @rdname report
setMethod(
f = "report",
signature = "AbSeqRep",
definition = function(object, outputDir, report = 3) {
skip <- FALSE
stopifnot(report %in% c(0, 1, 2, 3))
# give meaningful names to numerical values
if (report == 0) {
report <- FALSE
interactivePlot <- FALSE
skip <- TRUE
} else if (report == 1) {
report <- FALSE
interactivePlot <- FALSE
} else if (report == 2) {
report <- TRUE
interactivePlot <- FALSE
} else {
report <- TRUE
interactivePlot <- TRUE
}
if (!skip) {
analysisDirectories = c(file.path(.asRepertoireDir(object),
RESULT_DIR,
.asRepertoireName(object)))
# get analysis that were conducted by looking at the directory
# structure
analyses <-
unlist(.inferAnalyzed(analysisDirectories[1]))
sampleNames <- .asRepertoireName(object)
primer5Files <- list(.asRepertoirePrimer5(object))
primer3Files <- list(.asRepertoirePrimer3(object))
upstreamRanges <- list(.asRepertoireUpstream(object))
.plotSamples(
sampleNames,
analysisDirectories,
analyses,
outputDir,
primer5Files,
primer3Files,
upstreamRanges,
skipDgene = (.asRepertoireChain(object) != "hv")
)
if (report) {
.generateReport(
object,
root = outputDir,
outputDir = outputDir,
interactivePlot = interactivePlot
)
}
}
# to be consistent with the return value of abseqR::abseqReport()
lst <- list()
lst[[.asRepertoireName(object)]] <- object
return(lst)
}
)
#' @rdname report
setMethod(
f = "report",
signature = "AbSeqCRep",
definition = function(object, outputDir, report = 3) {
stopifnot(report %in% c(0, 1, 2, 3))
skip <- FALSE
if (report == 0) {
report <- FALSE
interactivePlot <- FALSE
skip <- TRUE
} else if (report == 1) {
report <- FALSE
interactivePlot <- FALSE
} else if (report == 2) {
report <- TRUE
interactivePlot <- FALSE
} else {
report <- TRUE
interactivePlot <- TRUE
}
sampleNames <-
unlist(lapply(.asRepertoireList(object), .asRepertoireName))
if (!skip) {
analysisDirectories <- unlist(
lapply(
.asRepertoireList(object), function(x) {
# /a/b/c/RESULT_DIR/sample_name has
# all the analysis folders
file.path(.asRepertoireDir(x),
RESULT_DIR,
.asRepertoireName(x))
}))
# get all analyses conducted by each repertoire by looking
# at the directory structure created by abseqPy
analysesConducted <- lapply(analysisDirectories, .inferAnalyzed)
# find the intersection of all analysis, because it makes no
# sense to compare samples if they don't have the same analysis
similarAnalyses <- unlist(Reduce(intersect, analysesConducted))
primer5Files <-
unlist(lapply(.asRepertoireList(object), .asRepertoirePrimer5))
primer3Files <-
unlist(lapply(.asRepertoireList(object), .asRepertoirePrimer3))
upstreamRanges <- lapply(.asRepertoireList(object),
.asRepertoireUpstream)
allChains <- lapply(.asRepertoireList(object), .asRepertoireChain)
# only include D gene plots if all chains only contain "hv"
skipD <- (("kv" %in% allChains) || ("lv" %in% allChains))
.plotSamples(
sampleNames,
analysisDirectories,
similarAnalyses,
outputDir,
primer5Files,
primer3Files,
upstreamRanges,
skipDgene = skipD
)
if (report) {
.generateReport(
object,
root = outputDir,
outputDir = outputDir,
interactivePlot = interactivePlot
)
}
}
lst <- .asRepertoireList(object)
names(lst) <- sampleNames
return(lst)
}
)
#' Generates HTML report from \code{\linkS4class{AbSeqRep}} and
#' \code{\linkS4class{AbSeqCRep}} ojects
#'
#' @importFrom rmarkdown pandoc_available render
#' @include util.R
#' @include accessors-AbSeq.R
#'
#' @param object AbSeqCRep type.
#' @param root string type. Root directory of the sample(s)
#' @param outputDir string type. The path where the HTML will be generated
#' @param interactivePlot logical type. Interactive or not
#' @param .indexHTML character type. The back button will redirect to this link.
#' This is typically used to redirect users back to index.html page
#'
#' @return path (including HTML name) where the report (HTML file) was saved to
setGeneric(
name = ".generateReport",
def = function(object,
root,
outputDir,
interactivePlot = TRUE,
.indexHTML = "#") {
standardGeneric(".generateReport")
}
)
setMethod(
f = ".generateReport",
signature = "AbSeqCRep",
definition = function(object,
root,
outputDir,
interactivePlot = TRUE,
.indexHTML = "#") {
if (rmarkdown::pandoc_available()) {
analysisDirectories = unlist(
lapply(
.asRepertoireList(object), function(x) {
# /a/b/c/RESULT_DIR/sample_name has all the analysis folders
file.path(.asRepertoireDir(x), RESULT_DIR, .asRepertoireName(x))
}))
sampleNames <-
unlist(lapply(.asRepertoireList(object), .asRepertoireName))
message("Generating HTML report for ",
paste(sampleNames, collapse = "_vs_"))
# get all analyses conducted by each repertoire by looking
# at the directory structure created by abseqPy
analysesConducted <- lapply(analysisDirectories, .inferAnalyzed)
# find the intersection of all analysis, because it makes no
# sense to compare samples if they don't have the same analysis
similarAnalyses <- unlist(Reduce(intersect, analysesConducted))
# define variables for template.Rmd's param list
allChains <-
lapply(.asRepertoireList(object), .asRepertoireChain)
# only include D gene plots if all chains only contain "hv"
includeD <- !(("kv" %in% allChains) || ("lv" %in% allChains))
# template.Rmd param list
bitFilters <-
lapply(.asRepertoireList(object), .asRepertoireBitscore)
alFilters <-
lapply(.asRepertoireList(object), .asRepertoireAlignLen)
ssFilters <-
lapply(.asRepertoireList(object), .asRepertoireSubjectStart)
qsFilters <-
lapply(.asRepertoireList(object), .asRepertoireQueryStart)
rawReadCounts <- lapply(X = analysisDirectories,
FUN = .readSummary,
ABSEQ_RAW_READ_COUNT_KEY)
annotReadCounts <- lapply(X = analysisDirectories,
FUN = .readSummary,
ABSEQ_ANNOT_READ_COUNT_KEY)
filteredReadCounts <- lapply(X = analysisDirectories,
FUN = .readSummary,
ABSEQ_FILT_READ_COUNT_KEY)
productiveReadCounts <- lapply(X = analysisDirectories,
FUN = .readSummary,
ABSEQ_PROD_READ_COUNT_KEY)
renderParams <- list(
rootDir = normalizePath(root),
single = FALSE,
interactive = interactivePlot,
inclD = includeD,
hasAnnot = (ABSEQ_DIR_ANNOT %in% similarAnalyses),
hasAbun = (ABSEQ_DIR_ABUN %in% similarAnalyses),
hasProd = (ABSEQ_DIR_PROD %in% similarAnalyses),
hasDiv = (ABSEQ_DIR_DIV %in% similarAnalyses),
name = paste(sampleNames, collapse = "_vs_"),
bitfilters = paste(bitFilters, collapse = ","),
alignfilters = paste(alFilters, collapse = ","),
sstartfilters = paste(ssFilters, collapse = ","),
qstartfilters = paste(qsFilters, collapse = ","),
rawReads = paste(rawReadCounts, collapse = ","),
annotReads = paste(annotReadCounts, collapse = ","),
filteredReads = paste(filteredReadCounts, collapse = ","),
productiveReads = paste(productiveReadCounts, collapse = ",")
)
# https://github.com/rstudio/rmarkdown/issues/861#issuecomment-326637323
# paraphrased: just don't use output_file or output_dir
# instead, copy to output_dir and remove it if you want to
# as a safety measure, rename the template.Rmd file to
# sample name so that the cache will not clash with other
# samples it it wasn't cleared in time
tmpTemplate <-
file.path(outputDir, paste0(paste(sampleNames, collapse = "_vs_"), ".Rmd"))
file.copy(
system.file("extdata", "template.Rmd", package = "abseqR"),
tmpTemplate,
overwrite = TRUE
)
# substitute href to '#' to index.html: only when there's a landing
# page that we do this. Calling abseqR::report() will leave href
# as-is
.substituteStringInFile(tmpTemplate,
"href: \"#\"",
paste0("href: \"", .indexHTML, "\""),
fixed = TRUE)
rmarkdown::render(tmpTemplate, params = renderParams)
file.remove(tmpTemplate)
return(sub(".Rmd", ".html", tmpTemplate))
} else {
warning("Pandoc cannot be detected on system, skipping HTML report")
return(NA)
}
}
)
setMethod(
f = ".generateReport",
signature = "AbSeqRep",
definition = function(object,
root,
outputDir,
interactivePlot = TRUE,
.indexHTML = "#") {
if (rmarkdown::pandoc_available()) {
message("Generating HTML report for ", .asRepertoireName(object))
analysisDirectory = file.path(.asRepertoireDir(object),
RESULT_DIR,
.asRepertoireName(object))
analyses <-
unlist(.inferAnalyzed(analysisDirectory))
# define parameters for template.Rmd's param list
bitFilter <- .asRepertoireBitscore(object)
qsFilter <- .asRepertoireQueryStart(object)
ssFilter <- .asRepertoireSubjectStart(object)
alFilter <- .asRepertoireAlignLen(object)
rawReadCount <- .readSummary(analysisDirectory,
ABSEQ_RAW_READ_COUNT_KEY)
annotReadCount <- .readSummary(analysisDirectory,
ABSEQ_ANNOT_READ_COUNT_KEY)
filteredReadCount <-
.readSummary(analysisDirectory,
ABSEQ_FILT_READ_COUNT_KEY)
productiveReadCount <-
.readSummary(analysisDirectory,
ABSEQ_PROD_READ_COUNT_KEY)
renderParams <- list(
rootDir = normalizePath(root),
single = TRUE,
interactive = interactivePlot,
inclD = (.asRepertoireChain(object) == "hv"),
hasAnnot = (ABSEQ_DIR_ANNOT %in% analyses),
hasAbun = (ABSEQ_DIR_ABUN %in% analyses),
hasProd = (ABSEQ_DIR_PROD %in% analyses),
hasDiv = (ABSEQ_DIR_DIV %in% analyses),
name = .asRepertoireName(object),
bitfilters = bitFilter,
qstartfilters = qsFilter,
sstartfilters = ssFilter,
alignfilters = alFilter,
rawReads = rawReadCount,
annotReads = annotReadCount,
filteredReads = filteredReadCount,
productiveReads = productiveReadCount
)
# https://github.com/rstudio/rmarkdown/issues/861#issuecomment-326637323
# paraphrased: just don't use output_file or output_dir
# instead, copy to output_dir and remove it if you want to
# as a safety measure, rename the template.Rmd file to
# sample name so that the cache will not clash with other
# samples it it wasn't cleared in time
tmpTemplate <- file.path(outputDir,
paste0(.asRepertoireName(object), ".Rmd"))
file.copy(
system.file("extdata", "template.Rmd", package = "abseqR"),
tmpTemplate,
overwrite = TRUE
)
.substituteStringInFile(tmpTemplate,
"href: \"#\"",
paste0("href: \"", .indexHTML, "\""),
fixed = TRUE)
rmarkdown::render(tmpTemplate, params = renderParams)
file.remove(tmpTemplate)
return(sub(".Rmd", ".html", tmpTemplate))
} else {
warning("Pandoc cannot be detected on system, skipping HTML report")
return(NA)
}
}
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.