Repository navigation
Decide concentration limits on the laboratory analysis, not the charge-balanced water (#84) - #85
Merged
Merged
Conversation
…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.
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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)
analytical_water_totalsfor rows and limits; balanced totals for the doseflahax batch(#79)diluted()_judgeas dosed candidatesStatus precedence
requires_review, with both valuesA 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)
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.CO3-2 = 0means measured carbon-free; carbon that is not reported at all is stillmissing_carbon.below_detectioncomponents (their detection limits are recorded).reconciledonly when the adjustment is within a statedbalance_ion_uncertainty_percent; otherwisereconciliation_out_of_bounds.assumed, and the chemistry stage plus every plan built on it isrequires_review.fixed_balance_ion, and no other ion is tried automatically.BalancedWaterAnalysiskeepsanalytical_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.35declares a maximum; undeclared limits are never assumed, and the report says so.below_detection,balance_ionandbalance_ion_uncertainty_percent.Tomato and publication changes (before → after)
Advanced tomato example (
python -m examples.tomato_advanced):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 inpaper.md,field-article/draft.mdorstory/en.md/ar.mdchanges; the drafts are untouched.Validation
FLAHAX_REQUIRE_PHREEQC=1unittest: 423 tests OK, including 18 new tests intests/test_analytical_water.pyverify_distribution: PASSsphinx -W: clean--check: okgit diff --checkok; no CRLF