Skip to contents

primarycensored 1.5.2.1000

This development version adds non-parametric delay distributions, both a direct PMF over fixed bins (step CDF) and a discrete-time hazard parameterisation, with support for fitting them via fitdistdoublecens() and pcd_cmdstan_model().

New features

  • Added a non-parametric step CDF family. pdiscretestep(), ddiscretestep(), and rdiscretestep() represent a delay via a direct PMF over fixed bins, and the discrete-time hazard variant pdiscretehazard(), ddiscretehazard(), and rdiscretehazard() parameterises the same family via per-bin hazards, with conversion utilities hazards_to_pmf() and pmf_to_hazards(). See #218.
  • fitdistdoublecens() accepts distr = "discretestep" and distr = "discretehazard" through the same code path as parametric distributions, with K (the number of bins) inferred from start. Hazard priors are user-settable via prior = list(...).
  • Added a second discrete-hazard parameterisation alongside the logit random walk. In fitdistdoublecens() the hazard_model argument picks between "rw" (random walk on the logit hazards, the default) and "re" (IID logit random effects around a mean intercept, logit(h_i) = alpha + sigma * eps_i with eps_i ~ N(0, 1)).
  • Added discretehazard_start() for building the named start-value list expected by fitdistdoublecens() with distr = "discretehazard".
  • Added Stan support for the non-parametric families. dist_id = 26 is the step CDF with the PMF supplied in params and dist_id = 27 the step CDF with the hazards supplied in params. Both take params = c(boundaries, weights) of length 2 * K + 1, so dist_lcdf() and primarycensored_lpmf() evaluate them from params alone. dist_id = 28 shares the likelihood of 27 and only differs in the prior used by the package model. The primary event censored CDF is analytic for the uniform and exponential growth primaries, for any bin widths and for boundaries that start below zero.
  • The Stan model returned by pcd_cmdstan_model() fits the non-parametric families directly: 26 with a Dirichlet prior on the PMF, 27 with a Gaussian random walk on the logit hazards and 28 with IID logit random effects on the hazards. pcd_as_stan_data() accepts dist_options = list(K = ..., boundaries = ...) to carry the bin shape, and the existing priors argument carries the prior: priors$scale is the length-K Dirichlet concentration for dist_id = 26, and priors$location / priors$scale are length-2 (mean, sd) for alpha and log_sigma for dist_id = 27 and 28.
  • The pdist argument of pprimarycensored(), dprimarycensored(), and qprimarycensored() now accepts a character string, looked up via the pcd_distributions registry; passing a function still works as before.
  • pprimary is now a user-facing argument on pprimarycensored(), dprimarycensored(), qprimarycensored(), and fitdistdoublecens(). It accepts either a function or a character string naming a primary distribution in pcd_primary_distributions. When omitted, the primary CDF is looked up automatically from the registry using the "name" attribute of dprimary. Supplying both dprimary and pprimary with inconsistent names (e.g. dunif + pexpgrowth) now errors clearly.
  • Soft-deprecated dprimary_args in favour of primary_args on pprimarycensored(), dprimarycensored(), qprimarycensored(), new_pcens(), and fitdistdoublecens(). The new name reflects that the arguments are passed to both dprimary and the matching primary CDF. The deprecation uses lifecycle::deprecate_soft(), so a warning is shown for direct use and during package tests, and calls from other packages keep working quietly.
  • Primary censored CDF dispatch now follows a two-layer S3 chain on pcens objects: a specific method for a (delay, primary) pair is tried first, then a delay-only general method, then a numerical default. The analytic primary convolution path now works for any primary with a known CDF, with the primary CDF plumbed through pprimarycensored(), dprimarycensored(), and qprimarycensored() via the pprimary argument.
  • dprimarycensored() and fitdistdoublecens() now accept observations whose secondary censoring interval straddles D (left < D <= right). The upper endpoint is internally clipped to D and the likelihood becomes P(X in [left, min(right, D)] | L <= X <= D). This is a no-op when right <= D and removes the need to pad D when fitting non-parametric delays whose support reaches D. Observations with left >= D are still rejected because under truncation at D no event with latent value >= D is observable. See #312.
  • Added vignette fitting-nonparametric-delays demonstrating end-to-end non-parametric delay estimation.

primarycensored 1.5.2

New features

  • Added analytical primary censored CDFs for the generalised gamma delay distribution with a uniform primary event, in R and Stan. In R, pcens_cdf() gains methods for flexsurv::pgengamma.orig() (Stacy parameterisation, always analytical) and flexsurv::pgengamma() (Prentice parameterisation, analytical for Q > 0 and numeric otherwise). pprimarycensored() and related functions already worked with any pdist, including these, via numeric integration. In Stan, dist_lcdf() now supports dist_id = 5 (generalised gamma, parameters [shape, scale, k]) through a new gengamma_lcdf() function and primarycensored_gengamma_uniform_lcdf() provides the analytical solution used by primarycensored_lpmf() and related functions, including in pcd_cmdstan_model(). flexsurv has been added to Suggests.
  • Functions exported by other packages (for example flexsurv::pgengamma.orig()) are now identified by name when passed as pdist or dprimary, so analytical solutions are used without needing add_name_attribute().

Documentation

  • Added the generalised gamma derivation to the “Analytic solutions” vignette. The gamma and Weibull solutions are recovered as special cases.

primarycensored 1.5.1

CRAN release: 2026-06-15

This patch release fixes a performance regression introduced in 1.5.0 that slowed the Stan likelihood for positive-support delays.

Bug fixes

  • Fixed a performance regression in the Stan primarycensored_lpmf and primarycensored_lcdf functions for positive-support delays. After the lower-truncation guard was relaxed in 1.5.0 to support negative L, every likelihood evaluation for positive-support delays entered a truncation-normalisation block that cancels to a no-op but still adds gradient calculations (an exp/log_diff_exp per call), giving a roughly 30% slowdown on the likelihood block. The guard now skips this block unless there is a finite D, a strictly positive L, or a finite L on a real-support distribution, restoring 1.4.0 performance without changing results or losing the negative-support behaviour. Thanks to @sbfnk for reporting (#323).

primarycensored 1.5.0

CRAN release: 2026-06-04

This minor release extends the L (lower truncation) parameter to accept negative and -Inf values in both the R and Stan code, letting delay distributions with support below zero (e.g. normal, logistic, Cauchy, Gumbel) be used with primary censoring and fitted via fitdistdoublecens() and pcd_cmdstan_model(). The default value of L has changed from 0 to -Inf, which leaves results unchanged for distributions with non-negative support (e.g. lognormal, gamma, Weibull). It also fixes a normalisation bug in the exponential growth primary distribution and rewrites the analytical CDFs in a CDF-direct form, dropping the pracma dependency.

Breaking changes

New features

  • L may now be negative or -Inf in pprimarycensored(), dprimarycensored(), qprimarycensored(), and rprimarycensored(). This lets delay distributions with support below zero (e.g. normal, logistic, Cauchy) be used with primary censoring. L = -Inf is the sentinel for “no left truncation”; any finite L left-truncates the distribution at L. (#267)
  • The Stan functions and pcd_as_stan_data() mirror the R-side handling of L: negative and -Inf values are accepted, and a missing start_relative_obs_time column defaults to -Inf. pcd_cmdstan_model() now accepts negative observed delays and fully-negative truncation windows, letting distributions with support on the reals (e.g. logistic, Cauchy, Gumbel) be fitted. (#313)
  • The dist_id upper bound in pcens_model.stan has been raised from 17 to 25, exposing every delay distribution that dist_lcdf already dispatches (Normal, Double Exponential, Pareto, scaled inverse chi-square, Student’s t, Uniform, von Mises) through pcd_cmdstan_model(). (#314)

Documentation

  • Added a CDF-direct form of the primary-censored analytic solutions to the “Why it works” and “Analytic solutions” vignettes alongside the existing survival-function form.
  • Added a “Fitting delay distributions with negative support” vignette that walks through estimating a logistic-distributed serial interval with both fitdistdoublecens() and pcd_cmdstan_model() from doubly-censored, right-truncated samples that include negative observed delays.

Bug fixes

  • Fixed incorrect normalisation in dexpgrowth(), pexpgrowth(), and their Stan equivalents (expgrowth_pdf, expgrowth_lpdf, expgrowth_cdf, expgrowth_rng) when min is non-zero. The PDF and CDF formulas contained a stray exp(-r * min) factor from using exp(r * (x - min)) instead of exp(r * x). The Stan RNG had a compensating xmin + offset. The bug did not affect results when min = 0 (the default and only value used within the package’s primary censoring functions). Thanks to @TimTaylor for reporting (#290).

Internal

  • Rewrote the analytical primary-censored CDFs (Gamma, Log-Normal, Weibull with uniform primary) in R and Stan to use a CDF-direct algebraic form, \(F_{S_+}(d) = [d F_T(d) - q F_T(q) - E(\tilde F(d) - \tilde F(q))]/w_P\). In Stan this unifies the q = 0 and q > 0 code paths (single algebraic expression, better for NUTS), the outer log_diff_exp ordering is now mathematically guaranteed, and the Gamma case uses the incomplete-gamma recursion \(P(k{+}1, y) = P(k, y) - y^k e^{-y}/\Gamma(k{+}1)\) to halve gamma_lcdf evaluations. Behaviour and tests are unchanged.
  • Replaced pracma::gammainc with stats::pgamma in the Weibull g() helper, dropping the pracma dependency. The previous pwindow > 3 fallback to numeric integration (and the internal overflow guard) is no longer needed — the base R implementation is stable across the full parameter range. Closes #127.

primarycensored 1.4.0

CRAN release: 2026-03-06

This major release adds left-truncation support via the L parameter, enabling distributions to be truncated over [L, D] rather than just [0, D]. It also removes deprecated functionality that was soft-deprecated in version 1.1.0 and removes the lifecycle and rlang packages from dependencies.

Breaking changes

  • Removed deprecated pdist_name and dprimary_name arguments from pprimarycensored(), dprimarycensored(), new_pcens(), and fitdistdoublecens(). Use add_name_attribute() on the pdist and dprimary functions instead to enable analytical solutions.
  • Removed deprecated support for passing numeric values to the pwindow and D arguments in fitdistdoublecens(). These must now be column names in censdata.
  • Removed lifecycle and rlang packages from dependencies.
  • R functions now include an L parameter before D in their signatures. If you were using positional arguments for D (e.g., pprimarycensored(x, pdist, pwindow, 10)), you must now use named arguments (e.g., pprimarycensored(x, pdist, pwindow, D = 10)). The affected functions are dprimarycensored(), pprimarycensored(), rprimarycensored(), and qprimarycensored(). (#63)
  • Stan functions now include an L parameter for lower truncation, placed before D. This affects primarycensored_lpmf, primarycensored_lcdf, primarycensored_cdf, primarycensored_pmf, and all vectorized variants. Update your Stan code to include the new parameter: primarycensored_lpmf(d | dist_id, params, pwindow, d_upper, L, D, primary_id, primary_params). (#63)

New features

  • Added dependencies argument to pcd_load_stan_functions() that automatically resolves and includes all functions that the requested functions depend on. When TRUE, dependencies are included in topological order (dependencies before functions that use them). (#171)
  • Added pcd_stan_function_deps() to query the dependency graph of Stan functions, returning all dependencies for a given function in topological order. (#171)
  • Added 8 distributions to pcd_distributions that were previously only available in Stan: normal, inverse chi-square, double exponential, pareto, scaled inverse chi-square, student t, uniform, and von Mises (IDs 18–25). These are now accessible via pcd_stan_dist_id(). (#277)
  • Added left-truncation support via the L parameter to all primary censored distribution functions (dprimarycensored(), pprimarycensored(), rprimarycensored(), qprimarycensored()) and Stan functions. The L parameter specifies the minimum delay (lower truncation point), enabling distributions to be truncated over [L, D] rather than just [0, D]. This is useful for generation intervals and other settings where delays below a threshold cannot occur. Defaults to L = 0 for backward compatibility. (#63)

Bug fixes

  • Fixed expgrowth_lpdf Stan function to support negative growth rates. Previously, log(r) returned NaN for r < 0. Now uses log(abs(r)) and log(abs(...)) for the denominator. (#276)
  • Fixed Stan dist_lcdf distribution ID mapping to match R’s pcd_distributions table. Previously, most distribution IDs were mismatched between R and Stan (e.g. pcd_stan_dist_id("weibull") returned 3 but Stan’s dist_lcdf used ID 3 for the Normal distribution). Only lognormal (1), gamma (2), and exponential (4) were correct. This affected the ODE numerical integration path for all mismatched distributions. (#277)
  • Renamed min and max parameters to xmin and xmax in Stan functions (expgrowth_pdf, expgrowth_lpdf, expgrowth_cdf, expgrowth_lcdf, expgrowth_rng, primary_lpdf) to avoid conflicts with Stan built-in functions. CmdStan 2.38.0 now strictly enforces reserved keyword restrictions when exposing Stan functions to R. (#258)

Documentation

  • Updated vignette titles and section headers to use sentence case consistently. (#273)

primarycensored 1.3.0

CRAN release: 2025-12-01

This minor release improves documentation for fitdistdoublecens() and adds learning objective sections to vignettes. It also fixes floating-point precision issues in dprimarycensored() and adds bounds checking to CDF methods.

Documentation

  • Improved documentation for fitdistdoublecens():
    • Expanded function description to explain primary censoring, secondary censoring, and truncation.
    • Added detailed @details sections explaining how distribution names are resolved (e.g., "gamma" uses dgamma() and pgamma()), and what the function does internally.
    • Enhanced distr parameter documentation with examples and guidance on custom distributions.
  • Added “What you will learn” and “How you might adapt this vignette” sections to both the fitdistrplus and Stan fitting vignettes to help users understand learning objectives and adapt the examples for their own data.

Package

Bug fixes

  • Fixed an issue where dprimarycensored() could return very small negative values (e.g., -2.2e-16) due to floating-point precision when computing PMF as CDF differences. PMF values are now clamped to be non-negative. (#238)
  • Added bounds checking to all pcens_cdf() methods to ensure CDF values are always in [0, 1], complementing the existing upper bound check with a lower bound check.

primarycensored 1.2.0

CRAN release: 2025-06-09

This minor release adds quantile functions for primary censored distributions and enhances the fitdistdoublecens() function to support varying primary censoring windows and truncation times. The release also improves documentation, particularly the Stan reference, making it easier for users to navigate and work with the Stan code.

Package

  • Added new functions to compute quantiles of the primary censored distribution:
    • pcens_quantile(): Core implementation using numerical optimisation to find quantiles by inverting the CDF. The implementation allows for analytical solutions to be added in future versions using the same interface as pcens_cdf().
    • qpcens() and qprimarycensored(): Convenient wrapper functions that provide alternative interfaces to pcens_quantile().
  • Added support to fitdistdoublecens() to allow for varying primary censoring windows and truncation times. As part of this refactor the interface has also been improved to allow for more flexible data input.

Documentation

  • Removed authorship from vignettes.
  • Updated the fitdistrplus vignette to use more complex data where the relative observation time is not constant. Also removed the note that the fitdistdoublecens() function is limited to a single primary censoring windows and truncation time as this is no longer the case.
  • The Stan Reference has been enhanced to make it easier to navigate the Stan code.

primarycensored 1.1.0

CRAN release: 2025-02-10

This minor release improves the documentation and the internal system used to automatically discover analytical solutions. It also adds lookups for supported supported distributions and tooling for working with these lookups. This makes it easier for package developers using primarycensored and also makes it easier to work with the Stan likelihood functions by improving the discoverability of the distribution functions. Minor bugs were also fixed.

Package

  • Updated the CI so that stan code is also tested on Windows and Mac. This is to ensure that the stan code is compatible with these platforms and in response to a CI bug in epidist.
  • Revised approach to automatic discovery of distribution functions. This soft deprecates the pdist_name and dprimary_name arguments throughout. Users wishing to pass distribution names (i.e. to potentially leverage analytical solutions) are advised to use the newly introduced add_name_attribute() function. Adds transient dependency on lifecycle and rlang packages. See #188 by @pearsonca.
  • Added pcd_stan_dist_id() to allow for discovery of distribution IDs for Stan models.
  • Added pcd_dist_name() to allow for discovery of distribution names for R functions as needed for add_name_attribute().
  • Added documentation to suggest the use of methods(pcens_cdf) to find analytical solutions.
  • Added new data sets pcd_distributions and pcd_primary_distributions to document the distributions supported by primarycensored.

Documentation

  • Added a CRAN downloads badge to the README.
  • Corrected how to specify an empty array in the docs of primarycensored_lcdf().
  • All documentation was reviewed and updated to enhance readability and clarity.

Bug fixes

  • Added a missing @family tag to the pcens functions. This omission resulted in the Weibull analytical solution not being visible in the package documentation.
  • Added precalculation of vector sizes to the primarycensored_cdf() stan function, avoiding errors on some platforms due to narrowing conversions in aggregate initialisation.
  • Changed D to be of type real in pcens_model.stan in order to support infinite relative_obs_time.
  • Switched to using num_elements() over size() in all stan code to resolve compilation issues on some platforms as reported by @sbfnk.

primarycensored 1.0.0

CRAN release: 2024-10-28

This is the first major release of primarycensored and has been submitted to CRAN.

Package

  • Fix internal package misspelling of primary_lpdf.
  • Move to “stable” lifecycle status.
  • Added rhub checks to the Github Actions workflow.
  • Added dependencies: "hard" to the R-CMD-check workflow to ensure checks pass without optional dependencies.
  • Improved handling of examples that use optional dependencies.
  • Check all URLs for redirects.
  • Ensure that all functions have documented return values.

primarycensored 0.6.0

This release renames the package to primarycensored from primarycensoredist and also renames many of the functions to remove the dist in their name. This was done to make the package name and the functions more consistent and to remove the need to use the dist suffix. It also aligns it with the new PrimaryCensored.jl package in our Julia ecosystem.

Aside from name changes, this release also adds an analytical solution for the weibull distribution with uniform primary censoring, removes the need to assign functions to the global environment for fitdistdoublecens() by using withr, and adds a check_truncation() function to check if the truncation time is larger than the maximum observed delay. This is used in fitdistdoublecens() and pcd_as_stan_data() to ensure that the truncation time is appropriate to maximise computational efficiency.

Package

  • Removed the need to assign functions to the global environment for fitdistdoublecens() by using withr.
  • Added a check_truncation() function to check if the truncation time is larger than the maximum observed delay. This is used in fitdistdoublecens() and pcd_as_stan_data() to ensure that the truncation time is appropriate to maximise computational efficiency.
  • pcd_as_cmdstan_data() has been renamed to pcd_as_stan_data() to better reflect that it is used for Stan models in general rather than just the CmdStan models.
  • The stan code has been refactored into a folder of functions within the current stan folder and the stan model has been moved into the stan folder. All paths to the stan code have been updated to reflect this.
  • Added R and stan implementations of the primary censored cdf for the weibull distribution with uniform primary censoring.
  • The package has been renamed to primarycensored as have all functions that use “dist” in their name.

Documentation

  • Simplified the “Analytic solutions” vignette by removing verbose derivation details.
  • Added links between vignettes to make it easier to navigate the documentation.
  • Added explicit usage of pdist, dprimary, rdist, and rprimary arguments in the getting started vignette to make it easier to link to mathematical details.
  • Fixed error in “Analytic solutions” vignette where the Weibull density was not being treated as zero for negative delays.
  • Split “Why it works” vignette into two separate vignettes, “Why it works” and “Analytic solutions for censored delay distributions”.

primarycensored 0.5.0

This release adds a new {touchstone} based benchmark suite to the package. It also adds a new “How it works” vignette which aims to give the reader more details into how the primary censored distributions work.

As part of the “How it works” we (@SamuelBrand1) found analytical solutions for the gamma, lognormal, and weibull distributions with uniform primary censoring. These are now implemented for the lognormal and gamma distributions in the R and stan code providing significant speedups to the fitting process (~10-20 times faster). The Weibull will be added in the next release.

Package

  • Add {touchstone} based benchmarks for benchmarking R utility functions, and fitting the stan and fitdistplus models.
  • Added a “How it works” vignette.
  • Added R infrastructure for analytical solutions via the primarycensored S3 class.
  • Added Weibull analytical solution to “How it works” vignette.
  • Added analytical solutions for the gamma and lognormal distributions with uniform primary censoring to both the R and stan code.
  • Added numerical protection to ensure that CDFs for delays greater than the maximum truncation are exactly 1.

primarycensored 0.4.0

In this release, we have added a new package stan model for fitting distributions using the cmdstanr package. We have also added a new function fitdistdoublecens() to allow for fitting of double censored and truncated data using the fitdistrplus package. As well as these functionality improvements this release focuses on improving the stability of the stan model and improving the speed of the primarycensored_ode function.

Package

  • Added a new function fitdistdoublecens() to allow for fitting of double censored and truncated data using the fitdistrplus package.
  • Added low level tests for the Stan primarycensored_ode function.
  • Rephrased the stan code to use a ODE solver rather than a numerical integration method. This allows for much faster and more stable computation of the likelihood
  • Added a CmdStan model for fitting distributions using the cmdstanr package.
  • Added helpers functions for working with the new CmdStan model and added an example to the vignette.
  • Added parameter recovery tests for the new CmdStan model which tests the primarycensored_lpmf function when used with NUTS based fitting.

primarycensored 0.3.0

This release fixes and improves truncation handling across the code base. It also adds a new vignette showcasing how to use the primarycensored and fitdistrplus packages together to fit distributions.

Package

  • Updated the approach to truncation to be outside the primary censored distribution integral.
  • Improved tests that compare random sampling and probability mass/density functions between R and Stan.
  • Improved cross-testing between R and Stan implementations of the primary censored distributions.
  • Worked on improving the stability of the primarycensored_lpmf when used for NUTS based fitting (i.e. in Stan).

Documentation

  • @athowes improved the getting started vignette by catching a few grammar errors and simplifying language.
  • Added a new vignette showcasing how to use the primarycensored and fitdistrplus packages together to fit distributions.

primarycensored 0.2.0

This release puts in place initial documentation and vignettes. It also includes a new primary censored distribution interface to allow for non-secondary event censored distributions. Development of this release as identified some numerical issues in the gradient evaluations for the primary censored distributions which may lead to breaking interface changes in 0.3.0 for the Stan code.

Package

  • Added support for swindow = 0 to rprimarycensored to allow for non-secondary event censored distributions.
  • Adapted rprimarycensored so that truncation is based on the primary censored distribution before secondary events are censored. This better matches the generative process.
  • Added a new Stan interface tool to enable finding which files functions are implemented in the Stan code.

Documentation

  • Added a getting started vignette.
  • Added a vignette showcasing how to use the package Stan code with cmdstanr.
  • Added a vignette showcasing how to fit distributions using the cmdstanr package.

primarycensored 0.1.0

This is the initial primarycensored release and includes R and stan tools for dealing with potentially truncated primary event censored delay distributions. We expect all current features to work but the UI may change as the package matures over the next few versions.

Package

  • Added package skeleton.
  • Added checking input functions.
  • Added stan functions for primary censored and truncated distributions.
  • Added R functions for primary censored and truncated distributions.
  • Add R function to facilitate working with the Stan code.
  • Added tests for primary censored and truncated distributions.
  • Added tests to compare R and Stan implementations.
  • Added tests for the R functions that facilitate working with the Stan code.
  • Resolved R CMD check errors, warnings and notes.
  • Added a hexsticker.
  • Added vignette skeletons in preparation for 0.2.0 release.