pyhs3.Model¶
- class pyhs3.Model(*, parameterset, distributions, domain, functions, progress=True, mode='FAST_RUN', observables=None, likelihood=None)[source]¶
Probabilistic model with compiled tensor operations.
A model represents a specific instantiation of a workspace with concrete parameter values and domain constraints. It builds symbolic computation graphs for distributions and functions, with optional compilation for performance optimization.
The model handles dependency resolution between parameters, functions, and distributions, ensuring proper evaluation order through topological sorting of the computation graph.
Single log-space pipeline. Every distribution node is built exactly once, in log space, as
self.log_distributions[name]; the probability-space counterpartself.distributions[name]is always derived aspt.exp(self.log_distributions[name])rather than built independently, so the two can never disagree on normalization or on their free inputs –pars()is therefore valid for bothpdf()andlogpdf()by construction.HFDC constraint storage. For
HistFactoryDistChanneldistributions,self.log_distributions[name]stores the full per-channel log expression (summed Poisson log-pmf plus summed log-constraints) so thatlogpdf(name, **params)matches pyhf/cabinetry semantics for callers asking about a single channel’s probability;self.distributions[name]ispt.expof that.self._hfdc_log_poisson[name]stores only the log-space Poisson term;log_probuses it to assemble the joint NLL without double-counting constraint factors when multiple channels share a nuisance parameter. Log-space constraint expressions are appended toself._hfdc_log_constraintsexactly once per unique dedup key across all channels: single-parameter modifiers (normsys,histosys) are deduped by parameter name usingself._hfdc_constraint_params_seen; multi-parameter modifiers (shapesys,staterror) are channel-local by workspace validation and always emitted as-is.log_probsumsself._hfdc_log_constraintsdirectly, so it stays finite where a probability-space constraint would underflow to 0.0.HS3 Reference
Models are computational representations of HS3 workspaces.
- Parameters:
parameterset (
ParameterSet)distributions (
Distributions)domain (
Domain)functions (
Functions)progress (
bool)mode (
str)likelihood (
Likelihood|None)
- __init__(*, parameterset, distributions, domain, functions, progress=True, mode='FAST_RUN', observables=None, likelihood=None)[source]¶
Represents a probabilistic model composed of parameters, domains, distributions, and functions.
- Parameters:
parameterset (ParameterSet) – The parameter set used in the model.
distributions (Distributions) – Set of distributions to include.
domain (Domain) – Domain constraints for parameters.
functions (Functions) – Set of functions that compute parameter values.
progress (bool) – Whether to show progress bar during dependency graph construction.
mode (str) – PyTensor compilation mode. Defaults to “FAST_RUN”. Options: “FAST_RUN” (apply all rewrites, use C implementations), “FAST_COMPILE” (few rewrites, Python implementations), “NUMBA” (compile using Numba), “JAX” (compile using JAX), “PYTORCH” (compile using PyTorch), “DebugMode” (debugging), “NanGuardMode” (NaN detection).
observables (dict[str, tuple[float, float]] | None) – Dictionary mapping observable names to (lower, upper) bounds.
- parameterset¶
The original parameter set with parameter values.
- Type:
- distributions¶
Symbolic distribution expressions.
- modifiers¶
HistFactory modifier terms (normalization factors, shape systematics, and similar) discovered while building the graph.
- log_distributions¶
Log-space expression for each distribution, keyed by name; what
logpdf()/logpdf_unsafe()evaluate.
- _compiled_functions¶
Cache of compiled PyTensor functions.
- Parameters:
likelihood (
Likelihood|None)
Methods
__init__(*, parameterset, distributions, ...)Represents a probabilistic model composed of parameters, domains, distributions, and functions.
graph_summary(name)Get a summary of the computation graph structure.
logpdf(name, **parametervalues)Evaluates the natural logarithm of the PDF.
logpdf_unsafe(name, **parametervalues)Evaluates the log PDF with automatic type conversion (convenience method).
pars(name)Get the ordered list of input parameter names for a distribution.
parsort(name, names)Similar to numpy's argsort, returns the indices that would sort the parameters.
pdf(name, **parametervalues)Evaluates the probability density function of the specified distribution.
pdf_unsafe(name, **parametervalues)Evaluates the PDF with automatic type conversion (convenience method).
visualize_graph(name[, fmt, outfile, path, ...])Visualize the computation graph for a distribution.
Attributes
Observed data arrays from the workspace, keyed by observable name.
Non-constant parameter values from the workspace parameter set.
Symbolic joint log-probability expression for the full likelihood.
Default parameter values from the workspace parameter set.
- Model.logpdf(name, **parametervalues)[source]¶
Evaluates the natural logarithm of the PDF.
This method requires all parameter values to be numpy arrays with dtype float64. For automatic type conversion, use
logpdf_unsafe()instead.The logarithm is evaluated in log space via a compiled log-PDF function (
log(prod(exp(...)))stays collapsed), so the result remains finite for HistFactory channels where the probability-spacepdfunderflows to0.0.- Parameters:
- Returns:
The log of the PDF.
- Return type:
npt.NDArray[np.float64]
- Raises:
TypeError – If any parameter value is not a numpy array.
See also
logpdf_unsafe(): Convenience version with automatic type conversionpdf(): PDF with strict type checkingExample
>>> import numpy as np >>> model.logpdf("gauss", x=np.array(1.5), mu=np.array(0.0), sigma=np.array(1.0))
- Model.logpdf_unsafe(name, **parametervalues)[source]¶
Evaluates the log PDF with automatic type conversion (convenience method).
This method automatically converts parameter values to numpy arrays before evaluation. Use this for convenience in testing or interactive use.
For performance-critical code, prefer
logpdf()with pre-converted numpy arrays.- Parameters:
- Returns:
The log of the PDF.
- Return type:
npt.NDArray[np.float64]
See also
logpdf(): Type-safe version requiring numpy arrayspdf_unsafe(): PDF with automatic type conversionExample
>>> model.logpdf_unsafe("gauss", x=1.5, mu=0.0, sigma=1.0) # floats ok
- Model.pars(name)[source]¶
Get the ordered list of input parameter names for a distribution.
This method returns the parameter names in the exact order expected by the compiled PDF function. Since the probability- and log-space expressions for a distribution share identical free inputs by construction (
pdf()evaluatespt.exp()of exactly whatlogpdf()evaluates), this same ordering is valid for bothpdf()andlogpdf().- Parameters:
name (
str) – Distribution name- Return type:
- Returns:
List of parameter names in the order expected by pdf() and logpdf()
Example
>>> model.pars("model_singlechannel") ['uncorr_bkguncrt_1', 'uncorr_bkguncrt_0', 'model_singlechannel_observed', 'mu', 'Lumi']
- Model.parsort(name, names)[source]¶
Similar to numpy’s argsort, returns the indices that would sort the parameters.
- Parameters:
- Return type:
- Returns:
List of indices that would sort the parameters
Example
>>> model.parsort("model_singlechannel", ["mu", "Lumi", "uncorr_bkguncrt_0", "uncorr_bkguncrt_1", "model_singlechannel_observed"]) [3, 2, 4, 0, 1]
- Model.pdf(name, **parametervalues)[source]¶
Evaluates the probability density function of the specified distribution.
This method requires all parameter values to be numpy arrays with dtype float64. For automatic type conversion, use
pdf_unsafe()instead.- Parameters:
- Returns:
The evaluated PDF value.
- Return type:
npt.NDArray[np.float64]
- Raises:
TypeError – If any parameter value is not a numpy array.
See also
pdf_unsafe(): Convenience version with automatic type conversionlogpdf(): Log PDF with strict type checkingExample
>>> import numpy as np >>> model.pdf("gauss", x=np.array(1.5), mu=np.array(0.0), sigma=np.array(1.0))
- Model.pdf_unsafe(name, **parametervalues)[source]¶
Evaluates the PDF with automatic type conversion (convenience method).
This method automatically converts parameter values to numpy arrays before evaluation. Use this for convenience in testing or interactive use.
For performance-critical code, prefer
pdf()with pre-converted numpy arrays.- Parameters:
- Returns:
The evaluated PDF value.
- Return type:
npt.NDArray[np.float64]
See also
pdf(): Type-safe version requiring numpy arrayslogpdf_unsafe(): Log PDF with automatic type conversionExample
>>> model.pdf_unsafe("gauss", x=1.5, mu=0.0, sigma=1.0) # floats ok >>> model.pdf_unsafe("gauss", x=[1.5], mu=0.0, sigma=1.0) # lists ok
- Model.visualize_graph(name, fmt='svg', outfile=None, path=None, *, op_params=mappingproxy({'ExpandDims': 'elide', 'DimShuffle': 'elide'}), show_id=False, show_dtype=False, show_shape=False, const_arrays='elide', const_array_threshold=8)[source]¶
Visualize the computation graph for a distribution.
The defaults favor a figure that’s readable at a glance over one that exposes every implementation detail: dtype/shape annotations and toposort-index ids are hidden, single-input broadcasting plumbing ops (
ExpandDims,DimShuffle) are spliced out of the drawing, and constant arrays larger thanconst_array_thresholdcollapse to aconst[shape]placeholder. Pass the corresponding kwarg to bring any of that detail back.- Parameters:
name (str) – Distribution name.
fmt (str) – Output format (‘svg’, ‘png’, ‘pdf’). Defaults to ‘svg’.
outfile (str | None) – Output filename. If None, uses ‘{name}_graph.{fmt}’.
path (str | None) – Directory path for output. If None, uses current working directory.
op_params (
Literal['orig','elide','none'] |Mapping[str,Literal['orig','elide','none']]) – Per-op-name display mode, or one mode applied to every op."orig"keeps the op’s full label (e.g.Sum{axis=0});"none"drops the parameter block (Sum);"elide"removes the node from the drawing entirely, rewiring its consumers to its own (sole) input - only sound for single-input ops. Op names absent from a mapping default to"orig". Defaults to elidingExpandDims/DimShuffleonly.show_id (
bool) – Append each op’s toposort index to its label (e.g.Add id=9). Defaults toFalse.show_dtype (
bool) – Keep the dtype portion of PyTensor’s type annotations (e.g.Matrix(float32)). Defaults toFalse.show_shape (
bool) – Keep the shape portion of PyTensor’s type annotations (e.g.Matrix(shape=(1, 1))). Defaults toFalse.const_arrays (
Literal['orig','truncate','elide']) – How to render constant arrays larger thanconst_array_thresholdelements."orig"leaves pydotprint’s own (possibly mid-token-truncated) value dump untouched;"truncate"shows a deliberate[v0, v1, v2, ...] (shape)preview;"elide"collapses it toconst[shape]. Defaults to"elide".const_array_threshold (
int) – Element count above whichconst_arraysapplies. Defaults to 8.
- Returns:
Path to the generated visualization file.
- Return type:
- Raises:
ImportError – If pydot is not installed.
- Model.data¶
Observed data arrays from the workspace, keyed by observable name.
Only available when the model was built via
ws.model(analysis)orws.model(likelihood). RaisesRuntimeErrorotherwise.Returns a dict suitable for passing directly to a compiled or JAX function alongside
free_params:jg = pyhs3.jaxify(model.log_prob) jg(**model.data, **model.free_params)
- Model.free_params¶
Non-constant parameter values from the workspace parameter set.
Like
nominal_paramsbut excludes parameters whoseParameterPoint.constflag isTrue. These are the parameters that remain as free symbolic inputs after model construction, making this dict the correct one to pass to a jaxified callable:jg = pyhs3.jaxify(model.log_prob) jg(**model.data, **model.free_params)
- Model.log_prob[source]¶
Symbolic joint log-probability expression for the full likelihood.
Returned as a 1-D PyTensor
TensorVarof shape(M,), whereMis the parameter batch size. For all-scalar (non-vectorised) parametersM = 1; for a profile scan overMpoints the shape is(M,). Observable data and parameters listed infree_paramsare symbolic free inputs; parameters withconst=Trueare baked as compile-time constants and do not appear as free inputs. The expression is suitable for JAX transpilation, gradient computation, or direct PyTensor compilation.Normalization denominators are fixed constants (axis bounds baked at
Modelconstruction time). For unweighted data, the same compiled/JAX function can be evaluated against different event arrays. WeightedUnbinnedDataentries bake the weights as constants at construction time; to use different weights, a newModelmust be built.The workspace defaults for evaluation are available via
dataandfree_params.Only available when the model was built via
ws.model(analysis)orws.model(likelihood). RaisesRuntimeErrorotherwise.Example:
model = ws.model(ws.analyses["CombinedPdf_combData"]) nll = -2 * model.log_prob jg = pyhs3.jaxify(nll) val = jg(**model.data, **model.free_params)
- Model.nominal_params¶
Default parameter values from the workspace parameter set.
Returns all parameters, including those marked
const=True(which are baked aspytensor.tensor.constant()in the symbolic graph and are therefore not free inputs to a jaxified expression).Use
free_paramswhen passing parameters to a jaxified callable to avoid supplying spurious keyword arguments.