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

Last change on this file since 581 was 525, checked in by jleconte, 13 years ago

UTIL PYTHON : moyenne selon les aires et compatibilite LMDz terrestre.

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