8000 Decide concentration limits on the laboratory analysis, not the charge-balanced water (#84) by rafatahmed · Pull Request #85 · rafatahmed/Flahax · GitHub
[go: up one dir, main page]

Skip to content

Decide concentration limits on the laboratory analysis, not the charge-balanced water (#84) - #85

Merged
rafatahmed merged 1 commit into
mainfrom
fix/analytical-water-limits
Oct 22, 2026
Merged

rafatahmed merged 1 commit into
mainfrom
fix/analytical-water-limits

Conversation

@rafatahmed
Copy link
Copy Markdown
Owner

Closes #84.

The rule

Nutrient targets and maximum concentrations are decided on the laboratory analysis after blending + products + pH reagent, at the final volume. The charge-balanced water is an input to chemistry only: pH, speciation, saturation, EC and reagent dose.

What was wrong (evidence in #84)

Path Before Now
Nitric delivery stage rows and limits rebuilt from balanced totals analytical_water_totals for rows and limits; balanced totals for the dose
flahax batch (#79) formulated on balanced mg/L nutrients straight from the analysis file
Tomato example blend chosen on the model: 9% blend chosen on the lab values: 8%
Publication example Na and Cl printed from the model lab values; chemistry from diluted()
pH plan, no reagent needed skipped the limit and saturation checks same _judge as dosed candidates

Status precedence

Result Status
Lab-basis concentration above a declared maximum blocked
Lab basis passes, but the balanced model would fail it (or the reverse) requires_review, with both values
Both agree and pass other checks decide

A review never downgrades a block. This holds in the workflow stages, in the final check of the selected pH plan, and in summarize_batch.

Balancing made explicit (owner follow-up)

  • Already balanced: an analysis whose charge closes at its measured pH within CLOSURE_TOLERANCE (0.0001% of total charge) is used unchanged and needs no balance ion. This tolerance is separate from the 5% screen. Pure water, KNO3 and KHCO3 chloride-free solutions now pass.
  • Zero, missing, below detection:
    • CO3-2 = 0 means measured carbon-free; carbon that is not reported at all is still missing_carbon.
    • Measured zeros are held fixed, and so are below_detection components (their detection limits are recorded).
  • Reconciliation:
    • reconciled only when the adjustment is within a stated balance_ion_uncertainty_percent; otherwise reconciliation_out_of_bounds.
    • Without a stated uncertainty the closure is assumed, and the chemistry stage plus every plan built on it is requires_review.
    • Never fixed_balance_ion, and no other ion is tried automatically.
  • Record: BalancedWaterAnalysis keeps analytical_totals (defensively copied), the analysis ID, units, the fixed and below-detection components, and the reconciliation state. diluted(fraction) blends with ion-free water only; it scales both inventories, recomputes the chemistry and keeps the measured pH as metadata.

CLI and report

  • flahax batch --limit Cl=106.35 declares a maximum; undeclared limits are never assumed, and the report says so.
  • The water file accepts measured zeros, below_detection, balance_ion and balance_ion_uncertainty_percent.
  • The report shows lab, modelled and adjusted water side by side, plus each limit wi 8000 th its decision basis.
  • The batch sheet shows the limits on the lab basis, under a prominent status box.

Tomato and publication changes (before → after)

Advanced tomato example (python -m examples.tomato_advanced):

Item Before (9%) After (8%)
Blend Cl / Na, mg/L 104.3 (model) / 61.2 102.4 / 54.4 (lab); 9% is 115.2 lab, fails
Phosphoric withdrawn 70 g/batch, pH 3.77 62 g, pH 3.83
Calcium nitrate 1034.1 g 1045.5 g
Mg nitrate 522.3 g 532.6 g
K nitrate 105.2 g 88.3 g
K sulfate 604.8 g 619.4 g
Ammonium sulfate 25.7 g 25.1 g
Mixed feed pH 5.89 5.84
Nitric to pH 5.5 12 mL, +2.1 mg N/L 9 mL, +1.7 mg N/L
EC25 acidified 3.07 mS/cm 3.04 mS/cm
HAP / MnHPO4 SI after acid 1.94 / 2.94 1.95 / 2.94
Stage 1 / 2 / 3 worst miss 0.0 / 0.1 / 26.1% 0.6 / 0.4 / 26.5%

Publication example (qatar_tomato.py, 1:3 blend kept): the recipe, acid dose, pH and SI are unchanged. Only the printed blend chloride changes, 290 → 320 mg/L (the lab value). No number quoted in paper.md, field-article/draft.md or story/en.md/ar.md changes; the drafts are untouched.

Validation

  • FLAHAX_REQUIRE_PHREEQC=1 unittest: 423 tests OK, including 18 new tests in tests/test_analytical_water.py
  • verify_distribution: PASS
  • sphinx -W: clean
  • API reference --check: ok
  • git diff --check ok; no CRLF
  • Regenerated tomato report, batch sheets and a well-water CLI report inspected in the browser

…e-balanced water (#84)

balance_water_analysis closes an analysis' charge on chloride or sodium, a
modelling step for speciation, but its totals were passed on as the water.
The nitric delivery stage rebuilt nutrient rows and limits from them, flahax
batch formulated on them, and the tomato example chose its blend on them: on
station 104 the model has 1158.5 mg/L Cl against 1280.4 measured, so 9% well
water passed the 3 mmol/L limit although it is 115.2 mg/L measured (8% is the
largest passing share). Balancing on sodium could likewise reject a water
that passes on its measurement.

- BalancedWaterAnalysis keeps analytical_totals (the analysis as entered)
  beside the model, with provenance; diluted() scales both and recomputes
  the blend's chemistry.
- The workflow accepts a prepared water_balance, rejects contradictory water
  inputs, passes analytical_water_totals to plan_equilibrium_delivery (rows
  and limits on the analysis, dose on the chemistry) and reports both waters
  in water_basis. A decision the balancing alone would flip asks for review;
  a laboratory-basis exceedance always blocks; review never downgrades a block.
- The no-reagent-needed pH candidate now gets the limit and saturation checks
  dosed candidates get, and the selected plan's limits are rechecked.
- Balancing is explicit: an analysis already closed at its measured pH is used
  unchanged and needs no balance ion; CO3-2 = 0 is measured carbon-free; zeros
  and below-detection components are fixed; the closure is reconciled only
  within a stated uncertainty, otherwise assumed and flagged for review; no
  other ion is tried automatically.
- flahax batch takes nutrients from the analysis file, accepts zeros,
  detection limits, balance ion and uncertainty, and gains --limit; the report
  and sheet show the decision basis.
- Tomato example recomputed at 8%; publication example keeps its 1:3 blend
  and separates accounting from chemistry.
@read-the-docs-community
Copy link
Copy Markdown

Documentation build overview

📚 Flahax | 🛠️ Build #35326128 | 📁 Comparing c8d9ae9 against latest (a07aab6)

  🔍 Preview build  

5 files changed · ± 5 modified

± Modified

@rafatahmed
rafatahmed merged commit 76d1044 into main Oct 22, 2026
6 checks passed
@rafatahmed
rafatahmed deleted the fix/analytical-water-limits branch October 22, 2026 13:22
@rafatahmed rafatahmed self-assigned this Oct 23, 2026
rafatahmed added a commit that referenced this pull request Nov 7, 2026
Decide concentration limits on the laboratory analysis, not the charge-balanced water (#84)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Concentration limits use charge-balanced water instead of the laboratory analysis

1 participant

0