source: trunk/UTIL/PYTHON/mymath.py @ 764

Last change on this file since 764 was 647, checked in by tnavarro, 13 years ago

Corrected bug in reducefield for masked arrays with grid area. Possibility to see stream function for a lat/vert slice with --stream option. Output of both data and axis with save txt option in 1D. Small bug corrected: title is the file name for multiple plots with multiple plots. Cleanup in myplot.py

File size: 9.2 KB
Line 
1def min (field,axis=None): 
2        import numpy as np
3        if field is None: return None
4        if type(field).__name__=='MaskedArray':
5              field.set_fill_value(np.NaN)
6              return np.ma.array(field).min(axis=axis)
7        elif (np.isnan(np.sum(field)) and (type(field).__name__ not in 'MaskedArray')):
8              return np.ma.masked_invalid(field).min(axis=axis)
9        else: return np.array(field).min(axis=axis)
10
11def max (field,axis=None):
12        import numpy as np
13        if field is None: return None
14        if type(field).__name__=='MaskedArray':
15              field.set_fill_value(np.NaN)
16              return np.ma.array(field).max(axis=axis)
17        elif (np.isnan(np.sum(field)) and (type(field).__name__ not in 'MaskedArray')):
18              return np.ma.masked_invalid(field).max(axis=axis) 
19        else: return np.array(field).max(axis=axis)
20
21def mean (field,axis=None):
22        import numpy as np
23        if field is None: return None
24        else: 
25           if type(field).__name__=='MaskedArray':
26              field.set_fill_value(np.NaN)
27              zout=np.ma.array(field).mean(axis=axis)
28              if axis is not None:
29                 zout.set_fill_value(np.NaN)
30                 return zout.filled()
31              else:return zout
32           elif (np.isnan(np.sum(field)) and (type(field).__name__ not in 'MaskedArray')):
33              zout=np.ma.masked_invalid(field).mean(axis=axis)
34              if axis is not None:
35                 zout.set_fill_value([np.NaN])
36                 return zout.filled()
37              else:return zout
38           else: 
39              return np.array(field).mean(axis=axis)
40
41def sum (field,axis=None):
42        import numpy as np
43        if field is None: return None
44        else:
45           if type(field).__name__=='MaskedArray':
46              field.set_fill_value(np.NaN)
47              zout=np.ma.array(field).sum(axis=axis)
48              if axis is not None:
49                 zout.set_fill_value(np.NaN)
50                 return zout.filled()
51              else:return zout
52           elif (np.isnan(np.sum(field)) and (type(field).__name__ not in 'MaskedArray')):
53              zout=np.ma.masked_invalid(field).sum(axis=axis)
54              if axis is not None:
55                 zout.set_fill_value([np.NaN])
56                 return zout.filled()
57              else:return zout
58           else:
59              return np.array(field).sum(axis=axis)
60             
61def getmask (field):
62        import numpy as np
63        if field is None: return None
64        if type(field).__name__=='MaskedArray':
65              return np.ma.getmask(field)
66        else:
67              return np.isnan(field)
68       
69
70def deg ():
71        return u'\u00b0'
72
73def writeascii ( tab, filename ):
74    mydata = tab
75    myfile = open(filename, 'w')
76    for line in mydata:
77        zeline = str(line)
78        zeline = zeline.replace('[','')
79        zeline = zeline.replace(']','')
80        myfile.write(zeline + '\n')
81    myfile.close()
82    return
83
84
85# A.C. routine to compute saturation temperature
86# Be Carefull, when asking for tsat-t, this routine outputs a masked array.
87# To be correctly handled, this call to tsat must be done before the call to
88# reduce_field, which handles correctly masked array with the new mean() function.
89def get_tsat(pressure,temp=None,zlon=None,zlat=None,zalt=None,ztime=None):
90    import math as mt
91    import numpy as np
92    acond=3.2403751E-04
93    bcond=7.3383721E-03
94    # if temp is not in input, the routine simply outputs the vertical profile
95    # of Tsat
96    if temp is None:
97      # Identify dimensions in temperature field
98      output=np.zeros(np.array(pressure).shape)
99      if len(np.array(pressure).shape) is 1:
100         #pressure field is a 1d column, (i.e. the altitude coordinate)
101         #temperature has to have a z-axis
102         i=0
103         for pp in pressure:
104            output[i]=1./(bcond-acond*mt.log(.0095*pp))         
105            i=i+1
106      else:
107         #pressure field is a field present in the file. Unhandled
108         #by this routine for now, which only loads unique variables.
109         print "3D pressure field not handled for now, exiting in tsat"
110         print "Use a vertical pressure coordinate if you want to compute Tsat"
111         exit()
112    # if temp is in input, the routine computes Tsat-T by detecting where the
113    # vertical axis is in temp
114    else:
115      output=np.zeros(np.array(temp).shape)
116      vardim=get_dim(zlon,zlat,zalt,ztime,temp)
117      if 'altitude' not in vardim.keys():
118         print 'no altitude coordinate in temperature field for Tsat computation'
119         exit()
120      zdim=vardim['altitude']
121      ndim=len(np.array(temp).shape)
122      print '--- in tsat(). vardim,zdim,ndim: ',vardim,zdim,ndim
123      i=0
124      for pp in pressure:
125        if ndim is 1:
126           output[i]=1./(bcond-acond*mt.log(.0095*pp))-temp[i]
127        elif ndim is 2:
128           if zdim is 0:
129              output[i,:]=1./(bcond-acond*mt.log(.0095*pp))-temp[i,:]
130           elif zdim is 1:
131              output[:,i]=1./(bcond-acond*mt.log(.0095*pp))-temp[:,i]
132           else:
133              print "stop in get_tsat: zdim: ",zdim
134              exit()
135        elif ndim is 3:
136           if zdim is 0:
137              output[i,:,:]=1./(bcond-acond*mt.log(.0095*pp))-temp[i,:,:]
138           elif zdim is 1:
139              output[:,i,:]=1./(bcond-acond*mt.log(.0095*pp))-temp[:,i,:]
140           elif zdim is 2:
141              output[:,:,i]=1./(bcond-acond*mt.log(.0095*pp))-temp[:,:,i]
142           else:
143              print "stop in get_tsat: zdim: ",zdim
144              exit()
145        elif ndim is 4:
146           if zdim is 0:
147              output[i,:,:,:]=1./(bcond-acond*mt.log(.0095*pp))-temp[i,:,:,:]
148           elif zdim is 1:
149              output[:,i,:,:]=1./(bcond-acond*mt.log(.0095*pp))-temp[:,i,:,:]
150           elif zdim is 2:
151              output[:,:,i,:]=1./(bcond-acond*mt.log(.0095*pp))-temp[:,:,i,:]
152           elif zdim is 3:
153              output[:,:,:,i]=1./(bcond-acond*mt.log(.0095*pp))-temp[:,:,:,i]
154           else:
155              print "stop in get_tsat: zdim: ", zdim
156              exit()
157        else:
158           print "stop in get_tsat: ndim: ",ndim
159           exit()
160        i=i+1
161    m=np.ma.masked_invalid(temp,copy=False)
162    zoutput=np.ma.array(output,mask=m.mask,fill_value=np.NaN)
163    return zoutput
164
165# A.C. Dirty routine to determine where are the axis of a variable
166def get_dim(zlon,zlat,zalt,ztime,zvar):
167   import numpy as np
168   nx,ny,nz,nt=0,0,0,0
169   if zlon is not None:
170      nx=len(zlon)
171   if zlat is not None:
172      ny=len(zlat)
173   if zalt is not None:
174      nz=len(zalt)
175   if ztime is not None:
176      nt=len(ztime)
177   zdims={}
178   zdims['longitude']=nx
179   zdims['latitude']=ny
180   zdims['altitude']=nz
181   zdims['Time']=nt
182   zvardim=np.array(zvar).shape
183   ndim=len(zvardim)
184   zzvardim=[[]]*ndim
185   j=0
186   output={}
187   for dim in zvardim:
188       if dim not in zdims.values():
189          print "WARNING -----------------------------"
190          print "Dimensions given to subroutine do not match variables dimensions :"
191          exit()
192       else:
193          a=get_key(zdims,dim)
194          if len(a) is not 1:
195             if j is 0:                ##this should solve most conflicts with Time
196                zzvardim[j]=a[1]
197             else:
198                zzvardim[j]=a[0]
199          else:
200              zzvardim[j]=a[0]
201          output[zzvardim[j]]=j
202          j=j+1
203   return output
204
205# A.C. routine that gets keys from a dictionnary value
206def get_key(self, value):
207    """find the key(s) as a list given a value"""
208    return [item[0] for item in self.items() if item[1] == value]
209
210# A.C. routine that gets the nearest value index of array and value
211def find_nearest(arr,value,axis=None,strict=False):
212    import numpy as np
213    # Special case when the value is nan
214    if value*0 != 0: return np.NaN
215    # Check that the value we search is inside the array for the strict mode
216    if strict:
217       min=arr.min()
218       max=arr.max()
219       if ((value > max) or (value < min)): return np.NaN
220
221    if type(arr).__name__=='MaskedArray':
222       mask=np.ma.getmask(arr)
223       idx=np.ma.argmin(np.abs(arr-value),axis=axis)
224    # Special case when there are only missing values on the axis
225       if mask[idx]:
226          idx=np.NaN
227    else:
228       idx=(np.abs(arr-value)).argmin(axis=axis)
229    return idx
230
231def fig2data ( fig ):
232    import numpy
233    """
234    @brief Convert a Matplotlib figure to a 4D numpy array with RGBA channels and return it
235    @param fig a matplotlib figure
236    @return a numpy 3D array of RGBA values
237    """
238    # draw the renderer
239    fig.canvas.draw ( )
240 
241    # Get the RGBA buffer from the figure
242    w,h = fig.canvas.get_width_height()
243    buf = numpy.fromstring ( fig.canvas.tostring_argb(), dtype=numpy.uint8 )
244    buf.shape = ( w, h,4 )
245 
246    # canvas.tostring_argb give pixmap in ARGB mode. Roll the ALPHA channel to have it in RGBA mode
247    buf = numpy.roll ( buf, 3, axis = 2 )
248    return buf
249
250def fig2img ( fig ):
251    import Image
252    import numpy
253    """
254    @brief Convert a Matplotlib figure to a PIL Image in RGBA format and return it
255    @param fig a matplotlib figure
256    @return a Python Imaging Library ( PIL ) image
257    """
258    # put the figure pixmap into a numpy array
259    buf = fig2data ( fig )
260    w, h, d = buf.shape
261    return Image.fromstring( "RGBA", ( w ,h ), buf.tostring( ) )
Note: See TracBrowser for help on using the repository browser.