00. Getting started

Language: Python (Jupyter notebook) - R version

Ported from 00_getting_started.ipynb in the USACE-RMC Numerics-Python-Examples repository (0BSD licensed). The upstream notebook drives the C# Numerics.dll through pythonnet; this version uses corehydropy, whose compiled core is a validated C++ port of the same library, so the numbers below reproduce the upstream outputs exactly. The R version of this example uses the same core and prints the same numbers.

What you’ll learn

  • How to install corehydropy and check the installation.
  • How to create a distribution and compute basic statistics.
  • What of the upstream setup you can skip entirely (spoiler: all of it).

Install

The upstream notebook spends its first four steps on .NET plumbing: installing a .NET runtime, obtaining Numerics.dll from NuGet, loading the CoreCLR runtime with pythonnet.load("coreclr") before importing clr, and resolving the DLL path. None of that exists here. corehydropy ships the ported library as a regular compiled Python extension:

pip install corehydropy

There is no runtime to select, no DLL to resolve, and results are identical on macOS, Linux, and Windows.

import corehydropy as ch

print("corehydropy imported successfully")
corehydropy imported successfully

Basic example: Normal distribution

Create a Normal distribution and compute basic statistics. The upstream code is Normal(100, 15) with property access (dist.Mean, dist.StandardDeviation, …); here every family is constructed by name through the Distribution class, and the moments come back in one dict.

dist = ch.Distribution("Normal", [100, 15])
m = dist.moments()

print(f"Mean: {m['mean']}")
print(f"Standard Deviation: {m['sd']}")
print(f"Variance: {m['sd']**2}")
print(f"Skewness: {m['skewness']}")
# Numerics reports Pearson kurtosis (raw fourth-moment form): 3.0 for a Normal.
# The "excess kurtosis" convention used by scipy/numpy is Pearson - 3.
print(f"Kurtosis: {m['kurtosis']}")

print("\nSmall sanity check")
print(f"{ch.Distribution('Normal', [0, 1]).cdf(0)} ~= 0.5")
Mean: 100.0
Standard Deviation: 15.0
Variance: 225.0
Skewness: 0.0
Kurtosis: 3.0

Small sanity check
0.5 ~= 0.5

No .NET arrays, no function wrappers

The upstream notebook needs System.Array[Double](python_list) conversions for data, and a LogLikelihood(...) delegate to wrap Python functions for the C# samplers. With corehydropy, plain lists and NumPy arrays work everywhere:

data = [12.0, 15.5, 14.2, 16.8, 13.9]

# Log-likelihood of the data under Normal(mean=14, sd=2), evaluated in the core
ll = ch.Distribution("Normal", [14, 2]).log_likelihood(data)
print(f"log-likelihood: {ll:.6f}")
log-likelihood: -9.827929

A first taste of seeded reproducibility

The port keeps the C# Mersenne Twister bit-exact, so seeded draws match the upstream library (and the R package) exactly. Later examples lean on this heavily.

draws = dist.random(5, seed=123)
print(draws)
[107.7140845  108.43058699  91.52951859  97.29597376  88.76115969]

Reproduction check

Values printed by the upstream notebook (run against the real C# library), compared with this port. Everything here is deterministic, so the match is exact.

Quantity Upstream C# This port Status
Normal(100,15).Mean 100.0 m['mean'] exact
Normal(100,15).StandardDeviation 15.0 m['sd'] exact
Normal(100,15).Variance 225.0 m['sd']**2 exact
Normal(100,15).Skewness 0.0 m['skewness'] exact
Normal(100,15).Kurtosis 3.0 m['kurtosis'] exact
Normal(0,1).CDF(0) 0.5 .cdf(0) exact

The cell below fails the notebook if any value drifts.

# Upstream reference values: notebook 00_getting_started.ipynb, cell 9 output.
assert m["mean"] == 100.0
assert m["sd"] == 15.0
assert m["sd"] ** 2 == 225.0
assert m["skewness"] == 0.0
assert m["kurtosis"] == 3.0
assert ch.Distribution("Normal", [0, 1]).cdf(0) == 0.5
# First seeded draw, identical across Python, R, and the C# library.
assert draws[0] == 107.71408449723363
print("All reproduction checks passed.")
All reproduction checks passed.