Typed pharmacometric model authoring¶
The pharmacometric DSL executes ordinary Python declarations to build typed
symbolic objects. It does not parse arbitrary model text. The output is a
validated pymixef.pharmacometrics.dsl.CompiledModel and then the
same versioned pymixef.ir.ModelIR used by the rest of PyMixEF.
Declare a model¶
from pymixef.pharmacometrics import (
Dose,
Eta,
Param,
State,
additive,
covariate,
d,
exp,
model,
observe,
)
@model(name="one_compartment_population_pk")
def population_pk():
tvcl = Param.positive("tvcl", init=5.0, unit="L/h")
volume = Param.positive("volume", init=25.0, unit="L")
sigma = Param.positive("sigma", init=0.2, unit="mg/L")
eta_cl = Eta.independent("eta_cl", block="omega_cl", level="subject")
weight = covariate("weight", unit="kg", reference=70.0)
central = State("central", unit="mg", initial=0.0)
clearance = tvcl * (weight / 70.0) ** 0.75 * exp(eta_cl)
equation = d(central, -(clearance / volume) * central)
dose = Dose.into(central, amount="AMT", rate="RATE", duration="DUR")
observation = observe(
"DV",
mean=central / volume,
error=additive(sigma),
)
return equation, dose, observation
compiled = population_pk()
print(compiled.explain())
The pymixef.pharmacometrics.dsl.model() decorator returns a
pymixef.pharmacometrics.dsl.ModelDefinition. Calling it executes the
declaration, collects returned components, validates them, and creates a
pymixef.pharmacometrics.dsl.CompiledModel.
The example declares the symbolic equations
Symbolic building blocks¶
Object/helper |
Role |
|---|---|
declared fixed/model parameters and constraints |
|
random effects, covariance block, and hierarchy level |
|
predictors with role, unit, and reference |
|
dynamic state and initial value |
|
differential equation for a state |
|
event fields mapped into a state |
|
endpoint, structural mean, error, and optional censoring |
|
typed symbolic transforms |
Expr.format() supports review, Expr.to_dict() supports serialization, and
Expr.evaluate() evaluates against an explicit symbol environment.
Constraints and transforms¶
Parameter declarations preserve support:
real → identity transform;
positive → log transform;
bounded → bounded transform with explicit lower/upper values.
Constraints become pymixef.ir.ParameterIR and
pymixef.ir.TransformIR nodes. Units are metadata and
are not automatically converted.
Random-effect blocks¶
An pymixef.pharmacometrics.dsl.Eta names the random effect, block,
covariance mode (diagonal or
correlated), and level such as subject. The DSL can represent richer blocks
than the integrated estimator currently supports; check validation compatibility
rather than assuming representability implies estimability.
Validate capability¶
validation = compiled.validate()
print(validation.valid)
print(validation.dimensions)
print(validation.estimator_compatibility)
for message in validation.messages:
print(message.to_dict())
Compatibility entries currently distinguish simulation, conditional-mode, FOCEI, and SAEM support. A syntactically valid model can still be incompatible with an estimator.
Compile to ModelIR¶
ir = compiled.to_ir()
print(ir.schema_version)
print(ir.semantic_hash)
print(ir.to_json(indent=2))
The IR contains typed parameter, random-effect, predictor, state-equation,
event, likelihood, transform, and output nodes with explicit dependencies.
Round-trip with pymixef.ir.ModelIR.from_json(); semantic equality and hash preservation
are testable.
Node counts and a valid dependency graph describe the model contract. They do not establish identifiability, estimator readiness, biological plausibility, or adequate data.
Programmatic construction¶
pymixef.pharmacometrics.dsl.compiled_model() constructs a
pymixef.pharmacometrics.dsl.CompiledModel directly from component
sequences. pymixef.pharmacometrics.dsl.ModelDefinition.compile(),
validate(),
explain(),
to_dict(),
to_ir(), and
declaration_signature
expose each stage without requiring an implicit fit.