Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import math
from .agri_seed_rate_types import SeedRate
from .math_round_div import round_div ← from math.round-div ^1.0.0 · built alongside by fune
from .math_round_float import round_float ← from math.round-float ^1.0.0 · built alongside by fune
def seed_rate(target_plants_per_square_metre: int, thousand_grain_weight_grams: float, establishment_basis_points: int) -> SeedRate:
"""Seed rate (kg/ha) = target plants/m2 x TGW (g) / expected establishment (%).
The TGW is taken to the centigram and the establishment is in basis points,
so kg/ha is exactly plants x centigrams / basis points and is rounded once.
Doing it in floats gets 100 x 1.15 / 100 = 1.1499999999999999, which rounds
to 1.1 kg/ha instead of 1.2.
"""
plants = target_plants_per_square_metre
if isinstance(plants, bool) or not isinstance(plants, int) or plants < 1 or plants > 100000:
raise ValueError("targetPlantsPerSquareMetre must be a whole number from 1 to 100000, received %r" % (plants,))
tgw = thousand_grain_weight_grams
if isinstance(tgw, bool) or not isinstance(tgw, (int, float)) or not math.isfinite(tgw) or tgw <= 0 or tgw > 1000:
raise ValueError("thousandGrainWeightGrams must be a finite number greater than 0 and at most 1000, received %r" % (tgw,))
centigrams = int(round(round_float(float(tgw), 2) * 100))
if centigrams < 1:
raise ValueError("thousandGrainWeightGrams must be at least 0.01 grams, received %r" % (tgw,))
bp = establishment_basis_points
if isinstance(bp, bool) or not isinstance(bp, int) or bp < 1 or bp > 10000:
raise ValueError("establishmentBasisPoints must be a whole number from 1 to 10000, received %r" % (bp,))
return SeedRate(
kg_per_hectare=round_div(plants * centigrams * 10, bp, "half-up") / 10,
seeds_per_square_metre=round_div(plants * 100000, bp, "half-up") / 10,
)