Air quality — how it is calculated
The score reflects the expected level of fine particulate matter PM2.5 around the address. Data is annual averages from the Sensor.Community archive (SDS011) for Sofia, not real-time API values; updated only when the build script is re-run. Distance interpolation (IDW). No sensors in range → neutral score of 50 in the composite.
What we measure
PM2.5 (µg/m³) from Sensor.Community (SDS011). The script aggregates daily averages from the archive over a window of up to ~1 year and records an annual mean per sensor. For each address: sensors up to 3 km (5 km if needed), IDW, then a linear scale 0–100: 5 µg/m³ (WHO) → 100, 15 µg/m³ → 0 — intentionally narrow for the real range of citizen sensors in Sofia.
Scale 0–100 (WHO)
| Score | Description |
|---|---|
| 90–100 | Interpolated PM2.5 ≈ up to ~6.5 µg/m³ (close to WHO annual mean guideline) |
| 70–89 | ≈ 6.5–8 µg/m³ |
| 50–69 | ≈ 8–10 µg/m³ |
| 30–49 | ≈ 10–12 µg/m³ |
| 0–29 | ≈ above ~12 µg/m³ (toward the model upper bound of 15 µg/m³) |
Data and updates
Output file: data/sofia/sources/air-quality-sensors.json (`npm run build:air-quality`). The script fetches locations from the API, then archived CSVs by date — stable annual averages, not "current air." Options: `--quick` for a shorter window; full window defaults to 365 days with 7-day steps (configurable via AQ_* env in build-air-quality-sofia.mjs).
What we do not measure
We do not model ozone, NO₂, or other pollutants separately. We do not account for indoor microclimate or filters. Official IAOS stations may be used for cross-referencing in a future version.
Model version: airQuality v1.2 (lib/livability/airQualityV1Constants.js).