1 from __future__
import print_function
2 import ncepbufr, os, sys, netCDF4, datetime
3 from optparse
import OptionParser
7 get_bin =
lambda x, n: format(x,
'b').zfill(n)
11 yyyy,mm,dd,hh = splitdate(yyyymmddhh)
13 give an date string (yyyymmddhh) return integers yyyy,mm,dd,hh.
15 yyyy =
int(yyyymmddhh[0:4])
16 mm =
int(yyyymmddhh[4:6])
17 dd =
int(yyyymmddhh[6:8])
18 hh =
int(yyyymmddhh[8:10])
22 yyyymmddhh = makedate(yyyy,mm,dd,hh)
24 return a date string of the form yyyymmddhh given integers yyyy,mm,dd,hh.
26 return '%0.4i'%(yyyy)+
'%0.2i'%(mm)+
'%0.2i'%(dd)+
'%0.2i'%(hh)
29 date_list = daterange(date1,date2,hrinc)
31 return of list of date strings of the form yyyymmddhh given
32 a starting date, ending date and an increment in hours.
35 delta = datetime.timedelta(hours=1)
37 d = datetime.datetime(yyyy,mm,dd,hh)
42 date =
makedate(d.year,d.month,d.day,d.hour)
48 ScriptName = os.path.basename(sys.argv[0])
49 UsageString =
"USAGE: {0:s} [options] <obs_type> <input_prepbufr> <output_netcdf>".format(ScriptName)
52 op = OptionParser(usage=UsageString)
53 op.add_option(
"-m",
"--max-msgs", type=
"int", dest=
"max_msgs", default=-1,
54 help=
"maximum number of messages to keep", metavar=
"<max_num_msgs>")
55 op.add_option(
"-c",
"--clobber", action=
"store_true",
56 help=
"allow overwrite of output netcdf file")
58 MyOptions, MyArgs = op.parse_args()
61 print(
"ERROR: must supply exactly 3 arguments")
65 MaxMsgs = MyOptions.max_msgs
66 ClobberOfile = MyOptions.clobber
69 if not ObsType.startswith(
'bend')
and not ObsType.startswith(
'ref'):
70 print(
"ERROR: obs type string must start with 'bend' or 'ref'")
74 netcdfFname = MyArgs[2]
78 if (
not os.path.isfile(bufrFname)):
79 print(
"ERROR: {0:s}: Specified input BUFR file does not exist: {0:s}".format(ScriptName, bufrFname))
83 if (os.path.isfile(netcdfFname)):
85 print(
"WARNING: {0:s}: Overwriting nc file: {1:s}".format(ScriptName, netcdfFname))
88 print(
"ERROR: {0:s}: Specified nc file already exists: {1:s}".format(ScriptName, netcdfFname))
89 print(
"ERROR: {0:s}: Use -c option to overwrite.".format(ScriptName))
96 hdrstr =
'YEAR MNTH DAYS HOUR MINU SECO PCCF ELRC SAID PTID GEODU QFRO'
100 bufr = ncepbufr.open(bufrFname)
103 while bufr.advance() == 0:
104 dates.append(bufr.msg_date)
106 dates = np.array(dates)
107 date1 =
str(dates.min()); date2 =
str(dates.max())
108 YYYY1 = date1[0:4]; YYYY2 = date2[0:4]
109 MM1 = date1[4:6]; MM2 = date2[4:6]
110 DD1 = date1[6:8]; DD2 = date2[6:8]
111 datestart =
'%04s%s%02s00' % (YYYY1,MM1,DD1)
112 dateend =
'%04s%02s%02s18' % (YYYY2,MM2,DD2)
113 for refdate
in daterange(datestart,dateend,6):
114 if refdate[8:10]
in [
'00',
'06',
'12',
'18']
and\
115 refdate > date1
and refdate < date2:
break
117 nc = netCDF4.Dataset(netcdfFname,
'w',format=
'NETCDF4')
118 nc.createDimension(
'nobs',
None)
120 lat = nc.createVariable(
'Latitude',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
121 lat.units=
'degrees north'
122 lon = nc.createVariable(
'Longitude',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
123 lon.units=
'degress east'
124 if ObsType.startswith(
'ref'):
125 hgt = nc.createVariable(
'Height',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
127 time = nc.createVariable(
'Time',np.int64,
'nobs',zlib=
True)
128 time.units =
'seconds since %04s-%02s-%02s %02s:00 UTC' %\
129 (refdate[0:4],refdate[4:6],refdate[6:8],refdate[8:10])
130 ob = nc.createVariable(
'Observation',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
131 if ObsType.startswith(
'bend'):
132 ob.long_name =
'bending angle observation at zero frequency'
134 ob.long_name =
'refractivity observation'
135 oberr = nc.createVariable(
'ObservationErrorBufr',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
136 obpcc = nc.createVariable(
'ObservationPercentConfidence',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
137 profpcc = nc.createVariable(
'ProfilePercentConfidence',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
138 satidn = nc.createVariable(
'SatelliteID',np.int16,
'nobs',zlib=
True)
139 platidn = nc.createVariable(
'PlatformTransmitterID',np.int16,
'nobs',zlib=
True)
140 rcurv = nc.createVariable(
'EarthLocalRadiusCurv',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
141 if ObsType.startswith(
'bend'):
142 imp = nc.createVariable(
'ImpactParameter',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
145 qf = nc.createVariable(
'QualityFlags',np.int16,
'nobs',zlib=
True)
146 geo = nc.createVariable(
'GeoidUndulation',np.float32,
'nobs',zlib=
True,fill_value=bufr.missing_value)
151 while bufr.advance() == 0:
152 print(bufr.msg_counter, bufr.msg_type, bufr.msg_date)
153 while bufr.load_subset() == 0:
156 hdr = np.asarray(bufr.read_subset(hdrstr).squeeze())
157 yyyymmddhhss =
'%04i%02i%02i%02i%02i%02i' % tuple(hdr[0:6])
159 timeval = netCDF4.date2num(date,units=time.units)
174 nreps_this_ROSEQ2 = bufr.read_subset(
'{ROSEQ2}').squeeze()
175 nreps_this_ROSEQ1 = len(nreps_this_ROSEQ2)
176 data1 = np.asarray(bufr.read_subset(
'ROSEQ1',seq=
True))
177 data2 = np.asarray(bufr.read_subset(
'ROSEQ3',seq=
True))
178 levs1 = data1.shape[1]
179 levs2 = data2.shape[1]
181 print(
'skip report due to bending angle/refractivity mismatch')
187 lats = []; lons = []; hgts = []; obs = []
188 pccs = []; rocs = []; satids = []; ptids = []
189 geoids = []; obserr = []; obspccf = []; rocs = []
190 qflags = []; impacts = []
192 for k
in range(levs):
197 if latval.mask
or lonval.mask
or hgtval.mask:
212 if ObsType.startswith(
'ref'):
217 obserr.append(ref_error)
218 obspccf.append(ref_pccf)
220 elif ObsType.startswith(
'bend'):
221 for i
in range(
int(nreps_this_ROSEQ2[k])):
224 impact = data1[m+1,k]
226 bend_error = data1[m+4,k]
229 if int(freq) == 0:
break
230 bend_pccf=data1[
int(6*nreps_this_ROSEQ2[k])+3,k]
232 obserr.append(bend_error)
233 obspccf.append(bend_pccf)
234 impacts.append(impact)
237 lat[nob:nob+ncount] = lats
238 lon[nob:nob+ncount] = lons
239 ob[nob:nob+ncount] = obs
240 oberr[nob:nob+ncount] = obserr
241 obpcc[nob:nob+ncount] = obspccf
242 time[nob:nob+ncount] = timeval
243 profpcc[nob:nob+ncount] = pccs
244 satidn[nob:nob+ncount] = satids
245 platidn[nob:nob+ncount] = ptids
246 rcurv[nob:nob+ncount] = rocs
247 geo[nob:nob+ncount] = geoids
249 qf[nob:nob+ncount] = qflags
250 if ObsType.startswith(
'ref'):
251 hgt[nob:nob+ncount] = hgts
253 imp[nob:nob+ncount] = impacts
256 if MaxMsgs > 0
and bufr.msg_counter == MaxMsgs:
break
def splitdate(yyyymmddhh)
def makedate(yyyy, mm, dd, hh)
def daterange(date1, date2, hrinc)