source: trunk/MESOSCALE/PLOT/PYTHON/pywrf.example.r39/wrf/utils.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: 21.9 KB
Line 
1"""
2repository of wrf utilities
3"""
4import os
5import sys
6import numpy as n
7import pylab as p
8from matplotlib.numerix import ma
9from matplotlib.toolkits.basemap import Basemap
10import pywrf.viz.utils as vu
11
12
13# the syntax to import nio depends on its version. We try all options from the
14# newest to the oldest
15try:
16    import Nio as nio
17except:
18    try:
19        import PyNGL.Nio as nio
20    except:
21        import PyNGL_numpy.Nio as nio
22
23# The following is only needed for hn3.its.monash.edu.au
24# Unfortunately we must get rid of spurious entries in the sys.path that can
25# lead to the loading of conflicting packages
26for dir_idx in range(len(sys.path)-1,-1,-1):
27    if 'python2.4' in sys.path[dir_idx]:
28        sys.path.pop(dir_idx)
29
30a_small_number = 1e-8
31
32def colons_to_underscores(test=False):
33    files = os.listdir('.')
34    print 'I plan to do the following:'
35    for file in files:
36        command = 'mv ' + file + ' ' + file[:-6] + '_00_00'
37        print command
38    print 'Happy? [y/n]'
39    answer = raw_input()
40    if answer == 'y':
41        for file in files:
42            command = 'mv ' + file + ' ' + file[:-6] + '_00_00'
43            os.system(command)
44    else:
45        print 'OK, maybe next time ;]' 
46    return
47
48def wrf_to_pressure(var, pressure, press_lvl, fill_value=1e35, positive_only=False):
49    """
50    this functions vertically interpolates to pressure levels WRF fields
51    usage
52    >>> interpolated_var(var, pressure, press_lvl, fill_value=1e35,
53    ...    positive_only=False)
54    where
55        var -> field to be interpolated
56        pressure -> total pressure field (p + pb)
57        press_lvl -> list or numpy array of desired levels
58        fill_value -> this is assigned to a cell if the requested pressure level
59          lies below or above the column of values supplied for that cell in
60          the pressure array.
61        positive_only -> set this flag to true to prevent the interpolation to
62          generate negative values for fields for which this does not make
63          sense.
64        interpolated_var -> the interpolated field which will have shape
65          (len(press_lvl), var.shape[1], var.shape[2])
66    NB in this current implementation of the function arrays need to be
67      destaggerred before they operated upon. Furthermore, it is assumed the
68      function is invoked to process one frame at at time i.e. it works on 3D
69      arrays. As usual COARDS ordering of dimensions i.e. (time,lvl,lat,lon)
70      is assumed.
71    """
72    # these are the pressure levels we want as output
73    k_max, j_max, i_max = pressure.shape
74    output = n.zeros((len(press_lvl), j_max, i_max))
75    for lvl_idx in range(len(press_lvl)):
76        for j in range(j_max):
77            for i in range(i_max):
78                # make it ascending for searchsorted
79                pressure_column = pressure[::-1,j,i]
80                if press_lvl[lvl_idx] > pressure_column.max() \
81                  or press_lvl[lvl_idx] < pressure_column.min():
82                    output[lvl_idx,j,i] = fill_value
83                else:
84                    var_column = var[::-1,j,i]
85                    press_idx = pressure_column.searchsorted(press_lvl[lvl_idx])
86                    xa = pressure_column[press_idx]
87                    xb = pressure_column[press_idx - 1]
88                    ya = var_column[press_idx]
89                    yb = var_column[press_idx - 1]
90                    x = press_lvl[lvl_idx]
91                    y = vu.lin_interp(xa, xb, ya, yb, x)
92                    if positive_only and y < 0.:
93                        y = 0.
94                    output[lvl_idx,j,i] = y
95    return output
96
97def wrf2latlon(projection, 
98  lat_0, lon_0,
99  lat_1,
100  lat_2,
101  grid_centre_lon,
102  grid_centre_lat,
103  nx,
104  ny,
105  delta,
106  staggered = False,
107  return_extra = False
108  ):
109    from pyproj import Proj
110    proj = Proj(proj=projection, lat_0=lat_0, lon_0=lon_0, lat_1=lat_1, lat_2=lat_2)
111    grid_centre_x, grid_centre_y = proj(grid_centre_lon, grid_centre_lat)
112    grid_x_extent = nx * delta
113    grid_y_extent = ny * delta
114    min_x = grid_centre_x - grid_x_extent/2.
115    min_y = grid_centre_y - grid_y_extent/2.
116    max_x = min_x + grid_x_extent
117    max_y = min_y + grid_y_extent
118    x = n.arange(min_x, max_x + a_small_number, delta)
119    y = n.arange(min_y, max_y + a_small_number, delta) 
120    X, Y = p.meshgrid(x,y)
121    lon, lat = proj(X, Y, inverse=True)
122
123    if staggered:
124        x_u = n.arange(min_x, max_x + delta + a_small_number, delta)
125        x_u -= (delta /2.)
126        X_u, Y_u = p.meshgrid(x_u,y)
127        y_v = n.arange(min_y, max_y + delta + a_small_number, delta) 
128        y_v -= (delta /2.)
129        X_v, Y_v = p.meshgrid(x,y_v)
130        lon_u, lat_u = proj(X_u, Y_u, inverse=True)
131        lon_v, lat_v = proj(X_v, Y_v, inverse=True)
132
133    llcrnrlon, llcrnrlat = proj(min_x, min_y, inverse=True)
134    urcrnrlon, urcrnrlat = proj(max_x, max_y, inverse=True)
135    map = Basemap(
136      projection = projection,
137      lon_0 = lon_0,
138      lat_0 = lat_0,
139      lat_1 = lat_1,
140      lat_2 = lat_2,
141      llcrnrlon = llcrnrlon,
142      llcrnrlat = llcrnrlat,
143      urcrnrlon = urcrnrlon,
144      urcrnrlat = urcrnrlat
145      )
146
147    if return_extra:
148        # it seems that the basemap automatically sets the origin the native
149        # coordinate system at its llcrnr (or close to it...)
150        offset = map(lon_0, lat_0)
151        if staggered:
152            X += offset[0]
153            Y += offset[1]
154            X_u += offset[0]
155            Y_u += offset[1]
156            X_v += offset[0]
157            Y_v += offset[1]
158            return lon, lat, lon_u, lat_u, lon_v, lat_v, \
159              X, Y, X_u, Y_u, X_v, Y_v, map
160        else:
161            X += offset[0]
162            Y += offset[1]
163            return lon, lat, X, Y, map
164    else: 
165        if staggered:
166            return lon, lat, lon_u, lat_u, lon_v, lat_v
167        else:
168            return lon, lat
169 
170def wrf_grid(
171  # WPS -> map_proj
172  projection,
173  # WPS -> truelat1
174  lat_1,
175  # WPS -> truelat2
176  lat_2,
177  # WPS -> stand_lon
178  lon_0,
179  # WPS -> ref_lat
180  grid_centre_lat,
181  # WPS -> ref_lon
182  grid_centre_lon,
183  delta_x,
184  delta_y,
185  # WPS -> e_we
186  nx,
187  # WPS -> e_sn
188  ny,
189  show_mass_grid = False,
190  show_stag_grids = False,
191  ):
192    if lon_0 != grid_centre_lon:
193        print 'not implemented yet -> see the source'
194        print "\tbut let's try it anyways..."
195        #return
196
197    width   = nx * delta_x
198    height  = ny * delta_y
199    frame_x = 10 * delta_x
200    frame_y = 10 * delta_y
201    m = Basemap(
202      lat_0 = grid_centre_lat,
203      # this could be a bad assumption... because lon_0 and grid_centre_lon
204      # need not be aligned, but at the same time I need to give this to
205      # basemap for the grid to be centred... I could probably fix it
206      # assigning lon_0 and then imposing a grid shift in native coordinates
207      # if ref_lon and lon_0 were not the same
208      lon_0 = lon_0,
209      lat_1 = lat_1,
210      lat_2 = lat_2,
211      width = width + 2*frame_x,
212      height = height + 2*frame_y,
213      resolution = 'l',
214      area_thresh=1000.
215      )
216    grid_centre_x, grid_centre_y = m(grid_centre_lon, grid_centre_lat)
217    min_x = grid_centre_x - width/2.
218    min_y = grid_centre_y - height/2.
219    max_x = min_x + width
220    max_y = min_y + height
221    x = n.arange(min_x, max_x + a_small_number, delta_x)
222    y = n.arange(min_y, max_y + a_small_number, delta_y) 
223    x = x[1:-1]
224    y = y[1:-1]
225    x_u = n.arange(min_x, max_x + delta_x + a_small_number, delta_x)
226    x_u -= delta_x/2.
227    x_u = x_u[1:-1]
228    y_v = n.arange(min_y, max_y + delta_y + a_small_number, delta_y)
229    y_v -= delta_y/2.
230    y_v = y_v[1:-1]
231    X, Y = p.meshgrid(x,y)
232    lon, lat = m(X, Y, inverse=True)
233    X_u, Y_u = p.meshgrid(x_u,y)
234    lon_u, lat_u = m(X_u, Y_u, inverse=True)
235    X_v, Y_v = p.meshgrid(x,y_v)
236    lon_v, lat_v = m(X_v, Y_v, inverse=True)
237    if show_mass_grid:
238        m.plot(X, Y, 'b+')
239        m.plot([grid_centre_x], [grid_centre_y], 'r+')
240        if show_stag_grids:
241            m.plot(X_u, Y_u, 'g+')
242            m.plot(X_v, Y_v, 'r+')
243        m.drawcoastlines()
244        p.show()
245    output = {
246      'map' : m,
247      'mass_stag': {
248        'lon_2d' : lon,
249        'lat_2d' : lat,
250        'x'      : x,
251        'y'      : y,
252        'x_2d'   : X,
253        'y_2d'   : Y,
254        }, 
255      'u_stag': {
256        'lon_2d' : lon_u,
257        'lat_2d' : lat_u,
258        'x'      : x_u,
259        'y'      : y,
260        'x_2d'   : X_u,
261        'y_2d'   : Y_u,
262        }, 
263      'v_stag': {
264        'lon_2d' : lon_v,
265        'lat_2d' : lat_v,
266        'x'      : x,
267        'y'      : y_v,
268        'x_2d'   : X_v,
269        'y_2d'   : Y_v,
270        } 
271      }
272
273    return output
274     
275
276def find_parent_ij(outer_grid, inner_grid):
277    projection = outer_grid[0]
278    lat_0 = outer_grid[1]
279    lon_0 = outer_grid[2]
280    lat_1 = outer_grid[3]
281    lat_2 = outer_grid[4]
282    grid_centre_lon = outer_grid[5]
283    grid_centre_lat = outer_grid[6]
284    nx = outer_grid[7]
285    ny = outer_grid[8]
286    delta = outer_grid[9]
287
288    from pyproj import Proj
289    proj = Proj(proj=projection, lat_0=lat_0, lon_0=lon_0, lat_1=lat_1, lat_2=lat_2)
290    grid_centre_x, grid_centre_y = proj(grid_centre_lon, grid_centre_lat)
291    grid_x_extent = nx * delta
292    grid_y_extent = ny * delta
293    min_x = grid_centre_x - grid_x_extent/2.
294    min_y = grid_centre_y - grid_y_extent/2.
295    max_x = min_x + grid_x_extent
296    max_y = min_y + grid_y_extent
297    outer_x = n.arange(min_x, max_x + a_small_number, delta)
298    outer_y = n.arange(min_y, max_y + a_small_number, delta) 
299
300    projection = inner_grid[0]
301    lat_0 = inner_grid[1]
302    lon_0 = inner_grid[2]
303    lat_1 = inner_grid[3]
304    lat_2 = inner_grid[4]
305    grid_centre_lon = inner_grid[5]
306    grid_centre_lat = inner_grid[6]
307    nx = inner_grid[7]
308    ny = inner_grid[8]
309    delta = inner_grid[9]
310 
311    grid_centre_x, grid_centre_y = proj(grid_centre_lon, grid_centre_lat)
312    grid_x_extent = nx * delta
313    grid_y_extent = ny * delta
314    min_x = grid_centre_x - grid_x_extent/2.
315    min_y = grid_centre_y - grid_y_extent/2.
316    max_x = min_x + grid_x_extent
317    max_y = min_y + grid_y_extent
318    inner_x = n.arange(min_x, max_x + a_small_number, delta)
319    inner_y = n.arange(min_y, max_y + a_small_number, delta)
320
321    return outer_x.searchsorted(inner_x[0]), outer_y.searchsorted(inner_y[0])
322
323def write_namelist(namelist_dict,outfile='outfile'):
324
325    out_string=''
326    for group in namelist_dict.keys():
327        out_string += group + '\n'
328        for variable in namelist_dict[group].keys():
329            out_string += variable + ' = ' 
330            for element in namelist_dict[group][variable]:
331                out_string += repr(element).strip("'")+', '
332            out_string+='\n'
333        out_string+= '/\n\n'
334
335    fid=open(outfile,'w')
336    fid.write(out_string)
337
338    return None
339
340
341
342def read_namelist(namelist_file):
343    """read contents of namelist file and return dictionary containing all options
344   
345    Created 20/01/08 by Thom Chubb.
346    Modified 20/01/08 by Thom Chubb and Valerio Bisignesi
347
348    TODO: mod_levs have a slightly different format in the namelist file, but as
349    they come last in namelist.wps I have conveniently dropped them (with a warning
350    of course =) ). Whoever needs them first can come up with a fix for this.
351    Untested as yet with the namelist.input file. It should work fine and may be useful
352    as a consistency check between the two files. This has been buggine me for a while.
353    """
354
355    fid=open(namelist_file)
356
357    out_dict={}
358    data = fid.readlines()
359    num_lines = len(data)
360
361    for line in data:
362        if '&' in line:
363            # Then this line is a namelist title
364            is_comment=False
365            current_label = line.rstrip('\n').lstrip(' ')
366            out_dict[current_label] ={}
367        elif '/' in line:
368            # Then lines following this are comments until the next '&'
369            is_comment=True
370        elif '=' in line:
371            # Then this line contains variable information to be stored
372            if not is_comment:
373                variable,values = line.split('=')
374                values = values.rstrip('\n').rstrip(',')
375                try:
376                    values=[int(element) for element in values.split(',')]
377                except ValueError:
378                    try:
379                        values=[float(element) for element in values.split(',')]
380                    except ValueError:
381                        values=[value.strip() for value in values.split(',')]
382
383                out_dict[current_label][variable.strip()]=values
384
385    return out_dict
386
387def check_namelist_consistency():
388    # TODO
389        # run time vs. run date
390        # strict consistency between dates in namelist.wps and namelist.input not
391        # necessary as long as dates in namelist.input are a subset of those in namelist.wps
392        # and the interval_seconds is correct
393    pass
394
395#def read_namelist_old(namelist_file):
396#    """read contents of namelist file and return dictionary containing all options
397#   
398#    Created 20/01/08 by Thom Chubb.
399#
400#    TODO: mod_levs have a slightly different format in the namelist file, but as
401#    they come last in namelist.wps I have conveniently dropped them (with a warning
402#    of course =) ). Whoever needs them first can come up with a fix for this.
403#    Untested as yet with the namelist.input file. It should work fine and may be useful
404#    as a consistency check between the two files. This has been buggine me for a while.
405#    """
406#
407#    fid=open(namelist_file)
408#
409#    out_dict={}
410#    data = fid.readlines()
411#    num_lines = len(data)
412#
413#    # for k in range(0,num_lines):
414#    for line in data:
415#       # str = data[k].rstrip('\n').rstrip(',').split()
416#       str = line.rstrip('\n').rstrip(',').split()
417#
418#       if str == []:
419#           pass
420#       elif str[0] == '': 
421#           pass
422#       elif str[0][0] == '':
423#           pass
424#       elif str[0][0] == '/' :
425#           is_comment=True
426#       elif str[0][0] == '&':
427#           # Then this line is a namelist title
428#           is_comment=False
429#           label = str[0]
430#
431#           if label == '&mod_levs':
432#               print ">> WARNING: mod levels don't work yet"
433#               break
434#
435#           out_dict[label] ={}
436#
437#       else:
438#           if not is_comment:
439#               field = str[0]
440#               out_dict[label][field] = []
441#
442#
443#               for k in range(2,str.__len__()):
444#                   dat = str[k].rstrip(',')
445#                   # dat = str[k].split(',')
446#                   print str, dat
447#                   try:
448#                       dat=float(dat)
449#                   except ValueError:
450#                       pass
451#                   except TypeError:
452#                       pass
453#
454#                   out_dict[label][field].extend(dat)
455#           
456#           # out_dict[label][field] = []
457#           # out_dict[label][field].append(str[2:])
458#
459#    return out_dict
460
461
462def wrf_grid_wrapper(namelist_file='namelist.wps',nest_level=0):
463    """
464    wrf_grid_wrapper(namelist_file='namelist.wps',nest_level=0):
465    Basic wrapper to easily visualise grids specified in namelist.wps
466   
467    Uses wrf.utils.read_namelist() to determine the read the appropriate variables
468    in a specified namelist file and then calls wrf.utils.wrf_grid() to define
469    the Basemap projection and show the grid over a map.
470
471    Created 20/01/08 by Thom Chubb.
472    Modified 27/01/08 - implemented viz.utils.plot_grid() to handle plotting and
473    capability for viewing as many grids as desired.
474
475    TODO: Could use some more error checking, i think it will all fail if nest_levels
476    are not consecutive!! Interpolation implemented is awkward but seems to work.
477       
478        """ 
479
480    # Create namelist dictionary
481    nd = read_namelist(namelist_file)
482
483    # Field editing to make python happy
484    if nd['&geogrid']['map_proj'][0]=="'lambert'":
485        print 'debug: modify input field lambert -> lcc' 
486        nd['&geogrid']['map_proj'][0]='lcc'
487   
488    grid = []
489
490    outer_grid = wrf2latlon(nd['&geogrid']['map_proj'][0],
491                    nd['&geogrid']['ref_lat'][0],
492                    nd['&geogrid']['ref_lon'][0],
493                    nd['&geogrid']['truelat1'][0], 
494                    nd['&geogrid']['truelat2'][0],
495                    nd['&geogrid']['ref_lon'][0],
496                    nd['&geogrid']['ref_lat'][0],
497#                   nd['&geogrid']['e_we'][nest_level[0]],
498#                   nd['&geogrid']['e_sn'][nest_level[0]],
499                    nd['&geogrid']['e_we'][0],
500                    nd['&geogrid']['e_sn'][0],
501                    nd['&geogrid']['dx'][0],
502                    staggered = False,
503                    return_extra = True
504                    )
505    # print "outer_grid.shape =", outer_grid[0].shape
506
507    grid.append(outer_grid)
508    nest_level.sort()
509    # nest_level=p.sort(nest_level)
510
511    # for k in nest_level[1:]:
512    for k in range(1,max(nest_level)+1):
513        this_grid = []
514        try:
515            e_we = nd['&geogrid']['e_we'][k]
516        except IndexError:
517            print "Out of range. Not enough grids specified within namelist file"
518            return 1
519        e_sn = nd['&geogrid']['e_sn'][k]
520        pgr  = nd['&geogrid']['parent_grid_ratio'][k]
521        ips  = nd['&geogrid']['i_parent_start'][k]
522        jps  = nd['&geogrid']['j_parent_start'][k]
523        print 'processing grid: ',k
524        # print e_we,e_sn,pgr,ips,jps
525        # print ips,':',(ips+(e_we/pgr)),',', jps,':',(jps+(e_sn/pgr))
526       
527        # Interpolate in grid space to estimate inner gridpoints -
528        # care to find a more elegant approach???
529        x1=grid[-1][2][jps, ips:ips+e_we/pgr]
530        y1=grid[-1][3][jps:jps+e_sn/pgr, ips]
531       
532        a1=n.arange(0,x1.__len__(),1) 
533        a2=n.arange(0,x1.__len__(),1./pgr)
534        b1=n.arange(0,y1.__len__(),1)
535        b2=n.arange(0,y1.__len__(),1./pgr)
536
537        x2=n.interp(a2,a1,x1)
538        y2=n.interp(b2,b1,y1)
539
540        [X,Y]=n.meshgrid(x2,y2)
541
542        # convert back to navigational coordinates
543        lon,lat=grid[-1][4](X,Y,nd['&geogrid']['map_proj'])
544
545        for j in [lon,lat,X,Y,grid[-1][4]]:
546            this_grid.append(j)
547        if (k in nest_level):   
548            map=vu.plot_grid(this_grid[0],this_grid[1],skip=10,same_figure=True,return_map=True) 
549        grid.append(this_grid) 
550        # print grid[-1][0].shape
551
552
553    if 0 in nest_level:
554        map=vu.plot_grid(outer_grid[0],outer_grid[1],skip=10,same_figure=True,return_map=True) 
555    map.drawmeridians(n.arange(130,180,15),labels=[1,0,0,1])
556    map.drawparallels(n.arange(0,-90,-15),labels=[1,0,0,1])
557    map.drawcoastlines()
558    map.drawrivers()
559    plot_custom_points(map)
560    p.show()
561   
562    return grid, map
563
564def calculate_mslp(p,pb,ph,phb,t,qvapor):
565    '''
566    calculate sea level pressure starting from 'raw' wrf output fields
567    usage:
568    >>> calculate_mslp(p,pb,ph,phb,t,qvapor)
569    where the arguments names correspond to the variable names in the
570    wrfout files e.g. p(lvl,lat,lon) or p(time,lvl,lat,lon)
571    '''
572    import  from_wrf_to_grads as fw2g
573    cs = fw2g.from_wrf_to_grads.compute_seaprs
574
575    if len(p.shape) == 3:
576       # recover the full pressure field by adding perturbation and base
577       p = p + pb
578       p_t = p.transpose()
579       # same geopotential height
580       ph = (ph + phb) / 9.81
581       ph_t = ph.transpose()
582       qvapor_t = qvapor.transpose()
583       # do not add the wrf specified 300 factor as the wrapped fortran code
584       # does that for us
585       t_t = t.transpose()
586       nz = ph_t.shape[2]
587       # populate the geopotential_height at mid_levels array with
588       # averages between layers below and above
589       z = (ph_t[:,:,:nz-1] + ph_t[:,:,1:nz]) / 2.0
590       # finally "in one fell sweep"
591       # the zero is for debug purposes
592       return cs(z,t_t,p_t,qvapor_t,0).transpose()
593    elif len(p.shape) == 4:
594       mslp_shape = (p.shape[0], p.shape[2], p.shape[3])
595       mslp = n.zeros(mslp_shape)
596       for time_idx in range(p.shape[0]):
597           # recover the full pressure field by adding perturbation and base
598           dummy_p = p[time_idx] + pb[time_idx]
599           dummy_p_t = dummy_p.transpose()
600           # same geopotential height
601           dummy_ph = (ph[time_idx] + phb[time_idx]) / 9.81
602           dummy_ph_t = dummy_ph.transpose()
603           dummy_qvapor_t = qvapor[time_idx].transpose()
604           # do not add the wrf specified 300 factor as the wrapped fortran code
605           # does that for us
606           dummy_t_t = t[time_idx].transpose()
607           nz = dummy_ph_t.shape[2]
608           # populate the geopotential_height at mid_levels array with
609           # averages between layers below and above
610           z = (dummy_ph_t[:,:,:nz-1] + dummy_ph_t[:,:,1:nz]) / 2.0
611           # finally "in one fell sweep"
612           # the zero is for debug purposes
613           mslp[time_idx] = cs(z,dummy_t_t,dummy_p_t,dummy_qvapor_t,0).transpose()
614       return mslp
615    else:
616       print 'Wrong shape of the array'
617       return
618
619def calculate_mslp_wrapper(vars_dict, time_idx):
620    """Utility function to
621    pull out the necessary variables from the wrfout file and call
622    calculate_mslp to generate the mslp field.
623    """
624    # accessing the times in the nc_file one at a time and
625    # using the .copy() method reduce the memory footprint
626    perturbation_pressure = vars_dict['P'].get_value()[time_idx].copy()
627    base_pressure = vars_dict['PB'].get_value()[time_idx].copy()
628    perturbation_geopotential = vars_dict['PH'].get_value()[time_idx].copy()
629    base_geopotential = vars_dict['PHB'].get_value()[time_idx].copy()
630    temperature = vars_dict['T'].get_value()[time_idx].copy()
631    mixing_ratio = vars_dict['QVAPOR'].get_value()[time_idx].copy()
632    mslp = calculate_mslp(
633      perturbation_pressure, 
634      base_pressure,
635      perturbation_geopotential,
636      base_geopotential,
637      temperature,
638      mixing_ratio)
639    #del perturbation_pressure, base_pressure
640    #del perturbation_geopotential, base_geopotential
641    #del temperature, mixing_ratio
642    return mslp
643
644def plot_custom_points(map):
645    """back by popular demand"""
646
647#    canberra_lon = [149 + 8./60]
648#    canberra_lat = [-35 - 17./60]
649#    map.plot(canberra_lon,canberra_lat, 'gs')
650
651    blue_calf_lon = [148.3944] 
652    blue_calf_lat = [-36.3869] 
653    map.plot(blue_calf_lon,blue_calf_lat, 'gs')
654    return
655
656def time_string_to_datetime(times):
657    '''
658    This function takes as input a numpy array of numpy string-arrays and
659    returns a list of corresponding datetime objects.
660    The array will be typically generated by a pynio get_value() call for
661    the 'Times' variable of a wrfout file.
662   
663    Usage:
664    >>> import wrf.utils as wu
665    >>> import viz.utils as vu
666    >>> f,fv = vu.peek('some_wrfout_file' + '.nc', return_pointers=True)
667    >>> times = fv['Times'].get_value()
668    >>> times = wu.time_string_to_datetime(times)
669    '''
670    from datetime import datetime
671    # VB we know that using pynio to access the 'Times' variable in a wrfout
672    # files we are returned a numpy array of string arrays hence
673    result = []
674    for time in times:
675        time_string = time.tostring()
676        year = int(time_string[:4])
677        month = int(time_string[5:7])
678        day = int(time_string[8:10])
679        hour = int(time_string[11:13])
680        minute = int(time_string[14:16])
681        second = int(time_string[17:])
682        # VB We assume the time is UTC so we will not bother
683        # specifying a time zone
684        result.append(datetime(year,month,day,hour,minute,second))
685    return result
686
Note: See TracBrowser for help on using the repository browser.