Release Notes for Pumas 2.9.0

Pumas

Stricter data handling and reserved names

Several changes in this release can cause data or models that previously ran to now error early. This is intended and protects you from silently wrong results:

  • Last-observation-carried-forward (LOCF) and next-observation-carried-backward (NOCB) covariate interpolation are no longer extrapolated past the observed covariate range. LOCF cannot produce a value before the first observed covariate time, and NOCB cannot produce a value after the last observed covariate time. A subject whose covariate is missing at that boundary time now errors when constructed. A model that evaluates the covariate outside the observed range errors during simulation or fitting instead of silently extrapolating.
  • events is now reserved as a model variable name. Models that define a variable called events in any block will error at model definition time and need to rename that variable.
  • read_pumas now requires the dose-related columns amt, rate, ss, ii, and addl to be given on dose rows and to be missing or zero on all other rows. Data that fills a dose column on observation rows, or leaves it blank on a dose row, is rejected with an error that names the offending column.
  • The tabular output of simulations requires a vector-valued variable in @vars, @derived, or @observed to provide exactly one value per observation time point. A vector whose length happened to match the number of doses was previously spread over the dose intervals, which could invent a time-stamping the user never chose.

Features and improvements

Experimental Features

  • Add experimental support for finite mixture models, where a population is described as a mixture of submodels that share parameters by name and the mixture probabilities are estimated. Pumas.Experimental.PumasMixtureModel supports fit with FOCE, LaplaceI, FO, and NaivePooled, predict with or without a fit, simobs, and the classification diagnostics responsibilities, subpopulation, and icl. A parameter shared by the submodels can be declared with a prior as well as with a domain, as long as every submodel declares it identically. The standard errors and confidence intervals of the mixture probabilities are on the probability scale and cover every component. Unsupported combinations are rejected with informative errors.
  • Add a new implementation of VPC, NPDE, and EWRES that computes the diagnostics from observed and pre-simulated DataFrames, so the expensive simulations can be reused when the binning, bandwidth, stratification, or transform is changed. It supports continuous, discrete, and censored outcomes, binned and binless summaries with per-stratum settings, and prediction correction, and it requires an explicit choice of the axes, the number of replicates, and the bandwidth instead of guessing defaults. Nothing is exported from the Pumas.Experimental submodule, so the functions are called qualified, for example Pumas.Experimental.vpc, Pumas.Experimental.npde, and Pumas.Experimental.vpc_setup; EWRES is returned as a column of the npde result. The existing vpc is unchanged.
  • Add sampler selection for the experimental MCEM estimation method, so the importance-sampling proposal can be chosen (for example a Laplace-approximation proposal with Student's t tails) rather than always sampling from the prior.
  • Support general error distributions in MCEM. The M-step was restricted to additive Gaussian error with constant variance; it now handles the error distributions Pumas supports, with fast sufficient-statistic paths for the Normal families, ProportionalGamma, and the multivariate Gaussian error models.
  • Improve the handling of non-finite likelihoods encountered during MCEM fits.
  • Parallelize the MCEM M-step across independent parameter blocks and use load balancing in the multithreaded sampling step.

Features

  • Add the ProportionalGamma error distribution, parameterized by a mean and a constant coefficient of variation, for use in @derived. It is supported under FOCE, LaplaceI, NaivePooled, and MCEM; FO rejects it with an informative error.
  • Add OrderedVectorDomain for parameters constrained to be ordered (monotonically increasing) vectors, such as the cut points (logits) in an OrderedLogit model.
  • Add SimplexDomain(n) for parameters that are probability vectors of length n, with non-negative entries that sum to one, such as the mixture probabilities of a PumasMixtureModel. Its default initial value is the uniform vector. vcov, coeftable and stderror report all n entries, so vcov is singular, and dof counts the n - 1 free ones.
  • Support BernoulliLogit observations under FOCE. Previously a FOCE fit of a BernoulliLogit dependent variable raised an ArgumentError even though LaplaceI, NaivePooled, and SAEM supported it.
  • Support an η-dependent shape parameter α for Gamma error models under FOCE. Previously only the scale could depend on the random effects, and a Gamma model whose shape depended on η would error.
  • Add support for marginalizing missing observations with the MvLogNormal, MvTDist, and MvNormalCanon multivariate error models. Previously only MvNormal was supported and the others raised an error when any element of an observation was missing.
  • Accept Catalyst reaction syntax directly in @dynamics, so reactions are written in the same block as ODE equations rather than in a separate @reactions block.
  • Store the full derived distributions in the output of predict, not just their means, and emit per-category probability columns in DataFrame representation of predictions for categorical-type models (for example OrderedLogit, Categorical, Binomial, and FiniteMarkov). This makes the full predictive distribution available for diagnostics.
  • Add dynamics_names to obtain the names of a model's dynamic variables. The names match the dynamics columns of the DataFrames produced from simobs, predict, and inspect results.
  • Add an ss_states option to control which dynamical states must reach steady state during steady-state dosing. A state such as a cumulative AUC has no steady state, so a model containing one could not be used with steady-state dosing at all. Excluded states are held at their pre-steady-state values.
  • Support a steady-state dose record at the same time as other dose records. Records at the same time take effect one after another in data set order, each acting on the state the previous one left, which matches NONMEM. read_pumas and DosageRegimen accepted such data before, but simulating or fitting it raised an error.
  • Add a cse option to @options, controlling whether common subexpressions in the generated @dynamics code are eliminated. The default true can make models with repeated subexpressions in their dynamics faster to simulate.
  • Support stratified η-shrinkage through a stratify_by keyword on ηshrinkage, computing shrinkage separately within each stratum defined by subject-constant covariates.
  • Add CovariateSelection.All to compare all possible covariate models in covariate_select.
  • Add loglikelihood and dof columns to the DataFrame of covariate_select output, and support constructing a DataFrame directly from covariate_select output.
  • Add samples_table to obtain a table of parameter samples from Bootstrap, SIR, and MarginalMCMC inference results. The per-sample log-likelihoods of Bootstrap and SIR results are now retained, so diagnostics can use them without re-evaluating the likelihood.
  • Add a description column to coeftable, filled from the parameter descriptions declared in @metadata, with the parameter name as the fallback.
  • Base the SIR procedure on any inference result. The covariance matrix of the initial proposal distribution can now be taken from a Bootstrap, MarginalMCMC, or previous SIR result rather than only the asymptotic one, and infer(fpm, sir; proposal_covariance = ...) accepts a parameter-labelled covariance matrix supplied by the user.
  • Fit SIR proposal distributions on an unconstrained parameter scale by default, selectable with SIR(; proposal_scale = ...), so no draws are rejected against the parameter domains, and optionally reshape each marginal with a Yeo-Johnson transformation using SIR(; proposal_shape = YeoJohnson()). Results of a multi-iteration SIR procedure can differ from earlier releases.
  • Support EnsembleSplitThreads in marginal likelihood calculations, allowing distributed computing where each worker further parallelizes its work across threads.
  • Support random effects input in icoef and dosecontrol.

Improvements

  • Select the quantities gsa analyzes with a post-processing function instead of a list of variable names, so the targets are no longer restricted to model variables. The function is the first argument, as in gsa((gen, obs) -> (; auc = ...), model, population, params, method, ...). Selecting the variables by name still works but is deprecated.
  • Run gsa multithreaded by default instead of serially.
  • elpd, p_eff, and psis_ic now return the sum of the pointwise log predictive densities over the held-out splits where they previously returned the mean. A value obtained with 2.8 equals the corresponding 2.9 value divided by the number of held-out splits. PSISCrossvalidation also no longer discards problematic splits by default, since filter_nans now defaults to false and pareto_shape_threshold to Inf.
  • Report the per-category probabilities of probstable in columns named nameₖ_ipred instead of name_iprobK, and stop expanding Bernoulli variables.
  • Report missing instead of 0 in the dose-related columns amt, rate, duration, ss, and ii on the non-dose rows of the DataFrames built from subjects, populations, simulations, predictions, and inspections.
  • Use Hager-Zhang (Optim.HagerZhang) as the default line search in fit instead of backtracking (Optim.BackTracking). Both the optimization path and the parameter estimates at convergence can differ from earlier releases.
  • Bayesian MCMC now draws the full requested number of samples by default. The ess_per_chain target that armed effective-sample-size–based early stopping now defaults to infinity, so sampling no longer stops short of nsamples on near-deterministic models. Set ess_per_chain to a finite value to opt back into early stopping.
  • Report Bayesian sampling progress as structured progress events, so it is displayed by VS Code instead of Pumas drawing its own terminal progress bar. With verbose = true, five HMC diagnostics are shown during sampling: acceptance rate, tree depth, step size, whether the transition diverged, and the log posterior density.
  • Make the directional-derivative calculations and asymptotic infer reproducible across different parallelizations by using a deterministic order of summation for the objective function and its gradients.
  • Make BayesMCMC and MarginalMCMC draw the same samples for a given rng whether the chains run serially or in parallel. The serial path drew a different random stream, so the samples depended on the number of threads of the machine. Samples drawn with EnsembleSerial() or on a single thread differ from earlier releases.
  • Extend directional-derivative support to FO, NaivePooled, and MAP, improving the performance of gradient-based estimation for these methods.
  • Speed up the derivative calculations of FOCE and LaplaceI.
  • Speed up fits of stiff models with many dynamical variables. The stiff solver of the default AutoVern7(Rodas5P()) now uses LUFactorization instead of GenericLUFactorization for its linear solves. In a benchmark of a stiff model with 16 dynamical variables, FO and FOCE fits took 0.5 to 0.6 times as long. In the same benchmark, simobs took 1.05 to 1.2 times as long for 5 to 29 dynamical variables. Models with fewer than 5 dynamical variables are unaffected. Log-likelihoods can differ slightly from earlier releases because the solver takes different steps.
  • Make the LaplaceI objective of models defined with @emmodel independent of the number of threads, so fits no longer depend on the machine they run on, and support EnsembleDistributed and EnsembleSplitThreads in fit and loglikelihood for such models.
  • Balance the load of parallel simobs by splitting the simulations into more blocks than there are workers, so a worker that finishes early takes on further work instead of idling.
  • Multithread several diagnostics functions and avoid unnecessary empirical-Bayes-estimate calculations, speeding up post-fit diagnostics.
  • Break ties between equally common candidate nodes of vpc by value. They were ranked in dictionary iteration order, which is not stable across Julia versions. The default nodes, and a VPC computed on them, can differ from earlier releases.
  • Skip the η-shrinkage calculation for random effects with a covariate dependency instead of raising an error, so shrinkage can be reported for the remaining random effects.
  • Ignore numerical errors raised during optimization of the empirical Bayes estimates rather than aborting, improving robustness during fitting.
  • Keep the information matrices that were computed before a covariance calculation failed, so a failed vcov or infer reports what was already available instead of discarding it.
  • Report every entry of a ZeroSumDomain parameter, including the last one, which the others determine, in vcov, coeftable, stderror, the displayed fit, and the columns of Chains. vcov(fpm) and vcov(infer(fpm)) gain one row and column per such parameter and are singular, so code that inverts or factorizes them needs updating. dof counts only the free entries. simobs(fpm, vcov), MvNormal(model, means, vcov), and the proposal_covariance keyword of infer(fpm, SIR(...)) take a covariance in the same layout.

Documentation and error messages

  • Add docstrings for FO, FOCE, and LaplaceI, and improve the docstrings of NaivePooled and SAEM.
  • Improve the error message shown when the initial log-likelihood is non-finite, and report the problematic subject IDs when the initial gradient is non-finite.
  • Report an ArgumentError before any sampling when an SIR iteration keeps too few resamples to form a covariance matrix, or when a proposal covariance matrix is singular or non-finite. Previously this surfaced as a PosDefException after the iteration completed, or as a procedure that did not terminate.
  • Report a PumasDataError from simobs and predict for an empty obstimes. Depending on the model, such a call returned zero-length observations, reported a count mismatch against @derived, or threw a BoundsError.
  • Document the ss_states option in the @options docstring, show the actual default line search in the fit docstring, and correct the LOCF and NOCB abbreviations in the covariate interpolation error messages.
  • Correct the vpc docstring, which said that prediction_correction uses the mean population prediction. It uses the median population prediction, from a quantile regression on the binning covariate.
  • Update the license text printed at load and the shipped LICENSE.md to the September 2026 revision of the Pumas EULA at https://pumas.ai/eula. Section 2(c)(j) prohibits using the Licensed Software and PumasAI Content to train, fine-tune, test or develop AI/ML systems, and Section 4(d) defines "Protected Software Materials". The other PumasAI packages of this release that carry the Pumas EULA ship the same revision.
  • Wire up PumasEMModel descriptions in the model display.
  • Consistently use "log-likelihood" rather than "log likelihood" throughout messages and documentation.
  • Fix the docstring for the OrderedLogit distribution.

Bugs

  • Fix EWRES, which returned the mean of the decorrelated simulated residuals. That quantity has expectation zero and does not depend on the observations, so EWRES was Monte Carlo noise rather than a diagnostic. It is now the decorrelated observed residual and is standard normal for a correctly specified model. Diagnostics based on EWRES produced with earlier versions should be recomputed.
  • Fix SAEM continuing from a non-finite proposal. The step limiting of the dispersion and covariance parameters discarded NaN and returned a finite value, so a NaN proposal was clamped to a plausible number and the fit carried on. Non-finite values now propagate and are handled as numerical errors.
  • Fix the Normal log-density used internally by SAEM, which returned NaN for a standard deviation of exactly zero instead of the limiting values, and raise a DomainError again when sampling a constrained diagonal MvNormal with a negative variance.
  • Allow dose events with amt = 0. fit and simobs errored on such records unless the bioavailability of the dose compartment happened to be zero. read_pumas still warns about them, since a zero amount is often unintended.
  • Filter out TimeToEvent distributions in predict, which also fixes inspect. Previously an error was thrown for models with time-to-event dependent variables.
  • Fix simobstte failing for subjects that carry extra observations or none at all, and for models that define derived variables besides the time-to-event one.
  • Fix VPC with EnsembleDistributed, and fix the error raised by time-to-event VPCs under EnsembleThreads.
  • Support BernoulliLogit observations in smooth discrete VPCs, which raised an ArgumentError even though the equivalent Bernoulli model worked.
  • Fix several simulation paths that accepted an ensemblealg but did not act on it or failed when it was not EnsembleSerial(), including time-to-event VPC not forwarding ensemblealg to simobstte.
  • Fix the pointwise confidence intervals of the observed Kaplan-Meier curve in a time-to-event vpc, which were computed at confidence level 1 - level with Survival.jl versions before v0.3.3. The Pumas 2.8 system image ships Survival.jl v0.3.2, so the default level = 0.95 gave 5% intervals there. The intervals are now computed at the requested level.
  • Fix parallel simobs for models whose simulation return type is not concrete. Such simulations previously failed to deserialize under EnsembleDistributed.
  • Fix the FOCE Fisher-information matrix for Beta error models when both α and β depend on the random effects. A missing cross-term previously biased standard errors and confidence intervals for such models.
  • Fix the reported count of fixed parameters in fit and infer output. Multidimensional parameters were previously counted as one rather than by the number of elements estimated.
  • Add the prior to the observed information and score only for MAP fits. A maximum likelihood fit of a model whose parameters carry priors reported standard errors that included prior terms its objective did not contain. vcov, stderror, and infer on a JointMAP fit now raise an informative error instead of a MethodError.
  • Exclude the priors of parameters held constant with constantcoef from the log-likelihood reported for MAP and JointMAP fits, which was shifted by the prior log-density at the held value, together with aic and bic.
  • Check the values of parameters held fixed with constantcoef against their declared domains in fit. A fixed value outside its domain, such as a negative clearance or a covariance matrix that is not positive definite, was accepted and ran a whole fit.
  • Fix the parameter indexing of JointMAP for models with an MvLogitNormal prior, which was off by one.
  • Fix infer and vcov for models with an MvLogitNormal prior, which threw an error. Such a parameter is reported with all n of its entries in vcov, coeftable, and stderror, and dof counts n - 1 of them, because the entries sum to one. vcov is therefore singular. An MvLogitNormal parameter value or random effect that does not sum to one throws a DomainError.
  • Fix the value of the internal LogitNormal transform, which returned 1 - p instead of p. A scalar LogitNormal(μ, σ) prior on a population parameter effectively acted as LogitNormal(-μ, σ) in Bayesian fits and in the prior term of MAP and JointMAP objectives.
  • Fix the default initial value of VectorDomain(; lower, upper), where the dimension is inferred: init_params returned nothing for such a parameter, so fit and sample_params failed on it. VectorDomain(n; lower, upper) was unaffected.
  • Fix == on domains and Constrained priors, which compared by identity. Two identical VectorDomains constructed separately compared unequal. isequal and hash now agree with ==.
  • Fix steady-state periodic infusions incorrectly converging to the constant-rate equilibrium.
  • Fix steady-state records with an absorption lag time and multiple overlapping implied infusions, which switched on more infusions than they terminated. Such a record climbed to the constant-rate plateau instead of washing out; it now reproduces the same doses written out as separate records, on both the analytical and the numerical path.
  • Evaluate @dosecontrol at each additional (addl) dose's own time instead of reusing the values evaluated at the initiating record's time. A repeated regimen with time-varying dose control parameters now reproduces the same doses written out as separate records, and the reported dose control parameters are the ones the solver used.
  • Deactivate all earlier dose records on a reset (evid = 3), a reset-and-dose record (evid = 4), and an ss = 1 dose record, as NONMEM does. Infusions in progress are terminated, and pending additional (addl) doses are cancelled, as is a dose still held back by an absorption lag. Previously a reset during an infusion left a negative rate behind, and the pending doses were still given. Infusions in progress also no longer contribute to the steady state of a steady-state dose record, and ss = 2 is no longer ignored for a constant-rate steady-state infusion solved numerically.
  • Fix DosageRegimen(dr1, dr2; offset), which treated the dose times of dr2 as intervals between doses instead of shifting them. With dr2 dosing at times 0, 5, and 10 and offset = 10 after a regimen ending at 168, the doses landed at 178, 183, and 193 instead of 178, 183, and 188.
  • Return the negative time to the first dose from tad for times before that dose, as documented, instead of the time itself. For a subject without doses, tad returns missing instead of throwing a MethodError. The tad column of the DataFrames built from subjects, populations, and simulations changes accordingly.
  • Respect covariates_direction in the analytical solver. The closed-form and linear-ODE paths applied a time-varying covariate's value from the end of each subinterval, which is correct only for :right (NOCB); with the default :left (LOCF), a covariate change took effect one subinterval too early. Results with covariates_direction = :right are unchanged.
  • Improve the accuracy of the analytical solutions for strongly decaying compartments, where the decay factor previously lost precision and underflowed to exactly zero. Parameter values with an exact limiting solution, such as an infinite volume or an infinite clearance, now return that solution with a successful return code.
  • Fix a MethodError when a model that mixes an analytical solution with an ODE is solved with a stiff solver such as Rodas5P, and fix the handling of a failed inner ODE solution in such models.
  • Fix a type assertion error for models without parameters and random effects.
  • Fix @model accepting a variable defined with := twice in one block, or a := variable with the same name as a variable defined with = or ~ in another block. Such models could compute wrong values, because the statements in @pre and @dosecontrol do not run in source order. They are now rejected.
  • Skip @pre statements whose result nothing reads, such as unused := cl. Simulating or fitting the model threw if such a statement failed, for instance with a DomainError from sqrt(cl - 3), or because it read a covariate outside its observed range.
  • Fix an InexactError in inspect(...; nsim=...) for Int-typed discrete observations.
  • Fix simobs and predict for models defined with @emmodel that have Categorical, truncated, censored, or BernoulliLogit derived variables. These threw a MethodError or a TypeError because the element type of the derived vectors was inferred separately from the distributions written into them.
  • Fix a MethodError when simulating or fitting a model defined with @emmodel that has a @dosecontrol block and a subject with a non-numeric covariate, even one the dose control parameters do not depend on.
  • Fix the relative effective sample size used for Pareto-smoothed importance sampling in Bayesian cross-validation. ParetoSmooth.jl computed it from the pointwise log-likelihoods instead of the likelihoods. Pumas now computes it itself and passes it to PSIS.jl.
  • Return an empty NamedTuple for the dynamics of simulations of models without continuous dynamics. Previously the field held missing, which surfaced as a dynamics entry in postprocess output.
  • Fix latexify rendering of indexed parameters, and of derivatives, which showed a multiplication dot as in \mathrm{d} \cdot Central. The equations of the built-in analytical models now use the compartment names the models define, and latexify no longer throws a MethodError for Depots2Central1Periph1 and Central1Meta1.
  • Return an empty NamedTuple instead of throwing in wresiduals for non-Gaussian models.
  • Enforce monotonicity of the logits in OrderedLogit.

Deprecations and removals

  • Deprecate the @reactions macro. Write Catalyst reaction syntax directly in @dynamics instead.
  • Deprecate the options on the BayesMCMC, MarginalMCMC, and JointMAP algorithm structs that duplicate fit keyword arguments, and pass them to fit instead. This covers ensemblealg, parallel_chains, parallel_subjects, verbose, rng, diffeq_options, ignore_numerical_error, and constantcoef for BayesMCMC and MarginalMCMC, and ensemblealg, diffeq_options, optim_alg, optim_options, optimize_fn, and constantcoef for JointMAP.
  • Rename the marginal_alg keyword of MarginalMCMC to approx. The old name warns, setting both raises an error, and leaving the approximation unset is deprecated.
  • Deprecate the ensemblealg field of ExactCrossvalidation in favor of the ensemblealg keyword of crossvalidate, and remove it from SubspaceCrossvalidation.
  • Deprecate passing a file path to read_pumas. Read the file into a data frame first, for example read_pumas(CSV.read("data.csv", DataFrame; missingstring = ["", ".", "NA"])). Note the missingstring argument: read_pumas treated . and NA as missing, while the CSV.read default treats only the empty string as missing, so dropping it can silently turn numeric columns into string columns.
  • Deprecate infer(fpm, SIR(...)) without an explicit source for the covariance matrix of the initial proposal distribution. State the source with infer(infer(fpm), sir), or supply the matrix with the proposal_covariance keyword.
  • Deprecate PSDDomain(init::AbstractVector). Pass Diagonal(init) instead, or use PDiagDomain for a domain of diagonal covariance matrices.
  • Deprecate loglikelihood(fpm) for models fitted with a method that does not compute a likelihood, such as SAEM. The call warns and falls back to LaplaceI(); pass the approximation explicitly as loglikelihood(fpm, approx). lrtest on two SAEM fits behaves the same way.
  • Deprecate passing a likelihood approximation to icoef and dosecontrol. Pass empirical Bayes estimates instead, for example icoef(model, subject, param, empirical_bayes(model, subject, param, approx)).
  • Deprecate selecting the quantities of gsa by variable name. Pass a post-processing function as the first argument instead.
  • Deprecate the batch keyword of gsa. Batching now follows from ensemblealg.
  • Deprecate DataFrame(fpmi.vcov) in favor of samples_table.
  • Remove the @nca macro, together with the conversion of a Subject to an NCASubject and of a Population to an NCAPopulation. NCA is no longer a dependency of Pumas, so add and load NCA yourself and compute the parameters from the simulation output: NCA.read_nca_pumas(DataFrame(sims); concentration = :dv) reads a simulation table into NCA profiles, which run_nca then takes.
  • Remove route from the dose representation. DosageRegimen and read_pumas still accept a route keyword but warn and ignore it, and route is no longer a column of the DataFrames built from subjects, populations, simulations, predictions, and inspections. Carry the route as a covariate instead, with values such as "ivbolus", "ivinfusion", or "ev".
  • Remove QuadratureExpectation, together with the unexported LLQuad likelihood approximation and the dependency on Integrals.jl. expectation supports MonteCarloExpectation.
  • Remove the re-export of Unitful. using Pumas no longer brings the Unitful names into scope, so a model written with units needs its own using Unitful.
  • Remove the Statistics.cor method that Pumas defined for a Vector of Vectors. Such a call now throws a MethodError, and cor(stack(v); dims = 2) computes the same correlation matrix. postprocess(f, sims; stat = cor) and cor(f, ::BayesMCMCResults) keep working, and now also accept an f that returns a vector other than a Vector, such as a view or a static vector.

Compatibility

  • Pumas now runs on Julia 1.13.3.
  • Pumas no longer depends on NCA. using Pumas does not bring run_nca, read_nca, summarize, or the other names NCA exports into scope, so a workflow computing NCA parameters needs NCA added to its own project and loaded explicitly. using PumasUtilities does bring the names NCA exports into scope, since PumasUtilities re-exports NCA. NCA 3 is itself a rewrite: NCASubject, NCAPopulation and NCAReport are gone, a profile is a DataFrame, and per-endpoint functions such as NCA.auc are replaced by endpoint symbols passed to run_nca. The NCA section below lists the main changes.
  • Pumas now uses ModelingToolkitBase and Catalyst 16.
  • Bayesian cross-validation now uses PSIS.jl instead of ParetoSmooth.jl for Pareto-smoothed importance sampling.
  • The observed Kaplan-Meier curve of a time-to-event vpc is now computed with SurvivalModels.jl instead of Survival.jl.

PumasPlots

Features and improvements

  • Add PumasPlots.Experimental.plot_vpc and PumasPlots.Experimental.plot_npde for the predictive checks in Pumas.Experimental, covering continuous, Bernoulli, categorical and cumulative discrete, and censored VPCs, as well as the NPDE and EWRES diagnostics. They stay experimental for as long as the Pumas.Experimental API they render does.
  • Support inspections of fitted mixture models in the goodness-of-fit and diagnostic recipes, plotting the responsibility-weighted marginal predictions and residuals. observations_vs_ipredictions gained a stratify_by keyword that colors the points, and fits the trend lines, per stratum such as the subpopulation of a mixture-model inspection.
  • Add a scale = :log option to observations_vs_predictions and observations_vs_ipredictions, which log-scales the axes and fits the trend lines on log-transformed data.
  • Show a loess trend line for continuous covariates in empirical_bayes_vs_covariates by default.
  • Add likelihood_ratio_ppplot, a P-P plot of the likelihood-ratio statistics of bootstrap or SIR parameter samples against the reference Chi-squared distribution.
  • Change the default of the identity, ols and zeroline trend-line keywords on the diagnostic recipes from true to false, so only the loess line is drawn unless the others are requested.
  • Use one row per subject in empirical_bayes_vs_covariates and empirical_bayes_dist, so subjects with many observations no longer dominate the reported correlation or the histogram counts. Time-varying covariates use each subject's baseline value.
  • Size faceted plots to their content instead of squeezing them into Makie's default figure size, and split legends with many entries into several columns so they no longer overflow the figure.
  • Treat Bool covariate columns as categorical rather than as continuous numbers.
  • Wrap the covariate facets of npde_vs_covariates when only one NPDE is plotted, instead of producing a single row of facets.
  • Make the group keyword of vpc_plot select the strata to draw. It was documented but ignored. It takes a tuple of pairs or a NamedTuple, and throws an ArgumentError that lists the valid choices when it names an unknown variable or matches no stratum.
  • Throw an error for keywords that vpc_plot does not support, instead of ignoring them. Calls that passed such keywords, for example rows, columns, facet, or figurelegend, need them removed. The figure they drew is unchanged.

Documentation and error messages

  • Report an informative error from goodness_of_fit when the inspection contains neither weighted residuals nor NPDEs, pointing at inspect(fpm; nsim = n).

Bugs

  • Fix observations_vs_time dropping unrelated observations whenever any observation column was missing at a given time point.
  • Keep time points whose observed or simulated value is missing in sim_plot. Previously such observations were silently dropped, and missing simulated values could error.
  • Fix the vpc_plot legend collapsing the two outer simulated-quantile bands into a single entry when they are drawn in different colors.

Deprecations

  • Deprecate covariates_check in favor of overview_table and covariates_dist. It will be removed in a future breaking release.

PlottingUtilities

Features and improvements

  • Support the rows and columns pagination keywords in plots that facet with a wrapped layout, such as sim_plot with separate = true. Each page now holds at most rows × columns panels arranged in columns columns. Previously the two keywords only took effect in plots faceted over explicit row and column groupings and were silently ignored otherwise. For wrapped layouts they must be given together and cannot be combined with limit.
  • Set the keyword arguments of the plot functions built on aog_spec, such as subject_fits, from a Makie theme, in a section keyed by package and function name, for example Makie.set_theme!(PumasPlots = (; subject_fits = (; ipred_color = :green))). A keyword given at the call takes precedence over the theme, and the theme over the default. A theme key the function does not accept throws an error that names it.

Bugs

  • Fix interactive throwing a PlotlyBackendException for figures that set the axis ticks to a plain vector of tick positions, as the NCA power_model and dose_vs_dose_normalized plots do.

Deprecations

  • Deprecate pair_plot in favor of the more comprehensive pairplot from the PairPlots package, which ships with Pumas.

NCA

Behavior change

  • NCA 3 is a rewrite of the package, so code written for NCA 2 does not run unchanged. Migrating from NCA v2 explains the changes, lists the individual renames and removals, and links an agent skill for translating NCA 2 code. The main changes:

    • NCASubject, NCAPopulation and NCAReport are removed. read_nca returns a DataFrame with one profile per dosing event and times relative to the dose, and run_nca returns a DataFrame of results.
    • read_nca takes long-format data in which each row repeats the dose information of its profile. The columns are concentration and dose instead of conc and amt, column names are matched exactly (ignoring case) without aliases, and the unit keywords are time_unit, concentration_unit, volume_unit and dose_unit. tau and assumed_tau columns replace ii and ss. read_nca_pumas reads NONMEM-style tables in which dose rows are interleaved with the observations, such as Pumas simulation output.
    • run_nca takes the endpoints as its second positional argument instead of the parameters keyword, and endpoint symbols replace per-endpoint functions such as NCA.auc. An endpoint that cannot be computed is missing, with the reason in an <endpoint>_err column, instead of a logged warning.
    • BLQ observations are flagged by a Boolean blq column instead of the llq keyword, which gave the limit of quantification. transform_nca substitutes the flagged values according to its blq_rules keyword.
    • Time columns cannot contain missing, so plasma and urine observations cannot be analyzed in one data set.
    • summarize always skips missing values and always reports numsamples and nonmissing columns, and its skipmissings keyword is removed.
    • The concthreshold keyword of the λz calculation is removed. BLQ handling covers it.
    • NCA no longer re-exports Unitful, but still works with Unitful data.
    • The NCA 2 endpoint names, such as cl, vss, mrt, auctau and thalf, still work but are deprecated.
  • NCAUtilities is merged into NCA. The NCA plots and geomean_cv_table come with NCA, and NCAUtilities is no longer part of the Pumas installation, so using NCAUtilities fails.

  • cmaxss and cminss of a profile with assumed_tau are the maximum and minimum of the predicted steady-state curve at the observation times in [0, assumed_tau] and at assumed_tau. NCA 2 scaled cmax and cmin by the accumulation index, which only holds when the whole profile declines at λz. Reported values change for most such profiles.

Features and improvements

  • Add superposition to predict steady-state and other multiple-dose profiles from single-dose data, with a max_auto_doses keyword that caps the automatic number of doses.
  • Add exclusions of observations or whole subjects through an exclusion column of reasons, and a lambdaz_mask column that selects the points of the λz regression. Excluded and BLQ observations are masked instead of deleted, and BLQ substitution keeps the original values in a separate column.
  • Add the experimental lambdaz_diagnostics endpoint, with per-point diagnostics of the λz regression: studentized residuals, leverage, Cook's distance, jackknife influence on the adjusted R², DFBETA on λz, and leave-one-out λz and half-life. The experimental format_diagnostics and exclude_lambdaz work with it.
  • Accept the route values "ivbolus" and "ivinfusion", which are preferred over "iv" and "inf".
  • Include every column that is not a grouping column in summarize, not only known endpoint names, so partial AUCs and renamed columns are summarized as well.
  • Reimplement the endpoint calculations and test many of them against WinNonlin results.

PumasUtilities

Behavior change

  • PumasUtilities re-exports NCA instead of NCAUtilities, which was merged into NCA 3.1. using PumasUtilities brings the names NCA exports into scope, including the NCA plots and geomean_cv_table that NCAUtilities provided before. Code written for NCA 2 or NCAUtilities needs to be updated to the NCA 3 API.

PumasReports

Behavior change

  • The parameter tables of report always have a description column, taken from coeftable, so a parameter without a description in @metadata shows its name. The column used to appear only for models that declared descriptions.
  • report no longer includes the "Data Checkout" figures built with the deprecated covariates_check. Covariate distributions are still shown for each fit through covariates_dist.

Bioequivalence

Behavior change

  • Pass a regulatory criterion as a type, for example pumas_be(data, FDA_HighlyVariable), instead of an enum value. The deprecated FDA and EMA_CMAX aliases are removed.
  • EMA_HighlyVariable performs average bioequivalence with expanding limits (ABEL) on replicated crossover designs. The acceptance limits widen for a within-subject CV of the reference between 30% and 50%, and standard average bioequivalence applies at or below 30%. It used to fall back to the FDA reference-scaled analysis with a warning.
  • reference_scale is the regulatory constant θ, the square of k, so the EMA value is reference_scale = 0.5776 instead of 0.76.
  • The EMA criteria, EMA_HighlyVariable and EMA_NarrowTherapeuticIndex, fit replicated crossover designs with LinearModel, ordinary least squares with subjects as a fixed effect, instead of a mixed model. custom_model = LinearMixedModel selects a mixed model, which defaults to equal residual variances for the EMA criteria.
  • The nonparametric analysis of a crossover design defaults to Koch's cross-sequence rank-sum construction, which cancels the period effect between the sequences. The pooled signed-rank analysis of earlier releases is selected with custom_model = SignedRankTest. Parallel designs, which failed before, run a rank-sum test. The result reports a median for each formulation, the Hodges-Lehmann estimate as Median Ratio (%), and the distribution-free interval, and it no longer gives an equivalence verdict. Designs without a valid distribution-free interval, and samples too small to reach level_tost, are rejected with an ArgumentError.
  • The nonparametric intervals come from HypothesisTests 0.12, which corrects the choice of order statistic, the null distribution behind the approximate interval, and the handling of zero differences. Reported intervals change.
  • cv_min and cv_max passed to a criterion that does not use them, and custom_model or reml where they have no effect, throw an ArgumentError instead of being ignored.
  • The acceptance bounds :ABE_RULE and :ABEL_RULE of the result table are (lower, upper) tuples instead of strings.
  • The replicated crossover paradigms are renamed to replicated_crossover_supports_abe_and_abel_only and replicated_crossover_supports_abe_abel_and_rsabe. The low-level reference-scaling helpers are no longer exported and remain available qualified, for example Bioequivalence.GeometricMeanRatioBounds.

Features and improvements

  • Add a wsv_model keyword to pumas_be and run_be that selects the model of the within-subject variability of the reference in replicated designs: formulation_pooled_wsv_model, period_only_wsv_model, period_by_sequence_wsv_model (FDA) or additive_sequence_wsv_model (EMA).
  • Add a cv_max keyword to pumas_be and run_be, which caps the expansion of EMA_HighlyVariable, for example cv_max = 0.57382 for Health Canada.
  • Make assess_be public and export set_result_table!, reference_scale_default and NoAssessmentBioequivalenceCriterion, so an analysis can run step by step as preprocess_be, run_be, assess_be, set_result_table!, with or without an assessment.
  • Report whether a design supports ABEL in the supports_abel field of detect_design.
  • Re-export SignedRankTest, so custom_model = SignedRankTest needs no using HypothesisTests.
  • Show BioequivalenceEndpointOutput and BioequivalenceEndpointDecision as one line inside containers and with print or repr, giving the criterion, the endpoint and the point estimate. The multi-line display is unchanged.

Documentation and error messages

  • Rewrite the documentation as nine reference pages covering every pumas_be argument, the regulatory criteria and their constants, and the fields of the output.

Bugs

  • Fix the within-subject CV reported for paired designs, which was computed from a standard deviation that was too large by a factor of √2.
  • Fix the HTML display of results, which misaligned the header of the results column and threw for an output whose result table was not populated.

Deprecations

  • Remove the userepeatedobsonly keyword of pumas_be, run_be and within_subject_variability. Only the repeated observations are used, as the FDA within-subject variability model requires.

OptimalDesign

Behavior change

  • named_fim returns a DimArray from DimensionalData with X and Y dimensions instead of a NamedArray. Index it as nf[X = At("θ₁"), Y = At("θ₂")] instead of nf["θ₁", "θ₂"], get the names with lookup(nf, X) instead of names(nf), and the matrix with parent(nf) instead of nf.array. At, X, Y and lookup need using DimensionalData.
  • The default and the cached FIM throw an ArgumentError when the dynamical system fails to solve, instead of computing with Inf predictions.

Bugs

  • Fix the default FIM of models without random effects, which used the inverse of the observation standard deviations instead of the inverse of the variances. FIMs computed with finitediff = true or cache = true were correct. Designs optimized with the default FIM for such models change.
  • Fix cache = true for models with numerical dynamics, which failed. The cached FIM rejects a solver with lazy interpolation, such as AutoVern7, and observation times outside the time span of the solution.
  • Fix the parameter names reported by compare_designs for parameters given in a different order than in the model.

InVitroInVivoCorrelation

Features and improvements

  • Add InVitroInVivoCorrelation, an experimental package for Level A in vitro–in vivo correlation. It fits unit impulse responses, deconvolves the in vivo profiles numerically, fits the Level A correlation, predicts new formulations, computes FDA-style validation metrics (%PE, f1/f2) and plots the results, with DataFrame input and output. run_ivivc runs the whole workflow. The API may change in future releases, and the package warns about this when it is loaded.

SummaryTables

Features and improvements

  • Add NumberFormat, which controls number formatting per value, per column, per variable or per table, with prefixes and suffixes, scaling, display limits like <0.001, magnitude suffixes like 5.4K and exponent style. Several formatting defaults change with it:

    • Exponential notation renders like 1.5 × 10⁶ instead of 1.5e6, which exponent_style = :e changes back, and exponent_thresholds controls from which magnitudes on it is used at all.
    • round_mode = :sigdigits shows 1234 as 1.23 × 10³ instead of 1230 at 3 digits, so that every displayed digit is a significant one.
    • trailing_zeros defaults to :auto, so the exact rounding modes display exactly the requested precision while round_mode = :auto does not pad.
    • trailing_zeros = true pads to the requested precision in the :auto and :sigdigits modes as well, for example 1.50 at 3 significant digits.
    • Trailing zeros are also stripped from e-notation mantissas and from negative numbers.
  • Control the rule widths, paddings and footnote appearance of a Table per table or globally, using font-relative (em) or absolute (pt) lengths that render consistently across all backends. Cell indents and row and column gaps accept these lengths as well, where bare numbers still mean points. to_docx takes an optional DocxDefaults argument, whose base_fontsize sets the font size that em lengths refer to in Word.

  • Align the category bars of overview_table with the corresponding text lines in HTML, typst and latex output.

  • Display a Table as text in the REPL and in any other text/plain output, with box-drawing rules. The REPL showed the fields of the Table struct before. Bold, italic, underline and color are dropped, and long cells are not wrapped.

Bugs

  • Reject header and footer indices that lie outside the table or overlap each other, such as header = 0 or header = 2, footer = 2. Such a Table was accepted and rendered wrongly, and its typst output did not compile.

Deprecations

  • Deprecate the indent_pt keyword in favor of indent.

AlgebraOfGraphics

Behavior change

  • Analyses (linear, smooth, density, histogram, expectation, filled_contours) now fit in transformed space and back-transform their output when the relevant aesthetic carries a scale function set through scales, for example scales(Y = (; scale = log10)), so a fit on log-scaled data is computed in log space. This is distinct from axis = (; yscale = ...), which only transforms the display.
  • Analyses (density, histogram, linear, smooth, frequency, expectation) now drop rows where any numeric input is missing or NaN instead of erroring or producing garbage. Infinite values throw an ArgumentError that names the column. Before, they caused unrelated errors in some analyses and were used silently in others: frequency counted Inf as a category, expectation included it in the mean, and histogram dropped it.
  • Legend entries now hide elements from plot types that have no data for a given category, so layers of different plot types sharing a categorical scale no longer each contribute a swatch to every entry. Disable it globally with legend = (; hide_unused = false) or per scale with hide_unused_legend. In paginated plots, the legend of each page shows only the categories present on that page.

Features and improvements

  • Add FacetSize and facet = (; size = FacetSize(...)) for declaring an axis sizing policy that adapts to the resolved grid layout. The default wrapped layout resolves its row and column positions at draw time from the effective axis aspect, picking a column count that brings the bunched axis areas closest to a square shape. For square axes the column count is the same as before. For non-square axes, such as axes given a width and height, the default layout can have a different number of columns than in earlier releases. FacetSize works with draw! as well as draw.
  • Add a direction keyword to 1D histogram, which sets the bar orientation and the aesthetic the bins are computed in.
  • Accept the generic dodge_x and dodge_y mapping for plot types with a native dodge attribute (BarPlot, BoxPlot, Violin, CrossBar), so a single mapping can be shared across companion layers instead of switching attribute names per layer.
  • Add support for Stem plots.
  • Accept Unitful and DynamicQuantities data in the analyses, including columns that contain missing.
  • Align Unitful and DynamicQuantities units in ABLines. The intercept takes the unit of y and the slope the unit of y/x, and incompatible units throw an error. A dimensionless slope is accepted when x and y carry the same unit.

Bugs

  • Fix paginate discarding the layout scale palette, so wrapped can be used to paginate with specific row and column shapes.
  • Fix palette pairs and categories passed through scales not matching presorted or nonnumeric wrapped data unless the keys were wrapped as well.
  • Fix mappings with verbatim picking up another layer's scale for the same aesthetic.
  • Fix smooth with the default degree = 2 collapsing on Date and other large-magnitude x axes.
  • Justify multiline footnotes according to footnotealign.

PumasAide

Features and improvements

  • Run a named chunk of a file with include_julia_file instead of the whole file. # %%, ##, and #- delimit chunks in a .jl file, and #| label: in the {julia} blocks of a .qmd, so an agent can rerun one cell of a script it has already executed.
  • Report a compact workspace delta from include_julia_file: one headline per binding the script created or reassigned, rather than the full objects. Bindings whose name begins with _ are treated as intermediates and left out, and the show argument expands named bindings in full.
  • Return from eval_julia_code what the REPL would return, the standard output and the value of the final expression. Intermediate assignments are no longer surfaced.
  • Assign to workspace variables from top-level for and while loops in eval_julia_code, following REPL soft scope.
  • Require Authorization: Bearer <token> on every request with serve(; token), so a host that starts PumasAide can keep other local processes from running code in its session.
  • Search the docstrings of loaded Pumas packages, such as Pumas, NCA, Bioequivalence and PumasPlots, with pumas_knowledge, so an agent can check the arguments and defaults of the installed versions.
  • Improve the matching of pumas_knowledge search.
  • Throw from serve when the port is already in use, instead of failing inside the server task.
  • Apply pending Revise revisions before each tool call whenever Revise is loaded, so an edit to tracked code takes effect in the next tool call. A revision that fails, such as a syntax error in a tracked file, fails the tool call with that error.
  • Tell the agent in the server instructions to call vscodedisplay(x) when the user asks to see a plot or table in VS Code.
  • Write scripts into the project's own layout, taken from its agent instructions, organisation rules, or existing folders. The programs/ and reports/ folders apply only when none of these sets a layout.
  • Mark tools anthropic/alwaysLoad so Claude Code loads their schemas upfront, give each tool a title for clients to display, and mark pumas_knowledge with readOnlyHint so clients can run its calls in parallel. The server reports its package version to MCP clients, where it reported 1.0.0.
  • Log each tool call in the Julia session as a framed, syntax-highlighted block, so the code an agent ran and the errors it hit can be read off the server log.
  • Point at the fix when a world-age error is raised, such as deserializing an object and using it in the same statement, which is resolved by splitting the statements or loading the model first.
  • Trim the server instructions sent to the client to the essentials, so that they fit the size limits of common clients.
  • Drop the hardcoded numeric ranges, thresholds, and acceptance criteria from the pharmacometric knowledge docs in favour of qualitative guidance, which an organisation pins down with its own rules.

Bugs

  • Fix the world-age MethodError raised when a serialized object, such as a Pumas fit read from a .jls file, was inspected in the call that loaded it.
  • Refuse a request whose Host is not an address the server serves under, and a state-changing request carrying an unrecognised Origin. Without the check, a page the user visits can point a hostname it controls at 127.0.0.1 and reach the local server through the browser as though it were local code.
  • Fix overlapping eval_julia_code and include_julia_file calls failing with SystemError: dup: Bad file descriptor or returning each other's output. Calls now take turns.
  • Fix a tool result being lost when the client connection dropped mid-call. A client that reconnects receives the rest of the stream, result included.
  • Fix logged tool calls splicing into each other in the server log when calls ran concurrently.
  • Fix include_julia_file with show over several chunks warning about unknown bindings for names another chunk created.
  • Fix pumas_knowledge printing deprecation warnings, such as for Pumas.FOCEI, when it built its docstring search index.
  • Fix the bioequivalence knowledge doc examples passing logtransformed=true on raw NCA values, which marks them as already logged and gives wrong GMRs.
  • Fix the BLQ handling knowledge doc. It separates NCA conventions from Beal's M1-M7 population PK methods, which the previous table misnumbered, and the NCA workflow makes BLQ handling an explicit decision step that the agent reports.

Deprecations and removals

  • Remove the browser interface: the /preview object viewer and its sidebar, the dependency graph page, the column-stat charts, and the preview URLs in tool responses. Objects are shown in VS Code through vscodedisplay.
  • Remove the dev keyword of serve, which served the browser interface.
  • Remove the revise preference. Pending Revise revisions are applied before each tool call whenever Revise is loaded.
  • Remove support for NCA 2. The NCA knowledge docs cover NCA 3 only, and PumasAide no longer depends on NCA, so projects that run NCA code add it themselves.

ADaM

Features and improvements

Features

  • Add write_spec, update_spec, and validate_spec for authoring an ADaM specification workbook from a variable template and a folder of SDTM .xpt files, editing it without discarding reviewer changes made in Excel, and checking a derived .xpt dataset against it.
  • Add conc_summary for the PK-standard concentration statistics (N, GeoMean, GeoCV, GSD, Mean, SD, CV, Median, Q1, Q3, Min, Max) by treatment and nominal time, optionally nested by dose.
  • Add bloq_summary for below-limit-of-quantification tables in one of three layouts.
  • Add population_flag_summary, subject_inclusion_exclusion, and record_inclusion_exclusion to account for the analysis population. Each renders a SummaryTables.Table, or returns the underlying DataFrame with as_df = true.
  • Add covariate_pairplot_df, continuous_covariate_distribution_df, categorical_covariate_count_df, samples_per_subject_df, and sampling_time_df to reshape an ADPPK dataset for the standard exploratory plots.
  • Add profile_dataset to profile a DataFrame, or a folder of .xpt and .sas7bdat files, into per-column statistics. *DTC columns report the distinct ISO 8601 formats present rather than the distinct values.
  • Add occasion to derive OCC on an ADPPK BDS dataset from a caller-supplied predicate.

Improvements

  • Default make_dtm to fmt = :iso8601_auto so a DTC column of mixed precision parses, and accept a Vector{DateFormat} and an on_error = :error | :missing keyword.
  • Flag the entire non-ascending sequence in make_time_fl rather than only the record where time dropped, and add a strict keyword for strictly increasing times.
  • Speed up the as-of joins in join_columns with a dictionary-based group index.
  • Simplify type signatures and validate argument types at the call rather than inside a derivation.

Bugs

  • Fix definition_table, which relied on SummaryTables internals.
  • Parse word-form frequencies such as ONCE WEEKLY, TWICE DAILY, and ONCE A WEEK in interdose_interval, which returned 0 or errored on them.
  • List categories with equal counts in sorted order in definition_table. They followed hash order, which differs between Julia 1.12 and 1.13, so the same data could give a different table, and a column with more than max_categories categories could list a different subset.

Deprecations

  • Rename the table keyword of bloq_summary to style, and identify total rows in the :simple_table layout by the time column so a colliding group value no longer renders bold.
  • Remove basic_info_pc, subject_trt_count, bmi_summary, and validate_column_structure with no replacement.

QuartoTools

Behavior change

  • Every cached result is computed again once. The cache keys and the storage layout changed, so entries written by earlier versions are not read. They are left in place, not deleted.
  • The key of a cached call covers every tracked function the call reaches, at any depth, so editing a function that the cached call depends on invalidates the entry. The key used to cover only the called function's own code.
  • The dependency walk stops at packages the active project does not depend on, so a development tool loaded from a shared environment does not enter the cache key.
  • A global that the cached code reads and whose value cannot be serialized is keyed on its type, with a warning that names it. Such a global used to make the call uncacheable.
  • An entry that cannot be read is dropped and the call runs in its place, instead of failing. A call to a function for which cacheable returns false runs uncached instead of raising Cannot cache function call.

Features and improvements

  • Apply @cache to a function definition or a callable-object definition, not only to a call. A docstring above such a definition documents it.
  • Inspect and clean up caches with entries, usage, drop!, and prune!. prune! removes entries by age, count, total size, or function name. Without a directory argument, the four functions cover the cache of the working directory and the cache beside each cached definition loaded so far.
  • Control what a cache key covers with track!, untrack!, is_tracked, dependencies, and ignore_global!.
  • Set the cache directory with cache_directory! or the QUARTOTOOLS_CACHE_DIRECTORY environment variable, and turn caching off with disable! or QUARTOTOOLS_CACHE_DISABLE.
  • Hash arguments with XXH3-128 instead of SHA-256, which reads the bytes of an argument about fifty times faster.

PumasLicenseManager

Behavior change

  • On Linux outside cluster installs, the hardware ID includes the UID and the username of the user, hashed, so distinct users on one machine get distinct hardware IDs. The hardware ID of such a machine changes with this release.
  • PUMAS_CLUSTER_LICENSE_PATH is ignored on operating systems other than Linux.

Bugs

  • Fix a floating-license seat being released as soon as the license details were displayed. The license handler is held for the session and freed at exit.
  • Fix the floating-license watchdog dying silently on an unexpected error. It now exits the process.
  • Fix an UndefVarError on Julia 1.12 and later when "enter license key" is picked from the interactive menu.