Skip to content

Data Analysis and Prediction

github-actions[bot] edited this page Oct 25, 2026 · 1 revision

This page is generated from the repository on every merge to main; changes made here are overwritten.

analyze_incident_trend

Is incident density in each zone rising or falling over time -- e.g. security incidents by district over the last few months. hotspot_analysis answers 'where is density high right now' (a single snapshot); this answers 'is it getting worse here.' A thin composite, not a new statistic: buckets point_layer's incidents into period_days-sized time periods per zone_layer feature, then feeds each zone's (period, count) series into the same _forecast_series/_linear_regression math forecast_trend already uses -- so results carry the same fit_confidence/trend_direction framing, and the same 'present as a projection, not a certain fact' rule applies. Needs at least 3 time periods of data to fit a trend (i.e. the date range in point_layer must span at least 3x period_days) -- returns a clear error naming how much data is actually available if not. A zone with zero incidents in every period is a valid, confidently-flat result, not an error.

Parameter Type Required Description
point_layer string yes Point layer of incidents, e.g. the shared 'Incidents' layer from add_incident_point.
date_field string yes Date field on point_layer.
zone_layer string yes Polygon layer of zones to analyze per-zone trend within (e.g. districts, or a hand-drawn area of interest).
zone_name_field string yes Field on zone_layer holding each zone's name.
period_days integer no Size of each time bucket in days. Defaults to 30.
periods_ahead integer no How many future periods to project per zone. Defaults to 1.

calculate_damage_exposure_severity

Composite post-crisis damage-and-exposure assessment, in the same thin-composite pattern as calculate_population_in_need: combines calculate_raster_change_detection's before/after pixel diff with fetch_building_footprints' building counts (and, optionally, a user-supplied hazard-intensity raster -- e.g. a shake-intensity or flood-depth layer) into one severity score per admin unit, plus a total building count in the high-severity units. Inspired by UNDP RAPIDA's rapid post-crisis assessment approach, deliberately scoped down to what's actually available here -- no seismic/hazard modeling, no social-media/night-light signal ingestion (see docs/archive/SECURITY_AND_COMPETITIVE_REVIEW_2026-08.md B.3 for that gap; this tool doesn't close it, just narrows it). Change magnitude is the MEAN absolute pixel difference within each unit, not the raw sum, which would just scale with unit area/pixel count. Building exposure counts footprint centroids falling within each unit -- units the change-detection raster doesn't cover are excluded from the severity index (never imputed as zero), matching calculate_severity_index's own rule; units with genuinely zero buildings still get a real 0, since that's an actual count, not missing data. Pass output_field to write each unit's severity score back to the layer for apply_graduated_style. Never hand-write this composition via execute_pyqgis_script -- use this tool.

Parameter Type Required Description
admin_layer string yes Polygon layer of admin units.
unit_name_field string yes Field holding each unit's name/P-code.
raster_before string yes Pre-event raster layer (see calculate_raster_change_detection).
raster_after string yes Post-event raster layer.
building_footprints_layer string yes Building footprint polygon layer, e.g. from fetch_building_footprints.
hazard_intensity_raster string no Optional hazard-intensity raster (shake intensity, flood depth, etc.) to weight the severity score alongside raw change magnitude.
high_severity_classes array[integer] no Severity classes (1-5) counted toward the exposed-building total. Defaults to [4, 5].
output_field string no Optional: write each unit's severity score back to the layer under this field name.

calculate_population_in_need

Combines calculate_severity_index's classification with population-per-pixel data to answer the number every HRP, donor brief, and allocation committee actually quotes -- 'X people in need in District Y', not just 'District Y is severity class 5'. Computes the severity index internally (same method and indicator handling as calculate_severity_index) from indicator fields already on a polygon layer, sums population within each admin unit via zonal statistics against an already-loaded population raster (same mechanism as estimate_population_exposure, which this calls internally -- e.g. a layer from fetch_worldpop_population), and reports a population_in_need total for the high-severity classes plus a population breakdown per severity class. Closes a gap where getting this number previously required manually chaining calculate_severity_index and estimate_population_exposure and matching the two up by hand -- easy to get subtly wrong (double-counting, or forgetting to exclude units calculate_severity_index itself flagged as missing data). Units excluded from severity scoring (missing indicator data) are excluded from the total, not silently counted as needy or safe -- same for units the population raster doesn't cover (no pop_sum value), listed separately rather than treated as zero population. Pass output_field to write each unit's population figure back to the layer, then style it directly with apply_graduated_style. Results are capped to 50 units (see unit_results_total/truncated) -- output_field still writes every unit's figure to the layer regardless of the cap.

Parameter Type Required Description
layer_name string yes Polygon layer of admin units with severity indicator fields.
indicator_fields array[string] yes Numeric indicator fields to combine into the severity score.
unit_name_field string yes Field on the polygon layer holding each unit's name/P-code.
population_raster_layer string yes A population-per-pixel raster layer already loaded (e.g. from fetch_worldpop_population).
weights object no Optional {indicator_field: weight} for the severity score. Defaults to equal.
invert_indicators array[string] no Indicator fields where a HIGHER raw value means a BETTER situation.
high_severity_classes array[integer] no Severity classes (1-5) counted toward the population_in_need total. Defaults to [4, 5].
output_field string no Optional: write each unit's population figure back to the layer under this field name.

calculate_presence_gap

Cross-reference a computed severity/needs index (see calculate_severity_index) against 3W/4W ('who does what where') operational-presence data to find admin units with HIGH severity but LOW or NO organizational presence -- the classic humanitarian coverage-gap question for targeting where a response is most under-resourced relative to need. Computes the severity index internally (same method and indicator handling as calculate_severity_index) from indicator fields already on a polygon layer, reads the 3W/4W file, and joins the two by admin unit name (case/whitespace-insensitive match). High-severity units with no match at all in the 3W data are reported separately as unmatched, since that could mean genuinely zero presence or just a name mismatch between the two datasets -- don't treat it the same as a confirmed zero. Pass output_field to write each high-severity unit's status ('gap'/'covered'/'unmatched') back to the layer, then style it directly with apply_categorized_style or place it on generate_html_dashboard -- do NOT hand-write PyQGIS renderer code for this via execute_pyqgis_script, use output_field plus the existing styling tools instead. Each of the three result lists is capped to 50 entries (see the matching _total fields and truncated) -- output_field still writes every classified unit's status to the layer regardless of the cap.

Parameter Type Required Description
layer_name string yes Polygon layer of admin units with severity indicator fields.
indicator_fields array[string] yes Numeric indicator fields to combine into the severity score.
unit_name_field string yes Field on the polygon layer holding each unit's name/P-code.
presence_file_path string yes Absolute path to the 3W/4W .csv/.xlsx/.xls file.
presence_admin_field string yes Column in the 3W/4W file holding the admin unit name/P-code.
presence_org_field string yes Column in the 3W/4W file holding the organization name.
weights object no Optional {indicator_field: weight} for the severity score. Defaults to equal.
invert_indicators array[string] no Indicator fields where a HIGHER raw value means a BETTER situation.
high_severity_classes array[integer] no Severity classes (1-5) counted as 'high need'. Defaults to [4, 5].
low_presence_threshold integer no Organization count strictly below this counts as a presence gap. Defaults to 1 (i.e. zero organizations).
sheet_name string no Sheet name if presence_file_path is a multi-sheet Excel file.
delimiter string no CSV delimiter for presence_file_path. Defaults to ','.
output_field string no Optional: write each high-severity unit's presence-gap status ('gap'/'covered'/'unmatched') back to the layer under this field name.

calculate_severity_index

Build a composite multi-indicator severity/needs index across admin units (a simple weighted min-max index in the style of INFORM/JIAF -- exploratory analysis only: it is NOT the JIAF method, so never call its result JIAF-compliant or an official severity classification), the standard basis for prioritizing which areas receive funding. Takes several numeric indicator fields already on a polygon layer's attribute table (e.g. food insecurity %, displacement %, protection incidents, WASH coverage), min-max normalizes each so higher always means worse, applies relative weights, and returns a 0-1 composite score plus a 1-5 severity class per unit, ranked worst-first. Use invert_indicators for fields where a HIGHER value means a BETTER situation (e.g. % with water access) -- otherwise well-served areas score as high-severity. Units missing any indicator are excluded and listed, never imputed. Always report the weights and any excluded units alongside the ranking, since both change how it should be read. Results are capped to the worst 50 units (see truncated/scored_units) -- output_field still writes the score for every unit to the layer regardless of the cap, so styling/mapping the full set is unaffected; only the returned JSON is capped.

Parameter Type Required Description
layer_name string yes Polygon layer of admin units.
indicator_fields array[string] yes Numeric indicator fields to combine.
unit_name_field string yes Field holding each unit's name/P-code, used to label results.
weights object no Optional {field: weight}; defaults to equal. Normalized to sum to 1, so these are relative.
invert_indicators array[string] no Indicator fields where a HIGHER raw value means a BETTER situation.
output_field string no Optional: write the composite score back to the layer under this field name.

forecast_trend

Project a simple linear trend forward from historical numeric data already in a layer's attribute table (e.g. case counts, incident counts, or any numeric field over time). Returns a mathematical trend projection with a stated fit confidence -- NOT a certain prediction; always present it as a projection, not a fact. Optionally group by a categorical field to get one forecast per group (e.g. one per district) instead of a single overall forecast.

Parameter Type Required Description
layer_name string yes
date_field string yes Field holding the date/time of each observation.
value_field string yes Numeric field to forecast.
periods_ahead integer no How many future points to project. Defaults to 3.
group_by_field string no Optional categorical field -- returns one forecast per distinct value instead of one overall forecast.

Clone this wiki locally