| Title: | Cell Culture Microscopy Assay Analysis and Reporting |
|---|---|
| Description: | Analysis and reporting pipeline for cell culture assays read out by microscopy, starting from segmented single-cell exports such as those written by 'segmantR', 'CellProfiler' or 'QuPath'. Recovers the experimental design from the directory tree and the file naming convention, resolves acquisitions into the analysis unit of replication, and standardizes every cell against the control condition of its own batch. Applies threshold and biological quality control gates, then estimates effect sizes with confidence intervals at both unit and cell level so that the cost of treating cells as replicates is visible rather than assumed. Sample sizes for a follow-up study are solved from the confidence bound nearer the null instead of the observed point estimate, after Cohen (1988, ISBN:9780805802832). Figures, machine-readable tables and a generated file of every quoted number are emitted from the same objects, and an interactive 'shiny' application provides guided analysis and report export. |
| Authors: | Raban Heller [aut, cre, cph] (ORCID: <https://orcid.org/0000-0001-8006-9742>), Leila Schwindling [aut], Alexander Büchner [aut], Lucia Lindenberger [aut], Steffen Müller [aut], Michael Hannemann [aut], Gerhard Achatz [aut], Simone Rothmiller [aut] |
| Maintainer: | Raban Heller <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.1.9000 |
| Built: | 2026-11-04 22:06:19 UTC |
| Source: | https://github.com/CTTIR/cellreportR |
Removes the cells of every unit the gate excluded, records the step in the QC log and stores the gate on the experiment so the decision remains auditable after the data have been trimmed.
cr_apply_gate(experiment, gate, units = NULL, drop_disputed = FALSE)cr_apply_gate(experiment, gate, units = NULL, drop_disputed = FALSE)
experiment |
A |
gate |
A |
units |
Optional character vector of unit identifiers to
remove instead of |
drop_disputed |
Also drop the units whose verdict depends on
which control centre is used. Default |
A modified cr_experiment. The gate is stored in
metadata$qc_gate.
cr_qc_gate(), cr_qc_gate_impact(), cr_qc_report().
Other quality control:
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") exp2 <- cr_apply_gate(exp, gate) cr_qc_summary(exp2)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") exp2 <- cr_apply_gate(exp, gate) cr_qc_summary(exp2)
Derives the identifier of the analysis unit — the spatial unit that is
the unit of replication — for every row of a cell table, merging the
files that belong to the same unit according to a cr_merge_rules()
set.
cr_assign_units( x, key_vars, replicate_var = "replicate", rules = cr_merge_rules(), id_col = "well_id", sep = "|", call = rlang::caller_env() )cr_assign_units( x, key_vars, replicate_var = "replicate", rules = cr_merge_rules(), id_col = "well_id", sep = "|", call = rlang::caller_env() )
x |
A data frame of cells (or of files) carrying the design columns and a replicate index. |
key_vars |
Character vector of column names that, together with the replicate index, identify one unit. |
replicate_var |
Name of the replicate index column. Default
|
rules |
A |
id_col |
Name of the unit identifier column to add. Default
|
sep |
Separator used to build the identifier. Default |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
The unit identifier is the combination of key_vars and the merged
replicate index. Files that share it are one unit; files that do not
are separate replicates. Because a unit may be assembled from more
than one file, cr_unit_map() should be used afterwards to see which
units were merged and from how many files.
x with two columns added: replicate_merged (the replicate
index after merging) and the unit identifier named by id_col. The
number of units is attached as the "n_units" attribute.
cr_unit_map(), cr_merge_rules(),
cr_centroid_overlap().
Other import:
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
files <- tibble::tibble( compound = "CompoundA", plate = "Plate_1", mode = "treated", replicate = c("1", "1.1", "2", "2.2"), merge_unit = c(FALSE, TRUE, FALSE, FALSE), reacquisition = FALSE ) units <- cr_assign_units(files, key_vars = c("compound", "plate", "mode")) units[, c("replicate", "replicate_merged", "well_id")]files <- tibble::tibble( compound = "CompoundA", plate = "Plate_1", mode = "treated", replicate = c("1", "1.1", "2", "2.2"), merge_unit = c(FALSE, TRUE, FALSE, FALSE), reacquisition = FALSE ) units <- cr_assign_units(files, key_vars = c("compound", "plate", "mode")) units[, c("replicate", "replicate_merged", "well_id")]
cr_result
Compute AUC with confidence interval from a cr_result
cr_auc(result, ci_method = c("delong", "bootstrap"), n_boot = 1000)cr_auc(result, ci_method = c("delong", "bootstrap"), n_boot = 1000)
result |
A |
ci_method |
|
n_boot |
Number of bootstrap resamples for |
A tibble with auc, ci_low, ci_high, method.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") cr_auc(res)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") cr_auc(res)
Computes a per-well background estimate and subtracts it from every cell in that well. Negative values are clipped to zero.
cr_background_subtract( experiment, channel, method = c("percentile", "modal", "empty_wells"), q = 0.05, empty_wells = NULL )cr_background_subtract( experiment, channel, method = c("percentile", "modal", "empty_wells"), q = 0.05, empty_wells = NULL )
experiment |
A |
channel |
Channel name. |
method |
Background estimator. |
q |
Percentile for |
empty_wells |
Character vector of well IDs for
|
A modified cr_experiment.
cr_normalize(), cr_standardize_batch()
Other normalization functions:
cr_normalize()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_background_subtract(exp, channel = "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_background_subtract(exp, channel = "marker_1")
Randomly subsamples each analysis unit to a common cell count. A unit acquired in several passes otherwise contributes several times as many cells as its single-pass neighbour and is silently over-weighted in every pooled quantity they share — including the control statistics of their own batch.
cr_balance_cells(experiment, unit = NULL, n_max = NULL, n = NULL, seed = NULL)cr_balance_cells(experiment, unit = NULL, n_max = NULL, n = NULL, seed = NULL)
experiment |
A |
unit |
Column in |
n_max |
Optional maximum number of cells per unit. |
n |
Optional exact number of cells per unit. Cannot be
combined with |
seed |
Optional integer seed. |
Three modes:
n_maxcap each unit at n_max cells, leaving smaller
units untouched. This is the usual choice for large
acquisitions.
ntake exactly n cells per unit (units with fewer
cells keep all of theirs).
take the smallest unit's cell count from every unit, which equalises the units exactly at the cost of discarding the most data.
Subsampling is random, so pass seed for a reproducible result.
The RNG state of the calling session is saved and restored, so a
seeded stream outside this function is never disturbed.
A modified cr_experiment. Per-unit counts before and
after are stored in metadata$balance_cells.
cr_exclude_small(), which should run first.
Other quality control:
cr_apply_gate(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) exp2 <- cr_balance_cells(exp, n_max = 20, seed = 1) max(exp2$metadata$balance_cells$n_after) # equalise every unit at the smallest unit's count exp3 <- cr_balance_cells(exp, seed = 1) length(unique(exp3$metadata$balance_cells$n_after))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) exp2 <- cr_balance_cells(exp, n_max = 20, seed = 1) max(exp2$metadata$balance_cells$n_after) # equalise every unit at the smallest unit's count exp3 <- cr_balance_cells(exp, seed = 1) length(unique(exp3$metadata$balance_cells$n_after))
A batch is rarely identified by a single column. Once an assay
spans several plates, acquisition runs or experiment days, the
analytical batch is the combination of those columns, and any
analysis that standardizes against a control has to respect that
combination. cr_batch_key() collapses any number of design or
cell columns into one character key that can be grouped on, joined
on and reported.
cr_batch_key(x, batch_vars, sep = " | ", na_label = "<NA>")cr_batch_key(x, batch_vars, sep = " | ", na_label = "<NA>")
x |
A |
batch_vars |
Character vector of column names that jointly
define a batch, for example
|
sep |
Separator placed between the parts of the key. |
na_label |
Label substituted for missing values. |
Missing values are replaced by na_label rather than propagated,
so that two rows with an unrecorded plate are grouped together
visibly instead of silently producing NA keys.
If distinct tuples produce the same displayed key, the function refuses
the collision; choose another separator or missing-value label.
A character vector with one key per row of x (one key per
cell when x is a cr_experiment).
cr_batch_reference(), cr_standardize_batch()
Other batch standardization functions:
cr_batch_reference(),
cr_correct_batch(),
cr_standardize_batch()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) key <- cr_batch_key(exp, c("plate", "timepoint")) head(unique(key)) # Works on a plain data frame too cr_batch_key(data.frame(a = c("x", "y"), b = 1:2), c("a", "b"))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) key <- cr_batch_key(exp, c("plate", "timepoint")) head(unique(key)) # Works on a plain data frame too cr_batch_key(data.frame(a = c("x", "y"), b = 1:2), c("a", "b"))
Summarizes the control cells of every batch: how many there are,
and their mean, median and standard deviation for one channel.
This table is the reference that cr_standardize_batch() divides
by, and it is worth inspecting on its own – a batch with very few
control cells, or none at all, is visible here before any
standardized value is computed.
cr_batch_reference( experiment, channel, control_level, batch_vars, control_var = "treatment", sd_floor = 1e-08 )cr_batch_reference( experiment, channel, control_level, batch_vars, control_var = "treatment", sd_floor = 1e-08 )
experiment |
A |
channel |
Channel column to summarize. Must be numeric. |
control_level |
Value (or values) of |
batch_vars |
Character vector of columns that jointly define a
batch. See |
control_var |
Column holding the treatment assignment.
Defaults to |
sd_floor |
Lower bound for the control standard deviation. A batch whose control cells are identical would otherwise divide by zero. |
Both centres are reported deliberately. A right-skewed signal has
mean > median, so a downstream gate that compares a well's median
against a control mean is silently stricter than the rule it
states. Keeping both lets each consumer compare like with like.
A tibble with one row per batch and the columns
batch_varsThe columns that define the batch.
batch_keyThe collapsed batch key.
n_cellsCells in the batch.
ctrl_nControl cells with a finite channel value.
ctrl_mean, ctrl_median, ctrl_sd
Control statistics;
NA when the batch has no control cells.
has_controlWhether the batch can be standardized.
cr_standardize_batch(), cr_batch_key()
Other batch standardization functions:
cr_batch_key(),
cr_correct_batch(),
cr_standardize_batch()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) cr_batch_reference(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) cr_batch_reference(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate")
Re-estimates each contrast within a blocking factor, typically the
plate. Units on one plate share a preparation run, an imaging
session and a single control denominator, so they are not
independent and a pooled estimate carries the between-plate variance
inside its standard deviation. Fitting value ~ group + block on
unit-level data removes the additive block effect and shows whether
the pooled headline estimate is conservative or inflated by pooling.
cr_blocked_effect( data, value, group_var, reference_level, comparison_levels = NULL, block_var, by = NULL, unit = NULL, conf_level = 0.95, min_blocks = 2 )cr_blocked_effect( data, value, group_var, reference_level, comparison_levels = NULL, block_var, by = NULL, unit = NULL, conf_level = 0.95, min_blocks = 2 )
data |
A data frame with one row per unit (or per cell when
|
value |
Name of the numeric response column. |
group_var |
Name of the column holding the compared groups. |
reference_level |
Reference level of |
comparison_levels |
Levels contrasted against the reference.
|
block_var |
Name of the blocking column, for example the plate. |
by |
Optional character vector of stratifying columns, for example the compound. |
unit |
Optional column identifying the unit of replication. When given, rows are averaged per unit before the model is fitted. |
conf_level |
Confidence level for the coefficient interval. |
min_blocks |
Minimum number of blocks that must carry data for a contrast to be fitted (default 2; with one block the model is the unblocked one). |
The reported d_within_block is the group coefficient divided by
the residual standard deviation of the blocked fit, so it is on the
same scale as Cohen's d from cr_effect_grid() but conditions on
the block.
A tibble with the by columns, contrast, n_units,
n_blocks, shift_within_block (the group coefficient),
ci_low, ci_high, resid_sd, d_within_block and p_value.
Contrasts that could not be fitted are returned in the skipped
attribute.
cr_effect_grid(), cr_unit_variability().
Other screen statistics:
cr_unit_variability()
set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 16), arm = rep(rep(c("reference", "interval_short"), each = 8), 2), plate = rep(rep(c("P1", "P2"), each = 4), 8), log2_fc = stats::rnorm(32) ) units$log2_fc <- units$log2_fc + ifelse(units$compound == "CompoundA" & units$arm == "interval_short", -1.2, 0) + ifelse(units$plate == "P2", 0.5, 0) cr_blocked_effect(units, value = "log2_fc", group_var = "arm", reference_level = "reference", block_var = "plate", by = "compound")set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 16), arm = rep(rep(c("reference", "interval_short"), each = 8), 2), plate = rep(rep(c("P1", "P2"), each = 4), 8), log2_fc = stats::rnorm(32) ) units$log2_fc <- units$log2_fc + ifelse(units$compound == "CompoundA" & units$arm == "interval_short", -1.2, 0) + ifelse(units$plate == "P2", 0.5, 0) cr_blocked_effect(units, value = "log2_fc", group_var = "arm", reference_level = "reference", block_var = "plate", by = "compound")
cr_experiment objectAssembles a validated cr_experiment from its components. A
cr_experiment is the central S3 object in cellreportR and holds
per-cell measurements, experimental design, channel metadata, plate
information, a QC log and arbitrary user metadata.
cr_build_experiment( cells, design = NULL, channels = NULL, plate_info = list(), metadata = list(), unit_var = NULL, batch_vars = NULL, provenance = NULL, set_aside = NULL, call = rlang::caller_env() )cr_build_experiment( cells, design = NULL, channels = NULL, plate_info = list(), metadata = list(), unit_var = NULL, batch_vars = NULL, provenance = NULL, set_aside = NULL, call = rlang::caller_env() )
cells |
A data frame / tibble of per-cell measurements, or a
|
design |
A data frame / tibble that maps each spatial unit to
treatment information, or a |
channels |
Optional tibble describing marker channels.
Columns: |
plate_info |
Optional list with plate metadata (e.g. |
metadata |
Optional list with arbitrary user metadata. |
unit_var |
Optional name of the analysis unit column. |
batch_vars |
Optional character vector of columns that together define a batch. |
provenance |
Optional per-file provenance table. |
set_aside |
Optional data frame or list of arms split out of the analysis pool. |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
Three optional slots describe structure that a single design table
cannot: unit_var names the analysis unit when it is neither well
nor slide (a unit assembled from several files, for instance),
batch_vars names the combination of columns that defines a batch,
and provenance keeps the per-file record that lets any cell be
traced back to its acquisition. set_aside holds arms that were split
out of the analysis pool, such as a specificity control, so that they
travel with the experiment instead of being lost.
A cr_experiment object (an S3 list).
cr_validate_experiment(), cr_dataset(), cr_design().
Other constructors:
cr_dataset(),
cr_design(),
cr_validate_experiment()
cells <- tibble::tibble( cell_id = sprintf("c%03d", 1:6), well = rep(c("A01", "A02"), each = 3), area = c(120, 130, 125, 118, 122, 131), target_signal = c(10, 12, 11, 30, 33, 29) ) design <- tibble::tibble( well = c("A01", "A02"), treatment = c("Vehicle", "CompoundA"), plate = "Plate_1" ) exp <- cr_build_experiment(cells, design, batch_vars = "plate") expcells <- tibble::tibble( cell_id = sprintf("c%03d", 1:6), well = rep(c("A01", "A02"), each = 3), area = c(120, 130, 125, 118, 122, 131), target_signal = c(10, 12, 11, 30, 33, 29) ) design <- tibble::tibble( well = c("A01", "A02"), treatment = c("Vehicle", "CompoundA"), plate = "Plate_1" ) exp <- cr_build_experiment(cells, design, batch_vars = "plate") exp
Answers the question a mergeable-looking replicate suffix raises: are these two files two passes over the same physical unit, or two different units? Two passes over one unit share their segmentation centroids; two different units share essentially none.
cr_centroid_overlap( x, unit_a, unit_b, coords = c("x", "y"), tol = 1, id_col = "well_id", call = rlang::caller_env() )cr_centroid_overlap( x, unit_a, unit_b, coords = c("x", "y"), tol = 1, id_col = "well_id", call = rlang::caller_env() )
x |
A cell table carrying a unit identifier and centroid columns. |
unit_a, unit_b
|
The two unit identifiers to compare. |
coords |
Length-2 character vector naming the centroid columns.
Default |
tol |
Numeric matching tolerance in centroid units. Default |
id_col |
Name of the unit identifier column. Default
|
call |
The execution environment of the calling function. Used for error reporting; experts only. |
A single number: the fraction of cells in the smaller unit
that have a centroid within tol of a centroid in the other unit.
The cell counts and the number of matches are attached as the
"n_a", "n_b" and "n_matched" attributes.
cr_assign_units(), cr_merge_rules().
Other import:
cr_assign_units(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
cells <- tibble::tibble( well_id = rep(c("u1", "u2"), each = 4), x = c(1, 2, 3, 4, 1, 2, 3, 90), y = c(1, 2, 3, 4, 1, 2, 3, 90) ) # u1 and u2 share three of four centroids: cr_centroid_overlap(cells, "u1", "u2")cells <- tibble::tibble( well_id = rep(c("u1", "u2"), each = 4), x = c(1, 2, 3, 4, 1, 2, 3, 90), y = c(1, 2, 3, 4, 1, 2, 3, 90) ) # u1 and u2 share three of four centroids: cr_centroid_overlap(cells, "u1", "u2")
cr_experiment
List channels in a cr_experiment
cr_channels(experiment)cr_channels(experiment)
experiment |
A |
A character vector of channel names.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) cr_channels(exp)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) cr_channels(exp)
Deterministically classify numeric results using explicit boundaries
cr_classify_result( value, negative_upper, positive_lower, labels = c(negative = "NEGATIVE", indeterminate = "INDETERMINATE", positive = "POSITIVE") )cr_classify_result( value, negative_upper, positive_lower, labels = c(negative = "NEGATIVE", indeterminate = "INDETERMINATE", positive = "POSITIVE") )
value |
Numeric vector. |
negative_upper, positive_lower
|
Explicit finite boundaries. Values at |
labels |
Named character vector containing |
Character vector with missing/non-finite inputs returned as NA.
Segmented single-cell exports name their columns however the
acquisition software happens to. A cr_column_map records how those
raw headers translate to the analysis names used downstream, so that
the mapping lives in one declarative object instead of being spread
through reader code.
cr_column_map(exact = NULL, prefix = NULL, keep = NULL) ## S3 method for class 'cr_column_map' print(x, ...)cr_column_map(exact = NULL, prefix = NULL, keep = NULL) ## S3 method for class 'cr_column_map' print(x, ...)
exact |
Named character vector. Names are raw header names, values the analysis name to rename them to. |
prefix |
Named character vector. Names are regular expressions matched against the raw header names, values the analysis name. The first matching column is renamed. |
keep |
Optional character vector of analysis names to retain
after renaming, in this order. Names that are absent are ignored.
|
x |
A |
... |
Ignored. |
Two matching modes are available because vendor headers are not
always stable: exact matches a header verbatim, while prefix
matches a regular expression. Prefix matching exists for headers that
embed a unit glyph (an area column ending in a squared-micrometre
symbol, for instance), where the exact spelling cannot be relied on.
Renaming is deliberately tolerant: names that do not occur in a given export are skipped silently rather than raising an error. Exports from the same instrument routinely carry different subsets of the available measurements, and a strict renamer forces a second reader to exist for every subset.
An object of class cr_column_map: a list with elements
exact, prefix and keep.
x, invisibly.
cr_read_export(), cr_read_exports().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
map <- cr_column_map( exact = c( "Event Label" = "cell_id", "Signal - Mean Intensity" = "target_signal" ), prefix = c("^Nuclei - Area" = "area"), keep = c("cell_id", "target_signal", "area") ) mapmap <- cr_column_map( exact = c( "Event Label" = "cell_id", "Signal - Mean Intensity" = "target_signal" ), prefix = c("^Nuclei - Area" = "area"), keep = c("cell_id", "target_signal", "area") ) map
Puts the two aggregation levels of a screen side by side and quantifies how much narrower the cell-level intervals are. A ratio well above one is pseudo-replication rather than precision: cells within a unit are not independent, so the cell-level interval understates the uncertainty of the very same estimate.
cr_compare_levels(unit_effects, cell_effects, by = NULL, estimate = "cohens_d")cr_compare_levels(unit_effects, cell_effects, by = NULL, estimate = "cohens_d")
unit_effects |
Effect grid computed with |
cell_effects |
Effect grid computed on the same data without
|
by |
Join keys. |
estimate |
Name of the effect size column to compare. |
A tibble with the join keys, estimate_unit,
estimate_cell, width_unit, width_cell and ratio
(width_unit / width_cell). The median ratio is attached as the
median_ratio attribute.
Other effect sizes:
cr_effect_grid(),
cr_effect_size()
set.seed(1) cells <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 240), arm = rep(rep(c("reference", "interval_short"), each = 120), 2), unit_id = rep(paste0("u", 1:8), each = 60), log2_fc = stats::rnorm(480) ) cells$log2_fc <- cells$log2_fc + ifelse(cells$compound == "CompoundA" & cells$arm == "interval_short", -1, 0) u <- cr_effect_grid(cells, "log2_fc", "arm", "reference", by = "compound", unit = "unit_id") k <- cr_effect_grid(cells, "log2_fc", "arm", "reference", by = "compound", min_n = 10) cmp <- cr_compare_levels(u, k) cmp attr(cmp, "median_ratio")set.seed(1) cells <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 240), arm = rep(rep(c("reference", "interval_short"), each = 120), 2), unit_id = rep(paste0("u", 1:8), each = 60), log2_fc = stats::rnorm(480) ) cells$log2_fc <- cells$log2_fc + ifelse(cells$compound == "CompoundA" & cells$arm == "interval_short", -1, 0) u <- cr_effect_grid(cells, "log2_fc", "arm", "reference", by = "compound", unit = "unit_id") k <- cr_effect_grid(cells, "log2_fc", "arm", "reference", by = "compound", min_n = 10) cmp <- cr_compare_levels(u, k) cmp attr(cmp, "median_ratio")
Returns a rich set of per-unit summary statistics for a single channel: mean, median, SD, MAD, CV, cell count and percent positive above a threshold. Useful as input for QC dashboards and as the between-unit variability input of a screen.
cr_compute_metrics(experiment, channel, positive_threshold = NULL, unit = NULL)cr_compute_metrics(experiment, channel, positive_threshold = NULL, unit = NULL)
experiment |
A |
channel |
Channel name (a column of |
positive_threshold |
Optional numeric threshold. Cells above it
are counted as "positive"; without it |
unit |
Optional name of the column that identifies the
analysis unit. May be a column of |
A tibble with one row per analysis unit and the design columns appended.
cr_summarize_wells(), cr_table_disposition().
Other quantification:
cr_fold_change(),
cr_summarize_wells(),
cr_table_disposition()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_compute_metrics(exp, channel = "marker_1") cr_compute_metrics(exp, channel = "marker_1", positive_threshold = 800)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_compute_metrics(exp, channel = "marker_1") cr_compute_metrics(exp, channel = "marker_1", positive_threshold = 800)
cr_result
Confusion matrix for a logistic cr_result
cr_confusion_matrix(result, threshold = 0.5)cr_confusion_matrix(result, threshold = 0.5)
result |
A |
threshold |
Classification threshold on predicted probability
(default |
A tibble with sensitivity, specificity, ppv, npv,
accuracy, and the confusion-matrix counts.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") cr_confusion_matrix(res, 0.5)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") cr_confusion_matrix(res, 0.5)
Returns the end of a confidence interval that lies closer to zero,
which is the conservative effect a follow-up study should be powered
on. When the interval spans the null there is nothing to power on
and NA is returned.
cr_conservative_effect(ci_low, ci_high)cr_conservative_effect(ci_low, ci_high)
ci_low |
Numeric vector of lower interval bounds. |
ci_high |
Numeric vector of upper interval bounds. |
A numeric vector the length of the recycled inputs. Scalars can recycle; other lengths must agree, and lower bounds cannot exceed upper bounds.
Other power:
cr_power(),
cr_power_analysis(),
cr_power_grid()
cr_conservative_effect(c(-1.8, -0.4), c(-0.6, 0.9))cr_conservative_effect(c(-1.8, -0.4), c(-0.6, 0.9))
Applies a simple batch correction. "median_center" shifts each
batch's median to the overall median. The legacy "combat" choice
is refused: this single-channel interface cannot supply the feature-by-sample
matrix required for a valid empirical-Bayes ComBat analysis. Previous
versions could substitute median centering after a ComBat error. Select
"median_center" explicitly if that is the intended analysis.
cr_correct_batch( experiment, batch_var, channel, method = c("median_center", "combat") )cr_correct_batch( experiment, batch_var, channel, method = c("median_center", "combat") )
experiment |
A |
batch_var |
Name of the batch variable, or a character vector
of several column names that jointly define a batch (they are
collapsed with |
channel |
Channel to correct. |
method |
|
Batch correction removes a batch offset from the measured signal.
It is not a substitute for cr_standardize_batch(), which
expresses every cell relative to the control cells of its own
batch and leaves the measured signal untouched.
A modified cr_experiment.
cr_batch_key(), cr_standardize_batch()
Other batch standardization functions:
cr_batch_key(),
cr_batch_reference(),
cr_standardize_batch()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$batch <- rep(c("b1", "b2"), length.out = nrow(exp$design)) cr_correct_batch(exp, batch_var = "batch", channel = "marker_1") # A batch defined by more than one column exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) cr_correct_batch(exp, batch_var = c("batch", "plate"), channel = "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$batch <- rep(c("b1", "b2"), length.out = nrow(exp$design)) cr_correct_batch(exp, batch_var = "batch", channel = "marker_1") # A batch defined by more than one column exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) cr_correct_batch(exp, batch_var = c("batch", "plate"), channel = "marker_1")
A cr_dataset is what comes out of ingest: the cells of every export,
the per-file provenance that lets any row be traced back to the
acquisition it came from, and optionally the design those files
encode. It is the object to inspect before committing to an analysis,
and it converts to a cr_experiment with cr_build_experiment().
cr_dataset( cells, design = NULL, unit_var = NULL, provenance = NULL, file_col = "source_path", metadata = list(), call = rlang::caller_env() ) ## S3 method for class 'cr_dataset' print(x, ...) ## S3 method for class 'cr_dataset' summary(object, ...)cr_dataset( cells, design = NULL, unit_var = NULL, provenance = NULL, file_col = "source_path", metadata = list(), call = rlang::caller_env() ) ## S3 method for class 'cr_dataset' print(x, ...) ## S3 method for class 'cr_dataset' summary(object, ...)
cells |
A data frame of cells, typically from
|
design |
Optional |
unit_var |
Name of the analysis unit column. Defaults to the
design's unit column, or the first of |
provenance |
Optional per-file table. When |
file_col |
Name of the file column used for provenance. Default
|
metadata |
Optional list of arbitrary user metadata. |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
x |
A |
... |
Ignored. |
object |
A |
An object of class cr_dataset:
cellsTibble of per-cell measurements.
provenanceTibble with one row per source file, or NULL.
designA cr_design, or NULL.
unit_varName of the analysis unit column, or NULL.
metadataList of user metadata.
x, invisibly.
A tibble with one row per source file, or NULL when the data
set carries no provenance.
cr_read_exports(), cr_design(), cr_build_experiment().
Other constructors:
cr_build_experiment(),
cr_design(),
cr_validate_experiment()
cells <- tibble::tibble( source_path = rep(c("a.csv", "b.csv"), each = 3), source_file = rep(c("a.csv", "b.csv"), each = 3), well = rep(c("A01", "A02"), each = 3), treatment = rep(c("Vehicle", "CompoundA"), each = 3), target_signal = c(10, 12, 11, 30, 33, 29) ) ds <- cr_dataset(cells) ds ds$provenancecells <- tibble::tibble( source_path = rep(c("a.csv", "b.csv"), each = 3), source_file = rep(c("a.csv", "b.csv"), each = 3), well = rep(c("A01", "A02"), each = 3), treatment = rep(c("Vehicle", "CompoundA"), each = 3), target_signal = c(10, 12, 11, 30, 33, 29) ) ds <- cr_dataset(cells) ds ds$provenance
A cr_design records both the design table — one row per analysis
unit — and the roles its columns play: which column identifies the
unit, which holds the treatment, which level of that treatment is the
reference, and which columns together define a batch.
cr_design( data, unit = NULL, treatment = "treatment", control_level = NULL, batch_vars = NULL, levels = list(), keep = NULL, call = rlang::caller_env() ) ## S3 method for class 'cr_design' print(x, ...)cr_design( data, unit = NULL, treatment = "treatment", control_level = NULL, batch_vars = NULL, levels = list(), keep = NULL, call = rlang::caller_env() ) ## S3 method for class 'cr_design' print(x, ...)
data |
A data frame carrying the design columns. |
unit |
Name of the column identifying the analysis unit. If
|
treatment |
Name of the treatment (group) column. Default
|
control_level |
Optional value of |
batch_vars |
Optional character vector of columns that together define a batch. |
levels |
Optional named list of factor level orders applied to the corresponding design columns. |
keep |
Optional character vector of design columns to keep. The
unit column is always kept. |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
x |
A |
... |
Ignored. |
Recording the roles alongside the table is what lets later stages standardise each cell against the control of its own batch rather than against one pooled reference. A batch is normally a combination of columns (compound, run, plate, experiment, pre-treatment interval), which a single batch variable cannot express.
data may be a per-unit table or a per-cell / per-file table; in the
latter case it is collapsed to unique rows. If a unit maps to more
than one combination of design values the collapse is ambiguous and
the offending columns are named in the error, since silently keeping
the first row would invent a design that was never run.
An object of class cr_design:
tableTibble with one row per analysis unit.
unitName of the unit column.
treatmentName of the treatment column.
control_levelReference level, or NULL.
batch_varsCharacter vector of batch columns.
levelsThe factor level orders that were applied.
x, invisibly.
cr_dataset(), cr_build_experiment(), cr_read_design().
Other constructors:
cr_build_experiment(),
cr_dataset(),
cr_validate_experiment()
units <- tibble::tibble( well = sprintf("A%02d", 1:6), treatment = rep(c("Vehicle", "CompoundA"), each = 3), plate = rep(c("Plate_1", "Plate_2"), 3), replicate = rep(1:3, 2) ) design <- cr_design(units, control_level = "Vehicle", batch_vars = c("plate")) designunits <- tibble::tibble( well = sprintf("A%02d", 1:6), treatment = rep(c("Vehicle", "CompoundA"), each = 3), plate = rep(c("Plate_1", "Plate_2"), 3), replicate = rep(1:3, 2) ) design <- cr_design(units, control_level = "Vehicle", batch_vars = c("plate")) design
Fits a dose-response model to well-level summaries of a treatment
across doses. Supports 4-parameter log-logistic ("4pl"),
3-parameter log-logistic with fixed lower asymptote at zero
("3pl"), and a simple linear model ("linear").
cr_dose_response( experiment, channel, treatment = NULL, model = c("4pl", "3pl", "linear"), log_dose = TRUE )cr_dose_response( experiment, channel, treatment = NULL, model = c("4pl", "3pl", "linear"), log_dose = TRUE )
experiment |
A |
channel |
Channel name. |
treatment |
Character. Names of treatments to include (for
example a compound at several doses). If |
model |
|
log_dose |
If |
The 4PL model fitted is:
where a is the top asymptote, d the bottom asymptote, e the
inflection point (EC50 / IC50), and b the Hill slope.
A list with class "cr_dose_response" containing the
fitted model, the data used for the fit, the estimated
parameters, and helper predictions.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) # Add a synthetic dose-response sub-design exp$design$dose <- ifelse(exp$design$treatment == "CompoundA_high", 500, exp$design$dose) fit <- cr_dose_response(exp, channel = "marker_1", model = "4pl") print(fit$params)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) # Add a synthetic dose-response sub-design exp$design$dose <- ifelse(exp$design$treatment == "CompoundA_high", 500, exp$design$dose) fit <- cr_dose_response(exp, channel = "marker_1", model = "4pl") print(fit$params)
Drives cr_effect_size() over every group in a screen: for each
stratum given by by, each comparison level of group_var is
contrasted against reference_level, and every requested effect
size is reported with a confidence interval. The same function
serves both aggregation levels: supply unit to aggregate the rows
to one value per experimental unit (the unit of replication) before
the contrast is computed, or leave it NULL to work on the rows as
they are (typically single cells).
cr_effect_grid( data, value, group_var, reference_level, comparison_levels = NULL, by = NULL, unit = NULL, methods = c("cohens_d", "hedges_g", "cliffs_delta"), conf_level = 0.95, min_n = 3, test = c("t", "wilcox", "none"), p_adjust = c("bonferroni", "BH"), level = NULL )cr_effect_grid( data, value, group_var, reference_level, comparison_levels = NULL, by = NULL, unit = NULL, methods = c("cohens_d", "hedges_g", "cliffs_delta"), conf_level = 0.95, min_n = 3, test = c("t", "wilcox", "none"), p_adjust = c("bonferroni", "BH"), level = NULL )
data |
A data frame (one row per cell or per unit) or a
|
value |
Name of the numeric response column, for example a standardized log2 fold change or a raw channel. |
group_var |
Name of the column holding the compared groups. |
reference_level |
Level of |
comparison_levels |
Levels contrasted against the reference.
|
by |
Optional character vector of stratifying columns. One set of contrasts is computed per combination, for example one per compound. |
unit |
Optional name of the column identifying the unit of replication. When given, rows are averaged to one value per unit before the contrast is computed. |
methods |
Effect sizes to compute; see |
conf_level |
Confidence level for the intervals. |
min_n |
Minimum number of observations required in each arm.
Contrasts below it are skipped and recorded in the |
test |
P-value to accompany the effect sizes: |
p_adjust |
Multiplicity adjustments applied across the grid.
Default both |
level |
Optional label written into the |
Cell-level intervals are anticonservative by construction, because
cells within a unit are not independent. Compute both levels and
pass them to cr_compare_levels() to quantify the difference;
interpretation belongs to the unit level.
Multiplicity adjustment is applied across the entire returned grid and reported alongside the unadjusted p-value, never in place of it: for an exploratory screen the effect sizes and their intervals are the reportable quantity.
A tibble with one row per stratum and contrast: the by
columns, contrast, level, n_ref, n_cmp, mean_shift, one
<method>, <method>_ci_low, <method>_ci_high and
<method>_magnitude triplet per requested method, p_value, one
p_<adjustment> column per entry of p_adjust, and
ci_excludes_zero for the first method. The attributes
conf_level, level, primary_method and skipped (a tibble of
the contrasts that fell below min_n) are attached.
cr_effect_size(), cr_compare_levels(),
cr_power_grid(), cr_blocked_effect().
Other effect sizes:
cr_compare_levels(),
cr_effect_size()
set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 12), arm = rep(rep(c("reference", "interval_short"), each = 6), 2), unit_id = paste0("u", 1:24), log2_fc = c(stats::rnorm(6, 0, 0.3), stats::rnorm(6, -1, 0.3), stats::rnorm(6, 0, 0.3), stats::rnorm(6, -0.1, 0.3)) ) eff <- cr_effect_grid(units, value = "log2_fc", group_var = "arm", reference_level = "reference", by = "compound") eff[, c("compound", "contrast", "cohens_d", "cohens_d_ci_low", "cohens_d_ci_high", "ci_excludes_zero")]set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 12), arm = rep(rep(c("reference", "interval_short"), each = 6), 2), unit_id = paste0("u", 1:24), log2_fc = c(stats::rnorm(6, 0, 0.3), stats::rnorm(6, -1, 0.3), stats::rnorm(6, 0, 0.3), stats::rnorm(6, -0.1, 0.3)) ) eff <- cr_effect_grid(units, value = "log2_fc", group_var = "arm", reference_level = "reference", by = "compound") eff[, c("compound", "contrast", "cohens_d", "cohens_d_ci_low", "cohens_d_ci_high", "ci_excludes_zero")]
Standardized effect sizes for a comparison of two independent samples, each with a confidence interval. Confidence intervals are analytic by default (deterministic and cheap on large samples); a bootstrap interval is available for cases where the analytic approximation is not wanted.
cr_effect_size( x, y, method = c("cohens_d", "hedges_g", "cliffs_delta", "rank_biserial", "glass_delta"), ci = 0.95, ci_method = c("analytic", "bootstrap"), n_boot = 200, seed = NULL )cr_effect_size( x, y, method = c("cohens_d", "hedges_g", "cliffs_delta", "rank_biserial", "glass_delta"), ci = 0.95, ci_method = c("analytic", "bootstrap"), n_boot = 200, seed = NULL )
x |
Numeric vector (treatment group). |
y |
Numeric vector (control / reference group). |
method |
Character vector of methods to compute. Allowed:
|
ci |
Confidence level for the interval (default 0.95). Set
|
ci_method |
|
n_boot |
Number of bootstrap resamples used when
|
seed |
Optional integer seed for the bootstrap. The global random number stream is restored on exit. |
Cohen's d uses the pooled standard deviation without small-sample
correction and its interval is the large-sample (Hedges-Olkin)
approximation with a t quantile on n_x + n_y - 2 degrees of
freedom. Hedges' g applies the bias correction
to both estimate and interval.
Glass's delta standardizes by the standard deviation of y only.
Cliff's delta uses the consistent variance estimator with the
interval on the transformed scale, so the bounds always lie inside
. The rank-biserial correlation of two independent
samples equals Cliff's delta and is reported on the same scale.
A tibble with columns method, estimate, ci_low,
ci_high and magnitude.
cr_effect_grid() for a whole grid of contrasts,
cr_power() for the sample size implied by an effect size.
Other effect sizes:
cr_compare_levels(),
cr_effect_grid()
set.seed(1) cr_effect_size(stats::rnorm(100, 1), stats::rnorm(100, 0)) # bootstrap interval with a reproducible seed cr_effect_size(stats::rnorm(50, 1), stats::rnorm(50, 0), method = "cliffs_delta", ci_method = "bootstrap", n_boot = 50, seed = 42)set.seed(1) cr_effect_size(stats::rnorm(100, 1), stats::rnorm(100, 0)) # bootstrap interval with a reproducible seed cr_effect_size(stats::rnorm(50, 1), stats::rnorm(50, 0), method = "cliffs_delta", ci_method = "bootstrap", n_boot = 50, seed = 42)
Renders a character vector as "a", "a and b" or "a, b and c",
with a fixed placeholder for the empty case. Sentences that
enumerate results — which contrasts cleared a threshold, which arms
were excluded — should be generated for the same reason the numbers
are: the hand-written version is right until the analysis changes.
cr_enumerate(x, conjunction = "and", empty = "none", oxford = FALSE)cr_enumerate(x, conjunction = "and", empty = "none", oxford = FALSE)
x |
Character vector. |
conjunction |
Word joining the last two elements. |
empty |
Text returned when nothing is left. |
oxford |
Whether to place a comma before the conjunction. |
A single string.
cr_macros(), cr_format_number().
Other macros:
cr_format_number(),
cr_macro_name(),
cr_macros(),
cr_macros_from()
cr_enumerate(c("CompoundA", "CompoundB", "CompoundC")) cr_enumerate(c("CompoundA", "CompoundB"), conjunction = "or") cr_enumerate(character())cr_enumerate(c("CompoundA", "CompoundB", "CompoundC")) cr_enumerate(c("CompoundA", "CompoundB"), conjunction = "or") cr_enumerate(character())
Builds the unit-level design table used by
cr_example_experiment(). Six treatment levels are crossed with two
plates and two pre-treatment intervals, so that a batch is the
combination of plate and interval rather than a single column and
every batch still contains untreated units to standardise against.
cr_example_design(plate_format = 96, n_wells_per_replicate = 4)cr_example_design(plate_format = 96, n_wells_per_replicate = 4)
plate_format |
Either |
n_wells_per_replicate |
Number of units per replicate per treatment level. |
Treatment names are deliberately abstract. Untreated is the vehicle
level, PosControl a positive control, and CompoundA appears at a
low and a high exposure level so that a dose axis exists;
CompoundB and CompoundC are further compounds at the low exposure
level. The four distinct values of dose are the four exposure
levels of the demonstration assay.
A tibble with one row per unit and the columns well,
treatment, dose, dose_unit, group, replicate, plate,
interval and timepoint.
cr_example_experiment(), cr_example_screen().
Other example data:
cr_example_experiment(),
cr_example_exports(),
cr_example_files(),
cr_example_path(),
cr_example_screen()
design <- cr_example_design(96) table(design$treatment, design$interval)design <- cr_example_design(96) table(design$treatment, design$interval)
cr_experiment
Simulates a compact demonstration experiment: one 96-unit plate format, six treatment levels, four exposure levels, two plates and two pre-treatment intervals. It is small enough that every example in the package can build a fresh copy in well under a second, and structured enough that the batch, quality-control and effect-size functions all have something to work on.
cr_example_experiment( seed = 42, n_cells_per_well = 150, n_wells_per_replicate = 4 )cr_example_experiment( seed = 42, n_cells_per_well = 150, n_wells_per_replicate = 4 )
seed |
Random seed. |
n_cells_per_well |
Mean number of cells per unit (Poisson, with a floor of ten). |
n_wells_per_replicate |
Number of units per replicate. |
Use cr_example_screen() instead when a multi-compound screen with
per-batch controls, merged analysis units and a specificity arm is
needed.
A cr_experiment whose cells table holds one row per cell
(cell_id, well, x, y, area, circularity, DAPI,
marker_1, marker_2, marker_3) and whose design table holds
one row per unit, as described in cr_example_design().
Values are drawn independently per cell from log-normal distributions, so that the marker channels are right-skewed the way measured intensities are:
Each unit draws ,
added to the log mean of every channel in that unit. This is what
makes the unit, and not the cell, the honest replicate.
marker_1 is
, where
is the treatment effect in log2 units: 0 untreated,
1.0 and 3.0 for the low and high exposure level of
CompoundA, 3.3 for the positive control, 0.4 for
CompoundB and 0.7 for CompoundC.
marker_2 moves against the target signal
at , marker_3 weakly with it at .
DAPI is
and carries no
treatment effect.
Nuclear area is
and circularity is
.
Units on the outer rows and columns get a
fixed +0.07 log bump on every channel, an edge effect for the
plate map to show.
Five per cent of the cells of each unit are shrunk to a twentieth of their area and a tenth of their nuclear signal, so that the quality-control filters have something to remove.
Two named units are multiplied up on marker_1
and down on area, a saturated pair for the outlier screens.
The random number generator state of the caller is restored on exit, so calling this function does not disturb a seeded analysis.
cr_example_design(), cr_example_screen(),
cr_example_files().
Other example data:
cr_example_design(),
cr_example_exports(),
cr_example_files(),
cr_example_path(),
cr_example_screen()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp head(exp$design, 3)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp head(exp$design, 3)
Writes a nested directory of single-acquisition export files whose
design information lives in the directory layout and the file names
rather than inside the files. This is the input the multi-file ingest
functions were written for, so that cr_read_exports(),
cr_parse_paths() and cr_extract_markers() can be demonstrated on
real files.
cr_example_exports( dir = tempdir(), seed = 42, n_cells = 20, format = c("csv", "xlsx") )cr_example_exports( dir = tempdir(), seed = 42, n_cells = 20, format = c("csv", "xlsx") )
dir |
Directory to write the tree into. Created when it does not exist. |
seed |
Random seed. |
n_cells |
Number of cells written per file. |
format |
File format, |
The layout below dir is
Run1/<compound>/<experiment>/<plate>/<file>, and the file names
follow the grammar <compound>_<interval>_<dose>_<mode>_<replicate>
in which an absent token is meaningful: a name carrying no exposure
token is a vehicle control. Parenthetical markers are attached to
three files – a two-pass acquisition, a repeated read and a
reagent-omitted acquisition – and one directory is marked as a partly
filled plate.
Column headers are raw instrument names rather than analysis names,
and one of them carries a unit glyph, so that a cr_column_map() is
genuinely required to read them.
A character vector of the written file paths, invisibly.
cr_read_exports(), cr_path_spec(), cr_example_screen(),
cr_example_path().
Other example data:
cr_example_design(),
cr_example_experiment(),
cr_example_files(),
cr_example_path(),
cr_example_screen()
d <- file.path(tempdir(), "cr_example_exports") files <- cr_example_exports(d, seed = 1, n_cells = 5) basename(files) map <- cr_column_map( exact = c("Event Label" = "cell_id", "Target - Signal Mean" = "target_signal"), prefix = c("^Nuclei - Area" = "area") ) cells <- cr_read_exports(d, column_map = map, progress = FALSE) head(cells[, c("source_file", "cell_id", "target_signal", "area")], 3)d <- file.path(tempdir(), "cr_example_exports") files <- cr_example_exports(d, seed = 1, n_cells = 5) basename(files) map <- cr_column_map( exact = c("Event Label" = "cell_id", "Target - Signal Mean" = "target_signal"), prefix = c("^Nuclei - Area" = "area") ) cells <- cr_read_exports(d, column_map = map, progress = FALSE) head(cells[, c("source_file", "cell_id", "target_signal", "area")], 3)
Writes the tables behind cr_example_experiment() in the layouts the
cr_read_* importers understand, so that the import functions can be
demonstrated on real files without any being shipped.
cr_example_files(dir = tempdir(), seed = 42)cr_example_files(dir = tempdir(), seed = 42)
dir |
Directory to write into. Created when it does not exist. |
seed |
Seed passed to |
A character vector of the written file paths, invisibly.
cr_example_exports() for a nested export tree with the
design encoded in the paths, cr_example_path() for the files
shipped inside the package.
Other example data:
cr_example_design(),
cr_example_experiment(),
cr_example_exports(),
cr_example_path(),
cr_example_screen()
d <- file.path(tempdir(), "cr_example_files") files <- cr_example_files(d, seed = 1) basename(files)d <- file.path(tempdir(), "cr_example_files") files <- cr_example_files(d, seed = 1) basename(files)
Three tiny synthetic files are installed under extdata so that
examples, tests and vignettes can read a real file without writing
one first and without depending on any gated data.
cr_example_path(file = NULL)cr_example_path(file = NULL)
file |
Name of one shipped file, or |
example-export.csvOne acquisition of one unit as a vendor
export: raw instrument headers, an all-blank trailing row of the
kind many instruments write, and a header carrying a unit glyph,
which is what the prefix matching of cr_column_map() exists
for.
example-export.xlsxThe same acquisition as a workbook.
example-design.csvThe unit-level design table covering the units in the exports.
The two exports are the treated acquisition that
cr_example_exports(seed = 42, n_cells = 20) writes, so the shipped
files can be regenerated at any time rather than being opaque
binaries.
A character vector of absolute paths; length one when file
is given.
cr_read_export(), cr_read_design(), cr_example_files().
Other example data:
cr_example_design(),
cr_example_experiment(),
cr_example_exports(),
cr_example_files(),
cr_example_screen()
basename(cr_example_path()) cells <- cr_read_export(cr_example_path("example-export.csv")) head(cells, 3)basename(cr_example_path()) cells <- cr_read_export(cr_example_path("example-export.csv")) head(cells, 3)
Simulates a screen of up to ten compounds, each acquired at four
exposure levels and two pre-treatment intervals, on two plates and in
two experiments. Unlike cr_example_experiment() the analysis unit is
not the raw plate well: units carry file provenance, some are
assembled from more than one acquisition, and one arm is set aside
instead of screened.
cr_example_screen( seed = 42, n_compounds = 10, n_cells_per_well = 40, n_units_per_arm = 3, n_experiments = 2 )cr_example_screen( seed = 42, n_compounds = 10, n_cells_per_well = 40, n_units_per_arm = 3, n_experiments = 2 )
seed |
Random seed. |
n_compounds |
Number of compounds, 1 to 10. They are named
|
n_cells_per_well |
Mean number of cells per unit (Poisson, with a floor of ten). |
n_units_per_arm |
Units per compound, experiment, interval and exposure level. Three or more is needed for the effect-size grid. |
n_experiments |
Number of experiments, 1 or 2. |
Everything the screening functions need is present: a vehicle control
inside every batch for cr_batch_reference() and
cr_standardize_batch(), one unit that fails a control-referenced
gate for cr_qc_gate(), enough units per arm for cr_effect_grid(),
plates crossed with arms for cr_blocked_effect(), and a
reagent-omitted arm in set_aside.
A cr_experiment with
cellsone row per cell: cell_id, well_id,
source_file, source_path, x, y, area, circularity,
nuclear_signal, target_signal.
designone row per unit: well_id, compound,
experiment, plate, well, interval, dose, dose_unit,
treatment, group, replicate.
provenanceone row per acquisition file, with marker flags and the number of files each unit was assembled from.
set_asidea list whose reagent_omitted element holds
the specificity arm.
unit_var is "well_id" and batch_vars is
c("compound", "experiment", "plate", "interval").
A batch is the combination of compound, experiment, plate and
interval. Writing for the potency of compound ,
for the exposure level and for the unit intercept:
runs from 1.6 down to 0.1 in equal
steps from CompoundA to the last compound, so the rank order of
the screen is known in advance and the top hit is a hit by
construction rather than by chance.
The response saturates in dose as
, so the four exposure levels are not equally
spaced in effect.
The longer pre-treatment interval multiplies the
effect by 1.15.
, in
log2 units against the vehicle of the same batch.
on the log scale,
one draw per unit.
The second experiment has a 1.35 times
higher raw baseline and the second plate a 1.08 times higher
one. Both act on control and treated units alike, which is what
standardising against the control of a unit's own batch removes,
and why raw signal is not comparable across experiments.
.
, with no treatment effect.
Nuclear area is
and circularity is
. Four per cent of objects are shrunk to
an eighth of their area, the sub-threshold debris that
cr_exclude_small() is meant to drop.
One treated unit of the first compound is given a negative effect, so it sits below the control of its own batch and fails a control-referenced gate.
One unit's cells are split across two
files, the second carrying a (split) marker and a .1
replicate suffix. Left unmerged it would count twice.
One unit's cells are split across a file and
its (repeat) sibling, which has to merge into it.
One separate unit is named with a .2
replicate suffix, which must not merge with the unit named 2:
it is a different physical unit on a different plate.
A reagent-omitted arm is generated and
placed in set_aside rather than in the analysis pool.
The random number generator state of the caller is restored on exit.
cr_example_experiment(), cr_example_exports(),
cr_batch_reference(), cr_effect_grid().
Other example data:
cr_example_design(),
cr_example_experiment(),
cr_example_exports(),
cr_example_files(),
cr_example_path()
screen <- cr_example_screen(seed = 1, n_compounds = 3, n_cells_per_well = 12) screen table(screen$design$compound, screen$design$treatment) # Units assembled from more than one acquisition file prov <- screen$provenance unique(prov$well_id[prov$n_files > 1])screen <- cr_example_screen(seed = 1, n_compounds = 3, n_cells_per_well = 12) screen table(screen$design$compound, screen$design$treatment) # Units assembled from more than one acquisition file prov <- screen$provenance unique(prov$well_id[prov$n_files > 1])
Removes objects whose segmentation size falls below a quantile of
the observed size distribution. Unlike cr_qc_filter(), which
applies an absolute threshold, the cut-off here is derived from the
data, so it adapts to magnification and segmentation settings. The
realised threshold is recorded, because a data-derived cut-off is
only reproducible if the value it resolved to is reported.
cr_exclude_small( experiment, var = "area", probs = 0.1, threshold = NULL, scope = c("pooled", "batch"), batch_vars = NULL )cr_exclude_small( experiment, var = "area", probs = 0.1, threshold = NULL, scope = c("pooled", "batch"), batch_vars = NULL )
experiment |
A |
var |
Name of the size column in |
probs |
Quantile of the |
threshold |
Optional absolute threshold. When supplied it
overrides |
scope |
|
batch_vars |
Character vector of columns (from |
Cells with a non-finite value in var are always removed: they
cannot be placed on either side of the threshold.
scope = "pooled" computes one threshold from all cells. That is
the right choice when the segmentation settings were shared across
the whole study. scope = "batch" computes one threshold per
combination of batch_vars, which protects a batch acquired at a
different magnification from being trimmed against a pool it does
not belong to — at the cost of a threshold that is no longer
comparable between batches.
Run this step before cr_balance_cells(): balancing changes how
many cells each unit contributes to the pool, so a threshold
computed afterwards is taken on a differently weighted
distribution.
A modified cr_experiment. The realised threshold(s) are
stored in metadata$exclude_small as a tibble and summarised in
the QC log.
cr_balance_cells(), cr_qc_filter(), cr_qc_report().
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) exp2 <- cr_exclude_small(exp, var = "area", probs = 0.10) exp2$metadata$exclude_small # one threshold per replicate block exp3 <- cr_exclude_small(exp, scope = "batch", batch_vars = "replicate") exp3$metadata$exclude_smallexp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) exp2 <- cr_exclude_small(exp, var = "area", probs = 0.10) exp2$metadata$exclude_small # one threshold per replicate block exp3 <- cr_exclude_small(exp, scope = "batch", batch_vars = "replicate") exp3$metadata$exclude_small
Export plots to PNG, PDF or SVG in batch
cr_export_plots( plots, path, format = c("png", "pdf", "svg"), width = 6, height = 4, dpi = 300, ... )cr_export_plots( plots, path, format = c("png", "pdf", "svg"), width = 6, height = 4, dpi = 300, ... )
plots |
A named list of ggplot2 objects. Unnamed elements are numbered. |
path |
Output directory, created when needed. |
format |
|
width, height
|
Figure dimensions in inches. |
dpi |
Resolution for raster outputs. |
... |
Further arguments passed to |
A character vector of written file paths (invisibly).
Other reporting:
cr_export_results(),
cr_export_tables(),
cr_render_report(),
cr_report(),
cr_table_qc(),
cr_tables()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) p1 <- cr_plot_intensity(exp, "marker_1") out <- tempfile("plots_") cr_export_plots(list(intensity = p1), out, width = 4, height = 3)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) p1 <- cr_plot_intensity(exp, "marker_1") out <- tempfile("plots_") cr_export_plots(list(intensity = p1), out, width = 4, height = 3)
Export report audit provenance as JSON
cr_export_report_audit(report, path, output_file = NULL)cr_export_report_audit(report, path, output_file = NULL)
report |
A |
path |
Output JSON path. |
output_file |
Optional rendered file to hash. |
Named field labels are encoded as a JSON object. Date-time export retains its existing whole-second representation; fractional precision is not preserved by this format.
cr_export_report_spec(spec, path, pretty = TRUE)cr_export_report_spec(spec, path, pretty = TRUE)
spec |
A |
path |
Output JSON path. |
pretty |
Pretty-print JSON. |
Writes a single flat table of results. Anything the reporting layer
produces is accepted: a cr_report, a cr_result, the list
returned by cr_test_all(), a named list of tables, or a plain data
frame.
cr_export_results(results, path, format = NULL)cr_export_results(results, path, format = NULL)
results |
A |
path |
Output file path. The extension determines the format
unless |
format |
One of |
The output path (invisibly).
cr_export_tables() to write several tables at once and
cr_macros() to emit individual numbers.
Other reporting:
cr_export_plots(),
cr_export_tables(),
cr_render_report(),
cr_report(),
cr_table_qc(),
cr_tables()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) rep <- cr_report(exp) f <- tempfile(fileext = ".csv") cr_export_results(rep$tables$disposition, f) utils::read.csv(f)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) rep <- cr_report(exp) f <- tempfile(fileext = ".csv") cr_export_results(rep$tables$disposition, f) utils::read.csv(f)
Writes the named list produced by cr_tables(). Excel output can go
into one workbook with a sheet per table; CSV always writes one file
per table into a directory, because a CSV file holds exactly one
table.
cr_export_tables(tables, path, format = c("csv", "xlsx"), one_file = TRUE)cr_export_tables(tables, path, format = c("csv", "xlsx"), one_file = TRUE)
tables |
A named list of data frames, or a single data frame. |
path |
Destination. For a single Excel workbook this is the file path; otherwise it is a directory, which is created when needed. |
format |
|
one_file |
Whether to write one Excel workbook with a sheet per table. Ignored for CSV. |
A character vector of written paths (invisibly).
cr_tables(), cr_export_results().
Other reporting:
cr_export_plots(),
cr_export_results(),
cr_render_report(),
cr_report(),
cr_table_qc(),
cr_tables()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) tabs <- cr_tables(exp) out <- tempfile("tables_") paths <- cr_export_tables(tabs, out) basename(paths)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) tabs <- cr_tables(exp) out <- tempfile("tables_") paths <- cr_export_tables(tabs, out) basename(paths)
Applies a cr_marker_rules() set to a table that carries a file-name
column, adding one logical column per rule plus a character variant
column holding any unmatched trailing parenthetical.
cr_extract_markers( x, name_col = "source_file", container_col = NULL, rules = cr_marker_rules(), stem_col = NULL, strip_ext = TRUE, call = rlang::caller_env() )cr_extract_markers( x, name_col = "source_file", container_col = NULL, rules = cr_marker_rules(), stem_col = NULL, strip_ext = TRUE, call = rlang::caller_env() )
x |
A data frame with one row per file (or per cell). |
name_col |
Name of the column holding the file name. Default
|
container_col |
Optional name of the column holding the container
(plate or directory) name that |
rules |
A |
stem_col |
Optional name of a column to write the marker-stripped name into. |
strip_ext |
Logical. Remove a trailing file extension before
matching. Default |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
x with the columns merge_unit, partial_plate,
omitted_reagent, reacquisition, lot (all logical) and
variant (character) added. Columns for rules that were not
supplied are FALSE throughout.
cr_marker_rules(), cr_parse_paths().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
files <- tibble::tibble( source_file = c("CompoundA_10uM_treated_1.csv", "CompoundA_10uM_treated_1.1 (split).csv", "CompoundA_vehicle_1 (no reagent).csv", "CompoundA_vehicle_2 (weekend).csv"), plate = c("Plate_1", "Plate_1", "Plate_1", "Plate_2 (partial)") ) cr_extract_markers( files, container_col = "plate", rules = cr_marker_rules(merge_unit = "\\(split\\)", partial_plate = "\\(partial\\)", omitted_reagent = "\\(no reagent\\)") )files <- tibble::tibble( source_file = c("CompoundA_10uM_treated_1.csv", "CompoundA_10uM_treated_1.1 (split).csv", "CompoundA_vehicle_1 (no reagent).csv", "CompoundA_vehicle_2 (weekend).csv"), plate = c("Plate_1", "Plate_1", "Plate_1", "Plate_2 (partial)") ) cr_extract_markers( files, container_col = "plate", rules = cr_marker_rules(merge_unit = "\\(split\\)", partial_plate = "\\(partial\\)", omitted_reagent = "\\(no reagent\\)") )
Build a descriptive figure caption
cr_figure_caption( title = NULL, description = NULL, n = NULL, unit = NULL, qc_note = NULL )cr_figure_caption( title = NULL, description = NULL, n = NULL, unit = NULL, qc_note = NULL )
title, description, qc_note
|
User-supplied descriptive text. |
n |
Optional observation count. |
unit |
Optional unit-of-replication label. |
Standard deterministic figure dimensions
cr_figure_size( size = c("single", "double", "report", "square"), units = c("mm", "in") )cr_figure_size( size = c("single", "double", "report", "square"), units = c("mm", "in") )
size |
One of |
units |
|
A cr_filename_grammar states how one export file name decomposes
into design facts: which trailing token is the replicate index, which
leading labels are stripped, which substrings are tokens, and which
whole-name shapes are legal at all.
cr_filename_grammar( tokens = list(), defaults = list(), core_patterns = character(), typo_fixes = character(), prefix_strip = character(), replicate = "[0-9]+(?:\\.[0-9]+)?", sep = "_", normalise_space = TRUE ) ## S3 method for class 'cr_filename_grammar' print(x, ...)cr_filename_grammar( tokens = list(), defaults = list(), core_patterns = character(), typo_fixes = character(), prefix_strip = character(), replicate = "[0-9]+(?:\\.[0-9]+)?", sep = "_", normalise_space = TRUE ) ## S3 method for class 'cr_filename_grammar' print(x, ...)
tokens |
Named list (or named character vector) of regular expressions. Each is searched for in the name core; the matched text becomes the value of a column named after the list element. |
defaults |
Named list of values to use when a token is absent.
Elements with no entry default to |
core_patterns |
Character vector of regular expressions. The core (the name with extension, markers, replicate index and prefix removed) must match at least one of them. Empty means no whitelist. |
typo_fixes |
Named character vector of |
prefix_strip |
Character vector of leading labels to strip from the core, longest first. |
replicate |
Regular expression for the trailing replicate token.
Default |
sep |
Token separator. Default |
normalise_space |
Logical. Convert runs of whitespace to |
x |
A |
... |
Ignored. |
The core_patterns whitelist exists because the absence of a token is
itself meaningful — a name with no interval token is the untreated
reference arm, a name with no concentration token is a vehicle
control. A mistyped token therefore matches nothing, falls through to
the defaults, and silently reclassifies a treated unit as a vehicle
control, pulling it into the control denominator of its own batch.
With a whitelist in place such a name is a hard error instead.
prefix_strip entries are removed longest-first, so a short label
cannot consume a longer one that starts with the same characters.
An object of class cr_filename_grammar (a list).
x, invisibly.
cr_parse_paths(), cr_path_spec().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
g <- cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM", mode = "treated|vehicle"), defaults = list(interval = "none", dose = "vehicle"), core_patterns = c("^vehicle$", "^[0-9]+min_vehicle$", "^[0-9]+uM_treated$", "^[0-9]+min_[0-9]+uM_treated$"), prefix_strip = c("CompoundA", "CompoundB") ) gg <- cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM", mode = "treated|vehicle"), defaults = list(interval = "none", dose = "vehicle"), core_patterns = c("^vehicle$", "^[0-9]+min_vehicle$", "^[0-9]+uM_treated$", "^[0-9]+min_[0-9]+uM_treated$"), prefix_strip = c("CompoundA", "CompoundB") ) g
cr_experiment
A thin wrapper around dplyr::filter() applied to the cells
slot. Filtering is additive: rows excluded here are removed from
the returned experiment and logged in qc_log.
cr_filter_cells(experiment, ...)cr_filter_cells(experiment, ...)
experiment |
A |
... |
Filtering expressions passed on to |
A modified cr_experiment.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) cr_filter_cells(exp, area > 50)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) cr_filter_cells(exp, area > 50)
Apply a caller-selected QC finalization rule
cr_finalize_result( classification, qc_status, failed_statuses = "FAIL", invalid_label = "INVALID", invalidate = TRUE )cr_finalize_result( classification, qc_status, failed_statuses = "FAIL", invalid_label = "INVALID", invalidate = TRUE )
classification |
Character vector. |
qc_status |
Character vector, recycled against |
failed_statuses |
QC labels treated as failed. |
invalid_label |
Label used for failed QC. |
invalidate |
Whether failed QC replaces the supplied classification. |
Returns log2 fold changes at the cell and unit levels, relative to one pooled reference computed from the control group.
cr_fold_change( experiment, channel, control_group, method = c("median", "mean"), eps = 0, unit = NULL )cr_fold_change( experiment, channel, control_group, method = c("median", "mean"), eps = 0, unit = NULL )
experiment |
A |
channel |
Channel name (a column of |
control_group |
Value in |
method |
|
eps |
Additive offset applied to numerator and denominator
before the ratio is taken, i.e. |
unit |
Optional name of the column that identifies the
analysis unit. May be a column of |
The reference is pooled across the whole experiment. When controls differ systematically between plates, runs or acquisition days, standardize each cell against the control of its own batch instead — a pooled reference silently mixes those batches together.
A list with components cell (tibble, one row per cell with
log2_fc), well (one row per analysis unit) and summary (per
treatment: number of units, median, mean and SD of the unit-level
log2 fold change).
Other quantification:
cr_compute_metrics(),
cr_summarize_wells(),
cr_table_disposition()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) fc <- cr_fold_change(exp, channel = "marker_1", control_group = "Untreated") fc$summary # additive offset instead of a floor fc2 <- cr_fold_change(exp, channel = "marker_1", control_group = "Untreated", eps = 1) fc2$summaryexp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) fc <- cr_fold_change(exp, channel = "marker_1", control_group = "Untreated") fc$summary # additive offset instead of a floor fc2 <- cr_fold_change(exp, channel = "marker_1", control_group = "Untreated", eps = 1) fc2$summary
Format an estimate and confidence interval
cr_format_interval(estimate, lower, upper, digits = 2)cr_format_interval(estimate, lower, upper, digits = 2)
estimate, lower, upper
|
Numeric vectors. |
digits |
Decimal places. |
Fixed-decimal formatting with the conventions a manuscript needs: a
placeholder rather than NaN for non-finite values, an optional
explicit sign — never printed on an exact zero, where a sign would
claim a direction the data does not support — and thousands
separators for counts.
cr_format_number(x, digits = 3, signed = FALSE, big_mark = ",", na = "--")cr_format_number(x, digits = 3, signed = FALSE, big_mark = ",", na = "--")
x |
Numeric vector. |
digits |
Decimal places. |
signed |
Whether to print a leading |
big_mark |
Thousands separator. |
na |
Placeholder for |
A character vector of the same length as x.
Other macros:
cr_enumerate(),
cr_macro_name(),
cr_macros(),
cr_macros_from()
cr_format_number(c(1.2345, -0.5, 0, NA)) cr_format_number(c(1.2345, -0.5, 0), signed = TRUE) cr_format_number(128400, digits = 0)cr_format_number(c(1.2345, -0.5, 0, NA)) cr_format_number(c(1.2345, -0.5, 0), signed = TRUE) cr_format_number(128400, digits = 0)
Format proportions as percentages
cr_format_percent(x, digits = 1)cr_format_percent(x, digits = 1)
x |
Numeric proportions. |
digits |
Decimal places. |
Format p-values without displaying calculated zero
cr_format_pvalue(x, digits = 3)cr_format_pvalue(x, digits = 3)
x |
Numeric p-values. |
digits |
Decimal places determining the reporting threshold. |
Extract IC50 / EC50 from a dose-response fit
cr_ic50(fit, level = 0.95)cr_ic50(fit, level = 0.95)
fit |
A |
level |
Confidence level for the interval (default 0.95). |
A tibble with estimate, ci_low, ci_high,
parameter (IC50 or EC50) and units.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$dose <- ifelse(exp$design$treatment == "CompoundA_high", 500, exp$design$dose) fit <- cr_dose_response(exp, channel = "marker_1", model = "4pl") cr_ic50(fit)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$dose <- ifelse(exp$design$treatment == "CompoundA_high", 500, exp$design$dose) fit <- cr_dose_response(exp, channel = "marker_1", model = "4pl") cr_ic50(fit)
Date-only timestamps retain Date class; ISO timestamps with Z or numeric offsets are restored as UTC date-times. Legacy space-separated UTC times with minutes or seconds (optionally ending in UTC) are also accepted. Custom-section lists and named field-label objects retain their structure. This cannot recover names or fractional seconds lost in older exports and does not guarantee equality of whole-report hashes after a JSON round trip.
cr_import_report_spec(path, validate = TRUE)cr_import_report_spec(path, validate = TRUE)
path |
Input JSON path. |
validate |
Validate the reconstructed specification. |
Look up explicit interpretation text
cr_interpretation_lookup(classification, dictionary, default = NA_character_)cr_interpretation_lookup(classification, dictionary, default = NA_character_)
classification |
Character vector. |
dictionary |
Named character vector or named list. |
default |
Value used for unknown or missing classifications. |
Assemble a laboratory report without recalculating analytical values
cr_lab_report( experiment = NULL, spec = cr_report_spec(), qc = NULL, result_graphic = FALSE, include_audit_appendix = NULL, strict = TRUE, style = NULL, profile = NULL )cr_lab_report( experiment = NULL, spec = cr_report_spec(), qc = NULL, result_graphic = FALSE, include_audit_appendix = NULL, strict = TRUE, style = NULL, profile = NULL )
experiment |
Optional validated |
spec |
A |
qc |
Optional concise QC table from |
result_graphic |
Optional precomputed plot, or |
include_audit_appendix |
Include a compact audit appendix in the rendered document. |
strict |
Apply strict specification validation. |
style |
A |
profile |
Optional |
Claim identifiers become custom-field names and their displays become field values. Existing custom fields with the same names are rejected. The existing report renderer and audit exporter revalidate source files and bound fields. Other report fields and free text are not verified by this contract.
cr_lab_report_from_evidence(evidence, root, spec = cr_report_spec(), ...)cr_lab_report_from_evidence(evidence, root, spec = cr_report_spec(), ...)
evidence |
A |
root |
Current source-tree root. Retained for local validation, but excluded from report data and portable evidence hashes. |
spec |
|
... |
Other arguments to |
A cr_lab_report with additional evidence and local root fields.
Stable line types for categorical figures
cr_linetypes(n = NULL, names = NULL)cr_linetypes(n = NULL, names = NULL)
n |
Number required, at most six. |
names |
Optional category names. |
Fits a univariate logistic regression on a single fluorescence
channel for the binary outcome treatment == treatment (vs.
treatment == control). Returns a cr_result with the fitted
model, ROC curve and AUC.
cr_logistic( experiment, channel, treatment, control, level = c("cell", "replicate") )cr_logistic( experiment, channel, treatment, control, level = c("cell", "replicate") )
experiment |
A |
channel |
Channel name. |
treatment |
Name of treatment group. |
control |
Name of control group. |
level |
|
A cr_result.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, channel = "marker_1", treatment = "CompoundA_high", control = "Untreated") print(res)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, channel = "marker_1", treatment = "CompoundA_high", control = "Untreated") print(res)
Turns a label into an identifier that a LaTeX control sequence
accepts: letters only, with digits spelled out and every other
character dropped. "CompoundA_5min" becomes "CompoundAfivemin".
cr_macro_name(x, prefix = NULL)cr_macro_name(x, prefix = NULL)
x |
Character vector of labels. |
prefix |
Optional prefix, transliterated the same way. |
A character vector of the same length as x.
Other macros:
cr_enumerate(),
cr_format_number(),
cr_macros(),
cr_macros_from()
cr_macro_name(c("CompoundA_5min", "interval-2", "n cells")) cr_macro_name("estimate", prefix = "screen")cr_macro_name(c("CompoundA_5min", "interval-2", "n cells")) cr_macro_name("estimate", prefix = "screen")
Writes every number a write-up quotes into one machine-generated file, so the text can reference the value by name instead of repeating the digits. A number that lives in exactly one place cannot disagree with itself: re-run the analysis, re-emit the file, and the document is current. Splicing an estimate from one run beside an interval from another stops being possible.
cr_macros( values, file, format = c("tex", "json", "yaml"), prefix = NULL, header = NULL, digits = 3, big_mark = ",", na = "--" )cr_macros( values, file, format = c("tex", "json", "yaml"), prefix = NULL, header = NULL, digits = 3, big_mark = ",", na = "--" )
values |
A named list or named atomic vector of scalars. Nested named lists are flattened, joining the names. |
file |
Output path. When |
format |
|
prefix |
Optional prefix prepended to every name. A prefix is
worth setting for |
header |
Optional character vector of header lines. |
digits |
Decimal places used when formatting numbers. Counts —
integers, and round values of 1000 or more — are written without
decimals and with |
big_mark |
Thousands separator used in |
na |
Placeholder for non-finite values in |
LaTeX control sequences may contain letters only, so names are
transliterated by cr_macro_name() — "CompoundA_5min" becomes
\CompoundAfivemin. Two source names that transliterate to the same
macro are an error rather than a silent overwrite.
The output path (invisibly), or a character vector of lines
when file is NULL.
cr_macros_from() to derive the values from a report,
cr_macro_name(), cr_format_number(), cr_enumerate().
Other macros:
cr_enumerate(),
cr_format_number(),
cr_macro_name(),
cr_macros_from()
vals <- list(cells_analyzed = 128400L, units_analyzed = 96L, top_estimate = 1.42, top_ci_low = 0.55) cat(cr_macros(vals, file = NULL), sep = "\n") f <- tempfile(fileext = ".tex") cr_macros(vals, f, prefix = "screen") cat(readLines(f)[1:2], sep = "\n")vals <- list(cells_analyzed = 128400L, units_analyzed = 96L, top_estimate = 1.42, top_ci_low = 0.55) cat(cr_macros(vals, file = NULL), sep = "\n") f <- tempfile(fileext = ".tex") cr_macros(vals, f, prefix = "screen") cat(readLines(f)[1:2], sep = "\n")
Walks an assembled report (or any table of contrasts) and turns it
into the named values cr_macros() emits: the disposition counts,
one entry per contrast and numeric column, and the enumerations that
a sentence would otherwise state by hand — which intervals exclude
the null, and how many. Enumerations are the entries most worth
generating, because a hand-typed list is wrong as soon as one row of
the analysis changes.
cr_macros_from(x, file, label_cols = NULL, ci = c("ci_low", "ci_high"), ...)cr_macros_from(x, file, label_cols = NULL, ci = c("ci_low", "ci_high"), ...)
x |
A |
file |
Output path, or |
label_cols |
Character vector naming the columns that identify
a row. |
ci |
Names of the lower and upper confidence-bound columns,
used for the "excludes zero" enumerations. |
... |
Passed to |
The output path (invisibly), or a character vector of lines
when file is NULL.
Other macros:
cr_enumerate(),
cr_format_number(),
cr_macro_name(),
cr_macros()
eff <- data.frame( group = c("CompoundA", "CompoundB", "CompoundC"), estimate = c(1.42, 0.31, -0.88), ci_low = c(0.55, -0.10, -1.60), ci_high = c(2.29, 0.72, -0.16) ) cat(cr_macros_from(eff, file = NULL), sep = "\n")eff <- data.frame( group = c("CompoundA", "CompoundB", "CompoundC"), estimate = c(1.42, 0.31, -0.88), ci_low = c(0.55, -0.10, -1.60), ci_high = c(2.29, 0.72, -0.16) ) cat(cr_macros_from(eff, file = NULL), sep = "\n")
Acquisition software and operators annotate exports with short
markers, and those markers change the analysis. A cr_marker_rules
object states which regular expression means what, so that a marker
becomes a typed flag instead of a string somebody has to remember.
cr_marker_rules( merge_unit = NULL, partial_plate = NULL, omitted_reagent = NULL, reacquisition = NULL, lot = NULL, capture_unknown = TRUE, ignore_case = TRUE )cr_marker_rules( merge_unit = NULL, partial_plate = NULL, omitted_reagent = NULL, reacquisition = NULL, lot = NULL, capture_unknown = TRUE, ignore_case = TRUE )
merge_unit |
Regular expression marking a file as one half of a
two-pass acquisition, or |
partial_plate |
Regular expression matched against the container
(directory) name, or |
omitted_reagent |
Regular expression marking the specificity arm,
or |
reacquisition |
Regular expression marking a repeated read, or
|
lot |
Regular expression marking a reagent lot, or |
capture_unknown |
Logical. Capture an unmatched trailing
parenthetical into |
ignore_case |
Logical. Match case-insensitively. Default |
The distinctions the rules encode are deliberate:
merge_unit sits on a file and means one spatial unit was
acquired in two passes. The two files are one unit and must be
merged before any per-unit balancing, or the unit contributes twice
the cells of its neighbours.
partial_plate sits on a container (the plate directory) and
means a partly filled plate. It has no downstream consequence.
Collapsing the two into one flag hides the one that matters, so they
are matched against different strings.
omitted_reagent marks the specificity arm, where the detection
reagent was left out. These acquisitions are never samples.
reacquisition marks a repeated read of a unit that already has a
plain sibling file.
lot marks a different reagent lot. A lot marker is not an
omitted-reagent control; pooling the two inverts the meaning of the
arm.
Any trailing parenthetical that matches none of the rules is captured
verbatim into a variant column when capture_unknown = TRUE, rather
than being guessed at or silently dropped.
An object of class cr_marker_rules (a list).
cr_extract_markers(), cr_parse_paths(),
cr_merge_rules().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
rules <- cr_marker_rules( merge_unit = "\\(split\\)", partial_plate = "\\(partial\\)", omitted_reagent = "\\(no reagent\\)", reacquisition = "\\(repeat\\)", lot = "\\(lot[A-Z]\\)" ) rulesrules <- cr_marker_rules( merge_unit = "\\(split\\)", partial_plate = "\\(partial\\)", omitted_reagent = "\\(no reagent\\)", reacquisition = "\\(repeat\\)", lot = "\\(lot[A-Z]\\)" ) rules
Combines two or more cr_experiment objects that share the same
schema (channel panel, spatial unit). Useful for multi-plate
studies. Well/slide names must be unique across inputs (prefix
them with a plate identifier if necessary).
cr_merge_experiments(...)cr_merge_experiments(...)
... |
|
A single merged cr_experiment.
e1 <- cr_example_experiment(seed = 1, n_cells_per_well = 10) e2 <- cr_example_experiment(seed = 2, n_cells_per_well = 10) e2$cells$well <- paste0("p2_", e2$cells$well) e2$design$well <- paste0("p2_", e2$design$well) merged <- cr_merge_experiments(e1, e2)e1 <- cr_example_experiment(seed = 1, n_cells_per_well = 10) e2 <- cr_example_experiment(seed = 2, n_cells_per_well = 10) e2$cells$well <- paste0("p2_", e2$cells$well) e2$design$well <- paste0("p2_", e2$design$well) merged <- cr_merge_experiments(e1, e2)
States which replicate suffixes and marker flags mean "these files are one unit" and which mean "these files are different units". Getting this wrong is silent in both directions, so each rule is explicit.
cr_merge_rules( merge_suffix = "\\.1$", merge_marker = "merge_unit", keep_separate = "\\.2$", reacquisition = "reacquisition", merge_reacquisition = TRUE, separate_suffix = "re" ) ## S3 method for class 'cr_merge_rules' print(x, ...)cr_merge_rules( merge_suffix = "\\.1$", merge_marker = "merge_unit", keep_separate = "\\.2$", reacquisition = "reacquisition", merge_reacquisition = TRUE, separate_suffix = "re" ) ## S3 method for class 'cr_merge_rules' print(x, ...)
merge_suffix |
Regular expression matched against the replicate
index, marking a second acquisition pass. |
merge_marker |
Name of a logical column that must be |
keep_separate |
Regular expression matched against the replicate
index, marking indices that must never merge. |
reacquisition |
Name of a logical column marking repeated reads,
or |
merge_reacquisition |
Logical. Fold repeated reads into their
plain sibling. Default |
separate_suffix |
Suffix appended to the replicate index of a
repeated read when |
x |
A |
... |
Ignored. |
merge_suffix matches the replicate index of a file that is the
second pass over a unit that already exists. Left unmerged, such a
unit draws a full cell allocation twice and is double-weighted in
its own batch.
merge_marker names a logical column (typically produced by
cr_extract_markers()) that must also be TRUE before a suffix
match is merged. Requiring the marker is the conservative default:
a suffix on its own is not evidence.
keep_separate matches replicate indices that look mergeable but
are a different physical unit. It always wins over merge_suffix.
cr_centroid_overlap() is the evidence test for deciding which of
the two a given suffix is.
reacquisition names the logical column marking a repeated read.
With merge_reacquisition = TRUE such a file folds into its plain
sibling; otherwise separate_suffix is appended so it stays a unit
of its own.
An object of class cr_merge_rules (a list).
x, invisibly.
cr_assign_units(), cr_extract_markers(),
cr_centroid_overlap().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
cr_merge_rules() cr_merge_rules(merge_marker = NULL, keep_separate = NULL)cr_merge_rules() cr_merge_rules(merge_marker = NULL, keep_separate = NULL)
cr_experiment
Count cells in a cr_experiment
cr_n_cells(experiment, by = NULL)cr_n_cells(experiment, by = NULL)
experiment |
A |
by |
Optional character vector of grouping columns from the
|
Either a scalar integer (no grouping) or a tibble with cell counts per group.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) cr_n_cells(exp) cr_n_cells(exp, by = "treatment")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) cr_n_cells(exp) cr_n_cells(exp, by = "treatment")
Applies a channel-wise normalization. The normalized channel
values replace the original column in cells.
cr_normalize( experiment, channel, method = c("background", "control", "zscore", "robust_zscore", "quantile"), control_group = NULL, ... )cr_normalize( experiment, channel, method = c("background", "control", "zscore", "robust_zscore", "quantile"), control_group = NULL, ... )
experiment |
A |
channel |
Channel column to normalize. |
method |
One of |
control_group |
For |
... |
Additional arguments passed to the underlying method. |
"background" subtracts per-well background via
cr_background_subtract() (percentile method, 5th percentile).
"control" divides each cell's intensity by the median intensity
of cells assigned to control_group, then takes the log2 ratio.
"zscore" applies a global Z-score across all cells.
"robust_zscore" uses the median and MAD.
"quantile" maps the per-well empirical distributions onto the
global quantile distribution.
All five methods use a single, pooled reference for the whole
experiment and overwrite the channel in place. When the reference
has to be the control of each cell's own batch – the usual
situation once several plates, runs or acquisition days are
involved – use cr_standardize_batch() instead, which adds new
columns rather than overwriting the measured signal.
A modified cr_experiment.
cr_standardize_batch() for per-batch standardization,
cr_background_subtract(), cr_correct_batch().
Other normalization functions:
cr_background_subtract()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_normalize(exp, channel = "marker_1", method = "robust_zscore")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_normalize(exp, channel = "marker_1", method = "robust_zscore")
Returns hex colours from the palette every cr_plot_* function uses for
discrete groupings. The qualitative set is Okabe-Ito, the standard
colour-vision-safe qualitative palette; it deliberately contains no
red/green pair, so hue never encodes an opposition that a large minority of
readers cannot separate.
cr_palette( n = NULL, type = c("qualitative", "sequential", "diverging"), names = NULL, mode = c("colour", "grayscale") )cr_palette( n = NULL, type = c("qualitative", "sequential", "diverging"), names = NULL, mode = c("colour", "grayscale") )
n |
Number of colours to return. |
type |
One of |
names |
Optional character vector of names to attach to the returned
colours, for use as the |
mode |
|
Hue alone is not treated as a sufficient encoding: use cr_shapes() (or
cr_scale_group(), which wires both at once) so that every grouping is
carried by shape as well as colour.
A character vector of hex colour strings, named when names is
supplied or when the whole qualitative palette is returned.
cr_shapes(), cr_scale_group(), cr_theme()
Other plot design:
cr_scale_group(),
cr_shapes(),
cr_theme()
cr_palette() cr_palette(3) cr_palette(5, names = c("a", "b", "c", "d", "e")) cr_palette(7, type = "diverging")cr_palette() cr_palette(3) cr_palette(5, names = c("a", "b", "c", "d", "e")) cr_palette(7, type = "diverging")
Turns a vector of export paths into one row of design information per
file: the directory levels below root, the file-name markers, the
replicate index and the grammar tokens.
cr_parse_paths( paths, root = NULL, levels = NULL, grammar = NULL, markers = NULL, strict = TRUE, spec = NULL, call = rlang::caller_env() )cr_parse_paths( paths, root = NULL, levels = NULL, grammar = NULL, markers = NULL, strict = TRUE, spec = NULL, call = rlang::caller_env() )
paths |
Character vector of file paths. |
root |
Directory the paths sit under. Required when |
levels |
Directory level specification; see |
grammar |
A |
markers |
A |
strict |
Logical. Abort on an unparseable file name. When |
spec |
Optional |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
With strict = TRUE (the default) a file name that matches no
core_patterns entry of the grammar aborts the parse. That is the
intended behaviour: a name that parses to defaults instead of failing
loudly can move a treated unit into a control arm without anything in
the analysis noticing.
A tibble with one row per path: source_file, source_path,
one column per directory level, the marker flag columns, variant,
core, replicate, one column per grammar token, and the
parse_ok / parse_error outcome.
cr_path_spec(), cr_filename_grammar(),
cr_marker_rules(), cr_read_exports().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
root <- file.path(tempdir(), "cr_paths_demo") paths <- file.path( root, "Run1", "CompoundA", "Plate_1", c("CompoundA_vehicle_1.csv", "CompoundA_5min_10uM_treated_1.csv") ) cr_parse_paths( paths, root = root, levels = c("run", "compound", "plate"), grammar = cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM"), defaults = list(interval = "none", dose = "vehicle"), prefix_strip = "CompoundA" ) )root <- file.path(tempdir(), "cr_paths_demo") paths <- file.path( root, "Run1", "CompoundA", "Plate_1", c("CompoundA_vehicle_1.csv", "CompoundA_5min_10uM_treated_1.csv") ) cr_parse_paths( paths, root = root, levels = c("run", "compound", "plate"), grammar = cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM"), defaults = list(interval = "none", dose = "vehicle"), prefix_strip = "CompoundA" ) )
A cr_path_spec holds everything needed to recover design facts from
where a file sits and what it is called: the meaning of each directory
level, the file-name grammar, the marker rules and whether an
unparseable name is an error.
cr_path_spec(levels = NULL, grammar = NULL, markers = NULL, strict = TRUE) ## S3 method for class 'cr_path_spec' print(x, ...)cr_path_spec(levels = NULL, grammar = NULL, markers = NULL, strict = TRUE) ## S3 method for class 'cr_path_spec' print(x, ...)
levels |
Either an unnamed character vector naming the directory
levels below the root in order (use |
grammar |
A |
markers |
A |
strict |
Logical. Treat a file name that does not match the
grammar as an error. Default |
x |
A |
... |
Ignored. |
An object of class cr_path_spec (a list).
x, invisibly.
cr_parse_paths(), cr_read_exports().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
spec <- cr_path_spec( levels = c(run = 1L, compound = 2L, plate = -1L), grammar = cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM") ), markers = cr_marker_rules(merge_unit = "\\(split\\)") ) specspec <- cr_path_spec( levels = c(run = 1L, compound = 2L, plate = -1L), grammar = cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM") ), markers = cr_marker_rules(merge_unit = "\\(split\\)") ) spec
Comparison panel (box, fold change, p-value) for a single result
cr_plot_comparison(result, experiment)cr_plot_comparison(result, experiment)
result |
A |
experiment |
A |
A ggplot object.
Other visualisation:
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_test(exp, "marker_1", "CompoundA_high", "Untreated", test = "mann_whitney", level = "replicate") cr_plot_comparison(res, exp)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_test(exp, "marker_1", "CompoundA_high", "Untreated", test = "mann_whitney", level = "replicate") cr_plot_comparison(res, exp)
Dose-response plot
cr_plot_dose_response(fit)cr_plot_dose_response(fit)
fit |
A |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$dose <- ifelse(exp$design$treatment == "CompoundA_high", 500, exp$design$dose) fit <- cr_dose_response(exp, channel = "marker_1", model = "4pl") cr_plot_dose_response(fit)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$dose <- ifelse(exp$design$treatment == "CompoundA_high", 500, exp$design$dose) fit <- cr_dose_response(exp, channel = "marker_1", model = "4pl") cr_plot_dose_response(fit)
Convenience wrapper around cr_plot_forest() for the result objects
produced by cr_test() and cr_test_all(). Use cr_plot_forest()
directly for an effect-size table with its own labelling, facetting or
colouring.
cr_plot_effect_sizes(results, method = "cohens_d", ...)cr_plot_effect_sizes(results, method = "cohens_d", ...)
results |
A single |
method |
Effect-size method to plot (default |
... |
Further arguments passed to |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) all_res <- cr_test_all(exp, "marker_1", "Untreated", level = "replicate") cr_plot_effect_sizes(all_res)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) all_res <- cr_test_all(exp, "marker_1", "Untreated", level = "replicate") cr_plot_effect_sizes(all_res)
Plot estimates and confidence intervals
cr_plot_estimates( data, estimate = "estimate", lower = "conf_low", upper = "conf_high", label = "group", group = NULL, reference = 0, order_by = c("design", "estimate", "name"), colour_mode = c("colour", "grayscale"), style = NULL )cr_plot_estimates( data, estimate = "estimate", lower = "conf_low", upper = "conf_high", label = "group", group = NULL, reference = 0, order_by = c("design", "estimate", "name"), colour_mode = c("colour", "grayscale"), style = NULL )
data |
Data frame of finalized estimates. |
estimate, lower, upper, label
|
Column names. |
group |
Optional grouping column, redundantly encoded by colour and shape. |
reference |
Optional explicit reference value. |
order_by |
|
colour_mode |
Colour mode. |
style |
Optional |
Fold-change forest plot
cr_plot_foldchange(result)cr_plot_foldchange(result)
result |
A |
A ggplot object.
cr_plot_forest() for effect sizes with confidence intervals.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) res <- cr_test_all(exp, "marker_1", "Untreated", level = "replicate") cr_plot_foldchange(res)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) res <- cr_test_all(exp, "marker_1", "Untreated", level = "replicate") cr_plot_foldchange(res)
Draws one row per contrast: the point estimate with its confidence interval, a reference line at the null, and the rows ordered by the estimate rather than alphabetically, so the ordering is computed from the data and cannot go stale.
cr_plot_forest( effects, estimate = "estimate", ci_low = "ci_low", ci_high = "ci_high", label = NULL, facet_by = NULL, colour_by = NULL, method = "cohens_d", reference = 0, order_by_estimate = TRUE, descending = FALSE, title = NULL, subtitle = NULL, x_lab = NULL, y_lab = NA )cr_plot_forest( effects, estimate = "estimate", ci_low = "ci_low", ci_high = "ci_high", label = NULL, facet_by = NULL, colour_by = NULL, method = "cohens_d", reference = 0, order_by_estimate = TRUE, descending = FALSE, title = NULL, subtitle = NULL, x_lab = NULL, y_lab = NA )
effects |
A data frame of effect sizes (for example the output of an
effect-size grid), a |
estimate, ci_low, ci_high
|
Names of the estimate and interval columns. |
label |
Name of the column identifying each row. |
facet_by |
One or two column names to facet on, or |
colour_by |
Column mapped to colour, fill and shape, or |
method |
Effect-size method to keep when |
reference |
Position of the null reference line (default |
order_by_estimate |
Order rows by the estimate (default |
descending |
Order largest estimate at the top (default |
title, subtitle, x_lab, y_lab
|
Plot labels. |
The default subtitle states which intervals exclude the reference. It is computed from the interval bounds for the same reason: the equivalent sentence written by hand in the source pipeline stopped matching the data the first time the data changed.
A ggplot object.
cr_plot_screen(), cr_plot_effect_sizes()
Other screen figures:
cr_plot_qc_gate(),
cr_plot_sample_size(),
cr_plot_screen(),
cr_plot_specificity(),
cr_save_plot()
effects <- data.frame( group = c("CompoundA", "CompoundB", "CompoundC"), estimate = c(-1.2, -0.35, 0.1), ci_low = c(-1.9, -0.95, -0.4), ci_high = c(-0.5, 0.25, 0.6) ) cr_plot_forest(effects)effects <- data.frame( group = c("CompoundA", "CompoundB", "CompoundC"), estimate = c(-1.2, -0.35, 0.1), ci_low = c(-1.9, -0.95, -0.4), ci_high = c(-0.5, 0.25, 0.6) ) cr_plot_forest(effects)
Heatmap of channel medians across groups
cr_plot_heatmap( experiment, channels, group_by = "treatment", scale = c("none", "row", "column") )cr_plot_heatmap( experiment, channels, group_by = "treatment", scale = c("none", "row", "column") )
experiment |
A |
channels |
Character vector of channel names. |
group_by |
Design column defining rows. Default
|
scale |
One of |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_heatmap(exp, c("DAPI", "marker_1", "marker_2"))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_heatmap(exp, c("DAPI", "marker_1", "marker_2"))
Histogram of channel intensity
cr_plot_histogram( experiment, channel, group_by = "treatment", facet_by = NULL, log_x = TRUE )cr_plot_histogram( experiment, channel, group_by = "treatment", facet_by = NULL, log_x = TRUE )
experiment |
A |
channel |
Channel name. |
group_by |
Design column used for colour. |
facet_by |
Design column used for facetting (or |
log_x |
Log-transform the x-axis. |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_histogram(exp, "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_histogram(exp, "marker_1")
Intensity distributions by group
cr_plot_intensity( experiment, channel, group_by = "treatment", geom = c("violin", "boxplot", "both"), log_y = TRUE )cr_plot_intensity( experiment, channel, group_by = "treatment", geom = c("violin", "boxplot", "both"), log_y = TRUE )
experiment |
A |
channel |
Channel name. |
group_by |
Design column to colour / facet on. Default
|
geom |
|
log_y |
Log-transform the y-axis (default |
A ggplot object.
cr_plot_screen() to overlay the unit of replication.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_intensity(exp, channel = "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_intensity(exp, channel = "marker_1")
Draws a plate-layout heatmap for a 96 or 384-well plate, showing a summary metric (median intensity, cell count, etc.) per well.
cr_plot_plate( experiment, channel, metric = c("median", "mean", "cv", "n_cells") )cr_plot_plate( experiment, channel, metric = c("median", "mean", "cv", "n_cells") )
experiment |
A |
channel |
Channel name for the metric computation. |
metric |
One of |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_plate(exp, channel = "marker_1", metric = "median")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_plate(exp, channel = "marker_1", metric = "median")
Combines cell count per well, area distributions and intensity distributions into a single multi-panel figure.
cr_plot_qc(experiment, channel = NULL)cr_plot_qc(experiment, channel = NULL)
experiment |
A |
channel |
Channel name used for the intensity panel. |
A ggplot object (facetted).
cr_plot_qc_gate() for the gate against each unit's own control.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_qc(exp, channel = "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_qc(exp, channel = "marker_1")
Plots each unit's statistic against the statistic of the control it is
gated on, with the line of equality. Points above the line pass a
"greater" gate; points below it fail and are excluded.
cr_plot_qc_gate( gate, statistic = NULL, reference = NULL, fails_median = NULL, fails_mean = NULL, direction = c("greater", "less"), log_scale = TRUE, label = NULL, title = NULL, subtitle = NULL, x_lab = NULL, y_lab = NULL )cr_plot_qc_gate( gate, statistic = NULL, reference = NULL, fails_median = NULL, fails_mean = NULL, direction = c("greater", "less"), log_scale = TRUE, label = NULL, title = NULL, subtitle = NULL, x_lab = NULL, y_lab = NULL )
gate |
A |
statistic |
Name of the unit statistic column. |
reference |
Name of the control statistic column. |
fails_median, fails_mean
|
Names of the logical verdict columns under
the two centres. |
direction |
|
log_scale |
Draw both axes on a log scale when every value is
positive (default |
label |
Optional column whose values annotate the failing units. |
title, subtitle, x_lab, y_lab
|
Plot labels. |
Where the input carries a verdict under both centres, median and mean, the units whose verdict depends on which centre was used are drawn as their own class. That distinction matters because a right-skewed signal has a mean above its median, so gating a raw median against a control mean is silently stricter than the stated rule, and a gate that can only drop low units manufactures apparent effects when it is too strict.
A ggplot object.
cr_plot_qc() for the distribution dashboard.
Other screen figures:
cr_plot_forest(),
cr_plot_sample_size(),
cr_plot_screen(),
cr_plot_specificity(),
cr_save_plot()
set.seed(1) units <- data.frame( well_id = paste0("W", 1:24), unit_median = c(rlnorm(20, 5, 0.3), rlnorm(4, 3.9, 0.2)), ctrl_median = rlnorm(24, 4.2, 0.1) ) cr_plot_qc_gate(units, label = "well_id")set.seed(1) units <- data.frame( well_id = paste0("W", 1:24), unit_median = c(rlnorm(20, 5, 0.3), rlnorm(4, 3.9, 0.2)), ctrl_median = rlnorm(24, 4.2, 0.1) ) cr_plot_qc_gate(units, label = "well_id")
Compact text-first QC status plot
cr_plot_qc_summary(qc, mode = c("colour", "grayscale"))cr_plot_qc_summary(qc, mode = c("colour", "grayscale"))
qc |
A report QC table. |
mode |
Colour mode. |
Plot a value relative to caller-supplied boundaries
cr_plot_result_position( value, thresholds, labels = NULL, xlim = NULL, unit = NULL, classification = NULL, show_value = TRUE, mode = c("colour", "grayscale"), style = NULL )cr_plot_result_position( value, thresholds, labels = NULL, xlim = NULL, unit = NULL, classification = NULL, show_value = TRUE, mode = c("colour", "grayscale"), style = NULL )
value |
Single finite numeric value. |
thresholds |
One or more sorted finite boundaries. |
labels |
Optional labels for the resulting intervals; must have one more item than thresholds. |
xlim |
Optional two-value display range. |
unit, classification
|
Optional user-supplied marker labels. |
show_value |
Include the numeric value below the marker. |
mode |
Colour or grayscale rendering. |
style |
Optional |
ROC curve plot
cr_plot_roc(result)cr_plot_roc(result)
result |
A single |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_scatter(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") cr_plot_roc(res)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") cr_plot_roc(res)
Draws, per group, the number of units a confirmatory study would need when powered on the observed effect beside the number needed when powered on the confidence bound nearer the null.
cr_plot_sample_size( sizes, label = NULL, observed = "n_observed", conservative = "n_conservative", available = NULL, colour_by = NULL, log_y = TRUE, title = NULL, subtitle = NULL, caption = NULL, x_lab = NA, y_lab = NULL )cr_plot_sample_size( sizes, label = NULL, observed = "n_observed", conservative = "n_conservative", available = NULL, colour_by = NULL, log_y = TRUE, title = NULL, subtitle = NULL, caption = NULL, x_lab = NA, y_lab = NULL )
sizes |
A data frame with one row per group, carrying the two sample-size columns. |
label |
Name of the grouping column. |
observed, conservative
|
Names of the two sample-size columns. |
available |
Optional name of a column giving the units already available per group; folded into the axis labels in brackets. |
colour_by |
Column mapped to fill, or |
log_y |
Draw the count axis on a log scale (default |
title, subtitle, caption, x_lab, y_lab
|
Plot labels. |
The gap between the two bars is the point of the figure. Powering on the observed effect of a screen's top hit is circular - that group is the largest only because it was selected for being largest - so the conservative bar is the one a confirmatory design should be built on, and a conservative figure exists only where the interval excludes the null.
Value labels are drawn in ink above the bars, never inside them, and the number of units already available is folded into the axis label rather than plotted as a marker that collides with the labels on short bars.
A ggplot object.
Other screen figures:
cr_plot_forest(),
cr_plot_qc_gate(),
cr_plot_screen(),
cr_plot_specificity(),
cr_save_plot()
sizes <- data.frame( group = c("CompoundA", "CompoundB", "CompoundC"), n_observed = c(12, 84, 640), n_conservative = c(46, NA, NA), n_available = c(6, 6, 6) ) cr_plot_sample_size(sizes, available = "n_available")sizes <- data.frame( group = c("CompoundA", "CompoundB", "CompoundC"), n_observed = c(12, 84, 640), n_conservative = c(46, NA, NA), n_available = c(6, 6, 6) ) cr_plot_sample_size(sizes, available = "n_available")
Biaxial scatter plot of two channels
cr_plot_scatter( experiment, channel_x, channel_y, color_by = "treatment", log_x = TRUE, log_y = TRUE )cr_plot_scatter( experiment, channel_x, channel_y, color_by = "treatment", log_x = TRUE, log_y = TRUE )
experiment |
A |
channel_x |
X-axis channel. |
channel_y |
Y-axis channel. |
color_by |
Design column used for colour. Default
|
log_x, log_y
|
Log-transform the respective axis. |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_spatial(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_scatter(exp, "DAPI", "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_scatter(exp, "DAPI", "marker_1")
Draws width-scaled violins of the cell-level value for each group, with the per-unit means overplotted as jittered points. Cells are the observations; the unit (well, slide or merged acquisition) is the unit of replication, and drawing both in one panel is what keeps a reader from reading cell counts as replicate counts.
cr_plot_screen( cells, value = "log2_fc", group_var = "treatment", units = NULL, unit_value = NULL, facet_by = NULL, colour_by = NULL, reference = 0, seed = NULL, title = NULL, subtitle = NULL, x_lab = NA, y_lab = NULL )cr_plot_screen( cells, value = "log2_fc", group_var = "treatment", units = NULL, unit_value = NULL, facet_by = NULL, colour_by = NULL, reference = 0, seed = NULL, title = NULL, subtitle = NULL, x_lab = NA, y_lab = NULL )
cells |
Cell-level data: a data frame, or a |
value |
Name of the cell-level value column, typically a standardised
value such as a log fold change (default |
group_var |
Name of the column defining the x-axis groups (default
|
units |
Unit-level data. Either a data frame of one row per unit, or
the name of a column in |
unit_value |
Name of the unit-level value column. Defaults to |
facet_by |
One or two column names to facet on, or |
colour_by |
Column mapped to fill and shape. |
reference |
Horizontal reference line, or |
seed |
Integer seed for the point jitter, so the figure reproduces. |
title, subtitle, x_lab, y_lab
|
Plot labels. |
The point layer is drawn with a fixed jitter seed so the figure is reproducible, and the subtitle states which layer is the unit of replication rather than leaving it to the caption.
A ggplot object.
cr_plot_forest(), cr_theme(), cr_scale_group()
Other screen figures:
cr_plot_forest(),
cr_plot_qc_gate(),
cr_plot_sample_size(),
cr_plot_specificity(),
cr_save_plot()
set.seed(1) cells <- data.frame( treatment = rep(c("Vehicle", "CompoundA", "CompoundB"), each = 120), well_id = rep(paste0("W", 1:18), each = 20), log2_fc = c(rnorm(120, 0, 0.5), rnorm(120, -0.8, 0.5), rnorm(120, -0.2, 0.5)) ) cr_plot_screen(cells, group_var = "treatment", units = "well_id", seed = 1)set.seed(1) cells <- data.frame( treatment = rep(c("Vehicle", "CompoundA", "CompoundB"), each = 120), well_id = rep(paste0("W", 1:18), each = 20), log2_fc = c(rnorm(120, 0, 0.5), rnorm(120, -0.8, 0.5), rnorm(120, -0.2, 0.5)) ) cr_plot_screen(cells, group_var = "treatment", units = "well_id", seed = 1)
Spatial scatter of cells in a well
cr_plot_spatial(experiment, channel, well = NULL)cr_plot_spatial(experiment, channel, well = NULL)
experiment |
A |
channel |
Channel used for colouring points. |
well |
Spatial unit (well or slide ID) to plot. If |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_timeline()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_spatial(exp, "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_plot_spatial(exp, "marker_1")
Draws the arms of the specificity control side by side: the assay with the detection reagent present against the same exposure with the reagent omitted. No amount of batch standardisation can show that a readout is reagent-dependent rather than background autofluorescence, which is what makes this the strongest validation a method-establishment result has.
cr_plot_specificity( spec, arm = "arm", value = NULL, arm_levels = NULL, colour_by = NULL, log_y = TRUE, ratio_arms = NULL, title = NULL, subtitle = NULL, x_lab = NA, y_lab = NULL )cr_plot_specificity( spec, arm = "arm", value = NULL, arm_levels = NULL, colour_by = NULL, log_y = TRUE, ratio_arms = NULL, title = NULL, subtitle = NULL, x_lab = NA, y_lab = NULL )
spec |
Cell-level or per-arm data: a data frame, or a list carrying
one in a |
arm |
Name of the column identifying the arm (default |
value |
Name of the value column. |
arm_levels |
Optional character vector fixing the order of the arms. |
colour_by |
Column mapped to fill, or |
log_y |
Draw the signal axis on a log scale (default |
ratio_arms |
Optional length-2 character vector naming the arms whose
median ratio is reported in the subtitle, as
|
title, subtitle, x_lab, y_lab
|
Plot labels. |
Accepts either cell-level data (one row per cell, drawn as violins with the arm medians annotated) or an already-summarised table (one row per arm, drawn as columns).
A ggplot object.
Other screen figures:
cr_plot_forest(),
cr_plot_qc_gate(),
cr_plot_sample_size(),
cr_plot_screen(),
cr_save_plot()
set.seed(1) spec <- data.frame( arm = rep(c("reagent omitted\n+ vehicle", "reagent omitted\n+ exposed", "reagent present\n+ vehicle", "reagent present\n+ exposed"), each = 60), value = c(rlnorm(60, 3, 0.3), rlnorm(60, 3.05, 0.3), rlnorm(60, 4.5, 0.3), rlnorm(60, 6.2, 0.3)) ) cr_plot_specificity(spec)set.seed(1) spec <- data.frame( arm = rep(c("reagent omitted\n+ vehicle", "reagent omitted\n+ exposed", "reagent present\n+ vehicle", "reagent present\n+ exposed"), each = 60), value = c(rlnorm(60, 3, 0.3), rlnorm(60, 3.05, 0.3), rlnorm(60, 4.5, 0.3), rlnorm(60, 6.2, 0.3)) ) cr_plot_specificity(spec)
Construct a reusable plot style
cr_plot_style( mode = c("colour", "grayscale"), variant = c("publication", "report"), base_size = 9, base_family = "sans", palette = NULL, shapes = NULL, linetypes = NULL, legend_position = "bottom" )cr_plot_style( mode = c("colour", "grayscale"), variant = c("publication", "report"), base_size = 9, base_family = "sans", palette = NULL, shapes = NULL, linetypes = NULL, legend_position = "bottom" )
mode |
|
variant |
|
base_size |
Font size in points; values below 8 are rejected. |
base_family |
System-safe font family. |
palette |
Optional named qualitative palette. |
shapes |
Optional named shape mapping. |
linetypes |
Optional named line-type mapping. |
legend_position |
Legend position. |
Time-course line plot
cr_plot_timeline(experiment, timepoint_var, channel, group_by = "treatment")cr_plot_timeline(experiment, timepoint_var, channel, group_by = "treatment")
experiment |
A |
timepoint_var |
Name of the time variable column. |
channel |
Channel to plot. |
group_by |
Grouping variable (colour). |
A ggplot object.
Other visualisation:
cr_plot_comparison(),
cr_plot_dose_response(),
cr_plot_effect_sizes(),
cr_plot_foldchange(),
cr_plot_heatmap(),
cr_plot_histogram(),
cr_plot_intensity(),
cr_plot_plate(),
cr_plot_qc(),
cr_plot_roc(),
cr_plot_scatter(),
cr_plot_spatial()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$timepoint <- rep(c(0, 6, 12, 24), length.out = nrow(exp$design)) cr_plot_timeline(exp, "timepoint", "marker_1")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp$design$timepoint <- rep(c(0, 6, 12, 24), length.out = nrow(exp$design)) cr_plot_timeline(exp, "timepoint", "marker_1")
Solves the two-sample design for the number of units per arm needed
to reach power at sig_level, once for the observed effect and
once for the confidence bound nearer the null.
cr_power( effect_size = NULL, ci_low = NULL, ci_high = NULL, power = 0.8, sig_level = 0.05, type = c("two.sample", "one.sample", "paired"), alternative = c("two.sided", "one.sided") )cr_power( effect_size = NULL, ci_low = NULL, ci_high = NULL, power = 0.8, sig_level = 0.05, type = c("two.sample", "one.sample", "paired"), alternative = c("two.sided", "one.sided") )
effect_size |
Numeric vector of observed standardized effects
(Cohen's d). May be |
ci_low, ci_high
|
Numeric vectors of interval bounds for the same effects. Optional. |
power |
Target power (default 0.8). |
sig_level |
Significance level (default 0.05). |
type |
Design: |
alternative |
|
The conservative figure is the reportable one. Powering a screen's
leading compound on its own point estimate is circular: that
compound is the largest of the set only by virtue of having been
selected for being largest, so a sample size derived from it can
hardly fail to be met. n_conservative is NA whenever the
interval spans the null, because an interval compatible with no
effect cannot be sized.
The solver is stats::power.t.test(), so the effect size is read as
a standardized mean difference and n is per group.
A tibble with one row per effect: d_observed,
n_observed, d_conservative, n_conservative, basis,
power and sig_level. Sample sizes are units per arm, rounded
up.
cr_power_grid(), cr_conservative_effect(),
cr_power_analysis().
Other power:
cr_conservative_effect(),
cr_power_analysis(),
cr_power_grid()
cr_power(effect_size = c(-1.31, -0.28), ci_low = c(-2.35, -1.20), ci_high = c(-0.27, 0.64)) # without an interval only the (circular) observed sizing is possible cr_power(effect_size = 0.8)cr_power(effect_size = c(-1.31, -0.28), ci_low = c(-2.35, -1.20), ci_high = c(-0.27, 0.64)) # without an interval only the (circular) observed sizing is possible cr_power(effect_size = 0.8)
A Monte-Carlo approximation of the power of a two-sample comparison
of replicate means formed from independent, unit-variance normal cells.
There is no between-unit random effect or intraclass correlation. The
result is an idealized scenario, not a validated estimate of power for a
clustered biological assay or a formal upper bound on laboratory power.
For a follow-up design use cr_power() with an effect on the independent
experimental-unit scale, or a separately specified correlated-data model.
cr_power_analysis( effect_size, n_replicates, n_cells_per_rep, alpha = 0.05, test = "t_test", n_sim = 500, seed = NULL )cr_power_analysis( effect_size, n_replicates, n_cells_per_rep, alpha = 0.05, test = "t_test", n_sim = 500, seed = NULL )
effect_size |
Cohen's d at the cell level. |
n_replicates |
Number of replicate units per group. |
n_cells_per_rep |
Cells per replicate unit. |
alpha |
Type I error rate. |
test |
Only |
n_sim |
Number of simulations (default 500). |
seed |
Optional integer seed. The caller's random number stream is restored on exit. |
A tibble with the inputs and the simulated power.
Other power:
cr_conservative_effect(),
cr_power(),
cr_power_grid()
cr_power_analysis(effect_size = 0.8, n_replicates = 4, n_cells_per_rep = 100, n_sim = 100, seed = 1)cr_power_analysis(effect_size = 0.8, n_replicates = 4, n_cells_per_rep = 100, n_sim = 100, seed = 1)
Applies cr_power() to every row of an effect grid produced by
cr_effect_grid() and binds the sizing columns onto it, so the
observed and the conservative sample size travel with the contrast
they belong to.
cr_power_grid( effects, estimate = "cohens_d", ci_low = NULL, ci_high = NULL, available = NULL, power = 0.8, sig_level = 0.05, type = c("two.sample", "one.sample", "paired"), alternative = c("two.sided", "one.sided") )cr_power_grid( effects, estimate = "cohens_d", ci_low = NULL, ci_high = NULL, available = NULL, power = 0.8, sig_level = 0.05, type = c("two.sample", "one.sample", "paired"), alternative = c("two.sided", "one.sided") )
effects |
An effect grid from |
estimate |
Name of the effect size column. The interval columns
default to |
ci_low, ci_high
|
Optional explicit names of the interval columns. |
available |
Units already available per arm, used to flag which
contrasts are already large enough. Either a column name in
|
power |
Target power (default 0.8). |
sig_level |
Significance level (default 0.05). |
type |
Design passed to |
alternative |
Alternative passed to |
effects with the columns d_conservative, n_observed,
n_conservative and basis appended, plus n_available and
sufficient when availability is known.
Sufficiency requires a finite conservative target; no observed-effect
fallback is used when the interval spans zero or has no usable bound.
Numeric availability inputs must be scalar or have one value per effect.
Other power:
cr_conservative_effect(),
cr_power(),
cr_power_analysis()
set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 12), arm = rep(rep(c("reference", "interval_short"), each = 6), 2), log2_fc = c(stats::rnorm(6, 0, 0.3), stats::rnorm(6, -1.4, 0.3), stats::rnorm(6, 0, 0.3), stats::rnorm(6, -0.1, 0.3)) ) eff <- cr_effect_grid(units, "log2_fc", "arm", "reference", by = "compound") sizes <- cr_power_grid(eff) sizes[, c("compound", "n_observed", "n_conservative", "basis")]set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 12), arm = rep(rep(c("reference", "interval_short"), each = 6), 2), log2_fc = c(stats::rnorm(6, 0, 0.3), stats::rnorm(6, -1.4, 0.3), stats::rnorm(6, 0, 0.3), stats::rnorm(6, -0.1, 0.3)) ) eff <- cr_effect_grid(units, "log2_fc", "arm", "reference", by = "compound") sizes <- cr_power_grid(eff) sizes[, c("compound", "n_observed", "n_conservative", "basis")]
Print a laboratory report specification
cr_print_report_spec(x, ...)cr_print_report_spec(x, ...)
x |
A |
... |
Unused. |
x, invisibly.
Flags cells whose size or DNA content is far above the population median, which in microscopy typically indicates segmented doublets. The cells are removed and recorded in the QC log.
cr_qc_doublets( experiment, channel = NULL, threshold_method = c("area", "channel"), k = 2.5 )cr_qc_doublets( experiment, channel = NULL, threshold_method = c("area", "channel"), k = 2.5 )
experiment |
A |
channel |
Name of the channel column used when
|
threshold_method |
|
k |
Multiplicative threshold: cells whose value exceeds
|
A modified cr_experiment.
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_qc_doublets(exp, threshold_method = "area") cr_qc_doublets(exp, channel = "DAPI", threshold_method = "channel")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_qc_doublets(exp, threshold_method = "area") cr_qc_doublets(exp, channel = "DAPI", threshold_method = "channel")
Removes debris and artifacts by thresholding morphological
measurements. Any parameter left at NA is not applied.
cr_qc_filter( experiment, min_area = NA, max_area = NA, min_circularity = NA, max_circularity = NA )cr_qc_filter( experiment, min_area = NA, max_area = NA, min_circularity = NA, max_circularity = NA )
experiment |
A |
min_area, max_area
|
Numeric area thresholds. Cells outside the inclusive interval are removed. |
min_circularity, max_circularity
|
Circularity thresholds (range 0-1). |
A modified cr_experiment with fewer cells and a QC log
entry.
cr_exclude_small() for a data-derived (quantile) area
threshold, and cr_qc_summary() for the log.
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 50) exp2 <- cr_qc_filter(exp, min_area = 100, max_area = 2000) cr_n_cells(exp2)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 50) exp2 <- cr_qc_filter(exp, min_area = 100, max_area = 2000) cr_n_cells(exp2)
A biological rather than a statistical gate: a treated unit must carry more target signal than the vehicle control acquired in its own batch. Units that do not are candidates for exclusion. The comparison is made against the control of the unit's own batch, so a plate that ran hot or cold as a whole cannot pass or fail units in unrelated batches.
cr_qc_gate( experiment, channel, control_level, batch_vars = NULL, unit = NULL, control_var = "treatment", statistic = c("median", "mean"), reference = c("median", "mean"), direction = c("greater", "less"), gate_controls = FALSE, min_cells = 1L )cr_qc_gate( experiment, channel, control_level, batch_vars = NULL, unit = NULL, control_var = "treatment", statistic = c("median", "mean"), reference = c("median", "mean"), direction = c("greater", "less"), gate_controls = FALSE, min_cells = 1L )
experiment |
A |
channel |
Name of the raw signal column in |
control_level |
Value of |
batch_vars |
Character vector of columns (from |
unit |
Column identifying the analysis unit. Defaults to the experiment's unit column, falling back to its spatial unit. |
control_var |
Column holding the treatment labels. Default
|
statistic |
Centre of the unit used for the comparison:
|
reference |
Centre of the control used as the threshold:
|
direction |
|
gate_controls |
Should control units be gated against
themselves? Default |
min_cells |
Units with fewer than |
Two properties of this gate decide whether it is honest, and both are made explicit here.
Like for like. Target signal is usually right-skewed, so a
control's mean sits above its median. Comparing a unit's median
against the control's mean is therefore silently stricter than
the rule it claims to apply. Because the gate can only ever drop
low units, an over-strict gate manufactures apparent treatment
effects. Both verdicts are computed for every unit —
fails_vs_median and fails_vs_mean — and the units whose verdict
depends on that choice are returned in $disputed. The default
(statistic = "median", reference = "median") is like for like.
Leverage. Excluding a unit changes the estimate it fed into.
Quantify that with cr_qc_gate_impact() before calling
cr_apply_gate(), while both states are still in hand.
Gate the analysis unit, not the acquisition file: a unit assembled from two files would otherwise be gated twice.
An object of class cr_qc_gate, a list with:
unitsOne row per analysis unit: cell count, both raw
centres, the control statistics of its batch,
pct_of_control, fails_vs_median, fails_vs_mean,
disputed, verdict and reason.
disputedThe units whose verdict depends on which control centre is used.
excludedIdentifiers of the units that fail under the
chosen statistic/reference combination.
paramsThe arguments the gate was built with.
cr_qc_gate_impact(), cr_apply_gate(),
cr_qc_report().
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) gate <- cr_qc_gate(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "replicate" ) gate head(gate$units[, c("well", "n_cells", "pct_of_control", "verdict")]) gate$excludedexp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) gate <- cr_qc_gate(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "replicate" ) gate head(gate$units[, c("well", "n_cells", "pct_of_control", "verdict")]) gate$excluded
Re-estimates every contrast affected by a gate exclusion twice — with the failing unit retained and with it removed — so that "one excluded unit changes the verdict" carries a number rather than a recollection. This matters most when an excluded unit sits in the reference arm, where retaining it makes the untreated condition look as though it were already responding.
cr_qc_gate_impact( experiment, gate, value = "log2_fc", group_var, reference_level, comparison_levels = NULL, by = NULL, unit = NULL, min_units = 3, affected_only = TRUE )cr_qc_gate_impact( experiment, gate, value = "log2_fc", group_var, reference_level, comparison_levels = NULL, by = NULL, unit = NULL, min_units = 3, affected_only = TRUE )
experiment |
A |
gate |
A |
value |
Per-cell numeric column averaged to the unit level
before the contrast is taken. Default |
group_var |
Column holding the arm labels of the contrast. |
reference_level |
Level of |
comparison_levels |
Levels contrasted against the reference.
|
by |
Optional character vector of columns to compute the contrasts within (for example the compound). |
unit |
Analysis unit column. Defaults to the gate's unit. |
min_units |
Minimum number of units per arm; contrasts below
it return |
affected_only |
Restrict the output to |
Call this before cr_apply_gate(): the "retained" state needs
the failing units to still be present in experiment.
A tibble with one row per by group and contrast:
unit counts in both states, estimate_with_excluded,
estimate_without_excluded, their magnitudes, and whether the
magnitude or the sign changes when the unit is dropped. The
estimate is a pooled, uncorrected standardised mean difference.
cr_qc_gate(), cr_apply_gate().
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) exp$cells$signal <- log2(exp$cells$marker_1) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") cr_qc_gate_impact(exp, gate, value = "signal", group_var = "treatment", reference_level = "Untreated" )exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) exp$cells$signal <- log2(exp$cells$marker_1) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") cr_qc_gate_impact(exp, gate, value = "signal", group_var = "treatment", reference_level = "Untreated" )
Removes cells whose intensity on a given channel is outside the
interval [min_intensity, max_intensity].
cr_qc_intensity(experiment, channel, min_intensity = NA, max_intensity = NA)cr_qc_intensity(experiment, channel, min_intensity = NA, max_intensity = NA)
experiment |
A |
channel |
Name of the channel column in |
min_intensity, max_intensity
|
Lower and upper bounds. Leave
|
A modified cr_experiment.
cr_qc_gate() for a gate against each unit's own
in-batch control rather than an absolute bound.
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_qc_intensity(exp, channel = "DAPI", min_intensity = 50)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_qc_intensity(exp, channel = "DAPI", min_intensity = 50)
Removes entire wells/slides and/or specific cell IDs (for example contaminated wells or cells with focus issues).
cr_qc_manual(experiment, well = NULL, cell_ids = NULL)cr_qc_manual(experiment, well = NULL, cell_ids = NULL)
experiment |
A |
well |
Character vector of well / slide identifiers to
remove. Default |
cell_ids |
Character vector of cell IDs to remove. |
A modified cr_experiment.
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_report(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) cr_qc_manual(exp, well = c("A01", "H12"))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) cr_qc_manual(exp, well = c("A01", "H12"))
Returns one row per analysis unit so that the gate can be audited: which units were seen, what their signal was relative to their own control, which were excluded and why, and how many cells each still contributes. Units the gate removed are kept in the report — a gate whose casualties disappear from the record cannot be reviewed.
cr_qc_report(experiment, gate = NULL, unit = NULL, vars = NULL)cr_qc_report(experiment, gate = NULL, unit = NULL, vars = NULL)
experiment |
A |
gate |
Optional |
unit |
Analysis unit column. Defaults to the gate's unit, or the experiment's unit / spatial unit. |
vars |
Optional character vector of extra design columns to
carry into the report. |
A tibble with one row per unit: the unit identifier, the
requested design columns, n_cells_gated (cells the gate saw),
n_cells (cells present now), retained, and — when a gate is
available — the control statistics, pct_of_control,
fails_vs_median, fails_vs_mean, disputed, verdict and
reason. Failing units are listed first.
cr_qc_gate(), cr_apply_gate(), cr_qc_summary().
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_summary(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") exp2 <- cr_apply_gate(exp, gate) rep <- cr_qc_report(exp2) head(rep[, c("well", "n_cells", "verdict", "reason")]) # without a gate the report is still a per-unit inventory head(cr_qc_report(exp))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 40) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") exp2 <- cr_apply_gate(exp, gate) rep <- cr_qc_report(exp2) head(rep[, c("well", "n_cells", "verdict", "reason")]) # without a gate the report is still a per-unit inventory head(cr_qc_report(exp))
Summarise QC steps applied to an experiment
cr_qc_summary(experiment)cr_qc_summary(experiment)
experiment |
A |
A tibble with one row per QC step: step, parameters,
cells_before, cells_after, cells_removed,
percent_removed and timestamp.
cr_qc_report() for a per-unit rather than per-step view.
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
print.cr_qc_gate()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp <- cr_qc_filter(exp, min_area = 50) cr_qc_summary(exp)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) exp <- cr_qc_filter(exp, min_area = 50) cr_qc_summary(exp)
Imports a CellProfiler CSV export and renames the columns to the
cellreportR convention (well, x, y, area, circularity,
one column per marker channel).
cr_read_cellprofiler(path)cr_read_cellprofiler(path)
path |
Path to CellProfiler CSV. |
A tibble with standardised column names.
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
f <- tempfile(fileext = ".csv") utils::write.csv( data.frame( Metadata_Well = c("A01", "A01"), Location_Center_X = c(10, 20), Location_Center_Y = c(15, 25), AreaShape_Area = c(120, 130), Intensity_MeanIntensity_marker_1 = c(0.4, 0.6) ), f, row.names = FALSE ) cr_read_cellprofiler(f)f <- tempfile(fileext = ".csv") utils::write.csv( data.frame( Metadata_Well = c("A01", "A01"), Location_Center_X = c(10, 20), Location_Center_Y = c(15, 25), AreaShape_Area = c(120, 130), Intensity_MeanIntensity_marker_1 = c(0.4, 0.6) ), f, row.names = FALSE ) cr_read_cellprofiler(f)
Reads per-cell measurements from CSV, TSV, Excel, RDS or FCS formats.
The format is auto-detected from the file extension unless
format is given explicitly.
cr_read_cells(path, format = NULL)cr_read_cells(path, format = NULL)
path |
Path to file. |
format |
Optional format string: one of |
A tibble of cell measurements.
cr_read_export() and cr_read_exports() for exports that
carry design information in their path and file name.
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
f <- tempfile(fileext = ".csv") utils::write.csv( data.frame(cell_id = "c1", well = "A01", target_signal = 12), f, row.names = FALSE ) cr_read_cells(f)f <- tempfile(fileext = ".csv") utils::write.csv( data.frame(cell_id = "c1", well = "A01", target_signal = 12), f, row.names = FALSE ) cr_read_cells(f)
Read experimental design from CSV or Excel
cr_read_design(path)cr_read_design(path)
path |
Path to file. |
A tibble of design information.
cr_design() to turn the table into a validated design
object.
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
f <- tempfile(fileext = ".csv") utils::write.csv( data.frame(well = c("A01", "A02"), treatment = c("Vehicle", "CompoundA")), f, row.names = FALSE ) cr_read_design(f)f <- tempfile(fileext = ".csv") utils::write.csv( data.frame(well = c("A01", "A02"), treatment = c("Vehicle", "CompoundA")), f, row.names = FALSE ) cr_read_design(f)
Reads a single export file (.csv, .tsv, .txt, .xls or
.xlsx), applies an optional column contract and prepends the file's
provenance.
cr_read_export( path, column_map = NULL, drop_empty_rows = TRUE, col_types = NULL, sheet = 1L, call = rlang::caller_env() )cr_read_export( path, column_map = NULL, drop_empty_rows = TRUE, col_types = NULL, sheet = 1L, call = rlang::caller_env() )
path |
Path to the export file. |
column_map |
Optional |
drop_empty_rows |
Logical. Drop rows that are |
col_types |
Optional column-type specification passed to the
underlying reader (a |
sheet |
Sheet name or index for Excel exports. Default |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
Provenance is not optional in this reader. One export is one
acquisition of one spatial unit, and export base names repeat across
plates, so the path — not the file name — identifies the
acquisition. Both are carried on every row as source_file and
source_path, and both survive into the analysis unit assignment
performed by cr_assign_units().
Many instruments terminate an export with a single all-blank row.
With drop_empty_rows = TRUE (the default) such rows are removed
rather than carried into the analysis as an all-NA cell.
A tibble of cells with source_file and source_path as the
first two columns.
cr_read_exports() for a whole directory tree,
cr_column_map().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
d <- file.path(tempdir(), "cr_export_demo") dir.create(d, showWarnings = FALSE) raw <- data.frame( "Event Label" = 1:3, "Signal - Mean Intensity" = c(120, 140, 95), check.names = FALSE ) raw[4, ] <- NA # trailing blank row, as many instruments write f <- file.path(d, "CompoundA_5min_10uM_treated_1.csv") utils::write.csv(raw, f, row.names = FALSE) map <- cr_column_map( exact = c("Event Label" = "cell_id", "Signal - Mean Intensity" = "target_signal") ) cr_read_export(f, column_map = map)d <- file.path(tempdir(), "cr_export_demo") dir.create(d, showWarnings = FALSE) raw <- data.frame( "Event Label" = 1:3, "Signal - Mean Intensity" = c(120, 140, 95), check.names = FALSE ) raw[4, ] <- NA # trailing blank row, as many instruments write f <- file.path(d, "CompoundA_5min_10uM_treated_1.csv") utils::write.csv(raw, f, row.names = FALSE) map <- cr_column_map( exact = c("Event Label" = "cell_id", "Signal - Mean Intensity" = "target_signal") ) cr_read_export(f, column_map = map)
Walks a directory recursively, reads every file matching pattern
with cr_read_export() and row-binds the result. Design facts that
live in the directory layout and in the file names — rather than
inside the files — are recovered by a parser and joined back onto the
cells.
cr_read_exports( root, pattern = "\\.(csv|tsv|xls|xlsx)$", column_map = NULL, spec = NULL, parser = NULL, recursive = TRUE, drop_empty_rows = TRUE, col_types = NULL, progress = TRUE, call = rlang::caller_env() )cr_read_exports( root, pattern = "\\.(csv|tsv|xls|xlsx)$", column_map = NULL, spec = NULL, parser = NULL, recursive = TRUE, drop_empty_rows = TRUE, col_types = NULL, progress = TRUE, call = rlang::caller_env() )
root |
Directory to walk. |
pattern |
Regular expression selecting export files. Default
matches |
column_map |
Optional |
spec |
Optional |
parser |
Optional function of the file paths returning a tibble with one row per path. |
recursive |
Logical. Walk sub-directories. Default |
drop_empty_rows |
Logical. Passed to |
col_types |
Optional column-type specification passed to
|
progress |
Logical. Show a progress bar while reading. Default
|
call |
The execution environment of the calling function. Used for error reporting; experts only. |
No naming convention is hardcoded. Either supply a cr_path_spec()
via spec, which is handed to cr_parse_paths(), or supply an
arbitrary parser function. A parser receives the character vector of
file paths and must return one row per path; if it returns a
source_path column the join is made on that column, otherwise row
order is assumed to match.
Row-binding is tolerant of exports that carry different subsets of the
available columns: absent columns are filled with NA.
A tibble of all cells, with source_file and source_path
provenance columns and any columns produced by the parser. The paths
that were read are attached as the "files" attribute.
cr_read_export(), cr_path_spec(), cr_parse_paths(),
cr_dataset().
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_qupath(),
cr_read_segmantr(),
cr_unit_map()
# Build a small two-file export tree. root <- file.path(tempdir(), "cr_exports_demo") unlink(root, recursive = TRUE) leaf <- file.path(root, "Run1", "CompoundA", "Plate_1") dir.create(leaf, recursive = TRUE, showWarnings = FALSE) one <- function(n) { data.frame("Event Label" = seq_len(n), "Signal - Mean Intensity" = seq_len(n) * 10, check.names = FALSE) } utils::write.csv(one(3), file.path(leaf, "CompoundA_vehicle_1.csv"), row.names = FALSE) utils::write.csv(one(4), file.path(leaf, "CompoundA_5min_10uM_treated_1.csv"), row.names = FALSE) spec <- cr_path_spec( levels = c("run", "compound", "plate"), grammar = cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM"), defaults = list(interval = "none", dose = "vehicle"), prefix_strip = "CompoundA" ) ) cells <- cr_read_exports(root, spec = spec, progress = FALSE) cells# Build a small two-file export tree. root <- file.path(tempdir(), "cr_exports_demo") unlink(root, recursive = TRUE) leaf <- file.path(root, "Run1", "CompoundA", "Plate_1") dir.create(leaf, recursive = TRUE, showWarnings = FALSE) one <- function(n) { data.frame("Event Label" = seq_len(n), "Signal - Mean Intensity" = seq_len(n) * 10, check.names = FALSE) } utils::write.csv(one(3), file.path(leaf, "CompoundA_vehicle_1.csv"), row.names = FALSE) utils::write.csv(one(4), file.path(leaf, "CompoundA_5min_10uM_treated_1.csv"), row.names = FALSE) spec <- cr_path_spec( levels = c("run", "compound", "plate"), grammar = cr_filename_grammar( tokens = list(interval = "[0-9]+min", dose = "[0-9]+uM"), defaults = list(interval = "none", dose = "vehicle"), prefix_strip = "CompoundA" ) ) cells <- cr_read_exports(root, spec = spec, progress = FALSE) cells
Read a QuPath measurement export
cr_read_qupath(path)cr_read_qupath(path)
path |
Path to QuPath TSV. |
A tibble with standardised column names.
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_segmantr(),
cr_unit_map()
f <- tempfile(fileext = ".tsv") writeLines( c("Image\tCentroid X um\tCentroid Y um\tArea um^2\tCell: marker_1 mean", "A01.ome.tif\t10\t12\t120\t0.44", "A01.ome.tif\t30\t42\t118\t0.51"), f ) cr_read_qupath(f)f <- tempfile(fileext = ".tsv") writeLines( c("Image\tCentroid X um\tCentroid Y um\tArea um^2\tCell: marker_1 mean", "A01.ome.tif\t10\t12\t120\t0.44", "A01.ome.tif\t30\t42\t118\t0.51"), f ) cr_read_qupath(f)
Imports an RDS file produced by the segmantR segmentation
package. Accepts either a segmantr_result list (where cells are
in $cells) or a plain data frame.
cr_read_segmantr(path)cr_read_segmantr(path)
path |
Path to RDS file. |
A tibble of cells.
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_unit_map()
f <- tempfile(fileext = ".rds") saveRDS(data.frame(cell_id = "c1", well = "A01", target_signal = 12), f) cr_read_segmantr(f)f <- tempfile(fileext = ".rds") saveRDS(data.frame(cell_id = "c1", well = "A01", target_signal = 12), f) cr_read_segmantr(f)
Render a concise laboratory report
cr_render_lab_report( report, output_file, template = NULL, quiet = TRUE, audit_file = NULL, overwrite = FALSE, keep_tex = FALSE )cr_render_lab_report( report, output_file, template = NULL, quiet = TRUE, audit_file = NULL, overwrite = FALSE, keep_tex = FALSE )
report |
A |
output_file |
Explicit output file ending in |
template |
Optional R Markdown template. The default HTML template embeds its assets, disables dynamic math rendering, and wraps long table values. Custom templates retain their own HTML output options. |
quiet |
Passed to |
audit_file |
Optional JSON audit path written after rendering. It must be distinct from the report path, including relative-path aliases. |
overwrite |
Replace existing report and audit files. Defaults to |
keep_tex |
Keep the generated |
Renders an assembled report through an R Markdown template. The
bundled template covers experimental setup, the QC log, an intensity
overview, the comparison summary and a session-info appendix. A
custom template receives the report through its params; only the
parameters a template declares are passed, so templates of different
vintages keep working.
cr_render_report( report, output_dir = tempdir(), format = c("html", "pdf", "docx"), template = NULL, title = NULL, author = NULL, quiet = TRUE )cr_render_report( report, output_dir = tempdir(), format = c("html", "pdf", "docx"), template = NULL, title = NULL, author = NULL, quiet = TRUE )
report |
A |
output_dir |
Output directory (default |
format |
One of |
template |
Path to an R Markdown template. If |
title, author
|
Override the report title and author. |
quiet |
Passed to |
Path to the rendered document (invisibly).
Other reporting:
cr_export_plots(),
cr_export_results(),
cr_export_tables(),
cr_report(),
cr_table_qc(),
cr_tables()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) rep <- cr_report(exp) if (requireNamespace("rmarkdown", quietly = TRUE) && requireNamespace("knitr", quietly = TRUE) && rmarkdown::pandoc_available()) { out <- cr_render_report(rep, output_dir = tempdir()) basename(out) }exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) rep <- cr_report(exp) if (requireNamespace("rmarkdown", quietly = TRUE) && requireNamespace("knitr", quietly = TRUE) && rmarkdown::pandoc_available()) { out <- cr_render_report(rep, output_dir = tempdir()) basename(out) }
Collects everything a write-up needs into one cr_report object:
the experiment, the statistical results, the quality-control record,
the effect-size grid, the sample-size table, any supplementary
tables and any plots. Assembling first and formatting later is what
keeps a number in the text tied to the object it came from — tables,
generated macros and the rendered document are then all derived from
the same assembly rather than transcribed from each other.
cr_report( experiment, results = NULL, qc = NULL, effects = NULL, sizes = NULL, tables = NULL, plots = NULL, title = "cellreportR analysis report", author = "", metadata = list(), render = NULL, template = NULL, output_dir = NULL, format = c("html", "pdf", "docx") )cr_report( experiment, results = NULL, qc = NULL, effects = NULL, sizes = NULL, tables = NULL, plots = NULL, title = "cellreportR analysis report", author = "", metadata = list(), render = NULL, template = NULL, output_dir = NULL, format = c("html", "pdf", "docx") )
experiment |
A |
results |
Optional |
qc |
Optional quality-control record: a data frame, or a list
holding one (for example a gate object with a |
effects |
Optional data frame of effect sizes — one row per contrast, typically with estimate and confidence-bound columns. |
sizes |
Optional data frame of sample-size calculations, one row per contrast. |
tables |
Optional named list of supplementary tables (data
frames). A |
plots |
Optional named list of ggplot2 objects. |
title |
Report title. |
author |
Author name for the report header. |
metadata |
Optional named list of arbitrary metadata. |
render |
Whether to render the report to a file. The default
|
template |
Path to an R Markdown template. If |
output_dir |
Output directory for the rendered document. |
format |
One of |
A cr_report object, an S3 list with the slots
experimentThe cr_experiment the report describes.
resultsNamed list of cr_result objects.
summaryOne-row-per-contrast overview tibble.
qcQuality-control tibble.
effectsEffect-size tibble, or NULL.
sizesSample-size tibble, or NULL.
tablesNamed list of supplementary tibbles.
plotsNamed list of ggplot2 objects.
metadataUser metadata.
paramsTitle, author, package version, creation time.
When rendering was requested, the path to the rendered document is
returned invisibly instead, carrying the assembled object in its
report attribute.
cr_render_report() to render an assembled report,
cr_tables() to extract its tables and cr_macros() to emit its
numbers.
Other reporting:
cr_export_plots(),
cr_export_results(),
cr_export_tables(),
cr_render_report(),
cr_table_qc(),
cr_tables()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) rep <- cr_report(exp, title = "Marker 1 overview") rep # supply an effect grid and the sample sizes derived from it eff <- data.frame( group = c("CompoundA_low", "CompoundA_high"), estimate = c(0.31, 1.42), ci_low = c(-0.10, 0.55), ci_high = c(0.72, 2.29) ) rep2 <- cr_report(exp, effects = eff, title = "Marker 1 screen") rep2$summaryexp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) rep <- cr_report(exp, title = "Marker 1 overview") rep # supply an effect grid and the sample sizes derived from it eff <- data.frame( group = c("CompoundA_low", "CompoundA_high"), estimate = c(0.31, 1.42), ci_low = c(-0.10, 0.55), ci_high = c(0.72, 2.29) ) rep2 <- cr_report(exp, effects = eff, title = "Marker 1 screen") rep2$summary
Inspect the exact structured values entering a laboratory report
cr_report_data(report)cr_report_data(report)
report |
A |
Produces already formatted labels, dates, values, section visibility flags, and audit rows. It does not change the report specification.
cr_report_display_data(report)cr_report_display_data(report)
report |
A |
A plain nested list suitable for inspection, serialization, and deterministic rendering.
Other laboratory reporting:
cr_report_profile(),
cr_report_spec(),
cr_report_style(),
cr_validate_report_spec()
This neutral provenance layer does not calculate effects, infer units, verify scientific validity, or prove that a figure was generated from its declared tables. Figure links are explicit declarations whose file identities are checked. Source files remain external to the report.
cr_report_evidence(root, tables, claims = list(), figures = list())cr_report_evidence(root, tables, claims = list(), figures = list())
root |
Existing directory containing all source files. Paths stored in the evidence are relative to this root, so the complete tree can be moved. |
tables |
Named list of descriptors with |
claims |
Named list of descriptors with |
figures |
Named list of descriptors with |
cr_report_evidence returns a versioned list with file SHA-256 hashes,
keyed raw values, formatted displays and a manifest SHA-256. Its hash uses
UTF-8 JSON bytes, not R serialization. Identifiers use radix ordering and
numeric displays use a period decimal mark regardless of locale/options.
Row order and
other source-byte changes deliberately invalidate the source hash.
root <- tempfile(); dir.create(root) writeLines(c("group,value", "control,1.25"), file.path(root, "result.csv")) evidence <- cr_report_evidence(root, tables = list(result = list(path = "result.csv", format = "csv", key = "group")), claims = list(mean = list(table = "result", key = c(group = "control"), column = "value", format = "number", digits = 2))) cr_validate_report_evidence(evidence, root) unlink(root, recursive = TRUE)root <- tempfile(); dir.create(root) writeLines(c("group,value", "control,1.25"), file.path(root, "result.csv")) evidence <- cr_report_evidence(root, tables = list(result = list(path = "result.csv", format = "csv", key = "group")), claims = list(mean = list(table = "result", key = c(group = "control"), column = "value", format = "number", digits = 2))) cr_validate_report_evidence(evidence, root) unlink(root, recursive = TRUE)
Hash report-relevant structured data
cr_report_hash(x, algorithm = "sha256")cr_report_hash(x, algorithm = "sha256")
x |
Any R object. |
algorithm |
Algorithm supported by |
A profile stores organization-wide branding and display policy separately from examination-specific scientific configuration.
cr_report_profile( laboratory = list(), style = cr_report_style(), labels = character(), footer_statement = NULL, default_title = NULL, required_fields = character() )cr_report_profile( laboratory = list(), style = cr_report_style(), labels = character(), footer_statement = NULL, default_title = NULL, required_fields = character() )
laboratory |
Default laboratory metadata. |
style |
|
labels |
Named display-label overrides. |
footer_statement |
Optional laboratory-controlled release statement. |
default_title |
Optional default report title. |
required_fields |
Optional dotted required-field paths. |
A cr_report_profile object.
Other laboratory reporting:
cr_report_display_data(),
cr_report_spec(),
cr_report_style(),
cr_validate_report_spec()
Build machine-readable report provenance
cr_report_provenance( experiment = NULL, report_spec, output_file = NULL, analysis_metadata = list() )cr_report_provenance( experiment = NULL, report_spec, output_file = NULL, analysis_metadata = list() )
experiment |
Optional |
report_spec |
A |
output_file |
Optional rendered file whose byte hash is recorded. |
analysis_metadata |
Optional concise metadata about upstream result objects. |
Construct a concise report QC table
cr_report_qc( criterion = character(), observed = character(), acceptance = character(), status = character(), source = character() )cr_report_qc( criterion = character(), observed = character(), acceptance = character(), status = character(), source = character() )
criterion, observed, acceptance, status
|
Vectors defining reportable QC rows. |
source |
Optional source identifiers. |
Convert an existing experiment QC log to report-compatible rows
cr_report_qc_from_log(x)cr_report_qc_from_log(x)
x |
A |
Creates an application object without starting a listener. The report is detached from the caller by serialization; previews and downloads validate its captured state and bound source files before and after each operation. Claim values, source metadata, limitations and report status are visible. Source details expand using keyboard-accessible disclosures on narrow screens.
cr_report_review_app(report, root = NULL)cr_report_review_app(report, root = NULL)
report |
An already-bound |
root |
Optional existing source root for identical relocated evidence. Defaults to the report's bound evidence root. |
The optional package bslib is required. HTML/PDF downloads additionally
require the render dependencies of cr_render_lab_report(), including
rmarkdown, Pandoc and a suitable LaTeX installation for PDF.
Only declared PNG/PDF figures are downloadable. Filename extensions and byte signatures must agree; this is not full decoding or content sanitization. Source tables are shown as metadata and are never registered as a static directory. Staged downloads are removed after failure or completion.
This application is not a sandbox, authentication service or authorization
system. Source identity does not establish scientific validity or release
authorization. Pre/post checks do not provide filesystem snapshot isolation.
The function starts no server and changes no global listener configuration.
For local review, explicitly use shiny::runApp(app, host = "127.0.0.1").
Claims and figures may be empty; bound evidence requires source tables.
A shiny.appobj, suitable for shiny::runApp().
cr_report_evidence(), cr_lab_report_from_evidence()
if (interactive() && requireNamespace("bslib", quietly = TRUE)) { root <- tempfile("report-sources-") dir.create(root) writeLines(c("group,value", "treated,1.25"), file.path(root, "results.csv")) evidence <- cr_report_evidence(root, tables = list(results = list( path = "results.csv", format = "csv", key = "group" )), claims = list(estimate = list( table = "results", key = c(group = "treated"), column = "value" )) ) spec <- cr_report_spec( report = list(report_id = "example"), result = list(display_value = "Source-bound example") ) report <- cr_lab_report_from_evidence(evidence, root, spec) app <- cr_report_review_app(report) # shiny::runApp(app, host = "127.0.0.1") }if (interactive() && requireNamespace("bslib", quietly = TRUE)) { root <- tempfile("report-sources-") dir.create(root) writeLines(c("group,value", "treated,1.25"), file.path(root, "results.csv")) evidence <- cr_report_evidence(root, tables = list(results = list( path = "results.csv", format = "csv", key = "group" )), claims = list(estimate = list( table = "results", key = c(group = "treated"), column = "value" )) ) spec <- cr_report_spec( report = list(report_id = "example"), result = list(display_value = "Source-bound example") ) report <- cr_lab_report_from_evidence(evidence, root, spec) app <- cr_report_review_app(report) # shiny::runApp(app, host = "127.0.0.1") }
Creates a domain-neutral, versioned description of values that may appear in a laboratory-style report. No analytical calculation or interpretation is performed. All scientific content is supplied by the caller.
cr_report_spec( report = list(), laboratory = list(), subject = list(), specimen = list(), examination = list(), result = list(), interpretation = list(), limitations = character(), authorization = list(), custom_fields = list(), custom_sections = list(), required_fields = character(), field_labels = character(), schema_version = "1.0" )cr_report_spec( report = list(), laboratory = list(), subject = list(), specimen = list(), examination = list(), result = list(), interpretation = list(), limitations = character(), authorization = list(), custom_fields = list(), custom_sections = list(), required_fields = character(), field_labels = character(), schema_version = "1.0" )
report, laboratory, subject, specimen, examination, result, interpretation, authorization
|
Named lists for the corresponding report sections. |
limitations |
Character vector of user-supplied limitations. |
custom_fields |
Named list of additional label/value pairs. |
custom_sections |
List of sections, each with |
required_fields |
Character vector of dotted field paths required by the caller. |
field_labels |
Named character vector of optional display-label overrides. |
schema_version |
Report-data schema version, independent of the package version. |
An object of class cr_report_spec.
Other laboratory reporting:
cr_report_display_data(),
cr_report_profile(),
cr_report_style(),
cr_validate_report_spec()
Creates a presentation-only object shared by programmatic rendering and the Shiny report workflow. It does not alter report values or analytical data.
cr_report_style( paper = "A4", mode = c("colour", "grayscale"), density = c("standard", "compact"), locale = c("en", "de"), logo = NULL, primary_colour = "#315A70", secondary_colour = "#65747C", date_format = NULL, date_time_format = NULL, labels = character(), footer_text = NULL, include_audit_appendix = FALSE, show_signature_lines = FALSE, draft_watermark = FALSE )cr_report_style( paper = "A4", mode = c("colour", "grayscale"), density = c("standard", "compact"), locale = c("en", "de"), logo = NULL, primary_colour = "#315A70", secondary_colour = "#65747C", date_format = NULL, date_time_format = NULL, labels = character(), footer_text = NULL, include_audit_appendix = FALSE, show_signature_lines = FALSE, draft_watermark = FALSE )
paper |
Paper size. Version 2 currently supports |
mode |
|
density |
|
locale |
Display-label locale, currently |
logo |
Optional local PNG, JPEG, or PDF logo path. |
primary_colour, secondary_colour
|
Six-digit hex colours. In grayscale mode neutral values are used regardless of these settings. |
date_format, date_time_format
|
Optional |
labels |
Named display-label overrides. |
footer_text |
Optional laboratory-controlled document-footer statement. |
include_audit_appendix |
Include the technical appendix by default. |
show_signature_lines |
Add printable reviewer/authorizer lines. |
draft_watermark |
Add a light watermark only when status is |
A cr_report_style object.
Other laboratory reporting:
cr_report_display_data(),
cr_report_profile(),
cr_report_spec(),
cr_validate_report_spec()
cr_result
Extract or compute an ROC curve from a cr_result
cr_roc(result)cr_roc(result)
result |
A |
A tibble with threshold, sensitivity, specificity,
fpr and tpr.
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") head(cr_roc(res))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_logistic(exp, "marker_1", "CompoundA_high", "Untreated") head(cr_roc(res))
Convert row and column indices to well IDs
cr_rowcol_to_well(row, col, pad = 2)cr_rowcol_to_well(row, col, pad = 2)
row |
Integer vector of row numbers (1 = A, 2 = B, ...). |
col |
Integer vector of column numbers. |
pad |
Number of digits to pad the column number to
(default 2, yielding |
A character vector of well IDs.
cr_rowcol_to_well(c(1, 2, 8), c(1, 5, 12))cr_rowcol_to_well(c(1, 2, 8), c(1, 5, 12))
Starts the interactive front-end bundled with the package. The app covers the whole analysis path in one place: point it at a directory of segmented exports (or upload the files), specify or edit the design, review quality control with a per-unit exclusion table, choose a normalisation, estimate effect sizes as a table plus forest plot, and export a report.
cr_run_app( experiment = NULL, report_spec = NULL, report_profile = NULL, max_upload_mb = 512, launch_browser = interactive(), ... )cr_run_app( experiment = NULL, report_spec = NULL, report_profile = NULL, max_upload_mb = 512, launch_browser = interactive(), ... )
experiment |
Optional |
report_spec |
Optional |
report_profile |
Optional |
max_upload_mb |
Numeric. Maximum upload size per request, in
megabytes. Segmented single-cell exports routinely exceed the
Shiny default of 5 MB; this argument raises the limit for the
duration of the running app and restores the previous value on
exit. Default |
launch_browser |
Whether to open a browser window. Defaults to
|
... |
Further arguments passed to |
The user interface, the server and every helper live inside the
package namespace, so the app can be driven in-process by
shiny::testServer() as well as from a browser. The directory under
inst/shiny/cellreportR/ holds the www/ assets and a thin app.R
shim for deployment on a Shiny server.
Requires the shiny, bslib, DT and ggplot2 packages, all
listed under Suggests. An informative error naming the missing
package is raised when any of them is unavailable.
Invoked for its side effect of running the app. Returns
whatever shiny::runApp() returns, invisibly.
cr_build_experiment(), cr_report()
if (interactive()) { cr_run_app() } # Start from an experiment that is already in the session: exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) if (interactive()) { cr_run_app(exp) }if (interactive()) { cr_run_app() } # Start from an experiment that is already in the session: exp <- cr_example_experiment(seed = 1, n_cells_per_well = 10) if (interactive()) { cr_run_app(exp) }
Save a publication-ready figure deterministically
cr_save_figure( plot, filename, size = c("single", "double", "report", "square"), dpi = 600, background = "white", metadata = NULL )cr_save_figure( plot, filename, size = c("single", "double", "report", "square"), dpi = 600, background = "white", metadata = NULL )
plot |
A ggplot object. |
filename |
Explicit PDF, SVG, PNG, TIFF or TIF filename. |
size |
Standard size name or numeric width/height. |
dpi |
Raster resolution. |
background |
Explicit background. |
metadata |
Optional list written to a JSON sidecar. |
TIFF uses Cairo with lossless LZW compression when native Cairo and TIFF support are available. Otherwise the normal bitmap device is used. With Quartz configured, the fallback is uncompressed because Quartz does not support compression. CRAN R on macOS needs XQuartz for Cairo devices. A reported Cairo capability alone does not establish that the runtime libraries are installed. The figure and optional sidecar are staged before replacing their targets. Missing or empty device output is an error. Ordinary publication failures restore previous files; callers must serialize writers to these paths.
Writes one plot to one or more formats with the package's publication defaults: 600 dpi, a white background (so a transparent panel does not render as black in a typeset document) and a golden-ratio height when none is given.
cr_save_plot( plot, path, width = 12, height = NULL, dpi = 600, formats = c("png", "pdf"), units = "in", bg = "white", quiet = FALSE )cr_save_plot( plot, path, width = 12, height = NULL, dpi = 600, formats = c("png", "pdf"), units = "in", bg = "white", quiet = FALSE )
plot |
A |
path |
Output path. Any extension is replaced by each entry of
|
width |
Width in |
height |
Height in |
dpi |
Raster resolution (default |
formats |
Character vector of file extensions to write (default
|
units |
Passed to |
bg |
Background colour (default |
quiet |
Suppress the message naming the written files (default
|
The written paths, invisibly, as a character vector.
Other screen figures:
cr_plot_forest(),
cr_plot_qc_gate(),
cr_plot_sample_size(),
cr_plot_screen(),
cr_plot_specificity()
p <- ggplot2::ggplot(data.frame(x = 1:5, y = 1:5), ggplot2::aes(x, y)) + ggplot2::geom_point() + cr_theme() out <- file.path(tempdir(), "figure-1") paths <- cr_save_plot(p, out, width = 5, formats = "png") basename(paths) unlink(paths)p <- ggplot2::ggplot(data.frame(x = 1:5, y = 1:5), ggplot2::aes(x, y)) + ggplot2::geom_point() + cr_theme() out <- file.path(tempdir(), "figure-1") paths <- cr_save_plot(p, out, width = 5, formats = "png") basename(paths) unlink(paths)
Manual colour scale from the cellreportR visual system
cr_scale_colour(values = NULL, mode = c("colour", "grayscale"), ...) cr_scale_fill(values = NULL, mode = c("colour", "grayscale"), ...) cr_shape_scale(values = NULL, ...) cr_linetype_scale(values = NULL, ...)cr_scale_colour(values = NULL, mode = c("colour", "grayscale"), ...) cr_scale_fill(values = NULL, mode = c("colour", "grayscale"), ...) cr_shape_scale(values = NULL, ...) cr_linetype_scale(values = NULL, ...)
values |
Optional named values. |
mode |
Colour mode. |
... |
Passed to |
Continuous diverging scale
cr_scale_diverging( midpoint = 0, aesthetics = c("colour", "fill"), mode = c("colour", "grayscale"), ... )cr_scale_diverging( midpoint = 0, aesthetics = c("colour", "fill"), mode = c("colour", "grayscale"), ... )
midpoint |
Explicit neutral midpoint. |
aesthetics |
|
mode |
Colour mode. |
... |
Passed to the gradient scale. |
Builds the discrete scales that carry a grouping variable: a
colour-vision-safe hue from cr_palette() plus a matching symbol from
cr_shapes(). Add the result to a plot with +, exactly like a single
scale.
cr_scale_group( aesthetics = c("colour", "fill", "shape"), name = NULL, guide_for = NULL, drop = TRUE, mode = c("colour", "grayscale") )cr_scale_group( aesthetics = c("colour", "fill", "shape"), name = NULL, guide_for = NULL, drop = TRUE, mode = c("colour", "grayscale") )
aesthetics |
Character vector of aesthetics to scale. Any of
|
name |
Legend title. |
guide_for |
Aesthetics that keep a visible guide. Use |
drop |
Passed to the underlying scales: drop unused factor levels
(default |
mode |
Colour or grayscale palette for colour/fill aesthetics. |
Because the same variable is mapped to several aesthetics, the guide is
emitted for one aesthetic only. A duplicate guide is what makes a composed
figure print the same legend twice, so guide_for names the single
aesthetic that keeps its legend and every other aesthetic is suppressed.
A list of ggplot2 scales.
cr_palette(), cr_shapes(), cr_theme()
Other plot design:
cr_palette(),
cr_shapes(),
cr_theme()
df <- data.frame(g = rep(c("a", "b", "c"), each = 10), y = rnorm(30)) ggplot2::ggplot(df, ggplot2::aes(g, y, colour = g, shape = g)) + ggplot2::geom_point() + cr_scale_group(c("colour", "shape"), name = "group") + cr_theme()df <- data.frame(g = rep(c("a", "b", "c"), each = 10), y = rnorm(30)) ggplot2::ggplot(df, ggplot2::aes(g, y, colour = g, shape = g)) + ggplot2::geom_point() + cr_scale_group(c("colour", "shape"), name = "group") + cr_theme()
Returns plotting symbols matched to cr_palette(), so that a grouping
encoded by hue is also encoded by shape. Filled shapes (21:25, which take
both a colour and a fill) come first, then open shapes.
cr_shapes(n = NULL, names = NULL)cr_shapes(n = NULL, names = NULL)
n |
Number of shapes to return. |
names |
Optional character vector of names to attach, for use as the
|
An integer vector of ggplot2 shape codes.
cr_palette(), cr_scale_group()
Other plot design:
cr_palette(),
cr_scale_group(),
cr_theme()
cr_shapes(4) cr_shapes(3, names = c("low", "mid", "high"))cr_shapes(4) cr_shapes(3, names = c("low", "mid", "high"))
Expresses every cell relative to the control cells of the batch it belongs to, rather than to one pooled reference for the whole experiment. This is the standardization a plate-based screen needs: plates, runs and acquisition days each carry their own offset, and a single pooled control folds that offset into the estimate.
cr_standardize_batch( experiment, channel, control_level, batch_vars, control_var = "treatment", method = c("log2_fc", "zscore", "raw"), eps = 1, sd_floor = 1e-08, value_to = "value_std", on_missing_control = c("error", "warn", "drop") )cr_standardize_batch( experiment, channel, control_level, batch_vars, control_var = "treatment", method = c("log2_fc", "zscore", "raw"), eps = 1, sd_floor = 1e-08, value_to = "value_std", on_missing_control = c("error", "warn", "drop") )
experiment |
A |
channel |
Channel column to standardize. Must be numeric. |
control_level |
Value (or values) of |
batch_vars |
Character vector of columns that jointly define a
batch. See |
control_var |
Column holding the treatment assignment.
Defaults to |
method |
Which quantity becomes the canonical analysis value
in |
eps |
Additive offset for the log2 fold change. |
sd_floor |
Lower bound for the control standard deviation. |
value_to |
Name of the column receiving the value selected by
|
on_missing_control |
What to do with batches that have no
control cells: |
Three quantities are always added, whichever method is chosen,
because downstream steps need different ones: log2_fc, z_ctrl
and the untouched channel. method only decides which of them is
copied into value_to as the canonical analysis value.
The log2 fold change uses an additive offset,
log2((y + eps) / (ctrl_mean + eps)), not a floor on y. An
offset keeps the transformation monotone and well behaved near
zero, whereas clamping small values to a floor flattens a whole
range of the signal onto one number.
The fold change divides by the control mean while
cr_batch_reference() also reports the control median; see
there for why both are kept.
A batch that contains no control cells cannot be standardized: its
reference does not exist, and a value computed against some other
batch's control would be a silent error rather than a measurement.
cr_standardize_batch() therefore refuses by default. Use
on_missing_control = "drop" to remove those cells (recorded in
the QC log) or "warn" to keep them with NA standardized values.
The cr_experiment with these columns added to cells:
batch_keyThe batch each cell belongs to.
ctrl_n, ctrl_mean, ctrl_median, ctrl_sd
The reference statistics of that batch.
z_ctrl(y - ctrl_mean) / ctrl_sd.
log2_fclog2((y + eps) / (ctrl_mean + eps)).
value_toThe value selected by method.
The reference table is stored as $batch_reference, the batch
columns as $batch_vars, and the settings under
$metadata$standardization.
cr_batch_reference(), cr_batch_key(), cr_normalize()
Other batch standardization functions:
cr_batch_key(),
cr_batch_reference(),
cr_correct_batch()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) std <- cr_standardize_batch(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate") round(summary(std$cells$log2_fc), 2) std$batch_reference # Per-batch z-score instead of the fold change z <- cr_standardize_batch(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate", method = "zscore") round(stats::median(z$cells$value_std), 2) # A batch without control cells is refused, not guessed at exp$design$plate[exp$design$treatment == "Untreated"] <- "P1" try(cr_standardize_batch(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate"))exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp$design$plate <- rep(c("P1", "P2"), length.out = nrow(exp$design)) std <- cr_standardize_batch(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate") round(summary(std$cells$log2_fc), 2) std$batch_reference # Per-batch z-score instead of the fold change z <- cr_standardize_batch(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate", method = "zscore") round(stats::median(z$cells$value_std), 2) # A batch without control cells is refused, not guessed at exp$design$plate[exp$design$treatment == "Untreated"] <- "P1" try(cr_standardize_batch(exp, channel = "marker_1", control_level = "Untreated", batch_vars = "plate"))
Aggregates the per-cell values of one channel to a single number
per analysis unit. By default the analysis unit is the spatial unit
of the experiment (well or slide), which is the unit of
replication for most plate-based assays. Pass unit to aggregate to
a merged analysis unit instead — for example when one physical unit
was acquired as several files and the acquisitions were assigned a
common identifier.
cr_summarize_wells(experiment, channel, fun = stats::median, unit = NULL)cr_summarize_wells(experiment, channel, fun = stats::median, unit = NULL)
experiment |
A |
channel |
Channel name (a column of |
fun |
Aggregation function. Default |
unit |
Optional name of the column that identifies the
analysis unit. May be a column of |
A tibble with one row per analysis unit containing the unit
identifier, n_cells, the aggregated value, and the design
columns. Design columns that are not constant within a unit are
returned as NA.
cr_compute_metrics() for a richer per-unit summary and
cr_table_disposition() for unit and cell counts per arm.
Other quantification:
cr_compute_metrics(),
cr_fold_change(),
cr_table_disposition()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_summarize_wells(exp, channel = "marker_1") # aggregate with a different estimator cr_summarize_wells(exp, channel = "marker_1", fun = mean)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) cr_summarize_wells(exp, channel = "marker_1") # aggregate with a different estimator cr_summarize_wells(exp, channel = "marker_1", fun = mean)
Counts of analysis units and cells, overall and per arm. The reported counts of an assay are themselves an analysis output: once they are generated from the object that was analyzed, a count in the write-up cannot drift away from the data it describes.
cr_table_disposition(experiment, by = NULL, unit = NULL, total = TRUE)cr_table_disposition(experiment, by = NULL, unit = NULL, total = TRUE)
experiment |
A |
by |
Character vector of grouping columns from |
unit |
Optional name of the column that identifies the
analysis unit. May be a column of |
total |
Whether to append a row holding the overall counts. The
grouping columns of that row carry the label |
A tibble with the grouping columns (as character), n_units,
n_cells and median_cells_per_unit.
Other quantification:
cr_compute_metrics(),
cr_fold_change(),
cr_summarize_wells()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) cr_table_disposition(exp) cr_table_disposition(exp, by = "group")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) cr_table_disposition(exp) cr_table_disposition(exp, by = "group")
Normalizes the several shapes a QC record can take — an experiment's QC log, a gate object, or a plain data frame — into one tibble suitable for a supplement.
cr_table_qc(x)cr_table_qc(x)
x |
A |
A tibble. For a list of several data frames the elements are
stacked and identified by a component column.
Other reporting:
cr_export_plots(),
cr_export_results(),
cr_export_tables(),
cr_render_report(),
cr_report(),
cr_tables()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp <- cr_filter_cells(exp, area > 100) cr_table_qc(exp)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) exp <- cr_filter_cells(exp, area > 100) cr_table_qc(exp)
Gathers every tabular artifact of an experiment or report into one
named list, ready for cr_export_tables(). Empty tables are
dropped, so the result reflects what actually exists.
cr_tables(x, results = NULL, which = NULL)cr_tables(x, results = NULL, which = NULL)
x |
A |
results |
Optional results to summarize when |
which |
Optional character vector selecting a subset of tables by name. Unknown names are an error that lists what is available. |
A named list of tibbles.
cr_export_tables(), cr_table_disposition(),
cr_table_qc().
Other reporting:
cr_export_plots(),
cr_export_results(),
cr_export_tables(),
cr_render_report(),
cr_report(),
cr_table_qc()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) tabs <- cr_tables(exp) names(tabs) tabs$dispositionexp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) tabs <- cr_tables(exp) names(tabs) tabs$disposition
Runs a parametric or non-parametric two-sample test comparing cells (or replicate summaries) from a treatment group to the control group on a single channel.
cr_test( experiment, channel, treatment, control, test = c("mann_whitney", "t_test", "welch", "wilcoxon_signed"), level = c("cell", "replicate", "both") )cr_test( experiment, channel, treatment, control, test = c("mann_whitney", "t_test", "welch", "wilcoxon_signed"), level = c("cell", "replicate", "both") )
experiment |
A |
channel |
Channel to test. |
treatment |
Name of the treatment group (matches
|
control |
Name of the control group. |
test |
One of |
level |
|
A cr_result object with the elements comparison,
cell_level, rep_level, effect_sizes and fold_change.
Effect sizes use cells for level = "cell" and replicate medians
for "replicate" or "both". With "both", the additional
cell_effect_sizes element retains the cell-level comparison.
Replicate effect estimates differ from versions through 0.2.0.9000,
which computed cell effects regardless of the requested level.
cr_test_all(), cr_effect_size(), cr_effect_grid().
Other statistics:
cr_test_all()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_test(exp, channel = "marker_1", treatment = "CompoundA_high", control = "Untreated", test = "mann_whitney", level = "replicate") print(res)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) res <- cr_test(exp, channel = "marker_1", treatment = "CompoundA_high", control = "Untreated", test = "mann_whitney", level = "replicate") print(res)
Runs cr_test() pairwise for every treatment versus the control
and adjusts the p-values across the whole family of comparisons.
Both a Bonferroni and a Benjamini-Hochberg adjustment are reported
next to the unadjusted p-value, never in place of it.
cr_test_all( experiment, channel, control_group, tests = "mann_whitney", p_adjust = "BH", level = c("replicate", "cell", "both") )cr_test_all( experiment, channel, control_group, tests = "mann_whitney", p_adjust = "BH", level = c("replicate", "cell", "both") )
experiment |
A |
channel |
Channel name. |
control_group |
Control group. |
tests |
Test to run (see |
p_adjust |
P-value adjustment method used for the |
level |
|
A named list of cr_result objects, one per treatment,
carrying the attributes summary (a tibble with treatment,
log2_fc, p_value, cohens_d, p_adj, p_bonferroni,
p_BH and interpretation), control_group, channel and
level.
Other statistics:
cr_test()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) all_res <- cr_test_all(exp, channel = "marker_1", control_group = "Untreated", level = "replicate") attr(all_res, "summary")exp <- cr_example_experiment(seed = 1, n_cells_per_well = 20) all_res <- cr_test_all(exp, channel = "marker_1", control_group = "Untreated", level = "replicate") attr(all_res, "summary")
The single ggplot2 theme every cr_plot_* function applies, so that
figures assembled from different functions sit together without
re-styling: a classic axis-line frame, a faint major grid, a bold title, a
muted subtitle and a bottom legend.
cr_theme( base_size = 11, base_family = "sans", grid = TRUE, legend_position = "bottom", variant = c("publication", "report"), mode = c("colour", "grayscale") )cr_theme( base_size = 11, base_family = "sans", grid = TRUE, legend_position = "bottom", variant = c("publication", "report"), mode = c("colour", "grayscale") )
base_size |
Base font size in points (default |
base_family |
Base font family. Default generic |
grid |
Draw the faint major grid (default |
legend_position |
Passed to |
variant |
|
mode |
Colour or grayscale mode. Typography is shared across modes. |
A ggplot2 theme object, usable with + like any other theme.
cr_palette(), cr_scale_group()
Other plot design:
cr_palette(),
cr_scale_group(),
cr_shapes()
df <- data.frame(g = rep(c("a", "b"), each = 20), y = rnorm(40)) ggplot2::ggplot(df, ggplot2::aes(g, y)) + ggplot2::geom_boxplot() + cr_theme()df <- data.frame(g = rep(c("a", "b"), each = 20), y = rnorm(40)) ggplot2::ggplot(df, ggplot2::aes(g, y)) + ggplot2::geom_boxplot() + cr_theme()
Summarises which file contributed how many cells to which unit, and
flags the units that were assembled from more than one file. This is
the post-condition check for cr_assign_units(): a unit built from
several files should be one you can name and justify.
cr_unit_map( x, id_col = "well_id", file_col = "source_path", call = rlang::caller_env() )cr_unit_map( x, id_col = "well_id", file_col = "source_path", call = rlang::caller_env() )
x |
A cell table carrying a unit identifier and a file column,
as returned by |
id_col |
Name of the unit identifier column. Default
|
file_col |
Name of the file column. Default |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
A tibble with one row per file: the unit identifier, the file,
n_cells, n_files (files contributing to that unit) and merged
(TRUE when n_files > 1).
Other import:
cr_assign_units(),
cr_centroid_overlap(),
cr_column_map(),
cr_extract_markers(),
cr_filename_grammar(),
cr_marker_rules(),
cr_merge_rules(),
cr_parse_paths(),
cr_path_spec(),
cr_read_cellprofiler(),
cr_read_cells(),
cr_read_design(),
cr_read_export(),
cr_read_exports(),
cr_read_qupath(),
cr_read_segmantr()
cells <- tibble::tibble( source_path = rep(c("a.csv", "b.csv", "c.csv"), times = c(3, 2, 4)), compound = "CompoundA", replicate = rep(c("1", "1.1", "2"), times = c(3, 2, 4)), merge_unit = rep(c(FALSE, TRUE, FALSE), times = c(3, 2, 4)) ) units <- cr_assign_units(cells, key_vars = "compound") cr_unit_map(units)cells <- tibble::tibble( source_path = rep(c("a.csv", "b.csv", "c.csv"), times = c(3, 2, 4)), compound = "CompoundA", replicate = rep(c("1", "1.1", "2"), times = c(3, 2, 4)), merge_unit = rep(c(FALSE, TRUE, FALSE), times = c(3, 2, 4)) ) units <- cr_assign_units(cells, key_vars = "compound") cr_unit_map(units)
Summarizes how far apart the units of one condition sit. For every
group defined by by that holds at least min_units units, the
number of units, the coefficient of variation, the spread
(max - min of the unit values) and the fold range
(log_base ^ spread) are reported.
cr_unit_variability(data, value, by, unit = NULL, min_units = 2, log_base = 2)cr_unit_variability(data, value, by, unit = NULL, min_units = 2, log_base = 2)
data |
A data frame with one row per unit (or per cell when
|
value |
Name of the numeric response column, typically a log-scale fold change. |
by |
Character vector of columns defining a condition, for example compound, experiment, plate and pre-treatment interval. |
unit |
Optional column identifying the unit of replication. When given, rows are averaged per unit first. |
min_units |
Minimum number of units a group must contain to be reported (default 2). |
log_base |
Base of the logarithm the response is on. Used to turn the spread into a fold range. Default 2. |
This is unit-to-unit variability. It is not within-unit technical repeatability: that would require the same unit to be measured twice, which a design with one acquisition per unit cannot deliver. A unit assembled from two partial acquisitions is two halves of one unit, not two reads of it.
The coefficient of variation is computed as
100 * sd / abs(mean), which is unstable when the mean of a
log-scale response approaches zero; the fold range is the robust
summary and is what the attached overall summary reports.
A tibble with the by columns, n_units, mean_value,
sd_value, cv_pct, spread and fold_range, carrying a
summary attribute (a one-row tibble with the number of groups
and the median, quartiles and maximum of the fold range).
cr_blocked_effect(), cr_effect_grid().
Other screen statistics:
cr_blocked_effect()
set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 12), plate = rep(rep(c("P1", "P2"), each = 6), 2), log2_fc = stats::rnorm(24, 0, 0.4) ) v <- cr_unit_variability(units, value = "log2_fc", by = c("compound", "plate")) v attr(v, "summary")set.seed(1) units <- data.frame( compound = rep(c("CompoundA", "CompoundB"), each = 12), plate = rep(rep(c("P1", "P2"), each = 6), 2), log2_fc = stats::rnorm(24, 0, 0.4) ) v <- cr_unit_variability(units, value = "log2_fc", by = c("compound", "plate")) v attr(v, "summary")
cr_experiment
Performs structural checks on a cr_experiment. Called
automatically by cr_build_experiment() but can also be used to
verify that manual modifications have not broken the object.
cr_validate_experiment(x, call = rlang::caller_env())cr_validate_experiment(x, call = rlang::caller_env())
x |
A |
call |
The execution environment of the calling function. Used for error reporting; experts only. |
The optional unit_var, batch_vars, provenance and set_aside
slots are checked only when they are present, so that objects built by
earlier versions still validate.
TRUE invisibly on success. On failure an informative
error is raised.
Other constructors:
cr_build_experiment(),
cr_dataset(),
cr_design()
cells <- tibble::tibble( cell_id = c("c1", "c2"), well = c("A01", "A02"), target_signal = c(10, 20) ) design <- tibble::tibble(well = c("A01", "A02"), treatment = c("Vehicle", "CompoundA")) cr_validate_experiment(cr_build_experiment(cells, design))cells <- tibble::tibble( cell_id = c("c1", "c2"), well = c("A01", "A02"), target_signal = c(10, 20) ) design <- tibble::tibble(well = c("A01", "A02"), treatment = c("Vehicle", "CompoundA")) cr_validate_experiment(cr_build_experiment(cells, design))
Revalidate report evidence against its current source tree
cr_validate_report_evidence(evidence, root)cr_validate_report_evidence(evidence, root)
evidence |
A |
root |
Current root of the source tree, including after relocation. |
Invisibly TRUE; invalid schemas, changed bytes or altered claims error.
Validate a concise report QC table
cr_validate_report_qc(qc)cr_validate_report_qc(qc)
qc |
A data frame with criterion, observed, acceptance and status columns. |
Validate a laboratory report specification
cr_validate_report_spec(spec, strict = TRUE, return_issues = FALSE)cr_validate_report_spec(spec, strict = TRUE, return_issues = FALSE)
spec |
A |
strict |
In strict mode structural minima and caller-defined required fields are errors. |
return_issues |
Return a severity-coded issue table instead of throwing errors. |
TRUE invisibly, or a data frame when return_issues = TRUE.
Other laboratory reporting:
cr_report_display_data(),
cr_report_profile(),
cr_report_spec(),
cr_report_style()
Splits well identifiers of the form "A01" into the letter row
and numeric column.
cr_well_to_rowcol(well)cr_well_to_rowcol(well)
well |
A character vector of well IDs (e.g. |
A tibble with columns well, row (integer, 1 = A) and
col (integer).
cr_well_to_rowcol(c("A01", "B05", "H12"))cr_well_to_rowcol(c("A01", "B05", "H12"))
cr_experiment
Print method for cr_experiment
## S3 method for class 'cr_experiment' print(x, ...)## S3 method for class 'cr_experiment' print(x, ...)
x |
A |
... |
Unused. |
x invisibly.
Print a QC gate
## S3 method for class 'cr_qc_gate' print(x, ...)## S3 method for class 'cr_qc_gate' print(x, ...)
x |
A |
... |
Ignored. |
x, invisibly.
Other quality control:
cr_apply_gate(),
cr_balance_cells(),
cr_exclude_small(),
cr_qc_doublets(),
cr_qc_filter(),
cr_qc_gate(),
cr_qc_gate_impact(),
cr_qc_intensity(),
cr_qc_manual(),
cr_qc_report(),
cr_qc_summary()
exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") print(gate)exp <- cr_example_experiment(seed = 1, n_cells_per_well = 30) gate <- cr_qc_gate(exp, "marker_1", "Untreated", batch_vars = "replicate") print(gate)
cr_report
Print method for cr_report
## S3 method for class 'cr_report' print(x, ...)## S3 method for class 'cr_report' print(x, ...)
x |
A |
... |
Unused. |
x invisibly.
cr_result
Print method for cr_result
## S3 method for class 'cr_result' print(x, ...)## S3 method for class 'cr_result' print(x, ...)
x |
A |
... |
Unused. |
x invisibly.
cr_experiment
Summary method for cr_experiment
## S3 method for class 'cr_experiment' summary(object, ...)## S3 method for class 'cr_experiment' summary(object, ...)
object |
A |
... |
Unused. |
A tibble summarising the experiment (invisibly printed).
cr_report
Summary method for cr_report
## S3 method for class 'cr_report' summary(object, ...)## S3 method for class 'cr_report' summary(object, ...)
object |
A |
... |
Unused. |
object invisibly.
cr_result
Summary method for cr_result
## S3 method for class 'cr_result' summary(object, ...)## S3 method for class 'cr_result' summary(object, ...)
object |
A |
... |
Unused. |
The result list, invisibly.