Data Specification#
Overview#
acestor’s dengue forecasting pipeline runs in two stages, each with its own input surface:
Raw case data — the IHIP linelist (per-case rows). Input to
dengue_prep.Prepared data —
cases_daily.csvandweather_daily.csvunderprepared_data/{region_type}/. Output ofdengue_prep, input to the maindenguepipeline.GeoJSON files — region boundaries and identifiers. Read by both stages (spatial join, parent-chain rollup, region metadata).
Weather is downloaded at prep-time from the openmeteo API by default — there is no raw local weather input.
1. Raw case data (IHIP linelist)#
The prep parser (pipelines/dengue_prep/lib/ihip.py) reads every
.xlsx, .xls, and .csv file under
data.case_download.source_path. Each row is treated as one confirmed
case; case counts are produced by grouping on (region_id, date).
Only the date column is strictly required. Region resolution and row filtering are configurable — the parser adapts to whichever columns the file provides.
Canonical IHIP L-form columns#
Dashboard exports (/api/cases/export.xlsx) and standard IHIP linelists
emit the 30 L-form columns below. The parser only requires the date column;
the rest are optional and consulted opportunistically by row filters,
region resolvers, and geocoding.
Case No, Aadhar No, Patient Name, Age, Gender, Contact Number,
Address, Village/Town/Ward, District, State, Pincode,
Latitude, Longitude,
Date Of Onset, Sample Collected Date, Test Performed Date,
Confirmed Diagnosis, Test Name, Test Result,
Hospitalised, Hospital Name, Outcome,
Reporting Unit, Reporting District, Reporting State,
Region Id, District Code, Block Code, Ward Code, ULB Code
Date column — candidate fallback#
data.case_parse.date_column accepts either a string or a list. When a
list is given, the parser walks it top-to-bottom per file and keeps the
first column that yields any parseable rows. This lets one config span
sources with different date semantics (e.g. dashboard exports populate
Test Performed Date, some state files only have Sample Collected
Date).
data:
case_parse:
date_column:
- Test Performed Date
- Date Of Onset
- Sample Collected Date
Both ISO (YYYY-MM-DD) and day-first (dd/mm/yyyy) formats are tried
for each candidate; whichever parses more rows wins.
Region resolution#
Four resolvers, tried in priority order until one applies:
Pre-resolved ``region_id`` column — set
data.case_parse.region_id_column: "Region Id"(dashboard exports). The parser trusts the column verbatim. IDs at a finer granularity thandata.region_type(e.g. ward IDs in a district-level run) are rolled up via the geojsonparentchain.LGD code column — set
lgd_code_column: "District Code". The integer code is mapped directly:502 → district_502. Fast and exact.Geocoding — enabled via
data.case_parse.geocoding.enabled: true. Composes a free-text address from configured fields, geocodes via Google, PIPs the result against the region layer.Spatial join — falls back to point-in-polygon on
Latitude/Longitudecolumns. Points just outside a polygon are snapped to the nearest one within 1000 m; anything farther is dropped.
Rows resolved to a region_id that isn’t present in the target
geojson layer are dropped (out-of-scope guard).
Row filters#
data.case_parse.filters is a list of {column, values} entries.
Rows must match every entry (AND); within an entry, any listed value
matches (OR). Missing columns are logged and skipped.
data:
case_parse:
filters:
- column: Confirmed Diagnosis
values: [Dengue]
- column: Test Result
values: [Positive]
Case sources#
data.case_download.source_mode selects a plugin from
pipelines/dengue_prep/lib/case_sources/:
filesystem— read files fromsource_path.dashboard— pull IHIP-shaped XLSX from a running dengue-dashboard backend viaPOST /api/auth/login+GET /api/cases/export.xlsx?from=…&to=…. Handles chunked backfill and incremental refetch (backfill_days) automatically.
External sources can be loaded by file path or dotted module path.
2. Prepared case data#
Written to prepared_data/{region_type}/cases_daily.csv (full overwrite
per run). Three columns, aggregated to one row per (region_id, date).
Column |
Type |
Description |
|---|---|---|
|
ISO date ( |
Case date, chosen from the configured |
|
String |
LGD-standard identifier — |
|
Integer |
Confirmed cases in |
date,region_id,case_count
2021-02-03,district_344,1
2021-08-21,district_344,1
2021-09-14,district_344,3
3. Prepared weather data#
Written to prepared_data/{region_type}/weather_daily.csv (full
overwrite per run). Eight columns, one row per (region_id, date).
Column |
Type |
Description |
|---|---|---|
|
String |
LGD-standard identifier. |
|
ISO date |
Observation date. |
|
Float, Kelvin |
Daily mean 2 m air temperature (ERA5 |
|
Float, Kelvin |
Daily mean 2 m dew-point temperature (ERA5 |
|
Float, metres |
Daily total precipitation (ERA5 |
|
String |
Region name (from geojson). |
|
String |
Parent region identifier (from geojson). |
|
String |
Parent region name (from geojson). |
Units on disk are always Kelvin (temperature) and metres
(precipitation), regardless of source. Sources declare their native
units via data.weather_download.temperature_unit and
precipitation_unit; the download step normalises before writing.
A detection guard (normalize_temperature) compares declared vs
observed magnitude and refuses double-conversion when the declared unit
disagrees with the data.
region_id,date,2mTemperature,2mDewpointTemperature,totalPrecipitation,name,parent,parent_name
district_344,2016-01-02,294.6357301806407,289.9042182571895,2.070384761243376e-05,ANUGUL,Odisha,Odisha
district_344,2016-01-03,294.6549358409932,289.62343289514274,5.913023588065236e-05,ANUGUL,Odisha,Odisha
The default source is openmeteo (ERA5 archive). Its ~5-day archive lag is applied silently — requested end dates within the lag window are capped, and empty chunks are logged and skipped rather than errored.
4. GeoJSON files#
Layout under data.geojson.base_path:
{base_path}/
├── districts/
│ ├── district_344.geojson
│ └── ...
├── blocks/
│ └── block_<lgd>.geojson
├── ulbs/
│ └── ulb_<lgd>.geojson
└── ulb_wards/
└── ulb_ward_<lgd>.geojson
Subdirectory names are plural (districts/, ulbs/,
ulb_wards/). The parser strips the trailing s to derive the
region-type prefix used in region_id (district_, ulb_,
ulb_ward_). Longest-prefix classification is used so ulb_ward_
IDs are not misclassified as ulb_.
Files are RFC 7946 GeoJSON in WGS84 (EPSG:4326). A file may be a single
Feature or a FeatureCollection. Geometry is Polygon or
MultiPolygon.
Feature properties#
Property |
Type |
Description |
|---|---|---|
|
String, required |
|
|
String, required |
Region name (used in weather CSV and summary reports). |
|
String, required |
Parent |
|
String |
Parent region name. |
State-specific extras (e.g. dtcode11, code2011, state_lgd)
are preserved but ignored by the pipeline.
{
"type": "Feature",
"properties": {
"region_id": "district_344",
"name": "ANGUL",
"parent": "state_21",
"parent_name": "ODISHA",
"dtcode11": "384",
"code2011": "213840160",
"state_lgd": 21
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [ ... ]
}
}
5. Data requirements#
Minimum span — controlled by
min_date_span_daysin the maindenguepipeline config. Runs shorter than this exit at the sufficiency gate.4–12 months — thresholds only, no model predictions.
≥ 12 months — full pipeline (thresholds + predictions).
Continuity — each ISO week must contain at least 4 days of data; weeks must be contiguous.
Region coverage —
min_distinct_regions(main pipeline config) gates whether there is enough spatial coverage to fit the neighbour model. Regions with LGD code 0 (placeholder / Union-Territory enclaves) are dropped from the prepared weather CSV.Alignment — every
region_idemitted by prep must exist in the geojson layer for the configuredregion_type. The prep out-of-scope guard enforces this; the main pipeline assumes it.