| 1 | """ |
|---|
| 2 | This function accepts the fields needed by WRF and more specifically: |
|---|
| 3 | |
|---|
| 4 | based on the GFS Vtable. |
|---|
| 5 | Assumptions: |
|---|
| 6 | - all the 3D fields need to be on isobaric levels when they are passed to the |
|---|
| 7 | encoding function |
|---|
| 8 | - every 3D field must be supplied with a corresponding surface field |
|---|
| 9 | - the COARDS ordering of dimensions is assumed i.e. time, level, lat, lon |
|---|
| 10 | |
|---|
| 11 | Usage: |
|---|
| 12 | |
|---|
| 13 | """ |
|---|
| 14 | |
|---|
| 15 | ############################################################################# |
|---|
| 16 | # TODO |
|---|
| 17 | # - change the 'data' structure to a dictionary creating appropriate labels |
|---|
| 18 | # from the dates |
|---|
| 19 | ############################################################################# |
|---|
| 20 | import os |
|---|
| 21 | import sys |
|---|
| 22 | |
|---|
| 23 | # the syntax to import nio depends on its version. We try all options from the |
|---|
| 24 | # newest to the oldest |
|---|
| 25 | try: |
|---|
| 26 | import Nio as nio |
|---|
| 27 | except: |
|---|
| 28 | try: |
|---|
| 29 | import PyNGL.Nio as nio |
|---|
| 30 | except: |
|---|
| 31 | import PyNGL_numpy.Nio as nio |
|---|
| 32 | |
|---|
| 33 | # The following is only needed for hn3.its.monash.edu.au |
|---|
| 34 | # Unfortunately we must get rid of spurious entries in the sys.path that can |
|---|
| 35 | # lead to the loading of conflicting packages |
|---|
| 36 | for dir_idx in range(len(sys.path)-1,-1,-1): |
|---|
| 37 | if 'python2.4' in sys.path[dir_idx]: |
|---|
| 38 | sys.path.pop(dir_idx) |
|---|
| 39 | |
|---|
| 40 | import numpy as n |
|---|
| 41 | import pylab as p |
|---|
| 42 | from matplotlib.numerix import ma |
|---|
| 43 | import grib2 |
|---|
| 44 | from string import zfill |
|---|
| 45 | import pywrf.viz.utils as vu |
|---|
| 46 | from pywrf.misc.met_utils import * |
|---|
| 47 | #data_directory = '/Users/val/data/laps_nc_files/press/first_try/' |
|---|
| 48 | #sfc_data_directory = '/Users/val/data/laps_surface_data/' |
|---|
| 49 | #data_directory = '/mnt/mac/Users/val/data/laps_nc_files/press/first_try/' |
|---|
| 50 | #sfc_data_directory = '/mnt/mac/Users/val/data/laps_surface_data/' |
|---|
| 51 | #data_directory = '/media/DATA/wrf/canberra_nc_files/press/' |
|---|
| 52 | #sfc_data_directory = '/media/DATA/wrf/canberra_nc_files/sfc/' |
|---|
| 53 | #data_directory = '/media/DATA/wrf/canberra/press/' |
|---|
| 54 | #sfc_data_directory = '/media/DATA/wrf/canberra/sfc/' |
|---|
| 55 | #data_directory = '/Volumes/COMMON/wrf/canberra/press/' |
|---|
| 56 | #sfc_data_directory = '/Volumes/COMMON/wrf/canberra/sfc/' |
|---|
| 57 | #data_directory = '/Volumes/DATA/wrf/canberra/press/' |
|---|
| 58 | #sfc_data_directory = '/Volumes/DATA/wrf/canberra/sfc/' |
|---|
| 59 | #data_directory = '/Users/val/Desktop/workspace/plotting/canberra/press/' |
|---|
| 60 | #sfc_data_directory = '/Users/val/Desktop/workspace/plotting/canberra/sfc/' |
|---|
| 61 | #data_directory = \ |
|---|
| 62 | # '/nfs/1/home/vbisign/wrf/wps_data/pygrib2_test/canberra/press/analyses/' |
|---|
| 63 | #sfc_data_directory = \ |
|---|
| 64 | # '/nfs/1/home/vbisign/wrf/wps_data/pygrib2_test/canberra/sfc/' |
|---|
| 65 | data_directory = \ |
|---|
| 66 | '/nfs/1/home/vbisign/wrf/wps_data/run_003/press/' |
|---|
| 67 | sfc_data_directory = \ |
|---|
| 68 | #sfc_data_directory = '/Users/val/Desktop/workspace/plotting/canberra/sfc/' |
|---|
| 69 | # It is assumed that most people will use a single nc file as the source |
|---|
| 70 | # of their fields. Neverthless, the field nc_file_name is available for those |
|---|
| 71 | # that need to use multiple data sources. |
|---|
| 72 | |
|---|
| 73 | # the code is split in two parts... the first part gathers all the |
|---|
| 74 | # information that is specific to your data source... stuff like the location |
|---|
| 75 | # of the netcdf files, the name of the variables of interest in your files, |
|---|
| 76 | # and any special treatment of the fields like changing units, scaling the |
|---|
| 77 | # data or anything that is needed to get the data in the form required by the |
|---|
| 78 | # encoding function. |
|---|
| 79 | # This translates to simply having to generate a fairly pedantic dictionary |
|---|
| 80 | # that spells out what needs to be done with the fields during the grib |
|---|
| 81 | # encoding |
|---|
| 82 | # the second part is the encoding function itself in which it is assumed the |
|---|
| 83 | # data is passed in a dictionary containing the data as numpy arrays in the |
|---|
| 84 | # right units |
|---|
| 85 | |
|---|
| 86 | # Unfortunately it proves hard to both generalize the data structure and |
|---|
| 87 | # maintain flexibility... hence at the price of making the code longer I am |
|---|
| 88 | # going to process one field at the time so that it is clear to anyone what |
|---|
| 89 | # the steps that are (may be) involved are... |
|---|
| 90 | # I still believe it is a good idea to collect all the information needed in |
|---|
| 91 | # one big dictionary for ease of retrieval |
|---|
| 92 | |
|---|
| 93 | |
|---|
| 94 | ############################################################################# |
|---|
| 95 | # Preliminaries |
|---|
| 96 | # This is the data structure that I will pass to the encoder |
|---|
| 97 | data = [] |
|---|
| 98 | |
|---|
| 99 | # to generate a grib2 file using Jeffrey Whitaker's grib2 class, it is necessary |
|---|
| 100 | # to provide the constructor with two pieces of information: |
|---|
| 101 | # - the discipline of the data to be encoded |
|---|
| 102 | # - the identification section |
|---|
| 103 | # this means the class will need to be reconstructed every time the discipline |
|---|
| 104 | # changes |
|---|
| 105 | |
|---|
| 106 | |
|---|
| 107 | def missing(octects): |
|---|
| 108 | # To say that something is not available in a grib field they use a |
|---|
| 109 | # sequence of 1s as long as the space allocated (number of octects). |
|---|
| 110 | # When this sequence is read as an integer, it corresponds to the maximum |
|---|
| 111 | # representable number given the octects*8 bits of memory, hence: |
|---|
| 112 | # PS: refer to the grib documentation to know how many octects are |
|---|
| 113 | # allocated to any particular field |
|---|
| 114 | return 2**(8*octects) - 1 |
|---|
| 115 | |
|---|
| 116 | def prepare_sfc_data(f, fv): |
|---|
| 117 | # work out which file to pick based on the base date of the first file |
|---|
| 118 | # this is based on the (fragile) assumption that nobody changed the file |
|---|
| 119 | # names from the standard laps... |
|---|
| 120 | # this was needed for the first batch of data... |
|---|
| 121 | valid_date = fv['valid_date'].get_value()[0] |
|---|
| 122 | valid_time = fv['valid_time'].get_value()[0] |
|---|
| 123 | # the following is old stuff |
|---|
| 124 | if 0: |
|---|
| 125 | # the data in each file 'starts' at 12:00pm (UTC) |
|---|
| 126 | if valid_time < 1200: |
|---|
| 127 | valid_date -= 1 |
|---|
| 128 | #sfc_file = 'laps' + str(valid_date)[4:] + '_surface.nc' |
|---|
| 129 | print sfc_data_directory + sfc_file |
|---|
| 130 | # this is new and (hopefully) better |
|---|
| 131 | if 1: |
|---|
| 132 | # there is one sfc data file for each of the analysis containing the |
|---|
| 133 | # full 73 hours of diagnostic fields |
|---|
| 134 | # in the simplified case that we do not span analysis -> we start again |
|---|
| 135 | # with a different file at every analysis: |
|---|
| 136 | base_date = fv['base_date'].get_value() |
|---|
| 137 | base_time = fv['base_time'].get_value() |
|---|
| 138 | sfc_file = 'regprog.laps_pt375.' \ |
|---|
| 139 | + str(base_date)[4:] + '.' + str(base_time).zfill(4)[:2] \ |
|---|
| 140 | + '.slvfld.n3.nc' |
|---|
| 141 | # if we use data from a single forecast we just name the appropriate file |
|---|
| 142 | # sfc_file = 'laps0117_surface.nc' |
|---|
| 143 | sfc_f = nio.open_file(sfc_data_directory + sfc_file) |
|---|
| 144 | sfc_fv = sfc_f.variables |
|---|
| 145 | # I need this to work out which time to pick in the file... |
|---|
| 146 | sfc_valid_time = sfc_fv['valid_time'].get_value() |
|---|
| 147 | time_idx = sfc_valid_time.tolist().index(valid_time) |
|---|
| 148 | return sfc_file, sfc_f, sfc_fv, time_idx |
|---|
| 149 | |
|---|
| 150 | ############################################################################# |
|---|
| 151 | |
|---|
| 152 | ############################################################################# |
|---|
| 153 | # this variables remain unchanged across the different times |
|---|
| 154 | # BTW these (with the exception of the significance_ref_time) should not |
|---|
| 155 | # affect WRF |
|---|
| 156 | |
|---|
| 157 | # Id of originating centre (Common Code Table C-1) -> 1 for Melbourne |
|---|
| 158 | # Id of originating centre (Common Code Table C-1) -> 7 for NCEP |
|---|
| 159 | centre = 7 |
|---|
| 160 | # Id of orginating sub-centre (local table) -> 0 for no subcentre |
|---|
| 161 | # Id of orginating sub-centre (local table) -> 3 for NCEP Central Operations |
|---|
| 162 | subcentre = 0 |
|---|
| 163 | # GRIB Master Tables Version Number (Code Table 1.0) |
|---|
| 164 | master_table = 1 |
|---|
| 165 | # GRIB Local Tables Version Number (Code Table 1.1) -> 0 for not used |
|---|
| 166 | # GRIB Local Tables Version Number (Code Table 1.1) -> 1 for let's see what happens |
|---|
| 167 | local_table = 1 |
|---|
| 168 | # Significance of Reference Time (Code Table 1.2) -> 1 for start of forecast |
|---|
| 169 | significance_ref_time = 1 |
|---|
| 170 | # Production status of data (Code Table 1.3) -> 2 for research product |
|---|
| 171 | production_status = 2 |
|---|
| 172 | # idsect[12]=Type of processed data (Code Table 1.4) -> 1 -> forecast product |
|---|
| 173 | type_processed_data = 1 |
|---|
| 174 | |
|---|
| 175 | ############################################################################# |
|---|
| 176 | |
|---|
| 177 | # the first dimension of data will be the times to be processed |
|---|
| 178 | # you will have to modify this to suit your data |
|---|
| 179 | # this could mean just having a time index to get different times from the |
|---|
| 180 | # same file or just pick different files for different times. |
|---|
| 181 | files = os.listdir(data_directory) |
|---|
| 182 | #for file in files[:2]: |
|---|
| 183 | for file in files: |
|---|
| 184 | f = nio.open_file(data_directory + file) |
|---|
| 185 | fv = f.variables |
|---|
| 186 | base_date = str(fv['base_date'].get_value()) |
|---|
| 187 | year = int(base_date[0:4]) |
|---|
| 188 | month = int(base_date[4:6]) |
|---|
| 189 | day = int(base_date[6:8]) |
|---|
| 190 | # padding needed to use a string method on an integer |
|---|
| 191 | base_time = zfill(str(fv['base_time'].get_value()),4) |
|---|
| 192 | hour = int(base_time[0:2]) |
|---|
| 193 | minute = int(base_time[2:]) |
|---|
| 194 | second = 0 |
|---|
| 195 | # I did not generate this in the preamble above because I needed to wait |
|---|
| 196 | # for the base date and time info from the netcdf files... |
|---|
| 197 | # NB the order of the variables in the list MATTERS! |
|---|
| 198 | idsect = [ |
|---|
| 199 | centre, |
|---|
| 200 | subcentre, |
|---|
| 201 | master_table, |
|---|
| 202 | local_table, |
|---|
| 203 | significance_ref_time, |
|---|
| 204 | year, |
|---|
| 205 | month, |
|---|
| 206 | day, |
|---|
| 207 | hour, |
|---|
| 208 | minute, |
|---|
| 209 | second, |
|---|
| 210 | production_status, |
|---|
| 211 | type_processed_data |
|---|
| 212 | ] |
|---|
| 213 | |
|---|
| 214 | print file |
|---|
| 215 | # gdsinfo - Sequence containing information needed for the grid definition |
|---|
| 216 | # section. |
|---|
| 217 | gdsinfo = n.zeros((5,), dtype=int) |
|---|
| 218 | # gdsinfo[0] = Source of grid definition (see Code Table 3.0) -> 0 -> will be |
|---|
| 219 | # specified in octects 13-14 |
|---|
| 220 | gdsinfo[0] = 0 |
|---|
| 221 | # gdsinfo[1] = Number of grid points in the defined grid. |
|---|
| 222 | # TODO make it more general |
|---|
| 223 | #lat = fv['lat'].get_value() |
|---|
| 224 | # the idx was chosen to stop the data at 55S and avoid the rubbish far south |
|---|
| 225 | lat_cheat_idx = 30 |
|---|
| 226 | # 1 for the full range |
|---|
| 227 | lon_cheat_idx = 1 |
|---|
| 228 | lat = fv['lat'].get_value()[lat_cheat_idx:] |
|---|
| 229 | lon = fv['lon'].get_value()[:-lon_cheat_idx] |
|---|
| 230 | gdsinfo[1] = len(lat)*len(lon) |
|---|
| 231 | # gdsinfo[2] = Number of octets needed for each additional grid points defn. |
|---|
| 232 | # Used to define number of points in each row for non-reg grids |
|---|
| 233 | # (=0 for regular grid). |
|---|
| 234 | gdsinfo[2] = 0 |
|---|
| 235 | # gdsinfo[3] = Interp. of list for optional points defn (Code Table 3.11) |
|---|
| 236 | # 0 -> There is no appended list |
|---|
| 237 | gdsinfo[3] = 0 |
|---|
| 238 | # gdsinfo[4] = Grid Definition Template Number (Code Table 3.1) |
|---|
| 239 | # 0 -> Latitude/Longitude (or equidistant cylindrical, or Plate Carree) |
|---|
| 240 | gdsinfo[4] = 0 |
|---|
| 241 | |
|---|
| 242 | # gdtmpl - Contains the data values for the specified Grid Definition |
|---|
| 243 | # Template ( NN=gds[4] ). Each element of this integer array contains |
|---|
| 244 | # an entry (in the order specified) of Grid Definition Template 3.NN |
|---|
| 245 | gdtmpl = n.zeros((19,), dtype=n.int64) |
|---|
| 246 | # In the following we refer to the lat/lon template (grid template 3.0) |
|---|
| 247 | # Oct: 15 Shape of the Earth (See Table 3.2) |
|---|
| 248 | # 0 -> spherical with radius = 6,367,470.0 m |
|---|
| 249 | # TODO double check the radius they used in Tan's code |
|---|
| 250 | gdtmpl[0] = 0 |
|---|
| 251 | # Oct: 16 Scale Factor of radius of spherical Earth |
|---|
| 252 | # TODO hopefully (given the last option) the next 5 are ignored... |
|---|
| 253 | # if 1 octet is the basic unit then a value of 255 should be equivalent |
|---|
| 254 | # to all bits set to 1 -> this could be broken if more than one octect |
|---|
| 255 | # is assigned -> maybe I should use the maximum represantable number |
|---|
| 256 | # tailored to the number of octects? |
|---|
| 257 | # are there any rules that make the encoder ignore automatically certain |
|---|
| 258 | # options e.g. the oblate spheroid one when a spherical shape is assumed |
|---|
| 259 | gdtmpl[1] = missing(1) |
|---|
| 260 | # Oct: 17-20 Scale value of radius of spherical Earth |
|---|
| 261 | # NB they (grib2 std) interprets all bits set to 1 as a missing value |
|---|
| 262 | # hence the value is base*(word_width*words_assigned) - 1 |
|---|
| 263 | # base is 2 since we are working in binary |
|---|
| 264 | # word_width is 8 since they use octects |
|---|
| 265 | # words_assigned is the number of words reserved to represent the value |
|---|
| 266 | # -1 gives us the greatest representable number since we start from 0 |
|---|
| 267 | gdtmpl[2] = missing(1) |
|---|
| 268 | # Oct: 21 Scale factor of major axis of oblate spheroid Earth |
|---|
| 269 | gdtmpl[3] = missing(1) |
|---|
| 270 | # Oct: 22-25 Scaled value of major axis of oblate spheroid Earth |
|---|
| 271 | gdtmpl[4] = missing(4) |
|---|
| 272 | # Oct: 26 Scale factor of minor axis of oblate spheroid Earth |
|---|
| 273 | gdtmpl[5] = missing(1) |
|---|
| 274 | # Oct: 27-30 Scaled value of minor axis of oblate spheroid Earth |
|---|
| 275 | gdtmpl[6] = missing(4) |
|---|
| 276 | # Oct: 31-34 Number of points along a parallel |
|---|
| 277 | gdtmpl[7] = len(lon) |
|---|
| 278 | # Oct: 35-38 Number of points along a meridian |
|---|
| 279 | gdtmpl[8] = len(lat) |
|---|
| 280 | # Oct: 39-42 Basic angle of the initial production domain (see Note 1) |
|---|
| 281 | gdtmpl[9] = missing(4) |
|---|
| 282 | # Oct: 43-46 Subdivisions of basic angle used to define extreme longitudes |
|---|
| 283 | # and latitudes, and direction increments (see Note 1) |
|---|
| 284 | gdtmpl[10] = missing(4) |
|---|
| 285 | # Oct: 47-50 La1 - Latitude of first grid point (see Note 1) |
|---|
| 286 | #gdtmpl.append(in_vars['lat'].get_value()[-1]*1e6) |
|---|
| 287 | gdtmpl[11] = lat[-1]*1e6 |
|---|
| 288 | #gdtmpl[11] = lat[0]*1e6 |
|---|
| 289 | # Oct: 51-54 Lo1 - Longitude of first grid point (see Note 1) |
|---|
| 290 | #gdtmpl.append(in_vars['lon'].get_value()[0]*1e6) |
|---|
| 291 | gdtmpl[12] = lon[0]*1e6 |
|---|
| 292 | # Oct: 55 Resolution and component flags (see Table 3.3) |
|---|
| 293 | # This should set all the bits to 0 meaning |
|---|
| 294 | # bit value meaning |
|---|
| 295 | # 1-2 ? Reserved |
|---|
| 296 | # 3 0 i direction increments not given |
|---|
| 297 | # 4 0 j direction increments not given |
|---|
| 298 | # 5 0 Resolved u and v components of vector quantities |
|---|
| 299 | # relative to easterly and northerly directions |
|---|
| 300 | # 6-8 0 Reserved - set to zero |
|---|
| 301 | #gdtmpl[13] = 0 |
|---|
| 302 | #gdtmpl[13] = 12 |
|---|
| 303 | gdtmpl[13] = 48 |
|---|
| 304 | # Oct: 56-59 La2 - Latitude of last grid point (see Note1) |
|---|
| 305 | #gdtmpl.append(in_vars['lat'].get_value()[0]*1e6) |
|---|
| 306 | gdtmpl[14] = lat[0]*1e6 |
|---|
| 307 | #gdtmpl[14] = lat[-1]*1e6 |
|---|
| 308 | # Oct: 60-63 Lo2 - Longitude of last grid point (see Note 1) |
|---|
| 309 | #gdtmpl.append(in_vars['lon'].get_value()[-1]*1e6) |
|---|
| 310 | gdtmpl[15] = lon[-1]*1e6 |
|---|
| 311 | # Oct: 64-67 i (west-east) Direction increment (see Note1) |
|---|
| 312 | #gdtmpl[16] = missing(4) |
|---|
| 313 | gdtmpl[16] = 0.375*1e6 |
|---|
| 314 | # Oct: 68-71 j (south-north) Direction increment (see Note1) |
|---|
| 315 | #gdtmpl[17] = missing(4) |
|---|
| 316 | gdtmpl[17] = 0.375*1e6 |
|---|
| 317 | #gdtmpl[17] = -0.375*1e6 |
|---|
| 318 | #gdtmpl[17] = 33143 |
|---|
| 319 | # Oct: 72 Scanning mode (flags see Table 3.4) |
|---|
| 320 | # TODO double check if this is legit considering the flags |
|---|
| 321 | # This should set all the bits to 0 meaning |
|---|
| 322 | # bit value meaning |
|---|
| 323 | # 1 0 Points in the first row or column scan in +i (+x) |
|---|
| 324 | # direction |
|---|
| 325 | # 2 0 Points in the first row or column scan in -i (-x) |
|---|
| 326 | # direction |
|---|
| 327 | # 3 0 Adjacent pints in i(x) direction are consecutive |
|---|
| 328 | # 4 0 All rows scan in the same direction |
|---|
| 329 | # 5-8 0 Reserved (set to zero) |
|---|
| 330 | # NB I suspect the 3 bit might be important for the 'majoring' of the array? |
|---|
| 331 | # # 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0 |
|---|
| 332 | # # 1 2 3 4 5 6 7 8 |
|---|
| 333 | gdtmpl[18] = 0 # 0 0 0 0 0 0 0 0 |
|---|
| 334 | #gdtmpl[18] = 16 # 0 0 0 1 0 0 0 0 |
|---|
| 335 | #gdtmpl[18] = 32 # 0 0 1 0 0 0 0 0 |
|---|
| 336 | #gdtmpl[18] = 64 # 0 1 0 0 0 0 0 0 |
|---|
| 337 | #gdtmpl[18] = 128 # 1 0 0 0 0 0 0 0 |
|---|
| 338 | |
|---|
| 339 | #gdtmpl[18] = 192 # 1 1 0 0 0 0 0 0 |
|---|
| 340 | #gdtmpl[18] = 160 # 1 0 1 0 0 0 0 0 |
|---|
| 341 | #gdtmpl[18] = 144 # 1 0 0 1 0 0 0 0 |
|---|
| 342 | #gdtmpl[18] = 96 # 0 1 1 0 0 0 0 0 |
|---|
| 343 | #gdtmpl[18] = 80 # 0 1 0 1 0 0 0 0 |
|---|
| 344 | #gdtmpl[18] = 48 # 0 0 1 1 0 0 0 0 |
|---|
| 345 | |
|---|
| 346 | #gdtmpl[18] = 224 # 1 1 1 0 0 0 0 0 |
|---|
| 347 | #gdtmpl[18] = 208 # 1 1 0 1 0 0 0 0 |
|---|
| 348 | #gdtmpl[18] = 176 # 1 0 1 1 0 0 0 0 |
|---|
| 349 | #gdtmpl[18] = 112 # 0 1 1 1 0 0 0 0 |
|---|
| 350 | |
|---|
| 351 | #gdtmpl[18] = 240 # 1 1 1 1 0 0 0 0 |
|---|
| 352 | |
|---|
| 353 | data.append( |
|---|
| 354 | { |
|---|
| 355 | 'idsect' : idsect, |
|---|
| 356 | 'gdsinfo' : gdsinfo, |
|---|
| 357 | 'gdtmpl' : gdtmpl, |
|---|
| 358 | 'discipline': |
|---|
| 359 | { |
|---|
| 360 | # the first number in the list is the code for the discipline |
|---|
| 361 | 'atmos': |
|---|
| 362 | { |
|---|
| 363 | 'code':0, |
|---|
| 364 | 'fields':{'2d':{}, '3d':{}} |
|---|
| 365 | }, |
|---|
| 366 | 'ocean': |
|---|
| 367 | { |
|---|
| 368 | 'code':10, |
|---|
| 369 | 'fields':{'2d':{}, '3d':{}} |
|---|
| 370 | }, |
|---|
| 371 | 'land': |
|---|
| 372 | { |
|---|
| 373 | 'code':2, |
|---|
| 374 | 'fields':{'2d':{}, '3d':{}} |
|---|
| 375 | } |
|---|
| 376 | } |
|---|
| 377 | } |
|---|
| 378 | ) |
|---|
| 379 | # this is the part where we extract the data from the nc files and put |
|---|
| 380 | # into the structure we will pass later to the encoder |
|---|
| 381 | # let's start with the atmospheric products specifically the surface |
|---|
| 382 | # fields |
|---|
| 383 | # each variables comes with all the metadata necessary to do its grib |
|---|
| 384 | # encoding using the addfield method of the encoder class i.e. pdtnum, |
|---|
| 385 | # pdtmpl, drtnum, drtmpl, field |
|---|
| 386 | |
|---|
| 387 | # -1 stands for the last one (time) added |
|---|
| 388 | dummy = data[-1]['discipline']['atmos']['fields']['2d'] |
|---|
| 389 | |
|---|
| 390 | # Let's prepare the surface pressure data and metadata |
|---|
| 391 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 392 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 393 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 394 | pdtnum = 0 |
|---|
| 395 | # array of zeros (int) of size 15 |
|---|
| 396 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 397 | # Follows the definition of template 4.0 |
|---|
| 398 | # Oct 10: Parameter category (see Code table 4.1). 3 -> mass |
|---|
| 399 | pdtmpl[0] = 3 |
|---|
| 400 | # Oct 11: Parameter number (see Code table 4.2). 0 -> pressure |
|---|
| 401 | pdtmpl[1] = 0 |
|---|
| 402 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 403 | pdtmpl[2] = 2 |
|---|
| 404 | # Oct 13: Background generating process identifier |
|---|
| 405 | # (defined by originating centre) |
|---|
| 406 | pdtmpl[3] = missing(1) |
|---|
| 407 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 408 | # (defined by originating centre) |
|---|
| 409 | pdtmpl[4] = missing(1) |
|---|
| 410 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 411 | pdtmpl[5] = missing(2) |
|---|
| 412 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 413 | pdtmpl[6] = missing(1) |
|---|
| 414 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 415 | # 1 -> hours |
|---|
| 416 | # NB WPS expects this to be hours! |
|---|
| 417 | pdtmpl[7] = 1 |
|---|
| 418 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 419 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 420 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 421 | # 1 -> ground or water surface |
|---|
| 422 | pdtmpl[9] = 1 |
|---|
| 423 | # Oct 24: Scale factor of first fixed surface |
|---|
| 424 | pdtmpl[10] = 0 |
|---|
| 425 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 426 | pdtmpl[11] = 0 |
|---|
| 427 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 428 | pdtmpl[12] = missing(1) |
|---|
| 429 | # Oct 30: Scale factor of second fixed surface |
|---|
| 430 | pdtmpl[13] = missing(1) |
|---|
| 431 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 432 | pdtmpl[14] = missing(3) |
|---|
| 433 | |
|---|
| 434 | # drtnum - Data Representation Template Number (see Code Table 5.0). |
|---|
| 435 | # 0 -> grid point data - simple packing |
|---|
| 436 | drtnum = 0 |
|---|
| 437 | # drtmpl - Sequence with the data values for the specified Data Representation |
|---|
| 438 | # Template (N=drtnum). Each element of this integer array contains an |
|---|
| 439 | # entry (in the order specified) of Data Representation Template 5.N Note |
|---|
| 440 | # that some values in this template (eg. reference values, number of |
|---|
| 441 | # bits, etc...) may be changed by the data packing algorithms. Use this to |
|---|
| 442 | # specify scaling factors and order of spatial differencing, if desired. |
|---|
| 443 | drtmpl = n.zeros((5,),dtype=int) |
|---|
| 444 | # NB to make sense of the following remember (from the wmo std): |
|---|
| 445 | # The original data value Y (in the units of code table 4.2) can be recovered |
|---|
| 446 | # with the formula: |
|---|
| 447 | # Y * 10^D= R + (X1+X2) * 2^E |
|---|
| 448 | # For simple packing and all spectral data |
|---|
| 449 | # E = Binary scale factor, |
|---|
| 450 | # D = Decimal scale factor |
|---|
| 451 | # R = Reference value of the whole field, |
|---|
| 452 | # X1 = 0, |
|---|
| 453 | # X2 = Scaled (encoded) value. |
|---|
| 454 | |
|---|
| 455 | # Oct: 12-15. Reference value (R) (IEEE 32-bit floating-point value) |
|---|
| 456 | drtmpl[0] = 0 |
|---|
| 457 | # Oct: 16-17. Binary scale factor (E) |
|---|
| 458 | drtmpl[1] = 0 |
|---|
| 459 | # Oct: 18-19. Decimal scale factor (D) |
|---|
| 460 | drtmpl[2] = 0 |
|---|
| 461 | # Oct: 20. Number of bits used for each packed value for simple packing, or |
|---|
| 462 | drtmpl[3] = 24 |
|---|
| 463 | # for each group reference value for complex packing or spatial differencing |
|---|
| 464 | # Oct: 21. Type of original field values (see Code Table 5.1) |
|---|
| 465 | # 0 -> floating point |
|---|
| 466 | drtmpl[4] = 0 |
|---|
| 467 | |
|---|
| 468 | cheat = fv['sfc_pres'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 469 | field = n.zeros(cheat.shape) |
|---|
| 470 | for lat_idx in range(cheat.shape[0]): |
|---|
| 471 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 472 | |
|---|
| 473 | if 0: |
|---|
| 474 | dummy['sfc_pres'] = { |
|---|
| 475 | 'long_name' : 'surface pressure', |
|---|
| 476 | 'pdtnum' : pdtnum, |
|---|
| 477 | 'pdtmpl' : pdtmpl, |
|---|
| 478 | 'drtnum' : drtnum, |
|---|
| 479 | 'drtmpl' : drtmpl, |
|---|
| 480 | #'field' : fv['sfc_pres'].get_value()[0] |
|---|
| 481 | #'field' : fv['sfc_pres'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 482 | 'field' : field |
|---|
| 483 | } |
|---|
| 484 | |
|---|
| 485 | # Let's prepare the mean sea level pressure data and metadata |
|---|
| 486 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 487 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 488 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 489 | pdtnum = 0 |
|---|
| 490 | # array of zeros (int) of size 15 |
|---|
| 491 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 492 | # Follows the definition of template 4.0 |
|---|
| 493 | # Oct 10: Parameter category (see Code table 4.1). 3 -> mass |
|---|
| 494 | pdtmpl[0] = 3 |
|---|
| 495 | # Oct 11: Parameter number (see Code table 4.2). 1 -> MSLP |
|---|
| 496 | pdtmpl[1] = 1 |
|---|
| 497 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 498 | pdtmpl[2] = 2 |
|---|
| 499 | # Oct 13: Background generating process identifier |
|---|
| 500 | # (defined by originating centre) |
|---|
| 501 | pdtmpl[3] = missing(1) |
|---|
| 502 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 503 | # (defined by originating centre) |
|---|
| 504 | pdtmpl[4] = missing(1) |
|---|
| 505 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 506 | pdtmpl[5] = missing(2) |
|---|
| 507 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 508 | pdtmpl[6] = missing(1) |
|---|
| 509 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 510 | # 1 -> hours |
|---|
| 511 | # NB WPS expects this to be hours! |
|---|
| 512 | pdtmpl[7] = 1 |
|---|
| 513 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 514 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 515 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 516 | # 101 -> sea level |
|---|
| 517 | pdtmpl[9] = 101 |
|---|
| 518 | # Oct 24: Scale factor of first fixed surface |
|---|
| 519 | pdtmpl[10] = 0 |
|---|
| 520 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 521 | pdtmpl[11] = 0 |
|---|
| 522 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 523 | pdtmpl[12] = missing(1) |
|---|
| 524 | # Oct 30: Scale factor of second fixed surface |
|---|
| 525 | pdtmpl[13] = missing(1) |
|---|
| 526 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 527 | pdtmpl[14] = missing(3) |
|---|
| 528 | |
|---|
| 529 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 530 | # replicate it in the following fields if you need to change this on a |
|---|
| 531 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 532 | # so then make sure you define one for each variable that follows or be |
|---|
| 533 | # aware that the last one defined will apply to all that follows. |
|---|
| 534 | |
|---|
| 535 | cheat = fv['mslp'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 536 | # to go from mb to Pa |
|---|
| 537 | #cheat *= 100. |
|---|
| 538 | cheat = cheat * 100. |
|---|
| 539 | field = n.zeros(cheat.shape) |
|---|
| 540 | for lat_idx in range(cheat.shape[0]): |
|---|
| 541 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 542 | |
|---|
| 543 | dummy['mslp'] = { |
|---|
| 544 | 'long_name' : 'mean sea level pressure', |
|---|
| 545 | # in my data it comes in mb and I want in Pascals |
|---|
| 546 | 'pdtnum' : pdtnum, |
|---|
| 547 | 'pdtmpl' : pdtmpl, |
|---|
| 548 | 'drtnum' : drtnum, |
|---|
| 549 | 'drtmpl' : drtmpl, |
|---|
| 550 | #'field' : fv['mslp'].get_value()[0]*100. |
|---|
| 551 | #'field' : fv['mslp'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx]*100. |
|---|
| 552 | 'field' : field |
|---|
| 553 | } |
|---|
| 554 | |
|---|
| 555 | # Let's prepare the 2m temperature data and metadata |
|---|
| 556 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 557 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 558 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 559 | pdtnum = 0 |
|---|
| 560 | # array of zeros (int) of size 15 |
|---|
| 561 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 562 | # Follows the definition of template 4.0 |
|---|
| 563 | # Oct 10: Parameter category (see Code table 4.1). 0 -> temperature |
|---|
| 564 | pdtmpl[0] = 0 |
|---|
| 565 | # Oct 11: Parameter number (see Code table 4.2). 0 -> temperature |
|---|
| 566 | pdtmpl[1] = 0 |
|---|
| 567 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 568 | pdtmpl[2] = 2 |
|---|
| 569 | # Oct 13: Background generating process identifier |
|---|
| 570 | # (defined by originating centre) |
|---|
| 571 | pdtmpl[3] = missing(1) |
|---|
| 572 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 573 | # (defined by originating centre) |
|---|
| 574 | pdtmpl[4] = missing(1) |
|---|
| 575 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 576 | pdtmpl[5] = missing(2) |
|---|
| 577 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 578 | pdtmpl[6] = missing(1) |
|---|
| 579 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 580 | # 1 -> hours |
|---|
| 581 | # NB WPS expects this to be hours! |
|---|
| 582 | pdtmpl[7] = 1 |
|---|
| 583 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 584 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 585 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 586 | # 1 -> ground or water surface |
|---|
| 587 | pdtmpl[9] = 103 |
|---|
| 588 | # Oct 24: Scale factor of first fixed surface |
|---|
| 589 | pdtmpl[10] = 0 |
|---|
| 590 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 591 | # -> 2m above ground |
|---|
| 592 | pdtmpl[11] = 2 |
|---|
| 593 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 594 | pdtmpl[12] = missing(1) |
|---|
| 595 | # Oct 30: Scale factor of second fixed surface |
|---|
| 596 | pdtmpl[13] = missing(1) |
|---|
| 597 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 598 | pdtmpl[14] = missing(3) |
|---|
| 599 | |
|---|
| 600 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 601 | # replicate it in the following fields if you need to change this on a |
|---|
| 602 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 603 | # so then make sure you define one for each variable that follows or be |
|---|
| 604 | # aware that the last one defined will apply to all that follows. |
|---|
| 605 | |
|---|
| 606 | cheat = fv['sfc_temp'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 607 | field = n.zeros(cheat.shape) |
|---|
| 608 | for lat_idx in range(cheat.shape[0]): |
|---|
| 609 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 610 | |
|---|
| 611 | dummy['sfc_temp'] = { |
|---|
| 612 | 'long_name' : 'surface temperature', |
|---|
| 613 | 'pdtnum' : pdtnum, |
|---|
| 614 | 'pdtmpl' : pdtmpl, |
|---|
| 615 | 'drtnum' : drtnum, |
|---|
| 616 | 'drtmpl' : drtmpl, |
|---|
| 617 | #'field' : fv['sfc_temp'].get_value()[0] |
|---|
| 618 | #'field' : fv['sfc_temp'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 619 | 'field' : field |
|---|
| 620 | } |
|---|
| 621 | |
|---|
| 622 | # Let's prepare the 2m temperature data and metadata |
|---|
| 623 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 624 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 625 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 626 | pdtnum = 0 |
|---|
| 627 | # array of zeros (int) of size 15 |
|---|
| 628 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 629 | # Follows the definition of template 4.0 |
|---|
| 630 | # Oct 10: Parameter category (see Code table 4.1). 0 -> temperature |
|---|
| 631 | pdtmpl[0] = 0 |
|---|
| 632 | # Oct 11: Parameter number (see Code table 4.2). 0 -> temperature |
|---|
| 633 | pdtmpl[1] = 0 |
|---|
| 634 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 635 | pdtmpl[2] = 2 |
|---|
| 636 | # Oct 13: Background generating process identifier |
|---|
| 637 | # (defined by originating centre) |
|---|
| 638 | pdtmpl[3] = missing(1) |
|---|
| 639 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 640 | # (defined by originating centre) |
|---|
| 641 | pdtmpl[4] = missing(1) |
|---|
| 642 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 643 | pdtmpl[5] = missing(2) |
|---|
| 644 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 645 | pdtmpl[6] = missing(1) |
|---|
| 646 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 647 | # 1 -> hours |
|---|
| 648 | # NB WPS expects this to be hours! |
|---|
| 649 | pdtmpl[7] = 1 |
|---|
| 650 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 651 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 652 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 653 | # 1 -> surface |
|---|
| 654 | pdtmpl[9] = 1 |
|---|
| 655 | # Oct 24: Scale factor of first fixed surface |
|---|
| 656 | pdtmpl[10] = 0 |
|---|
| 657 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 658 | # -> 2m above ground |
|---|
| 659 | pdtmpl[11] = 0 |
|---|
| 660 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 661 | pdtmpl[12] = missing(1) |
|---|
| 662 | # Oct 30: Scale factor of second fixed surface |
|---|
| 663 | pdtmpl[13] = missing(1) |
|---|
| 664 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 665 | pdtmpl[14] = missing(3) |
|---|
| 666 | |
|---|
| 667 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 668 | # replicate it in the following fields if you need to change this on a |
|---|
| 669 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 670 | # so then make sure you define one for each variable that follows or be |
|---|
| 671 | # aware that the last one defined will apply to all that follows. |
|---|
| 672 | |
|---|
| 673 | cheat = fv['skin_temp'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 674 | field = n.zeros(cheat.shape) |
|---|
| 675 | for lat_idx in range(cheat.shape[0]): |
|---|
| 676 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 677 | |
|---|
| 678 | dummy['skin_temp'] = { |
|---|
| 679 | 'long_name' : 'skin temperature', |
|---|
| 680 | 'pdtnum' : pdtnum, |
|---|
| 681 | 'pdtmpl' : pdtmpl, |
|---|
| 682 | 'drtnum' : drtnum, |
|---|
| 683 | 'drtmpl' : drtmpl, |
|---|
| 684 | #'field' : fv['skin_temp'].get_value()[0] |
|---|
| 685 | #'field' : fv['skin_temp'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 686 | 'field' : field |
|---|
| 687 | } |
|---|
| 688 | |
|---|
| 689 | # the next fields will come from a different file... |
|---|
| 690 | sfc_file, sfc_f, sfc_fv, time_idx = prepare_sfc_data(f,fv) |
|---|
| 691 | # DEBUG |
|---|
| 692 | #p.figure() |
|---|
| 693 | #p.contour(dummy['skin_temp']['field']) |
|---|
| 694 | #p.figure() |
|---|
| 695 | #p.contour(sfc_fv['skin_temp'].get_value()[time_idx]) |
|---|
| 696 | |
|---|
| 697 | # Let's prepare the 2m RH data and metadata |
|---|
| 698 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 699 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 700 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 701 | pdtnum = 0 |
|---|
| 702 | # array of zeros (int) of size 15 |
|---|
| 703 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 704 | # Follows the definition of template 4.0 |
|---|
| 705 | # Oct 10: Parameter category (see Code table 4.1). 1 -> moisture |
|---|
| 706 | pdtmpl[0] = 1 |
|---|
| 707 | # Oct 11: Parameter number (see Code table 4.2). 1 -> RH |
|---|
| 708 | pdtmpl[1] = 1 |
|---|
| 709 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 710 | pdtmpl[2] = 2 |
|---|
| 711 | # Oct 13: Background generating process identifier |
|---|
| 712 | # (defined by originating centre) |
|---|
| 713 | pdtmpl[3] = missing(1) |
|---|
| 714 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 715 | # (defined by originating centre) |
|---|
| 716 | pdtmpl[4] = missing(1) |
|---|
| 717 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 718 | pdtmpl[5] = missing(2) |
|---|
| 719 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 720 | pdtmpl[6] = missing(1) |
|---|
| 721 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 722 | # 1 -> hours |
|---|
| 723 | # NB WPS expects this to be hours! |
|---|
| 724 | pdtmpl[7] = 1 |
|---|
| 725 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 726 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 727 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 728 | # 103 -> fixed height above ground |
|---|
| 729 | pdtmpl[9] = 103 |
|---|
| 730 | # Oct 24: Scale factor of first fixed surface |
|---|
| 731 | pdtmpl[10] = 0 |
|---|
| 732 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 733 | # -> 2m above ground |
|---|
| 734 | pdtmpl[11] = 2 |
|---|
| 735 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 736 | pdtmpl[12] = missing(1) |
|---|
| 737 | # Oct 30: Scale factor of second fixed surface |
|---|
| 738 | pdtmpl[13] = missing(1) |
|---|
| 739 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 740 | pdtmpl[14] = missing(3) |
|---|
| 741 | |
|---|
| 742 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 743 | # replicate it in the following fields if you need to change this on a |
|---|
| 744 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 745 | # so then make sure you define one for each variable that follows or be |
|---|
| 746 | # aware that the last one defined will apply to all that follows. |
|---|
| 747 | |
|---|
| 748 | # The surface files do not come with mixing ratio, but we can calculate |
|---|
| 749 | # that from the dew point temperature... |
|---|
| 750 | #dew_point = sfc_fv['scrn_dewpt'].get_value()[time_idx] |
|---|
| 751 | dew_point = sfc_fv['scrn_dewpt'].get_value()[time_idx,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 752 | vapour_pressure = goff_gratch(dew_point) |
|---|
| 753 | #sfc_temp = sfc_fv['scrn_temp'].get_value()[time_idx] |
|---|
| 754 | sfc_temp = sfc_fv['scrn_temp'].get_value()[time_idx,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 755 | sat_vapour_pressure = goff_gratch(sfc_temp) |
|---|
| 756 | #sat_vapour_pressure = ma.masked_where(sat_vapour_pressure == 0., |
|---|
| 757 | # sat_vapour_pressure) |
|---|
| 758 | sfc_rh = vapour_pressure / sat_vapour_pressure * 100 |
|---|
| 759 | del sfc_temp, vapour_pressure, dew_point, sat_vapour_pressure |
|---|
| 760 | |
|---|
| 761 | cheat = sfc_rh |
|---|
| 762 | field = n.zeros(cheat.shape) |
|---|
| 763 | for lat_idx in range(cheat.shape[0]): |
|---|
| 764 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 765 | |
|---|
| 766 | dummy['sfc_rh'] = { |
|---|
| 767 | 'long_name' : '2m relative humidity', |
|---|
| 768 | 'pdtnum' : pdtnum, |
|---|
| 769 | 'pdtmpl' : pdtmpl, |
|---|
| 770 | 'drtnum' : drtnum, |
|---|
| 771 | 'drtmpl' : drtmpl, |
|---|
| 772 | #'field' : sfc_rh.filled(fill_value=0.) |
|---|
| 773 | #'field' : sfc_rh |
|---|
| 774 | 'field' : field |
|---|
| 775 | } |
|---|
| 776 | |
|---|
| 777 | # Let's prepare the zonal 10m wind data and metadata |
|---|
| 778 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 779 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 780 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 781 | pdtnum = 0 |
|---|
| 782 | # array of zeros (int) of size 15 |
|---|
| 783 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 784 | # Follows the definition of template 4.0 |
|---|
| 785 | # Oct 10: Parameter category (see Code table 4.1). 2 -> momentum |
|---|
| 786 | pdtmpl[0] = 2 |
|---|
| 787 | # Oct 11: Parameter number (see Code table 4.2). 2 -> u-component of wind |
|---|
| 788 | pdtmpl[1] = 2 |
|---|
| 789 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 790 | pdtmpl[2] = 2 |
|---|
| 791 | # Oct 13: Background generating process identifier |
|---|
| 792 | # (defined by originating centre) |
|---|
| 793 | pdtmpl[3] = missing(1) |
|---|
| 794 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 795 | # (defined by originating centre) |
|---|
| 796 | pdtmpl[4] = missing(1) |
|---|
| 797 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 798 | pdtmpl[5] = missing(2) |
|---|
| 799 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 800 | pdtmpl[6] = missing(1) |
|---|
| 801 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 802 | # 1 -> hours |
|---|
| 803 | # NB WPS expects this to be hours! |
|---|
| 804 | pdtmpl[7] = 1 |
|---|
| 805 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 806 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 807 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 808 | # 103 -> fixed height above ground |
|---|
| 809 | pdtmpl[9] = 103 |
|---|
| 810 | # Oct 24: Scale factor of first fixed surface |
|---|
| 811 | pdtmpl[10] = 0 |
|---|
| 812 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 813 | # -> 10m above ground |
|---|
| 814 | pdtmpl[11] = 10 |
|---|
| 815 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 816 | pdtmpl[12] = missing(1) |
|---|
| 817 | # Oct 30: Scale factor of second fixed surface |
|---|
| 818 | pdtmpl[13] = missing(1) |
|---|
| 819 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 820 | pdtmpl[14] = missing(3) |
|---|
| 821 | |
|---|
| 822 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 823 | # replicate it in the following fields if you need to change this on a |
|---|
| 824 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 825 | # so then make sure you define one for each variable that follows or be |
|---|
| 826 | # aware that the last one defined will apply to all that follows. |
|---|
| 827 | |
|---|
| 828 | cheat = sfc_fv['q10m_zonal_wnd'].get_value()[time_idx,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 829 | field = n.zeros(cheat.shape) |
|---|
| 830 | for lat_idx in range(cheat.shape[0]): |
|---|
| 831 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 832 | |
|---|
| 833 | dummy['sfc_zonal_wnd'] = { |
|---|
| 834 | 'long_name' : '10m zonal wind', |
|---|
| 835 | 'pdtnum' : pdtnum, |
|---|
| 836 | 'pdtmpl' : pdtmpl, |
|---|
| 837 | 'drtnum' : drtnum, |
|---|
| 838 | 'drtmpl' : drtmpl, |
|---|
| 839 | #'field' : sfc_fv['q10m_zonal_wnd'].get_value()[time_idx] |
|---|
| 840 | #'field' : sfc_fv['q10m_zonal_wnd'].get_value()[time_idx,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 841 | 'field' : field |
|---|
| 842 | } |
|---|
| 843 | |
|---|
| 844 | # Let's prepare the meridional 10m wind data and metadata |
|---|
| 845 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 846 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 847 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 848 | pdtnum = 0 |
|---|
| 849 | # array of zeros (int) of size 15 |
|---|
| 850 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 851 | # Follows the definition of template 4.0 |
|---|
| 852 | # Oct 10: Parameter category (see Code table 4.1). 2 -> momentum |
|---|
| 853 | pdtmpl[0] = 2 |
|---|
| 854 | # Oct 11: Parameter number (see Code table 4.2). 3 -> v-component of wind |
|---|
| 855 | pdtmpl[1] = 3 |
|---|
| 856 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 857 | pdtmpl[2] = 2 |
|---|
| 858 | # Oct 13: Background generating process identifier |
|---|
| 859 | # (defined by originating centre) |
|---|
| 860 | pdtmpl[3] = missing(1) |
|---|
| 861 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 862 | # (defined by originating centre) |
|---|
| 863 | pdtmpl[4] = missing(1) |
|---|
| 864 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 865 | pdtmpl[5] = missing(2) |
|---|
| 866 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 867 | pdtmpl[6] = missing(1) |
|---|
| 868 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 869 | # 1 -> hours |
|---|
| 870 | # NB WPS expects this to be hours! |
|---|
| 871 | pdtmpl[7] = 1 |
|---|
| 872 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 873 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 874 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 875 | # 103 -> fixed height above ground |
|---|
| 876 | pdtmpl[9] = 103 |
|---|
| 877 | # Oct 24: Scale factor of first fixed surface |
|---|
| 878 | pdtmpl[10] = 0 |
|---|
| 879 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 880 | # -> 10m above ground |
|---|
| 881 | pdtmpl[11] = 10 |
|---|
| 882 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 883 | pdtmpl[12] = missing(1) |
|---|
| 884 | # Oct 30: Scale factor of second fixed surface |
|---|
| 885 | pdtmpl[13] = missing(1) |
|---|
| 886 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 887 | pdtmpl[14] = missing(3) |
|---|
| 888 | |
|---|
| 889 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 890 | # replicate it in the following fields if you need to change this on a |
|---|
| 891 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 892 | # so then make sure you define one for each variable that follows or be |
|---|
| 893 | # aware that the last one defined will apply to all that follows. |
|---|
| 894 | |
|---|
| 895 | cheat = sfc_fv['q10m_merid_wnd'].get_value()[time_idx,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 896 | field = n.zeros(cheat.shape) |
|---|
| 897 | for lat_idx in range(cheat.shape[0]): |
|---|
| 898 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 899 | |
|---|
| 900 | dummy['sfc_merid_wnd'] = { |
|---|
| 901 | 'long_name' : '10m meridional wind', |
|---|
| 902 | 'pdtnum' : pdtnum, |
|---|
| 903 | 'pdtmpl' : pdtmpl, |
|---|
| 904 | 'drtnum' : drtnum, |
|---|
| 905 | 'drtmpl' : drtmpl, |
|---|
| 906 | #'field' : sfc_fv['q10m_merid_wnd'].get_value()[time_idx] |
|---|
| 907 | #'field' : sfc_fv['q10m_merid_wnd'].get_value()[time_idx,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 908 | 'field' : field |
|---|
| 909 | } |
|---|
| 910 | |
|---|
| 911 | if 1: |
|---|
| 912 | # Let's prepare the topography data and metadata |
|---|
| 913 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 914 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 915 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 916 | pdtnum = 0 |
|---|
| 917 | # array of zeros (int) of size 15 |
|---|
| 918 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 919 | # Follows the definition of template 4.0 |
|---|
| 920 | # Oct 10: Parameter category (see Code table 4.1). 3 -> mass |
|---|
| 921 | pdtmpl[0] = 3 |
|---|
| 922 | # Oct 11: Parameter number (see Code table 4.2). 5 -> geopotential height |
|---|
| 923 | pdtmpl[1] = 5 |
|---|
| 924 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 925 | pdtmpl[2] = 2 |
|---|
| 926 | # Oct 13: Background generating process identifier |
|---|
| 927 | # (defined by originating centre) |
|---|
| 928 | pdtmpl[3] = missing(1) |
|---|
| 929 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 930 | # (defined by originating centre) |
|---|
| 931 | pdtmpl[4] = missing(1) |
|---|
| 932 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 933 | pdtmpl[5] = missing(2) |
|---|
| 934 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 935 | pdtmpl[6] = missing(1) |
|---|
| 936 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 937 | # 1 -> hours |
|---|
| 938 | # NB WPS expects this to be hours! |
|---|
| 939 | pdtmpl[7] = 1 |
|---|
| 940 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 941 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 942 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 943 | # 1 -> surface |
|---|
| 944 | pdtmpl[9] = 1 |
|---|
| 945 | # Oct 24: Scale factor of first fixed surface |
|---|
| 946 | pdtmpl[10] = 0 |
|---|
| 947 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 948 | pdtmpl[11] = 0 |
|---|
| 949 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 950 | pdtmpl[12] = missing(1) |
|---|
| 951 | # Oct 30: Scale factor of second fixed surface |
|---|
| 952 | pdtmpl[13] = missing(1) |
|---|
| 953 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 954 | pdtmpl[14] = missing(3) |
|---|
| 955 | |
|---|
| 956 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 957 | # replicate it in the following fields if you need to change this on a |
|---|
| 958 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 959 | # so then make sure you define one for each variable that follows or be |
|---|
| 960 | # aware that the last one defined will apply to all that follows. |
|---|
| 961 | |
|---|
| 962 | cheat = fv['topog'].get_value()[lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 963 | field = n.zeros(cheat.shape) |
|---|
| 964 | for lat_idx in range(cheat.shape[0]): |
|---|
| 965 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 966 | |
|---|
| 967 | dummy['topog'] = { |
|---|
| 968 | 'long_name' : 'topography', |
|---|
| 969 | 'pdtnum' : pdtnum, |
|---|
| 970 | 'pdtmpl' : pdtmpl, |
|---|
| 971 | 'drtnum' : drtnum, |
|---|
| 972 | 'drtmpl' : drtmpl, |
|---|
| 973 | #'field' : fv['topog'].get_value() |
|---|
| 974 | #'field' : fv['topog'].get_value()[lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 975 | 'field' : field |
|---|
| 976 | } |
|---|
| 977 | |
|---|
| 978 | if 1: |
|---|
| 979 | # Let's prepare the water equivalent accumulated snow depth |
|---|
| 980 | # data and metadata |
|---|
| 981 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 982 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 983 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 984 | pdtnum = 0 |
|---|
| 985 | # array of zeros (int) of size 15 |
|---|
| 986 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 987 | # Follows the definition of template 4.0 |
|---|
| 988 | # Oct 10: Parameter category (see Code table 4.1). 1 -> moisture |
|---|
| 989 | pdtmpl[0] = 1 |
|---|
| 990 | # Oct 11: Parameter number (see Code table 4.2). 13 -> |
|---|
| 991 | # water equivalent of accumulated snow depth |
|---|
| 992 | pdtmpl[1] = 13 |
|---|
| 993 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 994 | pdtmpl[2] = 2 |
|---|
| 995 | # Oct 13: Background generating process identifier |
|---|
| 996 | # (defined by originating centre) |
|---|
| 997 | pdtmpl[3] = missing(1) |
|---|
| 998 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 999 | # (defined by originating centre) |
|---|
| 1000 | pdtmpl[4] = missing(1) |
|---|
| 1001 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1002 | pdtmpl[5] = missing(2) |
|---|
| 1003 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1004 | pdtmpl[6] = missing(1) |
|---|
| 1005 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1006 | # 1 -> hours |
|---|
| 1007 | # NB WPS expects this to be hours! |
|---|
| 1008 | pdtmpl[7] = 1 |
|---|
| 1009 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1010 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1011 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1012 | # 1 -> surface |
|---|
| 1013 | pdtmpl[9] = 1 |
|---|
| 1014 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1015 | pdtmpl[10] = 0 |
|---|
| 1016 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1017 | pdtmpl[11] = 0 |
|---|
| 1018 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1019 | pdtmpl[12] = missing(1) |
|---|
| 1020 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1021 | pdtmpl[13] = missing(1) |
|---|
| 1022 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1023 | pdtmpl[14] = missing(3) |
|---|
| 1024 | |
|---|
| 1025 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1026 | # replicate it in the following fields if you need to change this on a |
|---|
| 1027 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1028 | # so then make sure you define one for each variable that follows or be |
|---|
| 1029 | # aware that the last one defined will apply to all that follows. |
|---|
| 1030 | |
|---|
| 1031 | #dummy_field = n.zeros((len(lon),len(lat)),dtype=float) |
|---|
| 1032 | dummy_field = n.zeros((len(lat),len(lon)),dtype=float) |
|---|
| 1033 | dummy['weasd'] = { |
|---|
| 1034 | 'long_name' : 'water equivalent of accumulated snow depth', |
|---|
| 1035 | 'pdtnum' : pdtnum, |
|---|
| 1036 | 'pdtmpl' : pdtmpl, |
|---|
| 1037 | 'drtnum' : drtnum, |
|---|
| 1038 | 'drtmpl' : drtmpl, |
|---|
| 1039 | 'field' : dummy_field |
|---|
| 1040 | } |
|---|
| 1041 | |
|---|
| 1042 | ####################################################################### |
|---|
| 1043 | # Finished with the 2d fields |
|---|
| 1044 | # Let's move on to the 3d ones |
|---|
| 1045 | ####################################################################### |
|---|
| 1046 | |
|---|
| 1047 | dummy = data[-1]['discipline']['atmos']['fields']['3d'] |
|---|
| 1048 | |
|---|
| 1049 | # Let's prepare the air temperature data and metadata |
|---|
| 1050 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1051 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1052 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1053 | pdtnum = 0 |
|---|
| 1054 | # array of zeros (int) of size 15 |
|---|
| 1055 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1056 | # Follows the definition of template 4.0 |
|---|
| 1057 | # Oct 10: Parameter category (see Code table 4.1). 0 -> temperature |
|---|
| 1058 | pdtmpl[0] = 0 |
|---|
| 1059 | # Oct 11: Parameter number (see Code table 4.2). 0 -> temperature |
|---|
| 1060 | pdtmpl[1] = 0 |
|---|
| 1061 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1062 | pdtmpl[2] = 2 |
|---|
| 1063 | # Oct 13: Background generating process identifier |
|---|
| 1064 | # (defined by originating centre) |
|---|
| 1065 | pdtmpl[3] = missing(1) |
|---|
| 1066 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1067 | # (defined by originating centre) |
|---|
| 1068 | pdtmpl[4] = missing(1) |
|---|
| 1069 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1070 | pdtmpl[5] = missing(2) |
|---|
| 1071 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1072 | pdtmpl[6] = missing(1) |
|---|
| 1073 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1074 | # 1 -> hours |
|---|
| 1075 | # NB WPS expects this to be hours! |
|---|
| 1076 | pdtmpl[7] = 1 |
|---|
| 1077 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1078 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1079 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1080 | # 1 -> isobaric level |
|---|
| 1081 | pdtmpl[9] = 100 |
|---|
| 1082 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1083 | pdtmpl[10] = 0 |
|---|
| 1084 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1085 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1086 | # horizontal slabs for its encoding |
|---|
| 1087 | pdtmpl[11] = missing(3) |
|---|
| 1088 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1089 | pdtmpl[12] = missing(1) |
|---|
| 1090 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1091 | pdtmpl[13] = missing(1) |
|---|
| 1092 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1093 | pdtmpl[14] = missing(3) |
|---|
| 1094 | |
|---|
| 1095 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1096 | # replicate it in the following fields if you need to change this on a |
|---|
| 1097 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1098 | # so then make sure you define one for each variable that follows or be |
|---|
| 1099 | # aware that the last one defined will apply to all that follows. |
|---|
| 1100 | |
|---|
| 1101 | cheat = fv['air_temp'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1102 | field = n.zeros(cheat.shape) |
|---|
| 1103 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1104 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1105 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1106 | |
|---|
| 1107 | dummy['air_temp'] = { |
|---|
| 1108 | 'long_name' : '3D air temperature', |
|---|
| 1109 | 'pdtnum' : pdtnum, |
|---|
| 1110 | 'pdtmpl' : pdtmpl, |
|---|
| 1111 | 'drtnum' : drtnum, |
|---|
| 1112 | 'drtmpl' : drtmpl, |
|---|
| 1113 | #'field' : fv['air_temp'].get_value()[0], |
|---|
| 1114 | #'field' : fv['air_temp'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx], |
|---|
| 1115 | 'field' : field, |
|---|
| 1116 | #'field' : '', |
|---|
| 1117 | 'lvl' : fv['lvl'].get_value() |
|---|
| 1118 | } |
|---|
| 1119 | |
|---|
| 1120 | # Let's prepare the 3d relative humidity data and metadata |
|---|
| 1121 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1122 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1123 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1124 | pdtnum = 0 |
|---|
| 1125 | # array of zeros (int) of size 15 |
|---|
| 1126 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1127 | # Follows the definition of template 4.0 |
|---|
| 1128 | # Oct 10: Parameter category (see Code table 4.1). 1 -> moisture |
|---|
| 1129 | pdtmpl[0] = 1 |
|---|
| 1130 | # Oct 11: Parameter number (see Code table 4.2). 1 -> RH |
|---|
| 1131 | pdtmpl[1] = 1 |
|---|
| 1132 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1133 | pdtmpl[2] = 2 |
|---|
| 1134 | # Oct 13: Background generating process identifier |
|---|
| 1135 | # (defined by originating centre) |
|---|
| 1136 | pdtmpl[3] = missing(1) |
|---|
| 1137 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1138 | # (defined by originating centre) |
|---|
| 1139 | pdtmpl[4] = missing(1) |
|---|
| 1140 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1141 | pdtmpl[5] = missing(2) |
|---|
| 1142 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1143 | pdtmpl[6] = missing(1) |
|---|
| 1144 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1145 | # 1 -> hours |
|---|
| 1146 | # NB WPS expects this to be hours! |
|---|
| 1147 | pdtmpl[7] = 1 |
|---|
| 1148 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1149 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1150 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1151 | # 1 -> isobaric level |
|---|
| 1152 | pdtmpl[9] = 100 |
|---|
| 1153 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1154 | pdtmpl[10] = 0 |
|---|
| 1155 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1156 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1157 | # horizontal slabs for its encoding |
|---|
| 1158 | pdtmpl[11] = missing(3) |
|---|
| 1159 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1160 | pdtmpl[12] = missing(1) |
|---|
| 1161 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1162 | pdtmpl[13] = missing(1) |
|---|
| 1163 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1164 | pdtmpl[14] = missing(3) |
|---|
| 1165 | |
|---|
| 1166 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1167 | # replicate it in the following fields if you need to change this on a |
|---|
| 1168 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1169 | # so then make sure you define one for each variable that follows or be |
|---|
| 1170 | # aware that the last one defined will apply to all that follows. |
|---|
| 1171 | |
|---|
| 1172 | #mix_rto = fv['mix_rto'].get_value()[0] |
|---|
| 1173 | mix_rto = fv['mix_rto'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1174 | spec_hum = n.zeros(mix_rto.shape,dtype=float) |
|---|
| 1175 | spec_hum = mix_rto / (mix_rto + 1) |
|---|
| 1176 | #temp = fv['air_temp'].get_value()[0] |
|---|
| 1177 | temp = fv['air_temp'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1178 | #print temp.min(), temp.max() |
|---|
| 1179 | #print temp.min()-273.16, temp.max()-273.16 |
|---|
| 1180 | sat_vapour_pres = goff_gratch(temp) |
|---|
| 1181 | #print sat_vapour_pres.min(), sat_vapour_pres.max() |
|---|
| 1182 | pres = fv['lvl'].get_value() |
|---|
| 1183 | sat_spec_hum = n.zeros(mix_rto.shape,dtype=float) |
|---|
| 1184 | for lvl_idx in range(len(pres)): |
|---|
| 1185 | sat_spec_hum[lvl_idx] = 0.622 * sat_vapour_pres[lvl_idx] \ |
|---|
| 1186 | / pres[lvl_idx] |
|---|
| 1187 | #sat_spec_hum = ma.masked_where(sat_spec_hum <= 1.e-9, |
|---|
| 1188 | #sat_spec_hum = ma.masked_where(sat_spec_hum <= 1.e-6, |
|---|
| 1189 | #sat_spec_hum) |
|---|
| 1190 | rh = n.zeros(mix_rto.shape,dtype=float) |
|---|
| 1191 | rh = spec_hum / sat_spec_hum * 100 |
|---|
| 1192 | #sys.exit() |
|---|
| 1193 | del mix_rto, spec_hum, temp, sat_vapour_pres, pres, sat_spec_hum |
|---|
| 1194 | |
|---|
| 1195 | #cheat = rh |
|---|
| 1196 | #field = n.zeros(cheat.shape) |
|---|
| 1197 | #for lat_idx in range(cheat.shape[0]): |
|---|
| 1198 | # field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 1199 | |
|---|
| 1200 | cheat = rh |
|---|
| 1201 | field = n.zeros(cheat.shape) |
|---|
| 1202 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1203 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1204 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1205 | |
|---|
| 1206 | dummy['rh'] = { |
|---|
| 1207 | 'long_name' : '3D relative humidity', |
|---|
| 1208 | 'pdtnum' : pdtnum, |
|---|
| 1209 | 'pdtmpl' : pdtmpl, |
|---|
| 1210 | 'drtnum' : drtnum, |
|---|
| 1211 | 'drtmpl' : drtmpl, |
|---|
| 1212 | #'field' : rh.filled(fill_value=0.), |
|---|
| 1213 | #'field' : rh, |
|---|
| 1214 | 'field' : field, |
|---|
| 1215 | 'lvl' : fv['lvl'].get_value() |
|---|
| 1216 | } |
|---|
| 1217 | #sys.exit() |
|---|
| 1218 | |
|---|
| 1219 | # Let's prepare the 3d zonal wind data and metadata |
|---|
| 1220 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1221 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1222 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1223 | pdtnum = 0 |
|---|
| 1224 | # array of zeros (int) of size 15 |
|---|
| 1225 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1226 | # Follows the definition of template 4.0 |
|---|
| 1227 | # Oct 10: Parameter category (see Code table 4.1). 2 -> momentum |
|---|
| 1228 | pdtmpl[0] = 2 |
|---|
| 1229 | # Oct 11: Parameter number (see Code table 4.2). 2 -> u-component of the |
|---|
| 1230 | # wind |
|---|
| 1231 | pdtmpl[1] = 2 |
|---|
| 1232 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1233 | pdtmpl[2] = 2 |
|---|
| 1234 | # Oct 13: Background generating process identifier |
|---|
| 1235 | # (defined by originating centre) |
|---|
| 1236 | pdtmpl[3] = missing(1) |
|---|
| 1237 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1238 | # (defined by originating centre) |
|---|
| 1239 | pdtmpl[4] = missing(1) |
|---|
| 1240 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1241 | pdtmpl[5] = missing(2) |
|---|
| 1242 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1243 | pdtmpl[6] = missing(1) |
|---|
| 1244 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1245 | # 1 -> hours |
|---|
| 1246 | # NB WPS expects this to be hours! |
|---|
| 1247 | pdtmpl[7] = 1 |
|---|
| 1248 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1249 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1250 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1251 | # 1 -> isobaric level |
|---|
| 1252 | pdtmpl[9] = 100 |
|---|
| 1253 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1254 | pdtmpl[10] = 0 |
|---|
| 1255 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1256 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1257 | # horizontal slabs for its encoding |
|---|
| 1258 | pdtmpl[11] = missing(3) |
|---|
| 1259 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1260 | pdtmpl[12] = missing(1) |
|---|
| 1261 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1262 | pdtmpl[13] = missing(1) |
|---|
| 1263 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1264 | pdtmpl[14] = missing(3) |
|---|
| 1265 | |
|---|
| 1266 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1267 | # replicate it in the following fields if you need to change this on a |
|---|
| 1268 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1269 | # so then make sure you define one for each variable that follows or be |
|---|
| 1270 | # aware that the last one defined will apply to all that follows. |
|---|
| 1271 | |
|---|
| 1272 | cheat = fv['zonal_wnd'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1273 | field = n.zeros(cheat.shape) |
|---|
| 1274 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1275 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1276 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1277 | |
|---|
| 1278 | dummy['zonal_wnd'] = { |
|---|
| 1279 | 'long_name' : '3D zonal wind', |
|---|
| 1280 | 'pdtnum' : pdtnum, |
|---|
| 1281 | 'pdtmpl' : pdtmpl, |
|---|
| 1282 | 'drtnum' : drtnum, |
|---|
| 1283 | 'drtmpl' : drtmpl, |
|---|
| 1284 | #'field' : fv['zonal_wnd'].get_value()[0], |
|---|
| 1285 | #'field' : fv['zonal_wnd'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx], |
|---|
| 1286 | 'field' : field, |
|---|
| 1287 | #'field' : '', |
|---|
| 1288 | 'lvl' : fv['lvl'].get_value() |
|---|
| 1289 | } |
|---|
| 1290 | |
|---|
| 1291 | # Let's prepare the 3d zonal wind data and metadata |
|---|
| 1292 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1293 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1294 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1295 | pdtnum = 0 |
|---|
| 1296 | # array of zeros (int) of size 15 |
|---|
| 1297 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1298 | # Follows the definition of template 4.0 |
|---|
| 1299 | # Oct 10: Parameter category (see Code table 4.1). 2 -> momentum |
|---|
| 1300 | pdtmpl[0] = 2 |
|---|
| 1301 | # Oct 11: Parameter number (see Code table 4.2). 2 -> v-component of the |
|---|
| 1302 | # wind |
|---|
| 1303 | pdtmpl[1] = 3 |
|---|
| 1304 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1305 | pdtmpl[2] = 2 |
|---|
| 1306 | # Oct 13: Background generating process identifier |
|---|
| 1307 | # (defined by originating centre) |
|---|
| 1308 | pdtmpl[3] = missing(1) |
|---|
| 1309 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1310 | # (defined by originating centre) |
|---|
| 1311 | pdtmpl[4] = missing(1) |
|---|
| 1312 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1313 | pdtmpl[5] = missing(2) |
|---|
| 1314 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1315 | pdtmpl[6] = missing(1) |
|---|
| 1316 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1317 | # 1 -> hours |
|---|
| 1318 | # NB WPS expects this to be hours! |
|---|
| 1319 | pdtmpl[7] = 1 |
|---|
| 1320 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1321 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1322 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1323 | # 1 -> isobaric level |
|---|
| 1324 | pdtmpl[9] = 100 |
|---|
| 1325 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1326 | pdtmpl[10] = 0 |
|---|
| 1327 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1328 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1329 | # horizontal slabs for its encoding |
|---|
| 1330 | pdtmpl[11] = missing(3) |
|---|
| 1331 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1332 | pdtmpl[12] = missing(1) |
|---|
| 1333 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1334 | pdtmpl[13] = missing(1) |
|---|
| 1335 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1336 | pdtmpl[14] = missing(3) |
|---|
| 1337 | |
|---|
| 1338 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1339 | # replicate it in the following fields if you need to change this on a |
|---|
| 1340 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1341 | # so then make sure you define one for each variable that follows or be |
|---|
| 1342 | # aware that the last one defined will apply to all that follows. |
|---|
| 1343 | |
|---|
| 1344 | cheat =fv['merid_wnd'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1345 | field = n.zeros(cheat.shape) |
|---|
| 1346 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1347 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1348 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1349 | |
|---|
| 1350 | dummy['merid_wnd'] = { |
|---|
| 1351 | 'long_name' : '3D meridional wind', |
|---|
| 1352 | 'pdtnum' : pdtnum, |
|---|
| 1353 | 'pdtmpl' : pdtmpl, |
|---|
| 1354 | 'drtnum' : drtnum, |
|---|
| 1355 | 'drtmpl' : drtmpl, |
|---|
| 1356 | #'field' : fv['merid_wnd'].get_value()[0], |
|---|
| 1357 | #'field' : fv['merid_wnd'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx], |
|---|
| 1358 | 'field' : field, |
|---|
| 1359 | #'field' : '', |
|---|
| 1360 | 'lvl' : fv['lvl'].get_value() |
|---|
| 1361 | } |
|---|
| 1362 | |
|---|
| 1363 | # Let's prepare the 3d geopotential height data and metadata |
|---|
| 1364 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1365 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1366 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1367 | pdtnum = 0 |
|---|
| 1368 | # array of zeros (int) of size 15 |
|---|
| 1369 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1370 | # Follows the definition of template 4.0 |
|---|
| 1371 | # Oct 10: Parameter category (see Code table 4.1). 3 -> mass |
|---|
| 1372 | pdtmpl[0] = 3 |
|---|
| 1373 | # Oct 11: Parameter number (see Code table 4.2). 5 -> geopotential height |
|---|
| 1374 | pdtmpl[1] = 5 |
|---|
| 1375 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1376 | pdtmpl[2] = 2 |
|---|
| 1377 | # Oct 13: Background generating process identifier |
|---|
| 1378 | # (defined by originating centre) |
|---|
| 1379 | pdtmpl[3] = missing(1) |
|---|
| 1380 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1381 | # (defined by originating centre) |
|---|
| 1382 | pdtmpl[4] = missing(1) |
|---|
| 1383 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1384 | pdtmpl[5] = missing(2) |
|---|
| 1385 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1386 | pdtmpl[6] = missing(1) |
|---|
| 1387 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1388 | # 1 -> hours |
|---|
| 1389 | # NB WPS expects this to be hours! |
|---|
| 1390 | pdtmpl[7] = 1 |
|---|
| 1391 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1392 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1393 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1394 | # 1 -> isobaric level |
|---|
| 1395 | pdtmpl[9] = 100 |
|---|
| 1396 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1397 | pdtmpl[10] = 0 |
|---|
| 1398 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1399 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1400 | # horizontal slabs for its encoding |
|---|
| 1401 | pdtmpl[11] = missing(3) |
|---|
| 1402 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1403 | pdtmpl[12] = missing(1) |
|---|
| 1404 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1405 | pdtmpl[13] = missing(1) |
|---|
| 1406 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1407 | pdtmpl[14] = missing(3) |
|---|
| 1408 | |
|---|
| 1409 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1410 | # replicate it in the following fields if you need to change this on a |
|---|
| 1411 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1412 | # so then make sure you define one for each variable that follows or be |
|---|
| 1413 | # aware that the last one defined will apply to all that follows. |
|---|
| 1414 | |
|---|
| 1415 | cheat = fv['geop_ht'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1416 | field = n.zeros(cheat.shape) |
|---|
| 1417 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1418 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1419 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1420 | |
|---|
| 1421 | dummy['geop_ht'] = { |
|---|
| 1422 | 'long_name' : 'geopotential height', |
|---|
| 1423 | 'pdtnum' : pdtnum, |
|---|
| 1424 | 'pdtmpl' : pdtmpl, |
|---|
| 1425 | 'drtnum' : drtnum, |
|---|
| 1426 | 'drtmpl' : drtmpl, |
|---|
| 1427 | #'field' : fv['geop_ht'].get_value()[0], |
|---|
| 1428 | #'field' : fv['geop_ht'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx], |
|---|
| 1429 | 'field' : field, |
|---|
| 1430 | #'field' : '', |
|---|
| 1431 | 'lvl' : fv['lvl'].get_value() |
|---|
| 1432 | } |
|---|
| 1433 | |
|---|
| 1434 | ####################################################################### |
|---|
| 1435 | # Finished with the atmospheric discipline |
|---|
| 1436 | # Let's move on to the oceanographic one |
|---|
| 1437 | ####################################################################### |
|---|
| 1438 | |
|---|
| 1439 | if 0: |
|---|
| 1440 | # Preliminaries: we need to unpack the land_sea_ice mask from the laps |
|---|
| 1441 | # files. |
|---|
| 1442 | #sea_lnd_ice_mask = fv['sea_lnd_ice_mask'].get_value()[0] |
|---|
| 1443 | sea_lnd_ice_mask = fv['sea_lnd_ice_mask'].get_value()[0,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1444 | shape = sea_lnd_ice_mask.shape |
|---|
| 1445 | land_cover = n.zeros(shape, 'i') |
|---|
| 1446 | ice_cover = n.zeros(shape, 'i') |
|---|
| 1447 | # I assume (know) that the mask has 3 dimensions of which the first is time |
|---|
| 1448 | # which I am going to ignore for now |
|---|
| 1449 | # I am sure this could be done more elegantly with a numpy in-built |
|---|
| 1450 | # function, but I am not sure about which one would it be |
|---|
| 1451 | for i in range(shape[0]): |
|---|
| 1452 | for j in range(shape[1]): |
|---|
| 1453 | if sea_lnd_ice_mask[i,j] == 0: |
|---|
| 1454 | land_cover[i,j] = 0 |
|---|
| 1455 | ice_cover[i,j] = 0 |
|---|
| 1456 | elif sea_lnd_ice_mask[i,j] == 1: |
|---|
| 1457 | land_cover[i,j] = 1 |
|---|
| 1458 | ice_cover[i,j] = 0 |
|---|
| 1459 | elif sea_lnd_ice_mask[i,j] == 2: |
|---|
| 1460 | # the BoM only considers ice over water |
|---|
| 1461 | land_cover[i,j] = 0 |
|---|
| 1462 | ice_cover[i,j] = 1 |
|---|
| 1463 | else: |
|---|
| 1464 | print 'Illegal value in the sea_land_ice mask!' |
|---|
| 1465 | sys.exit() |
|---|
| 1466 | |
|---|
| 1467 | dummy = data[-1]['discipline']['ocean']['fields']['2d'] |
|---|
| 1468 | |
|---|
| 1469 | # Let's prepare the ice cover data and metadata |
|---|
| 1470 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1471 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1472 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1473 | pdtnum = 0 |
|---|
| 1474 | # array of zeros (int) of size 15 |
|---|
| 1475 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1476 | # Follows the definition of template 4.0 |
|---|
| 1477 | # Oct 10: Parameter category (see Code table 4.1). 2 -> ice |
|---|
| 1478 | pdtmpl[0] = 2 |
|---|
| 1479 | # Oct 11: Parameter number (see Code table 4.2). 0 -> ice-cover |
|---|
| 1480 | # 1=ice, 0=no-ice (over water) |
|---|
| 1481 | pdtmpl[1] = 0 |
|---|
| 1482 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1483 | pdtmpl[2] = 2 |
|---|
| 1484 | # Oct 13: Background generating process identifier |
|---|
| 1485 | # (defined by originating centre) |
|---|
| 1486 | pdtmpl[3] = missing(1) |
|---|
| 1487 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1488 | # (defined by originating centre) |
|---|
| 1489 | pdtmpl[4] = missing(1) |
|---|
| 1490 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1491 | pdtmpl[5] = missing(2) |
|---|
| 1492 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1493 | pdtmpl[6] = missing(1) |
|---|
| 1494 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1495 | # 1 -> hours |
|---|
| 1496 | # NB WPS expects this to be hours! |
|---|
| 1497 | pdtmpl[7] = 1 |
|---|
| 1498 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1499 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1500 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1501 | # 1 -> surface |
|---|
| 1502 | pdtmpl[9] = 1 |
|---|
| 1503 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1504 | pdtmpl[10] = 0 |
|---|
| 1505 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1506 | pdtmpl[11] = 0 |
|---|
| 1507 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1508 | pdtmpl[12] = missing(1) |
|---|
| 1509 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1510 | pdtmpl[13] = missing(1) |
|---|
| 1511 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1512 | pdtmpl[14] = missing(3) |
|---|
| 1513 | |
|---|
| 1514 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1515 | # replicate it in the following fields if you need to change this on a |
|---|
| 1516 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1517 | # so then make sure you define one for each variable that follows or be |
|---|
| 1518 | # aware that the last one defined will apply to all that follows. |
|---|
| 1519 | |
|---|
| 1520 | cheat = ice_cover |
|---|
| 1521 | field = n.zeros(cheat.shape) |
|---|
| 1522 | for lat_idx in range(cheat.shape[0]): |
|---|
| 1523 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 1524 | |
|---|
| 1525 | dummy['ice_cover'] = { |
|---|
| 1526 | 'long_name' : 'ice cover', |
|---|
| 1527 | 'pdtnum' : pdtnum, |
|---|
| 1528 | 'pdtmpl' : pdtmpl, |
|---|
| 1529 | 'drtnum' : drtnum, |
|---|
| 1530 | 'drtmpl' : drtmpl, |
|---|
| 1531 | #'field' : ice_cover |
|---|
| 1532 | 'field' : field |
|---|
| 1533 | } |
|---|
| 1534 | |
|---|
| 1535 | ####################################################################### |
|---|
| 1536 | # Finished with the oceanographic discipline |
|---|
| 1537 | # Let's move on to the land one |
|---|
| 1538 | ####################################################################### |
|---|
| 1539 | |
|---|
| 1540 | dummy = data[-1]['discipline']['land']['fields']['2d'] |
|---|
| 1541 | |
|---|
| 1542 | if 0: |
|---|
| 1543 | # Let's prepare the land cover data and metadata |
|---|
| 1544 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1545 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1546 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1547 | pdtnum = 0 |
|---|
| 1548 | # array of zeros (int) of size 15 |
|---|
| 1549 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1550 | # Follows the definition of template 4.0 |
|---|
| 1551 | # Oct 10: Parameter category (see Code table 4.1). 0 -> vegetation/biomass |
|---|
| 1552 | pdtmpl[0] = 0 |
|---|
| 1553 | # Oct 11: Parameter number (see Code table 4.2). 0 -> land-cover |
|---|
| 1554 | # (1=land, 0=ocean) |
|---|
| 1555 | pdtmpl[1] = 0 |
|---|
| 1556 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1557 | pdtmpl[2] = 2 |
|---|
| 1558 | # Oct 13: Background generating process identifier |
|---|
| 1559 | # (defined by originating centre) |
|---|
| 1560 | pdtmpl[3] = missing(1) |
|---|
| 1561 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1562 | # (defined by originating centre) |
|---|
| 1563 | pdtmpl[4] = missing(1) |
|---|
| 1564 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1565 | pdtmpl[5] = missing(2) |
|---|
| 1566 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1567 | pdtmpl[6] = missing(1) |
|---|
| 1568 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1569 | # 1 -> hours |
|---|
| 1570 | # NB WPS expects this to be hours! |
|---|
| 1571 | pdtmpl[7] = 1 |
|---|
| 1572 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1573 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1574 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1575 | # 1 -> surface |
|---|
| 1576 | pdtmpl[9] = 1 |
|---|
| 1577 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1578 | pdtmpl[10] = 0 |
|---|
| 1579 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1580 | pdtmpl[11] = 0 |
|---|
| 1581 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1582 | pdtmpl[12] = missing(1) |
|---|
| 1583 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1584 | pdtmpl[13] = missing(1) |
|---|
| 1585 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1586 | pdtmpl[14] = missing(3) |
|---|
| 1587 | |
|---|
| 1588 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1589 | # replicate it in the following fields if you need to change this on a |
|---|
| 1590 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1591 | # so then make sure you define one for each variable that follows or be |
|---|
| 1592 | # aware that the last one defined will apply to all that follows. |
|---|
| 1593 | |
|---|
| 1594 | # I seem to remember there was a problem with the land cover that I could |
|---|
| 1595 | # fix using the decimal scale factor... let's try |
|---|
| 1596 | land_cover_decimal_factor = 1 |
|---|
| 1597 | # Oct: 18-19. Decimal scale factor (D) |
|---|
| 1598 | #drtmpl[2] = land_cover_decimal_factor |
|---|
| 1599 | #print 'land_cover drtmpl', drtmpl |
|---|
| 1600 | |
|---|
| 1601 | cheat = land_cover * 10**land_cover_decimal_factor |
|---|
| 1602 | field = n.zeros(cheat.shape) |
|---|
| 1603 | for lat_idx in range(cheat.shape[0]): |
|---|
| 1604 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 1605 | |
|---|
| 1606 | dummy['land_cover'] = { |
|---|
| 1607 | 'long_name' : 'land cover', |
|---|
| 1608 | 'pdtnum' : pdtnum, |
|---|
| 1609 | 'pdtmpl' : pdtmpl, |
|---|
| 1610 | 'drtnum' : drtnum, |
|---|
| 1611 | 'drtmpl' : n.array([0,0,land_cover_decimal_factor,24,0]), |
|---|
| 1612 | #'drtmpl' : drtmpl, |
|---|
| 1613 | #'field' : land_cover * 10**land_cover_decimal_factor |
|---|
| 1614 | 'field' : field |
|---|
| 1615 | } |
|---|
| 1616 | |
|---|
| 1617 | # Now put it back to what it was |
|---|
| 1618 | # Oct: 18-19. Decimal scale factor (D) |
|---|
| 1619 | #drtmpl[2] = 0 |
|---|
| 1620 | |
|---|
| 1621 | if 1: |
|---|
| 1622 | # Let's prepare the topography data and metadata |
|---|
| 1623 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1624 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1625 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1626 | pdtnum = 0 |
|---|
| 1627 | # array of zeros (int) of size 15 |
|---|
| 1628 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1629 | # Follows the definition of template 4.0 |
|---|
| 1630 | # Oct 10: Parameter category (see Code table 4.1). 0 -> vegetation/biomass |
|---|
| 1631 | pdtmpl[0] = 0 |
|---|
| 1632 | # Oct 11: Parameter number (see Code table 4.2). 7 -> model terrain height |
|---|
| 1633 | pdtmpl[1] = 7 |
|---|
| 1634 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1635 | pdtmpl[2] = 2 |
|---|
| 1636 | # Oct 13: Background generating process identifier |
|---|
| 1637 | # (defined by originating centre) |
|---|
| 1638 | pdtmpl[3] = missing(1) |
|---|
| 1639 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1640 | # (defined by originating centre) |
|---|
| 1641 | pdtmpl[4] = missing(1) |
|---|
| 1642 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1643 | pdtmpl[5] = missing(2) |
|---|
| 1644 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1645 | pdtmpl[6] = missing(1) |
|---|
| 1646 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1647 | # 1 -> hours |
|---|
| 1648 | # NB WPS expects this to be hours! |
|---|
| 1649 | pdtmpl[7] = 1 |
|---|
| 1650 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1651 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1652 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1653 | # 1 -> surface |
|---|
| 1654 | pdtmpl[9] = 1 |
|---|
| 1655 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1656 | pdtmpl[10] = 0 |
|---|
| 1657 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1658 | pdtmpl[11] = 0 |
|---|
| 1659 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1660 | pdtmpl[12] = missing(1) |
|---|
| 1661 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1662 | pdtmpl[13] = missing(1) |
|---|
| 1663 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1664 | pdtmpl[14] = missing(3) |
|---|
| 1665 | |
|---|
| 1666 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1667 | # replicate it in the following fields if you need to change this on a |
|---|
| 1668 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1669 | # so then make sure you define one for each variable that follows or be |
|---|
| 1670 | # aware that the last one defined will apply to all that follows. |
|---|
| 1671 | cheat = fv['topog'].get_value()[lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1672 | field = n.zeros(cheat.shape) |
|---|
| 1673 | for lat_idx in range(cheat.shape[0]): |
|---|
| 1674 | field[-(lat_idx+1)] = cheat[lat_idx] |
|---|
| 1675 | |
|---|
| 1676 | dummy['topog'] = { |
|---|
| 1677 | 'long_name' : 'topography', |
|---|
| 1678 | 'pdtnum' : pdtnum, |
|---|
| 1679 | 'pdtmpl' : pdtmpl, |
|---|
| 1680 | 'drtnum' : drtnum, |
|---|
| 1681 | 'drtmpl' : drtmpl, |
|---|
| 1682 | #'field' : fv['topog'].get_value() |
|---|
| 1683 | #'field' : fv['topog'].get_value()[lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1684 | 'field' : field |
|---|
| 1685 | } |
|---|
| 1686 | |
|---|
| 1687 | dummy = data[-1]['discipline']['land']['fields']['3d'] |
|---|
| 1688 | |
|---|
| 1689 | if 1: |
|---|
| 1690 | # Let's prepare the 3d soil temperature data and metadata |
|---|
| 1691 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1692 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1693 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1694 | pdtnum = 0 |
|---|
| 1695 | # array of zeros (int) of size 15 |
|---|
| 1696 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1697 | # Follows the definition of template 4.0 |
|---|
| 1698 | # Oct 10: Parameter category (see Code table 4.1). 0 -> vegetation/biomass |
|---|
| 1699 | pdtmpl[0] = 0 |
|---|
| 1700 | # Oct 11: Parameter number (see Code table 4.2). 2 -> soil temperature |
|---|
| 1701 | pdtmpl[1] = 2 |
|---|
| 1702 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1703 | pdtmpl[2] = 2 |
|---|
| 1704 | # Oct 13: Background generating process identifier |
|---|
| 1705 | # (defined by originating centre) |
|---|
| 1706 | pdtmpl[3] = missing(1) |
|---|
| 1707 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1708 | # (defined by originating centre) |
|---|
| 1709 | pdtmpl[4] = missing(1) |
|---|
| 1710 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1711 | pdtmpl[5] = missing(2) |
|---|
| 1712 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1713 | pdtmpl[6] = missing(1) |
|---|
| 1714 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1715 | # 1 -> hours |
|---|
| 1716 | # NB WPS expects this to be hours! |
|---|
| 1717 | pdtmpl[7] = 1 |
|---|
| 1718 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1719 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1720 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1721 | # 106 -> depth below land surface |
|---|
| 1722 | pdtmpl[9] = 106 |
|---|
| 1723 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1724 | # 3 -> preserve mm accuracy |
|---|
| 1725 | # 2 -> preserve cm accuracy |
|---|
| 1726 | soil_lvl_scaling = 2 |
|---|
| 1727 | pdtmpl[10] = soil_lvl_scaling |
|---|
| 1728 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1729 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1730 | # horizontal slabs for its encoding |
|---|
| 1731 | pdtmpl[11] = missing(3) |
|---|
| 1732 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1733 | # 106 -> depth below land surface |
|---|
| 1734 | pdtmpl[12] = 106 |
|---|
| 1735 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1736 | # 3 -> preserve mm accuracy |
|---|
| 1737 | pdtmpl[13] = soil_lvl_scaling |
|---|
| 1738 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1739 | pdtmpl[14] = missing(3) |
|---|
| 1740 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1741 | # horizontal slabs for its encoding |
|---|
| 1742 | |
|---|
| 1743 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1744 | # replicate it in the following fields if you need to change this on a |
|---|
| 1745 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1746 | # so then make sure you define one for each variable that follows or be |
|---|
| 1747 | # aware that the last one defined will apply to all that follows. |
|---|
| 1748 | |
|---|
| 1749 | # Let's interpolate linearly to the Noah levels |
|---|
| 1750 | # NB for the deepest level we actually have an extrapolation |
|---|
| 1751 | laps_soil_lvl = fv['soil_lvl'].get_value() |
|---|
| 1752 | noah_soil_lvl = [0.10, 0.40, 1.0, 2.0] |
|---|
| 1753 | #laps_soil_temp = fv['soil_temp'].get_value()[0] |
|---|
| 1754 | laps_soil_temp = fv['soil_temp'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1755 | shape = laps_soil_temp.shape |
|---|
| 1756 | noah_soil_temp = n.zeros(shape, dtype=float) |
|---|
| 1757 | max_soil_lvl = 4 |
|---|
| 1758 | for soil_idx in range(max_soil_lvl): |
|---|
| 1759 | if soil_idx < max_soil_lvl - 1: |
|---|
| 1760 | x_a = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx] |
|---|
| 1761 | x_b = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx + 1] |
|---|
| 1762 | y_a = laps_soil_temp[soil_idx] |
|---|
| 1763 | y_b = laps_soil_temp[soil_idx + 1] |
|---|
| 1764 | else: |
|---|
| 1765 | # this accomplishes the extrapolation |
|---|
| 1766 | x_a = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx - 1] |
|---|
| 1767 | x_b = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx] |
|---|
| 1768 | y_a = laps_soil_temp[soil_idx - 1] |
|---|
| 1769 | y_b = laps_soil_temp[soil_idx] |
|---|
| 1770 | #print x_a, '\n\n', x_b, '\n\n', y_a, '\n\n', y_b, '\n\n' |
|---|
| 1771 | #print soil_idx, x_a.shape, x_b.shape, y_a.shape, y_b.shape |
|---|
| 1772 | x = n.ones((shape[1],shape[2])) * noah_soil_lvl[soil_idx] |
|---|
| 1773 | noah_soil_temp[soil_idx] = vu.lin_interp(x_a, x_b, y_a, y_b, x) |
|---|
| 1774 | |
|---|
| 1775 | |
|---|
| 1776 | cheat = noah_soil_temp |
|---|
| 1777 | field = n.zeros(cheat.shape) |
|---|
| 1778 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1779 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1780 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1781 | |
|---|
| 1782 | dummy['soil_temp'] = { |
|---|
| 1783 | 'long_name' : '3D volumetric soil temperature', |
|---|
| 1784 | 'pdtnum' : pdtnum, |
|---|
| 1785 | 'pdtmpl' : pdtmpl, |
|---|
| 1786 | 'drtnum' : drtnum, |
|---|
| 1787 | 'drtmpl' : drtmpl, |
|---|
| 1788 | #TODO: make sure the scaling is right |
|---|
| 1789 | #'field' : noah_soil_temp, |
|---|
| 1790 | 'field' : field, |
|---|
| 1791 | 'lvl' : noah_soil_lvl |
|---|
| 1792 | } |
|---|
| 1793 | |
|---|
| 1794 | |
|---|
| 1795 | if 1: |
|---|
| 1796 | # Let's prepare the 3d volumetric soil moisture |
|---|
| 1797 | # Product Definition Template Number (see Code Table 4.0) |
|---|
| 1798 | # 0 -> Analysis or forecast at a horizontal level or in a |
|---|
| 1799 | # horizontal layer at a point in time. (see Template 4.0) |
|---|
| 1800 | pdtnum = 0 |
|---|
| 1801 | # array of zeros (int) of size 15 |
|---|
| 1802 | pdtmpl = n.zeros((15,),dtype=int) |
|---|
| 1803 | # Follows the definition of template 4.0 |
|---|
| 1804 | # Oct 10: Parameter category (see Code table 4.1). 0 -> vegetation/biomass |
|---|
| 1805 | pdtmpl[0] = 0 |
|---|
| 1806 | # Oct 11: Parameter number (see Code table 4.2). 9 -> volumetric soil |
|---|
| 1807 | # moisture |
|---|
| 1808 | # pdtmpl[1] = 9 |
|---|
| 1809 | # I don't like this choice but maybe it is going to work more easily with |
|---|
| 1810 | # WRF and other NCAR utilities like cnvgrib |
|---|
| 1811 | pdtmpl[1] = 192 |
|---|
| 1812 | # Oct 12: Type of generating process (see Code table 4.3). 2 -> forecast |
|---|
| 1813 | pdtmpl[2] = 2 |
|---|
| 1814 | # Oct 13: Background generating process identifier |
|---|
| 1815 | # (defined by originating centre) |
|---|
| 1816 | pdtmpl[3] = missing(1) |
|---|
| 1817 | # Oct 14: Analysis or forecast generating process identified |
|---|
| 1818 | # (defined by originating centre) |
|---|
| 1819 | pdtmpl[4] = missing(1) |
|---|
| 1820 | # Oct 15-16: Hours of observational data cutoff after reference time |
|---|
| 1821 | pdtmpl[5] = missing(2) |
|---|
| 1822 | # Oct 17: Minutes of observational data cutoff after reference time |
|---|
| 1823 | pdtmpl[6] = missing(1) |
|---|
| 1824 | # Oct 18: Indicator of unit of time range (see Code table 4.4) |
|---|
| 1825 | # 1 -> hours |
|---|
| 1826 | # NB WPS expects this to be hours! |
|---|
| 1827 | pdtmpl[7] = 1 |
|---|
| 1828 | # Oct 19-22: Forecast time in units defined by octet 18 |
|---|
| 1829 | pdtmpl[8] = fv['forc_hrs'].get_value()[0] |
|---|
| 1830 | # Oct 23: Type of first fixed surface (see Code table 4.5) |
|---|
| 1831 | # 106 -> depth below land surface |
|---|
| 1832 | pdtmpl[9] = 106 |
|---|
| 1833 | # Oct 24: Scale factor of first fixed surface |
|---|
| 1834 | # 2 -> preserve cm accuracy |
|---|
| 1835 | pdtmpl[10] = 2 |
|---|
| 1836 | # Oct 25-28: Scaled value of first fixed surface |
|---|
| 1837 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1838 | # horizontal slabs for its encoding |
|---|
| 1839 | pdtmpl[11] = missing(3) |
|---|
| 1840 | # Oct 29: Type of second fixed surface (see Code table 4.5) |
|---|
| 1841 | # 106 -> depth below land surface |
|---|
| 1842 | pdtmpl[12] = 106 |
|---|
| 1843 | # Oct 30: Scale factor of second fixed surface |
|---|
| 1844 | # 2 -> preserve cm accuracy |
|---|
| 1845 | pdtmpl[13] = 2 |
|---|
| 1846 | # Oct 31-34: Scaled value of second fixed surfaces |
|---|
| 1847 | pdtmpl[14] = missing(3) |
|---|
| 1848 | # -> missing as there is will be defined later when the data is sliced in |
|---|
| 1849 | # horizontal slabs for its encoding |
|---|
| 1850 | |
|---|
| 1851 | # NB I am using the same drtnum and drtmpl for all data so I want |
|---|
| 1852 | # replicate it in the following fields if you need to change this on a |
|---|
| 1853 | # per-variable basis this is the place to redefine it. If you choose to do |
|---|
| 1854 | # so then make sure you define one for each variable that follows or be |
|---|
| 1855 | # aware that the last one defined will apply to all that follows. |
|---|
| 1856 | |
|---|
| 1857 | # in the ECMWF soil scheme the data is saved scaled by the depth of the |
|---|
| 1858 | # soil layer (or so I understand...) |
|---|
| 1859 | |
|---|
| 1860 | # TODO work out this 'not writable' rubbish |
|---|
| 1861 | #print laps_soil_mois.flags['WRITEABLE'] |
|---|
| 1862 | #laps_soil_mois.flags['WRITEABLE'] = True |
|---|
| 1863 | #laps_soil_mois = fv['soil_mois'].get_value()[0] |
|---|
| 1864 | #laps_soil_mois = fv['soil_mois'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1865 | tmp = fv['soil_mois'].get_value()[0,:,lat_cheat_idx:,:-lon_cheat_idx] |
|---|
| 1866 | shape = tmp.shape |
|---|
| 1867 | laps_soil_mois = n.zeros(shape) |
|---|
| 1868 | laps_soil_lvl = fv['soil_lvl'].get_value() |
|---|
| 1869 | for soil_idx in range(len(laps_soil_lvl)): |
|---|
| 1870 | #laps_soil_mois[soil_idx] /= laps_soil_lvl[soil_idx] |
|---|
| 1871 | laps_soil_mois[soil_idx] = tmp[soil_idx] / laps_soil_lvl[soil_idx] |
|---|
| 1872 | |
|---|
| 1873 | # Let's interpolate linearly to the Noah levels |
|---|
| 1874 | # NB for the deepest level we actually have an extrapolation |
|---|
| 1875 | noah_soil_lvl = [0.10, 0.40, 1.0, 2.0] |
|---|
| 1876 | noah_soil_mois = n.zeros(laps_soil_mois.shape, dtype=float) |
|---|
| 1877 | max_soil_lvl = 4 |
|---|
| 1878 | for soil_idx in range(max_soil_lvl): |
|---|
| 1879 | if soil_idx < max_soil_lvl - 1: |
|---|
| 1880 | x_a = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx] |
|---|
| 1881 | x_b = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx + 1] |
|---|
| 1882 | y_a = laps_soil_mois[soil_idx] |
|---|
| 1883 | y_b = laps_soil_mois[soil_idx + 1] |
|---|
| 1884 | else: |
|---|
| 1885 | # this accomplishes the extrapolation |
|---|
| 1886 | x_a = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx - 1] |
|---|
| 1887 | x_b = n.ones((shape[1],shape[2])) * laps_soil_lvl[soil_idx] |
|---|
| 1888 | y_a = laps_soil_mois[soil_idx - 1] |
|---|
| 1889 | y_b = laps_soil_mois[soil_idx] |
|---|
| 1890 | x = n.ones((shape[1],shape[2])) * noah_soil_lvl[soil_idx] |
|---|
| 1891 | noah_soil_mois[soil_idx] = vu.lin_interp(x_a, x_b, y_a, y_b, x) |
|---|
| 1892 | |
|---|
| 1893 | |
|---|
| 1894 | cheat = noah_soil_mois |
|---|
| 1895 | field = n.zeros(cheat.shape) |
|---|
| 1896 | for lvl_idx in range(cheat.shape[0]): |
|---|
| 1897 | for lat_idx in range(cheat.shape[1]): |
|---|
| 1898 | field[lvl_idx,-(lat_idx+1)] = cheat[lvl_idx,lat_idx] |
|---|
| 1899 | |
|---|
| 1900 | dummy['soil_mois'] = { |
|---|
| 1901 | 'long_name' : '3D volumetric soil moisture', |
|---|
| 1902 | 'pdtnum' : pdtnum, |
|---|
| 1903 | 'pdtmpl' : pdtmpl, |
|---|
| 1904 | 'drtnum' : drtnum, |
|---|
| 1905 | 'drtmpl' : drtmpl, |
|---|
| 1906 | #TODO: make sure the scaling is right |
|---|
| 1907 | #'field' : noah_soil_mois, |
|---|
| 1908 | 'field' : field, |
|---|
| 1909 | 'lvl' : noah_soil_lvl |
|---|
| 1910 | } |
|---|
| 1911 | |
|---|
| 1912 | f.close() |
|---|
| 1913 | sfc_f.close() |
|---|
| 1914 | |
|---|
| 1915 | #sys.exit() |
|---|
| 1916 | #p.show() |
|---|
| 1917 | |
|---|
| 1918 | |
|---|
| 1919 | |
|---|
| 1920 | # Multiple times can be included in a grib files as sequential messages so the |
|---|
| 1921 | # outermost 'dimension' of the data structure should be time |
|---|
| 1922 | # As I am going to use the GFS grib files from ncep as a template for my own |
|---|
| 1923 | # files, I will include only one time in each of the files. |
|---|
| 1924 | # It should be easy to wrap to modify the following code to concatenate |
|---|
| 1925 | # multiple times |
|---|
| 1926 | |
|---|
| 1927 | def do_the_encoding(data): |
|---|
| 1928 | dummy_idx = 0 |
|---|
| 1929 | for time_slice in data: |
|---|
| 1930 | g2e = grib2.grib2.Grib2Encode( |
|---|
| 1931 | time_slice['discipline']['atmos']['code'], |
|---|
| 1932 | time_slice['idsect']) |
|---|
| 1933 | g2e.addgrid(time_slice['gdsinfo'],time_slice['gdtmpl']) |
|---|
| 1934 | dummy = time_slice['discipline']['atmos']['fields']['2d'] |
|---|
| 1935 | for var_key in dummy.keys(): |
|---|
| 1936 | print 'Processing ' + dummy[var_key]['long_name'] |
|---|
| 1937 | g2e.addfield( |
|---|
| 1938 | dummy[var_key]['pdtnum'], |
|---|
| 1939 | dummy[var_key]['pdtmpl'], |
|---|
| 1940 | dummy[var_key]['drtnum'], |
|---|
| 1941 | dummy[var_key]['drtmpl'], |
|---|
| 1942 | dummy[var_key]['field'] |
|---|
| 1943 | ) |
|---|
| 1944 | dummy = time_slice['discipline']['atmos']['fields']['3d'] |
|---|
| 1945 | for var_key in dummy.keys(): |
|---|
| 1946 | print 'Processing ' + dummy[var_key]['long_name'] |
|---|
| 1947 | for lvl_idx in range(len(dummy[var_key]['lvl'])): |
|---|
| 1948 | print '\tlevel ' + str(lvl_idx) |
|---|
| 1949 | # '*100' because it must be in Pa |
|---|
| 1950 | dummy[var_key]['pdtmpl'][11] = \ |
|---|
| 1951 | dummy[var_key]['lvl'][lvl_idx]*100 |
|---|
| 1952 | g2e.addfield( |
|---|
| 1953 | dummy[var_key]['pdtnum'], |
|---|
| 1954 | dummy[var_key]['pdtmpl'], |
|---|
| 1955 | dummy[var_key]['drtnum'], |
|---|
| 1956 | dummy[var_key]['drtmpl'], |
|---|
| 1957 | dummy[var_key]['field'][lvl_idx] |
|---|
| 1958 | ) |
|---|
| 1959 | g2e.end() |
|---|
| 1960 | file_name = 'laps_' + str(time_slice['idsect'][5]) + '_' \ |
|---|
| 1961 | + str(zfill(time_slice['idsect'][6],2)) + '_' \ |
|---|
| 1962 | + str(zfill(time_slice['idsect'][7],2)) + '_' \ |
|---|
| 1963 | + str(zfill(time_slice['idsect'][8],2)) + 'Z_' \ |
|---|
| 1964 | + str(zfill(dummy[var_key]['pdtmpl'][8],2)) + '_hrs_fcst.grb2' |
|---|
| 1965 | #f = open('dummy' + str(dummy_idx) + '.grb2', 'w') |
|---|
| 1966 | f = open(file_name, 'w') |
|---|
| 1967 | f.write(g2e.msg) |
|---|
| 1968 | f.close() |
|---|
| 1969 | |
|---|
| 1970 | g2e = grib2.grib2.Grib2Encode( |
|---|
| 1971 | time_slice['discipline']['ocean']['code'], |
|---|
| 1972 | time_slice['idsect']) |
|---|
| 1973 | g2e.addgrid(time_slice['gdsinfo'],time_slice['gdtmpl']) |
|---|
| 1974 | dummy = time_slice['discipline']['ocean']['fields']['2d'] |
|---|
| 1975 | for var_key in dummy.keys(): |
|---|
| 1976 | print 'Processing ' + dummy[var_key]['long_name'] |
|---|
| 1977 | g2e.addfield( |
|---|
| 1978 | dummy[var_key]['pdtnum'], |
|---|
| 1979 | dummy[var_key]['pdtmpl'], |
|---|
| 1980 | dummy[var_key]['drtnum'], |
|---|
| 1981 | dummy[var_key]['drtmpl'], |
|---|
| 1982 | dummy[var_key]['field'] |
|---|
| 1983 | ) |
|---|
| 1984 | if 0: |
|---|
| 1985 | dummy = time_slice['discipline']['ocean']['fields']['3d'] |
|---|
| 1986 | for var_key in dummy.keys(): |
|---|
| 1987 | print 'Processing ' + dummy[var_key]['long_name'] |
|---|
| 1988 | for lvl_idx in range(len(dummy[var_key]['lvl'])): |
|---|
| 1989 | print '\tlevel ' + str(lvl_idx) |
|---|
| 1990 | # '*100' because it must be in Pa |
|---|
| 1991 | dummy[var_key]['pdtmpl'][11] = \ |
|---|
| 1992 | dummy[var_key]['lvl'][lvl_idx]*100 |
|---|
| 1993 | g2e.addfield( |
|---|
| 1994 | dummy[var_key]['pdtnum'], |
|---|
| 1995 | dummy[var_key]['pdtmpl'], |
|---|
| 1996 | dummy[var_key]['drtnum'], |
|---|
| 1997 | dummy[var_key]['drtmpl'], |
|---|
| 1998 | dummy[var_key]['field'][lvl_idx] |
|---|
| 1999 | ) |
|---|
| 2000 | g2e.end() |
|---|
| 2001 | #f = open('dummy' + str(dummy_idx) + '.grb2', 'a') |
|---|
| 2002 | f = open(file_name, 'a') |
|---|
| 2003 | f.write(g2e.msg) |
|---|
| 2004 | f.close() |
|---|
| 2005 | |
|---|
| 2006 | g2e = grib2.grib2.Grib2Encode( |
|---|
| 2007 | time_slice['discipline']['land']['code'], |
|---|
| 2008 | time_slice['idsect']) |
|---|
| 2009 | g2e.addgrid(time_slice['gdsinfo'],time_slice['gdtmpl']) |
|---|
| 2010 | dummy = time_slice['discipline']['land']['fields']['2d'] |
|---|
| 2011 | for var_key in dummy.keys(): |
|---|
| 2012 | print 'Processing ' + dummy[var_key]['long_name'] |
|---|
| 2013 | g2e.addfield( |
|---|
| 2014 | dummy[var_key]['pdtnum'], |
|---|
| 2015 | dummy[var_key]['pdtmpl'], |
|---|
| 2016 | dummy[var_key]['drtnum'], |
|---|
| 2017 | dummy[var_key]['drtmpl'], |
|---|
| 2018 | dummy[var_key]['field'] |
|---|
| 2019 | ) |
|---|
| 2020 | dummy = time_slice['discipline']['land']['fields']['3d'] |
|---|
| 2021 | for var_key in dummy.keys(): |
|---|
| 2022 | print 'Processing ' + dummy[var_key]['long_name'] |
|---|
| 2023 | for lvl_idx in range(len(dummy[var_key]['lvl'])): |
|---|
| 2024 | print '\tlevel ' + str(lvl_idx) |
|---|
| 2025 | if lvl_idx == 0: |
|---|
| 2026 | dummy[var_key]['pdtmpl'][11] = 0 |
|---|
| 2027 | else: |
|---|
| 2028 | dummy[var_key]['pdtmpl'][11] = \ |
|---|
| 2029 | round(dummy[var_key]['lvl'][lvl_idx-1]* 10**soil_lvl_scaling) |
|---|
| 2030 | dummy[var_key]['pdtmpl'][14] = \ |
|---|
| 2031 | round(dummy[var_key]['lvl'][lvl_idx]* 10**soil_lvl_scaling) |
|---|
| 2032 | g2e.addfield( |
|---|
| 2033 | dummy[var_key]['pdtnum'], |
|---|
| 2034 | dummy[var_key]['pdtmpl'], |
|---|
| 2035 | dummy[var_key]['drtnum'], |
|---|
| 2036 | dummy[var_key]['drtmpl'], |
|---|
| 2037 | dummy[var_key]['field'][lvl_idx] |
|---|
| 2038 | ) |
|---|
| 2039 | g2e.end() |
|---|
| 2040 | #f = open('dummy' + str(dummy_idx) + '.grb2', 'a') |
|---|
| 2041 | f = open(file_name, 'a') |
|---|
| 2042 | f.write(g2e.msg) |
|---|
| 2043 | f.close() |
|---|
| 2044 | |
|---|
| 2045 | #os.system('cnvgrib -g21 ' + file_name + ' ' + file_name[:-4] + 'grb') |
|---|
| 2046 | #os.system('/Users/val/src/cnvgrib-1.1.3/cnvgrib -g21 ' + file_name + ' ' + file_name[:-4] + 'grb') |
|---|
| 2047 | os.system('cnvgrib -g21 ' + file_name + ' ' + file_name[:-4] + 'grb') |
|---|
| 2048 | os.system('rm ' + file_name) |
|---|
| 2049 | |
|---|
| 2050 | dummy_idx += 1 |
|---|
| 2051 | |
|---|