source: trunk/UTIL/PYTHON/mcs.py @ 796

Last change on this file since 796 was 502, checked in by acolaitis, 13 years ago

Python. Minor corrections to several subroutines. Added possibility to label manually x and y axis. (use --xlabel and --ylabel). Corrected make_netcdf for certain tricky cases. Modified mcs.py to be complied with recent modifs in hrecast and zrecast. Treated cases with division by 0 in operation -%.

  • Property svn:executable set to *
File size: 14.2 KB
Line 
1#!/usr/bin/env python
2
3### A. Colaitis
4
5##
6#   This routine transforms a diagfi.nc file into a diagfi_MCS.nc file where
7#   the fields are directly comparable to those contained in MCS data, i.e.
8#   fields are re-binned at times over the ranges specified in the MCS file.
9###
10
11###########################################################################################
12###########################################################################################
13### What is below relate to running the file as a command line executable (very convenient)
14if __name__ == "__main__":
15   import sys
16   from optparse import OptionParser    ### to be replaced by argparse
17   from netCDF4 import Dataset
18   from os import system,path
19   from times import sol2ls
20   import numpy as np
21   from mymath import find_nearest
22   from myplot import getfield,separatenames
23   from make_netcdf import make_gcm_netcdf
24   from gcm_transformations import call_zrecast,call_hrecast
25   parser = OptionParser() 
26
27   #############################
28   ### Options
29   parser.add_option('-f', '--file',   action='store',dest='file',     type="string",  default=None,  help='[NEEDED] filename.')
30   parser.add_option('-m', '--mfile',  action='store',dest='mcsfile',     type="string",  default=None,  help='[NEEDED] filename for MCS comparison.')
31   parser.add_option('-v', '--var',    action='append',dest='var',      type="string",  default=None,  help='[NEEDED] Variables to process. (coma-separated list. aps and bps are always included.)')
32   parser.add_option('-x', action='store_false',dest='recast',     default=True,  help='Force aps and bps to be included in output file (usefull if your file is already recasted along z) [True]')
33   parser.add_option('-i', '--zrecast', action='store_true', dest='zrecast', default=False, help='Cast zrecast.e on diagfi file with MCS pressure levels. Will pass this operation is recasted file is already present, unless --override is specified. [False]')
34   parser.add_option('-H', '--hrecast', action='store_true', dest='hrecast', default=False, help='Cast hrecast.e on diagfi file on MCS lat/lon grid. Will pass this operation is recasted file is already present, unless --override is specified. [False]')
35   parser.add_option('--override', action='store_true', dest='override', default=False, help='Force zrecast.e to act even if recasted file is already present(will erase previous recasted file) [False]')
36   parser.add_option('--ditch', action='store_true', dest='ditch', default=False, help='Ditch recasted file when interpolation is performed. [False]')
37   parser.add_option('--latreverse', action='store_true', dest='latreverse', default=False, help='Reverse the latitude axis in output diagfi. [False]')
38
39   #############################
40   ### Get options and variables
41   (opt,args) = parser.parse_args()
42
43   #############################
44   ### Load and check data
45
46   if opt.var is None:
47      print "You must specify at least a field to process with -v."
48      exit()
49
50   # Hrecast & Zrecast
51
52   varznames=separatenames(opt.var[0])
53   filename=opt.file
54
55#   if opt.hrecast:
56#      if (path.exists(filename[0:len(filename)-3]+"_h.nc") and (not opt.override)):
57#         print "--> "+filename[0:len(filename)-3]+"_h.nc"
58#         print "Recasted file is already there, skipping interpolation. [use --override to force interpolation]"
59#         filename=filename[0:len(filename)-3]+"_h.nc"
60#      else:
61#         print "--> "+filename[0:len(filename)-3]+"_h.nc"
62#         filename=call_hrecast (  input_name      = [filename], \
63#                    fields  = varznames, \
64#                    predefined = 'mcs')[0]
65
66   if opt.zrecast:
67      if (path.exists(filename[0:len(filename)-3]+"_P.nc") and (not opt.override)):
68         print "--> "+filename[0:len(filename)-3]+"_P.nc"
69         print "Recasted file is already there, skipping interpolation. [use --override to force interpolation]"
70         filename=filename[0:len(filename)-3]+"_P.nc"
71      else:
72         print "--> "+filename[0:len(filename)-3]+"_P.nc"
73         filename=call_zrecast (  interp_mode   = 2, \
74                    input_name      = [filename], \
75                    fields  = varznames, \
76                    predefined = 'mcs')[0]
77
78   if opt.hrecast:
79      if (path.exists(filename[0:len(filename)-3]+"_h.nc") and (not opt.override)):
80         print "--> "+filename[0:len(filename)-3]+"_h.nc"
81         print "Recasted file is already there, skipping interpolation. [use --override to force interpolation]"
82         filename=filename[0:len(filename)-3]+"_h.nc"
83      else:
84         print "--> "+filename[0:len(filename)-3]+"_h.nc"
85         filename=call_hrecast (  input_name      = [filename], \
86                    fields  = varznames, \
87                    predefined = 'mcs')[0]
88
89
90   # Files
91
92   print "--> Loading diagfi dataset."
93
94   nc=Dataset(filename)
95   ncmcs=Dataset(opt.mcsfile)
96
97   # Dimensions
98
99   lon=nc.variables["longitude"][:]
100   lat=nc.variables["latitude"][:]
101   alt=nc.variables["altitude"][:]
102   time=nc.variables["Time"][:] # in fraction of sols
103   if "controle" in nc.variables:
104      controle=nc.variables["controle"][:]
105      day_ini=controle[3]%669
106   else:
107      if opt.zrecast:
108         nccontrol=Dataset(opt.file)
109         if "controle" in nccontrol.variables:
110            controle=nccontrol.variables["controle"][:]
111            day_ini=controle[3]%669
112         else:
113            print "Error: could not find controle variable in diagfi."
114            day_ini=input("Please type initial sol number:")%669
115      else:
116         print "Error: could not find controle variable in diagfi."
117         day_ini=input("Please type initial sol number:")%669
118   time[:]=time[:]+day_ini
119   nx=len(lon)
120   ny=len(lat)
121   nz=len(alt)
122   nt=len(time)
123   lstime=sol2ls(time)
124
125   # MCS
126
127   print "--> Loading and preparing MCS dataset."
128
129   dtimemintmp=ncmcs.variables["dtimemin"][:,:,:]
130   dtimemaxtmp=ncmcs.variables["dtimemax"][:,:,:]
131   ntimemintmp=ncmcs.variables["ntimemin"][:,:,:]
132   ntimemaxtmp=ncmcs.variables["ntimemax"][:,:,:]
133   lonmcs=ncmcs.variables["longitude"][:]
134   latmcs=ncmcs.variables["latitude"][:]
135   timemcs=ncmcs.variables["time"][:]%360 # IN LS
136
137   dtimemin=np.ma.masked_where(dtimemintmp < 0.,dtimemintmp)
138   dtimemin.set_fill_value([np.NaN])
139   dtimemax=np.ma.masked_where(dtimemaxtmp < 0.,dtimemaxtmp)
140   dtimemax.set_fill_value([np.NaN])
141   ntimemin=np.ma.masked_where(ntimemintmp < 0.,ntimemintmp)
142   ntimemin.set_fill_value([np.NaN])
143   ntimemax=np.ma.masked_where(ntimemaxtmp < 0.,ntimemaxtmp)
144   ntimemax.set_fill_value([np.NaN])
145
146   # Variables to treat
147
148   print "--> Preparing diagfi dataset."
149
150   varz=[]
151   n=0
152   for zn in varznames:
153       load=getfield(nc,zn)
154       load=np.ma.masked_where(load < -1.e-20,load)
155       load.set_fill_value([np.NaN])
156       load=load.filled()
157       load=np.ma.masked_invalid(load)
158       load.set_fill_value([np.NaN])
159       load=load.filled()
160       varz.append(load)
161       load=0.
162       print "Found: "+zn+" with dimensions: "
163       print np.array(varz[n]).shape
164       n=n+1
165
166   nzvar=len(varz)
167   dimensions={}
168   vv=0
169   for var in varz:
170       a=len(np.array(var).shape)
171       if a == 3: dimensions[vv]=a
172       elif a == 4: dimensions[vv]=a
173       else:
174          print "Warning, only 3d and 4d variables are supported for time-recasting"
175          exit()
176       vv=vv+1
177
178   # Variables to save but not treated (only along z, or phisinit-like files)
179
180   aps=nc.variables["aps"][:]
181   bps=nc.variables["bps"][:]
182   fullnames=["aps","bps"]
183   for name in varznames:
184       fullnames.append("d"+name)
185       fullnames.append("n"+name)
186   print "Will output: "
187   if opt.recast: print fullnames[2:]
188   else: print fullnames
189   #############################
190   ### Building
191   #############################
192
193   ### We loop over chunks of gcm data corresponding to MCS time dimension
194   ### Bin sizes for mcs data is 5 degrees ls centered on value
195   varday=np.zeros([len(timemcs),nz,ny,nx])
196   varnight=np.zeros([len(timemcs),nz,ny,nx])
197   vardayout=np.zeros([nzvar,len(timemcs),nz,ny,nx])
198   varnightout=np.zeros([nzvar,len(timemcs),nz,ny,nx])
199   vardayout=np.ma.masked_invalid(vardayout)
200   varnightout=np.ma.masked_invalid(varnightout)
201   i=0
202   for ls in timemcs:
203       lsstart=ls-2.5
204       lsstop=ls+2.5
205       istart=find_nearest(lstime,lsstart,strict=True)
206       istop=find_nearest(lstime,lsstop,strict=True)
207       varchk=0
208       if ((istart is np.NaN) or (istop is np.NaN)):
209          vardayout[:,i,:,:,:]=np.NaN
210          varnightout[:,i,:,:,:]=np.NaN
211          print "Time interval skipped. Ls MCS: (",lsstart,';',lsstop,')',"// Ls diagfi: (",lstime.min(),';',lstime.max(),')'
212          i=i+1
213          continue
214       print "--->> Processing Data. Ls MCS: (",lsstart,';',lsstop,')',"// Ls diagfi: (",lstime.min(),';',lstime.max(),')'
215       # warning, python's convention is that the second index of array[a:b] is the array index of element after the one being picked last.
216       # for that reason, array[0:0] is nan and array[0:1] is only one value. Hence, len(array[a:b+1]) is b-a+1 and not b-a+2
217       print "     .initialisation."
218       
219       
220       varchk=np.zeros([nzvar,istop-istart+1,nz,ny,nx])
221       vv=0
222       for variable in varz:
223           if dimensions[vv] is 3:
224              varchk[vv,:,0,:,:]=variable[istart:istop+1,:,:]
225           else:
226              varchk[vv,:,:,:,:]=variable[istart:istop+1,:,:,:]
227           vv=vv+1
228       varchk=np.ma.masked_invalid(varchk)
229       varchk.set_fill_value([np.NaN])
230       varchktime=time[istart:istop+1]
231       ndays=np.floor(varchktime[len(varchktime)-1])-np.floor(varchktime[0])
232       dtmichk=dtimemin[i,:,:]
233       dtmachk=dtimemax[i,:,:]
234       ntmichk=ntimemin[i,:,:]
235       ntmachk=ntimemax[i,:,:]
236       dtmichk.set_fill_value([np.NaN])
237       dtmachk.set_fill_value([np.NaN])
238       ntmichk.set_fill_value([np.NaN])
239       ntmachk.set_fill_value([np.NaN])
240       dtmichk=dtmichk.filled()
241       dtmachk=dtmachk.filled()
242       ntmichk=ntmichk.filled()
243       ntmachk=ntmachk.filled()
244
245   ### We iterate for each day in the chunk, on each grid point we find
246   ### the closest corresponding MCS grid point and the index of the
247   ### time in the chunk closest to the time in the closest MCS grid point.
248   ### (yea it's complicated)
249
250       vartmpnight=np.zeros([nzvar,ndays,nz,ny,nx])
251       vartmpday=np.zeros([nzvar,ndays,nz,ny,nx])
252       vartmpnight=np.ma.masked_invalid(vartmpnight)
253       vartmpday=np.ma.masked_invalid(vartmpday)
254       vartmpnight.set_fill_value([np.NaN])
255       vartmpday.set_fill_value([np.NaN])
256
257       nd=0
258       print "     .time indices MCS grid -> diagfi grid."
259       while nd < ndays:
260
261          daystart=find_nearest(varchktime-varchktime[0],nd)
262          daystop=find_nearest(varchktime-varchktime[0],nd+1)
263#          varchktime_lon=np.zeros([daystop-daystart+1,len(lon)])
264          ix=0
265          for x in lon:
266
267             varchktime_lon = 24.*(varchktime[daystart:daystop+1]-varchktime[daystart]) + x/15.
268
269             iy=0
270             for y in lat:
271                niy=find_nearest(latmcs,y)
272                nix=find_nearest(lonmcs,x)
273                nitdtmichk=find_nearest(varchktime_lon,dtmichk[niy,nix])
274                nitdtmachk=find_nearest(varchktime_lon,dtmachk[niy,nix])
275                nitntmichk=find_nearest(varchktime_lon,ntmichk[niy,nix])
276                nitntmachk=find_nearest(varchktime_lon,ntmachk[niy,nix])
277                for vv in np.arange(nzvar):
278                   if ((nitdtmichk is np.NaN) or (nitdtmachk is np.NaN)):
279                       vartmpday[vv,nd,:,iy,ix]=np.NaN
280                   elif nitdtmichk > nitdtmachk:
281                       vartmpday[vv,nd,:,iy,ix]=(np.ma.mean(varchk[vv,daystart+nitdtmichk:daystop+1,:,iy,ix],axis=0)+np.ma.mean(varchk[vv,daystart:daystart+nitdtmachk+1,:,iy,ix],axis=0))/2.
282                   else:
283                       vartmpday[vv,nd,:,iy,ix]=np.ma.mean(varchk[vv,daystart+nitdtmichk:daystart+nitdtmachk+1,:,iy,ix],axis=0)
284                   if ((nitntmichk is np.NaN) or (nitntmachk is np.NaN)):
285                       vartmpnight[vv,nd,:,iy,ix]=np.NaN
286                   elif nitntmichk > nitntmachk:
287                       vartmpnight[vv,nd,:,iy,ix]=(np.ma.mean(varchk[vv,daystart+nitntmichk:daystop+1,:,iy,ix],axis=0)+np.ma.mean(varchk[vv,daystart:daystart+nitntmachk+1,:,iy,ix],axis=0))/2.
288                   else:                                                           
289                       vartmpnight[vv,nd,:,iy,ix]=np.ma.mean(varchk[vv,daystart+nitntmichk:daystart+nitntmachk+1,:,iy,ix],axis=0)
290                iy=iy+1
291             ix=ix+1
292          nd=nd+1
293
294       print "     .creating bins."
295
296       vartmpdaymasked=np.ma.masked_invalid(vartmpday)
297       vartmpnightmasked=np.ma.masked_invalid(vartmpnight)
298       vartmpdaymasked.set_fill_value([np.NaN])
299       vartmpnightmasked.set_fill_value([np.NaN])
300       for vv in np.arange(nzvar):
301          vardayout[vv,i,:,:,:]=np.ma.mean(vartmpdaymasked[vv,:,:,:,:],axis=0)
302          varnightout[vv,i,:,:,:]=np.ma.mean(vartmpnightmasked[vv,:,:,:,:],axis=0)
303          print "          ."+varznames[vv]+".done"
304       i=i+1
305
306   print "--->> Preparing Data for ncdf. Missing value is NaN."
307
308   vardayout=np.ma.masked_invalid(vardayout)
309   varnightout=np.ma.masked_invalid(varnightout)
310   vardayout.set_fill_value([np.NaN])
311   varnightout.set_fill_value([np.NaN])
312
313   if opt.latreverse:
314       vardayout[:,:,:,:,:]=vardayout[:,:,:,::-1,:]
315       varnightout[:,:,:,:,:]=varnightout[:,:,:,::-1,:]
316
317   all=[aps,bps]
318   for vv in np.arange(nzvar):
319       if dimensions[vv] == 3:
320          all.append(vardayout[vv,:,0,:,:].filled())
321          all.append(varnightout[vv,:,0,:,:].filled())
322       elif dimensions[vv] == 4:
323          all.append(vardayout[vv,:,:,:,:].filled())
324          all.append(varnightout[vv,:,:,:,:].filled())
325
326   if opt.recast:
327      all=all[2:]
328      fullnames=fullnames[2:] 
329
330   if opt.latreverse:
331      lat=lat[::-1]
332
333   make_gcm_netcdf (zfilename=filename[0:len(filename)-3]+"_MCS.nc", \
334                        zdescription="Temperatures from diagfi reworked to match MCS format", \
335                        zlon=lon, \
336                        zlat=lat, \
337                        zalt=alt, \
338                        ztime=timemcs, \
339                        zvariables=all, \
340                        znames=fullnames)
341   if opt.zrecast and opt.ditch:
342      print "removing interpolated file"
343      system("rm -f "+opt.file[0:len(opt.file)-3]+"_P.nc")
Note: See TracBrowser for help on using the repository browser.