Internals

These types are not exported, but are documented here for contributors and for users who want to work with expand_geno's return value directly.

Dynema.ExpandedGeno — Type
ExpandedGeno

Stores genotype data at the sample level. Allows storage of SNP names and single-cell ids.

Arguments

  • mat::AbstractMatrix: donor × SNP genotype matrix (e.g., Matrix{Float64} or SparseMatrixCSC).
  • rows::AbstractVector: mapping from single-cell to donor rows.
  • rownames::Union{Nothing,String,AbstractVector}=nothing: optional cell ids
  • colnames::Union{Nothing,String,AbstractVector}=nothing: optional SNP names.
source
Dynema.ExpandedGenoView — Type
ExpandedGenoView(mat::AbstractMatrix, rows::AbstractVector,
                 cols::AbstractVector;
                 rownames=nothing, colnames=nothing)

A lazy view of an ExpandedGeno, representing a submatrix without copying data.

Arguments

  • mat::AbstractMatrix: underlying donor × SNP matrix.
  • rows::AbstractVector: row indices of the view.
  • cols::AbstractVector: column indices of the view.
  • rownames::Union{Nothing,AbstractVector}=nothing: optional subset of row names.
  • colnames::Union{Nothing,AbstractVector}=nothing: optional subset of column names.

Indexing

  • 2D indexing only: V[i, j], V[i, :], V[:, j], V[I, J].
  • Materializes single rows or single columns only.
  • Supports names(view, 1) and names(view, 2).

Examples

# Create a lazy submatrix
view = E[1:100, 5:10]    # returns ExpandedGenoView

# Materialize a single row from the view
row = view[1, :]          # Vector{Float64}

# Materialize a single column from the view
col = view[:, 1]          # Vector{Float64}

# Access row and column names from the view
rnames = names(view, 1)
cnames = names(view, 2)
source

The CRVE score test itself, and the per-context 1-df decomposition reported by multi-context interaction tests (the p_<context> columns; see map_locus's percontext keyword):

Dynema.smallsample_factors — Function
smallsample_factors(small, G, nobs) -> (clusteradj, smallsample, dof_r)

Small-sample factors of the cluster-robust score test, replicating WildBootTests.jl's ML (score) mode with one-way clustering and small = true (init.jl: clusteradj = small, smallsample = _dof / (Nobs - robust), dof_r = G - 1), which is how Dynema invokes it:

  • clusteradj = G / (G - 1) multiplies the cluster-robust denominator (the "meat"), where G is the number of clusters (donors);
  • smallsample = nobs / (nobs - 1) rescales the statistic (its square root for 1 df). WildBootTests derives _dof = nobs - k, but in ML mode Dynema supplies no predexog, so its k is 0. For single-cell data (nobs = number of cells) the factor is essentially 1; it is kept so the direct implementation reproduces the library to numerical precision;
  • dof_r = G - 1 is the residual degrees of freedom of the reference t (1 df) or F (q df) distribution.

With small = false all three are neutral: (1, 1, 0), and the reference distributions are N(0,1) (1 df) and χ² (q df).

source
Dynema.crvetest_direct — Function
crvetest_direct(R, A, Sg, clustshare; small = false, nobs = 0)

Direct implementation of the analytical CRVE score test for the shared-null fast path, replicating WildBootTests.scoretest's ml-mode statistic (reps = 0, imposenull = true, scorebs = true, one-way clustering) without the library's per-call setup:

  • numer = (A R')' S, with S the total score sum;
  • cluster-level K = Sg * (A R'), recentered by each cluster's share of observations, so denom = K'K is the CRVE meat transformed by A R';
  • small = false (default): q = 1: z = numer / sqrt(denom), p = ccdf(Chisq(1), z²) (two-tailed); q > 1: χ² = numer' denom⁻¹ numer, p = ccdf(Chisq(q), χ²);
  • small = true: with (cm, ss, dof_r) = smallsample_factors(true, G, nobs) (G = size(Sg, 1) clusters), the denominator becomes cm * denom, q = 1: t = sqrt(ss) * numer / sqrt(cm * denom), p = 2 * ccdf(TDist(G - 1), |t|); q > 1: F = (ss / q) * numer' (cm * denom)⁻¹ numer, p = ccdf(FDist(q, G - 1), F).

Sg is the G × k matrix of per-cluster score sums; clustshare[g] is cluster g's share of observations; nobs (number of observations/cells) is required when small = true.

Returns (stat, p, stattype, beta, se, dof_r) in the same shape crvetest results are consumed (plus pk for q > 1). beta = numer is the one-step (score-based) estimate of each tested coefficient from the null fit and se = sqrt(cm * diag(denom) / ss) its cluster-robust standard error, so that beta ./ se reproduces the reported z/t statistic of each tested term (for q = 1, exactly stat). stattype is "z"/"t" for q = 1 and "χ²"/"F" for q > 1.

source
Dynema.crve_percomponent — Function
crve_percomponent(R, A, Sg, clustshare; small = false, nobs = 0) -> Vector{Float64}
crve_percomponent(R, A; scores, clustid, small = false) -> Vector{Float64}

Per-component 1-df CRVE score p-values for each tested row of R, computed from the same restricted (null) fit as the joint test: with numer and denom = K'K exactly as in crvetest_direct, and se_k = sqrt(cm * denom[k,k] / ss) (factors from smallsample_factors; both 1 when small = false),

p_k = 2 * ccdf(Normal(), |numer[k] / se_k|)     (small = false)
p_k = 2 * ccdf(TDist(G - 1), |numer[k] / se_k|)  (small = true)

These are tests of each coefficient under the joint null (all tested coefficients zero) – exact size under that null, but under partial alternatives with correlated contexts, a true effect in one context can project onto another's score. They decompose the joint statistic; the joint test remains the primary inference.

The keyword method builds per-cluster score sums from row-level scores and one-way integer cluster ids (used by the generic, non-workspace path).

source

The cluster-robust standard errors of the unrestricted coefficients (the se_wald_<term> columns that accompany the effect-size estimates; see map_locus's betas keyword). These are Wald-type SEs at the unrestricted fit, distinct from the null-fit score test above:

Dynema.crve_se — Function
crve_se(X, y, β, groups; small = false) -> Vector{Float64}

One-way cluster-robust (CRVE) standard errors of the unrestricted Poisson/log-link coefficients β (the se_wald_<term> output columns, reported alongside the unrestricted estimates selected with betas).

Sandwich estimator V = (cm / ss) A (Σ_g s_g s_g') A, where

  • A = (X'diag(μ̂)X)⁻¹ is the model-based bread,
  • s_g is the sum of the scores (y - μ̂) .* X over the cells of cluster (donor) g,
  • everything is evaluated at the unrestricted fit μ̂ = exp.(Xβ),
  • cm = ss = 1 when small = false; with small = true they are the same small-sample factors as the score test (smallsample_factors: cm = G/(G-1), ss = nobs/(nobs-1)), so that SEs are on the same footing as the reported t statistics.

The SE of coefficient j is sqrt(V[j, j]), on the same (natural-log) scale as β[j]. β[j] / se[j] is therefore a Wald z-statistic (small = false) or a Wald t-statistic on G - 1 degrees of freedom (small = true).

Note

These SEs are not the quantities behind Dynema's p-values. The z/t and p columns come from a score test at the restricted (null) fit, with recentered scores (see crvetest_direct); this SE comes from the unrestricted fit, so |β| / se will generally differ from |z| (they agree asymptotically, and closely for small effects). With small = false no small-sample correction is applied, matching the score test, so SEs are optimistic with few donors. The score-test p (or p_boot) remains the primary inference; use se_wald_<term> for effect-size uncertainty and meta-analysis.

Returns NaNs under multiway clustering (size(groups, 2) != 1), which is not implemented here.

source
Note

Dynema.DynemaModel, the struct returned by map_locus, is intentionally accessed only through its get_*/set_* accessors (see the API Reference) rather than by touching its fields directly, so that the internal layout can change without breaking user code.