Skip to content

USFEMA_FloodInsuranceClaims: Optimize download and transformation pipeline - #2217

Open
kartik-s21 wants to merge 2 commits into
datacommonsorg:masterfrom
kartik-s21:usfema-flood-claims-optimization
Open

kartik-s21 wants to merge 2 commits into
datacommonsorg:masterfrom
kartik-s21:usfema-flood-claims-optimization

Conversation

@kartik-s21

@kartik-s21 kartik-s21 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Updated the download and data processing pipeline for USFEMA_FloodInsuranceClaims to eliminate multi-hour runtime bottlenecks and improve error resilience.

  1. Download Architecture & Data Integrity (fema_download.py)
  • Direct Bulk Streaming with Robust Fallback: Streams the static bulk CSV (~1 minute) with automatic fallback to paginated OpenFEMA REST API retrieval.
  • Atomic Pagination via Staging: Chunks in the pagination fallback are staged in temporary files and published atomically via shutil.move once the full dataset is downloaded, preventing data duplication on retries.
  • Fail-Fast Error Handling: Converted swallowed IOError to fatal exceptions to prevent downstream processing of truncated files. Added verification asserting records_downloaded >= total_records.
  • CLI & Path Resolution: Registered --output_dir and resolved all paths relative to the script directory to prevent root-directory path coupling.
  1. High-Performance Vectorized Processing (process.py)
  • Parallel Chunk Aggregations: Replaced sequential row-by-row iteration with batched processing across worker processes using ProcessPoolExecutor with multiprocessing.get_context('spawn').
  • 64-Core Cloud Batch Saturation: Adjusted the dynamic chunk size floor to 25,000 rows (max(25000, 2750000 // (workers * 2))), ensuring full core saturation for provisioned 64-core Cloud Batch instances.
  • Schema & Value Formatting: Emits CountOfClaims observations as clean integer strings (1, 2) while formatting monetary metrics to 2 decimal places. Preserves all-NaN groups using min_count=1.
  • Defensive FIPS Handling: Restores leading zeroes for 10-digit tracts (padded to 11) and 4-digit counties (padded to 5), stripping trailing .0 float artifacts to prevent data loss in states with FIPS < 10.
  • Dead Flag Cleanup: Removed unused --config_file flag and cleaned --pv_map arguments.
  1. Manifest & Operational Configuration (manifest.json)
  • Updated Cloud Batch resource allocations: 64 vCPUs, 256 GB RAM, 4 TB disk.
  • Included counters/* in source_files for pipeline monitoring.
  • Cleaned script invocation flags for process.py.
  1. Testing & Fixtures (fema_download_test.py, process_test.py, test_data/)
  • Expanded unit test suites covering bulk streaming, fallback pagination, 0-byte fallbacks, and I/O error handling.
  • Added string-type verification to guarantee integer count serialization.
  • Regenerated test_data/flood_insurance_claims_output.csv (6,929 rows) to reflect both P1M and P1Y resolutions.
  • Removed unused retry package from README.md prerequisites.
  1. Validation & Testing (process_test.py, fema_download_test.py):
  • Cloud Batch Job run (test env) : link
  • Validation Output : link
  1. Reports:
  • CRA Report : link
  • Postmortem Report : link
  • Import Diagnostics & Performance Optimization Report : link

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request re-engineers the FEMA flood insurance claims import pipeline, replacing a slow, sequential, row-by-row legacy processor with a highly optimized, vectorized, multi-process chunked pipeline. It introduces direct bulk CSV downloading with paginated API fallback, updates the manifest and documentation, and adds comprehensive unit tests. Feedback suggests further optimizing the generation of StatVar names in process.py by replacing .apply() with .map() using pre-computed unique flood zone names to avoid Python function call overhead when generating millions of observations.

Comment thread statvar_imports/fema/flood_insurance_claims/process.py Outdated
@kartik-s21
kartik-s21 force-pushed the usfema-flood-claims-optimization branch 2 times, most recently from 4d7f6d6 to 56746b1 Compare September 10, 2026 10:15
@kartik-s21
kartik-s21 force-pushed the usfema-flood-claims-optimization branch 4 times, most recently from 58c6d1a to 3848d33 Compare September 11, 2026 10:57
Comment thread statvar_imports/fema/flood_insurance_claims/manifest.json Outdated
@kartik-s21
kartik-s21 force-pushed the usfema-flood-claims-optimization branch from c6a8334 to 7bb1d11 Compare September 11, 2026 12:15
Comment thread statvar_imports/fema/flood_insurance_claims/manifest.json Outdated
…ipeline

- Re-engineer download pipeline with direct bulk CSV streaming and API pagination fallback.
- Replace sequential row iteration in process.py with multi-process vectorized pipeline.
- Use concurrent.futures.ProcessPoolExecutor with spawn context for safe multiprocessing.
- Add FIPS zero-padding for tract and county places to prevent data loss for states 01-09.
- Enforce atomic publishing for observations, MCF, TMCF, and counters.
- Improve error handling with non-zero exit on empty aggregations.
- Replace eval() with ast.literal_eval() for secure mapping parsing.
- Update manifest.json node_mcf pattern and source_files.
- Expand README documentation and add comprehensive unit test suite.
@kartik-s21
kartik-s21 force-pushed the usfema-flood-claims-optimization branch from 7bb1d11 to 0c411ef Compare September 11, 2026 12:38
@balit-raibot
balit-raibot self-requested a review September 17, 2026 03:19
- Fix swallowed IOError and stage chunks before atomic move in fema_download.py.
- Enforce record count verification and raise on incomplete pagination.
- Add --output_dir flag and resolve paths relative to script directory.
- Format CountOfClaims as clean integer strings and lower chunk size floor to 25k in process.py.
- Remove dead --config_file flag and clean pv_map argument in manifest.json and process.py.
- Remove unused retry dependency from README prerequisites.
- Add unit tests for download fallback paths and IOError handling in fema_download_test.py.
- Regenerate test_data/flood_insurance_claims_output.csv with current pipeline output.
mock_get_total_records.return_value = 2

def side_effect(url, output_folder, **kwargs):
if "fake-bulk.com" in url:
mock_get_total_records.return_value = 2

def side_effect(url, output_folder, **kwargs):
if "fake-bulk.com" in url:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants