π§οΈ ARC2 Rainfall Data Download Tutorial¶
Learn how to download ARC2 (Africa Rainfall Climatology version 2) daily rainfall data for climate and malaria modeling in Africa.
π Overview¶
This tutorial provides a complete Python script to download, convert, clip, and merge ARC2 daily rainfall data for any African region and time period.
ARC2 Dataset
ARC2 (Africa Rainfall Climatology v2.0) is NOAA's operational African rainfall dataset combining GPI satellite estimates with gauge observations.
- Temporal Coverage: 1983βpresent (near-real-time updates)
- Temporal Resolution: Daily
- Spatial Resolution: 0.1Β° (~10 km)
- Geographic Coverage: Africa only (40Β°Sβ40Β°N, 20Β°Wβ55Β°E)
- Format: Binary (.gz) β converted to NetCDF
- Update Lag: ~2 days
- Best For: Continental-scale African rainfall analysis
π― What This Script Does¶
The download script performs five main operations:
- π₯ Downloads ARC2 daily binary (.gz) files from NOAA CPC
- π Converts binary data to NetCDF format with proper georeferencing
- βοΈ Clips data to your region of interest (optional)
- π Merges multiple days into a single time-series NetCDF
- πΎ Saves compressed output for efficient storage
graph LR
A[Start Date] --> B[Download Binary .gz]
B --> C[Convert to NetCDF]
C --> D{Clip Region?}
D -->|Yes| E[Clip to Bounding Box]
D -->|No| F[Keep Full Africa]
E --> G[Merge Daily Files]
F --> G
G --> H[Save Time Series] π Quick Start¶
1. Installation¶
Install the required Python packages:
2. Save the Script¶
Create a new file called download_arc2.py and copy the script below into it.
3. Run Examples¶
Download 1 year, full Africa:
python download_arc2.py --start 2020-01-01 --end 2020-12-31 \
--outdir data/arc2_2020 \
--merge-name arc2_africa_2020.nc
Download and clip to Ethiopia:
python download_arc2.py --start 2013-01-01 --end 2019-12-31 \
--clip 18 3 32 50 \
--outdir data/arc2_ethiopia \
--merge-name arc2_ethiopia_2013-2019.nc
Convert existing files without re-downloading:
python download_arc2.py --start 2015-01-01 --end 2015-12-31 \
--outdir data/arc2_2015 \
--clip 15 -5 30 50 \
--merge-name arc2_ea_2015.nc \
--skip-download
π The Complete Python Script¶
Click the tabs below to view different sections of the script, or scroll down for the complete code.
This is the complete, production-ready script you can use immediately.
| download_arc2.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | |
π₯ Download Function¶
def download_file(url, dest, overwrite=False):
"""Downloads file with 404 handling and atomic write."""
dest.parent.mkdir(parents=True, exist_ok=True)
if dest.exists() and not overwrite:
return True
tmp = dest.with_suffix(dest.suffix + ".part")
with requests.get(url, stream=True, timeout=300) as r:
r.raise_for_status()
with open(tmp, "wb") as f:
for chunk in r.iter_content(chunk_size=1024*1024):
if chunk:
f.write(chunk)
tmp.replace(dest) # Atomic rename
return True
Features:
- Handles 404 errors gracefully (some dates may be missing)
- 5-minute timeout for slow connections
- Atomic write with
.parttemporary files - Streams large files efficiently
π Binary to NetCDF Conversion¶
def read_arc2_gz_to_array(bin_gz):
"""Reads gzipped binary and converts to 2D array."""
with gzip.open(bin_gz, "rb") as f:
buf = f.read()
data = np.frombuffer(buf, dtype=">f4") # big-endian float32
arr = data.reshape((NLAT, NLON)) # 801 x 751
return arr
Grid Specifications:
- Dimensions: 801 (lat) Γ 751 (lon)
- Coverage: 40Β°S to 40Β°N, 20Β°W to 55Β°E
- Resolution: 0.1Β° (~10 km)
- Format: Big-endian 32-bit floats
βοΈ Clipping Function¶
def convert_bin_to_nc(bin_gz, nc_path, clip_box=None, overwrite=False):
"""Converts binary to NetCDF with optional clipping."""
# Read binary data
arr = read_arc2_gz_to_array(bin_gz)
lats, lons = make_lat_lon()
# Create xarray Dataset
ds = xr.Dataset(
{"precip": (("time", "lat", "lon"), data3d)},
coords={"time": [t], "lat": lats, "lon": lons}
)
# Clip if requested
if clip_box:
N, S, W, E = clip_box
ds = ds.sel(lat=slice(S, N), lon=slice(W, E))
# Save with compression
ds.to_netcdf(nc_path, encoding=encoding)
π Merge Function¶
def merge_daily_nc(nc_paths, out_path, overwrite=False):
"""Merges daily files into time series."""
ds = xr.open_mfdataset(
nc_paths,
combine="by_coords",
parallel=False,
chunks={"time": 30} # Chunk for efficiency
)
encoding = {vn: {"zlib": True, "complevel": 4} for vn in ds.data_vars}
ds.to_netcdf(out_path, encoding=encoding)
The script accepts several command-line arguments:
| Argument | Required | Description | Example |
|---|---|---|---|
--start | β | Starting date | --start 2020-01-01 |
--end | β | Ending date (inclusive) | --end 2020-12-31 |
--outdir | β | Output directory | --outdir data/arc2 |
--clip | β | Bounding box [N S W E] | --clip 18 3 32 50 |
--merge-name | β | Merged filename | --merge-name arc2_ea.nc |
--skip-download | β | Skip download, only convert | --skip-download |
--overwrite | β | Overwrite existing files | --overwrite |
Default Values:
outdir:"data/arc2"merge-name: None (no merge unless specified)
Date Formats:
YYYYMMDD(e.g.,20200101)YYYY-MM-DD(e.g.,2020-01-01)
π Regional Bounding Boxes¶
Use these bounding boxes for common African regions:
π‘ Usage Examples¶
Example 1: Ethiopia - Full Time Period (2013-2019)¶
Download ARC2 data for the VECTRI Amhara case study:
python download_arc2.py \
--start 2013-01-01 \
--end 2019-12-31 \
--clip 18 3 32 50 \
--outdir data/arc2_ethiopia \
--merge-name arc2_ethiopia_2013-2019.nc
Output:
data/arc2_ethiopia/
βββ bin/
β βββ daily_clim.bin.20130101.gz
β βββ daily_clim.bin.20130102.gz
β βββ ...
βββ nc_daily/
β βββ arc2_20130101.nc
β βββ arc2_20130102.nc
β βββ ...
βββ arc2_ethiopia_2013-2019.nc β Use this file!
Example 2: Single Year - Full Africa¶
Download one year of continental data:
python download_arc2.py \
--start 2020-01-01 \
--end 2020-12-31 \
--outdir data/arc2_africa_2020 \
--merge-name arc2_africa_2020.nc
Note: Full Africa files are moderate size (~20 MB per day uncompressed, ~5 MB compressed)
Example 3: Convert Existing Files (No Download)¶
If you already have .gz files and just need to convert them:
python download_arc2.py \
--start 2015-01-01 \
--end 2015-12-31 \
--outdir data/arc2_2015 \
--clip 15 -5 30 50 \
--merge-name arc2_ea_2015.nc \
--skip-download
This is useful for:
- Re-clipping to a different region
- Re-processing with different settings
- Recovering from interrupted conversions
Example 4: Monthly Download Loop¶
Download data month by month (better for slow connections):
for month in {01..12}; do
python download_arc2.py \
--start 2020-${month}-01 \
--end 2020-${month}-31 \
--clip 15 -5 30 50 \
--outdir data/arc2_2020_monthly \
--merge-name arc2_ea_2020_${month}.nc
done
# Then merge monthly files
python -c "
import xarray as xr
from pathlib import Path
files = sorted(Path('data/arc2_2020_monthly').glob('arc2_ea_2020_*.nc'))
ds = xr.open_mfdataset(files, combine='by_coords')
ds.to_netcdf('data/arc2_ea_2020_full.nc',
encoding={'precip': {'zlib': True, 'complevel': 4}})
"
π Understanding the Output¶
File Structure¶
data/arc2_ethiopia/
βββ bin/ # Downloaded binary files
β βββ daily_clim.bin.20130101.gz
β βββ daily_clim.bin.20130102.gz
β βββ ...
βββ nc_daily/ # Individual daily NetCDFs
β βββ arc2_20130101.nc
β βββ arc2_20130102.nc
β βββ ...
βββ arc2_ethiopia_2013-2019.nc # Merged time series (use this!)
NetCDF Structure¶
Inspect the merged file:
Expected Structure:
<xarray.Dataset>
Dimensions: (time: 2557, lat: 151, lon: 181)
Coordinates:
* time (time) datetime64[ns] 2013-01-01 ... 2019-12-31
* lat (lat) float32 3.0 3.1 3.2 ... 17.8 17.9 18.0
* lon (lon) float32 32.0 32.1 32.2 ... 49.8 49.9 50.0
Data variables:
precip (time, lat, lon) float32 ...
Attributes:
source: NOAA CPC Africa Rainfall Climatology v2.0 (ARC2)
history: created from daily_clim.bin.YYYYMMDD.gz
π Advanced Usage¶
Processing After Download¶
1. Calculate Monthly Totals:
import xarray as xr
ds = xr.open_dataset("arc2_ethiopia_2013-2019.nc")
monthly = ds.resample(time="MS").sum()
monthly.to_netcdf("arc2_ethiopia_monthly.nc")
2. Extract Time Series for Location:
# Addis Ababa (9.03Β°N, 38.74Β°E)
point = ds.sel(lat=9.03, lon=38.74, method="nearest")
precip_ts = point["precip"].to_pandas()
3. Calculate Climatology:
4. Compare with CHIRPS:
import xarray as xr
arc2 = xr.open_dataset("arc2_ethiopia_2013-2019.nc")
chirps = xr.open_dataset("chirps_ethiopia_2013-2019.nc")
# Regrid ARC2 to CHIRPS resolution if needed
arc2_regrid = arc2.interp_like(chirps)
# Calculate difference
diff = arc2_regrid["precip"] - chirps["precip"]
β οΈ Troubleshooting¶
Common Issues and Solutions¶
404 Not Found
Problem: Some dates return 404 errors
Solution:
- ARC2 has occasional missing days
- Script automatically skips these
- Check NOAA CPC website for data availability
- Recent days may not be available yet (~2-day lag)
Binary Format Error
Problem: ValueError: wrong number of values
Solution:
- Check endianness: Change
dtype=">f4"todtype="<f4" - Verify file is not corrupted (re-download)
- Ensure complete download (check file size)
Out of Memory
Problem: Script crashes with memory error
Solution:
- Clip to smaller region
- Download shorter time periods
- Use chunking in merge step
- Close other applications
Missing Binary Files
Problem: "binary file missing after download"
Solution:
- Check internet connection
- Verify NOAA server is accessible
- Try
--overwriteto force re-download - Check disk space
Invalid Clip Bounds
Problem: Clip produces empty dataset
Solution:
- Ensure bounds within ARC2 coverage:
- Latitude: -40Β° to 40Β°N
- Longitude: -20Β° to 55Β°E
- Check South < North and West < East
- Verify coordinates are in correct hemisphere
π ARC2 vs CHIRPS Comparison¶
Understanding when to use each dataset:
| Feature | ARC2 | CHIRPS |
|---|---|---|
| Resolution | 0.1Β° (~10 km) | 0.05Β° (~5 km) or 0.25Β° |
| Coverage | Africa only | Quasi-global (50Β°Sβ50Β°N) |
| Temporal | 1983βpresent | 1981βpresent |
| Update Lag | ~2 days | ~2 weeks (final) |
| Data Format | Binary β NetCDF | NetCDF (direct) |
| Best For | Continental Africa, NRT | High-resolution, validated |
| Station Data | Included | Heavily used |
Recommendation:
- For Africa operational work: ARC2 (faster updates)
- For high-resolution studies: CHIRPS (better resolution)
- For validation: Use both and compare!
π Data Quality Notes¶
ARC2 Data Quality
Strengths:
- Continental coverage of Africa
- Near-real-time updates (~2 days)
- Consistent methodology since 1983
- Incorporates GTS station data
- Operational reliability
Limitations:
- Coarser than CHIRPS (0.1Β° vs 0.05Β°)
- Africa-only coverage
- Less station data than CHIRPS
- May miss localized extremes
- Binary format requires conversion
Recommended For:
- Continental-scale African studies
- Operational monitoring (NRT needs)
- Drought early warning systems
- Comparison with CHIRPS
- FEWS NET applications
π Additional Resources¶
- ARC2 Homepage: https://oasishub.co/dataset/africa-african-rainfall-climatology-1983-to-present-climate-prediction-center-noaa
-
Data Portal: https://ftp.cpc.ncep.noaa.gov/fews/fewsdata/africa/arc2/
-
Publication: Novella & Thiaw (2013), Journal of Applied Meteorology
π Support¶
Need help with the download script?
- Technical Issues: GitHub Issues
π― Next Steps¶
After downloading ARC2 data:
- Quality Check: Compare with CHIRPS or station data
- Visualization: Plot spatial and temporal patterns
- Analysis: Calculate statistics, trends, anomalies
- Integration: Combine with temperature data for VECTRI
- Comparison: Evaluate ARC2 vs CHIRPS for your region