3Copyright (C) 2011- Swedish Meteorological and Hydrological Institute (SMHI)
5This file is part of the bRopo extension to RAVE.
7RAVE is free software: you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
12RAVE is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15See the GNU Lesser General Public License for more details.
17You should have received a copy of the GNU Lesser General Public License
18along with RAVE. If not, see <http://www.gnu.org/licenses/>.
28from rave_defines
import UTF8
38import xml.etree.ElementTree
as ET
39from rave_quality_plugin
import QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY
40from rave_quality_plugin
import QUALITY_CONTROL_MODE_ANALYZE
43CONFIG_FILE = os.path.join(os.path.join(os.path.split(os.path.split(_ropogenerator.__file__)[0])[0],
44 'config'),
'ropo_options.xml')
58THRESHOLDS = {
"COLD" : (-6, -4, -2, 0, 2, 4, 6, 4, 2, 0, -2, -4),
59 "VERY_COLD" : (-12, -10, -6, -4, 0, 4, 6, 4, -4, -8, -10, -12),
60 "TEMPERATE" : (0, 2, 4, 6, 8, 10, 10, 8, 6, 4, 2, 0),
61 "FLAT-10" : (-10, -10, -10, -10, -10, -10, -10, -10, -10, -10, -10, -10),
62 "FLAT-24" : (-24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24),
63 "FLAT-30" : (-30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30),
66THRESHOLDS[
"DEFAULT"] = THRESHOLDS[
"FLAT-24"]
75 if initialized:
return
77 C = ET.parse(CONFIG_FILE)
80 for site
in list(OPTIONS):
83 for k
in site.attrib.keys():
84 if k ==
"parameters": opts.params = site.attrib[k]
85 elif k ==
"threshold": opts.threshold = site.attrib[k]
86 elif k ==
"highest-elev": opts.elev = float(site.attrib[k])
87 elif k ==
"restore": opts.restore = eval(site.attrib[k])
88 elif k ==
"restore-fill": opts.restore2 = eval(site.attrib[k])
89 elif k ==
"restore-thresh": opts.restore_thresh = eval(site.attrib[k])
90 elif k ==
"softcut": opts.softcut = eval(site.attrib[k])
91 elif k ==
"speckNormOld": opts.speckNormOld = eval(site.attrib[k])
92 elif k ==
"emitter2": opts.emitter2 = eval(site.attrib[k])
93 elif k ==
"ship": opts.ship = eval(site.attrib[k])
94 elif k ==
"speck": opts.speck = eval(site.attrib[k])
95 elif k ==
"padwidth": opts.padwidth = eval(site.attrib[k])
125 odim_source.CheckSource(inobj)
126 S = odim_source.ODIM_Source(inobj.source)
128 return copy.deepcopy(ARGS[S.nod])
130 return copy.deepcopy(ARGS[
"default"])
138 outo.beamwidth = ino.beamwidth
141 outo.height = ino.height
142 outo.latitude = ino.latitude
143 outo.longitude = ino.longitude
144 outo.source = ino.source
152def process_scan(scan, options, quality_control_mode=QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY):
153 newscan, gates =
PadNrays(scan, options)
155 image = _fmiimage.fromRave(newscan, options.params)
156 param = newscan.getParameter(options.params)
157 rg = _ropogenerator.new(image)
158 if options.threshold:
159 raw_thresh = int((options.threshold - image.offset) / image.gain)
160 rg.threshold(raw_thresh)
164 if scan.elangle * rd < options.elev:
165 if options.speckNormOld:
166 a, b, c = options.speckNormOld
167 rg.speckNormOld(a, b, c)
169 a, b, c = options.softcut
175 a, b, c = options.emitter2
178 classification = rg.classify().classification.toRaveField()
180 restored = rg.restore(int(options.restore_thresh)).toPolarScan()
181 elif options.restore2:
182 restored = rg.restore2(int(options.restore_thresh)).toPolarScan()
184 restored, classification =
UnpadNrays(restored, classification, gates)
185 dbzh = scan.getParameter(
"DBZH")
186 if quality_control_mode != QUALITY_CONTROL_MODE_ANALYZE:
187 dbzh.setData(restored.getParameter(
"DBZH").getData())
188 scan.addParameter(dbzh)
189 scan.addOrReplaceQualityField(classification)
198def process_pvol(pvol, options, quality_control_mode=QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY):
201 out = _polarvolume.new()
207 month = int(pvol.date[4:6]) - 1
208 options.threshold = THRESHOLDS[options.threshold][month]
210 for a
in pvol.getAttributeNames():
211 out.addAttribute(a, pvol.getAttribute(a))
213 for s
in range(pvol.getNumberOfScans()):
214 scan = pvol.getScan(s)
215 scan =
process_scan(scan, options, quality_control_mode)
225def generate(inobj, reprocess_quality_flag=True, quality_control_mode=QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY):
226 if _polarscan.isPolarScan(inobj) ==
False and _polarvolume.isPolarVolume(inobj) ==
False:
227 raise IOError(
"Input file must be either polar scan or volume.")
229 if reprocess_quality_flag ==
False:
230 if _polarscan.isPolarScan(inobj)
and inobj.findQualityFieldByHowTask(
"fi.fmi.ropo.detector.classification"):
232 elif _polarvolume.isPolarVolume(inobj):
234 for i
in range(inobj.getNumberOfScans()):
235 scan = inobj.getScan(i)
236 if not scan.findQualityFieldByHowTask(
"fi.fmi.ropo.detector.classification"):
243 if _polarvolume.isPolarVolume(inobj):
244 ret =
process_pvol(inobj, options, quality_control_mode)
245 elif _polarscan.isPolarScan(inobj):
246 month = int(inobj.date[4:6]) - 1
247 options.threshold = THRESHOLDS[options.threshold][month]
248 ret =
process_scan(inobj, options, quality_control_mode)
262 from numpy
import vstack
264 if options.padwidth
is not None:
265 width = float(options.padwidth)
266 elif options.emitter2
is not None and len(options.emitter2) > 2:
267 width = float(options.emitter2[2])
269 width = DEFAULT_PADWIDTH
271 gatew = 360.0 / scan.nrays
272 gates = (width / gatew)
273 if (gates - 1) > 0.0:
274 gates = int(gates + 1)
278 newscan = _polarscan.new()
280 dbzh = scan.getParameter(
"DBZH").clone()
281 data = dbzh.getData()
282 toprays = data[0:gates, ]
283 botrays = data[scan.nrays - gates:, ]
284 data = vstack((botrays, data, toprays))
286 dbzh.quantity =
"DBZH"
287 newscan.addParameter(dbzh)
288 newscan.elangle = scan.elangle
289 return newscan, gates
297 dbzh = scan.getParameter(
"DBZH")
298 data = dbzh.getData()
299 data = data[gates:scan.nrays - gates, ]
302 qdata = classification.getData()
303 qdata = qdata[gates:scan.nrays - gates, ]
304 classification.setData(qdata)
306 scan.removeParameter(
"DBZH")
307 scan.addParameter(dbzh)
308 return scan, classification
315if __name__ ==
"__main__":
Class used to organize options and argument values to ropo.
process_scan(scan, options, quality_control_mode=QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY)
TODO: activate parameters list.
UnpadNrays(scan, classification, gates)
Internal function to unwrap a scan from overlapping rays.
get_options(inobj)
Based on the /what/source attribute, find site-specific options/arguments.
init()
Initializes the ARGS dictionary by reading content from XML file.
process_pvol(pvol, options, quality_control_mode=QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY)
Loops through a volume and processes scans using process_scan.
generate(inobj, reprocess_quality_flag=True, quality_control_mode=QUALITY_CONTROL_MODE_ANALYZE_AND_APPLY)
Generate - does the real work.
PadNrays(scan, options)
Internal function to wrap rays near 360-0 degrees.
copy_topwhat(ino, outo)
Copies the top-level 'what' attributes from one object to another.