source: trunk/src/useCorrTb_daily.py @ 706

Last change on this file since 706 was 706, checked in by pinsard, 8 years ago

rewrite one docstring for sphinx

  • Property svn:mime-type set to text/x-python; charset=UTF-8
File size: 10.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# import
5import logging
6
7from pylab import *
8from ReadRawFile import *
9from datetime import date
10import netCDF4
11from scipy import spatial
12from mpl_toolkits.basemap import pyproj
13import itertools as it
14import time
15
16##-------------------------------##
17#     Class for satellite name    #
18##-------------------------------##
19class SatName: 
20    """ ### Defined a number for each satellite """
21    def __init__(self):
22        self.satname = array(['AMSUBN15','AMSUBN16','MHSN18','MHSN19','MHSM01','MHSM02'])
23        self.satnum  = arange(size(self.satname))+1
24
25    def get_satnum(self,name):
26        return concatenate([self.satnum[nn == self.satname] for nn in name])
27   
28    def get_satname(self,num):
29        return concatenate([self.satname[nn == self.satnum] for nn in num])
30
31##-------------------------------##
32#     Correction for one orbit    #
33##-------------------------------##
34def applycorr2orb(fname,lonvec,latvec,ch=['All'],area=[-35.,35.,-180.,180.]):
35    """ ### Apply correction to AMSU or MHS orbit
36    ## Inputs
37    # fname  = file name
38    # tstep  = time resolution for new grid in minutes
39    # lonvec = longitude vecteur of new grid
40    # latvec = latitude vecteur of new grid
41    # ch     = list of extrated channel ('B1','B2','B3','B4','B5' or 'All'), default 'All'
42    # area   = limits [LS,LN,LW,LE] for extracted area, default is world (ie [-35.,35.,-180.,180.])
43    #
44    # Outputs
45    # tbcorrm = brightness temperature of orbit in new grid
46    # trefm   = ordinal time
47    #
48    """
49
50    t=time.time()
51
52    logger = logging.getLogger()
53
54    # ## Read orbit file
55    # print 'Read ', fname
56    lon, lat, dt, tb, fov = load_amsub_mhs(fname,ch,area)
57
58    try:
59        # ##  Class of each orbit points
60        # print 'Classification'
61        clz = find_class(lat,lon)
62        nozero = (clz != 0)
63
64    except ValueError:
65        logger.error('Orbit is out of the area: {0}'.format(fname))
66        return [], [], []
67
68    else:
69        # ## Coef of correction as a function of classification, fov and day of year
70        # print 'Correction'
71        coefz = find_corrcoef(dt[nozero],fov[nozero],clz[nozero],ch=ch)
72        tbcorr = array(tb)[:,nozero] - coefz
73        # ## Average on new grid
74        tbcorrm, tobsm = newgrid(lonvec,latvec,lon[nozero],lat[nozero],dt[nozero],tbcorr)
75   
76    logger.info('Deal {0} in: {1}'.format(fname, time.time()-t))
77
78    return tbcorrm, tobsm, fname.split('/')[3]
79
80##----------------------------------##
81#      Read AMSU-B and MHS files     #
82##----------------------------------##
83def load_amsub_mhs(fname,ch,area):
84    """ ### Read AMSU-B and MHS files
85    ## Inputs
86    # fname = file name
87    # ch    = list of extrated channel ('B1','B2','B3','B4','B5' or 'All'), default 'All'
88    # area  = limits [LS,LN,LW,LE] for extracted area, default is world (ie [-35,35,-180.,180])
89    #
90    ## Outputs
91    # lon  = Longitude
92    # lat  = Latitude
93    # yday = Day of year
94    # tms  = UTC time in milliseconds
95    # tb   = Brightness temperature for each channel
96    # err  = 1 if reading error, 0 else
97    #
98    """
99
100    # Index of channel
101    ch=[cch.lower() for cch in ch]
102    if (ch[0] == 'all'):
103        ich = arange(5)
104    else:
105        ich = array([int(cch[1])-1  for cch in ch])
106
107    project = os.environ['PROJECT']
108    hdr_file = '{0}/src/external_python/ReadRawFile/data/amsub-mhs_1c_header'.format(project)
109    rec_file = '{0}/src/external_python/ReadRawFile/data/amsub-mhs_1c_record'.format(project)
110    # Variables
111    dset_names = ['amb1c_latlon','amb1c_btemps','amb1c_scnlindy','amb1c_scnlintime','amb1c_scnlinyr']
112    try:
113        headers, datasets = ReadRawFile(fname, hdr_file, rec_file, False, dset_names)   
114    except:
115        logger.error('Error with {0}'.format(fname))
116        # continue
117        return 
118
119    # Latitude
120    lat = float32(datasets['amb1c_latlon'][:,:,0]/1.E4)
121    # Longitude
122    lon = float32(datasets['amb1c_latlon'][:,:,1]/1.E4)
123    # Year
124    yyyy= datasets['amb1c_scnlinyr']
125    # Day of Year
126    yday= datasets['amb1c_scnlindy']
127    # Time in milliseconds
128    tms = datasets['amb1c_scnlintime']
129    # Tb
130    tb  = float32(datasets['amb1c_btemps'][:,:,ich]/1.E2)
131    # Remplace fill values -9999.99 by NaN
132    tb[(tb == -9999.99)] = NaN
133
134    ### Extract Area
135    # Index in the defined area
136    LS, LN, LW, LE = area
137    zone = (lon>=LW) & (lon<=LE) & (lat>=LS) & (lat<=LN)
138    nscn, nfov, nch = tb.shape
139    # Extraction of Tb for each channel
140    tb = [(tb[:,:,ii])[zone] for ii in xrange(nch)]
141    # day of year and time
142    yyyy = transpose([yyyy]*nfov)[zone]
143    yday = transpose([yday]*nfov)[zone]
144    tms  = transpose([tms]*nfov)[zone]
145    # Find location in fov
146    fov = array(range(nfov)*nscn).reshape(nscn,nfov)[zone]+1
147
148    ### Convert in python date/time
149    dd = num2date(yday)
150    tt = [ms2time(ms) for ms in tms]
151    dt = array([d.replace(year=y,hour=h,minute=m,second=s) for d,y,(h,m,s) in zip(dd,yyyy,tt)])
152
153    return lon[zone], lat[zone], dt, tb, fov
154
155##-----------------------------------------------------##
156#      Convert milliseconds in hour, minute, second     #
157##-----------------------------------------------------##
158def ms2time(ms):
159    """
160    Convert milliseconds in hour, minute, second
161
162    .. warning::
163
164       lost millisecond because second is integer
165
166    .. warning::
167
168       no day (but hour might be greater than 24)
169
170    :param ms: millisecond
171
172    :return: tuple (hour, minute, second)
173    :rtype: tuple
174
175    >>> # one hour
176    >>> ms = 1000 * 60 * 60
177    >>> (h, m, s) = ms2time(ms)
178    >>> print ('{0} h {1} m {2} s'.format(h, m, s))
179    1 h 0 m 0 s
180
181    >>> # one hour + 1 ms
182    >>> ms = (1000 * 60 * 60) + 1
183    >>> (h, m, s) = ms2time(ms)
184    >>> print ('{0} h {1} m {2} s'.format(h, m, s))
185    1 h 0 m 0 s
186
187    >>> # one day + one hour
188    >>> ms = (1000 * 60 * 60 * 24) + (1000 * 60 * 60)
189    >>> (h, m, s) = ms2time(ms)
190    >>> print ('{0} h {1} m {2} s'.format(h, m, s))
191    25 h 0 m 0 s
192    """
193
194    s    = ms/1000
195    m, s = divmod(s,60)
196    h, m = divmod(m,60)
197    #d, h = divmod(h,24)
198    return h, m, s
199
200##---------------------##
201#      Find classes     #
202##---------------------##
203def find_class(lat,lon):
204    """ ### Find class of each given (lat,lon)
205    ## Inputs
206    # lat  = Latitude (degrees)
207    # lon  = Longitude (degrees)
208    #
209    ## Output
210    # clpt = class of each point (same shape as lat and lon)
211    #
212    """
213    project = os.environ['PROJECT']
214    # Read the classification file
215    fic_class = '{0}/data/classifERAI_Trop.nc'.format(project)
216    fileID = netCDF4.Dataset(fic_class)
217    lat_class = fileID.variables['lat'][:]
218    lon_class = fileID.variables['lon'][:]
219    classif   = int16(fileID.variables['classif_tot'][:])
220    fileID.close()
221
222    # Latitude limits of classification (ie tropical band)
223    latstep = abs(diff(lat_class))[0]
224    latmin = lat_class.min()-latstep/2.
225    latmax = lat_class.max()+latstep/2.
226    # Only points in the area of classification
227    inclass = logical_and(lat>=latmin,lat<=latmax)
228
229    # Geographic projection (lon/lat in degrees to x/y in m)
230    projG = pyproj.Proj("+proj=merc +ellps=WGS84 +datum=WGS84")
231    longd_class,latgd_class = meshgrid(lon_class,lat_class)
232    xclass,yclass = projG(longd_class,latgd_class)
233    xx,yy = projG(lon[inclass],lat[inclass]) 
234
235    # Find the nearest neighbour (euclidian distance) with a kd-tree
236    tree = spatial.cKDTree(zip(ravel(xclass),ravel(yclass)))
237    _, ind = tree.query(zip(xx,yy))
238    clpt = zeros(shape(lat),dtype=int16)
239    clpt[inclass] = classif.flatten()[ind]
240
241    return clpt
242
243##-------------------------------------------##
244#      Find the coefficient of correction     #
245##-------------------------------------------##
246def find_corrcoef(dt,fov,cl,ch=['All']):
247    """ ### Find the coefficient of correction
248    ## Inputs
249    # dt  = Python date
250    # fov = Location in the swath
251    # cl  = Class
252    # ch  = list of extrated channel ('B1','B2','B3','B4','B5' or 'All'), default 'All'
253    #
254    ## Outputs
255    # coef = Coefficient of correction
256    #
257    """
258    # Index of channel
259    ch=[cch.lower() for cch in ch]
260    if (ch[0] == 'all'):
261        ich = arange(5)
262    else:
263        ich = array([int(cch[1])-1  for cch in ch])
264    nch = ich.size
265   
266    # Read the classification file
267    project = os.environ['PROJECT']
268    fic_corr = '{0}/data/corrTb_AMSUB_MHS_L1C.nc'.format(project)
269    fileID = netCDF4.Dataset(fic_corr)
270    day_corr  = fileID.variables['day'][:]
271    coef_corr = fileID.variables['coefcorr'][:,:,:,ich]#[:]
272    fileID.close()
273
274    # Find the day of year
275    yday = array([d.timetuple().tm_yday for d in dt])
276    # Find the day of correction
277    nday = day_corr.size
278    daystep = diff(day_corr)[0]
279    icorr = list(flatten([[ii]*daystep for ii in xrange(nday)])) + [0]*6
280    iday = array(icorr)[yday-1]
281
282    # Find correction
283    noclass = (cl == 0)
284    icl  = array(cl-1,dtype=int)
285    ifov = array(fov-1,dtype=int)
286    coef = []
287    for ii in ich:
288        dd = zeros(cl.shape)+NaN
289        dd[~noclass] = coef_corr[iday[~noclass],icl[~noclass],ifov[~noclass],ii]
290        coef.append(dd)
291
292    return float32(coef)
293
294##---------------------------##
295#      New grid and time      #
296##---------------------------##
297def newgrid(lonvec,latvec,lon,lat,dt,tb):
298    """ ### Find the coefficient of correction
299    ## Inputs
300    #
301    #
302    ## Outputs
303    #
304    #
305    """
306
307    # from date to ordinal
308    dtord = date2num(dt)
309
310    ### Find index of each pixel in new grid 
311    # Geographic projection (lon/lat in degrees to x/y in m)
312    projG = pyproj.Proj("+proj=merc +ellps=WGS84 +datum=WGS84")
313    longd, latgd = meshgrid(lonvec,latvec)
314    xgd, ygd = projG(longd,latgd)
315    xx, yy = projG(lon,lat) 
316    # Find the nearest neighbour (euclidian distance) with a kd-tree
317    tree = spatial.cKDTree(zip(ravel(xgd),ravel(ygd)))
318    _, indll = tree.query(zip(xx,yy))
319
320    # Mean
321    nch = tb.shape[0]
322    tbm = zeros((nch,lonvec.size*latvec.size),dtype=float32)+NaN
323    dtm = zeros((lonvec.size*latvec.size))+NaN
324    for ii in unique(indll):
325        tbm[:,ii] = nanmean(tb[:,(indll==ii)],axis=1)
326        dtm[ii]  = nanmean(dtord[(indll==ii)])
327
328    return tbm, dtm
Note: See TracBrowser for help on using the repository browser.