Skip to content

ProbUnitFloat

ProbUnitFloat

ProbUnitFloat(
    samples: Iterable[float],
    unit: Union[str, "CompoundUnit"],
)

An uncertain scalar quantity represented by Monte Carlo samples.

Stores n samples drawn from a probability distribution, all carrying the same physical unit. Arithmetic between two ProbUnitFloat instances is performed sample-wise, naturally propagating correlations introduced by shared inputs.

Do not construct directly — use the class factories: :meth:uniform, :meth:normal, :meth:triangular, :meth:lognormal.

Parameters passed to factories

unit : str or CompoundUnit Physical unit shared by all samples. n : int, optional Monte Carlo sample count. Defaults to the value set by :func:quantia.config (1 000 if not overridden).

Examples:

Basic uncertainty propagation:

>>> import quantia as qu
>>> with qu.config(n_samples=5000, seed=42):
...     eff      = qu.ProbUnitFloat.uniform(0.88, 0.95, '1')
...     power_in = qu.ProbUnitFloat.normal(500.0, 10.0, 'W')
>>> power_out = eff * power_in
>>> power_out.mean()
UnitFloat(457..., 'W')
>>> lo, hi = power_out.interval(0.90)

Petroleum OOIP with uncertain Bo:

>>> with qu.config(seed=0, n_samples=3000):
...     Bo = qu.ProbUnitFloat.normal(1.25, 0.05, 'm3_res')
>>> Vp   = qu.Q(1_000_000.0, 'm3_res')
>>> ooip = Vp * 0.75 / (Bo / qu.Q(1.0, 'm3_sc'))
>>> ooip.percentile(10)   # P10
UnitFloat(..., ...)

interval

interval(
    confidence: float = 0.95,
) -> tuple["UnitFloat", "UnitFloat"]

Return a central confidence interval from the sample distribution.

Parameters:

Name Type Description Default
confidence float

Confidence level in (0, 1). Default 0.95 returns the P2.5–P97.5 range. Use 0.80 for P10–P90 (common in petroleum).

0.95

Returns:

Type Description
tuple of (UnitFloat, UnitFloat)

(lower_bound, upper_bound) at the requested confidence level.

Raises:

Type Description
ValueError

If confidence is not in (0, 1).

Examples:

>>> lo, hi = power_out.interval(0.90)   # P10–P90
>>> lo, hi = power_out.interval(0.80)   # P10–P90 (petroleum convention)

lognormal classmethod

lognormal(
    mean: float,
    std: float,
    unit: Union[str, "CompoundUnit"],
    n: int | None = None,
) -> "ProbUnitFloat"

Create samples from a log-normal distribution.

Parameters:

Name Type Description Default
mean float

Mean of the underlying normal distribution (i.e. ln X ~ N(mean, std)).

required
std float

Standard deviation of the underlying normal. Must be > 0.

required
unit str or CompoundUnit

Physical unit for all samples.

required
n int

Sample count.

None

Returns:

Type Description
ProbUnitFloat

Raises:

Type Description
ValueError

If std <= 0.

mean

mean() -> 'UnitFloat'

Return the sample mean.

Returns:

Type Description
UnitFloat

Mean value in the distribution's unit.

Examples:

>>> with qu.config(seed=0, n_samples=10000):
...     x = qu.ProbUnitFloat.uniform(0.0, 10.0, 'm')
>>> x.mean().value   # ≈ 5.0
5.0...

median

median() -> 'UnitFloat'

Return the sample median (P50).

Returns:

Type Description
UnitFloat

Median value in the distribution's unit.

normal classmethod

normal(
    mean: float,
    std: float,
    unit: Union[str, "CompoundUnit"],
    n: int | None = None,
) -> "ProbUnitFloat"

Create samples from a normal distribution N(mean, std).

Parameters:

Name Type Description Default
mean float

Distribution mean.

required
std float

Standard deviation. Must be strictly positive.

required
unit str or CompoundUnit

Physical unit for all samples.

required
n int

Sample count.

None

Returns:

Type Description
ProbUnitFloat

Raises:

Type Description
ValueError

If std <= 0.

Examples:

>>> with qu.config(seed=42):
...     p = qu.ProbUnitFloat.normal(3000.0, 200.0, 'psia')
>>> p.std().value
200...

percentile

percentile(p: float) -> 'UnitFloat'

Return the p-th percentile of the sample distribution.

Parameters:

Name Type Description Default
p float

Percentile value in [0, 100]. P10 = pessimistic, P50 = median, P90 = optimistic (petroleum convention: P10 is the low case).

required

Returns:

Type Description
UnitFloat

The p-th percentile in the distribution's unit.

Raises:

Type Description
ValueError

If p is not in [0, 100].

Examples:

>>> ooip.percentile(10)    # P10 — low case
UnitFloat(..., 'bbl')
>>> ooip.percentile(50)    # P50 — base case
UnitFloat(..., 'bbl')
>>> ooip.percentile(90)    # P90 — high case
UnitFloat(..., 'bbl')

std

std() -> 'UnitFloat'

Return the sample standard deviation.

Uses Welford's online algorithm (single pass, numerically stable).

Returns:

Type Description
UnitFloat

Standard deviation in the distribution's unit.

triangular classmethod

triangular(
    low: float,
    mode: float,
    high: float,
    unit: Union[str, "CompoundUnit"],
    n: int | None = None,
) -> "ProbUnitFloat"

Create samples from a triangular distribution.

Parameters:

Name Type Description Default
low float

Minimum value.

required
mode float

Most likely value. Must satisfy low <= mode <= high.

required
high float

Maximum value. Must be strictly greater than low.

required
unit str or CompoundUnit

Physical unit for all samples.

required
n int

Sample count.

None

Returns:

Type Description
ProbUnitFloat

Raises:

Type Description
ValueError

If low > mode, mode > high, or low == high.

Examples:

>>> with qu.config(seed=1):
...     h = qu.ProbUnitFloat.triangular(10.0, 15.0, 22.0, 'm')

uniform classmethod

uniform(
    low: float,
    high: float,
    unit: Union[str, "CompoundUnit"],
    n: int | None = None,
) -> "ProbUnitFloat"

Create samples from a uniform distribution U(low, high).

Parameters:

Name Type Description Default
low float

Lower bound (inclusive).

required
high float

Upper bound. Must be strictly greater than low.

required
unit str or CompoundUnit

Physical unit for all samples.

required
n int

Sample count. Defaults to active :func:~quantia.config value.

None

Returns:

Type Description
ProbUnitFloat

Raises:

Type Description
ValueError

If low >= high.

Examples:

>>> with qu.config(seed=0):
...     eff = qu.ProbUnitFloat.uniform(0.88, 0.95, '1')
>>> eff.mean().value
0.915...