1 | # $HeadURL$ |
---|
2 | # $Date$ |
---|
3 | # $Revision$ |
---|
4 | |
---|
5 | import datetime, netCDF4, numpy as np, os |
---|
6 | |
---|
7 | path_luh = "/home/surface7/vuichard/LandUseMap_CMIP6/ESA2.0.7b_19PFT_quarterdeg_final//landusemap_%(year)s.nc" |
---|
8 | path_orc = "/home/satellites7/vbastri/LC/orchidee/ESA2.0.7b/19PFT_quarterdeg_final/PFTmap_2010.nc" |
---|
9 | path_out = "/home/satellites7/vbastri/LC/orchidee/ESA-LUH2-final/PFTmap_%(year)s.nc" |
---|
10 | |
---|
11 | # Define global attributes to be written in the output netcdf-files |
---|
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)", |
---|
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) |
---|
26 | orc = nc.variables["maxvegetfrac"][0] |
---|
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 | |
---|
43 | for year in range(850, 2016): |
---|
44 | print year |
---|
45 | nc = netCDF4.Dataset(path_luh % dict(year=year)) |
---|
46 | veg = nc.variables["YEARLYMAXVEGETFRAC_NORMALIZE"][0,:,::-1,:] |
---|
47 | nc.close |
---|
48 | |
---|
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 | |
---|
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 |
---|
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.) |
---|
59 | |
---|
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 | |
---|
66 | # Fill masked inland pts with bare soil |
---|
67 | ys, xs = np.ma.where((orc[-2] > 0) & (veg[0].mask == True)) |
---|
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 |
---|
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.) |
---|
72 | |
---|
73 | # Extend by 1 pixel outside the land |
---|
74 | for idx in range(1): |
---|
75 | print "Extend by 1 pixel" |
---|
76 | veg = extend(veg) |
---|
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.) |
---|
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")) |
---|
97 | ncout.variables["lat"][:] = lat |
---|
98 | ncout.variables["lon"][:] = lon |
---|
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 | |
---|