Skip to content
RivuletCheck

Method

How Rivulet gets from a photo to a status

Rivulet is a trust and quality layer for citizen observations. This page states every step, every constant and what the result does not mean, so a scientist can disagree with it precisely. Method version 1.5.0, published 2026-09-21.

Rules, not a black box: no learned model decides a status. The one AI component only flags a photo for a person to look at.

The pipeline

  1. 1. Read the colour

    The phone photo is reduced on the device to a water colour on the 21-step Forel–Ule scale, using a simplified WACODI-style conversion (sRGB to CIE XYZ to hue angle). The full photo never leaves the phone: only the class, a confidence and, for the optional photo check, a tiny thumbnail are sent. There is no per-camera calibration, so colour is a proxy, not a measurement.

    src/lib/science/forel-ule.ts, extract-colour.ts

  2. 2. Turn what people see into evidence

    Smell, foam, algae, dead fish, clarity, flow, litter and recognisable animal groups each add a small, declared amount of evidence for or against good condition. Animal groups use sensitivity values on the BMWP 1–10 family scale as a simplified proxy, not the BMWP protocol.

    src/lib/science/indicators.ts

  3. 3. Check before counting

    GPS accuracy, distance from the mapped stream, an hourly limit per observer and an optional AI check that the photo shows water are evaluated independently. Anything doubtful is stored but held out of assessments, trust and exports until a person approves or rejects it.

    src/lib/science/plausibility.ts, src/lib/moderation/

  4. 4. Weigh the observer

    Each observer's trust is how well they agree with other people's reports of the same streams (leave-one-out, so nobody is judged against themselves), shrunk toward neutral when there is little history. Trust multiplies the weight of their evidence. Agreement is not truth: observers who agree can all be wrong.

    src/lib/science/trust.ts, weighting.ts

  5. 5. Estimate with uncertainty

    Weighted evidence updates a Beta–Bernoulli posterior. Rivulet reports its mean, a 90% credible interval and a data-confidence figure. Below a minimum confidence it says "insufficient data" instead of guessing. Five status classes carry the names of the EU Water Framework Directive, but their limits are equal-width priors, so this is not an official classification.

    src/lib/science/bayes.ts, wfd.ts, snapshot.ts

  6. 6. Read it for people and animals

    Hazard is the trust-weighted share of recent reports showing a warning sign. Exposure is what OpenStreetMap places within 150 m: playgrounds, schools, parks, dog areas, bathing and fishing spots. A hazard near a place people or dogs use raises the concern. No recent reports reads as unknown, never as safe.

    src/lib/science/one-health.ts

  7. 7. Cross-check from space

    A Sentinel-2 hue angle for the stream is compared with the residents' colour. Most urban streams are narrower than a 10 m pixel, so most get no clear satellite view. If the two disagree beyond a declared threshold, every contributing weight is halved: the estimate widens and confidence cannot rise because of that pass. The reflectance conversion is a placeholder, not the published Sentinel-2 calibration.

    src/lib/science/satellite.ts, scripts/satellite/

Every constant, declared

80 parameters: 8 come from a cited standard or publication and 72 are expert-judgement priors that say, in their own row, that they are uncalibrated and why they were chosen. Nothing is an unlabelled magic number. The list below is generated from the code's own registry, so it cannot drift from what runs.

Water colour scale5
  • forel-ule.class-limits21 valuesStandard

    Hue angle class limits: Novoa, Wernand & van der Woerd 2013, J. Eur. Opt. Soc. Rapid Publ. 8, 13057 (doi:10.2971/jeos.2013.13057), as distributed in CefasRepRes/FUME data/hue_angle_limits_NWW2013.csv; legend colours from FUME forelulecmap(). FUME contains public sector information licensed under the Open Government Licence v3.0. Hue angle measured from chromaticity x = y = 1/3.

  • forel-ule.hue-reference0.3333, 0.3333Standard

    Forel–Ule hue angle convention, chromaticity x = y = 1/3 (Novoa, Wernand & van der Woerd 2013; as implemented in CefasRepRes/FUME)

  • forel-ule.min-usable-pixels100Prior

    Below this many coloured open-water pixels the mean hue is dominated by glare, banks and noise, so no reading is returned. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • forel-ule.min-chroma-distance0.01Prior

    Pixels this close to the D65 white point (sky glare, foam, overcast reflections) carry no water hue and would bias readings toward blue-green classes, so they are excluded. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • forel-ule.confidence-spread-scale30Prior

    A circular hue spread of this many degrees across the sampled region maps to zero confidence, falling linearly from full confidence at zero spread. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Colour conversion3
  • colour.srgb-transfer0.0404, 12.92, 0.055, 2.4Standard

    IEC 61966-2-1:1999, sRGB colour space transfer function

  • colour.srgb-to-xyz0.4125, 0.3576, 0.1804, 0.2127, 0.7152, 0.0722, 0.0193, 0.1192, 0.9503Standard

    IEC 61966-2-1:1999, linear sRGB (D65) to CIE 1931 XYZ matrix

  • colour.d65-white0.3127, 0.329Standard

    CIE standard illuminant D65 chromaticity, CIE 1931 2° standard observer

indicators17
  • indicators.bmwp-max-score10Standard

    Maximum family score of the Biological Monitoring Working Party score system (Armitage, Moss, Wright & Furse 1983, Water Research 17:333–347)

  • indicators.taxon-sensitivity10, 9, 8, 6, 3, 1Prior

    Sensitivity for the taxon groups a resident can recognise (stonefly, mayfly, caddisfly, freshwater shrimp, leech, sludge worm), set on the 1–10 BMWP family scale (Armitage et al. 1983). Mayfly and caddisfly groups contain families with a wide range of BMWP scores, so single representative values are used. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.sensitiveTaxonThreshold6Prior

    Taxa scoring at or above this BMWP-scale value count as evidence of good condition; below it, as evidence of organic pollution. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.forelUleClearMax5Prior

    Forel–Ule classes up to this value (blue to greenish-blue water) count as evidence of low algal enrichment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.forelUleEnrichedMin13Prior

    Forel–Ule classes from this value (yellowish-green to brown water) count as evidence of enrichment or heavy humic and sediment load. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.forelUleClear1Prior

    Evidence added for a clear-water Forel–Ule class. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.forelUleEnriched1Prior

    Evidence added for an enriched Forel–Ule class. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.forelUleIntermediate0.25Prior

    Weak positive evidence for intermediate Forel–Ule classes, which are common in healthy lowland streams. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.pollutedOdour1.5Prior

    Sewage or chemical odour is treated as strong evidence of contamination. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.foam0.5Prior

    Persistent surface foam is treated as moderate evidence of detergents or organic load. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.deadFish2Prior

    Dead fish are treated as the strongest single survey signal of acute pollution or oxygen depletion. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.visibleAlgae0.75Prior

    Visible algal growth is treated as evidence of nutrient enrichment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.stagnantFlow0.5Prior

    Stagnant flow is treated as mild evidence of degraded condition through low oxygen and warming. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.heavyLitterMin2Prior

    Litter levels from this value on the 0–3 survey scale count as heavy. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.heavyLitter0.5Prior

    Evidence added for heavy litter on the margins. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.clearWater0.5Prior

    Evidence added when the resident reports clear water. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • indicators.evidence.opaqueWater1Prior

    Evidence added when the resident reports opaque water. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Observation weighting12
  • weighting.base0.5Prior

    Starting weight of an observation before evidence-quality adjustments. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.photoBonus0.2Prior

    Largest weight added when a photo yields a Forel–Ule reading, scaled by that reading's confidence. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.unknownPhotoConfidence0.5Prior

    Colour confidence assumed for a photo whose reading confidence is unknown. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.measurementBonus0.05Prior

    Weight added for each instrument reading (pH, dissolved oxygen, temperature, nitrate). Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.maxCountedMeasurements4Prior

    Instrument readings beyond this count add no further weight. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.preciseGpsMetres20Prior

    GPS accuracy at or better than this many metres carries no penalty. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.approximateGpsMetres100Prior

    GPS accuracy up to this many metres counts as approximate. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.approximateGpsFactor0.85Prior

    Weight multiplier for an approximate GPS position. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.poorGpsFactor0.6Prior

    Weight multiplier for a poor or unknown GPS position. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.unknownGpsMetres1000Prior

    Accuracy assumed when the device reports none, so unknown precision is treated as poor rather than good. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.halfLifeHours720Prior

    An observation's weight halves after this many hours (30 days), reflecting how quickly stream condition can change. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • weighting.floor0.1Prior

    Minimum weight, so no accepted observation is silently discarded. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Bayesian estimate2
  • bayes.uniform-prior1, 1Standard

    Bayes–Laplace uniform prior Beta(1, 1) for a proportion with no prior information (Gelman et al., Bayesian Data Analysis, 3rd ed., 2013, chapter 2)

  • bayes.credible-mass0.9Prior

    Probability mass of the reported equal-tailed credible interval; a reporting convention chosen for Rivulet v1. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

confidence6
  • confidence.volumeScale5Prior

    Effective observation weight at which the volume component reaches about 63% of its maximum. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • confidence.diversityScale3Prior

    Number of distinct observers at which the diversity component reaches about 63% of its maximum. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • confidence.recencyHalfLifeHours1440Prior

    The recency component halves after this many hours (60 days) since the newest observation. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • confidence.volumeWeight0.4Prior

    Share of data confidence given to the amount of weighted evidence. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • confidence.diversityWeight0.3Prior

    Share of data confidence given to the number of independent observers. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • confidence.recencyWeight0.3Prior

    Share of data confidence given to how recent the newest observation is. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Status classes2
  • wfd.class-boundaries0.2, 0.4, 0.6, 0.8Prior

    Directive 2000/60/EC (Annex V) defines five ecological status classes on an Ecological Quality Ratio from 0 to 1, but sets class boundaries per quality element through intercalibration; Rivulet v1 uses equal-width bands with boundaries at 0.2, 0.4, 0.6 and 0.8. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • wfd.min-confidence-for-class0.25Prior

    Below this data confidence no ecological status class is assigned and the stream is shown as having insufficient data. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Observer trust5
  • trust.priorStrength5Prior

    Pseudo-count weight of the neutral prior against an observer's own agreement evidence, in units of observations. Trust is shrunk towards this neutral value using a Beta-binomial-style pseudo-count prior (Gelman et al., Bayesian Data Analysis, 3rd ed., 2013, chapter 5). Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • trust.minIndependent2Prior

    An observation gives no trust signal unless at least this many observations by other observers exist for the same water body. Trust is shrunk towards this neutral value using a Beta-binomial-style pseudo-count prior (Gelman et al., Bayesian Data Analysis, 3rd ed., 2013, chapter 5). Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • trust.multiplierMin0.4Prior

    Lower clamp on the trust multiplier applied to evidence weight. Trust is shrunk towards this neutral value using a Beta-binomial-style pseudo-count prior (Gelman et al., Bayesian Data Analysis, 3rd ed., 2013, chapter 5). Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • trust.multiplierMax1.6Prior

    Upper clamp on the trust multiplier applied to evidence weight. Trust is shrunk towards this neutral value using a Beta-binomial-style pseudo-count prior (Gelman et al., Bayesian Data Analysis, 3rd ed., 2013, chapter 5). Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • trust.neutralTrust0.5Prior

    Trust score with no effect on evidence weight (multiplier of 1). Trust is shrunk towards this neutral value using a Beta-binomial-style pseudo-count prior (Gelman et al., Bayesian Data Analysis, 3rd ed., 2013, chapter 5). Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Plausibility checks5
  • plausibility.maxGpsAccuracyM250Prior

    GPS accuracy worse than this many metres (or missing) flags the observation for human review instead of auto-approving it. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • plausibility.maxPerHour5Prior

    More than this many observations by the same observer in the previous hour flags the batch for human review as a basic anti-spam check. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • plausibility.maxFutureMinutes5Prior

    A claimed observation time more than this many minutes ahead of the server clock is rejected outright as an implausible payload. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • plausibility.maxPastDays30Prior

    A claimed observation time more than this many days behind the server clock is rejected outright as an implausible payload. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • plausibility.maxDistanceFromWaterbodyM200Prior

    A submitted GPS point more than this many metres from the claimed water body's geometry flags the observation for human review instead of auto-approving it, but never blocks submission. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Points4
  • contribution.basePoints10Prior

    Points awarded for one counted, trust- and quality-weighted observation. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • contribution.gapBonus5Prior

    Extra points for the first observation on a water body that had none in the preceding window, rewarding coverage over repetition. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • contribution.gapDays30Prior

    A water body counts as a data gap if it had no observation in this many preceding days. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • contribution.minTrustForPoints0.35Prior

    Below this Trust Score an observer earns no points, so sheer volume of readings that disagree with everyone else cannot buy a place in the ranking. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Certificates5
  • certificate.contributorMinObservations5Prior

    Validated observations required for the entry-level Contributor certificate. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • certificate.contributorMinTrust0.5Prior

    Minimum Trust Score required for the Contributor certificate. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • certificate.dataStewardMinObservations20Prior

    Validated observations required for the higher Data Steward certificate. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • certificate.dataStewardMinTrust0.6Prior

    Minimum Trust Score required for the Data Steward certificate. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • certificate.dataStewardMaxRank100Prior

    Rank an observer must reach or beat in their home city's people leaderboard for the Data Steward certificate. This is a programme rule, not a scientific estimate, but is declared here for transparency. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

oneHealth6
  • oneHealth.windowDays30Prior

    Only observations from this many recent days count as current hazard signs; older reports say little about the water today, and no recent report is shown as unknown, never as safe. An indicative screening rule, not a public health or bathing-water assessment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • oneHealth.exposureRadiusM150Prior

    Playgrounds, schools, parks, bathing and fishing spots and allotments within this distance of a stream count as bringing people or dogs close to it. An indicative screening rule, not a public health or bathing-water assessment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • oneHealth.possibleShare0.2Prior

    A sign (sewage smell, algae or scum, chemical smell or foam, dead fish, heavy litter) counts as a possible hazard when at least this trust- and quality-weighted share of recent reports mention it. An indicative screening rule, not a public health or bathing-water assessment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • oneHealth.likelyShare0.5Prior

    A sign counts as a likely hazard when at least this weighted share of recent reports mention it. An indicative screening rule, not a public health or bathing-water assessment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • oneHealth.likelyMinObservers2Prior

    A likely hazard also needs this many different observers, so one person cannot raise a stream to the highest concern alone. An indicative screening rule, not a public health or bathing-water assessment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • oneHealth.heavyLitterMin2Prior

    Litter at or above this value on the 0–3 survey scale counts as an injury hazard for children, dogs and wildlife. An indicative screening rule, not a public health or bathing-water assessment. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

Satellite cross-check8
  • satellite.minUsablePixels4Prior

    Below this many cloud-, shadow- and land-masked water pixels in the sample window, a Sentinel-2 pass is recorded with null indices rather than a reading — never as agreement. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • satellite.minNdwi0Prior

    A pixel counts as open water if its NDWI is above this value or the Sentinel-2 scene classification labels it water (class 6); other pixels are treated as land or mixed bank and excluded from the mean. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • satellite.windowPixels5Prior

    Width in 10 m pixels of the band sampled along each water body's whole line; urban streams are narrower than a pixel, so most are invisible to Sentinel-2 and are recorded as unavailable rather than guessed. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • satellite.maxAgeDays30Prior

    A satellite reading older than this many days no longer counts as a current cross-check and is excluded from the snapshot. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • satellite.evidenceWeight0.4Prior

    Weight a satellite reading carries in the Bayesian model relative to a full-weight citizen observation, reflecting its coarser spatial resolution and unvalidated calibration. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • satellite.divergenceThresholdFu3Prior

    Absolute Forel-Ule class distance between the citizen and satellite readings above which they are treated as diverging rather than agreeing. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

  • satellite.cie-band-centre-cmf0.032, 0.208, 0.4652, 0.5945, 0.995, 0.0039, 0.1212, 0.0446, 0Standard

    CIE 1931 2° standard observer colour-matching functions (CIE 15:2004), read at the 5nm-tabulated wavelength nearest each Sentinel-2 L2A band's centre wavelength (blue B02 ≈492nm, green B03 ≈560nm, red B04 ≈665nm)

  • satellite.hue-angle-calibration0Prior

    The Sentinel-2 hue-angle conversion (reflectance -> CIE XYZ via band-centre colour-matching weights -> hue angle) is a placeholder approximation, NOT the published van der Woerd & Wernand (2015, 2018) Sentinel-2 hue-angle calibration and its delta-correction, which Rivulet intends to adopt once implemented. Treat satellite Forel-Ule equivalents as a coarse, uncalibrated cross-check rather than a validated measurement. Uncalibrated Rivulet v1 expert-judgement prior; calibration against official water-quality data is planned.

How the model behaves

The engine's own answers to fixed, simple situations, computed live rather than described. Each report is from a different observer at neutral trust unless stated. Read the interval, not just the class: one report already gives a class, but with a wide interval, and the interval narrows as reports agree.

Agreeing reports

SituationMean90% intervalConfidenceStatus
No reports (0)0.500.05–0.950.00insufficient data
All healthy (1)0.810.51–0.990.46high
All healthy (2)0.890.68–0.990.58high
All healthy (3)0.920.77–1.000.67high
All healthy (5)0.950.85–1.000.80high
All healthy (8)0.970.90–1.000.90high
All healthy (12)0.980.93–1.000.96high
All polluted (1)0.140.01–0.380.46bad
All polluted (2)0.080.00–0.230.58bad
All polluted (3)0.060.00–0.160.67bad
All polluted (5)0.030.00–0.100.80bad
All polluted (8)0.020.00–0.070.90bad
All polluted (12)0.020.00–0.040.96bad

Disagreeing reports

SituationMean90% intervalConfidenceStatus
Half healthy, half polluted (4)0.400.23–0.580.74poor
Half healthy, half polluted (8)0.390.27–0.530.90poor
Half healthy, half polluted (12)0.390.29–0.500.96poor

Whom you believe

SituationMean90% intervalConfidenceStatus
3 healthy from trusted observers, 3 polluted from low-trust0.700.54–0.840.84good
3 healthy from low-trust observers, 3 polluted from trusted0.160.07–0.280.84bad

The last table is the point of the trust layer: the same six reports give a different answer depending on who made them, because an observer who has tended to disagree with everyone else counts for less. Mixed evidence lands below the middle because warning signs are weighted more heavily than the absence of them, a declared choice.

What it does not claim

  • It is not a laboratory, regulatory or public-health assessment, and never says water is safe.
  • The class names come from Directive 2000/60/EC Annex V; the class limits are not calibrated EQR boundaries.
  • Colour comes from an uncalibrated phone camera and says nothing about chemistry.
  • Trust is peer agreement, not truth, and the model still needs validating against independent measurements.
  • The satellite check is coarse and its reflectance conversion is a declared placeholder.
  • Rivulet's survey is a quick visual complement to, not a substitute for, the professional OneAquaHealth field sampling protocols (macroinvertebrates, water chemistry, habitat and more).

Version history

  • 1.5.0 — Resident-scored flow and the animal-group score no longer borrow the OneAquaHealth codes hydrology and macroinvertebreates: they move to the Rivulet code system as flow-state and invertebrate-groups-score, because a resident's 0-3 flow rating and a BMWP-family sum are not a hydromorphological survey or a benthic macroinvertebrate count. No estimate changes. Each exported Observation also carries the stated derivation of its value as a note.
  • 1.4.0 — Sentinel-2 satellite readings enter computeSnapshot as an independent, coarse cross-check at a fixed evidence weight. The reflectance-to-hue-angle conversion uses CIE 1931 colour-matching weights at each band's centre wavelength and is NOT the published van der Woerd & Wernand Sentinel-2 hue-angle calibration (see satellite.hue-angle-calibration). When the citizen and satellite Forel-Ule readings diverge beyond the declared threshold, every contributing weight for that water body is halved: the posterior widens and data confidence cannot rise because of the diverging pass.
  • 1.3.0 — One Health reading: warning signs from the last 30 days of trust-weighted reports (hazard) combined with playgrounds, schools, parks, bathing and fishing spots and allotments from OpenStreetMap within 150 m (exposure), shown for people, dogs and wildlife. No recent reports reads as unknown, never as safe.
  • 1.2.0 — Observations flagged by plausibility checks no longer count towards assessments, trust or exports until a person reviews them. Resident-reported signs (clarity, sewage odour, algae, foam, dead fish, litter) move from OneAquaHealth analyte codes to the Rivulet code system. Flow and litter are now asked in the survey instead of defaulting.
  • 1.1.0 — Observer trust now weights evidence: computeSnapshot multiplies each observation's quality weight by trustMultiplier(observerTrust), shrinking noisy or disagreeing observers' influence towards neutral.

Sources

  • Directive 2000/60/EC of the European Parliament and of the Council establishing a framework for Community action in the field of water policy (Water Framework Directive), Annex V
  • Novoa, Wernand & van der Woerd 2013, The Forel-Ule scale revisited spectrally: preparation protocol, transmission measurements and chromaticity, J. Eur. Opt. Soc. Rapid Publ. 8, 13057 (hue angle class limits via CefasRepRes/FUME)
  • Novoa et al. 2015, WACODI: a generic algorithm to derive the intrinsic color of natural waters from digital images, Limnology and Oceanography: Methods, doi:10.1002/lom3.10059
  • IEC 61966-2-1:1999, Multimedia systems and equipment — Colour measurement and management — Default RGB colour space — sRGB
  • Armitage, Moss, Wright & Furse 1983, The performance of a new biological water quality score system based on macroinvertebrates over a wide range of unpolluted running-water sites, Water Research 17:333-347
  • Gelman et al. 2013, Bayesian Data Analysis, 3rd edition, CRC Press
  • Gelman et al. 2013, Bayesian Data Analysis, 3rd edition, CRC Press, chapter 5 (hierarchical and shrinkage models — basis for shrinking observer trust towards neutral)
  • HL7 Europe, OneAquaHealth FHIR Implementation Guide, github.com/hl7-eu/oah
  • van der Woerd, H.J. & Wernand, M.R. 2015, True Colour Classification of Natural Waters with Medium-Spectral Resolution Satellites: SeaWiFS, MODIS, MERIS and OLCI, Sensors 15(10):25663-25680, doi:10.3390/s151025663 — intended Sentinel-2 hue-angle calibration, not yet adopted
  • van der Woerd, H.J. & Wernand, M.R. 2018, Hue-Angle Product for Low to Medium Spatial Resolution Optical Satellite Sensors, Remote Sensing 10(2):180, doi:10.3390/rs10020180 — Sentinel-2 delta-correction, not yet adopted
  • Copernicus Sentinel data 2026, processed via Element 84 Earth Search STAC and AWS-hosted Sentinel-2 L2A Cloud-Optimised GeoTIFFs

The code is open under Apache-2.0 and its tests are in src/lib/science. Data leaves Rivulet as FHIR from the open data page.