A Python port of the MATLAB UQ toolbox one directory up: distribution-independent uncertainty quantification from scarce samples, including data with extremes, using L-moments. Same method, same 9 supported distribution families, plus an interactive Streamlit UI.
No MATLAB installation was available while writing this port, so it was
not validated by diffing against MATLAB output. Instead, every
parameter-estimation formula and distribution-parameterization/sign
convention was validated by generating large synthetic samples from known
scipy.stats parameters and checking that this code recovers them — see
tests/test_lmoments.py (26 tests, all passing).
If you have MATLAB available, cross-checking a few outputs against the
original .m files would be a good next step.
cd python
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[ui,dev]"pytest tests/ -vpython demo_example.py --no-show # saves demo_example_output.pngstreamlit run app.pyLets you paste in a sample (or generate a synthetic scarce+extreme one), see its L-moments and the ranked distribution-family match, pick a family to fit, and view the PDF/CDF fit against the sample compared with a conventional-moment (MLE) fit of the same family, plus Jensen-Shannon divergence numbers quantifying the difference.
from lmoments import identify_dist, parameter_estimation, pdf_l, cdf_l, random_l, js_div
result = identify_dist(x) # {'best', 'ranking', 'L_sample'}
params = parameter_estimation(x, result['best'], *result['L_sample'])
pdf_vals = pdf_l(xgrid, result['best'], params)identify_distreturns the full ranked distance to all 9 candidate families (result['ranking']), not just the single closest match — a strict addition, useful for the UI's ranking table.parameter_identify(x, k)genuinely fits the top-kcandidates; the MATLAB version'sKargument silently breaks forK>1becauseIdentify_dist.mnever actually returns more than one candidate.- The Gamma distribution's location shift is applied consistently in both
pdf_landcdf_lin both implementations (MATLAB'sCDF_l.mhistorically omitted it; fixed as of the SoftwareX/JSS submission preparation). kl_div(p, q)returnsinfwhenphas mass in a bin whereqhas none (the mathematically correct value); MATLAB'sKLDiv.mdrops such bins and can return a finite — even negative — divergence there. This cannot affectjs_div, whose mixture term is positive whereverpis, andjs_divwas verified to machine precision againstscipy.spatial.distance.jensenshannon(see the divergence tests).weibulis supported inparameter_estimation/pdf_l/cdf_l/random_lfor completeness, but — matching the MATLAB version — is not one of the familiesidentify_distwill pick automatically.
- Weibull is not offered for automatic identification (see above).
- Gumbel is the k=0 special case of the GEV curve, and Uniform is the k=1
boundary case of the GP curve, on the L-moment ratio diagram; for
samples near those special cases,
identify_distcan pick either the special-case family or its generalizing family. This is a property of the diagram itself, not a bug (seetests/test_lmoments.pyfor how this is handled in testing).