[4777] | 1 | # $HeadURL$ |
---|
| 2 | # $Date$ |
---|
| 3 | # $Revision$ |
---|
| 4 | |
---|
[4776] | 5 | import datetime, netCDF4, numpy as np, os |
---|
| 6 | |
---|
[4805] | 7 | path_luh = "/home/surface7/vuichard/LandUseMap_CMIP6/ESA2.0.7b_19PFT_quarterdeg_final//landusemap_%(year)s.nc" |
---|
[4776] | 8 | path_orc = "/home/satellites7/vbastri/LC/orchidee/ESA2.0.7b/19PFT_quarterdeg_final/PFTmap_2010.nc" |
---|
[4805] | 9 | path_out = "/home/satellites7/vbastri/LC/orchidee/ESA-LUH2-final/PFTmap_%(year)s.nc" |
---|
[4776] | 10 | |
---|
| 11 | # Define global attributes to be written in the output netcdf-files |
---|
[4805] | 12 | atts = dict(description = "ORCHIDEE PFT map based on the ESA CCI Land Cover map v2.0.7b for 2010 aggregated by the user-tool v3.13 with the cross-walking table v2.4, followed by historical reconstrution using G. Hurtt data LU2v2h with merging rules v2.0", |
---|
| 13 | contact = "V.Bastrikov (vladislav.bastrikov@lsce.ipsl.fr), P.Peylin (philippe.peylin@lsce.ipsl.fr), N.Vuichard (nicolas.vuichard@lsce.ipsl.fr)", |
---|
[4776] | 14 | web = "https://orchidas.lsce.ipsl.fr/dev/LCCCI.php", |
---|
| 15 | date = datetime.datetime.now().strftime("%d/%m/%Y %H:%M"), |
---|
| 16 | resolution = "Regular lat/lon 0.25-degree") |
---|
| 17 | |
---|
| 18 | # Generate latitudes/longitudes arrays and calculate areas of grid cells |
---|
| 19 | step = 0.25 |
---|
| 20 | lat = np.arange(90 - step/2., -90, -step) |
---|
| 21 | lon = np.arange(-180 + step/2., 180, step) |
---|
| 22 | area = 2 * 6.371229E6**2 * np.repeat(step, len(lon))[None,:] * np.pi/180 * np.sin(0.5 * np.repeat(step, len(lat))[:,None] * np.pi/180) * np.cos(lat[:,None] * np.pi/180) |
---|
| 23 | |
---|
| 24 | # Load ORCHIDEE PFT data for year 2010 (with 19 PFTs) |
---|
| 25 | nc = netCDF4.Dataset(path_orc) |
---|
[4805] | 26 | orc = nc.variables["maxvegetfrac"][0] |
---|
[4776] | 27 | nc.close() |
---|
| 28 | |
---|
| 29 | # Function to extend land by 1 pixel outside land-sea mask |
---|
| 30 | def extend(veg): |
---|
| 31 | newveg = np.ma.masked_all((len(veg), len(lat), len(lon))) |
---|
| 32 | loc_area = np.where(veg[0].mask == False, area, 0) |
---|
| 33 | wveg = veg * loc_area |
---|
| 34 | for ilat in range(len(lat)): |
---|
| 35 | for ilon in range(len(lon)): |
---|
| 36 | if veg[0,ilat,ilon] is not np.ma.masked: |
---|
| 37 | newveg[:,ilat,ilon] = veg[:,ilat,ilon] |
---|
| 38 | else: |
---|
| 39 | if wveg[:, max(0, ilat-1) : ilat+2, max(0, ilon-1) : ilon+2].count() == 0: continue |
---|
| 40 | newveg[:,ilat,ilon] = wveg[:, max(0, ilat-1) : ilat+2, max(0, ilon-1) : ilon+2].sum(axis=-1).sum(axis=-1) / loc_area[max(0, ilat-1) : ilat+2, max(0, ilon-1) : ilon+2].sum() |
---|
| 41 | return newveg |
---|
| 42 | |
---|
[4805] | 43 | for year in range(850, 2016): |
---|
[4776] | 44 | print year |
---|
| 45 | nc = netCDF4.Dataset(path_luh % dict(year=year)) |
---|
| 46 | veg = nc.variables["YEARLYMAXVEGETFRAC_NORMALIZE"][0,:,::-1,:] |
---|
| 47 | nc.close |
---|
| 48 | |
---|
[4805] | 49 | print "Veg range [%s - %s], total range [%s - %s], %s pts" % (veg.min(), veg.max(), veg.sum(axis=0).min(), veg.sum(axis=0).max(), veg.count() / 15.) |
---|
| 50 | |
---|
[4776] | 51 | # Make LSM uniform across pfts |
---|
| 52 | vegsum = veg.sum(axis=0) |
---|
| 53 | for pft in range(15): |
---|
| 54 | ys, xs = np.where((vegsum.mask == False) & (veg[pft].mask == True)) |
---|
| 55 | if len(ys) > 0: |
---|
| 56 | print "Add %s pts to PFT%s" % (len(ys), pft+1) |
---|
| 57 | veg[pft, ys, xs] = 0 |
---|
[4805] | 58 | print "Veg range [%s - %s], total range [%s - %s], %s pts" % (veg.min(), veg.max(), veg.sum(axis=0).min(), veg.sum(axis=0).max(), veg.count() / 15.) |
---|
[4776] | 59 | |
---|
[4805] | 60 | # Clip to [0,1] and normalize |
---|
| 61 | veg = np.ma.clip(veg, 0, 1) |
---|
| 62 | veg = veg / veg.sum(axis=0) |
---|
| 63 | print "Clip to [0,1] and normalize" |
---|
| 64 | print "Veg range [%s - %s], total range [%s - %s], %s pts" % (veg.min(), veg.max(), veg.sum(axis=0).min(), veg.sum(axis=0).max(), veg.count() / 15.) |
---|
| 65 | |
---|
[4776] | 66 | # Fill masked inland pts with bare soil |
---|
[4805] | 67 | ys, xs = np.ma.where((orc[-2] > 0) & (veg[0].mask == True)) |
---|
[4776] | 68 | print "Add %s pts as bare soil" % len(ys) |
---|
| 69 | veg[0, ys, xs] = 1 |
---|
| 70 | for pft in range(1,15): veg[pft, ys, xs] = 0 |
---|
[4805] | 71 | print "Veg range [%s - %s], total range [%s - %s], %s pts" % (veg.min(), veg.max(), veg.sum(axis=0).min(), veg.sum(axis=0).max(), veg.count() / 15.) |
---|
[4776] | 72 | |
---|
[4805] | 73 | # Extend by 1 pixel outside the land |
---|
| 74 | for idx in range(1): |
---|
[4776] | 75 | print "Extend by 1 pixel" |
---|
| 76 | veg = extend(veg) |
---|
[4805] | 77 | print "Veg range [%s - %s], total range [%s - %s], %s pts" % (veg.min(), veg.max(), veg.sum(axis=0).min(), veg.sum(axis=0).max(), veg.count() / 15.) |
---|
[4776] | 78 | |
---|
| 79 | # Write output file |
---|
| 80 | if os.path.exists(path_out % dict(year=year)): raw_input("The file already exists! Press CTRL-C to exit or any key to continue") |
---|
| 81 | ncout = netCDF4.Dataset(path_out % dict(year=year), "w", format = "NETCDF3_CLASSIC") |
---|
| 82 | ncout.setncatts(atts) |
---|
| 83 | ncout.createDimension("lat", len(lat)) |
---|
| 84 | ncout.createDimension("lon", len(lon)) |
---|
| 85 | ncout.createDimension("time_counter", None) |
---|
| 86 | ncout.createDimension("veget", len(veg)) |
---|
| 87 | ncout.createVariable("lat", "f8", ("lat",)) |
---|
| 88 | ncout.createVariable("lon", "f8", ("lon",)) |
---|
| 89 | ncout.createVariable("maxvegetfrac", "f4", ("time_counter", "veget", "lat", "lon"), fill_value = 1.e+20) |
---|
| 90 | ncout.createVariable("time_counter", "f4", ("time_counter",)) |
---|
| 91 | ncout.createVariable("veget", "i4", ("veget",)) |
---|
| 92 | ncout.variables["lat"].setncatts(dict(long_name="Latitude", valid_max=90., valid_min=-90., units="degrees_north", axis="Y")) |
---|
| 93 | ncout.variables["lon"].setncatts(dict(long_name="Longitude", valid_max=180., valid_min=-180., units="degrees_east", axis="X", modulo=360., topology="circular")) |
---|
| 94 | ncout.variables["maxvegetfrac"].setncatts(dict(name = "maxvegetfrac", long_name = "Vegetation types", units = "-")) |
---|
| 95 | ncout.variables["time_counter"].setncatts(dict(units = "years since 0-1-1", calendar = "gregorian", axis = "T")) |
---|
| 96 | ncout.variables["veget"].setncatts(dict(valid_min = 1, valid_max = len(veg), long_name = "Vegetation classes", units = "-", axis = "Z")) |
---|
[4805] | 97 | ncout.variables["lat"][:] = lat |
---|
| 98 | ncout.variables["lon"][:] = lon |
---|
[4776] | 99 | ncout.variables["maxvegetfrac"][0] = veg |
---|
| 100 | ncout.variables["time_counter"][0] = year |
---|
| 101 | ncout.variables["veget"][:] = range(1, len(veg)+1) |
---|
| 102 | ncout.close() |
---|
| 103 | |
---|