source: trunk/TOOLS/GENERATE_VEGET_MAP/ESA-LUH2/post_PFT.py @ 6267

Last change on this file since 6267 was 4805, checked in by josefine.ghattas, 7 years ago

Updated to avoid negative values. Also only use 1 pixel extension. This version is used for the data post-processed on the 29 of Novembre.
Done by V Bastrikov

  • Property svn:keywords set to Date Revision HeadURL Author
File size: 5.5 KB
Line 
1# $HeadURL$
2# $Date$
3# $Revision$
4
5import datetime, netCDF4, numpy as np, os
6
7path_luh = "/home/surface7/vuichard/LandUseMap_CMIP6/ESA2.0.7b_19PFT_quarterdeg_final//landusemap_%(year)s.nc"
8path_orc = "/home/satellites7/vbastri/LC/orchidee/ESA2.0.7b/19PFT_quarterdeg_final/PFTmap_2010.nc"
9path_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
12atts = 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
19step = 0.25
20lat = np.arange(90 - step/2., -90, -step)
21lon = np.arange(-180 + step/2., 180, step)
22area = 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)
25nc = netCDF4.Dataset(path_orc)
26orc = nc.variables["maxvegetfrac"][0]
27nc.close()
28
29# Function to extend land by 1 pixel outside land-sea mask
30def 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
43for 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
Note: See TracBrowser for help on using the repository browser.