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(), andrdiscretestep()represent a delay via a direct PMF over fixed bins, and the discrete-time hazard variantpdiscretehazard(),ddiscretehazard(), andrdiscretehazard()parameterises the same family via per-bin hazards, with conversion utilitieshazards_to_pmf()andpmf_to_hazards(). See #218. -
fitdistdoublecens()acceptsdistr = "discretestep"anddistr = "discretehazard"through the same code path as parametric distributions, withK(the number of bins) inferred fromstart. Hazard priors are user-settable viaprior = list(...). - Added a second discrete-hazard parameterisation alongside the logit random walk. In
fitdistdoublecens()thehazard_modelargument 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_iwitheps_i ~ N(0, 1)). - Added
discretehazard_start()for building the named start-value list expected byfitdistdoublecens()withdistr = "discretehazard". - Added Stan support for the non-parametric families.
dist_id = 26is the step CDF with the PMF supplied inparamsanddist_id = 27the step CDF with the hazards supplied inparams. Both takeparams = c(boundaries, weights)of length2 * K + 1, sodist_lcdf()andprimarycensored_lpmf()evaluate them fromparamsalone.dist_id = 28shares the likelihood of27and 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:26with a Dirichlet prior on the PMF,27with a Gaussian random walk on the logit hazards and28with IID logit random effects on the hazards.pcd_as_stan_data()acceptsdist_options = list(K = ..., boundaries = ...)to carry the bin shape, and the existingpriorsargument carries the prior:priors$scaleis the length-KDirichlet concentration fordist_id = 26, andpriors$location/priors$scaleare length-2(mean, sd)foralphaandlog_sigmafordist_id = 27and28. - The
pdistargument ofpprimarycensored(),dprimarycensored(), andqprimarycensored()now accepts a character string, looked up via thepcd_distributionsregistry; passing a function still works as before. -
pprimaryis now a user-facing argument onpprimarycensored(),dprimarycensored(),qprimarycensored(), andfitdistdoublecens(). It accepts either a function or a character string naming a primary distribution inpcd_primary_distributions. When omitted, the primary CDF is looked up automatically from the registry using the"name"attribute ofdprimary. Supplying bothdprimaryandpprimarywith inconsistent names (e.g.dunif+pexpgrowth) now errors clearly. - Soft-deprecated
dprimary_argsin favour ofprimary_argsonpprimarycensored(),dprimarycensored(),qprimarycensored(),new_pcens(), andfitdistdoublecens(). The new name reflects that the arguments are passed to bothdprimaryand the matching primary CDF. The deprecation useslifecycle::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
pcensobjects: 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 throughpprimarycensored(),dprimarycensored(), andqprimarycensored()via thepprimaryargument. -
dprimarycensored()andfitdistdoublecens()now accept observations whose secondary censoring interval straddlesD(left < D <= right). The upper endpoint is internally clipped toDand the likelihood becomesP(X in [left, min(right, D)] | L <= X <= D). This is a no-op whenright <= Dand removes the need to padDwhen fitting non-parametric delays whose support reachesD. Observations withleft >= Dare still rejected because under truncation atDno event with latent value>= Dis observable. See #312. - Added vignette
fitting-nonparametric-delaysdemonstrating 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 forflexsurv::pgengamma.orig()(Stacy parameterisation, always analytical) andflexsurv::pgengamma()(Prentice parameterisation, analytical forQ > 0and numeric otherwise).pprimarycensored()and related functions already worked with anypdist, including these, via numeric integration. In Stan,dist_lcdf()now supportsdist_id = 5(generalised gamma, parameters[shape, scale, k]) through a newgengamma_lcdf()function andprimarycensored_gengamma_uniform_lcdf()provides the analytical solution used byprimarycensored_lpmf()and related functions, including inpcd_cmdstan_model().flexsurvhas been added toSuggests. - Functions exported by other packages (for example
flexsurv::pgengamma.orig()) are now identified by name when passed aspdistordprimary, so analytical solutions are used without needingadd_name_attribute().
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_lpmfandprimarycensored_lcdffunctions for positive-support delays. After the lower-truncation guard was relaxed in 1.5.0 to support negativeL, every likelihood evaluation for positive-support delays entered a truncation-normalisation block that cancels to a no-op but still adds gradient calculations (anexp/log_diff_expper call), giving a roughly 30% slowdown on the likelihood block. The guard now skips this block unless there is a finiteD, a strictly positiveL, or a finiteLon 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
- The default value of
Linpprimarycensored(),dprimarycensored(),qprimarycensored(),rprimarycensored(), andpcens_quantile()has changed from0to-Inf.fitdistdoublecens()now treats a missingLcolumn asL = -Infto match. For delay distributions with support on the non-negative reals (e.g. lognormal, gamma, Weibull)F_cens(0) = 0, so the new default leaves results unchanged. Callers that relied on the implicit left truncation at0(for example to truncate signed-support delays such aspnorm) must now passL = 0explicitly (or add anLcolumn infitdistdoublecens()). (#267)
New features
-
Lmay now be negative or-Infinpprimarycensored(),dprimarycensored(),qprimarycensored(), andrprimarycensored(). This lets delay distributions with support below zero (e.g. normal, logistic, Cauchy) be used with primary censoring.L = -Infis the sentinel for “no left truncation”; any finiteLleft-truncates the distribution atL. (#267) - The Stan functions and
pcd_as_stan_data()mirror the R-side handling ofL: negative and-Infvalues are accepted, and a missingstart_relative_obs_timecolumn 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_idupper bound inpcens_model.stanhas been raised from17to25, exposing every delay distribution thatdist_lcdfalready dispatches (Normal, Double Exponential, Pareto, scaled inverse chi-square, Student’s t, Uniform, von Mises) throughpcd_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()andpcd_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) whenminis non-zero. The PDF and CDF formulas contained a strayexp(-r * min)factor from usingexp(r * (x - min))instead ofexp(r * x). The Stan RNG had a compensatingxmin +offset. The bug did not affect results whenmin = 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 = 0andq > 0code paths (single algebraic expression, better for NUTS), the outerlog_diff_expordering 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 halvegamma_lcdfevaluations. Behaviour and tests are unchanged. - Replaced
pracma::gammaincwithstats::pgammain the Weibullg()helper, dropping thepracmadependency. The previouspwindow > 3fallback 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_nameanddprimary_namearguments frompprimarycensored(),dprimarycensored(),new_pcens(), andfitdistdoublecens(). Useadd_name_attribute()on thepdistanddprimaryfunctions instead to enable analytical solutions. - Removed deprecated support for passing numeric values to the
pwindowandDarguments infitdistdoublecens(). These must now be column names incensdata. - Removed
lifecycleandrlangpackages from dependencies. - R functions now include an
Lparameter beforeDin their signatures. If you were using positional arguments forD(e.g.,pprimarycensored(x, pdist, pwindow, 10)), you must now use named arguments (e.g.,pprimarycensored(x, pdist, pwindow, D = 10)). The affected functions aredprimarycensored(),pprimarycensored(),rprimarycensored(), andqprimarycensored(). (#63) - Stan functions now include an
Lparameter for lower truncation, placed beforeD. This affectsprimarycensored_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
dependenciesargument topcd_load_stan_functions()that automatically resolves and includes all functions that the requested functions depend on. WhenTRUE, 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_distributionsthat 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 viapcd_stan_dist_id(). (#277) - Added left-truncation support via the
Lparameter to all primary censored distribution functions (dprimarycensored(),pprimarycensored(),rprimarycensored(),qprimarycensored()) and Stan functions. TheLparameter 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 toL = 0for backward compatibility. (#63)
Bug fixes
- Fixed
expgrowth_lpdfStan function to support negative growth rates. Previously,log(r)returned NaN forr < 0. Now useslog(abs(r))andlog(abs(...))for the denominator. (#276) - Fixed Stan
dist_lcdfdistribution ID mapping to match R’spcd_distributionstable. Previously, most distribution IDs were mismatched between R and Stan (e.g.pcd_stan_dist_id("weibull")returned 3 but Stan’sdist_lcdfused 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
minandmaxparameters toxminandxmaxin 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
@detailssections explaining how distribution names are resolved (e.g.,"gamma"usesdgamma()andpgamma()), and what the function does internally. - Enhanced
distrparameter 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
- Added tests to verify that
pcd_as_stan_data()andfitdistdoublecens()correctly handle data frames with additional columns beyond those required. (#213)
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 aspcens_cdf(). -
qpcens()andqprimarycensored(): Convenient wrapper functions that provide alternative interfaces topcens_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
fitdistrplusvignette to use more complex data where the relative observation time is not constant. Also removed the note that thefitdistdoublecens()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_nameanddprimary_namearguments throughout. Users wishing to pass distribution names (i.e. to potentially leverage analytical solutions) are advised to use the newly introducedadd_name_attribute()function. Adds transient dependency onlifecycleandrlangpackages. 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 foradd_name_attribute(). - Added documentation to suggest the use of
methods(pcens_cdf)to find analytical solutions. - Added new data sets
pcd_distributionsandpcd_primary_distributionsto document the distributions supported byprimarycensored.
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
@familytag to thepcensfunctions. 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
Dto be of type real inpcens_model.stanin order to support infiniterelative_obs_time. - Switched to using
num_elements()oversize()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
rhubchecks to theGithub Actionsworkflow. - Added
dependencies: "hard"to theR-CMD-checkworkflow 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 usingwithr. - Added a
check_truncation()function to check if the truncation time is larger than the maximum observed delay. This is used infitdistdoublecens()andpcd_as_stan_data()to ensure that the truncation time is appropriate to maximise computational efficiency. -
pcd_as_cmdstan_data()has been renamed topcd_as_stan_data()to better reflect that it is used forStanmodels in general rather than just theCmdStanmodels. - The stan code has been refactored into a folder of functions within the current
stanfolder and thestanmodel has been moved into thestanfolder. 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
primarycensoredas 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, andrprimaryarguments 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 thestanandfitdistplusmodels. - Added a “How it works” vignette.
- Added R infrastructure for analytical solutions via the
primarycensoredS3 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
Randstancode. - 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 thefitdistrpluspackage. - Added low level tests for the Stan
primarycensored_odefunction. - 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
CmdStanmodel for fitting distributions using thecmdstanrpackage. - Added helpers functions for working with the new
CmdStanmodel and added an example to the vignette. - Added parameter recovery tests for the new
CmdStanmodel which tests theprimarycensored_lpmffunction 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_lpmfwhen used for NUTS based fitting (i.e. in Stan).
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 = 0torprimarycensoredto allow for non-secondary event censored distributions. - Adapted
rprimarycensoredso 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.
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.0release.
