source: trunk/MESOSCALE/PLOT/PYTHON/pywrf.example.r39/wrf/wrf_grib_encoder.py @ 183

Last change on this file since 183 was 183, checked in by aslmd, 14 years ago

MESOSCALE: PYTHON: added pywrf r39 to act as a reference for futher developments

File size: 87.0 KB
Line 
1"""
2This function accepts the fields needed by WRF and more specifically:
3
4based on the GFS Vtable.
5Assumptions:
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
11Usage:
12
13"""
14
15#############################################################################
16# TODO
17# - change the 'data' structure to a dictionary creating appropriate labels
18# from the dates
19#############################################################################
20import os
21import sys
22
23# the syntax to import nio depends on its version. We try all options from the
24# newest to the oldest
25try:
26    import Nio as nio
27except:
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
36for 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
40import numpy as n
41import pylab as p
42from matplotlib.numerix import ma
43import grib2
44from string import zfill
45import pywrf.viz.utils as vu
46from 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/'
65data_directory = \
66  '/nfs/1/home/vbisign/wrf/wps_data/run_003/press/'
67sfc_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
97data = []
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
107def 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
116def 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
159centre = 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
162subcentre = 0
163# GRIB Master Tables Version Number (Code Table 1.0)
164master_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
167local_table = 1
168# Significance of Reference Time (Code Table 1.2) -> 1 for start of forecast
169significance_ref_time = 1
170# Production status of data (Code Table 1.3) -> 2 for research product
171production_status = 2
172# idsect[12]=Type of processed data (Code Table 1.4) -> 1 -> forecast product
173type_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.
181files = os.listdir(data_directory)
182#for file in files[:2]:
183for 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
1927def 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         
Note: See TracBrowser for help on using the repository browser.