Skip to content

API reference

The public API. Import these from the top-level pilotr package, for example from pilotr import simulate, power.

Simulation

pilotr.simulate.simulate

simulate(spec) -> Dataset

Simulate a data set from a design specification.

Build a linear predictor from the fixed effect sizes (categorical contrasts, continuous predictors and their interactions) plus the crossed by-subject and by-item random intercepts and slopes, then map it through the chosen response family.

Parameters:

Name Type Description Default
spec dict or str

A design specification, either an already-parsed dict or a path to a JSON spec file. The format is documented at https://github.com/pablobernabeu/pilotr/blob/main/spec/SPEC.md.

required

Returns:

Type Description
Dataset

A table with one row per observation: a subject column, an optional item column, any grouping, factor, and continuous-predictor columns, and the response column named by spec["response"]["name"].

pilotr.simulate.load_spec

load_spec(path)

Load a JSON design specification from a file.

Parameters:

Name Type Description Default
path str

Path to a JSON design-specification file.

required

Returns:

Type Description
dict

The parsed specification, ready for simulate or power.

pilotr.examples.pilotr_example

pilotr_example(name: Optional[str] = None) -> Union[list[str], str]

List the bundled example specifications, or return the path to one.

pilotr ships one ready-to-run specification per design family, as JSON. These are the same files that drive the R twin and the no-code app.

Parameters:

Name Type Description Default
name str

The base name of an example, with or without the .json extension, for example "between_2group_gaussian". When None (the default), the available example names are returned instead of a path.

None

Returns:

Type Description
list of str, or str

When name is None, the available example names. Otherwise, the path to that example's JSON file, ready to pass to :func:pilotr.simulate.load_spec.

pilotr.simulate.Dataset

A simulated data set: named columns and a list of row dicts.

Returned by simulate. Lightweight and dependency-free; build a pandas DataFrame from dataset.rows when you need one.

Attributes:

Name Type Description
columns list of str

Column names, in order.

rows list of dict

One dict per observation, keyed by column name.

column

column(name)

Return the values in column name as a list.

head

head(n=6)

Return the first n rows (default 6) as a list of dicts.

to_csv

to_csv(path)

Write the data set to path as CSV: a header row then one row per observation.

Power and design analysis

pilotr.power.power

power(spec, n_sims=1000, alpha=0.05, workers=1)

Simulation-based power and design analysis for a two-group Gaussian design.

Repeatedly simulate from the specification, apply a two-sample t-test, and report power together with the Type S (sign) and Type M (magnitude) errors of Gelman and Carlin (2014), computed over the significant replicates.

Parameters:

Name Type Description Default
spec dict or str

A two-group Gaussian design specification (dict or path to a JSON file).

required
n_sims int

Number of Monte Carlo replicates (default 1000).

1000
alpha float

Two-sided significance level (default 0.05).

0.05
workers int

Number of local worker processes over which to spread the replicates (default 1, serial). Each replicate seeds the shared RNG from its own index, so any worker count returns results identical to a serial run.

1

Returns:

Type Description
dict

Keys: n_sims, alpha, power, n_significant, true_effect, mean_estimate, type_s, type_m.

Raises:

Type Description
NotImplementedError

If the design is not a single two-level between-subjects Gaussian factor.

Notes

Requires scipy (imported lazily, in each worker process when parallel); install the power or dev extra.

pilotr.power.power_curve

power_curve(spec, subject_ns, n_sims=1000, alpha=0.05, workers=1)

Power curve over sample size for a two-group Gaussian design.

Sweep the number of subjects and compute power at each grid point.

Parameters:

Name Type Description Default
spec dict or str

A two-group Gaussian design specification.

required
subject_ns iterable of int

Subject counts to evaluate.

required
n_sims int

Replicates per grid point (default 1000).

1000
alpha float

Significance level (default 0.05).

0.05
workers int

Number of local worker processes over which to spread the replicates at each grid point (default 1, serial). One process pool is started and reused across the whole sweep, and any worker count returns results identical to a serial run.

1

Returns:

Type Description
list of dict

One dict per grid point, with keys n_subject, power, type_m.

pilotr.power.power_mixed

power_mixed(spec, n_sims=50, alpha=0.05, workers=1)

Crossed mixed-effects simulation-based power in Python, via statsmodels MixedLM with by-subject and by-item random intercepts and slopes as (independent) variance components.

This is pilotr's own simulation loop over the portable design specification, not a wrapper around an existing power package. It covers territory pioneered by simr (Green and MacLeod, 2016, doi:10.1111/2041-210x.12504) and mixedpower (Kumle, Vo and Draschkow, 2021, doi:10.3758/s13428-021-01546-0); pilotr differs in being driven by the portable cross-language spec, in reporting Type S and Type M errors and in built-in parallelisation via workers (default 1, serial), which returns results identical to a serial run for any worker count.

Accuracy caveat (verified behaviour, not a bug). statsmodels fits crossed random effects as independent variance components and, in our tests, substantially overstates random-slope variance (for example, a by-subject slope SD of about 0.12 estimated against 0.04 true). This inflates the fixed-effect standard error. For designs with by-subject or by-item random slopes, the backend is therefore markedly conservative. On the crossed RT design it reports power around 0.48, against the R/lme4 reference of about 0.73. It still recovers the fixed effect (mean estimate about 0.048 against 0.05 true) and the Type S and Type M quantities correctly, and it is reliable for random-intercept designs. We recommend treating its output as a conservative lower bound and using the R/lme4 power_mixed as the reference whenever random slopes or random-effect correlations matter. Data generation is identical across R and Python. This discrepancy arises solely in the Python LMM estimator.

Parameters:

Name Type Description Default
spec dict or str

A design specification (dict or path to a JSON file) with exactly one within-unit factor and a crossed design with an item unit.

required
n_sims int

Number of Monte Carlo replicates (default 50, smaller than power's 1000 because each replicate fits a mixed model).

50
alpha float

Two-sided significance level (default 0.05).

0.05
workers int

Number of local worker processes over which to spread the replicates (default 1, serial). Each replicate seeds the shared RNG from its own index, so any worker count returns results identical to a serial run.

1

Returns:

Type Description
dict

Keys: backend (the estimator used), n_sims, n_converged (how many replicates the model fit), alpha, power, n_significant, true_effect, mean_estimate, type_s, type_m. power is the proportion of significant results among the n_converged converged replicates, not among n_sims.

Raises:

Type Description
ValueError

If the spec has no item unit (power_mixed requires a crossed design).

NotImplementedError

If the design does not have exactly one within-unit factor.

Notes

Requires the mixed extra (statsmodels and pandas, imported lazily in each worker process when parallel).

Numerical core

pilotr.core.RNG

Shared cross-language random-number generator.

The combined linear congruential generator of L'Ecuyer (1988), implemented identically in R and Python so that a given seed yields the same stream in both. All intermediate products stay below 2**53, so the arithmetic is exact in IEEE-754 doubles. The draw-order contract is documented in the specification at https://github.com/pablobernabeu/pilotr/blob/main/spec/SPEC.md.

Parameters:

Name Type Description Default
seed int

Seed for the generator (coerced to a non-negative integer).

required

uniform

uniform() -> float

Return one draw from the standard uniform distribution on (0, 1).

normal

normal() -> float

Return one draw from the standard normal distribution.

normals

normals(k: int) -> list[float]

Return a list of k standard-normal draws.

pilotr.core.as241

as241(p: float) -> float

Inverse standard-normal CDF (quantile function), Wichura's (1988) Algorithm AS 241.

The PPND16 routine underlying R's qnorm, accurate to full double precision.

Parameters:

Name Type Description Default
p float

A probability in the open interval (0, 1).

required

Returns:

Type Description
float

The standard-normal quantile for p.

pilotr.core.inv_logit

inv_logit(x: float) -> float

Logistic (inverse-logit) link 1 / (1 + exp(-x)), evaluated stably for large |x|.