Last active
August 18, 2022 14:40
-
-
Save bennyistanto/ff16dc08cc06b5a13740323db41dc8f3 to your computer and use it in GitHub Desktop.
Convert clipped Java boundary's CHIRPS GeoTIFFs in a folder to single NetCDF file with time dimension enabled and CF-Compliant
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
------------------------------------------------------------------------------------------------------------- | |
Convert CHIRPS GeoTIFF in a folder to single NetCDF file with time dimension enabled that is CF-Compliant | |
http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html | |
Based on Rich Signell's answer on StackExchange: https://gis.stackexchange.com/a/70487 | |
This script was tested using CHIRPS dekad data. Adjustment is needed if using other timesteps data for CHIRPS | |
NCO (http://nco.sourceforge.net) must be installed before using this script | |
Modified by | |
Benny Istanto, UN World Food Programme, [email protected] | |
------------------------------------------------------------------------------------------------------------- | |
""" | |
# Case Java island, Indonesia - 105.05,116,25,-8.80,-5.05 | |
# | |
# Original data in GeoTIFF format downloaded from https://data.chc.ucsb.edu/products/CHIRPS-2.0/global_monthly/tifs/ | |
# Then clipped using Java boundary (http://on.istan.to/365PSyH) via gdalwarp | |
# for i in `find *.tif`; do gdalwarp --config GDALWARP_IGNORE_BAD_CUTLINE YES -srcnodata NoData -dstnodata -9999 -cutline java_bnd_chirps_subset.shp -crop_to_cutline $i java_$i; done | |
# | |
# Clipped GeoTIFF file for Java (https://on.istan.to/3iLu68v) | |
import numpy as np | |
import datetime as dt | |
import os | |
from osgeo import gdal | |
import netCDF4 | |
import re | |
ds = gdal.Open('/path/to/directory/java_chirps-v2.0.1981.01.tif') # Data location | |
a = ds.ReadAsArray() | |
nlat,nlon = np.shape(a) | |
b = ds.GetGeoTransform() #bbox, interval | |
lon = np.arange(nlon)*b[1]+b[0] | |
lat = np.arange(nlat)*b[5]+b[3] | |
basedate = dt.datetime(1980,1,1,0,0,0) | |
# Create NetCDF file | |
nco = netCDF4.Dataset('java_cli_chirps_1months_1981_2020.nc','w',clobber=True) # Output name | |
# Create dimensions, variables and attributes: | |
nco.createDimension('lon',nlon) | |
nco.createDimension('lat',nlat) | |
nco.createDimension('time',None) | |
timeo = nco.createVariable('time','f4',('time')) | |
timeo.units = 'days since 1980-1-1 00:00:00' | |
timeo.standard_name = 'time' | |
timeo.calendar = 'gregorian' | |
timeo.axis = 'T' | |
lono = nco.createVariable('lon','f4',('lon')) | |
lono.units = 'degrees_east' | |
lono.standard_name = 'longitude' | |
lono.long_name = 'longitude' | |
lono.axis = 'X' | |
lato = nco.createVariable('lat','f4',('lat')) | |
lato.units = 'degrees_north' | |
lato.standard_name = 'latitude' | |
lato.long_name = 'latitude' | |
lato.axis = 'Y' | |
# Create container variable for CRS: lon/lat WGS84 datum | |
crso = nco.createVariable('crs','i4') | |
crso.long_name = 'Lon/Lat Coords in WGS84' | |
crso.grid_mapping_name='latitude_longitude' | |
crso.longitude_of_prime_meridian = 0.0 | |
crso.semi_major_axis = 6378137.0 | |
crso.inverse_flattening = 298.257223563 | |
# Create float variable for precipitation data, with chunking | |
pcpo = nco.createVariable('precip', 'f4', ('time', 'lat', 'lon'),zlib=True,fill_value=-9999.) | |
pcpo.units = 'mm' | |
pcpo.standard_name = 'convective precipitation rate' | |
pcpo.long_name = 'Climate Hazards group InfraRed Precipitation with Stations' | |
pcpo.time_step = 'dekad' | |
pcpo.missing_value = -9999. | |
pcpo.geospatial_lat_min = -8.8 | |
pcpo.geospatial_lat_max = -5.05 | |
pcpo.geospatial_lon_min = 105.05 | |
pcpo.geospatial_lon_max = 116.25 | |
pcpo.grid_mapping = 'crs' | |
pcpo.set_auto_maskandscale(False) | |
# Additional attributes | |
nco.Conventions='CF-1.6' | |
nco.title = "CHIRPS v2.0" | |
nco.history = "created by Climate Hazards Group. University of California at Santa Barbara" | |
nco.version = "Version 2.0" | |
nco.comments = "time variable denotes the first day of the given dekad." | |
nco.website = "https://www.chc.ucsb.edu/data/chirps" | |
nco.date_created = "2021-01-25" | |
nco.creator_name = "Benny Istanto" | |
nco.creator_email = "[email protected]" | |
nco.institution = "UN World Food Programme" | |
nco.note = "The data is developed to support regular updating procedure for SPI analysis (https://github.com/wfpidn/SPI). This activities will support WFP to assess extreme dry and wet periods as part of WFP's Seasonal Monitoring" | |
# Write lon,lat | |
lono[:]=lon | |
lato[:]=lat | |
pat = re.compile('java_chirps-v2.0.[0-9]{4}\.[0-9]{2}') | |
itime=0 | |
# Step through data, writing time and data to NetCDF | |
for root, dirs, files in os.walk('/path/to/directory/'): | |
dirs.sort() | |
files.sort() | |
for f in files: | |
if re.match(pat,f): | |
# read the time values by parsing the filename | |
year=int(f[17:21]) | |
mon=int(f[22:24]) | |
date=dt.datetime(year,mon,1,0,0,0) | |
print(date) | |
dtime=(date-basedate).total_seconds()/86400. | |
timeo[itime]=dtime | |
# precipitation | |
pcp_path = os.path.join(root,f) | |
print(pcp_path) | |
pcp=gdal.Open(pcp_path) | |
a=pcp.ReadAsArray() #data | |
pcpo[itime,:,:]=a | |
itime=itime+1 | |
nco.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment