lactationcurve
A package for fitting dairy animal lactation curves, evaluating lactation curve characteristics (LCCs) (time to peak, peak yield, cumulative yield, persistency), and computing 305-day milk yield using the ICAR guideline.
Contact: Meike van Leerdam, mbv32@cornell.edu
Authors: Meike van Leerdam,Judith Osei-Tete, Douwe de Kok, Lucia Trapanese
Initial authored: 2025‑08‑12
Updated: 2026‑02‑24
Main Lactation curve models implemented:
MilkBot: Flexible four-parameter model describing rise, peak, and decline. (Both frequentist and Bayesian fitting available)
Wood: Incomplete gamma function; most popular due to its simplicity, its stability in the presence of missing data, and its computational ease.
Wilmink: Linear–exponential hybrid model, with fixed or estimated decay rate.
Ali & Schaeffer: Polynomial-logarithmic model with a linear regression component for more complex curve shapes.
Fischer: Simple exponential decay model.
Additional models available for a.o. symbolic LCC derivations: Brody, Sikka, Nelder, Dhanoa, Emmans, Hayashi, Rook, Dijkstra, Prasad.
Model Formulas
- Wood :
y(t) = a * t^b * exp(-c * t) - Wilmink :
y(t) = a + b * t + c * exp(k * t)with defaultk = -0.05 Ali & Schaeffer :
t_scaled = t / 305,L = ln(305 / t)y(t) = a + b*t_scaled + c*t_scaled^2 + d*L + k*L^2- Fischer :
y(t) = a - b*t - a*exp(-c*t) - MilkBot :
y(t) = a * (1 - exp((c - t)/b) / 2) * exp(-d*t)
Features
- Frequentist fitting (numeric optimization & least squares):
- Wood, Wilmink, Ali & Schaeffer, Fischer, MilkBot
- Bayesian fitting via MilkBot API:
- MilkBot
- Lactation Curve Characteristics — symbolic + numeric:
- time_to_peak, peak_yield, cumulative_milk_yield, persistency
- ICAR procedures cumulative milk yield:
- Test Interval Method
- Input validation/normalization via
validate_and_prepare_inputs - Caching of symbolic expressions for performance
API Overview
The package is organized into three main modules:
Output Types Summary Of Most Important Functions
| Function | Output |
|---------|--------|
| fit_lactation_curve | Predicted yields (np.ndarray) |
| get_lc_parameters | Tuple of numerical parameters |
| bayesian_fit_milkbot_single_lactation | Dict of MilkBot parameters |
| lactation_curve_characteristic_function | (expr, params, func) |
| calculate_characteristic | float (LCC value) |
| test_interval_method | DataFrame with 305‑day totals |
Bayesian Fitting (MilkBot API)
- Set
fitting="bayesian"andmodel="milkbot"infit_lactation_curveorcalculate_characteristic. - Provide an API key via .env
- Choose priors via
continent="USA" | "EU" | "CHEN"(CHEN supplies published priors from literature). - The helper
bayesian_fit_milkbot_single_lactation(...)normalizes differing API responses. - The key can be requested by sending an email to Jim Ehrlich jehrlich@MilkBot.com.
- More information about the API can be found in the API documentation, or in the corresponding paper.
Citing the lactationcurve package
If you use the lactationcurve package in your research, please consider citing it as follows:
van Leerdam, M. B., de Kok, D., Osei-Tete, J. A., & Hostens, M. (2026). Bovi-analytics/lactation_curve_core: v.0.1.0. (v.0.1.0). Zenodo. https://doi.org/10.5281/zenodo.18715145
If you also use the Bayesian fitting functionality that relies on the MilkBot API, please also cite the following paper:
Ehrlich, J.L., 2013. Quantifying inter-group variability in lactation curve shape and magnitude with the MilkBot lactation model. PeerJ 1, e54. https://doi.org/10.7717/peerj.54
License
Current version of the package
1""" 2 3A package for fitting **dairy animal lactation curves**, evaluating 4**lactation curve characteristics (LCCs)** (time to peak, peak yield, 5cumulative yield, persistency), and computing **305-day milk yield** 6using the **ICAR guideline**. 7 8> **Contact:** Meike van Leerdam, mbv32@cornell.edu 9> 10> **Authors:** Meike van Leerdam,Judith Osei-Tete, Douwe de Kok, Lucia Trapanese 11 12> **Initial authored:** 2025‑08‑12 13 14> **Updated:** 2026‑02‑24 15 16--- 17 18## Main Lactation curve models implemented: 19 20MilkBot: Flexible four-parameter model describing rise, peak, 21and decline. (Both frequentist and Bayesian fitting available) 22 23Wood: Incomplete gamma function; most popular due to its simplicity, 24its stability in the presence of missing data, and its 25computational ease. 26 27Wilmink: Linear–exponential hybrid model, with fixed or estimated decay rate. 28 29Ali & Schaeffer: Polynomial-logarithmic model with a linear 30regression component for more complex curve shapes. 31 32Fischer: Simple exponential decay model. 33 34Additional models available for a.o. symbolic LCC derivations: 35**Brody**, **Sikka**, **Nelder**, **Dhanoa**, **Emmans**, 36**Hayashi**, **Rook**, **Dijkstra**, **Prasad**. 37 38--- 39 40## Model Formulas 41 42* **Wood** : `y(t) = a * t^b * exp(-c * t)` 43* **Wilmink** : `y(t) = a + b * t + c * exp(k * t)` with default `k = -0.05` 44* **Ali & Schaeffer** : `t_scaled = t / 305`, `L = ln(305 / t)` 45 46 `y(t) = a + b*t_scaled + c*t_scaled^2 + d*L + k*L^2` 47* **Fischer** : `y(t) = a - b*t - a*exp(-c*t)` 48* **MilkBot** : `y(t) = a * (1 - exp((c - t)/b) / 2) * exp(-d*t)` 49 50--- 51 52## Features 53 54- **Frequentist fitting** (numeric optimization & least squares): 55 - Wood, Wilmink, Ali & Schaeffer, Fischer, MilkBot 56- **Bayesian fitting via MilkBot API**: 57 - MilkBot 58- **Lactation Curve Characteristics** — symbolic + numeric: 59 - time_to_peak, peak_yield, cumulative_milk_yield, persistency 60- **ICAR procedures cumulative milk yield:** 61 - Test Interval Method 62- Input validation/normalization via `validate_and_prepare_inputs` 63- Caching of symbolic expressions for performance 64 65--- 66 67## API Overview 68 69The package is organized into three main modules: 70 711. `lactationcurve.fitting` 722. `lactationcurve.characteristics` 733. `lactationcurve.preprocessing` 74 75--- 76 77## Output Types Summary Of Most Important Functions 78 79| Function | Output | 80 81|---------|--------| 82 83| `fit_lactation_curve` | Predicted yields (np.ndarray) | 84 85| `get_lc_parameters` | Tuple of numerical parameters | 86 87| `bayesian_fit_milkbot_single_lactation` | Dict of MilkBot parameters | 88 89| `lactation_curve_characteristic_function` | (expr, params, func) | 90 91| `calculate_characteristic` | float (LCC value) | 92 93| `test_interval_method` | DataFrame with 305‑day totals | 94 95--- 96 97## Bayesian Fitting (MilkBot API) 98 99* Set `fitting="bayesian"` and `model="milkbot"` in 100 `fit_lactation_curve` or `calculate_characteristic`. 101* Provide an **API key** via .env 102* Choose priors via `continent="USA" | "EU" | "CHEN"` 103 ([CHEN](https://github.com/Bovi-analytics/Chen-et-al-2023b) 104 supplies published priors from literature). 105* The helper `bayesian_fit_milkbot_single_lactation(...)` 106 normalizes differing API responses. 107* The key can be requested by sending an email to Jim Ehrlich 108 [jehrlich@MilkBot.com](mailto:jehrlich@MilkBot.com). 109* More information about the API can be found in the 110 [API documentation](https://api.milkbot.com/), or in the 111 corresponding 112 [paper](https://peerj.com/articles/54/#MainContent). 113 114--- 115 116## Citing the lactationcurve package 117 118If you use the `lactationcurve` package in your research, please consider citing it as follows: 119 120*van Leerdam, M. B., de Kok, D., Osei-Tete, J. A., & 121Hostens, M. (2026). Bovi-analytics/lactation_curve_core: 122v.0.1.0. (v.0.1.0). Zenodo. 123https://doi.org/10.5281/zenodo.18715145* 124 125 126If you also use the Bayesian fitting functionality that relies 127on the MilkBot API, please also cite the following paper: 128 129*Ehrlich, J.L., 2013. Quantifying inter-group variability 130in lactation curve shape and magnitude with the MilkBot 131lactation model. PeerJ 1, e54. 132https://doi.org/10.7717/peerj.54* 133 134--- 135 136## License 137 138[MIT License](https://github.com/Bovi-analytics/lactation_curve_core/blob/master/LICENSE) 139 140 141--- 142 143## Current version of the package 144 145""" 146 147 148# import submodules to make them available at the package level 149 150from . import characteristics, fitting, preprocessing 151 152__all__ = ["fitting", "characteristics", "preprocessing"] 153# from .characteristics import ( 154# calculate_characteristic, 155# lactation_curve_characteristic_function, 156# numeric_cumulative_yield, 157# numeric_peak_yield, 158# numeric_time_to_peak, 159# persistency_fitted_curve, 160# persistency_milkbot, 161# persistency_wood, 162# test_interval_method, 163# ) 164# from .fitting import ( 165# ali_schaeffer_model, 166# bayesian_fit_milkbot_single_lactation, 167# brody_model, 168# dhanoa_model, 169# dijkstra_model, 170# emmans_model, 171# fischer_model, 172# fit_lactation_curve, 173# get_chen_priors, 174# get_lc_parameters, 175# get_lc_parameters_least_squares, 176# hayashi_model, 177# milkbot_model, 178# nelder_model, 179# prasad_model, 180# rook_model, 181# sikka_model, 182# wilmink_model, 183# wood_model, 184# ) 185# from .preprocessing import ( 186# PreparedInputs, 187# standardize_lactation_columns, 188# validate_and_prepare_inputs, 189# ) 190 191# __all__ = [ 192# # Preprocessing 193# "PreparedInputs", 194# "standardize_lactation_columns", 195# "validate_and_prepare_inputs", 196# # Fitting 197# "ali_schaeffer_model", 198# "bayesian_fit_milkbot_single_lactation", 199# "brody_model", 200# "dhanoa_model", 201# "dijkstra_model", 202# "emmans_model", 203# "fischer_model", 204# "fit_lactation_curve", 205# "get_chen_priors", 206# "get_lc_parameters", 207# "get_lc_parameters_least_squares", 208# "hayashi_model", 209# "milkbot_model", 210# "nelder_model", 211# "prasad_model", 212# "rook_model", 213# "sikka_model", 214# "wilmink_model", 215# "wood_model", 216# # Characteristics 217# "calculate_characteristic", 218# "lactation_curve_characteristic_function", 219# "numeric_cumulative_yield", 220# "numeric_peak_yield", 221# "numeric_time_to_peak", 222# "persistency_fitted_curve", 223# "persistency_milkbot", 224# "persistency_wood", 225# "test_interval_method", 226# ] 227 228# Expose package version (try metadata, fall back to a sensible dev string) 229try: 230 from importlib.metadata import PackageNotFoundError, version 231except Exception: 232 try: 233 from importlib_metadata import PackageNotFoundError, version # type: ignore 234 except Exception: 235 version = None 236 PackageNotFoundError = Exception 237 238if version: 239 try: 240 __version__ = version("lactationcurve") 241 except PackageNotFoundError: 242 __version__ = "0+dev" 243else: 244 __version__ = "0+dev" 245 246__all__.append("__version__")