Skip to content

Score transparency — indicator explanations, scoring curves & open-source metadata #598

@SvenVw

Description

@SvenVw

Background

The BLN3 scoring system can feel like a "black box" to users: they see a score but don't understand why their field received it. Research into best practices for agricultural soil quality tools has identified compelling UX patterns for making scores transparent — interactive scoring curves, rich indicator descriptions, visible formulas, and guided explanation wizards.

These features depend on having access to the open-source BLN3 calculator code. For OBI, this already exists at nmi-agro/Open-Bodem-Index-Calculator. The BLN3 calculator will follow the same open-source model, but is not yet available. This issue should be implemented once the BLN3 calculator is open-sourced.

Key UX patterns for score transparency

The following patterns have been identified as best practices for soil quality score transparency:

  1. Framework View: A flow diagram (Inputs → Indicators → Soil Functions → Score) showing the entire calculation pipeline at a glance. Each step is clickable.
  2. Simulator: Indicator values as interactive sliders. Adjusting any value instantly recalculates the final score, giving users a "what-if" experience.
  3. Indicator Detail: Clicking any indicator shows:
    • A plain-language explanation (e.g., "Stikstof is meestal het eerst beperkende nutriënt. De N-levering (NLV) is de meerjarig gemiddelde hoeveelheid N die in het groeiseizoen beschikbaar komt via mineralisatie van organische stof. Voor grasland ligt het optimum rond 140 kg N/ha, voor bouwland rond 100.")
    • An SVG scoring curve showing the mathematical function with the current value plotted as a dot with crosshairs
    • The formula in monospace text
    • A score ring (circular progress) with verbal verdict

What we adopt (and don't)

Adopt:

  • Indicator explanations (descriptions, why-it-matters, optimal ranges)
  • Scoring curve SVG visualizations in the indicator deep-dive
  • Formula transparency for expert users
  • Calculation pipeline visibility (lightweight flow indicator)

Don't adopt:

  • Full slider simulator on raw soil values (inappropriate for real production data — users can't change their lab results)
  • Standalone 4-column framework diagram (too complex for embedded use; simplified flow indicator instead)
  • Standalone design/aesthetic (fdm-app has its own design system)

The measures impact toggle ("Met/zonder maatregelen") in issue-bln3-3 and issue-bln3-4 provides the equivalent of the simulator experience — applied to something the user can actually control.

User Stories

As an advisor, I want to understand why an indicator has a certain score — what was measured, what the formula is, and how my field compares to the optimum — so I can explain results to farmers.

As an advisor, I want to see the scoring curve for each indicator so I can understand the relationship between measured values and scores without reading academic papers.

As a farmer, I want a plain-language explanation of each indicator (what it means, why it matters for my crops) so I don't need to be a soil scientist to use this tool.

As a researcher, I want to see the actual scoring formula so I can verify the calculation and build trust in the system.

Acceptance Criteria

Indicator Metadata Package (fdm-data or dedicated package)

  • A bln3-indicator-metadata module exists, exporting a Bln3IndicatorMetadata[] array
  • Each of the 28 BLN3 indicators has metadata including: indicator_id, name, description, why_it_matters, unit, optimal_range, scoring_function, formula_text, category
  • Scoring function parameters are extracted from the open-source BLN3 calculator (R/Python → TypeScript)
  • Descriptions are sourced from BLN3 documentation and agronomic literature
  • Package is published and importable by fdm-app
  • Metadata is static JSON — no API calls needed for the visualization layer

Scoring Curve Component (fdm-app)

  • A reusable <ScoringCurve indicator={metadata} currentValue={status} /> component renders an SVG chart
  • X-axis: measured value range (from optimal_range.min to optimal_range.max), labeled with the indicator's unit
  • Y-axis: score (0–1)
  • The scoring function curve is drawn as a path (solid line)
  • The current field's value is plotted as a highlighted dot with dashed crosshair lines to both axes
  • The optimal zone is subtly shaded (green background region)
  • Responsive: scales to container width, minimum height 140px

Indicator Deep-Dive Enhancements (indicators.$b_id.$indicator_id)

  • Indicator explanation section at top of deep-dive: description and why_it_matters from metadata
  • Scoring curve rendered below the explanation, showing current field value on the curve
  • Formula displayed in a collapsible "Berekening" section (monospace, collapsed by default)
  • Input data provenance section: "Gebruikte gegevens" showing which soil analysis values, field characteristics, and measures fed the calculation, with dates and sources

Calculation Pipeline Indicator (field-level page)

  • A lightweight horizontal flow indicator at the top of the field indicator page: Invoergegevens → Indicatoren → Aggregaties → Score
  • Each step is clickable: scrolls to or opens the relevant section
  • Compact design (single row, not a full diagram) — fits within the existing page header area

Onboarding Wizard (Phase 2+)

  • A (?) "Wat is BLN3?" button in the indicator page header opens a 3-step modal:
    1. "BLN3 beoordeelt uw bodem op 28 indicatoren" — category icons
    2. "Maatregelen verbeteren uw scores" — before/after example
    3. "Alle percelen op een rij" — heatmap preview
  • Shown automatically on first visit (dismissed state stored in PostHog/localStorage)
  • Available anytime via the (?) button

Technical Specification

Metadata TypeScript interface

// fdm-data/src/bln3/indicator-metadata.ts (or dedicated package)

export interface Bln3IndicatorMetadata {
    indicator_id: string              // e.g., "C_N", "P_DS"
    name: string                      // Dutch name: "Stikstofbeschikbaarheid"
    description: string               // Rich explanation (2-3 sentences)
    why_it_matters: string            // Farming-practice relevance
    unit: string                      // Measurement unit: "kg N/ha", "pH", "%"
    optimal_range: {
        min: number
        max: number
        optimum: number               // Peak of the scoring curve
    }
    scoring_function?: {
        type: "logistic" | "linear" | "piecewise" | "custom"
        params: Record<string, number>  // Function-specific parameters
    }
    formula_text: string              // Human-readable formula: "I_N = 1 / (1 + exp(-k * (NLV - x0)))"
    category: "biological" | "chemical" | "physical"
        | "environmental_gw" | "environmental_nut" | "environmental_sw"
}

export const bln3IndicatorMetadata: Bln3IndicatorMetadata[] = [
    {
        indicator_id: "C_N",
        name: "Stikstofbeschikbaarheid",
        description: "Stikstof is meestal het eerst beperkende nutriënt. De N-levering (NLV) is de meerjarig gemiddelde hoeveelheid N die in het groeiseizoen beschikbaar komt via mineralisatie van organische stof.",
        why_it_matters: "Voor grasland ligt het optimum rond 140 kg N/ha, voor bouwland rond 100. Een te lage NLV beperkt de gewasopbrengst direct.",
        unit: "kg N/ha",
        optimal_range: { min: 0, max: 250, optimum: 140 },
        scoring_function: {
            type: "logistic",
            params: { k: 0.05, x0: 100 }  // Extracted from open-source calculator
        },
        formula_text: "I_N = 1 / (1 + exp(-0.05 × (NLV - 100)))",
        category: "chemical",
    },
    // ... 27 more indicators
]

Scoring curve rendering

// fdm-app/app/components/bln3/scoring-curve.tsx

interface ScoringCurveProps {
    metadata: Bln3IndicatorMetadata
    currentValue: number          // The field's measured value
    currentScore: number          // The API-returned score (for validation)
    width?: number
    height?: number
}

// Renders an SVG with:
// - Axes labeled with unit (X) and score 0–1 (Y)
// - The scoring function curve as a <path>
// - Current value as a highlighted dot with crosshair lines
// - Optimal zone as a subtle green background region
// - Grid lines at 0.25, 0.5, 0.75 on Y-axis

Data extraction from open-source calculator

The Open Bodem Index Calculator (R package) contains scoring functions like:

# From R package:
calc_nlv_score <- function(NLV, crop_type) {
    # logistic scoring curve
    score <- 1 / (1 + exp(-0.05 * (NLV - ifelse(crop_type == "gras", 140, 100))))
    return(pmin(pmax(score, 0), 1))
}

These will be translated to TypeScript scoring function parameters:

// Automated extraction script (CI workflow)
// Reads R source → extracts function type + params → writes JSON

When the BLN3 calculator is open-sourced, the same process applies. Until then, for indicators shared between OBI and BLN3, the OBI calculator can be used as an interim source for curve parameters.

Wireframe

Indicator deep-dive with scoring curve

╔═════════════════╦════════════════════════════════════════════════════╗
║  [MAP]          ║  🟡 C_N — Stikstofbeschikbaarheid                  ║
║  (same as       ║  ─────────────────────────────────────────────    ║
║   field detail) ║  Stikstof is meestal het eerst beperkende         ║
║                 ║  nutriënt. De N-levering (NLV) is de meerjarig    ║
║                 ║  gemiddelde hoeveelheid N die in het               ║
║                 ║  groeiseizoen beschikbaar komt via mineralisatie   ║
║                 ║  van organische stof.                              ║
║                 ║                                                    ║
║                 ║  STATUS: 95 kg N/ha | DOEL: 140 | INDEX: 55/100  ║
║                 ║                                                    ║
║                 ║  ┌─── SCORINGSCURVE ─────────────────────────┐    ║
║                 ║  │ 1.0 ┤            ●━━━━━━━━━━━━━━━━        │    ║
║                 ║  │     │          ╱                           │    ║
║                 ║  │ 0.5 ┤─ ─ ─ ╱─ ─ ─ ─ ─ ─ ─ ─ ─ ─        │    ║
║                 ║  │     │    ╱  ↑ 95 kg N/ha → 0.55           │    ║
║                 ║  │ 0.0 ┤━╱────┼──────────────────────        │    ║
║                 ║  │     0    50   100   150   200   250       │    ║
║                 ║  │          N-levering (kg N/ha)              │    ║
║                 ║  └───────────────────────────────────────────┘    ║
║                 ║                                                    ║
║                 ║  ▸ Berekening (klik om te openen)                  ║
║                 ║    I_N = 1 / (1 + exp(-0.05 × (NLV - 100)))      ║
║                 ║                                                    ║
║                 ║  GEBRUIKTE GEGEVENS                                ║
║                 ║  ┌────────────────────────────────────────────┐   ║
║                 ║  │ Bodemanalyse: 15-03-2024 (Eurofins)       │   ║
║                 ║  │ N-totaal: 2100 mg/kg · OS: 4.2%           │   ║
║                 ║  │ Bodemtype: zeeklei · Gewas: wintertarwe    │   ║
║                 ║  └────────────────────────────────────────────┘   ║
║                 ║                                                    ║
║                 ║  IMPACT VAN MAATREGELEN  (+12 punten → 67)        ║
║                 ║  ┌──────────────────────────────────────────┐     ║
║                 ║  │ BM07  Groenbemester inzaaien       +8   │     ║
║                 ║  │ BM03  Organische stof aanvoer      +4   │     ║
║                 ║  └──────────────────────────────────────────┘     ║
╚═════════════════╩════════════════════════════════════════════════════╝

Blocked By

  • Open-source BLN3 calculator: Scoring function parameters and indicator descriptions must be extracted from the open-source repository once available. The OBI calculator can serve as an interim source for shared indicators.

Dependencies

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions