wradlib: An Open Source Library for Weather Radar Data Processing¶
Release: | 1.0.0 |
---|---|
Date: | April 06, 2018 |
The \(\omega radlib\) project has been initiated in order facilitate the use of weather radar data as well as to provide a common platform for research on new algorithms. \(\omega radlib\) is an open source library which is well documented and easy to use. It is written in the free programming language Python.
Note
Please cite \(\omega radlib\) as Heistermann, M., Jacobi, S., and Pfaff, T.: Technical Note: An open source library for processing weather radar data (wradlib), Hydrol. Earth Syst. Sci., 17, 863-871, doi:10.5194/hess-17-863-2013, 2013

Weather radar data is potentially useful in meteorology, hydrology and risk management. Its ability to provide information on precipitation with high spatio-temporal resolution over large areas makes it an invaluable tool for short term weather forecasting or flash flood forecasting.
\(\omega radlib\) is designed to assist you in the most important steps of processing weather radar data. These may include: reading common data formats, georeferencing, converting reflectivity to rainfall intensity, identifying and correcting typical error sources (such as clutter or attenuation) and visualising the data.
This documentation is under steady development. It provides a complete library reference as well as a set of tutorials which will get you started in working with \(\omega radlib\).
Getting Started¶
Installation¶
In order to run \(\omega radlib\), you need to have a Python interpreter installed on your local computer, as well as a number of Python packages (Dependencies). We recommend to install Anaconda as it installs Python, a number of required packages, and other useful tools (e.g. spyder).
Using Anaconda the installation process is harmonised across platforms. Download and install the latest Anaconda distribution from https://www.anaconda.com/download/ for your specific OS. You might also consider the minimal Miniconda if you do not want to install a full scientific python stack.
We are constantly performing tests with these distributions (for python versions 2.7, 3.5 and 3.6 respectively).
If your Anaconda Python installation is working, the following command (in a console) should work:
$ python --version
Python 3.5.1 :: Continuum Analytics, Inc.
Now you can use the conda
package and environment manager (conda documentation) to setup your \(\omega radlib\) installation.
Add the conda-forge channel, where \(\omega radlib\) and its dependencies are located. Read more about the community effort conda-forge:
$ conda config --add channels conda-forge
Create a new environment from scratch:
$ conda create --name wradlib python=3.6
Activate the \(\omega radlib\) environment
Linux:
$ source activate wradlib
Windows:
> activate wradlib
Install \(\omega radlib\) and its dependencies:
(wradlib) $ conda install wradlib
Make sure the GDAL_DATA environment variable (needed for georeferencing) is set within your environment.
Linux/OSX:
(wradlib) $ echo $GDAL_DATA
Windows CMD.exe:
[wradlib] > echo %GDAL_DATA%
If not, you can set it like this:
Linux/OSX:
(wradlib) $ export GDAL_DATA=/path/to/anaconda/envs/wradlib/share/gdal
Windows CMD.exe:
[wradlib] > setx GDAL_DATA C:\path\to\anaconda\envs\wradlib\Library\share\gdal
Now you have a conda
environment with a working \(\omega radlib\) installation.
Test the integrity of your \(\omega radlib\) installation by opening a console window and typing calling the python interpreter:
$ python
Python 3.6.2 | packaged by conda-forge | (default, Jul 23 2017, 22:59:30)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
The Python prompt should appear. Then type:
>>> import wradlib
>>> wradlib.__version__
'1.0.0'
If everything is ok, this will show the running \(\omega radlib\) version. If the \(\omega radlib\) package is not found by the interpreter, you will get:
>>> import wradlib
ImportError: No module named wradlib
Alternatively, you can install the Bleeding edge code, but you have to keep track of \(\omega radlib's\) dependencies yourself.
Bleeding edge code¶
Warning
The \(\omega radlib\) version on PyPI might lag behind the actual developments. You can use the bleeding edge code from the \(\omega radlib\) repository. Note, however, that you need to make sure yourself that all Dependencies are met (see below).
Download the source, unzip, and run:
$ python setup.py install
Alternatively, you can add the \(\omega radlib\) directory to your environment variable PYTHONPATH
.
Installing via pip¶
Although we recommend using the Anaconda Python Environment you can install \(\omega radlib\) from PyPi via pip
.
Open a terminal and run:
$ pip install wradlib
Depending on your system you might need to be root (or sudo the above command) for this to work.
pip
will then fetch the source distribution from the Python Package Index and run the installation.
Afterwards it will check for any dependencies not met, yet.
Be aware that using pip
we can only look for python-module dependencies.
For example the numpy module itself depends on some other libraries, which need to be present in order for the module to compile properly after being downloaded by pip
. We have no control over these dependencies and it is rather hard to give a complete overview.
Therefore we recommend trying to satisfy the dependencies using your favorite package management system.
Dependencies¶
\(\omega radlib\) was not designed to be a self-contained library. Besides extensive use of Numpy and Scipy, \(\omega radlib\) uses additional libraries, which you will need to install before you can use \(\omega radlib\).
Package | min | recommended |
---|---|---|
numpy | >= 1.6.1 | >= 1.14.0 |
matplotlib | >= 1.5.1 | >= 2.1.0 |
scipy | >= 0.9 | >= 1.0.0 |
h5py | >= 2.0.1 | >= 2.7.0 |
netCDF4 | >= 1.0 | >= 1.3.0 |
gdal | >= 1.9 | >= 2.2.0 |
You can check whether the required Dependencies are available on your computer by opening a Python console and enter:
>>> import <package_name>
ImportError: No module named <package_name>
This will be the response in case the package is not available.
In case the import is successful, you should also check the version number:
>>> package_name.__version__
some version number
The version number should be consistent with the above Dependencies.
Optional Dependencies¶
Apart from the obligatory Dependencies, some dependencies in \(\omega radlib\) are optional. This is because the installation of these dependencies can be somewhat tedious while many \(\omega radlib\) users will not need them anyway. In case users use a \(\omega radlib\) function that requires an optional dependency, and this dependency is not satisfied in the local environment, \(\omega radlib\) will raise an exception.
As for now, the following dependencies are defined as optional:
The speedup module
The speedup module is intended as a collection of Fortran code in order to speed up specific \(\omega radlib\) function that are critical for performance.
In order to build the speedup module as a shared library, you need to use f2py (https://sysbio.ioc.ee/projects/f2py2e/). f2py usually ships with numpy and should be available via the command line. To test whether f2py is available on your system, execute f2py
on the system console. Or, alternatively, f2py.py
. If it is available, you should get a bunch of help instructions. Now change to the \(\omega radlib\) module directory and execute on the system console:
$ f2py.py -c -m speedup speedup.f
Now the speedup module should be available.
xmltodict
We use xmltodict to convert the Rainbow Data Files (which have a metadata XML header) to an ordered dict. It is easily installed with pip
:
$ pip install xmltodict
Known Issues¶
Depending on your OS and installation method you may encounter different problems. Here are some guidelines for attacking them.
We strongly recommend using the Anaconda conda package and environment manager (see Installation). Using conda-forge we will maintain the wradlib-feedstock for constant availability of recent \(\omega radlib\) versions.
If you can’t use Anaconda/Miniconda, it is generally a good idea to use your systems package manager to install dependencies. This will also take account for other needed bindings, libs etc.
If you encounter problems installing \(\omega radlib\), check on your favorite search engine or create an issue here with details on the problem or send an email on the wradlib-users mailing list.
Community¶
\(\omega radlib\) is intended to be a community effort, and community needs communication.
The key communication platform for \(\omega radlib\) is the wradlib-users mailing list and forum. Through this forum, you can help to improve \(\omega radlib\) by reporting bugs, proposing enhancements, or by contributing code snippets (in any programming language) and documentation of algorithms.
You can also ask other users and developers for help, or use your own knowledge and experience to help other users. We strongly encourage you to subscribe to this list. Check it out!
Learn more about \(\omega radlib\) as a community effort here!
Tutorials and Examples¶
This tutorials and examples should give an idea how the individual functions of \(\omega radlib\) can be used for weather radar processing. For additional help to certain functions also consider to have look at the jupyter notebooks and example scripts distributed with the source code.
How to use the tutorials and examples?¶
Examples: your entry point to wradlib¶
The documentation of \(\omega radlib\) basically consists of two elements: the first element is the library reference which provides a systematic documentation of each function in wradlib’s API. In order to use the library reference properly, you should have an idea what you’re actually looking for. This is why new users mostly start with the second element, the tutorials and examples. Here you can look for application examples that are close to what you actually want to achieve, and then use these as a basis for further development. Once you understood an example, you also know what to look for in the library reference.
Interactive examples with jupyter notebooks¶
All \(\omega radlib\) examples are distributed as jupyter notebooks in the wradlib-notebooks repository. This way, you can interactively explore various topics. Each notebook is organized in documented code blocks. You can browse through a notebook block by block, inspect the results, and experiment with the code. However, you can also view the rendered notebooks including the example results on the web pages of this section: Each page was directly generated from \(\omega radlib\)‘s example notebooks. This way, you can copy&paste code snippets directly into your applications.
Note
Are you using \(\omega radlib\) on the Open Virtual Machine for Cross-Platform Weather Radar Science? Then skip the rest: just log in, run the command $ ./start_notebook.sh
and direct your browser to http://127.0.0.1:8888/tree. That’s it.
Otherwise, you need to make sure to
Once these conditions are met, you can open a notebook: Launch a console or bash window in the directory that contains the example notebooks. If you installed \(\omega radlib\) (e.g. via conda install wradlib
) into Anaconda’s default (root) environment, you just need to execute:
> jupyter notebook
If you installed \(\omega radlib\) into a conda environment (as recommended here), you need to activate that environment first. Let’s say you named the environment wradlib:
> activate wradlib
> jupyter notebook
Did you forget the name of the environment that contains wradlib? This way, you get an overview over all environments:
> conda info --envs
which will give you something like (example output under Windows):
# conda environments
wradlib C:\Anaconda2\envs\wradlib
root * C:\Anaconda2
In both cases, a browser window will open (typically at http://localhost:8888/tree) which will show the tree of the directory in which you started the jupyter notebook server. Just open any notebook by clicking. Code cells are executed by hitting Shift + Enter
or by using the toolbar icons. It’s pretty much self-explaining, and you’ll soon get the hang of it.
How can I get the example notebooks?¶
The notebooks are available in the wradlib-notebooks repository. Alternatively, you can download the latest (“bleeding edge”) notebooks. In both cases, you find everything in the directory /notebooks
(after extracting the downloaded archives).
How can I get the example data?¶
Most notebooks use example data. These data are provided in a separate repository and you need to “install” them manually. “Installing” actually means: Download the data archive here and extract it into any arbitrary directory. Now you need to set an environment variable pointing to that directory:
Under Windows, open a console and execute setx WRADLIB_DATA <full path to wradlib-data>
.
Under Linux, you need to set the env variable in your current shell profile. In most cases, this will be loaded from ~/.bashrc
. Open that file in an editor (e.g. via $EDITOR ~/.bashrc
) and add the following line at the end of the file:
export WRADLIB_DATA=/insert/full/path/to/wradlib-data/
After this procedure, the example notebooks will automagically pull the required files from the data archive.
How to install jupyter?¶
As already pointed out above, you can just look at the rendered notebooks online docs. In order to use them interactively, you need to install jupyter
. jupyter
is shipped with Anaconda’s distribution by default. If you installed \(\omega radlib\) in a separate virtual environment (as recommended here), you need to install jupyter
in that virtual environment, too:
Under Windows:
> activate wradlib
[wradlib] > conda install jupyter
Under Linux/OSX:
$ source activate wradlib
[wradlib] $ conda install jupyter
If you are not sure which conda environments you have, you can check via conda info --envs
.
If you did not install \(\omega radlib\) on top of Anaconda, you should first check whether jupyter
might already be available on your system (use e.g. jupyter --version
). If jupyter
is not available, you should check out the jupyter docs for alternative installation options.
I prefer simple Python scripts instead of notebooks¶
No problem. If you downloaded the notebooks directly from the wradlib repository, you can easily convert them to Python scripts yourself (but you need to install jupyter to do the conversion):
$ jupyter nbconvert --to script <name of the notebook>
Integrated Development Environments for Python¶
Development Environments vs. Notebooks¶
Jupyter notebooks are great for courses and for interactive data exploration. However, they are not suited for developing applications. Once you start to build applications or scripts on top of \(\omega radlib\), you should use a suitable Integrated Development Environmemt (IDE). IDEs give you the opportunity for organising different source files, debugging, avraible inspection and a lot more.
Some suitable IDEs¶
There is a comprehensive Wiki article on Python IDEs. Maybe a bit too comprehensive… if you already are used to an IDE and happy with it, there is no reason to change it.
However, if you have no idea which IDE to choose, why not start with Spyder. It is included in the Anaconda Python Distribution by default. If you installed Anaconda, just open a shell and enter:
$ spyder
Alternatively, we can warmly recommend PyCharm which has a free, yet powerful Community Edition.
An incomplete introduction to Python¶
In order to use \(\omega radlib\), you need to be able to use Python. The notebooks in this section will give you a glimpse of the Python language and important scientific packages, confront you with some Python exercises, and refer you to further online material. In addition, we will address some issues that are relevant to \(\omega radlib\), but do not necessarily address \(\omega radlib\) functionality.
As an introduction to scientific python, this section is necessarily incomplete. There are better and more comprehensive courses such as the SciPy Lecture Notes or the Dive into Python book.
Mostly, we will assume that you have some basic knowledge about programming, e.g. from other interpreted langauages such as R or Matlab. Otherwise, a fundamental course such as Dive into Python might help you more.
A quick start to Python¶
In order to use \(\omega radlib\), you need to be able to use Python.
This notebook will - give you a glimpse of the Python language, - confront you with some Python exercises, - and refer you to further in-depth courses for learning Python.
Hello interpreted world¶
Python is an interpreted language just as e.g. R, Matlab and many others. In contrast to a compiled languages such as C, C++ or Fortran, each command is immediately interpreted by the Python interpreter. In this case, executing the following cell produces an immediate output.
In [1]:
print("Hello interpreted world.")
Hello interpreted world.
Writing a program in Python¶
Instead of entering this command interactively in a Python console (or a jupyter cell, as in this case), you can also write a Python script (or, in other words, a Python “program”).
- Use a text editor to create a file,
- add the line
print("Hello interpreted world.")
, - save the file under the name
demoscript.py
(by convention, Python scripts should have the extension .py
).
Now execute your script from any shell (or the DOS console on Windows):
$ python demoscript.py
Note that this will work only if you open the shell in the same directory in which you saved your script. Otherwise, you need to provide the full path like e.g.
Under Linux/OSX:
$ python /home/user/path/to/demoscript.py
Under Windows:
> python e:\path\to\demoscript.py
Important data types¶
Python knows various standard data types such as - integer
, -
float
, - bool
, - and str
.
If you define a variable, Python typically assigns the type of that variable for you.
In [2]:
x1 = 2
print("x1 is of %r" % type(x1))
x2 = 2.3
print("x2 is of %r" % type(x2))
x3 = True
print("x3 is of %r" % type(x3))
x4 = x1 * x2
print("x4 is of %r" % type(x4))
x5 = "Hello interpreted world."
print("x5 is of %r" % type(x5))
x1 is of <class 'int'>
x2 is of <class 'float'>
x3 is of <class 'bool'>
x4 is of <class 'float'>
x5 is of <class 'str'>
As you noticed in the above cell, you can inspect the data type of a
variable by using function type()
. Python has a plethora of data
types beyond the standard ones shown above. See for example:
In [3]:
print( type(sum) )
print( type(type) )
<class 'builtin_function_or_method'>
<class 'type'>
Other data types: collections¶
Further important data types (and specific to Python) are so called
data collections
(or containers
), namely
- lists (
list
), - dictionaries (
dict
), - and tuples (
tuple
).
Lists¶
A list is an ordered collection of objects which may have different types.
In [4]:
# a list
l = [1, "Paris", 3.0]
# a list is "mutable" (i.e. you can change the values of its elements)
l[1] = 2
print(l)
print(l[0:2])
[1, 2, 3.0]
[1, 2]
Excursus: indexing in Python¶
You might have noticed that the index 1
refers to the second element
of the list.
This is an important rule for all containers in Python: indexing begins with 0
(which is familiar e.g. to C programmers, and new e.g. to R programmers)
Dictionaries¶
- a
dictionary
is basically an efficient table that mapskeys
tovalues
. - it is an unordered container.
There are two ways to define dictionaries - both are equivalent.
In [5]:
# One way to define a dictionary
d1 = {"band": "C", "altitude":1000.}
# Another way to define a dictionary
d2 = dict(band="C", altitude=1000.)
# Both are equivalent
print("d1 equals d2 is a %r statement " % (d1 == d2) )
print("The type of d1 is %r" % type(d1) )
d1 equals d2 is a True statement
The type of d1 is <class 'dict'>
A dictionary
can be queried using their keywords. You can also
iterate over the keys.
In [6]:
print(d1["band"])
print("Printing all keys and values of d1:")
for key in d1.keys():
print("\t%s: %r" % (key, d1[key]) )
C
Printing all keys and values of d1:
band: 'C'
altitude: 1000.0
Control flow¶
Loops or iterations as well as conditional statments are key to data processing workflows.
In this section, we will present the most important syntax for control flow.
“for” loops¶
In [7]:
# For loops
for i in range(3):
print(i)
0
1
2
Indentation in Python
Indentation is a mandatory element of Python syntax - not just a question of style.
Not using indentation will raise an IndentationError
.
“while” loops¶
In [8]:
# While loops (in case the number of iterations is not known a-priori)
i = 0
while i < 3:
print(i)
i += 1
0
1
2
Conditional statements¶
In [9]:
# Conditional statements
a = 5
if a < 10:
print("a is less than 10.")
elif a == 10:
print("a equals 10.")
else:
print("a is greater than 10.")
a is less than 10.
You can also exit a loop before it is finished or skip parts of a specific iteration.
In [10]:
for i in range(3):
# Exit the loop already if i equals 1
if i == 1:
break
print(i)
0
In [11]:
for i in range(3):
# Skip the iteration if i equals 1 (but continue the loop)
if i == 1:
continue
print(i)
0
2
Importing functions from modules¶
For most applications, you will need to use functions
that are
available in modules
. Just think of a module as a collection (or
library) of functions. Some are shipped with the Python interpreter
(Python Standard Library),
others (such as wradlib) need to be installed (e.g. from the Python
Package Index) or using the
Anaconda Package Manager
(conda
).
In order to use a function from a module, you need to import
the
module. See e.g. how to import the os
module and use its getcwd
function (which retruns the path to the current working directory):
In [12]:
import os
mycwd = os.getcwd()
print(mycwd)
/home/travis/build/wradlib/wradlib-notebooks/notebooks/python
Getting help¶
- In most environments, you can use the TAB key for code completion and for listing functions available in a module.
- Use the following cell, enter
os.
and hit the TAB key. You can narrow down available functions by typing further characters. - Once you’ve selected (or typed) a function name, jupyter will show you the help content after hitting TAB+Shift.
- Alternatively, you can get help for a function in any Python
environment by calling
help
(e.g.help(os.getcwd)
). In juypter, you can also use the following syntax:os.getcwd?
Writing your own functions¶
In order to organise applications and write reusable code, you will need to write funcions on you own.
This is how you define and call a function (notice again the indentation):
In [13]:
# Define the function...
def demofunction(a, b):
c = a + b
return(c)
In [14]:
# ...and call the function
demofunction(2,3)
Out[14]:
5
Using docstrings
, you can document your function as you write it.
In [15]:
def demofunction(a, b):
"""This function computes the sum of a and b.
Parameters
----------
a : numeric
b : numeric
Returns
-------
output : numeric (the sum of a and b)
"""
c = a + b
return(c)
Now try calling help(demofunction)
.
This should be the output:
Help on function demofunction in module __main__:
demofunction(a, b)
This function computes the sum of a and b
Parameters
----------
a : numeric
b : numeric
Returns
-------
output : numeric (the sum of a and b)
Functions can have keyword arguments with default values. In the
following example, we set a default value for parameter b
.
In [16]:
def demofunction(a, b=2):
"""Adds 2 to a by default.
"""
c = a + b
return(c)
In [17]:
print(demofunction(3))
print(demofunction(3, b=3))
5
6
File input and output¶
This is the basic way to read from and write to text and binary files (there are a lot of other file formats which have specific interfaces - particularly in the radar world: see file formats supported by wradlib).
In [18]:
# Open a file for writing
f = open('testfile.txt', 'w') # opens the workfile file
print(type(f))
f.write('This is a test line,\nand another test line.\n')
f.close()
<class '_io.TextIOWrapper'>
In [19]:
# Open a file for reading
f = open('testfile.txt', 'r')
s = f.read()
print(s)
f.close()
This is a test line,
and another test line.
A safer way to handle files is to use Python’s with
statement which
makes sure that the file is properly closed even if your code breaks
inbetween opening and closing the file.
In [20]:
with open("testfile.txt") as f:
s = f.read()
print(s)
This is a test line,
and another test line.
The building blocks of scientific Python¶
With this, we conclude the basic Python intro.
The following sections introduce, we introduce the most important packages for scientific computing in Python. Unlike Matlab, Scilab or R, Python does not come with a pre-bundled set of modules for scientific computing. Instead, a scientific computing environment can be obtained by combining these building blocks:
- Python, a generic and modern computing language, including standard data types and collections, flow control, modules of the standard library, and development tools (automatic testing, documentation generation)
- IPython: an interactive Python shell, see our article on how to use notebooks.
- Numpy: provides powerful numerical arrays objects, and routines to manipulate them - see our NumPy intro article
- Matplotlib : visualization and “publication-ready” plots, see related intro here
- Scipy: high-level data processing routines - e.g. optimization, regression, interpolation, etc (https://www.scipy.org)
Please also check out further in-depth courses such as - the SciPy Lecture Notes or - the Dive into Python book.
In [1]:
from __future__ import print_function
NumPy: manipulating numerical data¶
NumPy is the key Python package for creating and manipulating (multi-dimensional) numerical arrays. NumPy arrays are also the most important data objects in \(\omega radlib\). It has become a convention to import NumPy as follows:
In [2]:
import numpy as np
Creating and inspecting NumPy arrays¶
The ndarray
, a numerical array, is the most important data type in
NumPy.
In [3]:
a = np.array([0, 1, 2, 3])
print(a)
print(type(a))
[0 1 2 3]
<class 'numpy.ndarray'>
Inspect the shape
(i.e. the number and size of the dimensions of an
array).
In [4]:
print(a.shape)
# This creates a 2-dimensional array
a2 = np.array([[0, 1], [2, 3]])
print(a2.shape)
(4,)
(2, 2)
There are various ways to create arrays: from lists (as above), using convenience functions, or from file.
In [5]:
# From lists
a = np.array([0, 1, 2, 3])
print("a looks like:\n%r\n" % a)
# Convenience functions
b = np.ones( shape=(2,3) )
print("b looks like:\n%r\nand has shape %r\n" % (b, b.shape) )
c = np.zeros( shape=(2,1) )
print("c looks like:\n%r\nand has shape %r\n" % (c, c.shape) )
d = np.arange(2,10)
print("d looks like:\n%r\nand has shape %r\n" % (d, d.shape) )
e = np.linspace(0,10,5)
print("e looks like:\n%r\nand has shape %r\n" % (e, e.shape) )
a looks like:
array([0, 1, 2, 3])
b looks like:
array([[1., 1., 1.],
[1., 1., 1.]])
and has shape (2, 3)
c looks like:
array([[0.],
[0.]])
and has shape (2, 1)
d looks like:
array([2, 3, 4, 5, 6, 7, 8, 9])
and has shape (8,)
e looks like:
array([ 0. , 2.5, 5. , 7.5, 10. ])
and has shape (5,)
You can change the shape of an array without changing its size.
In [6]:
a = np.arange(10)
b = np.reshape(a, (2,5))
print("Array a has shape %r.\nArray b has shape %r" % (a.shape, b.shape))
Array a has shape (10,).
Array b has shape (2, 5)
Indexing and slicing¶
You can index an ndarray
in the same way as a list
:
In [7]:
a = np.arange(10)
print(a)
print(a[0], a[2], a[-1])
[0 1 2 3 4 5 6 7 8 9]
0 2 9
Just follow your intuition for indexing multi-dimensional arrays:
In [8]:
a = np.diag(np.arange(3))
print(a, end="\n\n")
print("Second row, second column: %r\n" % a[1, 1])
# Setting an array item
a[2, 1] = 10 # third line, second column
print(a, end="\n\n")
# Acessing a full row
print("Second row:\n%r" % a[1])
[[0 0 0]
[0 1 0]
[0 0 2]]
Second row, second column: 1
[[ 0 0 0]
[ 0 1 0]
[ 0 10 2]]
Second row:
array([0, 1, 0])
Slicing is just a way to access multiple array items at once:
In [9]:
a = np.arange(10)
print(a, end="\n\n")
print("1st:", a[2:9])
print("2nd:", a[2:])
print("3rd:", a[:5])
print("4th:", a[2:9:3]) # [start:end:step]
print("5th:", a[a>5]) # using a mask
[0 1 2 3 4 5 6 7 8 9]
1st: [2 3 4 5 6 7 8]
2nd: [2 3 4 5 6 7 8 9]
3rd: [0 1 2 3 4]
4th: [2 5 8]
5th: [6 7 8 9]
Get further info on NumPy arrays here!
Visualisation and plotting with Matplotlib¶
Matplotlib is the key Python package for producing so called publication-ready plot. It provides the basis for \(\omega radlib\)’s entire visualisation module, and is typically used together with NumPy - which is the other major \(\omega radlib\) dependency.
Different ways to import matplotlib¶
In a Python script¶
import matplotlib.pyplot as pl
In an IPython notebook¶
# This magic just sets up matplotlib's interactive mode
%matplotlib
# So you have to explicitely import the module into the namespace
import matplotlib.pyplot as pl
If you want to enable inline plotting
(mandatory if you use the Virtual Machine for Cross-Platform Weather Radar Science)
# This magic just sets up matplotlib's interactive mode
%matplotlib inline
# So you have to explicitely import the module into the namespace
import matplotlib.pyplot as pl
%matplotlib inline
turns on “inline plotting”, where plot graphics
will appear in your notebook. This has important implications for
interactivity: for inline plotting, commands in cells below the cell
that outputs a plot will not affect the plot. For example, changing the
color map is not possible from cells below the cell that creates a plot.
However, for other backends, such as qt4, that open a separate window,
cells below those that create the plot will change the plot - it is a
live object in memory. If you are not using matplotlib in interactive
mode at all, figures will only appear if you invoke plt.show()
.
If you do not want to use inline plotting, just use %matplotlib
instead of %matplotlib inline
. The Kernel has to be restarted for
this change to become effective.
If you want to magically import numpy and matplotlib
%pylab
# or
%pylab inline
In the following, we use a sightly different syntax for
matplotlib inline
. This is because the notebook needs to be
convertable to a Python script where IPython magic does not work. Please
don’t let this confuse you…
In [1]:
# Instead of matplotlib inline
import matplotlib.pyplot as pl
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
Simple plots and decorations¶
After these imports, inline plots should work rightaway, e.g. a simple line plot of the sinus function:
In [2]:
x = np.arange(0,4*np.pi,0.1)
y = np.sin(x)
pl.plot(x, y)
Out[2]:
[<matplotlib.lines.Line2D at 0x7face88c6550>]

More complex plots and fine control¶
A matplotlib plot can be understood from an object-oriented perspective. Each plot consists of a figure object (like a canvas), an axes object (like a subplot or panel), and other objects such as a title, an axis, or a colorbar.

alt text
Accordingly, a plot can be developed by creating or modifying the
different objects. For example, the size of the entire plot is
controlled by the Figure
object. Each subplot
in that figure
corresponds to an axes
object.
In [3]:
# Create the figure object
fig = pl.figure(figsize=(12,8))
# Add first axes object (of a multi-panel plot with two rows and one column)
ax = fig.add_subplot(211)
pl.plot(x, np.sin(x))
pl.title("The Sinus Function")
pl.xlabel("This is my x-axis label")
# Add second axes object
ax = fig.add_subplot(212)
pl.plot(x, np.cos(x))
pl.title("The Cosinus Function")
pl.xlabel("This is my x-axis label")
# Make sure the elements of the plot are arranged properly
pl.tight_layout()

Dealing with time series¶
Dealing with radar data typically means implies dealing with time series (of radar records or rain gauge observations). This article gives a brief intro on how to deal with times series and datetimes in Python.
The datetime module¶
The datetime module provides a number of types to deal with dates, times, and time intervals.
In [1]:
import datetime as dt
There are different ways to create datetime objects.
In [2]:
# This is now (system time)
now = dt.datetime.now()
# Just using the date
birth_van_rossum = dt.datetime(1956, 1, 31)
# Providing both date and time
first_wradlib_commit = dt.datetime(2011, 10, 26, 11, 54, 58)
# Or initialising from a string
erad_2016_begins = dt.datetime.strptime("2016-10-09 09:00:00", "%Y-%m-%d %H:%M:%S")
You can compute the difference between two datetime objects.
In [3]:
# Age of Guido van Rossum
age_van_rossum = now - birth_van_rossum
print("This is a %r object.\n" % type(age_van_rossum) )
print("It looks like this: %r" % age_van_rossum )
print("and consists of\n\t%d days,\n\t%d seconds,\n\tand %d microseconds.\n"
% (age_van_rossum.days, age_van_rossum.seconds, age_van_rossum.microseconds) )
# Age of wradlib
age_wradlib = now - first_wradlib_commit
# Time until (or since) beginning of ERAD 2016 OSS Short course
from_to_erad2016 = now - erad_2016_begins
print("Guido van Rossum is %d seconds old." % age_van_rossum.total_seconds())
print("wradlib's first commit was %d days ago." % age_wradlib.days)
if from_to_erad2016.total_seconds() < 0:
print("The ERAD 2016 OSS Short course will start in %d days." % -from_to_erad2016.days )
else:
print("The ERAD 2016 OSS Short course took place %d days ago." % from_to_erad2016.days)
This is a <class 'datetime.timedelta'> object.
It looks like this: datetime.timedelta(22703, 50902, 574390)
and consists of
22703 days,
50902 seconds,
and 574390 microseconds.
Guido van Rossum is 1961590102 seconds old.
wradlib's first commit was 2346 days ago.
The ERAD 2016 OSS Short course took place 536 days ago.
Or you can create a datetime.timedelta
object yourself and
add/subtract a time interval from/to a datetime
object. You can use
any of these keywords:
days, seconds, microseconds, milliseconds, minutes, hours, weeks
,
but datetime.timedelta
will always represent the result in
days, seconds, microseconds
.
In [4]:
# This is an interval of two minutes
print(dt.timedelta(minutes=1, seconds=60))
# And this is, too
print(dt.timedelta(minutes=2))
now = dt.datetime.now()
print("This is now: %s" % now)
print("This is two minutes before: %s" % (now - dt.timedelta(minutes=2)) )
0:02:00
0:02:00
This is now: 2018-03-29 14:08:22.621256
This is two minutes before: 2018-03-29 14:06:22.621256
The default string format of a datetime
object corresponds to the
isoformat. Using the
strftime
function, however, you can control string formatting
yourself. The following example shows this feature together with other
features we have learned before. The idea is to loop over time and
generate corresponding string representations. We also store the
datetime
objects in a list.
In [5]:
start = dt.datetime(2016, 10, 9)
end = dt.datetime(2016, 10, 14)
interval = dt.timedelta(days=1)
dtimes = []
print("These are the ERAD 2016 conference days (incl. short courses):")
while start <= end:
print(start.strftime("\t%A, %d. %B %Y"))
dtimes.append(start)
start += interval
These are the ERAD 2016 conference days (incl. short courses):
Sunday, 09. October 2016
Monday, 10. October 2016
Tuesday, 11. October 2016
Wednesday, 12. October 2016
Thursday, 13. October 2016
Friday, 14. October 2016
matplotlib generally understands
datetime
objects and tries to make sense of them in plots.
In [6]:
# Instead of %matplotlib inline
import matplotlib.pyplot as pl
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
In [7]:
# Create some dummy data
level = np.linspace(100,0,len(dtimes))
# And add a time series plot
fig = pl.figure(figsize=(10,5))
ax = fig.add_subplot(111)
pl.plot(dtimes, level, "bo", linestyle="dashed")
pl.xlabel("Day of the conference", fontsize=15)
pl.ylabel("Relative attentiveness (%)", fontsize=15)
pl.title("Development of participants' attentiveness during the conference", fontsize=15)
pl.tick_params(labelsize=12)

Using virtual environments¶
Virtual environments provide a great opportunity to experiment with different system configuations (e.g. package versions) without putting your entire Python installation at risk. Working with Anaconda makes the use of virtual environments quite easy.
Why should I use virtual environments¶
To be continued…
Why should I NOT use virtual environments¶
To be continued…
Getting started with wradlib¶
This section provides a collection of example code snippets to make users familiar with \(\omega radlib\).
Import wradlib and check its version¶
This simple example shows the \(\omega radlib\) version at rendering time.
In [1]:
import wradlib
print(wradlib.__version__)
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
1.0.0
A Typical Workflow For Radar-Based Rainfall Estimation¶
Raw, unprocessed reflectivity products can already provide useful visual information about the spatial distribution of rainfall fields. However, in order to use weather radar observations for quantitative studies (e.g. in hydrological modelling or for assimilation into Numerical Weather Prediction models), the data has to be carefully processed in order to account for typical errors sources such as ground echoes (clutter), attenuation of the radar signal, or uncertainties in the Z/R relationship.
Moreover, it might be necessary to transfer the data from polar coordinates to Cartesian grids, or to combine observations from different radar locations in overlapping areas on a common grid (composition). And in the end, you would typically like to visualise the spatial rainfall distribution on a map. Many users also need to quantify the potential error (uncertainty) of their data-based rainfall estimation.
These are just some steps that might be necessary in order to make radar data useful in a specific quantitative application environment. All steps together are typically referred to as a “radar data processing chain”. \(\omega radlib\) was designed to support you in establishing your own processing chain, suited to your specific requirements. In the following, we will provide an outline of a typical processing chain, step-by-step. You might not need all steps for your own workflow, or you might need steps which are not yet included here.
Introduction¶
Consider this just as an example. We will not go into detail for each step in this section, but refer to more detailed tutorials (if available) or the corresponding entry in the library reference. Most of the steps have a corresponding \(\omega radlib\) module. In order to access the functions of \(\omega radlib\), you have to import \(\omega radlib\) in your Python environment:
import wradlib as wrl
If you have trouble with that import, please head back to the Getting Started section.
Note
The data used in this tutorial can be found in the wradlib-data repository. Follow these instructions to install and use this data files.
Warning
Be aware that applying an algorithm for error correction does not guarantee that the error is totally removed. Error correction procedures are suceptible to errors, too. Not only might they fail to remove the error. They might also introduce new errors. The trade-off between costs (introduction of new errors) and benefits (error reduction) can turn out differently for different locations, different points in time, or different rainfall situations.
Reading the data¶
The binary encoding of many radar products is a major obstacle for many potential radar users. Often, decoder software is not easily available. \(\omega radlib\) supports a couple of formats such as the ODIM_H5 implementation, NetCDF, and some formats used by the German Weather Service. We seek to continuously enhance the range of supported formats.
The basic data type used in \(\omega radlib\) is a multi-dimensional array, the numpy.ndarray. Such an array might e.g. represent a polar or Cartesian grid, or a series of rain gage observations. Metadata are normally managed as Python dictionaries. In order to read the content of a data file into a numpy array, you would normally use the wradlib.io module. In the following example, a local PPI from the German Weather Service, a DX file, is read:
In [2]:
import pylab as pl
pl.figure(figsize=(10,8))
filename = wrl.util.get_wradlib_data_file('dx/raa00-dx_10908-0806021655-fbg---bin.gz')
data, metadata = wrl.io.read_dx(filename)
ax, pm = wrl.vis.plot_ppi(data) # simple diagnostic plot
cbar = pl.colorbar(pm, shrink=0.75)
<Figure size 720x576 with 0 Axes>

The metadata
object can be inspected via keywords. The data
object contains the actual data, in this case a polar grid with 360
azimuth angles and 128 range bins.
Seealso
Get more info in the section Supported radar data formats and in the library reference section Raw Data I/O.
Clutter removal¶
Clutter are non-meteorological echos. They are caused by the radar beam hitting objects on the earth’s surface (e.g. mountain or hill tops, houses, wind turbines) or in the air (e.g. airplanes, birds). These objects can potentially cause high reflectivities due large scattering cross sections. Static clutter, if not efficiently removed by Doppler filters, can cause permanent echos which could introduce severe bias in quantitative applications. Thus, an efficient identification and removal of clutter is mandatory e.g. for hydrological studies. Clutter removal can be based on static maps or dynamic filters. Normally, static clutter becomes visible more clearly in rainfall accumulation maps over periods of weeks or months. We recommend such accumulations to create static clutter maps which can in turn be used to remove the static clutter from an image and fill the resulting gaps by interpolation.
In the following example, the clutter filter published by Gabella et al., 2002) is applied to the single radar sweep of the above example:
In [3]:
clutter = wrl.clutter.filter_gabella(data, tr1=12, n_p=6, tr2=1.1)
pl.figure(figsize=(10,8))
ax, pm = wrl.vis.plot_ppi(clutter, cmap=pl.cm.gray)
pl.title('Clutter Map')
Out[3]:
Text(0.5,1,'Clutter Map')
<Figure size 720x576 with 0 Axes>

The resulting Boolean array clutter
indicates the position of
clutter. It can be used to interpolate the values at those positons from
non-clutter values, as shown in the following line:
In [4]:
data_no_clutter = wrl.ipol.interpolate_polar(data, clutter)
pl.figure(figsize=(10,8))
ax, pm = wrl.vis.plot_ppi(data_no_clutter) # simple diagnostic plot
cbar = pl.colorbar(pm, shrink=0.75)
<Figure size 720x576 with 0 Axes>

It is generally recommended to remove the clutter before e.g. gridding the data. Otherwise the clutter signal might be “smeared” over multiple grid cells, resulting into a decrease in detectability.
Seealso
Get more info in the library reference section Clutter Identification.
Attenuation correction¶
Attenuation by wet radome and by heavy rainfall can cause serious
underestimation of rainfall for C-Band and
X-Band
devices. For such radar devices, situations with heavy rainfall require
a correction of attenuation effects. The general approach with
single-polarized radars is to use a recursive gate-by-gate approach. See
Kraemer et al.,
2008
for an introduction to this concept. Basically, the specific attenuation
k
of the first range gate is computed via a so-called k-Z
relationship. Based on k
, the reflectivity of the second range gate
is corrected and then used to compute the specific attenuation for the
second range gate (and so on). The concept was first introduced by
Hitschfeld et al.,
1954).
Its main drawback is its suceptibility to instable behaviour.
\(\omega radlib\) provides different implementations which address
this problem.
One example is the algorithm published by Jacobi and Heistermann, 2016:
In [5]:
pia = wrl.atten.correct_attenuation_constrained(data_no_clutter, a_max=1.67e-4, a_min=2.33e-5,
n_a=100, b_max=0.7, b_min=0.65, n_b=6,
gate_length=1., constraints=[wrl.atten.constraint_dbz,
wrl.atten.constraint_pia],
constraint_args=[[59.0],[20.0]])
data_attcorr = data_no_clutter + pia
The first line computes the path integrated attenuation pia
for each
radar bin. The second line uses pia
to correct the reflectivity
values. Let’s inspect the effect of attenuation correction for an
azimuth angle of 65 deg:
In [6]:
pl.figure(figsize=(10,8))
pl.plot(data_attcorr[65], label="attcorr")
pl.plot(data_no_clutter[65], label="no attcorr")
pl.xlabel("km")
pl.ylabel("dBZ")
pl.legend()
Out[6]:
<matplotlib.legend.Legend at 0x7f4733d10518>

Seealso
Get more info in the library reference section Attenuation Correction. There you will learn to know the algorithms available for attenuation correction and how to manipulate their behaviour by using additonal keyword arguments.
Vertical Profile of Reflectivity¶
Precipitation is 3-dimensional in space. The vertical distribution of precipitation (and thus reflectivity) is typically non-uniform. As the height of the radar beam increases with the distance from the radar location (beam elevation, earth curvature), one sweep samples from different heights. The effects of the non-uniform VPR and the different sampling heights need to be accounted for if we are interested in the precipiation near the ground or in defined altitudes.
Seealso
Get more info in the library reference section Vertical Profile of Reflectivity (VPR). There you will learn how to reference polar volume data, to create CAPPIs and Pseudo CAPPIs, to inspect vertical profiles of reflectivity (UNDER DEVELOPMENT), and to use these for correction (UNDER DEVELOPMENT).
Conversion of Reflectivity into Rainfall¶
Reflectivity (Z) and precipitation rate (R) can be related in form of a
power law \(R=a*Z^b\). The parameters a
and b
depend on the
type of precipitation in terms of drop size distribution and water
temperature. Before applying the Z-R relationship, we need to convert
from dBZ to Z:
In [7]:
R = wrl.zr.z_to_r(wrl.trafo.idecibel(data_attcorr))
The above line uses the default parameters a=200
and b=1.6
for
the Z-R relationship. In order to compute a rainfall depth from rainfall
intensity, we have to specify an integration interval in seconds. In
this example, we choose five minutes (300 s), corresponding to the scan
interval.
In [8]:
depths = wrl.trafo.r_to_depth(R, 300)
Seealso
Get more info in the section Converting reflectivity to
rainfall and in the library reference
sections Z-R Conversions
and Data
Transformation. Here
you will learn about the effects of the Z-R parameters a
and b
.
Rainfall accumulation¶
For many applications, accumulated rainfall depths over specific time
intervals are required, e.g. hourly or daily accumulations. In the
following example, we will use a synthetic time series of 5 minute
intervals. Just imagine we have repeated the above procedure for one day
of five-minute sweeps and combined the arrays of rainfall depth in a
3-dimensional array of shape
(number of time steps, number of azimuth angles, number of range gates)
.
Now we want to compute the daily rainfall sum:
In [9]:
sweep_times = wrl.util.from_to("2012-10-26 00:00:00", "2012-10-27 00:00:00", 300)
depths_5min = np.random.uniform(size=(len(sweep_times)-1, 360, 128))
depth_daily = depths_5min.sum(axis=0)
Check the shape the resulting array for plausibility:
In [10]:
print(depth_daily.shape)
(360, 128)
Seealso
For more advanced operations on time series, we recommend the Pandas package.
Georeferencing and Projection¶
In order to define the horizontal and vertical position of the radar bins, we need to retrieve the corresponding 3-dimensional coordinates in terms of longitude, latitude and altitude. This information is required e.g. if the positions should be plotted on a map. It is also required for constructing CAPPIs. The position of a radar bin in 3-dimensional space depends on the position of the radar device, the elevation and azimuth angle of the radar beam, the range of the bin, and the assumed influence of atmospheric refraction on the beam propagation. For the sample data used above, the position of the radar device is the Feldberg in Germany (8.005, 47.8744, 1517):
In [11]:
radar_location = (8.005, 47.8744, 1517) # (lon, lat, alt) in decimal degree and meters
elevation = 0.5 # in degree
azimuths = np.arange(0,360) # in degrees
ranges = np.arange(0, 128000., 1000.) # in meters
polargrid = np.meshgrid(ranges, azimuths)
Using georef.spherical_to_xyz
we get the cartesian coordinates in
xyz-space and the connected azimuthal equidistant projection osr-object
rad
.
In [12]:
coords, rad = wrl.georef.spherical_to_xyz(polargrid[0], polargrid[1],
elevation, radar_location)
x = coords[..., 0]
y = coords[..., 1]
\(\omega radlib\) supports the projection between geographical coordinates (lon/lat) and other reference systems. It uses GDAL/OSR Spatial References Objects as function parameters. Basically, you have to create the OSR-object by using GDAL-capabilities or one of the provided helper functions. We recommend the creation using EPSG numbers:
In [13]:
# Gauss Krueger Zone 3, EPSG-Number 31467
gk3 = wrl.georef.epsg_to_osr(31467)
gk3_coords = wrl.georef.reproject(coords, projection_source=rad,
projection_target=gk3)
Second, you can provide a string which represents the projection - based on the PROJ.4 library. You can look up projection strings, but for some projections, \(\omega radlib\) helps you to define a projection string. In the following example, the target projection is ‘dwd-radolan’:
In [14]:
radolan = wrl.georef.create_osr("dwd-radolan")
radolan_coords = wrl.georef.reproject(coords, projection_target=radolan)
Seealso
Get more info in the library reference section Georeferencing.
Gridding¶
Assume you would like to transfer the rainfall intensity from the above
example from polar
coordinates to a Cartesian grid, or to an arbitrary set of irregular
points in space (e.g. centroids of sub-catchments). You already
retrieved the Cartesian coordinates of the radar bins in the previous
section Georeferencing and
Projection. Now you only need to
define the target coordinates (e.g. a grid) and apply the togrid
function of the
wradlib.comp module.
In this example, we want our grid only to represent the South-West
sector of our radar circle on a 100 x 100 grid. First, we define the
target grid coordinates (these must be an array of 100x100 rows with one
coordinate pair each):
In [15]:
xgrid = np.linspace(x.min(), x.mean(), 100)
ygrid = np.linspace(y.min(), y.mean(), 100)
grid_xy = np.meshgrid(xgrid, ygrid)
grid_xy = np.vstack((grid_xy[0].ravel(), grid_xy[1].ravel())).transpose()
Now we transfer the polar data to the grid and mask out invalid values for plotting (values outside the radar circle receive NaN):
In [16]:
xy=np.concatenate([x.ravel()[:,None],y.ravel()[:,None]], axis=1)
gridded = wrl.comp.togrid(xy, grid_xy, 128000., np.array([x.mean(), y.mean()]), data.ravel(), wrl.ipol.Nearest)
gridded = np.ma.masked_invalid(gridded).reshape((len(xgrid), len(ygrid)))
fig = pl.figure(figsize=(10,8))
ax = pl.subplot(111, aspect="equal")
pm = pl.pcolormesh(xgrid, ygrid, gridded)
pl.colorbar(pm, shrink=0.75)
pl.xlabel("Easting (m)")
pl.ylabel("Northing (m)")
pl.xlim(min(xgrid), max(xgrid))
pl.ylim(min(ygrid), max(ygrid))
Out[16]:
(-126946.43557281807, 0.0)

Seealso
Get more info about the function wradlib.comp.togrid().
Adjustment by rain gage observations¶
Adjustment normally refers to using rain gage observations on the ground to correct for errors in the radar-based rainfall estimating. Goudenhoofdt et al., 2009 provide an excellent overview of adjustment procedures. A typical approach is to quantify the error of the radar-based rainfall estimate at the rain gage locations, assuming the rain gage observation to be accurate. The error can be assumed to be additive, multiplicative, or a mixture of both. Most approaches assume the error to be heterogeneous in space. Hence, the error at the rain gage locations will be interpolated to the radar bin (or grid) locations and then used to adjust (correct) the raw radar rainfall estimates.
In the following example, we will use an illustrative one-dimensional example with synthetic data (just imagine radar rainfall estimates and rain gage observations along one radar beam).
First, we create the synthetic “true” rainfall (truth
):
In [17]:
import numpy as np
radar_coords = np.arange(0,101)
truth = np.abs(1.5+np.sin(0.075*radar_coords)) + np.random.uniform(-0.1,0.1,len(radar_coords))
The radar rainfall estimate radar
is then computed by imprinting a
multiplicative error
on truth
and adding some noise:
In [18]:
error = 0.75 + 0.015*radar_coords
radar = error * truth + np.random.uniform(-0.1,0.1,len(radar_coords))
Synthetic gage observations obs
are then created by selecting
arbitrary “true” values:
In [19]:
obs_coords = np.array([5,10,15,20,30,45,65,70,77,90])
obs = truth[obs_coords]
Now we adjust the radar
rainfall estimate by using the gage
observations. First, you create an “adjustment object” from the approach
you want to use for adjustment. After that, you can call the object with
the actual data that is to be adjusted. Here, we use a multiplicative
error model with spatially heterogenous error (see
wradlib.adjust.AdjustMultiply():
In [20]:
adjuster = wrl.adjust.AdjustMultiply(obs_coords, radar_coords, nnear_raws=3)
adjusted = adjuster(obs, radar)
Let’s compare the truth
, the radar
rainfall estimate and the
adjusted
product:
In [21]:
pl.plot(radar_coords, truth, 'k-', label="True rainfall", linewidth=2.)
pl.xlabel("Distance (km)")
pl.ylabel("Rainfall intensity (mm/h)")
pl.plot(radar_coords, radar, 'k-', label="Raw radar rainfall", linewidth=2., linestyle="dashed")
pl.plot(obs_coords, obs, 'o', label="Gage observation", markersize=10.0, markerfacecolor="grey")
pl.plot(radar_coords, adjusted, '-', color="green", label="Multiplicative adjustment", linewidth=2., )
pl.legend(prop={'size':12})
Out[21]:
<matplotlib.legend.Legend at 0x7f472b9adf28>

Seealso
Get more info in the library reference section Gage Adjustment. There, you will also learn how to use the built-in cross-validation in order to evaluate the performance of the adjustment approach.
Verification and quality control¶
Typically, radar-based precipitation estimation and the effectiveness of the underlying correction and adjustment methods are verified by comparing the results against rain gage observations on the ground. wradlib.verify module provides procedures not only to extract the radar values at specific gauge locations, but also a set of error metrics which are computed from gage observations and the corresponding radar-based precipitation estimates (including standard metrics such as RMSE, mean error, Nash-Sutcliffe Efficiency). In the following, we will illustrate the usage of error metrics by comparing the “true” rainfall against the raw and adjusted radar rainfall estimates from the above example:
In [22]:
raw_error = wrl.verify.ErrorMetrics(truth, radar)
adj_error = wrl.verify.ErrorMetrics(truth, adjusted)
Error metrics can be reported e.g. as follows:
In [23]:
print("Error metrics for unadjusted radar rainfall estimates:")
raw_error.pprint()
print("\nError metrics for adjusted radar rainfall estimates:")
adj_error.pprint()
Error metrics for unadjusted radar rainfall estimates:
{'corr': 0.7,
'mas': 0.77,
'meanerr': 0.69,
'mse': 1.21,
'nash': -1.59,
'pbias': 43.6,
'r2': 0.48,
'ratio': 1.5,
'rmse': 1.1,
'spearman': 0.77,
'sse': 122.13}
Error metrics for adjusted radar rainfall estimates:
{'corr': 0.99,
'mas': 0.09,
'meanerr': 0.06,
'mse': 0.01,
'nash': 0.98,
'pbias': 3.8,
'r2': 0.98,
'ratio': 1.03,
'rmse': 0.1,
'spearman': 0.99,
'sse': 1.33}
Seealso
Get more info in the library reference section Verification.
Visualisation and mapping¶
In the above sections Reading the data, Clutter removal, and Gridding you already saw examples of the \(\omega radlib's\) plotting capabilities.
Seealso
Get more info in the library reference section Visualisation.
Data export to other applications¶
Once you created a dataset which meets your requirements, you might want to export it to other applications or archives. \(\omega radlib\) does not favour or support a specific output format. Basically, you have all the freedom of choice offered by Python and its packages in order to export your data. Arrays can be stored as text or binary files by using numpy functions. You can use the package NetCDF4 to write NetCDF files, and the packages h5py or PyTables to write hdf5 files. At a later stage of development, \(\omega radlib\) might support a standardized data export by using the OPERA’s ODIM_H5 data model (see Supported Radar Data Formats). Of course, you can also export data as images. See Visualisation for some options.
Export your data array as a text file:
In [24]:
np.savetxt("mydata.txt", data)
Or as a gzip-compressed text file:
In [25]:
np.savetxt("mydata.gz", data)
Or as a NetCDF file:
In [26]:
import netCDF4
rootgrp = netCDF4.Dataset('test.nc', 'w', format='NETCDF4')
sweep_xy = rootgrp.createGroup('sweep_xy')
dim_azimuth = sweep_xy.createDimension('azimuth', None)
dim_range = sweep_xy.createDimension('range', None)
azimuths_var = sweep_xy.createVariable('azimuths','i4',('azimuth',))
ranges_var = sweep_xy.createVariable('ranges','f4',('range',))
dBZ_var = sweep_xy.createVariable('dBZ','f4',('azimuth','range',))
azimuths_var[:] = np.arange(0,360)
ranges_var[:] = np.arange(0, 128000., 1000.)
dBZ_var[:] = data
You can easily add metadata to the NetCDF file on different group levels:
In [27]:
rootgrp.bandwith = "C-Band"
sweep_xy.datetime = "2012-11-02 10:15:00"
rootgrp.close()
Note
An example for hdf5 export will follow.
Converting Reflectivity to Rainfall¶
Reflectivity (Z) and precipitation rate (R) can be related in form of a
power law \(Z=a \cdot R^b\). The parameters a
and b
depend
on the type of precipitation (i.e. drop size distribution and water
temperature). \(\omega radlib\) provides a couple of functions that
could be useful in this context.
The following example demonstrates the steps to convert from the common unit dBZ (decibel of the reflectivity factor Z) to rainfall intensity (in the unit of mm/h). This is an array of typical reflectivity values (unit: dBZ)
In [2]:
dBZ = np.array([20., 30., 40., 45., 50., 55.])
print(dBZ)
[20. 30. 40. 45. 50. 55.]
Convert to reflectivity factor Z (unit: \(mm^6/m^3\)):
In [3]:
Z = wrl.trafo.idecibel(dBZ)
print(Z)
[1.00000000e+02 1.00000000e+03 1.00000000e+04 3.16227766e+04
1.00000000e+05 3.16227766e+05]
Convert to rainfall intensity (unit: mm/h) using the Marshall-Palmer Z(R) parameters:
In [4]:
R = wrl.zr.z_to_r(Z, a=200., b=1.6)
print(np.round(R, 2))
[ 0.65 2.73 11.53 23.68 48.62 99.85]
Convert to rainfall depth (unit: mm) assuming a rainfall duration of five minutes (i.e. 300 seconds)
In [5]:
depth = wrl.trafo.r_to_depth(R, 300)
print(np.round(depth, 2))
[0.05 0.23 0.96 1.97 4.05 8.32]
An example with real radar data¶
The following example is based on observations of the DWD C-band radar on mount Feldberg (SW-Germany). The figure shows a 15 minute accumulation of rainfall which was produced from three consecutive radar scans at 5 minute intervals between 17:30 and 17:45 on June 8, 2008.
The radar data are read using wradlib.io.read_dx function which returns an array of dBZ values and a metadata dictionary (see also Reading-DX-Data). The conversion is carried out the same way as in the example above. The plot is produced using the function wradlib.vis.plot_ppi.
In [6]:
def read_data(dtimes):
"""Helper function to read raw data for a list of datetimes <dtimes>
"""
data = np.empty((len(dtimes),360,128))
for i, dtime in enumerate(dtimes):
f = wrl.util.get_wradlib_data_file('dx/raa00-dx_10908-{0}-fbg---bin.gz'.format(dtime))
data[i], attrs = wrl.io.read_dx(f)
return data
Read data from radar Feldberg for three consecutive 5 minute intervals and compute the accumulated rainfall depth.
In [7]:
# Read
dtimes = ["0806021735","0806021740","0806021745"]
dBZ = read_data(dtimes)
# Convert to rainfall intensity (mm/h)
Z = wrl.trafo.idecibel(dBZ)
R = wrl.zr.z_to_r(Z, a=200., b=1.6)
# Convert to rainfall depth (mm)
depth = wrl.trafo.r_to_depth(R, 300)
# Accumulate 15 minute rainfall depth over all three 5 minute intervals
accum = np.sum(depth, axis=0)
Plot PPI of 15 minute rainfall depth
In [8]:
pl.figure(figsize=(10,8))
ax, cf = wrl.vis.plot_ppi(accum, cmap="viridis")
pl.xlabel("Easting from radar (km)")
pl.ylabel("Northing from radar (km)")
pl.title("Radar Feldberg\n15 min. rainfall depth, 2008-06-02 17:30-17:45 UTC")
cb = pl.colorbar(cf, shrink=0.8)
cb.set_label("mm")
pl.xlim(-128,128)
pl.ylim(-128,128)
pl.grid(color="grey")
<Figure size 720x576 with 0 Axes>

A simple function to plot polar data in cartesian coordinate systems¶
In [1]:
import numpy as np
import matplotlib.pyplot as pl
import wradlib
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Read a polar data set from the German Weather Service¶
In [2]:
filename = wradlib.util.get_wradlib_data_file('dx/raa00-dx_10908-0806021735-fbg---bin.gz')
img, meta = wradlib.io.read_dx(filename)
Inspect the data set a little
In [3]:
print("Shape of polar array: %r\n" % (img.shape,))
print("Some meta data of the DX file:")
print("\tdatetime: %r" % (meta["datetime"],))
print("\tRadar ID: %s" % (meta["radarid"],))
Shape of polar array: (360, 128)
Some meta data of the DX file:
datetime: datetime.datetime(2008, 6, 2, 17, 35, tzinfo=<UTC>)
Radar ID: 10908
The simplest way to plot this dataset¶
In [4]:
wradlib.vis.plot_ppi(img)
txt = pl.title('Simple PPI')

Plotting just one sector¶
For this purpose, we need to give the ranges and azimuths explicitly…
In [5]:
r = np.arange(40, 81)
az = np.arange(200, 251)
ax, pm = wradlib.vis.plot_ppi(img[200:250, 40:80], r, az, autoext=False)
txt = pl.title('Sector PPI')

Notice we passed one more range value and azimuth angle as we passed actual data. Otherwise the last row and column of our data would not be plotted.
Adding a crosshair to the PPI¶
In [6]:
# We introduce a site offset...
site = (10., 45.)
wradlib.vis.plot_ppi(img, site=site)
# ... plot a crosshair over our data...
wradlib.vis.plot_ppi_crosshair(site=site, ranges=[50, 100, 128],
angles=[0, 90, 180, 270],
line=dict(color='white'),
circle={'edgecolor': 'white'})
pl.title('Offset and Custom Crosshair')
pl.axis("tight")
pl.axes().set_aspect('equal')

Placing the polar data in a projected Cartesian reference system¶
Using the proj
keyword we tell the function to: - interpret the site
coordinates as longitude/latitude - reproject the coordinates to the
given projection (here: dwd-radolan composite coordinate system)
In [7]:
site=(10., 45., 0)
proj_rad = wradlib.georef.create_osr("dwd-radolan")
ax, pm = wradlib.vis.plot_ppi(img, site=site, proj=proj_rad)
# Now the crosshair ranges must be given in meters
wradlib.vis.plot_ppi_crosshair(site=site,
ranges=[40000, 80000, 128000],
line=dict(color='white'),
circle={'edgecolor':'white'},
proj=proj_rad
)
pl.title('Georeferenced/Projected PPI')
pl.axis("tight")
pl.axes().set_aspect('equal')

Some side effects of georeferencing¶
Transplanting the radar virtually moves it away from the central meridian of the projection (which is 10 degrees east). Due north now does not point straight upwards on the map.
The crosshair shows this: for the case that the lines should actually become curved, they are implemented as a piecewise linear curve with 10 vertices. The same is true for the range circles, but with more vertices, of course.
In [8]:
site=(45., 7.)
ax, pm = wradlib.vis.plot_ppi(img, site=site, proj=proj_rad)
ax = wradlib.vis.plot_ppi_crosshair(site=site,
ranges=[64000, 128000],
line=dict(color='red'),
circle={'edgecolor': 'red'},
proj=proj_rad
)
txt = pl.title('Projection Side Effects')

More decorations and annotations¶
You can annotate these plots by using standard matplotlib methods.
In [9]:
ax, pm = wradlib.vis.plot_ppi(img)
ylabel = ax.set_xlabel('easting [km]')
ylabel = ax.set_ylabel('northing [km]')
title = ax.set_title('PPI manipulations/colorbar')
# you can now also zoom - either programmatically or interactively
xlim = ax.set_xlim(-80, -20)
ylim = ax.set_ylim(-80, 0)
# as the function returns the axes- and 'mappable'-objects colorbar needs, adding a colorbar is easy
cb = pl.colorbar(pm, ax=ax)

Plot data to curvelinear grid¶
Preface¶
If you are working with radar station data, it is almost ever only available as polar data. This means you have a 2D-array, one dimension holding the azimuth (PPI) or elevation (RHI) angle values and the other holding the range values.
In \(\omega radlib\) it is assumed that the first dimension is over the azimuth/elevation angles, while the second dimension is over the range bins.
Create Curvelinear Grid¶
The creation process of the curvelinear grid is bundled in the helper function wradlib.vis.create_cg(). I will not dwell too much on that, just this far wradlib.vis.create_cg() uses a derived Axes implementation.
wradlib.vis.create_cg() takes scan type (‘PPI’ or ‘RHI’) as argument, figure object and grid definition are optional. The grid creation process generates three axes objects and set some reasonable starting values for labeling.
The returned objects are cgax
, caax
and paax
.
cgax
: matplotlib toolkit axisartist Axes object, Curvelinear Axes which holds the angle-range-gridcaax
: matplotlib Axes object (twin to cgax), Cartesian Axes (x-y-grid) for plotting cartesian datapaax
: matplotlib Axes object (parasite to cgax), The parasite axes object for plotting polar data
A typical invocation of wradlib.vis.create_cg() for a PPI is:
# create curvelinear axes
cgax, caax, paax = create_cg('PPI', fig, subplot)
For plotting actual polar data two functions exist, depending on whether your data holds a PPI wradlib.vis.plot_ppi() or an RHI (wradlib.vis.plot_rhi()).
refrac
keyword with
wradlib.vis.plot_rhi()
the data is plotted to the cartesian axis caax
.Plotting on Curvelinear Grids¶
Plot CG PPI¶
wradlib.vis.plot_ppi()
with keyword cg=True
is used in this section.
First we will look into plotting a PPI. We start with importing the necessary modules:
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Next, we will load a polar scan from the WRADLIB_DATA folder and prepare it:
In [2]:
# load a polar scan and create range and azimuth arrays accordingly
filename = wrl.util.get_wradlib_data_file('misc/polar_dBZ_tur.gz')
data = np.loadtxt(filename)
r = np.arange(0, data.shape[1])
az = np.arange(0, data.shape[0])
# mask data array for better presentation
mask_ind = np.where(data <= np.nanmin(data))
data[mask_ind] = np.nan
ma = np.ma.array(data, mask=np.isnan(data))
For this simple example, we do not need the returned axes. The plotting routine would be invoked like this:
In [3]:
fig = pl.figure(figsize=(10,8))
wrl.vis.plot_ppi(ma, fig=fig, refrac=False, cg=True)
t = pl.title('Simple CG PPI')
t.set_y(1.05)

Decorated CG PPI¶
Now we will make use of some of the capabilities of this curvelinear axes.
You see, that for labeling x- and y-axis the cartesian axis is used. The
azimuth
label is set via :func:text
. Also a colorbar is easily
added. The plotting routine would be invoked like this, adding range and
azimuth arrays and using the autoext
feature:
In [4]:
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_ppi(ma, r, az, autoext=True,
fig=fig, refrac=False, cg=True)
caax = cgax.parasites[0]
t = pl.title('Decorated CG PPI')
t.set_y(1.05)
cbar = pl.gcf().colorbar(pm, pad=0.075)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
cbar.set_label('reflectivity [dBZ]')

And, we will use grid_helper
to set the starting value for the
curvelinear grid. This is because data at the center of the image is
obscured by the gridlines.
In [5]:
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_ppi(ma, r, az, autoext=True,
fig=fig, refrac=False, cg=True)
caax = cgax.parasites[0]
t = pl.title('Decorated CG PPI')
t.set_y(1.05)
cbar = pl.gcf().colorbar(pm, pad=0.075)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
cbar.set_label('reflectivity [dBZ]')
# set appropriate value for lat_minmax
gh = cgax.get_grid_helper()
latlim = gh.grid_finder.extreme_finder.lat_minmax
latlim = (15, latlim[1])
gh.grid_finder.extreme_finder.lat_minmax = latlim

Sector CG PPI¶
What if I want to plot only an interesting sector of the whole PPI?
Not as easy, one might think. We also can generate a so called floating
axis using the cgax
now. Here we go:
In [6]:
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_ppi(ma[200:250, 40:80],
r[40:81], az[200:251],
autoext=False, refrac=False,
fig=fig, cg=True)
caax = cgax.parasites[0]
t = pl.title('Decorated Sector CG PPI')
t.set_y(1.05)
cbar = pl.gcf().colorbar(pm, pad=0.075)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
cbar.set_label('reflectivity [dBZ]')
# add floating axis
cgax.axis["lat"] = cgax.new_floating_axis(0, 240)
cgax.axis["lat"].set_ticklabel_direction('-')
cgax.axis["lat"].label.set_text("range [km]")
cgax.axis["lat"].label.set_rotation(180)
cgax.axis["lat"].label.set_pad(10)

Special Markers¶
One more good thing about curvelinear axes is that you can plot polar as
well as cartesian data. However, you have to be careful, where to plot.
Polar data has to be plottet to the parasite axis (paax
). Cartesian
data can be plottet to caax
, although you can also plot cartesian
data to the main cgax
.
Anyway, it is easy to overlay your polar data, with other station data (e.g. gauges). Taking the former sector example, we can plot some additional stations:
In [7]:
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_ppi(ma[200:250, 40:80],
r[40:81], az[200:251],
autoext=False, refrac=False,
fig=fig, cg=True)
caax = cgax.parasites[0]
paax = cgax.parasites[1]
t = pl.title('Decorated Sector CG PPI')
t.set_y(1.05)
cbar = pl.gcf().colorbar(pm, pad=0.075)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
cbar.set_label('reflectivity [dBZ]')
cgax.axis["lat"] = cgax.new_floating_axis(0, 240)
cgax.axis["lat"].set_ticklabel_direction('-')
cgax.axis["lat"].label.set_text("range [km]")
cgax.axis["lat"].label.set_rotation(180)
cgax.axis["lat"].label.set_pad(10)
#plot on cartesian axis
caax.plot(-60, -60, 'ro', label="caax")
caax.plot(-50, -70, 'ro')
# plot on polar axis
paax.plot(220, 90, 'bo', label="paax")
# plot on cg axis (same as on cartesian axis)
cgax.plot(-50, -60, 'go', label="cgax")
# legend on main cg axis
cgax.legend()
Out[7]:
<matplotlib.legend.Legend at 0x7f1f2e16d518>

Special Specials¶
But there is more to know, when using the curvelinear grids! As an
example, you can get access to the underlying cgax
and
grid_helper
to change the azimuth and range resolution:
In [8]:
from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_ppi(ma[200:250, 40:80],
r[40:81], az[200:251],
autoext=False,
fig=fig, refrac=False, cg=True)
caax = cgax.parasites[0]
t = pl.title('Decorated Sector CG PPI')
t.set_y(1.05)
cbar = pl.gcf().colorbar(pm, pad=0.075)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
cbar.set_label('reflectivity [dBZ]')
gh = cgax.get_grid_helper()
# set azimuth resolution to 15deg
locs = [i for i in np.arange(0., 359., 5.)]
gh.grid_finder.grid_locator1 = FixedLocator(locs)
gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
gh.grid_finder.grid_locator2._nbins = 30
gh.grid_finder.grid_locator2._steps = [1, 1.5, 2, 2.5, 5, 10]
cgax.axis["lat"] = cgax.new_floating_axis(0, 240)
cgax.axis["lat"].set_ticklabel_direction('-')
cgax.axis["lat"].label.set_text("range [km]")
cgax.axis["lat"].label.set_rotation(180)
cgax.axis["lat"].label.set_pad(10)

The use of FixedLocator
and DictFormatter
should be clear. The
use of _nbins
and _steps
is a bit of head-twisting. With
_steps
you can set the possible divisions of the range. In
connection with the _nbins
the range grid is created depending on
maximum range. In the above situation with _nbins
set to 10 we get
an range grid resolution of 25 (divider 2.5). When setting steps to 20
we get a resolution of 15 (divider 1.5). Choosing 30 lead to resolution
of 10 (divider 1/10). So it may be good to play around a bit, for wanted
results.
As you might have noticed the cartesian grid remained the same and the
azimuth labels are bit overplottet. But matplotlib would be not
matplotlib if there would be no solution. First we take care of the
labeling. We push the title a bit higher to get space and toggle the
caax
labels to right and top:
t = plt.title('Very Special Sector CG PPI')
t.set_y(1.1)
caax.toggle_axisline()
Then we toggle “left” and “right” and “top” and “bottom” axis behaviour. We also have to put the colorbar a bit to the side and alter the location of the azimuth label. And, not to forgot to adapt the ticklabels of the cartesian axes. With little effort we got a better (IMHO) representation.
In [9]:
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_ppi(ma[200:250, 40:80],
r[40:81], az[200:251],
autoext=False,
fig=fig, refrac=False,
cg=True)
caax = cgax.parasites[0]
t = pl.title('Very Special Sector CG PPI')
t.set_y(1.1)
cbar = pl.gcf().colorbar(pm, pad=0.1)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
caax.toggle_axisline()
caax.grid(True)
from matplotlib.ticker import MaxNLocator
caax.xaxis.set_major_locator(MaxNLocator(15))
caax.yaxis.set_major_locator(MaxNLocator(15))
# make ticklabels of left and bottom axis visible,
cgax.axis["left"].major_ticklabels.set_visible(True)
cgax.axis["bottom"].major_ticklabels.set_visible(True)
cgax.axis["left"].get_helper().nth_coord_ticks = 0
cgax.axis["bottom"].get_helper().nth_coord_ticks = 0
# and also set tickmarklength to zero for better presentation
cgax.axis["right"].major_ticks.set_ticksize(0)
cgax.axis["top"].major_ticks.set_ticksize(0)
# make ticklabels of left and bottom axis unvisible,
# because we are drawing them
cgax.axis["right"].major_ticklabels.set_visible(False)
cgax.axis["top"].major_ticklabels.set_visible(False)
# and also set tickmarklength to zero for better presentation
cgax.axis["right"].major_ticks.set_ticksize(0)
cgax.axis["top"].major_ticks.set_ticksize(0)
pl.text(0.025, -0.065, 'azimuth', transform=caax.transAxes, va='bottom',
ha='left')
cbar.set_label('reflectivity [dBZ]')
gh = cgax.get_grid_helper()
# set azimuth resolution to 5deg
locs = [i for i in np.arange(0., 359., 5.)]
gh.grid_finder.grid_locator1 = FixedLocator(locs)
gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
#gh.grid_finder.grid_locator1 = FixedLocator([i for i in np.arange(0, 359, 5, dtype=np.int32)])
#gh.grid_finder.grid_locator1 = LocatorDMS(15)
gh.grid_finder.grid_locator2._nbins = 30
gh.grid_finder.grid_locator2._steps = [1, 1.5, 2, 2.5, 5, 10]
cgax.axis["lat"] = cgax.new_floating_axis(0, 240)
cgax.axis["lat"].set_ticklabel_direction('-')
cgax.axis["lat"].label.set_text("range [km]")
cgax.axis["lat"].label.set_rotation(180)
cgax.axis["lat"].label.set_pad(10)

Plot CG RHI¶
wradlib.vis.plot_rhi() is used in this section. An CG RHI plot is a little different compared to an CG PPI plot. I covers only one quadrant and the data is plottet counterclockwise from “east” (3 o’clock) to “north” (12 o’clock).
Everything else is much the same and you can do whatever you want as shown in the section Plot CG PPI.
So just a quick example of an cg rhi plot with some decorations. Note,
the grid_locator1
for the theta angles is overwritten and now the
grid is much finer.
In [10]:
from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
# reading in GAMIC hdf5 file
filename = wrl.util.get_wradlib_data_file('hdf5/2014-06-09--185000.rhi.mvol')
data, metadata = wrl.io.read_gamic_hdf5(filename)
data = data['SCAN0']['ZH']['data']
r = metadata['SCAN0']['r']
th = metadata['SCAN0']['el']
# mask data array for better presentation
mask_ind = np.where(data <= np.nanmin(data))
data[mask_ind] = np.nan
ma = np.ma.array(data, mask=np.isnan(data))
#----------------------------------------------------------------
# the simplest call, plot cg rhi in new window
fig = pl.figure(figsize=(10,8))
cgax, pm = wrl.vis.plot_rhi(ma, r=r, th=th, rf=1e3, refrac=False,
fig=fig, ax=111, cg=True)
caax = cgax.parasites[0]
t = pl.title('Decorated CG RHI')
t.set_y(1.05)
cgax.set_ylim(0,14)
cbar = pl.gcf().colorbar(pm, pad=0.05)
cbar.set_label('reflectivity [dBZ]')
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
gh = cgax.get_grid_helper()
# set theta to some nice values
#gh.grid_finder.grid_locator1 = FixedLocator([i for i in np.arange(0, 359, 5)])
locs = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.,
15., 16., 17., 18., 20., 22., 25., 30., 35., 40., 50., 60., 70., 80., 90.]
gh.grid_finder.grid_locator1 = FixedLocator(locs)
gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
# set starting value of range grid
gh.grid_finder.extreme_finder.lat_minmax =(2, np.inf)

Plotting on Grids¶
There are serveral possibilities to plot multiple cg plots in one figure. Since both plotting routines are equipped with the same mechanisms it is concentrated mostly on RHI plots.
Note
Using the :func:tight_layout
and :func:subplots_adjust
functions
most alignment problems can be avoided.
The Built-In Method¶
Using the matplotlib grid definition for the parameter subplot
, we
can easily plot two or more plots in one figure on a regular grid:
In [11]:
# mask data array for better presentation
mask_ind = np.where(data <= np.nanmin(data))
data[mask_ind] = np.nan
ma = np.ma.array(data, mask=np.isnan(data))
subplots = [221, 222, 223, 224]
fig = pl.figure(figsize=(10,8))
for sp in subplots:
cgax, pm = wrl.vis.plot_rhi(ma, r, th, rf=1e3, autoext=True,
refrac=False, ax=sp, cg=True)
caax.parasites=[0]
t = pl.title('CG RHI #%(sp)d' %locals())
t.set_y(1.1)
cgax.set_ylim(0, 15)
cbar = pl.gcf().colorbar(pm, pad=0.125)
caax.set_xlabel('range [km]')
caax.set_ylabel('height [km]')
gh = cgax.get_grid_helper()
# set theta to some nice values
locs = [0., 5., 10., 15., 20., 30., 40., 60., 90.]
gh.grid_finder.grid_locator1 = FixedLocator(locs)
gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
cbar.set_label('reflectivity [dBZ]')

The GridSpec Method¶
Here the abilities of Matplotlib
GridSpec are used. Now
we can also plot on irregular grids. Just create your grid and take the
GridSpec object as an input to the parameter subplot
as follows
(some padding has to be adjusted to get a nice plot):
In [12]:
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(3, 3)
subplots = [gs[0, :], gs[1, :-1], gs[1:, -1], gs[-1, 0], gs[-1, -2]]
cbarpad = [0.05, 0.075, 0.2, 0.2, 0.2]
labelpad = [1.25, 1.25, 1.1, 1.25, 1.25]
fig = pl.figure(figsize=(10,8))
for i, sp in enumerate(subplots):
cgax, pm = wrl.vis.plot_rhi(ma, r, th, rf=1e3, autoext=True,
refrac=False, ax=sp, cg=True)
caax = cgax.parasites[0]
t = pl.title('CG RHI #%(i)d' %locals())
t.set_y(labelpad[i])
cgax.set_ylim(0, 15)
cbar = pl.gcf().colorbar(pm, pad=cbarpad[i])
caax.set_xlabel('range [km]')
caax.set_ylabel('height [km]')
gh = cgax.get_grid_helper()
# set theta to some nice values
locs = [0., 5., 10., 15., 20., 30., 40., 60., 90.]
gh.grid_finder.grid_locator1 = FixedLocator(locs)
gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
cbar.set_label('reflectivity [dBZ]')
pl.tight_layout()

The AxesDivider Method¶
Here the capabilities of Matplotlib AxesGrid1 are used.
We make a PPI now, it matches much better. Just plot your PPI data and create an axes divider:
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.ticker import NullFormatter, FuncFormatter, MaxNLocator
divider = make_axes_locatable(cgax)
Now you can easily append more axes to plot some other things, eg a maximum intensity projection:
axMipX = divider.append_axes("top", size=1.2, pad=0.1, sharex=cgax))
axMipY = divider.append_axes("right", size=1.2, pad=0.1, sharey=cgax))
OK, we have to create the mip data, we use the wradlib.util.maximum_intensity_projection():
In [13]:
# angle of *cut* through ppi and scan elev.
angle = 0.0
elev = 0.0
filename = wrl.util.get_wradlib_data_file('misc/polar_dBZ_tur.gz')
data = np.loadtxt(filename)
# we need to have meter here for the georef function inside mip
d1 = np.arange(data.shape[1], dtype=np.float) * 1000
d2 = np.arange(data.shape[0], dtype=np.float)
data = np.roll(data, (d2 >= angle).nonzero()[0][0], axis=0)
# calculate max intensity proj
xs, ys, mip1 = wrl.util.maximum_intensity_projection(data, r=d1, az=d2, angle=angle, elev=elev)
xs, ys, mip2 = wrl.util.maximum_intensity_projection(data, r=d1, az=d2, angle=90+angle, elev=elev)
We also need a new formatter:
In [14]:
def mip_formatter(x, pos):
x = x / 1000.
fmt_str = '{:g}'.format(x)
if np.abs(x) > 0 and np.abs(x) < 1:
return fmt_str.replace("0", "", 1)
else:
return fmt_str
In [15]:
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.ticker import NullFormatter, FuncFormatter, MaxNLocator
fig = pl.figure(figsize=(10,8))
# normal cg plot
cgax, pm = wrl.vis.plot_ppi(data, r=d1, az=d2, refrac=True, fig=fig, cg=True)
caax = cgax.parasites[0]
cgax.set_xlim(-np.max(d1),np.max(d1))
cgax.set_ylim(-np.max(d1),np.max(d1))
caax.xaxis.set_major_formatter(FuncFormatter(mip_formatter))
caax.yaxis.set_major_formatter(FuncFormatter(mip_formatter))
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
# axes divider section
divider = make_axes_locatable(cgax)
axMipX = divider.append_axes("top", size=1.2, pad=0.1, sharex=cgax)
axMipY = divider.append_axes("right", size=1.2, pad=0.1, sharey=cgax)
# special handling for labels etc.
cgax.axis["right"].major_ticklabels.set_visible(False)
cgax.axis["top"].major_ticklabels.set_visible(False)
axMipX.xaxis.set_major_formatter(NullFormatter())
axMipX.yaxis.set_major_formatter(FuncFormatter(mip_formatter))
axMipX.yaxis.set_major_locator(MaxNLocator(5))
axMipY.yaxis.set_major_formatter(NullFormatter())
axMipY.xaxis.set_major_formatter(FuncFormatter(mip_formatter))
axMipY.xaxis.set_major_locator(MaxNLocator(5))
# plot max intensity proj
ma = np.ma.array(mip1, mask=np.isnan(mip1))
axMipX.pcolormesh(xs, ys, ma)
ma = np.ma.array(mip2, mask=np.isnan(mip2))
axMipY.pcolormesh(ys.T, xs.T, ma.T)
# set labels, limits etc
axMipX.set_xlim(-np.max(d1),np.max(d1))
er = 6370000.
axMipX.set_ylim(0, wrl.georef.bin_altitude(d1[-2], elev, 0, re=er))
axMipY.set_xlim(0, wrl.georef.bin_altitude(d1[-2], elev, 0, re=er))
axMipY.set_ylim(-np.max(d1),np.max(d1))
axMipX.set_ylabel('height [km]')
axMipY.set_xlabel('height [km]')
axMipX.grid(True)
axMipY.grid(True)
t = pl.gcf().suptitle('AxesDivider CG-MIP Example')

A one hour tour of wradlib¶
Data Input - Data Output¶
This section provides a collection of example code snippets to show which data formats \(\omega radlib\) can handle and and how to facilitate that.
Supported radar data formats¶
The binary encoding of many radar products is a major obstacle for many potential radar users. Often, decoder software is not easily available. In case formats are documented, the implementation of decoders is a major programming effort. This tutorial provides an overview of the data formats currently supported by \(\omega radlib\). We seek to continuously enhance the range of supported formats, so this document is only a snapshot. If you need a specific file format to be supported by \(\omega radlib\), please raise an issue of type enhancement. You can provide support by adding documents which help to decode the format, e.g. format reference documents or software code in other languages for decoding the format.
At the moment, supported format means that the radar format can be read and further processed by wradlib. Normally, wradlib will return an array of data values and a dictionary of metadata - if the file contains any. wradlib does not support encoding to any specific file formats, yet! This might change in the future, but it is not a priority. However, you can use Python’s netCDF4 or h5py packages to encode the results of your analysis to standard self-describing file formats such as netCDF or hdf5.
In the following, we will provide an overview of file formats which can be currently read by \(\omega radlib\).
Reading weather radar files is done via the wradlib.io module. There you will find a complete function reference.
German Weather Service: DX format¶
The German Weather Service uses the DX file format to encode local radar sweeps. DX data are in polar coordinates. The naming convention is as follows:
raa00-dx_<location-id>-<YYMMDDHHMM>-<location-abreviation>---bin
or
raa00-dx_<location-id>-<YYYYMMDDHHMM>-<location-abreviation>---bin
Read and plot DX radar data from DWD provides an extensive introduction into working with DX data. For now, we would just like to know how to read the data:
In [2]:
fpath = 'dx/raa00-dx_10908-0806021655-fbg---bin.gz'
f = wrl.util.get_wradlib_data_file(fpath)
data, metadata = wrl.io.read_dx(f)
Here, data
is a two dimensional array of shape (number of azimuth
angles, number of range gates). This means that the number of rows of
the array corresponds to the number of azimuth angles of the radar sweep
while the number of columns corresponds to the number of range gates per
ray.
In [3]:
print(data.shape)
print(metadata.keys())
(360, 128)
dict_keys(['producttype', 'datetime', 'radarid', 'bytes', 'version', 'cluttermap', 'dopplerfilter', 'statfilter', 'elevprofile', 'message', 'elev', 'azim', 'clutter'])
In [4]:
fig = pl.figure(figsize=(10,8))
im = wrl.vis.plot_ppi(data, fig=fig, cg=True)

German Weather Service: RADOLAN (quantitative) composit¶
The quantitative composite format of the DWD (German Weather Service) was established in the course of the RADOLAN project. Most quantitative composite products from the DWD are distributed in this format, e.g. the R-series (RX, RY, RH, RW, …), the S-series (SQ, SH, SF, …), and the E-series (European quantitative composite, e.g. EZ, EH, EB). Please see the composite format description for a full reference and a full table of products (unfortunately only in German language). An extensive section covering many RADOLAN aspects is here: RADOLAN
Currently, the RADOLAN composites have a spatial resolution of 1km x 1km, with the national composits (R- and S-series) being 900 x 900 grids, and the European composits 1500 x 1400 grids. The projection is polar-stereographic. The products can be read by the following function:
In [5]:
fpath = 'radolan/misc/raa01-rw_10000-1408102050-dwd---bin.gz'
f = wrl.util.get_wradlib_data_file(fpath)
data, metadata = wrl.io.read_radolan_composite(f)
Here, data
is a two dimensional integer array of shape (number of
rows, number of columns). Different product types might need different
levels of postprocessing, e.g. if the product contains rain rates or
accumulations, you will normally have to divide data by factor 10.
metadata
is again a dictionary which provides metadata from the
files header section, e.g. using the keys producttype, datetime,
intervalseconds, nodataflag.
In [6]:
print(data.shape)
print(metadata.keys())
(900, 900)
dict_keys(['producttype', 'datetime', 'radarid', 'datasize', 'maxrange', 'radolanversion', 'precision', 'intervalseconds', 'nrow', 'ncol', 'radarlocations', 'nodataflag', 'secondary', 'cluttermask'])
Masking the NoData (or missing) values can be done by:
In [7]:
maskeddata = np.ma.masked_equal(data,
metadata["nodataflag"])
In [8]:
fig = pl.figure(figsize=(10,8))
# get coordinates
radolan_grid_xy = wrl.georef.get_radolan_grid(900,900)
x = radolan_grid_xy[:,:,0]
y = radolan_grid_xy[:,:,1]
# create quick plot with colorbar and title
pl.figure(figsize=(10,8))
pl.pcolormesh(x, y, maskeddata)
Out[8]:
<matplotlib.collections.QuadMesh at 0x7ff1e85e9198>
<Figure size 720x576 with 0 Axes>

HDF5¶
OPERA HDF5 (ODIM_H5)¶
HDF5 is a data model, library, and file format for storing and managing data. The OPERA 3 program developed a convention (or information model) on how to store and exchange radar data in hdf5 format. It is based on the work of COST Action 717 and is used e.g. in real-time operations in the Nordic European countries. The OPERA Data and Information Model (ODIM) is documented e.g. in this report. Make use of these documents in order to understand the organization of OPERA hdf5 files!
The hierarchical nature of HDF5 can be described as being similar to
directories, files, and links on a hard-drive. Actual metadata are
stored as so-called attributes, and these attributes are organized
together in so-called groups. Binary data are stored as so-called
datasets. As for ODIM_H5, the root
(or top level) group contains
three groups of metadata: these are called what
(object, information
model version, and date/time information), where
(geographical
information), and how
(quality and optional/recommended metadata).
For a very simple product, e.g. a CAPPI, the data is organized in a
group called dataset1
which contains another group called data1
where the actual binary data are found in data
. In analogy with a
file system on a hard-disk, the HDF5 file containing this simple product
is organized like this:
/
/what
/where
/how
/dataset1
/dataset1/data1
/dataset1/data1/data
The philosophy behind the \(\omega radlib\) interface to OPERA’s
data model is very straightforward: \(\omega radlib\) simply
translates the complete file structure to one dictionary and returns
this dictionary to the user. Thus, the potential complexity of the
stored data is kept and it is left to the user how to proceed with this
data. The keys of the output dictionary are strings that correspond to
the “directory trees” shown above. Each key ending with /data
points
to a Dataset (i.e. a numpy array of data). Each key ending with
/what
, /where
or /how
points to another dictionary of
metadata. The entire output can be obtained by:
In [9]:
fpath = 'hdf5/knmi_polar_volume.h5'
f = wrl.util.get_wradlib_data_file(fpath)
fcontent = wrl.io.read_opera_hdf5(f)
The user should inspect the output obtained from his or her hdf5 file in order to see how access those items which should be further processed. In order to get a readable overview of the output dictionary, one can use the pretty printing module:
In [10]:
# which keyswords can be used to access the content?
print(fcontent.keys())
# print the entire content including values of data and metadata
# (numpy arrays will not be entirely printed)
print(fcontent['dataset1/data1/data'])
dict_keys(['dataset1/data1/data', 'dataset1/data1/what', 'dataset1/what', 'dataset1/where', 'dataset10/data1/data', 'dataset10/data1/what', 'dataset10/what', 'dataset10/where', 'dataset11/data1/data', 'dataset11/data1/what', 'dataset11/what', 'dataset11/where', 'dataset12/data1/data', 'dataset12/data1/what', 'dataset12/what', 'dataset12/where', 'dataset13/data1/data', 'dataset13/data1/what', 'dataset13/what', 'dataset13/where', 'dataset14/data1/data', 'dataset14/data1/what', 'dataset14/what', 'dataset14/where', 'dataset2/data1/data', 'dataset2/data1/what', 'dataset2/what', 'dataset2/where', 'dataset3/data1/data', 'dataset3/data1/what', 'dataset3/what', 'dataset3/where', 'dataset4/data1/data', 'dataset4/data1/what', 'dataset4/what', 'dataset4/where', 'dataset5/data1/data', 'dataset5/data1/what', 'dataset5/what', 'dataset5/where', 'dataset6/data1/data', 'dataset6/data1/what', 'dataset6/what', 'dataset6/where', 'dataset7/data1/data', 'dataset7/data1/what', 'dataset7/what', 'dataset7/where', 'dataset8/data1/data', 'dataset8/data1/what', 'dataset8/what', 'dataset8/where', 'dataset9/data1/data', 'dataset9/data1/what', 'dataset9/what', 'dataset9/where', 'what', 'where'])
[[107 97 47 ... 0 0 0]
[111 112 45 ... 0 0 0]
[134 147 87 ... 0 0 0]
...
[109 91 37 ... 0 0 0]
[109 91 45 ... 0 0 0]
[107 100 40 ... 0 0 0]]
Please note that in order to experiment with such datasets, you can download hdf5 sample data from the OPERA or use the example data provided with the wradlib-data repository.
In [11]:
fig = pl.figure(figsize=(10,8))
im = wrl.vis.plot_ppi(fcontent['dataset1/data1/data'], fig=fig, cg=True)

GAMIC HDF5¶
GAMIC refers to the commercial GAMIC Enigma MURAN software which exports data in hdf5 format. The concept is quite similar to the above OPERA HDF5 (ODIM_H5) format. Such a file (typical ending: .mvol) can be read by:
In [12]:
fpath = 'hdf5/2014-08-10--182000.ppi.mvol'
f = wrl.util.get_wradlib_data_file(fpath)
data, metadata = wrl.io.read_gamic_hdf5(f)
While metadata represents the usual dictionary of metadata, the data variable is a dictionary which might contain several numpy arrays with the keywords of the dictionary indicating different moments.
In [13]:
print(metadata.keys())
print(metadata['VOL'])
print(metadata['SCAN0'].keys())
dict_keys(['SCAN0', 'VOL'])
{'Latitude': 50.73052, 'Longitude': 7.071663, 'Height': 99.5}
dict_keys(['bin_count', 'range_start', 'scan_speed', 'range', 'range_step', 'range_samples', 'PRF', 'time_samples', 'angle_step', 'unfolding', 'pulse_width', 'filter', 'angle_sync', 'radar_wave_length', 'output64', 'half_resolution', 'ray_count', 'azi_start', 'azi_stop', 'elevation', 'bin_range', 'zero_index', 'az', 'el', 'r', 'Time', 'max_range'])
In [14]:
print(data['SCAN0'].keys())
print(data['SCAN0']['PHIDP'].keys())
print(data['SCAN0']['PHIDP']['data'].shape)
dict_keys(['KDP', 'PHIDP', 'ZH', 'ZV', 'RHOHV', 'UH', 'UV', 'VH', 'VV', 'WH', 'WV', 'ZDR'])
dict_keys(['data', 'dyn_range_max', 'dyn_range_min'])
(360, 1000)
In [15]:
fig = pl.figure(figsize=(10,8))
im = wrl.vis.plot_ppi(data['SCAN0']['ZH']['data'], fig=fig, cg=True)

Generic HDF5¶
This is a generic hdf5 reader, which will read any hdf5 structure.
In [16]:
fpath = 'hdf5/2014-08-10--182000.ppi.mvol'
f = wrl.util.get_wradlib_data_file(fpath)
fcontent = wrl.io.read_generic_hdf5(f)
In [17]:
print(fcontent.keys())
dict_keys(['how', 'scan0/how', 'scan0/how/extended', 'scan0/moment_0', 'scan0/moment_1', 'scan0/moment_10', 'scan0/moment_11', 'scan0/moment_2', 'scan0/moment_3', 'scan0/moment_4', 'scan0/moment_5', 'scan0/moment_6', 'scan0/moment_7', 'scan0/moment_8', 'scan0/moment_9', 'scan0/ray_header', 'scan0/what', 'what', 'where'])
In [18]:
print(fcontent['where'])
print(fcontent['how'])
print(fcontent['scan0/moment_3'].keys())
print(fcontent['scan0/moment_3']['attrs'])
print(fcontent['scan0/moment_3']['data'].shape)
{'attrs': {'lon': 7.071663, 'lat': 50.73052, 'height': 99.5}}
{'attrs': {'software': b'MURAN', 'template_name': b'ppi_1p5deg', 'site_name': b'12345', 'host_name': b'radar.meteo.uni-bonn.de', 'elevation_beam': 1.0, 'azimuth_beam': 1.0, 'sdp_name': b'ENIGMA III DUALPOL'}}
dict_keys(['attrs', 'data'])
{'moment': b'UH', 'format': b'UV8', 'dyn_range_max': 95.5, 'dyn_range_min': -32.0}
(360, 1000)
In [19]:
fig = pl.figure(figsize=(10,8))
im = wrl.vis.plot_ppi(fcontent['scan0/moment_3']['data'], fig=fig, cg=True)

NetCDF¶
The NetCDF format also claims to be self-describing. However, as for all such formats, the developers of netCDF also admit that “[…] the mere use of netCDF is not sufficient to make data self-describing and meaningful to both humans and machines […]” (see here. Different radar operators or data distributors will use different naming conventions and data hierarchies (i.e. “data models”) that the reading program might need to know about.
\(\omega radlib\) provides two solutions to address this challenge. The first one ignores the concept of data models and just pulls all data and metadata from a NetCDF file (wradlib.io.read_generic_netcdf(). The second is designed for a specific data model used by the EDGE software (wradlib.io.read_edge_netcdf()).
Generic NetCDF reader (includes CfRadial)¶
\(\omega radlib\) provides a function that will virtually read any NetCDF file irrespective of the data model: wradlib.io.read_generic_netcdf(). It is built upon Python’s netcdf4 library. wradlib.io.read_generic_netcdf() will return only one object, a dictionary, that contains all the contents of the NetCDF file corresponding to the original file structure. This includes all the metadata, as well as the so called “dimensions” (describing the dimensions of the actual data arrays) and the “variables” which will contains the actual data. Users can use this dictionary at will in order to query data and metadata; however, they should make sure to consider the documentation of the corresponding data model. wradlib.io.read_generic_netcdf() has been shown to work with a lot of different data models, most notably CfRadial (see here for details). A typical call to wradlib.io.read_generic_netcdf() would look like:
In [20]:
fpath = 'netcdf/example_cfradial_ppi.nc'
f = wrl.util.get_wradlib_data_file(fpath)
outdict = wrl.io.read_generic_netcdf(f)
for key in outdict.keys():
print(key)
comment
title
Conventions
source
version
references
instrument_name
institution
field_names
history
dimensions
variables
Please see this example notebook to get started.
EDGE NetCDF¶
EDGE is a commercial software for radar control and data analysis provided by the Enterprise Electronics Corporation. It allows for netCDF data export. The resulting files can be read by wradlib.io.read_generic_netcdf(), but \(\omega radlib\) also provides a specific function, wradlib.io.read_edge_netcdf() to return metadata and data as seperate objects:
In [21]:
fpath = 'netcdf/edge_netcdf.nc'
f = wrl.util.get_wradlib_data_file(fpath)
data, metadata = wrl.io.read_edge_netcdf(f)
print(data.shape)
print(metadata.keys())
(360, 240)
dict_keys(['TypeName', 'DataType', 'Latitude', 'Longitude', 'Height', 'FractionalTime', 'attributes', 'NyquistVelocity-unit', 'NyquistVelocity-value', 'vcp-unit', 'vcp-value', 'radarName-unit', 'radarName-value', 'ColorMap-unit', 'ColorMap-value', 'Elevation', 'ElevationUnits', 'MissingData', 'RangeFolded', 'RadarParameters', 'PRF-unit', 'PRF-value', 'PulseWidth-unit', 'PulseWidth-value', 'MaximumRange-unit', 'MaximumRange-value', 'ConversionPlugin', 'az', 'r', 'sitecoords', 'time', 'max_range'])
Gematronik Rainbow¶
Rainbow refers to the commercial RAINBOW®5 APPLICATION SOFTWARE which exports data in an XML flavour, which due to binary data blobs violates XML standard. Gematronik provided python code for implementing this reader in \(\omega radlib\), which is very much appreciated.
The philosophy behind the \(\omega radlib\) interface to Gematroniks
data model is very straightforward: \(\omega radlib\) simply
translates the complete xml file structure to one dictionary and
returns this dictionary to the user. Thus, the potential complexity of
the stored data is kept and it is left to the user how to proceed with
this data. The keys of the output dictionary are strings that correspond
to the “xml nodes” and “xml attributes”. Each data
key points to a
Dataset (i.e. a numpy array of data). Such a file (typical ending:
.vol or .azi) can be read by:
In [22]:
fpath = 'rainbow/2013070308340000dBuZ.azi'
f = wrl.util.get_wradlib_data_file(fpath)
fcontent = wrl.io.read_rainbow(f)
The user should inspect the output obtained from his or her Rainbow file in order to see how access those items which should be further processed. In order to get a readable overview of the output dictionary, one can use the pretty printing module:
In [23]:
# which keyswords can be used to access the content?
print(fcontent.keys())
# print the entire content including values of data and metadata
# (numpy arrays will not be entirely printed)
print(fcontent['volume']['sensorinfo'])
odict_keys(['volume'])
OrderedDict([('@type', 'rainscanner'), ('@id', 'WUE'), ('@name', 'Wuestebach'), ('lon', '6.330970'), ('lat', '50.504900'), ('alt', '0.000000'), ('wavelen', '0.05'), ('beamwidth', '1')])
You can check this example notebook for getting a first impression.
Vaisala Sigmet IRIS¶
IRIS refers to the commercial Vaisala Sigmet Interactive Radar Information System. The Vaisala Sigmet Digital Receivers export data in a well documented binary format.
The philosophy behind the \(\omega radlib\) interface to the IRIS data model is very straightforward: \(\omega radlib\) simply translates the complete binary file structure to one dictionary and returns this dictionary to the user. Thus, the potential complexity of the stored data is kept and it is left to the user how to proceed with this data. The keys of the output dictionary are strings that correspond to the Sigmet Data Structures.
Each data
key points to a Dataset (i.e. a numpy array of data). Such
a file (typical ending: *.RAWXXXX) can be read by:
In [24]:
fpath = 'sigmet/cor-main131125105503.RAW2049'
f = wrl.util.get_wradlib_data_file(fpath)
fcontent = wrl.io.read_iris(f)
In [25]:
# which keyswords can be used to access the content?
print(fcontent.keys())
# print the entire content including values of data and
# metadata of the first sweep
# (numpy arrays will not be entirely printed)
print(fcontent['data'][1])
odict_keys(['product_hdr', 'product_type', 'ingest_header', 'nsweeps', 'nrays', 'nbins', 'data_types', 'data', 'raw_product_bhdrs'])
OrderedDict([('ingest_data_hdrs', OrderedDict([('DB_DBZ', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 2)])), ('DB_VEL', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 3)])), ('DB_ZDR', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 5)])), ('DB_KDP', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 14)])), ('DB_PHIDP', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 16)])), ('DB_RHOHV', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 19)])), ('DB_HCLASS', OrderedDict([('structure_header', OrderedDict([('structure_identifier', 24), ('format_version', 3), ('bytes_in_structure', 244876), ('flag', 1)])), ('sweep_start_time', datetime.datetime(2013, 11, 25, 10, 55, 5, 589000)), ('sweep_number', 1), ('number_rays_per_sweep', 360), ('first_ray_index', 0), ('number_rays_file_expected', 360), ('number_rays_file_written', 360), ('fixed_angle', 0.4998779296875), ('bits_per_bin', 8), ('data_type', 55)]))])), ('sweep_data', OrderedDict([('DB_DBZ', OrderedDict([('data', array([[-32. , 3.5, 6. , ..., -32. , -32. , -32. ],
[-20.5, -32. , -32. , ..., -32. , -32. , -32. ],
[-32. , -32. , -32. , ..., -32. , -32. , -32. ],
...,
[-32. , -32. , -32. , ..., -32. , -32. , -32. ],
[-32. , -32. , -32. , ..., -32. , -32. , -32. ],
[-20. , -32. , -32. , ..., -32. , -32. , -32. ]])), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))])), ('DB_VEL', OrderedDict([('data', array([[-6.71496063, -6.71496063, -6.71496063, ..., -6.71496063,
-6.71496063, -6.71496063],
[-6.71496063, -6.71496063, -6.71496063, ..., -6.71496063,
-6.71496063, -6.71496063],
[-6.71496063, -6.71496063, -6.71496063, ..., -6.71496063,
-6.71496063, -6.71496063],
...,
[-6.71496063, -6.71496063, -6.71496063, ..., -6.71496063,
-6.71496063, -6.71496063],
[-6.71496063, -6.71496063, -6.71496063, ..., -6.71496063,
-6.71496063, -6.71496063],
[-6.71496063, -6.71496063, -6.71496063, ..., -6.71496063,
-6.71496063, -6.71496063]])), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))])), ('DB_ZDR', OrderedDict([('data', array([[-7.9375, -7.9375, 4.375 , ..., -8. , -8. , -8. ],
[-7.9375, 4.1875, -7.9375, ..., -8. , -8. , -8. ],
[-7.9375, -7.9375, -7.9375, ..., -8. , -8. , -8. ],
...,
[-7.9375, -7.9375, -7.9375, ..., -8. , -8. , -8. ],
[-7.9375, -7.9375, -3.5 , ..., -8. , -8. , -8. ],
[-7.9375, -6.6875, -7.9375, ..., -8. , -8. , -8. ]])), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))])), ('DB_KDP', OrderedDict([('data', array([[-0. , 0.04458246, 0.04458246, ..., -0. ,
-0. , -0. ],
[-0. , -0. , -0. , ..., -0. ,
-0. , -0. ],
[-0. , -0. , -0. , ..., -0. ,
-0. , -0. ],
...,
[-0. , -0. , -0. , ..., -0. ,
-0. , -0. ],
[-0. , -0. , -0. , ..., -0. ,
-0. , -0. ],
[-0. , -0. , -0. , ..., -0. ,
-0. , -0. ]])), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))])), ('DB_PHIDP', OrderedDict([('data', array([[-0.70866142, -0.70866142, -0.70866142, ..., -0.70866142,
-0.70866142, -0.70866142],
[-0.70866142, -0.70866142, -0.70866142, ..., -0.70866142,
-0.70866142, -0.70866142],
[-0.70866142, -0.70866142, -0.70866142, ..., -0.70866142,
-0.70866142, -0.70866142],
...,
[-0.70866142, -0.70866142, -0.70866142, ..., -0.70866142,
-0.70866142, -0.70866142],
[-0.70866142, -0.70866142, -0.70866142, ..., -0.70866142,
-0.70866142, -0.70866142],
[-0.70866142, -0.70866142, -0.70866142, ..., -0.70866142,
-0.70866142, -0.70866142]])), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))])), ('DB_RHOHV', OrderedDict([('data', array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]])), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))])), ('DB_HCLASS', OrderedDict([('data', array([[4361, 4369, 4369, ..., 0, 0, 0],
[4361, 4369, 2321, ..., 0, 0, 0],
[4369, 4369, 4369, ..., 0, 0, 0],
...,
[4369, 4369, 4352, ..., 0, 0, 0],
[4361, 4361, 4369, ..., 0, 0, 0],
[4369, 4369, 4369, ..., 0, 0, 0]], dtype=int16)), ('azi_start', array([359.54406738, 0.69763184, 1.66442871, 2.45544434,
3.79577637, 4.37255859, 5.86669922, 6.49291992,
7.71240234, 8.63525391, 9.48669434, 10.51391602,
11.6015625 , 12.61230469, 13.57910156, 14.61730957,
15.61157227, 16.57287598, 17.578125 , 18.63830566,
19.52270508, 20.63781738, 21.55517578, 22.39562988,
23.74145508, 24.79614258, 25.59265137, 26.27929688,
27.50976562, 28.54797363, 29.61914062, 30.60791016,
31.61865234, 32.50305176, 33.58520508, 34.71130371,
35.60668945, 36.48010254, 37.80944824, 38.60595703,
39.32556152, 40.63842773, 41.53930664, 42.61047363,
43.68713379, 44.57702637, 45.4119873 , 46.8347168 ,
47.64221191, 48.39477539, 49.52087402, 50.57556152,
51.67419434, 52.39929199, 53.49243164, 54.7064209 ,
55.44250488, 56.60705566, 57.42553711, 58.4967041 ,
59.72717285, 60.43029785, 61.5838623 , 62.58911133,
63.62731934, 64.52270508, 65.57189941, 66.5057373 ,
67.8515625 , 68.4173584 , 69.60388184, 70.6640625 ,
71.31774902, 72.80090332, 73.51501465, 74.54223633,
75.74523926, 76.63513184, 77.49755859, 78.59069824,
79.47509766, 80.75500488, 81.59545898, 82.51281738,
83.69934082, 84.44091797, 85.69885254, 86.58325195,
87.63244629, 88.53881836, 89.69787598, 90.45593262,
91.62597656, 92.64770508, 93.47717285, 94.54284668,
95.60852051, 96.58630371, 97.60253906, 98.61877441,
99.51965332, 100.60180664, 101.6015625 , 102.56286621,
103.62304688, 104.63378906, 105.59509277, 106.47399902,
107.60559082, 108.56140137, 109.46228027, 110.58288574,
111.53869629, 112.70874023, 113.51623535, 114.59289551,
115.52124023, 116.54846191, 117.66357422, 118.58642578,
119.61364746, 120.53100586, 121.66809082, 122.39868164,
123.55773926, 124.62890625, 125.61218262, 126.48010254,
127.5567627 , 128.5949707 , 129.62768555, 130.57250977,
131.61071777, 132.65991211, 133.47290039, 134.69238281,
135.63720703, 136.50512695, 137.58178711, 138.5925293 ,
139.52636719, 140.59204102, 141.58630371, 142.61901855,
143.59130859, 144.53613281, 145.65673828, 146.50268555,
147.62329102, 148.5736084 , 149.56787109, 150.60058594,
151.59484863, 152.59460449, 153.58337402, 154.56665039,
155.56640625, 156.61010742, 157.5604248 , 158.70300293,
159.49401855, 160.65856934, 161.51550293, 162.68005371,
163.50952148, 164.58618164, 165.55847168, 166.35498047,
167.70629883, 168.43139648, 169.70031738, 170.54626465,
171.57348633, 172.59521484, 173.50158691, 174.56726074,
175.62194824, 176.67114258, 177.4017334 , 178.64318848,
179.5111084 , 180.6427002 , 181.58752441, 182.68615723,
183.515625 , 184.41101074, 185.61950684, 186.41052246,
187.63549805, 188.58032227, 189.5690918 , 190.53588867,
191.6619873 , 192.5958252 , 193.57910156, 194.55688477,
195.58410645, 196.75964355, 197.46276855, 198.78112793,
199.47875977, 200.49499512, 201.61010742, 202.69226074,
203.33496094, 204.62585449, 205.53771973, 206.59790039,
207.59216309, 208.60290527, 209.5916748 , 210.70678711,
211.43737793, 212.67883301, 213.4588623 , 214.66186523,
215.61218262, 216.43615723, 217.87536621, 218.39172363,
219.55627441, 220.62194824, 221.57775879, 222.57202148,
223.73657227, 224.38476562, 225.7800293 , 226.46118164,
227.62573242, 228.64196777, 229.63623047, 230.67443848,
231.38305664, 232.57507324, 233.80554199, 234.63500977,
235.49743652, 236.49169922, 237.54089355, 238.66149902,
239.6282959 , 240.7598877 , 241.33666992, 242.67700195,
243.48999023, 244.56115723, 245.59936523, 246.62109375,
247.44506836, 248.66455078, 249.65332031, 250.64208984,
251.5045166 , 252.60314941, 253.71826172, 254.48730469,
255.48156738, 256.60217285, 257.73925781, 258.66760254,
259.70581055, 260.35949707, 261.71081543, 262.57873535,
263.69384766, 264.53430176, 265.52307129, 266.67663574,
267.55004883, 268.47290039, 269.90661621, 270.44494629,
271.6809082 , 272.35656738, 273.80126953, 274.4934082 ,
275.61950684, 276.7401123 , 277.22351074, 278.58032227,
279.59655762, 280.54138184, 281.67297363, 282.53540039,
283.4197998 , 284.53491211, 285.46875 , 286.75415039,
287.69348145, 288.70422363, 289.36889648, 290.6817627 ,
291.47827148, 292.68127441, 293.4942627 , 294.63684082,
295.79040527, 296.43310547, 297.49328613, 298.72375488,
299.55871582, 300.62438965, 301.63513184, 302.31079102,
303.59069824, 304.44213867, 305.85388184, 306.43066406,
307.72705078, 308.36975098, 309.67712402, 310.41320801,
311.75354004, 312.5390625 , 313.61572266, 314.60998535,
315.57678223, 316.50512695, 317.79052734, 318.48815918,
319.35058594, 320.57006836, 321.36108398, 322.734375 ,
323.60778809, 324.7668457 , 325.33813477, 326.7388916 ,
327.41455078, 328.68896484, 329.75463867, 330.48522949,
331.50146484, 332.59460449, 333.48449707, 334.74243164,
335.4675293 , 336.76391602, 337.62084961, 338.30749512,
339.41162109, 340.64208984, 341.61437988, 342.59216309,
343.86108398, 344.33349609, 345.50354004, 346.72851562,
347.53051758, 348.68408203, 349.55200195, 350.46936035,
351.60644531, 352.40844727, 353.89709473, 354.41345215,
355.77575684, 356.35803223, 357.57751465, 358.45092773])), ('ele_start', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('azi_stop', array([ 0.49987793, 1.57104492, 2.51586914, 3.52661133,
4.51538086, 5.52062988, 6.52038574, 7.51464844,
8.4979248 , 9.50866699, 10.51391602, 11.51916504,
12.52441406, 13.51867676, 14.5513916 , 15.51818848,
16.51794434, 17.51220703, 18.51745605, 19.52270508,
20.52246094, 21.50024414, 22.50549316, 23.51074219,
24.5324707 , 25.51025391, 26.71325684, 27.52624512,
28.52050781, 29.52026367, 30.53649902, 31.53076172,
32.50305176, 33.52478027, 34.50256348, 35.51330566,
36.51306152, 37.52929688, 38.50158691, 39.71008301,
40.51757812, 41.50634766, 42.51708984, 43.52233887,
44.52209473, 45.52185059, 46.52709961, 47.51586914,
48.515625 , 49.52087402, 50.51513672, 51.49841309,
52.55859375, 53.51989746, 54.49768066, 55.50292969,
56.50268555, 57.50793457, 58.53515625, 59.52941895,
60.50720215, 61.51245117, 62.50671387, 63.51196289,
64.52270508, 65.50598145, 66.5057373 , 67.50549316,
68.59863281, 69.51599121, 70.51574707, 71.5045166 ,
72.4987793 , 73.51501465, 74.51477051, 75.58044434,
76.51977539, 77.49755859, 78.5357666 , 79.5135498 ,
80.52978516, 81.5020752 , 82.51281738, 83.51806641,
84.52331543, 85.50109863, 86.52282715, 87.51159668,
88.51135254, 89.5111084 , 90.50537109, 91.51062012,
92.49938965, 93.50463867, 94.51538086, 95.51513672,
96.52038574, 97.50915527, 98.4979248 , 99.51965332,
100.50842285, 101.51367188, 102.52441406, 103.50769043,
104.51843262, 105.50720215, 106.50146484, 107.50671387,
108.50097656, 109.52270508, 110.50598145, 111.5057373 ,
112.50549316, 113.51623535, 114.50500488, 115.52124023,
116.51550293, 117.50427246, 118.52600098, 119.52026367,
120.5090332 , 121.51977539, 122.51403809, 123.50830078,
124.50256348, 125.50231934, 126.50756836, 127.50183105,
128.50708008, 129.5123291 , 130.51208496, 131.51733398,
132.51159668, 133.51135254, 134.50561523, 135.51635742,
136.50512695, 137.5213623 , 138.50463867, 139.49890137,
140.50964355, 141.49841309, 142.49816895, 143.56384277,
144.50317383, 145.50292969, 146.50268555, 147.50244141,
148.51867676, 149.50744629, 150.51818848, 151.51245117,
152.51220703, 153.51745605, 154.51171875, 155.50598145,
156.51672363, 157.5 , 158.52172852, 159.52148438,
160.51574707, 161.51550293, 162.4987793 , 163.50952148,
164.49829102, 165.50354004, 166.50878906, 167.50854492,
168.50280762, 169.50256348, 170.51879883, 171.51306152,
172.52929688, 173.50158691, 174.50134277, 175.5065918 ,
176.50634766, 177.64343262, 178.52233887, 179.5111084 ,
180.52185059, 181.51611328, 182.49938965, 183.515625 ,
184.49890137, 185.49865723, 186.51489258, 187.53112793,
188.5144043 , 189.50866699, 190.50842285, 191.5246582 ,
192.50244141, 193.51867676, 194.52392578, 195.51818848,
196.51794434, 197.51220703, 198.52294922, 199.50622559,
200.52246094, 201.51123047, 202.51098633, 203.62060547,
204.50500488, 205.50476074, 206.51000977, 207.52624512,
208.50402832, 209.50927734, 210.49804688, 211.5032959 ,
212.52502441, 213.51379395, 214.50805664, 215.5078125 ,
216.60644531, 217.53479004, 218.50708008, 219.52331543,
220.50109863, 221.52282715, 222.51708984, 223.50585938,
224.50561523, 225.52185059, 226.51611328, 227.50488281,
228.52661133, 229.60327148, 230.49865723, 231.51489258,
232.50915527, 233.5144043 , 234.50317383, 235.49743652,
236.51367188, 237.50244141, 238.52966309, 239.50744629,
240.51269531, 241.51794434, 242.51220703, 243.51745605,
244.50622559, 245.50048828, 246.5057373 , 247.5 ,
248.52722168, 249.49951172, 250.52124023, 251.5045166 ,
252.51525879, 253.50952148, 254.50927734, 255.51452637,
256.50878906, 257.50854492, 258.63464355, 259.50805664,
260.5078125 , 261.51306152, 262.51831055, 263.51806641,
264.5123291 , 265.52307129, 266.52282715, 267.52258301,
268.50036621, 269.52758789, 270.51635742, 271.51062012,
272.51037598, 273.49914551, 274.53186035, 275.52062988,
276.52587891, 277.68493652, 278.50891113, 279.50866699,
280.50842285, 281.51367188, 282.50793457, 283.50769043,
284.51843262, 285.5291748 , 286.51794434, 287.62756348,
288.52844238, 289.50073242, 290.51696777, 291.5057373 ,
292.52746582, 293.52722168, 294.50500488, 295.51025391,
296.69677734, 297.52075195, 298.52600098, 299.50927734,
300.51452637, 301.5032959 , 302.51953125, 303.49731445,
304.52453613, 305.51330566, 306.57348633, 307.50732422,
308.51806641, 309.50134277, 310.52307129, 311.51184082,
312.51159668, 313.51135254, 314.51660156, 315.51635742,
316.50512695, 317.50488281, 318.515625 , 319.50439453,
320.50964355, 321.52038574, 322.49816895, 323.5144043 ,
324.53063965, 325.72265625, 326.50817871, 327.5189209 ,
328.51867676, 329.56237793, 330.51269531, 331.50146484,
332.52868652, 333.50646973, 334.52270508, 335.56640625,
336.53320312, 337.51098633, 338.71398926, 339.49951172,
340.51025391, 341.52648926, 342.52075195, 343.50952148,
344.75097656, 345.5090332 , 346.50878906, 347.49755859,
348.58520508, 349.50256348, 350.52429199, 351.50756836,
352.51831055, 353.51806641, 354.61120605, 355.51208496,
356.51184082, 357.51159668, 358.52233887, 359.5111084 ])), ('ele_stop', array([0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527,
0.47790527, 0.47790527, 0.47790527, 0.47790527, 0.47790527])), ('rbins', array([664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
664, 664, 664, 664, 664, 664, 664, 664, 664], dtype=int16)), ('dtime', array([11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11], dtype=int16))]))]))])
OPERA BUFR¶
WARNING \(\omega radlib\) does currently not support the BUFR format!
The Binary Universal Form for the Representation of meteorological data (BUFR) is a binary data format maintained by the World Meteorological Organization (WMO).
The BUFR format was adopted by OPERA for the representation of weather radar data. A BUFR file consists of a set of descriptors which contain all the relevant metadata and a data section. The descriptors are identified as a tuple of three integers. The meaning of these tupels is described in the so-called BUFR tables. There are generic BUFR tables provided by the WMO, but it is also possible to define so called local tables - which was done by the OPERA consortium for the purpose of radar data representation.
If you want to use BUFR files together with \(\omega radlib\), we recommend that you check out the OPERA webpage where you will find software for BUFR decoding. In particular, you might want to check out this tool which seems to support the conversion of OPERA BUFR files to ODIM_H5 (which is supported by \(\omega radlib\)). However, you have to build it yourself.
It would be great if someone could add a tutorial on how to use OPERA BUFR software together with \(\omega radlib\)!
Handling DX Radar Data (German Weather Service)¶
This tutorial helps you to read and plot the raw polar radar data provided by German Weather Service (DWD).
Reading DX-Data¶
The German weather service provides polar radar data in the so called
DX
format. These have to be unpacked and transfered into an array of
360 (azimuthal resolution of 1 degree) by 128 (range resolution of 1
km).
The naming convention for DX data is:
raa00-dx_<location-id>-<YYMMDDHHMM>-<location-abreviation>---bin
or
raa00-dx_<location-id>-<YYYYMMDDHHMM>-<location-abreviation>---bin
For example: raa00-dx_10908-200608281420-fbg---bin
raw data from
radar station Feldberg (fbg, 10908) from 2006-08-28 14:20:00.
Each DX file also contains additional information like the elevation angle for each beam. Note, however, that the format is not “self-describing”.
Raw data for one time step¶
Suppose we want to read a radar-scan for a defined time step. You need to make sure that the data file is given with the correct path to the file. The read_dx function returns two variables: the reflectivity array, and a dictionary of metadata attributes.
In [2]:
filename = wrl.util.get_wradlib_data_file('dx/raa00-dx_10908-200608281420-fbg---bin.gz')
one_scan, attributes = wrl.io.read_dx(filename)
print(one_scan.shape)
print(attributes.keys())
print(attributes['radarid'])
(360, 128)
dict_keys(['producttype', 'datetime', 'radarid', 'bytes', 'version', 'cluttermap', 'dopplerfilter', 'statfilter', 'elevprofile', 'message', 'elev', 'azim', 'clutter'])
10908
Raw data for multiple time steps¶
To read multiple scans into one array, you should create an empty array with the shape of the desired dimensions. In this example, the dataset contains 2 timesteps of 360 by 128 values. Note that we simply catch the metadata dictionary in a dummy variable:
In [3]:
import numpy as np
two_scans = np.empty((2,360,128))
metadata = [[],[]]
filename = wrl.util.get_wradlib_data_file('dx/raa00-dx_10908-0806021740-fbg---bin.gz')
two_scans[0], metadata[0] = wrl.io.read_dx(filename)
filename = wrl.util.get_wradlib_data_file('dx/raa00-dx_10908-0806021745-fbg---bin.gz')
two_scans[1], metadata[1] = wrl.io.read_dx(filename)
print(two_scans.shape)
(2, 360, 128)
Visualizing dBZ values¶
Now we want to create a quick diagnostic PPI plot of reflectivity in a polar coordiate system:
In [4]:
pl.figure(figsize=(10,8))
ax, pm = wrl.vis.plot_ppi(one_scan)
# add a colorbar with label
cbar = pl.colorbar(pm, shrink=0.75)
cbar.set_label("Reflectivity (dBZ)")
<Figure size 720x576 with 0 Axes>

This is a stratiform event. Apparently, the radar system has already masked the foothills of the Alps as clutter. The spike in the south-western sector is caused by a broadcasting tower nearby the radar antenna.
Another case shows a convective situation:
In [5]:
pl.figure(figsize=(10,8))
ax, pm = wrl.vis.plot_ppi(two_scans[0])
cbar = pl.colorbar(pm, shrink=0.75)
cbar.set_label("Reflectivity (dBZ)")
<Figure size 720x576 with 0 Axes>

You can also modify or decorate the image further, e.g. add a cross-hair, a title, use a different colormap, or zoom in:
In [6]:
pl.figure(figsize=(10,8))
# Plot PPI,
ax, pm = wrl.vis.plot_ppi(two_scans[0], cmap="viridis")
# add crosshair,
ax = wrl.vis.plot_ppi_crosshair((0,0), ranges=[40,80,128])
# add colorbar,
cbar = pl.colorbar(pm, shrink=0.9)
cbar.set_label("Reflectivity (dBZ)")
# add title,
pl.title('Reflectivity at {0}\nDWD radar Feldberg'.format(metadata[0]['datetime']))
# and zoom in.
pl.xlim((-128,128))
pl.ylim((-128,128))
Out[6]:
(-128, 128)
<Figure size 720x576 with 0 Axes>

In addition, you might want to tweak the colorscale to allow for better comparison of different images:
In [7]:
fig = pl.figure(figsize=(12,10))
# Add first subplot (stratiform)
ax = pl.subplot(121, aspect="equal")
# Plot PPI,
ax, pm = wrl.vis.plot_ppi(one_scan, cmap="viridis", vmin=20, vmax=60)
# add crosshair,
ax = wrl.vis.plot_ppi_crosshair((0,0), ranges=[40,80,128])
# add colorbar,
cbar = pl.colorbar(pm, shrink=0.5)
cbar.set_label("Reflectivity (dBZ)")
# add title,
pl.title('Reflectivity at {0}\nDWD radar Feldberg'.format(metadata[0]['datetime']))
# and zoom in.
pl.xlim((-128,128))
pl.ylim((-128,128))
# Add second subplot (convective)
ax = pl.subplot(122, aspect="equal")
# Plot PPI,
ax, pm = wrl.vis.plot_ppi(two_scans[0], cmap="viridis", vmin=20, vmax=60)
# add crosshair,
ax = wrl.vis.plot_ppi_crosshair((0,0), ranges=[40,80,128])
# add colorbar,
cbar = pl.colorbar(pm, shrink=0.5)
cbar.set_label("Reflectivity (dBZ)")
# add title,
pl.title('Reflectivity at {0}\nDWD radar Feldberg'.format(attributes['datetime']))
# and zoom in.
pl.xlim((-128,128))
pl.ylim((-128,128))
Out[7]:
(-128, 128)



The radar data was kindly provided by the German Weather Service.
RADOLAN binary data format¶
The RADOLAN binary data file format is described in the RADOLAN Kompositformat. The radolan composite files consists of an ascii header containing all needed information to decode the following binary data block. \(\omega radlib\) provides wradlib.io.read_radolan_composite() to read the data.
The function wradlib.io.parse_dwd_composite_header()
takes care of
correctly decoding the ascii header. All available header information is
transferred into the metadata dictionary.
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
In [2]:
# load radolan files
rw_filename = wrl.util.get_wradlib_data_file('radolan/misc/raa01-rw_10000-1408102050-dwd---bin.gz')
filehandle = wrl.io.get_radolan_filehandle(rw_filename)
header = wrl.io.read_radolan_header(filehandle)
print(header)
RW102050100000814BY1620134VS 3SW 2.13.1PR E-01INT 60GP 900x 900MS 62<boo,ros,emd,hnr,umd,pro,ess,asd,neu,nhb,oft,tur,isn,fbg,mem>
In [3]:
attrs = wrl.io.parse_dwd_composite_header(header)
print(attrs)
{'producttype': 'RW', 'datetime': datetime.datetime(2014, 8, 10, 20, 50), 'radarid': '10000', 'datasize': 1620000, 'maxrange': '150 km', 'radolanversion': '2.13.1', 'precision': 0.1, 'intervalseconds': 3600, 'nrow': 900, 'ncol': 900, 'radarlocations': ['boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem']}
In the following example, the header information of four different composites is extracted.
In [4]:
# load radolan file
filename = 'radolan/showcase/raa01-rx_10000-1408102050-dwd---bin.gz'
rx_filename = wrl.util.get_wradlib_data_file(filename)
filename = 'radolan/showcase/raa01-ex_10000-1408102050-dwd---bin.gz'
ex_filename = wrl.util.get_wradlib_data_file(filename)
filename = 'radolan/showcase/raa01-rw_10000-1408102050-dwd---bin.gz'
rw_filename = wrl.util.get_wradlib_data_file(filename)
filename = 'radolan/showcase/raa01-sf_10000-1408102050-dwd---bin.gz'
sf_filename = wrl.util.get_wradlib_data_file(filename)
rxdata, rxattrs = wrl.io.read_radolan_composite(rx_filename)
exdata, exattrs = wrl.io.read_radolan_composite(ex_filename)
rwdata, rwattrs = wrl.io.read_radolan_composite(rw_filename)
sfdata, sfattrs = wrl.io.read_radolan_composite(sf_filename)
# print the available attributes
print("RX Attributes:")
for key, value in rxattrs.items():
print(key + ':', value)
print("----------------------------------------------------------------")
# print the available attributes
print("EX Attributes:")
for key, value in exattrs.items():
print(key + ':', value)
print("----------------------------------------------------------------")
# print the available attributes
print("RW Attributes:")
for key, value in rwattrs.items():
print(key + ':', value)
print("----------------------------------------------------------------")
# print the available attributes
print("SF Attributes:")
for key, value in sfattrs.items():
print(key + ':', value)
print("----------------------------------------------------------------")
RX Attributes:
producttype: RX
datetime: 2014-08-10 20:50:00
radarid: 10000
datasize: 810000
maxrange: 150 km
radolanversion: 2.13.1
precision: 1.0
intervalseconds: 300
nrow: 900
ncol: 900
radarlocations: ['boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem', 'bdy']
nodataflag: -9999
cluttermask: []
----------------------------------------------------------------
EX Attributes:
producttype: EX
datetime: 2014-08-10 20:50:00
radarid: 10000
datasize: 2100000
maxrange: 128 km
radolanversion: 2.13.1
precision: 1.0
intervalseconds: 300
nrow: 1500
ncol: 1400
radarlocations: ['sin', 'rom', 'vir', 'bor', 'nld', 'zav', 'wid', 'sui', 'abv', 'ave', 'tra', 'arc', 'ncy', 'bgs', 'bla', 'sly', 'sem', 'boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem', 'bdy', 'ska']
nodataflag: -9999
cluttermask: []
----------------------------------------------------------------
RW Attributes:
producttype: RW
datetime: 2014-08-10 20:50:00
radarid: 10000
datasize: 1620000
maxrange: 150 km
radolanversion: 2.13.1
precision: 0.1
intervalseconds: 3600
nrow: 900
ncol: 900
radarlocations: ['boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem']
nodataflag: -9999
secondary: [ 799 800 801 ... 806263 806264 807163]
cluttermask: []
----------------------------------------------------------------
SF Attributes:
producttype: SF
datetime: 2014-08-10 20:50:00
radarid: 10000
datasize: 1620000
maxrange: 150 km
radolanversion: 2.13.1
precision: 0.1
intervalseconds: 86400
nrow: 900
ncol: 900
radarlocations: ['boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem']
radardays: ['asd 24', 'boo 24', 'emd 24', 'ess 24', 'fbg 24', 'hnr 24', 'isn 24', 'mem 24', 'neu 24', 'nhb 24', 'oft 24', 'pro 24', 'ros 24', 'tur 24', 'umd 24']
nodataflag: -9999
secondary: [ 188 189 190 ... 809566 809567 809568]
cluttermask: []
----------------------------------------------------------------
Reading NetCDF files with a generic reader¶
In this example, we read NetCDF files from different sources using a generic reader from \(\omega radlib's\) io module.
In [1]:
from wradlib.io import read_generic_netcdf
from wradlib.util import get_wradlib_data_file
import os
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
In [2]:
# A little helper function for repeated tasks
def read_and_overview(filename):
"""Read NetCDF using read_generic_netcdf and print upper level dictionary keys
"""
test = read_generic_netcdf(filename)
print("\nPrint keys for file %s" % os.path.basename(filename))
for key in test.keys():
print("\t%s" % key)
CfRadial example from TITAN homepage¶
See also: http://www.ral.ucar.edu/projects/titan/docs/radial_formats
In [3]:
filename = 'netcdf/cfrad.20080604_002217_000_SPOL_v36_SUR.nc'
filename = get_wradlib_data_file(filename)
read_and_overview(filename)
Print keys for file cfrad.20080604_002217_000_SPOL_v36_SUR.nc
Conventions
version
title
institution
references
source
history
comment
instrument_name
site_name
scan_name
scan_id
platform_is_mobile
n_gates_vary
dimensions
variables
Example PPI from Py-ART repository¶
See also: https://github.com/ARM-DOE/pyart/
In [4]:
filename = 'netcdf/example_cfradial_ppi.nc'
filename = get_wradlib_data_file(filename)
read_and_overview(filename)
Print keys for file example_cfradial_ppi.nc
comment
title
Conventions
source
version
references
instrument_name
institution
field_names
history
dimensions
variables
Example RHI from Py-ART repository¶
See also: https://github.com/ARM-DOE/pyart/
In [5]:
filename = 'netcdf/example_cfradial_rhi.nc'
filename = get_wradlib_data_file(filename)
read_and_overview(filename)
Print keys for file example_cfradial_rhi.nc
comment
title
Conventions
source
version
references
instrument_name
institution
field_names
history
dimensions
variables
Example EDGE NetCDF export format¶
In [6]:
filename = 'netcdf/edge_netcdf.nc'
filename = get_wradlib_data_file(filename)
read_and_overview(filename)
Print keys for file edge_netcdf.nc
TypeName
DataType
Latitude
Longitude
Height
Time
FractionalTime
attributes
NyquistVelocity-unit
NyquistVelocity-value
vcp-unit
vcp-value
radarName-unit
radarName-value
ColorMap-unit
ColorMap-value
Elevation
ElevationUnits
MissingData
RangeFolded
RadarParameters
PRF-unit
PRF-value
PulseWidth-unit
PulseWidth-value
MaximumRange-unit
MaximumRange-value
ConversionPlugin
dimensions
variables
Load and inspect data from a Rainbow file¶
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import numpy as np
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Load Rainbow file¶
In [2]:
filename = wrl.util.get_wradlib_data_file('rainbow/2013070308340000dBuZ.azi')
rbdict = wrl.io.read_rainbow(filename)
Get azimuthal data¶
In [3]:
azi = rbdict['volume']['scan']['slice']['slicedata']['rayinfo']['data']
azidepth = float(rbdict['volume']['scan']['slice']
['slicedata']['rayinfo']['@depth'])
azirange = float(rbdict['volume']['scan']['slice']
['slicedata']['rayinfo']['@rays'])
azires = float(rbdict['volume']['scan']['slice']['anglestep'])
azi = (azi * azirange / 2**azidepth) * azires
Create range array¶
In [4]:
stoprange = float(rbdict['volume']['scan']['slice']['stoprange'])
rangestep = float(rbdict['volume']['scan']['slice']['rangestep'])
r = np.arange(0, stoprange, rangestep)
Get reflectivity data¶
In [5]:
data = rbdict['volume']['scan']['slice']['slicedata']['rawdata']['data']
datadepth = float(rbdict['volume']['scan']['slice']
['slicedata']['rawdata']['@depth'])
datamin = float(rbdict['volume']['scan']['slice']
['slicedata']['rawdata']['@min'])
datamax = float(rbdict['volume']['scan']['slice']
['slicedata']['rawdata']['@max'])
data = datamin + data * (datamax - datamin) / 2 ** datadepth
Get annotation data¶
In [6]:
unit = rbdict['volume']['scan']['slice']['slicedata']['rawdata']['@type']
time = rbdict['volume']['scan']['slice']['slicedata']['@time']
date = rbdict['volume']['scan']['slice']['slicedata']['@date']
lon = rbdict['volume']['sensorinfo']['lon']
lat = rbdict['volume']['sensorinfo']['lat']
sensortype = rbdict['volume']['sensorinfo']['@type']
sensorname = rbdict['volume']['sensorinfo']['@name']
Plot data with annotation¶
In [7]:
fig = pl.figure(figsize=(8,8))
cgax, pm = wrl.vis.plot_ppi(data, r=r, az=azi, fig=fig, cg=True)
title = '{0} {1} {2} {3}\n{4}E {5}N'.format(sensortype, sensorname, date,
time, lon, lat)
caax = cgax.parasites[0]
t = pl.title(title, fontsize=12)
t.set_y(1.1)
cbar = pl.gcf().colorbar(pm, pad=0.075)
caax.set_xlabel('x_range [km]')
caax.set_ylabel('y_range [km]')
pl.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',
ha='right')
cbar.set_label('reflectivity [' + unit + ']')

Export a dataset in GIS-compatible format¶
In this notebook, we demonstrate how to export a gridded dataset in GeoTIFF and ESRI ASCII format. This will be exemplified using RADOLAN data from the German Weather Service.
In [1]:
import wradlib as wrl
import numpy as np
import warnings
warnings.filterwarnings('ignore')
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Step 1: Read the original data¶
In [2]:
# We will export this RADOLAN dataset to a GIS compatible format
wdir = wrl.util.get_wradlib_data_path() + '/radolan/grid/'
filename = 'radolan/misc/raa01-sf_10000-1408102050-dwd---bin.gz'
filename = wrl.util.get_wradlib_data_file(filename)
data_raw, meta = wrl.io.read_radolan_composite(filename)
Step 2: Get the projected coordinates of the RADOLAN grid¶
In [3]:
# This is the RADOLAN projection
proj_osr = wrl.georef.create_osr("dwd-radolan")
# Get projected RADOLAN coordinates for corner definition
xy_raw = wrl.georef.get_radolan_grid(900, 900)
Step 3: Check Origin and Row/Column Order¶
We know, that wrl.read_radolan_composite
returns a 2D-array (rows,
cols) with the origin in the lower left corner. Same applies to
wrl.georef.get_radolan_grid
. For the next step, we need to flip the
data and the coords up-down. The coordinate corner points also need to
be adjusted from lower left corner to upper right corner.
In [4]:
data, xy = wrl.georef.set_raster_origin(data_raw, xy_raw, 'upper')
Step 4a: Export as GeoTIFF¶
For RADOLAN grids, this projection will probably not be recognized by ESRI ArcGIS.
In [5]:
# create 3 bands
data = np.stack((data, data+100, data+1000))
ds = wrl.georef.create_raster_dataset(data, xy, projection=proj_osr)
wrl.io.write_raster_dataset(wdir + "geotiff.tif", ds, 'GTiff')
Step 4b: Export as ESRI ASCII file (aka Arc/Info ASCII Grid)¶
In [6]:
# Export to Arc/Info ASCII Grid format (aka ESRI grid)
# It should be possible to import this to most conventional
# GIS software.
# only use first band
proj_esri = proj_osr.Clone()
proj_esri.MorphToESRI()
ds = wrl.georef.create_raster_dataset(data[0], xy, projection=proj_esri)
wrl.io.write_raster_dataset(wdir + "aaigrid.asc", ds, 'AAIGrid', options=['DECIMAL_PRECISION=2'])
Step 5a: Read from GeoTIFF¶
In [7]:
ds1 = wrl.io.open_raster(wdir + "geotiff.tif")
data1, xy1, proj1 = wrl.georef.extract_raster_dataset(ds1, nodata=-9999.)
np.testing.assert_array_equal(data1, data)
np.testing.assert_array_equal(xy1[:-1,:-1,:], xy)
Step 5b: Read from ESRI ASCII file (aka Arc/Info ASCII Grid)¶
In [8]:
ds2 = wrl.io.open_raster(wdir + "aaigrid.asc")
data2, xy2, proj2 = wrl.georef.extract_raster_dataset(ds2, nodata=-9999.)
np.testing.assert_array_almost_equal(data2, data[0], decimal=2)
np.testing.assert_array_almost_equal(xy2[:-1,:-1,:], xy)
Attenuation correction¶
In this example, we will compare different approaches to constrain the gate-by-gate retrieval of path-integrated attenuation.
Introduction¶
Rainfall-induced attenuation is a major source of underestimation for radar-based precipitation estimation at C-band and X-band. Unconstrained forward gate-by-gate correction is known to be inherently unstable and thus not suited for unsupervised quality control procedures. Ideally, reference measurements (e.g. from microwave links) should be used to constrain gate-by-gate procedures. However, such attenuation references are usually not available. \(\omega radlib\) provides a pragmatic approach to constrain gate-by-gate correction procedures, inspired by the work of Kraemer et al., 2008. It turned out that these procedures can effectively reduce the error introduced by attenuation, and, at the same time, minimize instability issues (Jacobi et al., 2016).
The Example Event: June 2nd, 2008, SW-Germany¶
Let’s have a look at the situation in South-West Germany on June 2nd, 2008, at 16:55 UTC, as observed by the DWD C-band radar on mount Feldberg.
The data can be read by the following lines and then visualized by wradlib.vis.plot_ppi():
In [2]:
fpath = 'dx/raa00-dx_10908-0806021655-fbg---bin.gz'
f = wrl.util.get_wradlib_data_file(fpath)
data, attrs = wrl.io.read_dx(f)
In [3]:
pl.figure(figsize=(10,8))
ax, cf = wrl.vis.plot_ppi(data, cmap="viridis")
pl.xlabel("Easting from radar (km)")
pl.ylabel("Northing from radar (km)")
pl.title("Radar Feldberg, 2008-06-02 16:55 UTC")
cb = pl.colorbar(cf, shrink=0.8)
cb.set_label("dBZ")
pl.plot([0,105.6],[0,73.4],"-", color="white", lw=2)
pl.xlim(-128,128)
pl.ylim(-128,128)
pl.grid(color="grey")
<Figure size 720x576 with 0 Axes>

We see a set of convective cells with high rainfall intensity in the NE-sector of the Feldberg radar. Let us examine the reflectivity profile along three beams which at azimuths 53-55 degree (as marked by the white line in the PPI above).
In [4]:
# just a little helper function
def plot_beams(data, mybeams, sub=111):
ax = fig.add_subplot(sub)
labelsize=13
for beam in range(mybeams.start, mybeams.stop):
pl.plot(data[beam], label="{0} deg".format(beam))
pl.grid()
pl.text(0.99, 0.88, "Reflectivity along beams",
horizontalalignment='right',
transform = ax.transAxes, fontsize="large")
pl.xlabel("range (km)", fontsize="large")
pl.ylabel("Reflectivity (dBZ)", fontsize="large")
pl.legend(loc="upper left")
ax.tick_params(axis='x', labelsize=labelsize)
ax.tick_params(axis='y', labelsize=labelsize)
pl.xlim(0,128)
In [5]:
mybeams = slice(53,56)
fig = pl.figure(figsize=(10,3))
plot_beams(data, mybeams)

Examining different attenuation correction procedures¶
Hitschfeld and Bordan¶
Unconstrained gate-by-gate retrieval (1954)
First, we examine the behaviour of the “classical” unconstrained forward correction which is typically referred to Hitschfeld et al., 1954, although Hitschfeld and Bordan themselves rejected this approach. The Path Integrated Attenuation (PIA) according to this approach can be obtained as follows:
In [6]:
pia_hibo = wrl.atten.correct_attenuation_hb(
data,
coefficients = dict(a=8.e-5, b=0.731, gate_length=1.0),
mode="warn",
thrs=59.)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
corrected signal over threshold (59.0)
In the coefficients dictionary, we can pass the power law parameters of
the A(Z) relation as well as the gate length (in km). If we pass “warn”
as the mode argument, we will obtain a warning log in case the corrected
reflectivity exceeds the value of argument thrs
(dBZ).
Plotting the result below the reflectivity profile, we obtain the following figure.
In [7]:
# another little helper function
def plot_pia(pia, sub=111, title=None):
ax = fig.add_subplot(sub)
labelsize=13
pl.plot(pia.T)
pl.grid()
pl.ylim(0,30)
pl.ylabel("PIA (dB)", fontsize="large")
pl.text(0.01, 0.88, title,
transform = ax.transAxes, fontsize="large")
ax.tick_params(axis='x', labelsize=labelsize)
ax.tick_params(axis='y', labelsize=labelsize)
pl.xlim(0,128)
In [8]:
fig = pl.figure(figsize=(10,6))
plot_beams(data, mybeams, 211)
plot_pia(pia_hibo[mybeams], 212,
"PIA according to Hitchfeld and Bordan")
pl.tight_layout()

Apparently, slight differences in the reflectivity profile can cause a dramatic change in the behaviour. While at 54 and 55 degrees, the retrieval of PIA appears to be fairly stable, the profile of PIA for 53 degree demonstrates a case of instability.
Harrison¶
Harrison et.al. (2000): Cap PIA at a factor of two
Harrison et al., 2000 suggested to simply cap PIA in case it would cause a correction of rainfall intensity by more than a factor of two. Depending on the parameters of the Z(R) relationship, that would correpond to PIA values between 4 and 5 dB (4.8 dB if we assume exponent b=1.6).
One way to implement this approach would be the following:
In [9]:
pia_harrison = wrl.atten.correct_attenuation_hb(
data,
coefficients = dict(a=4.57e-5, b=0.731, gate_length=1.0),
mode="warn",
thrs=59.)
pia_harrison[pia_harrison > 4.8] = 4.8
And the results would look like this:
In [10]:
fig = pl.figure(figsize=(10,6))
mybeams = slice(53,56)
labelsize=13
plot_beams(data, mybeams, 211)
plot_pia(pia_harrison[mybeams], 212,
"PIA according to Harrison")
pl.tight_layout()

Kraemer¶
Kraemer et al. (2008): Iterative estimation of A(Z) relationsip
Kraemer et al.,
2008
suggested to iteratively determine the power law parameters of the A(Z).
In particular, the power law coefficient is interatively decreased until
the attenuation correction does not lead to reflectivity values above a
given threshold (Kraemer suggested 59 dBZ). Using \(\omega radlib\),
this would be called by using the function
wradlib.atten.correct_attenuation_constrained()
with a specific constraints
argument:
In [11]:
pia_kraemer = wrl.atten.correct_attenuation_constrained(
data,
a_max=1.67e-4,
a_min=2.33e-5,
n_a=100,
b_max=0.7,
b_min=0.65,
n_b=6,
gate_length=1.,
constraints=[wrl.atten.constraint_dbz],
constraint_args=[[59.0]])
In brief, this call specifies ranges of the power parameters a and b of
the A(Z) relation. Beginning from the maximum values (a_max
and
b_max
), the function searches for values of a
and b
so that
the corrected reflectivity will not exceed the dBZ constraint of 59 dBZ.
Compared to the previous results, the corresponding profiles of PIA look
like this:
In [12]:
fig = pl.figure(figsize=(10,6))
plot_beams(data, mybeams, 211)
plot_pia(pia_kraemer[mybeams], 212,
"PIA according to Kraemer")
pl.tight_layout()

Modified Kraemer¶
Generalised Kraemer procedure: adding additional constraints
The function
wradlib.atten.correct_attenuation_constrained()
allows us to pass any kind of constraint function or lists of constraint
functions via the argument constraints
. The arguments of these
functions are passed via a nested list as argument constraint_args
.
For example, Jacobi et al.,
2016
suggested to constrain both the corrected reflectivity (by a maximum
of 59 dBZ) and the resulting path-intgrated attenuation PIA (by a
maximum of 20 dB):
In [13]:
pia_mkraemer = wrl.atten.correct_attenuation_constrained(
data,
a_max=1.67e-4,
a_min=2.33e-5,
n_a=100,
b_max=0.7,
b_min=0.65,
n_b=6,
gate_length=1.,
constraints=[wrl.atten.constraint_dbz,
wrl.atten.constraint_pia],
constraint_args=[[59.0],[20.0]])
In [14]:
fig = pl.figure(figsize=(10,6))
plot_beams(data, mybeams, 211)
plot_pia(pia_mkraemer[mybeams], 212,
"PIA according to modified Kraemer")
pl.tight_layout()

Comparison of all Methods¶
Plotting all of the above methods (Hitschfeld and Bordan, Harrison, Kraemer, Modified Kraemer allows for a better comparison of their behaviour. Please refer to Jacobi et al., 2016 for an in-depth discussion of this example.
In [15]:
fig = pl.figure(figsize=(10,12))
plot_beams(data, mybeams, 511)
plot_pia(pia_hibo[mybeams], 512,
"PIA according to Hitschfeld and Bordan" )
plot_pia(pia_harrison[mybeams], 513,
"PIA according to Harrison")
plot_pia(pia_kraemer[mybeams], 514,
"PIA according to Kraemer")
plot_pia(pia_mkraemer[mybeams], 515,
"PIA according to modified Kraemer")
pl.tight_layout()

Beam Blockage Calculation using a DEM¶
Here, we derive (partial) beam-blockage (PBB) from a Digital Elevation Model (DEM).
We require - the local radar setup (sitecoords, number of rays, number of bins, antenna elevation, beamwidth, and the range resolution); - a DEM with a adequate resolution.
Here we use pre-processed data from the GTOPO30 and SRTM missions.
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import matplotlib as mpl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Setup for Bonn radar¶
First, we need to define some radar specifications (here: University of Bonn).
In [2]:
sitecoords = (7.071663, 50.73052, 99.5)
nrays = 360 # number of rays
nbins = 1000 # number of range bins
el = 1.0 # vertical antenna pointing angle (deg)
bw = 1.0 # half power beam width (deg)
range_res = 100. # range resolution (meters)
Create the range, azimuth, and beamradius arrays.
In [3]:
r = np.arange(nbins) * range_res
beamradius = wrl.util.half_power_radius(r, bw)
We use
to calculate the spherical coordinates of the bin centroids and their longitude, latitude and altitude.
In [4]:
coord = wrl.georef.sweep_centroids(nrays, range_res, nbins, el)
coords = wrl.georef.spherical_to_proj(coord[..., 0],
np.degrees(coord[..., 1]),
coord[..., 2], sitecoords)
lon = coords[..., 0]
lat = coords[..., 1]
alt = coords[..., 2]
In [5]:
polcoords = coords[..., :2]
print("lon,lat,alt:", coords.shape)
lon,lat,alt: (360, 1000, 3)
In [6]:
rlimits = (lon.min(), lat.min(), lon.max(), lat.max())
print("Radar bounding box:\n\t%.2f\n%.2f %.2f\n\t%.2f" %
(lat.max(), lon.min(), lon.max(), lat.min()))
Radar bounding box:
51.63
5.66 8.49
49.83
Preprocessing the digitial elevation model¶
- Read the DEM from a
geotiff
file (inWRADLIB_DATA
); - clip the region inside the bounding box;
- map the DEM values to the polar grid points.
Note: You can choose between the coarser resolution bonn_gtopo.tif
(from GTOPO30) and the finer resolution bonn_new.tif
(from the SRTM
mission).
The DEM raster data is opened via wradlib.io.open_raster and extracted via wradlib.georef.extract_raster_dataset.
In [7]:
#rasterfile = wrl.util.get_wradlib_data_file('geo/bonn_gtopo.tif')
rasterfile = wrl.util.get_wradlib_data_file('geo/bonn_new.tif')
ds = wrl.io.open_raster(rasterfile)
rastervalues, rastercoords, proj = wrl.georef.extract_raster_dataset(ds, nodata=-32768.)
# Clip the region inside our bounding box
ind = wrl.util.find_bbox_indices(rastercoords, rlimits)
rastercoords = rastercoords[ind[1]:ind[3], ind[0]:ind[2], ...]
rastervalues = rastervalues[ind[1]:ind[3], ind[0]:ind[2]]
# Map rastervalues to polar grid points
polarvalues = wrl.ipol.cart_to_irregular_spline(rastercoords, rastervalues,
polcoords, order=3,
prefilter=False)
Calculate Beam-Blockage¶
Now we can finally apply the wradlib.qual.beam_block_frac function to calculate the PBB.
In [8]:
PBB = wrl.qual.beam_block_frac(polarvalues, alt, beamradius)
PBB = np.ma.masked_invalid(PBB)
print(PBB.shape)
(360, 1000)
So far, we calculated the fraction of beam blockage for each bin.
But we need to into account that the radar signal travels along a beam. Cumulative beam blockage (CBB) in one bin along a beam will always be at least as high as the maximum PBB of the preceeding bins (see wradlib.qual.cum_beam_block_frac)
In [9]:
CBB = wrl.qual.cum_beam_block_frac(PBB)
print(CBB.shape)
(360, 1000)
Visualize Beamblockage¶
Now we visualize - the average terrain altitude per radar bin - a beam blockage map - interaction with terrain along a single beam
In [10]:
# just a little helper function to style x and y axes of our maps
def annotate_map(ax, cm=None, title=""):
ticks = (ax.get_xticks()/1000).astype(np.int)
ax.set_xticklabels(ticks)
ticks = (ax.get_yticks()/1000).astype(np.int)
ax.set_yticklabels(ticks)
ax.set_xlabel("Kilometers")
ax.set_ylabel("Kilometers")
if not cm is None:
pl.colorbar(cm, ax=ax)
if not title=="":
ax.set_title(title)
ax.grid()
In [11]:
fig = pl.figure(figsize=(10, 8))
# create subplots
ax1 = pl.subplot2grid((2, 2), (0, 0))
ax2 = pl.subplot2grid((2, 2), (0, 1))
ax3 = pl.subplot2grid((2, 2), (1, 0), colspan=2, rowspan=1)
# azimuth angle
angle = 225
# Plot terrain (on ax1)
ax1, dem = wrl.vis.plot_ppi(polarvalues,
ax=ax1, r=r,
az=np.degrees(coord[:,0,1]),
cmap=mpl.cm.terrain, vmin=0.)
ax1.plot([0,np.sin(np.radians(angle))*1e5],
[0,np.cos(np.radians(angle))*1e5],"r-")
ax1.plot(sitecoords[0], sitecoords[1], 'ro')
annotate_map(ax1, dem, 'Terrain within {0} km range'.format(np.max(r / 1000.) + 0.1))
# Plot CBB (on ax2)
ax2, cbb = wrl.vis.plot_ppi(CBB, ax=ax2, r=r,
az=np.degrees(coord[:,0,1]),
cmap=mpl.cm.PuRd, vmin=0, vmax=1)
annotate_map(ax2, cbb, 'Beam-Blockage Fraction')
# Plot single ray terrain profile on ax3
bc, = ax3.plot(r / 1000., alt[angle, :], '-b',
linewidth=3, label='Beam Center')
b3db, = ax3.plot(r / 1000., (alt[angle, :] + beamradius), ':b',
linewidth=1.5, label='3 dB Beam width')
ax3.plot(r / 1000., (alt[angle, :] - beamradius), ':b')
ax3.fill_between(r / 1000., 0.,
polarvalues[angle, :],
color='0.75')
ax3.set_xlim(0., np.max(r / 1000.) + 0.1)
ax3.set_ylim(0., 3000)
ax3.set_xlabel('Range (km)')
ax3.set_ylabel('Altitude (m)')
ax3.grid()
axb = ax3.twinx()
bbf, = axb.plot(r / 1000., CBB[angle, :], '-k',
label='BBF')
axb.set_ylabel('Beam-blockage fraction')
axb.set_ylim(0., 1.)
axb.set_xlim(0., np.max(r / 1000.) + 0.1)
legend = ax3.legend((bc, b3db, bbf),
('Beam Center', '3 dB Beam width', 'BBF'),
loc='upper left', fontsize=10)

Visualize Beam Propagation showing earth curvature¶
Now we visualize - interaction with terrain along a single beam
In this representation the earth curvature is shown. For this we assume the earth a sphere with exactly 6370000 m radius. This is needed to get the height ticks at nice position.
In [12]:
def height_formatter(x, pos):
x = (x - 6370000) / 1000
fmt_str = '{:g}'.format(x)
return fmt_str
def range_formatter(x, pos):
x = x / 1000.
fmt_str = '{:g}'.format(x)
return fmt_str
- The wradlib.vis.create_cg-function is facilitated to create the curved geometries.
- The actual data is plottet as (theta, range) on the parasite axis.
- Some tweaking is needed to get the final plot look nice.
In [13]:
fig = pl.figure(figsize=(10, 6))
cgax, caax, paax = wrl.vis.create_cg('RHI', fig, 111)
# azimuth angle
angle = 225
# fix grid_helper
er = 6370000
gh = cgax.get_grid_helper()
gh.grid_finder.grid_locator2._nbins=80
gh.grid_finder.grid_locator2._steps=[1,2,4,5,10]
# calculate beam_height and arc_distance for ke=1
# means line of sight
bhe = wrl.georef.bin_altitude(r, 0, sitecoords[2], re=er, ke=1.)
ade = wrl.georef.bin_distance(r, 0, sitecoords[2], re=er, ke=1.)
nn0 = np.zeros_like(r)
# for nice plotting we assume earth_radius = 6370000 m
ecp = nn0 + er
# theta (arc_distance sector angle)
thetap = - np.degrees(ade/er) + 90.0
# zero degree elevation with standard refraction
bh0 = wrl.georef.bin_altitude(r, 0, sitecoords[2], re=er)
# plot (ecp is earth surface normal null)
bes, = paax.plot(thetap, ecp, '-k', linewidth=3, label='Earth Surface NN')
bc, = paax.plot(thetap, ecp + alt[angle, :], '-b', linewidth=3, label='Beam Center')
bc0r, = paax.plot(thetap, ecp + bh0 + alt[angle, 0] , '-g', label='0 deg Refraction')
bc0n, = paax.plot(thetap, ecp + bhe + alt[angle, 0], '-r', label='0 deg line of sight')
b3db, = paax.plot(thetap, ecp + alt[angle, :] + beamradius, ':b', label='+3 dB Beam width')
paax.plot(thetap, ecp + alt[angle, :] - beamradius, ':b', label='-3 dB Beam width')
# orography
paax.fill_between(thetap, ecp,
ecp + polarvalues[angle, :],
color='0.75')
# shape axes
cgax.set_xlim(0, np.max(ade))
cgax.set_ylim([ecp.min()-1000, ecp.max()+2500])
caax.grid(True, axis='x')
cgax.grid(True, axis='y')
cgax.axis['top'].toggle(all=False)
caax.yaxis.set_major_locator(mpl.ticker.MaxNLocator(steps=[1,2,4,5,10], nbins=20, prune='both'))
caax.xaxis.set_major_locator(mpl.ticker.MaxNLocator())
caax.yaxis.set_major_formatter(mpl.ticker.FuncFormatter(height_formatter))
caax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(range_formatter))
caax.set_xlabel('Range (km)')
caax.set_ylabel('Altitude (km)')
legend = paax.legend((bes, bc0n, bc0r, bc, b3db),
('Earth Surface NN', '0 deg line of sight', '0 deg std refraction', 'Beam Center', '3 dB Beam width'),
loc='upper left', fontsize=10)

Go back to Read DEM Raster Data, change the rasterfile to use the other resolution DEM and process again.
Clutter and Echo Classification¶
This section provides a collection of example code snippets to show clutter detection and correction as well as echo classification capabilities of \(\omega radlib\).
Clutter detection using the Gabella approach¶
In [1]:
import matplotlib.pyplot as pl
import numpy as np
import wradlib.vis as vis
import wradlib.clutter as clutter
import wradlib.util as util
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Read the data¶
In [2]:
filename = util.get_wradlib_data_file('misc/polar_dBZ_fbg.gz')
data = np.loadtxt(filename)
Apply filter¶
In [3]:
clmap = clutter.filter_gabella(data,
wsize=5,
thrsnorain=0.,
tr1=6.,
n_p=8,
tr2=1.3)
Plot results¶
In [4]:
fig = pl.figure(figsize=(12,8))
ax = fig.add_subplot(121)
ax, pm = vis.plot_ppi(data, ax=ax)
ax.set_title('Reflectivity')
ax = fig.add_subplot(122)
ax, pm = vis.plot_ppi(clmap, ax=ax)
ax.set_title('Cluttermap')
Out[4]:
Text(0.5,1,'Cluttermap')

Clutter detection by using space-born cloud images¶
In [1]:
import numpy as np
import wradlib.vis as vis
import wradlib.clutter as cl
import wradlib.georef as georef
import wradlib.ipol as ipol
import wradlib.io as io
import wradlib.util as util
import matplotlib.pyplot as plt
try:
get_ipython().magic("matplotlib inline")
except:
plt.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Read the radar data and count the number of tilts¶
In [2]:
# read the radar volume scan
filename = 'hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf'
filename = util.get_wradlib_data_file(filename)
pvol = io.read_opera_hdf5(filename)
# Count the number of dataset
ntilt = 1
for i in range(100):
try:
pvol["dataset%d/what" % ntilt]
ntilt += 1
except Exception:
ntilt -= 1
break
Reconstruct the radar values¶
In [3]:
nrays = int(pvol["dataset1/where"]["nrays"])
nbins = int(pvol["dataset1/where"]["nbins"])
val = np.empty((ntilt, nrays, nbins))
for t in range(ntilt):
val[t, ...] = pvol["dataset%d/data1/data" % (t + 1)]
gain = float(pvol["dataset1/data1/what"]["gain"])
offset = float(pvol["dataset1/data1/what"]["offset"])
val = val * gain + offset
Construct the corresponding radar coordinates¶
In [4]:
rscale = int(pvol["dataset1/where"]["rscale"])
coord = np.empty((ntilt, nrays, nbins, 3))
for t in range(ntilt):
elangle = pvol["dataset%d/where" % (t + 1)]["elangle"]
coord[t, ...] = georef.sweep_centroids(nrays, rscale, nbins, elangle)
# ascale = math.pi / nrays
sitecoords = (pvol["where"]["lon"], pvol["where"]["lat"],
pvol["where"]["height"])
coord, proj_radar = georef.spherical_to_xyz(coord[..., 0],
np.degrees(coord[..., 1]),
coord[..., 2], sitecoords,
re=6370040.,
ke=4./3.)
Construct collocated satellite data¶
In [5]:
filename = 'hdf5/SAFNWC_MSG3_CT___201304290415_BEL_________.h5'
filename = util.get_wradlib_data_file(filename)
sat_gdal = io.read_safnwc(filename)
val_sat = georef.read_gdal_values(sat_gdal)
coord_sat = georef.read_gdal_coordinates(sat_gdal)
proj_sat = georef.read_gdal_projection(sat_gdal)
coord_sat = georef.reproject(coord_sat, projection_source=proj_sat,
projection_target=proj_radar)
coord_radar = coord
interp = ipol.Nearest(coord_sat[..., 0:2].reshape(-1, 2),
coord_radar[..., 0:2].reshape(-1, 2))
val_sat = interp(val_sat.ravel()).reshape(val.shape)
Estimate localisation errors¶
In [6]:
timelag = 9 * 60
wind = 10
error = np.absolute(timelag) * wind
Identify clutter based on collocated cloudtype¶
In [7]:
clutter = cl.filter_cloudtype(val[0, ...], val_sat[0, ...],
scale=rscale, smoothing=error)
Plot the results¶
In [8]:
fig = plt.figure(figsize=(16,8))
ax = fig.add_subplot(131)
ax, pm = vis.plot_ppi(val[0, ...], ax=ax)
plt.colorbar(pm, shrink=0.5)
plt.title('Radar reflectivity')
ax = fig.add_subplot(132)
ax, pm = vis.plot_ppi(val_sat[0, ...], ax=ax)
plt.colorbar(pm, shrink=0.5)
plt.title('Satellite cloud classification')
ax = fig.add_subplot(133)
ax, pm = vis.plot_ppi(clutter, ax=ax)
plt.title('Detected clutter')
Out[8]:
Text(0.5,1,'Detected clutter')

Heuristic clutter detection based on distribution properties (“histo cut”)¶
Detects areas with anomalously low or high average reflectivity or precipitation. It is recommended to use long term average or sums (months to year).
In [1]:
import wradlib.clutter as clutter
from wradlib.vis import plot_ppi
import wradlib.util as util
import numpy as np
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Load annual rainfall acummulation example (from DWD radar Feldberg)¶
In [2]:
filename = util.get_wradlib_data_file('misc/annual_rainfall_fbg.gz')
yearsum = np.loadtxt(filename)
Apply histo-cut filter to retrieve boolean array that highlights clutter as well as beam blockage¶
In [3]:
mask = clutter.histo_cut(yearsum)
Plot results¶
In [4]:
fig = pl.figure(figsize=(14,8))
ax = fig.add_subplot(121)
ax, pm = plot_ppi(np.log(yearsum), ax=ax)
pl.title("Logarithm of annual precipitation sum")
pl.colorbar(pm, shrink=0.75)
ax = fig.add_subplot(122)
ax, pm = plot_ppi(mask.astype(np.uint8), ax=ax)
pl.title("Map of execptionally low and high values\n(clutter and beam blockage)")
pl.colorbar(pm, shrink=0.75)
Out[4]:
<matplotlib.colorbar.Colorbar at 0x7f3ef32ae358>

This notebook is part of the \(\omega radlib\) documentation: http://docs.wradlib.org.
Copyright (c) \(\omega radlib\) developers. Distributed under the MIT License. See LICENSE.txt for more info.
Simple fuzzy echo classification from dual-pol moments¶
In [1]:
import wradlib
from wradlib.util import get_wradlib_data_file
import os
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
plt.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Setting the file paths¶
In [2]:
rhofile = get_wradlib_data_file('netcdf/TAG-20120801-140046-02-R.nc')
phifile = get_wradlib_data_file('netcdf/TAG-20120801-140046-02-P.nc')
reffile = get_wradlib_data_file('netcdf/TAG-20120801-140046-02-Z.nc')
dopfile = get_wradlib_data_file('netcdf/TAG-20120801-140046-02-V.nc')
zdrfile = get_wradlib_data_file('netcdf/TAG-20120801-140046-02-D.nc')
mapfile = get_wradlib_data_file('hdf5/TAG_cmap_sweeps_0204050607.hdf5')
Read the data (radar moments and static clutter map)¶
In [3]:
# We need to organize our data as a dictionary
dat = {}
dat["rho"], attrs_rho = wradlib.io.read_edge_netcdf(rhofile)
dat["phi"], attrs_phi = wradlib.io.read_edge_netcdf(phifile)
dat["ref"], attrs_ref = wradlib.io.read_edge_netcdf(reffile)
dat["dop"], attrs_dop = wradlib.io.read_edge_netcdf(dopfile)
dat["zdr"], attrs_zdr = wradlib.io.read_edge_netcdf(zdrfile)
dat["map"] = wradlib.io.from_hdf5(mapfile)[0][0]
Identify non-meteorological echoes using fuzzy echo classification¶
See Crisologo et al. (2015) and Vulpiani et al. (2012) for details.
In [4]:
weights = {"zdr": 0.4,
"rho": 0.4,
"rho2": 0.4,
"phi": 0.1,
"dop": 0.1,
"map": 0.5}
cmap, nanmask = wradlib.clutter.classify_echo_fuzzy(dat,
weights=weights,
thresh=0.5)
View classfication results¶
In [5]:
fig = plt.figure(figsize=(18,16))
# Horizontal reflectivity
ax = plt.subplot(121, aspect="equal")
ax, pm = wradlib.vis.plot_ppi(np.ma.masked_invalid(dat["ref"]), ax=ax)
ax = wradlib.vis.plot_ppi_crosshair(site=(0,0),
ranges=[80,160,240])
plt.xlim(-240,240)
plt.ylim(-240,240)
plt.xlabel("# bins from radar")
plt.ylabel("# bins from radar")
cbar = plt.colorbar(pm, shrink=0.3)
cbar.set_label("dBZ", fontsize = "large")
# Echo classification
ax = plt.subplot(122, aspect="equal")
ax, pm = wradlib.vis.plot_ppi(np.ma.masked_array(cmap.astype(np.uint8),
np.isnan(dat["ref"]), ax=ax),
cmap="bwr")
ax = wradlib.vis.plot_ppi_crosshair(site=(0,0),
ranges=[80,160,240])
plt.xlim(-240,240)
plt.ylim(-240,240)
plt.xlabel("# bins from radar")
plt.ylabel("# bins from radar")
cbar = plt.colorbar(pm, shrink=0.3)
cbar.set_label("meterol. echo=0 - non-meteorol. echo=1",
fontsize = "large")


Georeferencing¶
This section provides a collection of example code snippets to show how georeferencing of radar and ancillary data is done in \(\omega radlib\).
Computing cartesian and geographical coordinates for polar data¶
In [1]:
import numpy as np
import wradlib.georef as georef
import wradlib.io as io
import wradlib.util as util
import warnings
warnings.filterwarnings('ignore')
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Read the data¶
Here, we use an OPERA hdf5 dataset.
In [2]:
filename = 'hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf'
filename = util.get_wradlib_data_file(filename)
pvol = io.read_opera_hdf5(filename)
Count the number of datasets¶
In [3]:
ntilt = 1
for i in range(100):
try:
pvol["dataset%d/what" % ntilt]
ntilt += 1
except Exception:
ntilt -= 1
break
Define radar location and scan geometry¶
In [4]:
nrays = int(pvol["dataset1/where"]["nrays"])
nbins = int(pvol["dataset1/where"]["nbins"])
rscale = int(pvol["dataset1/where"]["rscale"])
coord = np.empty((ntilt, nrays, nbins, 3))
for t in range(ntilt):
elangle = pvol["dataset%d/where" % (t + 1)]["elangle"]
coord[t, ...] = georef.sweep_centroids(nrays, rscale, nbins, elangle)
# ascale = math.pi / nrays
sitecoords = (pvol["where"]["lon"], pvol["where"]["lat"],
pvol["where"]["height"])
print(coord.shape)
(5, 360, 960, 3)
Retrieve azimuthal equidistant coordinates and projection¶
In [5]:
coords, proj_radar = georef.spherical_to_xyz(coord[..., 0],
np.degrees(coord[..., 1]),
coord[..., 2], sitecoords)
test = coords[0, 90, 0:960:60, 0]
print(test)
[1.24984800e+02 1.51230048e+04 3.01206529e+04 4.51178353e+04
6.01144584e+04 7.51104287e+04 9.01056525e+04 1.05100036e+05
1.20093487e+05 1.35085910e+05 1.50077213e+05 1.65067302e+05
1.80056083e+05 1.95043465e+05 2.10029352e+05 2.25013652e+05]
Retrieve geographic coordinates (longitude and latitude)¶
Using convenience function spherical_to_proj.¶
In [6]:
lonlatalt = georef.spherical_to_proj(coord[..., 0],
np.degrees(coord[..., 1]),
coord[..., 2], sitecoords)
test = lonlatalt[0, 90, 0:960:60, 0]
print(test)
[5.50734017 5.71615328 5.92494778 6.13371911 6.34246274 6.55117413
6.75984874 6.96848204 7.17706951 7.38560664 7.5940889 7.8025118
8.01087084 8.21916154 8.42737941 8.63552 ]
Using reproject¶
In [7]:
lonlatalt1 = georef.reproject(coords, projection_source=proj_radar,
projection_target=georef.get_default_projection())
test = lonlatalt1[0, 90, 0:960:60, 0]
print(test)
[5.50734017 5.71615328 5.92494778 6.13371911 6.34246274 6.55117413
6.75984874 6.96848204 7.17706951 7.38560664 7.5940889 7.8025118
8.01087084 8.21916154 8.42737941 8.63552 ]
Example for georeferencing a radar dataset¶
In [1]:
import wradlib.georef as georef
import numpy as np
import matplotlib.pyplot as pl
import matplotlib as mpl
from matplotlib.patches import Rectangle
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
1st step: Compute centroid coordinates and vertices of all radar bins in WGS84 (longitude and latitude).
In [2]:
# Define the polar coordinates and the site coordinates in lat/lon
r = np.arange(1, 129) * 1000
az = np.linspace(0, 360, 361)[0:-1]
# Site coordinates for different DWD radar locations (you choose)
# LAT: drs: 51.12527778 ; fbg: 47.87444444 ; tur: 48.58611111 ; # muc: 48.3372222
# LON: drs: 13.76972222 ; fbg: 8.005 ; tur: 9.783888889 ; muc: 11.61277778
sitecoords = (9.7839, 48.5861)
We can now generate the polgon vertices of the radar bins - with each vertex in lon/lat coordinates.
In [3]:
proj_wgs84 = georef.epsg_to_osr(4326)
polygons = georef.spherical_to_polyvert(r, az, 0, sitecoords,
proj=proj_wgs84)
polygons = polygons[..., 0:2]
… or we can compute the corresponding centroids of all bins - - with each centroid in lon/lat coordinates.
In [4]:
cent_coords = georef.spherical_to_centroids(r, az, 0, sitecoords,
proj=proj_wgs84)
cent_lon = cent_coords[..., 0]
cent_lat = cent_coords[..., 1]
In order to understand how vertices and centroids correspond, we can plot them together.
In [5]:
fig = pl.figure(figsize=(16, 16))
aspect = ( cent_lon.max()-cent_lon.min() ) / ( cent_lat.max()-cent_lat.min() )
ax = fig.add_subplot(121, aspect = aspect )
polycoll = mpl.collections.PolyCollection(polygons, closed=True,
facecolors='None', linewidth=0.1)
ax.add_collection(polycoll, autolim=True)
#ax.plot(cent_lon, cent_lat, 'r+')
pl.title('Zoom in\n(only possible for interactive plots).')
ax.add_patch(Rectangle((sitecoords[0]+0.25, sitecoords[1]+0.25), 0.2, 0.2/aspect, edgecolor="red", facecolor="None", zorder=3))
pl.xlim(cent_lon.min(), cent_lon.max())
pl.ylim(cent_lat.min(), cent_lat.max())
ax = fig.add_subplot(122, aspect = aspect)
polycoll = mpl.collections.PolyCollection(polygons, closed=True,
facecolors='None')
ax.add_collection(polycoll, autolim=True)
ax.plot(cent_lon, cent_lat, 'r+')
pl.title('Zoom into red box of left plot')
pl.xlim(sitecoords[0]+0.25, sitecoords[0]+0.25+0.2)
pl.ylim(sitecoords[1]+0.25, sitecoords[1]+0.25+0.2/aspect)
Out[5]:
(48.8361, 48.96877939304968)

2nd step: Reproject the centroid coordinates to Gauss-Krueger Zone 3 (i.e. EPSG-Code 31467).
In [6]:
proj_gk3 = georef.epsg_to_osr(31467)
x, y = georef.reproject(cent_lon, cent_lat, projection_targe=proj_gk3)
RADOLAN Grid¶
Polar Stereographic Projection¶
The projected composite raster is equidistant with a grid-spacing of 1.0 km in most cases. There are composites which have 2.0 km grid-spacing (e.g. PC).
There are three different grid sizes, the well-known 900 rows by 900 columns (normal), 1500 rows by 1400 columns (extended, european) and 460 rows by 460 columns (small).
Common to all is that the plane of projection intersects the earth sphere at \(\phi_0 = 60.0^{\circ}N\). The cartesian co-ordinate system is aligned parallel to the \(\lambda_0 = 10.0^{\circ}E\) meridian.
The reference point (\(\lambda_m\), \(\phi_m\)) is \(9.0^{\circ}E\) and \(51.0^{\circ}N\), which is the center of the two smaller grids. The extended grid has an offset in respect to this reference point of 350km by 150km.
The earth as sphere with an radius of 6370.04 km is used for all calculations.
With formulas (1), (2) and (3) the geographic reference points (\(\lambda\), \(\phi\)) can be converted to projected cartesian coordinates. The calculated (x y) is the distance vector to the origign of the cartesian coordinate system (north pole).
\(\begin{equation} x = R * M(\phi) * cos(\phi) * sin(\lambda - \lambda_0) \tag{1} \end{equation}\)
\(\begin{equation} y = -R * M(\phi) * cos(\phi) * cos(\lambda - \lambda_0) \tag{2} \end{equation}\)
\(\begin{equation} M(\phi) = \frac {1 + sin(\phi_0)} {1 + sin(\phi)} \tag{3} \end{equation}\)
Assumed the point (\(10.0^{\circ}E\), \(90.0^{\circ}N\)) is defined as coordinate system origin. Then all ccordinates can be calculated with the known grid-spacing d as:
\(\begin{equation} x = x_0 + d * (j - j_0) \tag{4} \end{equation}\)
\(\begin{equation} y = y_0 + d * (i - i_0) \tag{5} \end{equation}\)
with i, j as cartesian indices.
\(\omega radlib\) provides the convenience function
wradlib.georef.get_radolan_grid()
which returns the radolan grid for further processing. It takes
nrows
and ncols
as parameters and returns the projected
cartesian coordinates or the wgs84 coordinates (keyword arg wgs84=True)
as numpy ndarray (nrows x ncols x 2).
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
In [2]:
radolan_grid_xy = wrl.georef.get_radolan_grid(900,900)
print("{0}, ({1:.4f}, {2:.4f})".format(radolan_grid_xy.shape, *radolan_grid_xy[0,0,:]))
(900, 900, 2), (-523.4622, -4658.6447)
In [3]:
radolan_grid_ll = wrl.georef.get_radolan_grid(900,900, wgs84=True)
print("{0}, ({1:.4f}, {2:.4f})".format(radolan_grid_ll.shape, *radolan_grid_ll[0,0,:]))
(900, 900, 2), (3.5889, 46.9526)
Inverse Polar Stereographic Projection¶
The geographic coordinates of specific datapoints can be calculated by using the cartesian coordinates (x,y) and the following formulas:
\(\begin{equation} \lambda = \arctan\left(\frac {-x} {y}\right) + \lambda_0 \tag{6} \end{equation}\)
\(\begin{equation} \phi = \arcsin\left(\frac {R^2 * \left(1 + \sin\phi_0\right)^2 - \left(x^2 + y^2\right)} {R^2 * \left(1 + \sin\phi_0\right)^2 + \left(x^2 + y^2\right)}\right) \tag{7} \end{equation}\)
Standard Formats¶
WKT-String¶
The German Weather Service provides a WKT-string. This WKT (well known text) is used to create the osr-object representation of the radolan projection.
For the scale_factor the intersection of the projection plane with the earth sphere at \(60.0^{\circ}N\) has to be taken into account:
\(\begin{equation} scale\_factor = \frac {1 + \sin\left(60.^{\circ}\right)} {1 + \sin\left(90.^{\circ}\right)} = 0.93301270189 \tag{8} \end{equation}\)
Also, the PROJECTION["Stereographic_North_Pole"]
isn’t known within
GDAL/OSR. It has to be changed to the known
PROJECTION["polar_stereographic"]
.
With these adaptions we finally yield the Radolan Projection as WKT-string. This WKT-string is used within \(\omega radlib\) to create the osr-object by using the helper-function wradlib.georef.create_osr().
In [4]:
proj_stereo = wrl.georef.create_osr("dwd-radolan")
print(proj_stereo)
PROJCS["Radolan projection",
GEOGCS["Radolan Coordinate System",
DATUM["Radolan Kugel",
SPHEROID["Erdkugel",6370040.0,0.0]],
PRIMEM["Greenwich",0.0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.017453292519943295],
AXIS["Longitude",EAST],
AXIS["Latitude",NORTH]],
PROJECTION["polar_stereographic"],
PARAMETER["central_meridian",10.0],
PARAMETER["latitude_of_origin",60.0],
PARAMETER["scale_factor",0.9330127019],
PARAMETER["false_easting",0.0],
PARAMETER["false_northing",0.0],
UNIT["m*1000.0",1000.0],
AXIS["X",EAST],
AXIS["Y",NORTH]]
PROJ.4¶
Using the above WKT-String the PROJ.4 representation can be derived as:
+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189
+x_0=0 +y_0=0 +a=6370040 +b=6370040 +to_meter=1000 +no_defs
This PROJ.4-string can also be used to create the osr-object by using the helper-function wradlib.georef.proj4_to_osr():
In [5]:
# create radolan projection osr object
dwd_string = ('+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189'
'+x_0=0 +y_0=0 +a=6370040 +b=6370040 +to_meter=1000 +no_defs')
proj_stereo = wrl.georef.proj4_to_osr(dwd_string)
print(proj_stereo)
PROJCS["unnamed",
GEOGCS["unnamed ellipse",
DATUM["unknown",
SPHEROID["unnamed",6370040,0]],
PRIMEM["Greenwich",0],
UNIT["degree",0.0174532925199433]],
PROJECTION["Polar_Stereographic"],
PARAMETER["latitude_of_origin",90],
PARAMETER["central_meridian",10],
PARAMETER["scale_factor",0.93301270189],
PARAMETER["false_easting",0],
PARAMETER["false_northing",0],
UNIT["kilometre",1000]]
Grid Reprojection¶
Within \(\omega radlib\) the wradlib.georef.reproject() function can be used to convert the radolan grid data from xy-space to lonlat-space and back. First, we need to create the necessary Spatial Reference Objects for the RADOLAN-projection and wgs84.
In [6]:
from osgeo import osr
proj_stereo = wrl.georef.create_osr("dwd-radolan")
proj_wgs = osr.SpatialReference()
proj_wgs.ImportFromEPSG(4326)
print(proj_wgs)
GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]]
Then, we call reproject
with the osr-objects as
projection_source
and projection_target
parameters.
In [7]:
radolan_grid_ll = wrl.georef.reproject(radolan_grid_xy, projection_source=proj_stereo, projection_target=proj_wgs)
print("{0}, ({1:.4f}, {2:.4f})".format(radolan_grid_ll.shape, *radolan_grid_ll[0,0,:]))
(900, 900, 2), (3.5889, 46.9526)
And the other way round.
In [8]:
radolan_grid_xy = wrl.georef.reproject(radolan_grid_ll, projection_source=proj_wgs, projection_target=proj_stereo)
print("{0}, ({1:.4f}, {2:.4f})".format(radolan_grid_xy.shape, *radolan_grid_xy[0,0,:]))
(900, 900, 2), (-523.4622, -4658.6447)
In the following example the RADOLAN grid is projected to wgs84 and GaussKrüger Zone3.
In [9]:
# create Gauss Krueger zone 3 projection osr object
proj_gk3 = osr.SpatialReference()
proj_gk3.ImportFromEPSG(31467)
# transform radolan polar stereographic projection to wgs84 and then to gk3
radolan_grid_ll = wrl.georef.reproject(radolan_grid_xy,
projection_source=proj_stereo,
projection_target=proj_wgs)
radolan_grid_gk = wrl.georef.reproject(radolan_grid_ll,
projection_source=proj_wgs,
projection_target=proj_gk3)
lon_wgs0 = radolan_grid_ll[:, :, 0]
lat_wgs0 = radolan_grid_ll[:, :, 1]
x_gk3 = radolan_grid_gk[:, :, 0]
y_gk3 = radolan_grid_gk[:, :, 1]
x_rad = radolan_grid_xy[:, :, 0]
y_rad = radolan_grid_xy[:, :, 1]
print("\n------------------------------")
print("source radolan x,y-coordinates")
print(u" {0} {1} ".format('x [km]', 'y [km]'))
print("ll: {:10.4f} {:10.3f} ".format(x_rad[0, 0], y_rad[0, 0]))
print("lr: {:10.4f} {:10.3f} ".format(x_rad[0, -1], y_rad[0, -1]))
print("ur: {:10.4f} {:10.3f} ".format(x_rad[-1, -1], y_rad[-1, -1]))
print("ul: {:10.4f} {:10.3f} ".format(x_rad[-1, 0], y_rad[-1, 0]))
print("\n--------------------------------------")
print("transformed radolan lonlat-coordinates")
print(u" {0} {1} ".format('lon [degE]', 'lat [degN]'))
print("ll: {:10.4f} {:10.4f} ".format(lon_wgs0[0, 0], lat_wgs0[0, 0]))
print("lr: {:10.4f} {:10.4f} ".format(lon_wgs0[0, -1], lat_wgs0[0, -1]))
print("ur: {:10.4f} {:10.4f} ".format(lon_wgs0[-1, -1], lat_wgs0[-1, -1]))
print("ul: {:10.4f} {:10.4f} ".format(lon_wgs0[-1, 0], lat_wgs0[-1, 0]))
print("\n-----------------------------------")
print("transformed radolan gk3-coordinates")
print(u" {0} {1} ".format('easting [m]', 'northing [m]'))
print("ll: {:10.0f} {:10.0f} ".format(x_gk3[0, 0], y_gk3[0, 0]))
print("lr: {:10.0f} {:10.0f} ".format(x_gk3[0, -1], y_gk3[0, -1]))
print("ur: {:10.0f} {:10.0f} ".format(x_gk3[-1, -1], y_gk3[-1, -1]))
print("ul: {:10.0f} {:10.0f} ".format(x_gk3[-1, 0], y_gk3[-1, 0]))
------------------------------
source radolan x,y-coordinates
x [km] y [km]
ll: -523.4622 -4658.645
lr: 375.5378 -4658.645
ur: 375.5378 -3759.645
ul: -523.4622 -3759.645
--------------------------------------
transformed radolan lonlat-coordinates
lon [degE] lat [degN]
ll: 3.5889 46.9526
lr: 14.6087 47.0711
ur: 15.7042 54.7327
ul: 2.0736 54.5790
-----------------------------------
transformed radolan gk3-coordinates
easting [m] northing [m]
ll: 3088210 5215765
lr: 3926038 5230008
ur: 3931614 6087692
ul: 3052550 6072015
Plot additional geodata¶
- underlay e.g. terrain data from a Digital Elevation Model (DEM)
- overlay features such as administrative borders, rivers, catchments, rain gauges, cities, …
Here, we create a map without radar data to concentrate on the other layers.
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
# Some more matplotlib tools we will need...
import matplotlib.ticker as ticker
from matplotlib.colors import LogNorm
from mpl_toolkits.axes_grid1 import make_axes_locatable
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Plotting a Digital Elevation Model (DEM)¶
We use a preprocessed geotiff which was created from
**SRTM** data via gdal
gdalwarp -te 88. 20. 93. 27. srtm_54_07.tif srtm_55_07.tif srtm_54_08.tif srtm_55_08.tif bangladesh.tif
Here we - read the DEM via
wradlib.io.open_raster
and extracted via
wradlib.georef.extract_raster_dataset.
- resample the data to a (lon/lat) grid with spacing=0.005
.
Note: we organise the code in functions which we can re-use in this notebook.
In [2]:
def plot_dem(ax):
filename = wrl.util.get_wradlib_data_file('geo/bangladesh.tif')
ds = wrl.io.open_raster(filename)
# pixel_spacing is in output units (lonlat)
ds = wrl.georef.reproject_raster_dataset(ds, spacing=0.005)
rastervalues, rastercoords, proj = wrl.georef.extract_raster_dataset(ds)
# specify kwargs for plotting, using terrain colormap and LogNorm
dem = ax.pcolormesh(rastercoords[..., 0], rastercoords[..., 1],
rastervalues, cmap=pl.cm.terrain, norm=LogNorm(),
vmin=1, vmax=3000)
# make some space on the right for colorbar axis
div1 = make_axes_locatable(ax)
cax1 = div1.append_axes("right", size="5%", pad=0.1)
# add colorbar and title
# we use LogLocator for colorbar
cb = pl.gcf().colorbar(dem, cax=cax1,
ticks=ticker.LogLocator(subs=range(10)))
cb.set_label('terrain height [m]')
In [3]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_dem(ax)

Plotting borders¶
For country borders, we use ESRI Shapfiles from Natural Earth Data.
We extract features using - the OGR.Layer
AttributeFilter
and -
the
wradlib.georef.get_vector_coordinates
function.
The plot overlay is done via wradlib.vis.add_lines.
In [4]:
def plot_borders(ax):
# country list
countries = ['India', 'Nepal', 'Bhutan', 'Myanmar']
# open the input data source and get the layer
filename = wrl.util.get_wradlib_data_file('geo/ne_10m_admin_0_boundary_'
'lines_land.shp')
dataset, inLayer = wrl.io.open_vector(filename)
# iterate over countries, filter accordingly, get coordinates and plot
for item in countries:
# SQL-like selection syntax
fattr = "(adm0_left = '" + item + "' or adm0_right = '" + item + "')"
inLayer.SetAttributeFilter(fattr)
# get borders and names
borders, keys = wrl.georef.get_vector_coordinates(inLayer, key='name')
wrl.vis.add_lines(ax, borders, color='black', lw=2, zorder=4)
ax.autoscale()
In [5]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_dem(ax)
plot_borders(ax)
ax.set_xlim((88, 93))
ax.set_ylim((20, 27))
Out[5]:
(20, 27)

Plotting Rivers¶
For rivers, we use ESRI Shapfiles from FAO and Natural Earth Data.
We extract features using - the OGR.Layer
SpatialFilter
and -
the
wradlib.georef.get_vector_coordinates
function.
Then we use wradlib.vis.add_lines again for the overlay.
In [6]:
def plot_rivers(ax):
# plot rivers from esri vector shape, filter spatially
# http://www.fao.org/geonetwork/srv/en/metadata.show?id=37331
# open the input data source and get the layer
filename = wrl.util.get_wradlib_data_file('geo/rivers_asia_37331.shp')
dataset, inLayer = wrl.io.open_vector(filename)
# do spatial filtering to get only geometries inside bounding box
inLayer.SetSpatialFilterRect(88, 20, 93, 27)
rivers, keys = wrl.georef.get_vector_coordinates(inLayer, key='MAJ_NAME')
# plot on ax1, and ax4
wrl.vis.add_lines(ax, rivers, color=pl.cm.terrain(0.), lw=0.5, zorder=3)
In [7]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_dem(ax)
plot_borders(ax)
plot_rivers(ax)
ax.set_xlim((88, 93))
ax.set_ylim((20, 27))
Out[7]:
(20, 27)

In [8]:
def plot_water(ax):
# plot rivers from esri vector shape, filter spatially
# plot rivers from NED
# open the input data source and get the layer
filename = wrl.util.get_wradlib_data_file('geo/ne_10m_rivers_lake_'
'centerlines.shp')
dataset, inLayer = wrl.io.open_vector(filename)
inLayer.SetSpatialFilterRect(88, 20, 93, 27)
rivers, keys = wrl.georef.get_vector_coordinates(inLayer)
wrl.vis.add_lines(ax, rivers, color=pl.cm.terrain(0.), lw=0.5, zorder=3)
In [9]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_dem(ax)
plot_borders(ax)
plot_rivers(ax)
plot_water(ax)
ax.set_xlim((88, 93))
ax.set_ylim((20, 27))
Out[9]:
(20, 27)

Plotting Cities¶
The 5 biggest cities of bangladesh are added using simple matplotlib functions.
In [10]:
def plot_cities(ax):
# plot city dots with annotation, finalize plot
# lat/lon coordinates of five cities in Bangladesh
lats = [23.73, 22.32, 22.83, 24.37, 24.90]
lons = [90.40, 91.82, 89.55, 88.60, 91.87]
cities = ['Dhaka', 'Chittagong', 'Khulna', 'Rajshahi', 'Sylhet']
for lon, lat, city in zip(lons, lats, cities):
ax.plot(lon, lat, 'ro', zorder=5)
ax.text(lon + 0.01, lat + 0.01, city, fontsize='large')
In [11]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_dem(ax)
plot_borders(ax)
plot_rivers(ax)
plot_water(ax)
plot_cities(ax)
ax.set_xlim((88, 93))
ax.set_ylim((20, 27))
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
ax.set_aspect('equal')
ax.set_title('Bangladesh')
Out[11]:
Text(0.5,1,'Bangladesh')

Plotting country patches¶
Plotting in “geographic projection” (WGS84)¶
Here, we plot countries as patches
on a lat/lon (WGS84) map (data
from Natural Earth Data again).
We again extract the features using - the OGR.Layer
SpatialFilter
and -
wradlib.georef.get_vector_coordinates.
Then the patches are added one by one via wradlib.vis.add_patches.
In [12]:
def plot_wgs84(ax):
from osgeo import osr
wgs84 = osr.SpatialReference()
wgs84.ImportFromEPSG(4326)
# some testing on additional axes
# add Bangladesh to countries
countries = ['India', 'Nepal', 'Bhutan', 'Myanmar', 'Bangladesh']
# create colors for country-patches
cm = pl.cm.jet
colors = []
for i in range(len(countries)):
colors.append(cm(1. * i / len(countries)))
# open the input data source and get the layer
filename = wrl.util.get_wradlib_data_file('geo/ne_10m_admin_0_'
'countries.shp')
dataset, layer = wrl.io.open_vector(filename)
# filter spatially and plot as PatchCollection on ax3
layer.SetSpatialFilterRect(88, 20, 93, 27)
patches, keys = wrl.georef.get_vector_coordinates(layer,
dest_srs=wgs84,
key='name')
i = 0
for name, patch in zip(keys, patches):
# why comes the US in here?
if name in countries:
wrl.vis.add_patches(ax, patch, facecolor=colors[i],
cmap=pl.cm.viridis, alpha=0.4)
i += 1
ax.autoscale(True)
ax.set_aspect('equal')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
ax.set_title('South Asia - WGS 84')
In [13]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_wgs84(ax)

Plotting with a map projection¶
Here, we plot countries as patches on a projected map.
We extract the features using - the OGR.Layer
AttributeFilter
and - the
wradlib.georef.get_vector_coordinates
function.
The coordinates of the features are reprojected on the fly using the
dest_srs
keyword of
wradlib.georef.get_vector_coordinates.
Then, the patches are added to the map via wradlib.vis.add_patches.
In [14]:
def plot_mercator(ax):
from osgeo import osr
proj = osr.SpatialReference()
# "Web Mercator" projection (used by GoogleMaps, OSM, ...)
proj.ImportFromEPSG(3857)
# add Bangladesh to countries
countries = ['India', 'Nepal', 'Bhutan', 'Myanmar', 'Bangladesh']
# create colors for country-patches
cm = pl.cm.jet
colors = []
for i in range(len(countries)):
colors.append(cm(1. * i / len(countries)))
# open the input data source and get the layer
filename = wrl.util.get_wradlib_data_file('geo/ne_10m_admin_0_'
'countries.shp')
dataset, layer = wrl.io.open_vector(filename)
# iterate over countries, filter by attribute,
# plot single patches on ax2
for i, item in enumerate(countries):
fattr = "name = '" + item + "'"
layer.SetAttributeFilter(fattr)
# get country patches and geotransform to destination srs
patches, keys = wrl.georef.get_vector_coordinates(layer,
dest_srs=proj,
key='name')
wrl.vis.add_patches(pl.gca(), patches, facecolor=colors[i])
ax.autoscale(True)
ax.set_aspect('equal')
ax.set_xlabel('X - Coordinate')
ax.set_ylabel('Y - Coordinate')
ax.ticklabel_format(style='sci', scilimits=(0, 0))
ax.set_title('South Asia in Web Mercator Projection ')
In [15]:
fig = pl.figure(figsize=(10,10))
ax = fig.add_subplot(111, aspect='equal')
plot_mercator(ax)

Zonal Statistics¶
The wradlib.zonalstats module provides classes and functions for calculation of zonal statistics for data on arbitrary grids and projections.
It provides classes for:
- managing georeferenced data (grid points or grid polygons, zonal polygons),
- calculation of geographic intersections and managing resulting vector data
- calculation of zonal statistics and managing result data as vector attributes
- output to vector and raster files available within ogr/gdal
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import matplotlib as mpl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
DataSource¶
The wradlib.zonalstats.DataSource class handles point or polygon vector data by wrapping ogr.DataSource with special functions.
The following example shows how to create different DataSource objects:
In [2]:
from osgeo import osr
# create gk zone 2 projection osr object
proj_gk2 = osr.SpatialReference()
proj_gk2.ImportFromEPSG(31466)
# Setting up DataSource
box0 = np.array([[2600000., 5630000.],[2600000., 5640000.],
[2610000., 5640000.],[2610000., 5630000.],
[2600000., 5630000.]])
box1 = np.array([[2610000., 5630000.],[2610000., 5640000.],
[2620000., 5640000.],[2620000., 5630000.],
[2610000., 5630000.]])
box2 = np.array([[2600000., 5640000.],[2600000., 5650000.],
[2610000., 5650000.],[2610000., 5640000.],
[2600000., 5640000.]])
box3 = np.array([[2610000., 5640000.],[2610000., 5650000.],
[2620000., 5650000.],[2620000., 5640000.],
[2610000., 5640000.]])
point0 = np.array(wrl.georef.get_centroid(box0))
point1 = np.array(wrl.georef.get_centroid(box1))
point2 = np.array(wrl.georef.get_centroid(box2))
point3 = np.array(wrl.georef.get_centroid(box3))
# creates Polygons in Datasource
poly = wrl.zonalstats.DataSource(np.array([box0, box1, box2, box3]), srs=proj_gk2, name='poly')
# creates Points in Datasource
point = wrl.zonalstats.DataSource(np.vstack((point0, point1, point2, point3)),
srs=proj_gk2, name='point')
Let’s have a look at the data, which will be exported as numpy arrays.
The property data
exports all available data:
In [3]:
print(poly.data)
print(point.data)
[[[2600000. 5630000.]
[2600000. 5640000.]
[2610000. 5640000.]
[2610000. 5630000.]
[2600000. 5630000.]]
[[2610000. 5630000.]
[2610000. 5640000.]
[2620000. 5640000.]
[2620000. 5630000.]
[2610000. 5630000.]]
[[2600000. 5640000.]
[2600000. 5650000.]
[2610000. 5650000.]
[2610000. 5640000.]
[2600000. 5640000.]]
[[2610000. 5640000.]
[2610000. 5650000.]
[2620000. 5650000.]
[2620000. 5640000.]
[2610000. 5640000.]]]
[[2605000. 5635000.]
[2615000. 5635000.]
[2605000. 5645000.]
[2615000. 5645000.]]
Currently data can also be retrieved by:
- index - wradlib.zonalstats.DataSource.get_data_by_idx(),
- attribute - wradlib.zonalstats.DataSource.get_data_by_att() and
- geometry - wradlib.zonalstats.DataSource.get_data_by_geom().
Now, with the DataSource being created, we can add/set attribute data of the features:
In [4]:
# add attribute
poly.set_attribute('mean', np.array([10.1, 20.2, 30.3, 40.4]))
point.set_attribute('mean', np.array([10.1, 20.2, 30.3, 40.4]))
Attributes associated with features can also be retrieved:
In [5]:
# get attributes
print(poly.get_attributes(['mean']))
# get attributes filtered
print(poly.get_attributes(['mean'], filt=('index', 2)))
[[10.1, 20.2, 30.3, 40.4]]
[[30.3]]
Finally, we can export the contained data to OGR/GDAL supported vector and raster files:
In [6]:
# dump as 'ESRI Shapefile', default
poly.dump_vector('test_poly.shp')
point.dump_vector('test_point.shp')
# dump as 'GeoJSON'
poly.dump_vector('test_poly.geojson', 'GeoJSON')
point.dump_vector('test_point.geojson', 'GeoJSON')
# dump as 'GTiff', default
poly.dump_raster('test_poly_raster.tif', attr='mean', pixel_size=100.)
# dump as 'netCDF'
poly.dump_raster('test_poly_raster.nc', 'netCDF', attr='mean', pixel_size=100.)
Rasterize layers
Rasterize layers
ZonalData¶
ZonalData is usually available as georeferenced regular gridded data. Here the wradlib.zonalstats.ZonalDataBase class manages the grid data, the zonal data (target polygons) and the intersection data of source grid and target polygons. Because the calculation of intersection is different for point grids and polygon grids, we have subclasses wradlib.zonalstats.ZonalDataPoly and wradlib.zonalstats.ZonalDataPoint.
Basically, wradlib.zonalstats.ZonalDataBase encapsulates three wradlib.zonalstats.DataSource objects:
- source grid (points/polygons)
- target polygons
- destination (intersection) (points/polygons)
The destination DataSource object is created from the provided source grid and target polygons at initialisation time.
As an example the creation of a wradlib.zonalstats.ZonalDataPoly class instance is shown:
In [7]:
# setup test grid and catchment
lon = 7.071664
lat = 50.730521
r = np.array(range(50, 100*1000 + 50 , 100))
a = np.array(range(0, 90, 1))
rays = a.shape[0]
bins = r.shape[0]
# setup OSR objects
proj_gk = osr.SpatialReference()
proj_gk.ImportFromEPSG(31466)
# create polar grid polygon vertices in gk
radar_gk = wrl.georef.spherical_to_polyvert(r, a, 0, (lon, lat),
proj=proj_gk)
radar_gk = radar_gk[..., 0:2]
# reshape
radar_gk.shape = (rays * bins, 5, 2)
box0 = np.array([[2600000., 5630000.],[2600000., 5640000.],
[2610000., 5640000.],[2610000., 5630000.],
[2600000., 5630000.]])
box1 = np.array([[2610000., 5630000.],[2610000., 5640000.],
[2620000., 5640000.],[2620000., 5630000.],
[2610000., 5630000.]])
targets = np.array([box0, box1])
zdpoly = wrl.zonalstats.ZonalDataPoly(radar_gk, targets, srs=proj_gk)
When calculationg the intersection, also weights are calculated for every source grid feature and attributed to the destination features.
With the property isecs
it is possible to retrieve the intersection
geometries as numpy array, further get-functions add to the
functionality:
In [8]:
# get intersections as numpy array
isecs = zdpoly.isecs
# get intersections for target polygon 0
isec0 = zdpoly.get_isec(0)
# get source indices referring to target polygon 0
ind0 = zdpoly.get_source_index(0)
print(isecs.shape, isec0.shape, ind0.shape)
(2,) (2152,) (2152,)
There are import/export functions using ESRI-Shapfile Format as data format. Next export and import is shown: wradlib.zonalstats.ZonalDataBase
In [9]:
zdpoly.dump_vector('test_zdpoly')
zdpoly_new = wrl.zonalstats.ZonalDataPoly('test_zdpoly')
ZonalStats¶
For ZonalStats the
wradlib.zonalstats.ZonalStatsBase
class and the two subclasses
wradlib.zonalstats.ZonalStatsPoly
and
wradlib.zonalstats.ZonalStatsPoint
are available. ZonalStatsBase encapsulates one ZonalData object.
Properties for simple access of ZonalData, intersection indices and
weights are provided. The following code will add mean
and var
attributes to the target DataSource:
In [10]:
# create ZonalStatsPoly instance
gc = wrl.zonalstats.ZonalStatsPoly(zdpoly_new)
# create some artificial data for processing using the features indices
count = radar_gk.shape[0]
data = 1000000. / np.array(range(count))
# calculate mean and variance
mean = gc.mean(data)
var = gc.var(data)
print("Average:", mean)
print("Variance:", var)
Average: [13.03540605 12.43517116]
Variance: [4.10381513 1.88270044]
Next we can export the resulting zonal statistics to vector and raster files:
In [11]:
# export to vector GeoJSON
gc.zdata.trg.dump_vector('test_zonal_json.geojson', 'GeoJSON')
# export 'mean' to raster netCDF
gc.zdata.trg.dump_raster('test_zonal_hdr.nc', 'netCDF', 'mean', pixel_size=100.)
Rasterize layers
The ZonalStats classes can also be used without any ZonalData by instantiating with precalculated index and weight values. Be sure to use matching ix, w and data arrays:
In [12]:
# get ix, and weight arrays
ix = gc.ix
w = gc.w
# instantiate new ZonlaStats object
gc1 = wrl.zonalstats.ZonalStatsPoly(ix=ix, w=w)
# caclulate statistics
avg = gc1.mean(data)
var = gc1.var(data)
print("Average:", avg)
print("Variance:", var)
Average: [13.03540605 12.43517116]
Variance: [4.10381513 1.88270044]
Examples¶
Examples of using Zonal Statistics working with rectangular grids as well as polar grids is shown in the Zonal Statistics Example notebook.
Match spaceborn SR (GPM/TRMM) with ground radars GR¶
The idea is to match ground radar (GR) and space-born radar (SR) measurements in order to create spatially and temporally coicident samples without interpolation. The procedure had been suggested by Schwaller and Morris (2011) and is based on the adaption by Warren, et. al. (2017).
The basic principle is illustrated in Fig. 2 of the original paper of Schwaller and Morris (2011):

image
Quote Warren, et.al: “[…] In this approach, intersections between indi vidual SR beams and GR elevation sweeps are identified and the reflectivity values from both instruments are averaged within a spatial neighborhood around the intersection. Specifically, SR data are averaged in range over the width of the GR beam at the GR range of the intersection, while GR data are averaged in the range–azimuth plane within the footprint of the SR beam. The result is a pair of reflectivity measurements corresponding to approximately the same volume of atmosphere. […]”.
This becomes clearer in Fig. 3:
Schwaller, MR, and Morris, KR. 2011. A ground validation network for the Global Precipitation Measurement mission. J. Atmos. Oceanic Technol., 28, 301-319.
Warren, R.A., A. Protat, S.T. Siems, H.A. Ramsay, V. Louf, M.J. Manton, and T.A. Kane, 0: Calibrating ground-based radars against TRMM and GPM. J. Atmos. Oceanic Technol., 0,
Conventions¶
This code is based on the following conventions:
gr
indicates ground radarsr
indicates space-born precipitation radar (TRMM or GPM)
The base routines are designed to process one GR sweep at a time. If a
full GR volume with nelev
of sweeps is available, you can iterate
over each sweep. In this code, ee
is an index that points to one of
the nelev
sweeps/elevation angles. Accordingly, a GR data set
will be organised as an array of shape
(nelev_gr, nray_gr, ngate_gr)
.
A SR data set is typically organised as arrays with dimensions
(nscan_sr, nray_sr, ngate_sr)
.
Please note: the GR and SR datasets are managed by using convenience
functions from the module file io_func.py
located in the same
directory as this notebook.
In [1]:
import warnings
warnings.filterwarnings('ignore')
import wradlib as wrl
import matplotlib.pyplot as pl
import matplotlib as mpl
from matplotlib.collections import PatchCollection
from matplotlib.colors import from_levels_and_colors
from matplotlib.path import Path
import matplotlib.patches as patches
import matplotlib.cm as cm
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
import datetime as dt
from osgeo import osr
In [2]:
# define GPM data set
gpm_file = wrl.util.get_wradlib_data_file('gpm/2A-CS-151E24S154E30S.GPM.Ku.V7-20170308.20141206-S095002-E095137.004383.V05A.HDF5')
# define matching ground radar file
gr2gpm_file = wrl.util.get_wradlib_data_file('hdf5/IDR66_20141206_094829.vol.h5')
# define TRMM data sets
trmm_2a23_file = wrl.util.get_wradlib_data_file('trmm/2A-CS-151E24S154E30S.TRMM.PR.2A23.20100206-S111425-E111526.069662.7.HDF')
trmm_2a25_file = wrl.util.get_wradlib_data_file('trmm/2A-CS-151E24S154E30S.TRMM.PR.2A25.20100206-S111425-E111526.069662.7.HDF')
# define matching ground radar file
gr2trmm_file = wrl.util.get_wradlib_data_file('hdf5/IDR66_20100206_111233.vol.h5')
In [3]:
# Space-born precipitation radar parameters
sr_pars = {"trmm": {
"zt": 402500., # orbital height of TRMM (post boost) APPROXIMATION!
"dr": 250., # gate spacing of TRMM
"gr_file": gr2trmm_file,
}, "gpm": {
"zt": 407000., # orbital height of GPM APPROXIMATION!
"dr": 125., # gate spacing of GPM
"gr_file": gr2gpm_file,
}}
In [4]:
# Set parameters for this procedure
bw_sr = 0.71 # SR beam width
platf = "trmm" # SR platform/product: one out of ["gpm", "trmm"]
zt = sr_pars[platf]["zt"] # SR orbit height (meters)
dr_sr = sr_pars[platf]["dr"] # SR gate length (meters)
gr_file = sr_pars[platf]["gr_file"]
ee = 2 # Index that points to the GR elevation angle to be used
Data Input¶
Read and organize the GR data¶
The following code reads data in ODIM H5 format. If your GR data is in some other format respective adaptions are needed.
In [5]:
def _get_tilts(dic):
i = 0
for k in dic.keys():
if 'dataset' in k:
i += 1
return i
def read_gr(filename, loaddata=True):
gr_data = wrl.io.read_generic_netcdf(filename)
dat = gr_data['what']['date']
tim = gr_data['what']['time']
date = dt.datetime.strptime(dat + tim, "%Y%d%m%H%M%S")
source = gr_data['what']['source']
lon = gr_data['where']['lon']
lat = gr_data['where']['lat']
alt = gr_data['where']['height']
if gr_data['what']['object'] == 'PVOL':
ntilt = _get_tilts(gr_data)
else:
raise ValueError('GR file is no PPI/Volume File')
ngate = np.zeros(ntilt, dtype=np.int16)
nbeam = np.zeros(ntilt)
elang = np.zeros(ntilt)
r0 = np.zeros(ntilt)
dr = np.zeros(ntilt)
a0 = np.zeros(ntilt)
for i in range(0, ntilt):
dset = gr_data['dataset{0}'.format(i+1)]
a0[i] = dset['how']['astart']
elang[i] = dset['where']['elangle']
ngate[i] = dset['where']['nbins']
r0[i] = dset['where']['rstart']
dr[i] = dset['where']['rscale']
nbeam[i] = dset['where']['nrays']
if ((len(np.unique(r0)) != 1) |
(len(np.unique(dr)) != 1) |
(len(np.unique(a0)) != 1) |
(len(np.unique(nbeam)) != 1) |
(nbeam[0] != 360)):
raise ValueError('GroundRadar Data layout dos not match')
gr_dict = {}
gr_dict.update({'source': source, 'date': date, 'lon': lon, 'lat': lat,
'alt': alt, 'ngate': ngate, 'nbeam': nbeam, 'ntilt': ntilt,
'r0': r0, 'dr': dr, 'a0': a0, 'elang': elang})
if not loaddata:
return gr_dict
sdate = []
refl = []
for i in range(0, ntilt):
dset = gr_data['dataset{0}'.format(i+1)]
dat = dset['what']['startdate']
tim = dset['what']['starttime']
date = dt.datetime.strptime(dat + tim, "%Y%d%m%H%M%S")
sdate.append(date)
data = dset['data1']
quantity = data['what']['quantity']
factor = data['what']['gain']
offset = data['what']['offset']
if quantity == 'DBZH':
dat = data['variables']['data']['data'] * factor + offset
refl.append(dat)
sdate = np.array(sdate)
refl = np.array(refl)
gr_dict.update({'sdate': sdate, 'refl': refl})
return gr_dict
In [6]:
# read matching GR data
gr_data = read_gr(gr_file)
Data handling¶
Extract relevant GR data and meta-data¶
In [7]:
# number of rays in gr sweep
nray_gr = gr_data['nbeam'].astype("i4")[ee]
# number of gates in gr beam
ngate_gr = gr_data['ngate'].astype("i4")[ee]
# number of sweeps
nelev = gr_data['ntilt']
# elevation of sweep (degree)
elev_gr = gr_data['elang'][ee]
# gate length (meters)
dr_gr = gr_data['dr'][ee]
# reflectivity array of sweep
ref_gr = gr_data['refl'][ee]
# sweep datetime stamp
date_gr = gr_data['sdate'][ee]
# range of first gate
r0_gr = gr_data['r0'][ee]
# azimuth angle of first beam
a0_gr = gr_data['a0'][ee]
# Longitude of GR
lon0_gr = gr_data['lon']
# Latitude of GR
lat0_gr = gr_data['lat']
# Altitude of GR (meters)
alt0_gr = gr_data['alt']
# Beam width of GR (degree)
bw_gr = 1.
print(elev_gr, lon0_gr)
1.2999999523162842 153.24000549316406
Calculate GR Bounding Box¶
In [8]:
coord = wrl.georef.sweep_centroids(nray_gr, dr_gr, ngate_gr, elev_gr)
coords = wrl.georef.spherical_to_proj(coord[..., 0],
np.degrees(coord[..., 1]),
coord[..., 2],
(lon0_gr, lat0_gr, alt0_gr))
lon = coords[..., 0]
lat = coords[..., 1]
alt = coords[..., 2]
bbox = wrl.zonalstats.get_bbox(lon, lat)
print("Radar bounding box:\n\t%.2f\n%.2f %.2f\n\t%.2f" %
(bbox['top'], bbox['left'], bbox['right'], bbox['bottom']))
Radar bounding box:
-26.37
151.72 154.76
-29.07
Read and organize the SR data¶
In [9]:
# read spaceborn SR data
if platf == "gpm":
sr_data = wrl.io.read_gpm(gpm_file, bbox)
elif platf == "trmm":
sr_data = wrl.io.read_trmm(trmm_2a23_file, trmm_2a25_file, bbox)
else:
raise("Invalid platform")
In [10]:
refl = sr_data['refl']
print(refl)
[[[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
...
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]]
[[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
...
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]]
[[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
...
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]]
...
[[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
...
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]]
[[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
...
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]]
[[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
...
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]
[-- -- -- ... 0.0 0.0 0.0]]]
Extract relevant SR data and meta-data¶
In [11]:
# Longitudes of SR scans
sr_lon = sr_data['lon']
# Latitudes of SR scans
sr_lat = sr_data['lat']
# Precip flag
pflag = sr_data['pflag']
# Number of scans on SR data
nscan_sr= sr_data['nscan']
# Number of rays in one SR scan
nray_sr = sr_data['nray']
# Number of gates in one SR ray
ngate_sr = sr_data['nbin']
In [12]:
print(sr_lon.shape)
(94, 49)
Georeferencing¶
Set fundamental georeferencing parameters¶
In [13]:
# Calculate equivalent earth radius
wgs84 = wrl.georef.get_default_projection()
re1 = wrl.georef.get_earth_radius(lat0_gr, wgs84)
print("Earth radius 1:", re1)
a = wgs84.GetSemiMajor()
b = wgs84.GetSemiMinor()
print("SemiMajor, SemiMinor:", a, b)
# Set up aeqd-projection gr-centered
rad = wrl.georef.proj4_to_osr(('+proj=aeqd +lon_0={lon:f} ' +
'+lat_0={lat:f} +a={a:f} ' +
'+b={b:f}').format(lon=lon0_gr,
lat=lat0_gr,
a=a, b=b))
re2 = wrl.georef.get_earth_radius(lat0_gr, rad)
print("Earth radius 2:", re2)
Earth radius 1: 6373541.039814419
SemiMajor, SemiMinor: 6378137.0 6356752.314245179
Earth radius 2: 6373541.039814381
Georeference GR data¶
In [14]:
# create gr range and azimuth arrays
rmax_gr = r0_gr + ngate_gr * dr_gr
r_gr = np.arange(0, ngate_gr) * dr_gr + dr_gr/2.
az_gr = np.arange(0, nray_gr) - a0_gr
print("Range/Azi-Shape:", r_gr.shape, az_gr.shape)
# create gr polar grid and calculate aeqd-xyz coordinates
gr_polargrid = np.meshgrid(r_gr, az_gr)
gr_xyz, rad = wrl.georef.spherical_to_xyz(gr_polargrid[0], gr_polargrid[1], elev_gr, (lon0_gr, lat0_gr, alt0_gr ))
print("XYZ-Grid-Shape:", gr_xyz.shape)
# create gr poygon array in aeqd-xyz-coordinates
gr_poly, rad1 = wrl.georef.spherical_to_polyvert(r_gr, az_gr, elev_gr, (lon0_gr, lat0_gr, alt0_gr))
print(gr_poly.shape, 360 * 600)
gr_poly.shape = (nray_gr, ngate_gr, 5, 3)
# get radar domain (outer ring)
gr_domain = gr_xyz[:,-1,0:2]
gr_domain = np.vstack((gr_domain, gr_domain[0]))
print("Domain-Shape:", gr_domain.shape)
Range/Azi-Shape: (600,) (360,)
XYZ-Grid-Shape: (360, 600, 3)
(216000, 5, 3) 216000
Domain-Shape: (361, 2)
Georeference SR data¶
In [15]:
sr_x, sr_y = wrl.georef.reproject(sr_lon, sr_lat,
projection_source=wgs84,
projection_target=rad)
sr_xy = np.dstack((sr_x, sr_y))
print("SR-GRID-Shapes:", sr_x.shape, sr_y.shape, sr_xy.shape)
SR-GRID-Shapes: (94, 49) (94, 49) (94, 49, 2)
Subset relevant SR data¶
In [16]:
# Create ZonalData for spatial subsetting (inside GR range domain)
# get precip indexes
print(sr_xy.shape)
print(pflag.shape)
precip_mask = (pflag == 2) & wrl.zonalstats.get_clip_mask(sr_xy, gr_domain, rad)
# get iscan/iray boolean arrays
print(precip_mask.shape, sr_xy.shape)
print(pflag.shape, sr_xy.reshape(-1, sr_xy.shape[-1]).shape)
pl.imshow(precip_mask)
(94, 49, 2)
(94, 49)
(94, 49) (94, 49, 2)
(94, 49) (4606, 2)
Out[16]:
<matplotlib.image.AxesImage at 0x7f82a3425630>

SR Parallax Correction¶
In [17]:
print("NRAY", nray_sr)
print("NBIN", ngate_sr)
# use localZenith Angle
alpha = sr_data['zenith']
beta = abs(-17.04 + np.arange(nray_sr) * bw_sr)
# Correct for parallax, get 3D-XYZ-Array
# xyzp_sr: Parallax corrected xyz coordinates
# r_sr_inv: range array from ground to SR platform
# zp: SR bin altitudes
xyp_sr, r_sr_inv, z_sr = wrl.georef.correct_parallax(sr_xy, ngate_sr, dr_sr, alpha)
print(xyp_sr.shape, r_sr_inv.shape, z_sr.shape)
xyzp_sr = np.concatenate((xyp_sr, z_sr[..., np.newaxis]),
axis=-1)
print(sr_xy.shape)
print("SR_XYP:", xyp_sr.shape, xyzp_sr.shape, r_sr_inv.shape, z_sr.shape)
NRAY 49
NBIN 80
(94, 49, 80, 2) (80,) (94, 49, 80)
(94, 49, 2)
SR_XYP: (94, 49, 80, 2) (94, 49, 80, 3) (80,) (94, 49, 80)
Compute spherical coordinates of SR bins with regard to GR¶
In [18]:
r_sr, az_sr, elev_sr = wrl.georef.xyz_to_spherical(xyzp_sr, alt0_gr, proj=rad)
#TODO: hardcoded 1.0
mask = (elev_sr > (1.0 - bw_gr/2.)) & (elev_sr < (1.0 + bw_gr/2.))
pl.figure()
pl.pcolormesh(mask[40,:,:].T)
Out[18]:
<matplotlib.collections.QuadMesh at 0x7f82a65e6b00>

Compute SR and GR pulse volumes¶
Calculate distance from orbit \(r_s\)¶
In [19]:
rs = wrl.georef.dist_from_orbit(zt, alpha, beta, r_sr_inv, re1)
SR pulse volume¶
In [20]:
# Small anngle approximation
vol_sr2 = np.pi * dr_sr * rs**2 * np.radians(bw_sr / 2.)**2
# Or using wradlib's native function
vol_sr = wrl.qual.pulse_volume(rs, dr_sr, bw_sr)
# Evaluate difference between both approaches
print("Min. difference (m3):", (vol_sr - vol_sr2).min())
print("Max. difference (m3): ", (vol_sr - vol_sr2).max())
print("Average rel. difference (%):", round(np.mean(vol_sr-vol_sr2)*100./np.mean(np.mean(vol_sr2)), 4))
# Verdict: differences are negligble - use wradlibs's native function!
Min. difference (m3): 113043.78644371033
Max. difference (m3): 137576.38737678528
Average rel. difference (%): 0.0026
GR pulse volume¶
In [21]:
# GR pulse volumes
# along one beam
vol_gr = wrl.qual.pulse_volume(r_gr, dr_gr, bw_gr)
# with shape (nray_gr, ngate_gr)
vol_gr = np.repeat(vol_gr, nray_gr).reshape((nray_gr, ngate_gr), order="F")
Calculate horizontal and vertical dimensions \(R_s\) and \(D_s\) of SR bins¶
In [22]:
Rs = 0.5 * (1 + np.cos(np.radians(alpha)))[:,:,np.newaxis] * rs * np.tan(np.radians(bw_sr/2.))
Ds = dr_sr / np.cos(np.radians(alpha))
Ds = np.broadcast_to(Ds[..., np.newaxis], Rs.shape)
Median Brightband Width/Height¶
In [23]:
print(z_sr.shape)
print(sr_data['zbb'].shape, sr_data['bbwidth'].shape, sr_data['quality'].shape)
ratio, ibb = wrl.qual.get_bb_ratio(sr_data['zbb'], sr_data['bbwidth'], sr_data['quality'], z_sr)
print(ratio.shape)
zbb = sr_data['zbb'].copy()
zbb[~ibb] = np.nan
print(np.nanmin(ratio[..., 9]), np.nanmax(ratio[..., 9]))
#pl.imshow(ratio, vmin=-10, vmax=30)
(94, 49, 80)
(94, 49) (94, 49) (94, 49)
(94, 49, 80)
-2.480953963698855 -2.302551401079081
Convert SR Ku reflectivities to S-band¶
Based on Cao et.al (2013)
In [24]:
ref_sr = sr_data['refl'].filled(np.nan)
print(ref_sr.shape, ratio.shape)
ref_sr_ss = np.zeros_like(ref_sr) * np.nan
ref_sr_sh = np.zeros_like(ref_sr) * np.nan
a_s, a_h = (wrl.trafo.KuBandToS.snow, wrl.trafo.KuBandToS.hail)
ia = (ratio >= 1)
ref_sr_ss[ia] = ref_sr[ia] + wrl.util.calculate_polynomial(ref_sr[ia], a_s[:,10])
ref_sr_sh[ia] = ref_sr[ia] + wrl.util.calculate_polynomial(ref_sr[ia], a_h[:,10])
ib = (ratio <= 0)
ref_sr_ss[ib] = ref_sr[ib] + wrl.util.calculate_polynomial(ref_sr[ib], a_s[:,0])
ref_sr_sh[ib] = ref_sr[ib] + wrl.util.calculate_polynomial(ref_sr[ib], a_h[:,0])
im = (ratio > 0) & (ratio < 1)
ind = np.round(ratio[im] * 10).astype(np.int)
ref_sr_ss[im] = ref_sr[im] + wrl.util.calculate_polynomial(ref_sr[im], a_s[:,ind])
ref_sr_sh[im] = ref_sr[im] + wrl.util.calculate_polynomial(ref_sr[im], a_h[:,ind])
# Jackson Tan's fix for C-band
is_cband = False
if (is_cband):
deltas = (ref_sr_ss - ref_sr) * 5.3 / 10.0
ref_sr_ss = outref_sr + deltas
deltah = (ref_sr_sh - ref_sr) * 5.3 / 10.0
ref_sr_sh = ref_sr + deltah
ref_sr_ss[ref_sr < 0] = np.nan
(94, 49, 80) (94, 49, 80)
Convert S-band GR reflectivities to Ku-band¶
Using the method of Liao and Meneghini (2009)
In [25]:
# Convert S-band GR reflectivities to Ku-band using method of Liao and Meneghini (2009)
ref_gr_ku = np.zeros_like(ref_gr) * np.nan
# Which zbb value should we take here???
# Q'n'Dirty: just take the mean of all SR profiles
# TODO: Consider zbb for each profile during the matching process
# Snow
ia = ( gr_xyz[...,2] >= np.nanmean(zbb) )
#ref_gr_ku[ia] = wrl.trafo.KuBandToS.snow[0] + wrl.trafo.KuBandToS.snow[1]*ref_gr[ia] + wrl.trafo.KuBandToS.snow[2]*ref_gr[ia]**2
ref_gr_ku[ia] = wrl.util.calculate_polynomial(ref_gr[ia], wrl.trafo.SBandToKu.snow)
# Rain
ib = ( gr_xyz[...,2] < np.nanmean(zbb) )
#ref_gr_ku[ib] = wrl.trafo.KuBandToS.rain[0] + wrl.trafo.KuBandToS.rain[1]*ref_gr[ia] + wrl.trafo.KuBandToS.rain[2]*ref_gr[ia]**2
ref_gr_ku[ib] = wrl.util.calculate_polynomial(ref_gr[ib], wrl.trafo.SBandToKu.rain)
# Jackson Tan's fix for C-band
is_cband = False
if (is_cband):
delta = (ref_gr_ku - ref_gr) * 5.3/10.0
ref_gr_ku = ref_gr + delta
Matching SR/GR¶
Identify which SR rays actually intersect with the GR sweep¶
Based on the above criteria (in radar range, precipitating SR profile) and based on SR elevation angle (with regard to GR).
In [26]:
# First assumption: no valid SR bins (all False)
valid = np.asarray(elev_sr, dtype=np.bool)==False
print(valid.shape, precip_mask.shape)
# SR is inside GR range and is precipitating
iscan = precip_mask.nonzero()[0]
iray = precip_mask.nonzero()[1]
valid[iscan,iray] = True
# SR bins intersect with GR sweep
valid = valid & (elev_sr >= (elev_gr-bw_gr/2.)) & (elev_sr <= (elev_gr+bw_gr/2.))
# Number of matching SR bins per profile
nvalids = np.sum(valid, axis=2)
# scan and ray indices for profiles with at least one valid bin
vscan, vray = np.where(nvalids>0)
# number of profiles with at least one valid bin
nprof = len(vscan)
print(vscan.shape)
print(valid.shape)
(94, 49, 80) (94, 49)
(1164,)
(94, 49, 80)
Averaging SR parameters¶
In [27]:
# average coordinates
xyz_v1 = xyzp_sr.copy()
print(xyz_v1.shape)
xyz_v1[~valid] = np.nan
xyz_c1 = xyzp_sr.copy()
xyz_c1[~valid] = 0
c = np.count_nonzero(xyz_c1[..., 0], axis=2)
ntotsr = c[vscan, vray]
xyz_m1 = np.nanmean(xyz_v1,axis=2)
xyz = xyz_m1[vscan, vray]
print(xyz.shape, c.shape)
# approximate Rs
rs_v1 = Rs.copy()
rs_v1[~valid] = np.nan
rs_m1 = np.nanmax(rs_v1, axis=2)
rs_prof = rs_m1[vscan, vray]
ds = rs_prof
# approximate Ds
ds_v1 = Ds.copy()
ds_v1[~valid] = np.nan
ds_m1 = np.nansum(ds_v1, axis=2)
ds_prof = ds_m1[vscan, vray]
dz = ds_prof
# approximate Vs
vs_v1 = vol_sr.copy()
vs_v1[~valid] = np.nan
vs_m1 = np.nansum(vs_v1, axis=2)
vs_prof = vs_m1[vscan, vray]
volsr1 = vs_prof
from mpl_toolkits.mplot3d import Axes3D
fig = pl.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xyz_m1[..., 0], xyz_m1[..., 1], xyz_m1[..., 2], c=c.ravel())
(94, 49, 80, 3)
(1164, 3) (94, 49)
Out[27]:
<mpl_toolkits.mplot3d.art3d.Path3DCollection at 0x7f82a67ce630>

Calculate spherical coordinates of SR sample volume with respect to GR¶
In [28]:
r_sr, az_sr, el_rs = wrl.georef.xyz_to_spherical(xyz, alt0_gr, proj=rad)
Average SR reflectivity¶
In [29]:
ref_sr_1 = wrl.trafo.idecibel(ref_sr)
ref_sr_1[~valid] = np.nan
refsr1a = np.nanmean(ref_sr_1, axis=2)[vscan,vray]
refsr1a = wrl.trafo.decibel(refsr1a)
ref_sr_2 = wrl.trafo.idecibel(ref_sr_ss)
ref_sr_2[~valid] = np.nan
refsr2a = np.nanmean(ref_sr_2, axis=2)[vscan,vray]
refsr2a = wrl.trafo.decibel(refsr2a)
ref_sr_3 = wrl.trafo.idecibel(ref_sr_sh)
ref_sr_3[~valid] = np.nan
refsr3a = np.nanmean(ref_sr_3, axis=2)[vscan,vray]
refsr3a = wrl.trafo.decibel(refsr3a)
print(refsr1a.shape)
(1164,)
Identify which GR bins actually intersect with the SR footprint¶
Create Zonal Data Source of matching SR profiles¶
In [30]:
zds = wrl.zonalstats.DataSource(xyz[:, 0:2].reshape(-1, 2), rad)
print(zds.ds.GetLayer().GetFeatureCount())
1164
Create SR beam polygons using \(R_s\)¶
In [31]:
tmp_trg_lyr = zds.ds.GetLayer()
trg_poly = []
for i, feat in enumerate(tmp_trg_lyr):
geom = feat.GetGeometryRef().Buffer(rs_prof[i])
poly = wrl.georef.ogr_to_numpy(geom)
trg_poly.append(poly)
Create ZonalDataPoly for GR and SR profiles¶
In [32]:
%%time
print("creating")
zdp = wrl.zonalstats.ZonalDataPoly(gr_poly[..., 0:2].reshape(-1, 5, 2), trg_poly, srs=rad)
zdp.dump_vector('m3d_zonal_poly_{0}'.format(platf))
creating
CPU times: user 1min 17s, sys: 1.74 s, total: 1min 19s
Wall time: 1min 19s
In [33]:
%%time
print("loading")
obj3 = wrl.zonalstats.ZonalStatsPoly('m3d_zonal_poly_{0}'.format(platf))
loading
CPU times: user 1min 54s, sys: 95.3 ms, total: 1min 54s
Wall time: 1min 54s
Average GR volume and reflectivity¶
In [34]:
%%time
print(obj3.ix.shape)
volgr1 = np.array([np.sum(vol_gr.ravel()[obj3.ix[i]])
for i in np.arange(len(obj3.ix))[~obj3.check_empty()]])
print(volgr1.shape)
ref_gr_i = wrl.trafo.idecibel(ref_gr.ravel())
ref_gr_ku_i = wrl.trafo.idecibel(ref_gr_ku.ravel())
refgr1a = np.array([np.nanmean(ref_gr_i[obj3.ix[i]])
for i in np.arange(len(obj3.ix))[~obj3.check_empty()]])
refgr1a = wrl.trafo.decibel(refgr1a)
refgr2a = np.array([np.nanmean(ref_gr_ku_i[obj3.ix[i]])
for i in np.arange(len(obj3.ix))[~obj3.check_empty()]])
refgr2a = wrl.trafo.decibel(refgr2a)
(1164,)
(1164,)
CPU times: user 692 ms, sys: 12.2 ms, total: 704 ms
Wall time: 691 ms
Diagnostic Plots¶
In [35]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr1a, refsr1a, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr1a[refsr1a>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr1a[refsr1a>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("uncorrected GR vs uncorrected SR")
Out[35]:
Text(0.5,0.98,'uncorrected GR vs uncorrected SR')

In [36]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr2a, refsr1a, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr1a[refsr1a>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr1a[refsr1a>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("corrected GR vs uncorrected SR")
Out[36]:
Text(0.5,0.98,'corrected GR vs uncorrected SR')

In [37]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr2a, refsr2a, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr2a[refsr2a>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr2a[refsr2a>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("corrected GR vs corrected SR snow")
Out[37]:
Text(0.5,0.98,'corrected GR vs corrected SR snow')

In [38]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr2a, refsr3a, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr2a[refsr3a>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr3a[refsr3a>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("corrected GR vs corrected SR hail")
Out[38]:
Text(0.5,0.98,'corrected GR vs corrected SR hail')

In [39]:
fig = pl.figure(figsize=(12,8))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(xyz[..., 0], xyz[...,1], c=refsr1a, cmap=pl.cm.viridis, vmin=10, vmax=50, edgecolor="None")
pl.title("SR reflectivity")
pl.xlim(-100000, 150000)
pl.ylim(-150000, 150000)
pl.grid()
ax = fig.add_subplot(122, aspect="equal")
pl.scatter(xyz[..., 0], xyz[...,1], c=refgr1a, cmap=pl.cm.viridis, vmin=10, vmax=50, edgecolor="None")
pl.title("GR reflectivity")
pl.xlim(-100000, 150000)
pl.ylim(-150000, 150000)
pl.grid()
fig.suptitle("uncorrected GR vs uncorrected SR")
pl.tight_layout()

Former Method using loop¶
In [40]:
# Lots of containers to store samples (only for one GR sweep angle!)
x = np.zeros(nprof)*np.nan # x coordinate of sample
y = np.zeros(nprof)*np.nan # y coordinate of sample
z = np.zeros(nprof)*np.nan # z coordinate of sample
dz = np.zeros(nprof)*np.nan # depth of sample
ds = np.zeros(nprof)*np.nan # width of sample
rs = np.zeros(nprof)*np.nan # range of sample from GR
refsr1 = np.zeros(nprof)*np.nan # SR reflectivity
refsr2 = np.zeros(nprof)*np.nan # SR reflectivity (S-band, snow)
refsr3 = np.zeros(nprof)*np.nan # SR reflectivity (S-band, hail)
refgr1 = np.zeros(nprof)*np.nan # GR reflectivity
refgr2 = np.zeros(nprof)*np.nan # GR reflectivity (Ku-band)
ntotpr = np.zeros(nprof,dtype="i4")# total number of SR bins in sample
nrej1 = np.zeros(nprof,dtype="i4")# number of rejected SR bins in sample
ntotgr = np.zeros(nprof,dtype="i4")# total number of GR bins in sample
nrej2 = np.zeros(nprof,dtype="i4")# number of rejected GR bins in sample
iref1 = np.zeros(nprof)*np.nan # path-integrated SR reflectivity
iref2 = np.zeros(nprof)*np.nan # path-integrated GR reflectivity
stdv1 = np.zeros(nprof)*np.nan # std. dev. of SR reflectivity in sample
stdv2 = np.zeros(nprof)*np.nan # std. dev. of GR reflectivity in sample
volsr = np.zeros(nprof)*np.nan # total volume of SR bins in sample
volgr = np.zeros(nprof)*np.nan # total volume of GR bins in sample
In [41]:
%%time
# Loop over relevant SR profiles
for ii, (ss, rr) in enumerate(zip(vscan,vray)):
# Index and count valid bins in each profile
ip = np.where(valid[ss,rr])[0]
numbins = len(ip)
ntotpr[ii]=numbins
if numbins == 0:
continue
# Compute the mean position of these bins
x[ii]=np.mean(xyzp_sr[ss,rr,ip,0])
y[ii]=np.mean(xyzp_sr[ss,rr,ip,1])
z[ii]=np.mean(xyzp_sr[ss,rr,ip,2])
# Thickness of the layer
dz[ii]=(numbins * dr_sr) / np.cos( np.radians(alpha[ss, rr]) )
# SR averaging volume
volsr[ii]=np.sum(vol_sr[ss, rr, ip])
# Note mean TRMM beam diameter
ds[ii]=np.radians(bw_sr) * np.mean( ( (zt-z[ii]) /
np.cos( np.radians(alpha[ss, rr]) ) ) )
# Note distance from radar
s=np.sqrt(x[ii]**2+y[ii]**2)
rs[ii]=(re2+z[ii]) * np.sin(s/re2) / np.cos(np.radians(elev_gr))
# This should not be required because we applied ZonalData
### Check that sample is within radar range
##if r[ii,jj]+ds[ii,jj]/2. gt rmax then continue
## THIS IS THE ORIGINAL IDL CODE - IS THIS A BUG???
##ref1[ii,jj]=MEAN(ref_sr1,/nan)
##ref3[ii,jj]=MEAN(ref_sr2,/nan)
##ref4[ii,jj]=MEAN(ref_sr3,/nan)
# Simple linear average of reflectivity
# - we can become fancier in the next step
# ATTENTION: NEED TO FLIP ARRAY
refsr1[ii]=np.nanmean(ref_sr[ss,rr,ip])
refsr2[ii]=np.nanmean(ref_sr_ss[ss,rr,ip])
refsr3[ii]=np.nanmean(ref_sr_sh[ss,rr,ip])
## Not sure why we need this...
### Note the number of rejected bins
##nrej1[ii,jj]=ROUND(TOTAL(FINITE(ref_sr1,/nan)))
##if FINITE(stdv1[ii,jj]) eq 0 and np-nrej1[ii,jj] gt 1 then STOP
# SHOULD WE USE ZONALDATA INSTEAD? COULD BE MORE ACCURATE, BUT ALSO SLOWER
# WE COULD BASICALLY START A NEW LOOP HERE AND RUN ZONALDATA BEFORE
# Compute the horizontal distance to all the GR bins
d = np.sqrt((gr_xyz[...,0]-x[ii])**2 + (gr_xyz[...,1]-y[ii])**2)
# Find all GR bins within the SR beam
aa, bb = np.where(d <= ds[ii]/2.)
# Store the number of bins
ntotgr[ii] = len(aa)
if len(aa) == 0:
continue
# Extract the relevant GR bins
# Compute the GR averaging volume
volgr[ii]=np.sum(vol_gr[aa,bb])
# Average over those bins that exceed the reflectivity threshold
# IDL code does exponential distance and volume weighting
# Let's try simple mean first,
# THEN ZonalStats!
refgr1[ii]=np.nanmean(ref_gr[aa,bb])
refgr2[ii]=np.nanmean(ref_gr_ku[aa,bb])
CPU times: user 3.47 s, sys: 16 ms, total: 3.48 s
Wall time: 3.48 s
In [42]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr1, refsr1, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr1[refsr1>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr1[refsr1>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("uncorrected GR vs uncorrected SR")
Out[42]:
Text(0.5,0.98,'uncorrected GR vs uncorrected SR')

In [43]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr2, refsr1, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr1[refsr1>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr1[refsr1>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("corrected GR vs uncorrected SR")
Out[43]:
Text(0.5,0.98,'corrected GR vs uncorrected SR')

In [44]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr2, refsr2, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr2[refsr2>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr2[refsr2>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("corrected GR vs corrected SR snow")
Out[44]:
Text(0.5,0.98,'corrected GR vs corrected SR snow')

In [45]:
fig = pl.figure(figsize=(12,5))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(refgr2, refsr3, marker="+", c="black")
pl.plot([0,60],[0,60], linestyle="solid", color="black")
pl.xlim(10,50)
pl.ylim(10,50)
pl.xlabel("GR reflectivity (dBZ)")
pl.ylabel("SR reflectivity (dBZ)")
ax = fig.add_subplot(122)
pl.hist(refgr2[refsr3>10], bins=np.arange(-10,50,5), edgecolor="None", label="GR")
pl.hist(refsr3[refsr3>-10], bins=np.arange(-10,50,5), edgecolor="red", facecolor="None", label="SR")
pl.xlabel("Reflectivity (dBZ)")
pl.legend()
fig.suptitle("corrected GR vs corrected SR hail")
Out[45]:
Text(0.5,0.98,'corrected GR vs corrected SR hail')

In [46]:
fig = pl.figure(figsize=(12,8))
ax = fig.add_subplot(121, aspect="equal")
pl.scatter(x, y, c=refsr1, cmap=pl.cm.viridis, vmin=10, vmax=50, edgecolor="None")
pl.title("SR reflectivity")
pl.xlim(-100000, 150000)
pl.ylim(-150000, 150000)
pl.grid()
ax = fig.add_subplot(122, aspect="equal")
pl.scatter(x, y, c=refgr1, cmap=pl.cm.viridis, vmin=10, vmax=50, edgecolor="None")
pl.title("GR reflectivity")
pl.xlim(-100000, 150000)
pl.ylim(-150000, 150000)
pl.grid()
fig.suptitle("uncorrected GR vs uncorrected SR")
pl.tight_layout()

How to use wradlib’s ipol module for interpolation tasks?¶
In [1]:
import wradlib.ipol as ipol
from wradlib.util import get_wradlib_data_file
from wradlib.vis import plot_ppi
import numpy as np
import matplotlib.pyplot as pl
import datetime as dt
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
1-dimensional example¶
Includes Nearest Neighbours, Inverse Distance Weighting, and Ordinary Kriging.
In [2]:
# Synthetic observations
xsrc = np.arange(10)[:, None]
vals = np.sin(xsrc).ravel()
# Define target coordinates
xtrg = np.linspace(0, 20, 100)[:, None]
# Set up interpolation objects
# IDW
idw = ipol.Idw(xsrc, xtrg)
# Nearest Neighbours
nn = ipol.Nearest(xsrc, xtrg)
# Linear
ok = ipol.OrdinaryKriging(xsrc, xtrg)
# Plot results
pl.figure(figsize=(10,5))
pl.plot(xsrc.ravel(), vals, 'bo', label="Observation")
pl.plot(xtrg.ravel(), idw(vals), 'r-', label="IDW interpolation")
pl.plot(xtrg.ravel(), nn(vals), 'k-', label="Nearest Neighbour interpolation")
pl.plot(xtrg.ravel(), ok(vals), 'g-', label="Ordinary Kriging")
pl.xlabel("Distance", fontsize="large")
pl.ylabel("Value", fontsize="large")
pl.legend(loc="bottomright")
Out[2]:
<matplotlib.legend.Legend at 0x7fc1e1509da0>

2-dimensional example¶
Includes Nearest Neighbours, Inverse Distance Weighting, Linear Interpolation, and Ordinary Kriging.
In [3]:
# Synthetic observations and source coordinates
src = np.vstack( (np.array([4, 7, 3, 15]), np.array([8, 18, 17, 3]))).transpose()
vals = np.random.uniform(size=len(src))
# Target coordinates
xtrg = np.linspace(0, 20, 40)
ytrg = np.linspace(0, 20, 40)
trg = np.meshgrid(xtrg, ytrg)
trg = np.vstack( (trg[0].ravel(), trg[1].ravel()) ).T
# Interpolation objects
idw = ipol.Idw(src, trg)
nn = ipol.Nearest(src, trg)
linear = ipol.Linear(src, trg)
ok = ipol.OrdinaryKriging(src, trg)
# Subplot layout
def gridplot(interpolated, title=""):
pm = ax.pcolormesh(xtrg, ytrg, interpolated.reshape( (len(xtrg), len(ytrg)) ) )
pl.axis("tight")
ax.scatter(src[:, 0], src[:, 1], facecolor="None", s=50, marker='s')
pl.title(title)
pl.xlabel("x coordinate")
pl.ylabel("y coordinate")
# Plot results
fig = pl.figure(figsize=(8,8))
ax = fig.add_subplot(221, aspect="equal")
gridplot(idw(vals), "IDW")
ax = fig.add_subplot(222, aspect="equal")
gridplot(nn(vals), "Nearest Neighbours")
ax = fig.add_subplot(223, aspect="equal")
gridplot(np.ma.masked_invalid(linear(vals)), "Linear interpolation")
ax = fig.add_subplot(224, aspect="equal")
gridplot(ok(vals), "Ordinary Kriging")
pl.tight_layout()

Using the convenience function ipol.interpolation in order to deal with missing values¶
(1) Exemplified for one dimension in space and two dimensions of the source value array (could e.g. be two time steps).
In [4]:
# Synthetic observations (e.g. two time steps)
src = np.arange(10)[:, None]
vals = np.hstack((1.+np.sin(src), 5. + 2.*np.sin(src)))
# Target coordinates
trg = np.linspace(0, 20, 100)[:, None]
# Here we introduce missing values in the second dimension of the source value array
vals[3:5, 1] = np.nan
# interpolation using the convenience function "interpolate"
idw_result = ipol.interpolate(src, trg, vals, ipol.Idw, nnearest=4)
nn_result = ipol.interpolate(src, trg, vals, ipol.Nearest)
# Plot results
fig = pl.figure(figsize=(10,5))
ax = fig.add_subplot(111)
pl1 = ax.plot(trg, idw_result, 'b-', label="IDW")
pl2 = ax.plot(trg, nn_result, 'k-', label="Nearest Neighbour")
pl3 = ax.plot(src, vals, 'ro', label="Observations")

(2) Exemplified for two dimensions in space and two dimensions of the source value array (e.g. time steps), containing also NaN values (here we only use IDW interpolation)
In [5]:
# Just a helper function for repeated subplots
def plotall(ax, trgx, trgy, src, interp, pts, title, vmin, vmax):
ix = np.where(np.isfinite(pts))
ax.pcolormesh(trgx, trgy, interp.reshape( (len(trgx),len(trgy) ) ), vmin=vmin, vmax=vmax )
ax.scatter(src[ix, 0].ravel(), src[ix, 1].ravel(), c=pts.ravel()[ix], s=20, marker='s',
vmin=vmin, vmax=vmax)
ax.set_title(title)
pl.axis("tight")
In [6]:
# Synthetic observations
src = np.vstack( (np.array([4, 7, 3, 15]), np.array([8, 18, 17, 3])) ).T
vals = np.round(np.random.uniform(size=(len(src), 2)), 1)
# Target coordinates
trgx = np.linspace(0, 20, 100)
trgy = np.linspace(0, 20, 100)
trg = np.meshgrid(trgx, trgy)
trg = np.vstack((trg[0].ravel(), trg[1].ravel())).transpose()
result = ipol.interpolate(src, trg, vals, ipol.Idw, nnearest=4)
# Now introduce NaNs in the observations
vals_with_nan = vals.copy()
vals_with_nan[1, 0] = np.nan
vals_with_nan[1:3, 1] = np.nan
result_with_nan = ipol.interpolate(src, trg, vals_with_nan, ipol.Idw, nnearest=4)
vmin = np.concatenate((vals.ravel(), result.ravel())).min()
vmax = np.concatenate((vals.ravel(), result.ravel())).max()
fig = pl.figure(figsize=(8,8))
ax = fig.add_subplot(221)
plotall(ax, trgx, trgy, src, result[:, 0], vals[:, 0], '1st dim: no NaNs', vmin, vmax)
ax = fig.add_subplot(222)
plotall(ax, trgx, trgy, src, result[:, 1], vals[:, 1], '2nd dim: no NaNs', vmin, vmax)
ax = fig.add_subplot(223)
plotall(ax, trgx, trgy, src, result_with_nan[:, 0], vals_with_nan[:, 0], '1st dim: one NaN', vmin, vmax)
ax = fig.add_subplot(224)
plotall(ax, trgx, trgy, src, result_with_nan[:, 1], vals_with_nan[:, 1], '2nd dim: two NaN', vmin, vmax)
pl.tight_layout()

How to use interpolation for gridding data in polar coordinates?¶
Read polar coordinates and corresponding rainfall intensity from file
In [7]:
filename = get_wradlib_data_file('misc/bin_coords_tur.gz')
src = np.loadtxt(filename)
filename = get_wradlib_data_file('misc/polar_R_tur.gz')
vals = np.loadtxt(filename)
Define target grid coordinates
In [8]:
xtrg = np.linspace(src[:,0].min(), src[:,0].max(), 200)
ytrg = np.linspace(src[:,1].min(), src[:,1].max(), 200)
trg = np.meshgrid(xtrg, ytrg)
trg = np.vstack((trg[0].ravel(), trg[1].ravel())).T
IDW interpolation
In [9]:
ip = ipol.Nearest(src, trg)
result = ip(vals.ravel())
Plot results
In [10]:
fig = pl.figure(figsize=(14,14))
ax = fig.add_subplot(121, aspect="equal")
plot_ppi(vals, ax=ax)
ax = fig.add_subplot(122, aspect="equal")
pl.pcolormesh(xtrg, ytrg, result.reshape( (len(xtrg), len(ytrg)) ) )
Out[10]:
<matplotlib.collections.QuadMesh at 0x7fc1e12e4240>

Adjusting radar-base rainfall estimates by rain gauge observations¶
Background¶
There are various ways to correct specific errors and artifacts in radar-based quantitative precipitation estimates (radar QPE). Alternatively, you might want to correct your radar QPE regardless of the error source - by using ground truth, or, more specifically, rain gauge observations. Basically, you define the error of your radar QPE at a rain gauge location by the discrepancy between rain gauge observation (considered as “the truth”) and radar QPE at that very location. Whether you consider this “discrepancy” as an additive or multiplicative error is somehow arbitrary - typically, it’s a mix of both. If you quantify this error at various locations (i.e. rain gauges), you can go ahead and construct correction fields for your radar QPE. You might compute a single correction factor for your entire radar domain (which would e.g. make sense in case of hardware miscalibration), or you might want to compute a spatially variable correction field. This typically implies to interpolate the error in space.
\(\omega radlib\) provides different error models and different spatial interpolation methods to address the adjustment problem. For details, please refer to \(\omega radlib's\) library reference.
In [1]:
import wradlib.adjust as adjust
import wradlib.verify as verify
import wradlib.util as util
import numpy as np
import matplotlib.pyplot as pl
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Example for the 1-dimensional case¶
Looking at the 1-D (instead of 2-D) case is more illustrative.
Create synthetic data¶
First, we create synthetic data: - true rainfall, - point observations of the truth, - radar observations of the truth.
The latter is disturbed by some kind of error, e.g. a combination between systemtic and random error.
In [2]:
# gage and radar coordinates
obs_coords = np.array([5, 10, 15, 20, 30, 45, 65, 70, 77, 90])
radar_coords = np.arange(0, 101)
# true rainfall
truth = np.abs(1.5 + np.sin(0.075 * radar_coords)) + np.random.uniform(
-0.1, 0.1, len(radar_coords))
# radar error
erroradd = 0.7 * np.sin(0.2 * radar_coords + 10.)
errormult = 0.75 + 0.015 * radar_coords
noise = np.random.uniform(-0.05, 0.05, len(radar_coords))
# radar observation
radar = errormult * truth + erroradd + noise
# gage observations are assumed to be perfect
obs = truth[obs_coords]
# add a missing value to observations (just for testing)
obs[1] = np.nan
Apply different adjustment methods¶
- additive error, spatially variable (
AdjustAdd
) - multiplicative error, spatially variable (
AdjustMultiply
) - mixed error, spatially variable (
AdjustMixed
) - multiplicative error, spatially uniform (
AdjustMFB
)
In [3]:
# number of neighbours to be used
nnear_raws = 3
# adjust the radar observation by additive model
add_adjuster = adjust.AdjustAdd(obs_coords, radar_coords,
nnear_raws=nnear_raws)
add_adjusted = add_adjuster(obs, radar)
# adjust the radar observation by multiplicative model
mult_adjuster = adjust.AdjustMultiply(obs_coords, radar_coords,
nnear_raws=nnear_raws)
mult_adjusted = mult_adjuster(obs, radar)
# adjust the radar observation by AdjustMixed
mixed_adjuster = adjust.AdjustMixed(obs_coords, radar_coords,
nnear_raws=nnear_raws)
mixed_adjusted = mixed_adjuster(obs, radar)
# adjust the radar observation by MFB
mfb_adjuster = adjust.AdjustMFB(obs_coords, radar_coords,
nnear_raws=nnear_raws,
mfb_args = dict(method="median"))
mfb_adjusted = mfb_adjuster(obs, radar)
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/numpy/core/fromnumeric.py:664: UserWarning: Warning: 'partition' will ignore the 'mask' of the MaskedArray.
a.partition(kth, axis=axis, kind=kind, order=order)
Plot adjustment results¶
In [4]:
# Enlarge all label fonts
font = {'size' : 15}
pl.rc('font', **font)
pl.figure(figsize=(10,5))
pl.plot(radar_coords, radar, 'k-', linewidth=2., linestyle="dashed", label="Unadjusted radar", )
pl.plot(radar_coords, truth, 'k-', linewidth=2., label="True rainfall", )
pl.plot(obs_coords, obs, 'o', markersize=10.0, markerfacecolor="grey", label="Gage observation")
pl.plot(radar_coords, add_adjusted, '-', color="red", label="Additive adjustment")
pl.plot(radar_coords, mult_adjusted, '-', color="green", label="Multiplicative adjustment")
pl.plot(radar_coords, mfb_adjusted, '-', color="orange", label="Mean Field Bias adjustment")
pl.plot(radar_coords, mixed_adjusted,'-', color="blue", label="Mixed (mult./add.) adjustment")
pl.xlabel("Distance (km)")
pl.ylabel("Rainfall intensity (mm/h)")
leg = pl.legend(prop={'size': 10})

Verification¶
We use the verify
module to compare the errors of different
adjustment approaches.
Here, we compare the adjustment to the “truth”. In practice, we would carry out a cross validation.
In [5]:
# Verification for this example
rawerror = verify.ErrorMetrics(truth, radar)
mfberror = verify.ErrorMetrics(truth, mfb_adjusted)
adderror = verify.ErrorMetrics(truth, add_adjusted)
multerror = verify.ErrorMetrics(truth, mult_adjusted)
mixerror = verify.ErrorMetrics(truth, mixed_adjusted)
In [6]:
# Helper function for scatter plot
def scatterplot(x, y, title=""):
"""Quick and dirty helper function to produce scatter plots
"""
pl.scatter(x, y)
pl.plot([0, 1.2 * maxval], [0, 1.2 * maxval], '-', color='grey')
pl.xlabel("True rainfall (mm)")
pl.ylabel("Estimated rainfall (mm)")
pl.xlim(0, maxval + 0.1 * maxval)
pl.ylim(0, maxval + 0.1 * maxval)
pl.title(title)
In [7]:
# Verification reports
maxval = 4.
# Enlarge all label fonts
font = {'size' : 10}
pl.rc('font', **font)
fig = pl.figure(figsize=(14, 8))
ax = fig.add_subplot(231, aspect=1.)
scatterplot(rawerror.obs, rawerror.est, title="Unadjusted radar")
ax.text(0.2, maxval, "Nash=%.1f" % rawerror.nash(), fontsize=12)
ax = fig.add_subplot(232, aspect=1.)
scatterplot(adderror.obs, adderror.est, title="Additive adjustment")
ax.text(0.2, maxval, "Nash=%.1f" % adderror.nash(), fontsize=12)
ax = fig.add_subplot(233, aspect=1.)
scatterplot(multerror.obs, multerror.est, title="Multiplicative adjustment")
ax.text(0.2, maxval, "Nash=%.1f" % multerror.nash(), fontsize=12)
ax = fig.add_subplot(234, aspect=1.)
scatterplot(mixerror.obs, mixerror.est, title="Mixed (mult./add.) adjustment")
ax.text(0.2, maxval, "Nash=%.1f" % mixerror.nash(), fontsize=12)
ax = fig.add_subplot(235, aspect=1.)
scatterplot(mfberror.obs, mfberror.est, title="Mean Field Bias adjustment")
ax.text(0.2, maxval, "Nash=%.1f" % mfberror.nash(), fontsize=12)
pl.tight_layout()

Example for the 2-dimensional case¶
For the 2-D case, we follow the same approach as before:
- create synthetic data: truth, rain gauge observations, radar-based rainfall estimates
- apply adjustment methods
- verification
The way these synthetic data are created is totally arbitrary - it’s just to show how the methods are applied.
Create 2-D synthetic data¶
In [8]:
# grid axes
xgrid = np.arange(0, 10)
ygrid = np.arange(20, 30)
# number of observations
num_obs = 10
# create grid
gridshape = len(xgrid), len(ygrid)
grid_coords = util.gridaspoints(ygrid, xgrid)
# Synthetic true rainfall
truth = np.abs(10. * np.sin(0.1 * grid_coords).sum(axis=1))
# Creating radar data by perturbing truth with multiplicative and
# additive error
# YOU CAN EXPERIMENT WITH THE ERROR STRUCTURE
radar = 0.6 * truth + 1. * np.random.uniform(low=-1., high=1,
size=len(truth))
radar[radar < 0.] = 0.
# indices for creating obs from raw (random placement of gauges)
obs_ix = np.random.uniform(low=0, high=len(grid_coords),
size=num_obs).astype('i4')
# creating obs_coordinates
obs_coords = grid_coords[obs_ix]
# creating gauge observations from truth
obs = truth[obs_ix]
Apply different adjustment methods¶
In [9]:
# Mean Field Bias Adjustment
mfbadjuster = adjust.AdjustMFB(obs_coords, grid_coords)
mfbadjusted = mfbadjuster(obs, radar)
# Additive Error Model
addadjuster = adjust.AdjustAdd(obs_coords, grid_coords)
addadjusted = addadjuster(obs, radar)
# Multiplicative Error Model
multadjuster = adjust.AdjustMultiply(obs_coords, grid_coords)
multadjusted = multadjuster(obs, radar)
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/wradlib-1.0.0-py3.6.egg/wradlib/adjust.py:628: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
Plot 2-D adjustment results¶
In [10]:
# Helper functions for grid plots
def gridplot(data, title):
"""Quick and dirty helper function to produce a grid plot
"""
xplot = np.append(xgrid, xgrid[-1] + 1.) - 0.5
yplot = np.append(ygrid, ygrid[-1] + 1.) - 0.5
grd = ax.pcolormesh(xplot, yplot, data.reshape(gridshape), vmin=0,
vmax=maxval)
ax.scatter(obs_coords[:, 0], obs_coords[:, 1], c=obs.ravel(),
marker='s', s=50, vmin=0, vmax=maxval)
#pl.colorbar(grd, shrink=0.5)
pl.title(title)
In [11]:
# Maximum value (used for normalisation of colorscales)
maxval = np.max(np.concatenate((truth, radar, obs, addadjusted)).ravel())
# open figure
fig = pl.figure(figsize=(10, 6))
# True rainfall
ax = fig.add_subplot(231, aspect='equal')
gridplot(truth, 'True rainfall')
# Unadjusted radar rainfall
ax = fig.add_subplot(232, aspect='equal')
gridplot(radar, 'Radar rainfall')
# Adjusted radar rainfall (MFB)
ax = fig.add_subplot(234, aspect='equal')
gridplot(mfbadjusted, 'Adjusted (MFB)')
# Adjusted radar rainfall (additive)
ax = fig.add_subplot(235, aspect='equal')
gridplot(addadjusted, 'Adjusted (Add.)')
# Adjusted radar rainfall (multiplicative)
ax = fig.add_subplot(236, aspect='equal')
gridplot(multadjusted, 'Adjusted (Mult.)')
pl.tight_layout()

In [12]:
# Open figure
fig = pl.figure(figsize=(6, 6))
# Scatter plot radar vs. observations
ax = fig.add_subplot(221, aspect='equal')
scatterplot(truth, radar, 'Radar vs. Truth (red: Gauges)')
pl.plot(obs, radar[obs_ix], linestyle="None", marker="o", color="red")
# Adjusted (MFB) vs. radar (for control purposes)
ax = fig.add_subplot(222, aspect='equal')
scatterplot(truth, mfbadjusted, 'Adjusted (MFB) vs. Truth')
# Adjusted (Add) vs. radar (for control purposes)
ax = fig.add_subplot(223, aspect='equal')
scatterplot(truth, addadjusted, 'Adjusted (Add.) vs. Truth')
# Adjusted (Mult.) vs. radar (for control purposes)
ax = fig.add_subplot(224, aspect='equal')
scatterplot(truth, multadjusted, 'Adjusted (Mult.) vs. Truth')
pl.tight_layout()

In [1]:
# flake8: noqa
Routine verification measures for radar-based precipitation estimates¶
In [2]:
import wradlib
import os
import numpy as np
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Extract bin values from a polar radar data set at rain gage locations¶
Read polar data set¶
In [3]:
filename = wradlib.util.get_wradlib_data_file('misc/polar_R_tur.gz')
data = np.loadtxt(filename)
Define site coordinates (lon/lat) and polar coordinate system¶
In [4]:
r = np.arange(1,129)
az = np.linspace(0,360,361)[0:-1]
sitecoords = (9.7839, 48.5861)
Make up two rain gauge locations (say we want to work in Gaus Krueger zone 3)¶
In [5]:
# Define the projection via epsg-code
proj = wradlib.georef.epsg_to_osr(31467)
# Coordinates of the rain gages in Gauss-Krueger 3 coordinates
x, y = np.array([3557880, 3557890]), np.array([5383379, 5383375])
Now extract the radar values at those bins that are closest to our rain gauges¶
For this purppose, we use the PolarNeighbours class from wraldib’s verify module. Here, we extract the 9 nearest bins…
In [6]:
polarneighbs = wradlib.verify.PolarNeighbours(r, az, sitecoords, proj, x, y, nnear=9)
radar_at_gages = polarneighbs.extract(data)
print( "Radar values at rain gauge #1: %r" % radar_at_gages[0].tolist())
print( "Radar values at rain gauge #2: %r" % radar_at_gages[1].tolist())
Radar values at rain gauge #1: [0.01, 0.01, 0.02, 0.02, 0.01, 0.01, 0.02, 0.01, 0.05]
Radar values at rain gauge #2: [0.15, 0.2, 0.06, 0.06, 0.26, 0.69, 0.03, 0.05, 0.09]
Retrieve the bin coordinates (all of them or those at the rain gauges)¶
In [7]:
binx, biny = polarneighbs.get_bincoords()
binx_nn, biny_nn = polarneighbs.get_bincoords_at_points()
Plot the entire radar domain and zoom into the surrounding of the rain gauge locations¶
In [8]:
fig = pl.figure(figsize=(12,12))
ax = fig.add_subplot(121)
ax.plot(binx, biny, 'r+')
ax.plot(binx_nn, biny_nn, 'b+', markersize=10)
ax.plot(x, y, 'bo')
ax.axis('tight')
ax.set_aspect("equal")
pl.title("Full view")
ax = fig.add_subplot(122)
ax.plot(binx, biny, 'r+')
ax.plot(binx_nn, biny_nn, 'b+', markersize=10)
ax.plot(x, y, 'bo')
pl.xlim(binx_nn.min()-5, binx_nn.max()+5)
pl.ylim(biny_nn.min()-7, biny_nn.max()+8)
ax.set_aspect("equal")
txt = pl.title("Zoom into rain gauge locations")
pl.tight_layout()

Create a verification report¶
In this example, we make up a true Kdp profile and verify our reconstructed Kdp.
Create synthetic data and reconstruct KDP¶
In [9]:
# Synthetic truth
dr = 0.5
r = np.arange(0, 100, dr)
kdp_true = np.sin(0.3*r)
kdp_true[kdp_true<0] = 0.
phidp_true = np.cumsum(kdp_true)*2*dr
# Synthetic observation of PhiDP with a random noise and gaps
phidp_raw = phidp_true + np.random.uniform(-2, 2, len(phidp_true))
gaps = np.random.uniform(0, len(r), 20).astype("int")
phidp_raw[gaps] = np.nan
# Reconstruct PhiDP and KDP
phidp_re, kdp_re = wradlib.dp.process_raw_phidp_vulpiani(phidp_raw, dr=dr)
# Plot results
fig = pl.figure(figsize=(12,8))
ax = fig.add_subplot(211)
pl.plot(kdp_true, "g-", label="True KDP")
pl.plot(kdp_re, "r-", label="Reconstructed KDP")
pl.grid()
lg = pl.legend()
ax = fig.add_subplot(212)
pl.plot(r, phidp_true, "b--", label="True PhiDP")
pl.plot(r, np.ma.masked_invalid(phidp_raw), "b-", label="Raw PhiDP")
pl.plot(r, phidp_re, "g-", label="Reconstructed PhiDP")
pl.grid()
lg = pl.legend(loc="lower right")
txt = pl.xlabel("Range (km)")

Create verification report¶
In [10]:
metrics = wradlib.verify.ErrorMetrics(kdp_true, kdp_re)
metrics.pprint()
ax = pl.subplot(111, aspect=1.)
ax.plot(metrics.obs, metrics.est, "bo")
ax.plot([-1, 2], [-1, 2], "k--")
pl.xlim(-0.3, 1.1)
pl.ylim(-0.3, 1.1)
xlabel = ax.set_xlabel("True KDP (deg/km)")
ylabel = ax.set_ylabel("Reconstructed KDP (deg/km)")
{'corr': 0.93,
'mas': 0.11,
'meanerr': -0.0,
'mse': 0.02,
'nash': 0.87,
'pbias': -0.0,
'r2': 0.86,
'ratio': nan,
'rmse': 0.14,
'spearman': 0.89,
'sse': 4.23}

Recipes¶
This recipe section provides a collection of code snippets for exemplary \(\omega radlib\) applications. Compared to the other notebooks, the level of documentation is a bit lower. For each recipe, we provide a short summary and a link to the example code.
Please feel to send us your recipes so we can include them on this page. Please send an e-mail to wradlib-dev@googlegroups.com containing:
- optional: name and affiliation
- a suggested title of the recipe
- a short decription of the recipe (max. 100 words)
- the recipe code (please add comments within the code!)
- optional: the data needed to run the code (or a hyperlink to the data)
- optional: some test output of the recipe (e.g. an image file)
Recipe #1: Clutter and attenuation correction plus composition for two DWD radars¶
This recipe shows a workflow to process radar data provided by the German Weather Service (DWD). The processing includes:
- (1) Reading local DX-Data for radars Feldberg and Tuerkheim.
- (2) Clutter correction using the Gabella filter algorithm.
- (3) Attenuation correction using the modified Kraemer algorithm.
- (4) Conversion from reflectivity to rainfall using the Z-R Conversions module.
- (5) Accumulation of rainfall depths over the entire event.
- (6) Composition of data from both radars to a common Cartesian grid (Gauss Krueger Zone 3). Composition is based on a weighted combination, using the sampling volume as a quality criterion
- (7) Plotting a rainfall map using cartesian_plot
In [2]:
import glob
import os
def process_polar_level_data(radarname):
"""Reading and processing polar level data (DX) for radar <radarname>
"""
print("Polar level processing for radar %s..." % radarname)
# preparations for loading sample data in source directory
files = glob.glob(os.path.join(wrl.util.get_wradlib_data_path(),
'dx/recipe1_data/raa*%s*bin' % radarname))
if len(files) == 0:
print("WARNING: No data files found - maybe you did not extract "
"the data from data/recipe1_data.zip?")
data = np.empty((len(files), 360, 128))
# loading the data (two hours of 5-minute images)
for i, f in enumerate(files):
#print(i, f)
data[i], attrs = wrl.io.read_dx(f)
# Clutter filter on an event base
clmap = wrl.clutter.filter_gabella(data.mean(axis=0), tr1=12, n_p=6,
tr2=1.1)
for i, scan in enumerate(data):
data[i] = wrl.ipol.interpolate_polar(scan, clmap)
# correcting for attenuation
pia = wrl.atten.correct_attenuation_constrained(
data,
a_max=1.67e-4,
a_min=2.33e-5,
n_a=100,
b_max=0.7,
b_min=0.65,
n_b=6,
gate_length=1.,
constraints=[wrl.atten.constraint_dbz,
wrl.atten.constraint_pia],
constraint_args=[[59.0],[10.0]])
data = data + pia
# converting to precipitation depth
R = wrl.zr.z_to_r(wrl.trafo.idecibel(data), a=256, b=1.4)
depth = wrl.trafo.r_to_depth(R, 300.)
# calculate hourly accumulation
accum = depth.sum(axis=0)
return accum
In [3]:
def bbox(*args):
"""Get bounding box from a set of radar bin coordinates
"""
x = np.array([])
y = np.array([])
for arg in args:
x = np.append(x, arg[:, 0])
y = np.append(y, arg[:, 1])
xmin = x.min()
xmax = x.max()
ymin = y.min()
ymax = y.max()
return xmin, xmax, ymin, ymax
In [4]:
import zipfile
import shutil
import datetime as dt
# set timer
start = dt.datetime.now()
# unzip data
filename = wrl.util.get_wradlib_data_file('dx/recipe1_data.zip')
targetdir = wrl.util.get_wradlib_data_path() + '/dx/recipe1_data'
with zipfile.ZipFile(filename, 'r') as z:
z.extractall(targetdir)
# set scan geometry and radar coordinates
r = np.arange(500., 128500., 1000.)
az = np.arange(0, 360)
tur_sitecoords = (9.7839, 48.5861)
fbg_sitecoords = (8.005, 47.8744)
# processing polar level radar data
# Tuerkheim
tur_accum = process_polar_level_data("tur")
# Feldberg
fbg_accum = process_polar_level_data("fbg")
# remove unzipped files
if os.path.exists(targetdir):
try:
shutil.rmtree(targetdir)
except Exception:
print("WARNING: Could not remove directory data/recipe1_data")
# derive Gauss-Krueger Zone 3 coordinates of range-bin centroids
# create osr projection using epsg number for GK Zone 3
proj_gk3 = wrl.georef.epsg_to_osr(31467)
# for Tuerkheim radar
tur_coord = wrl.georef.spherical_to_centroids(r, az, 0, tur_sitecoords,
proj=proj_gk3)
tur_coord = tur_coord[..., 0:2]
tur_coord = tur_coord.reshape(-1, tur_coord.shape[-1])
# for Feldberg radar
fbg_coord = wrl.georef.spherical_to_centroids(r, az, 0, fbg_sitecoords,
proj=proj_gk3)
fbg_coord = fbg_coord[..., 0:2]
fbg_coord = fbg_coord.reshape(-1, fbg_coord.shape[-1])
# define target grid for composition
xmin, xmax, ymin, ymax = bbox(tur_coord, fbg_coord)
x = np.linspace(xmin, xmax + 1000., 1000.)
y = np.linspace(ymin, ymax + 1000., 1000.)
grid_coords = wrl.util.gridaspoints(y, x)
# derive quality information - in this case, the pulse volume
pulse_volumes = np.tile(wrl.qual.pulse_volume(r, 1000., 1.), 360)
# interpolate polar radar-data and quality data to the grid
print("Gridding Tuerkheim data...")
tur_quality_gridded = wrl.comp.togrid(tur_coord, grid_coords,
r.max() + 500.,
tur_coord.mean(axis=0),
pulse_volumes,
wrl.ipol.Nearest)
tur_gridded = wrl.comp.togrid(tur_coord, grid_coords, r.max() + 500.,
tur_coord.mean(axis=0),
tur_accum.ravel(),
wrl.ipol.Nearest)
print("Gridding Feldberg data...")
fbg_quality_gridded = wrl.comp.togrid(fbg_coord, grid_coords,
r.max() + 500.,
fbg_coord.mean(axis=0),
pulse_volumes,
wrl.ipol.Nearest)
fbg_gridded = wrl.comp.togrid(fbg_coord, grid_coords, r.max() + 500.,
fbg_coord.mean(axis=0),
fbg_accum.ravel(),
wrl.ipol.Nearest)
# compose the both radar-data based on the quality information
# calculated above
print("Composing Tuerkheim and Feldbarg data on a common grid...")
composite = wrl.comp.compose_weighted([tur_gridded, fbg_gridded],
[1. / (tur_quality_gridded + 0.001),
1. / (fbg_quality_gridded + 0.001)])
composite = np.ma.masked_invalid(composite)
print("Processing took:", dt.datetime.now() - start)
Polar level processing for radar tur...
Polar level processing for radar fbg...
Gridding Tuerkheim data...
Gridding Feldberg data...
Composing Tuerkheim and Feldbarg data on a common grid...
Processing took: 0:00:13.204166
In [5]:
# Plotting rainfall map
pl.figure(figsize=(10,8))
pl.subplot(111, aspect="equal")
pm = pl.pcolormesh(x, y, composite.reshape((len(x), len(y))),
cmap="viridis")
pl.grid()
pl.xlim(min(x), max(x))
pl.ylim(min(y), max(y))
pl.colorbar(pm, shrink=0.85)
Out[5]:
<matplotlib.colorbar.Colorbar at 0x7fdf3c7ae978>

Download required data at the wradlib-data repository.
Note
In order to run the recipe code, you need to extract the sample data
into a directory pointed to by environment variable WRADLIB_DATA
.
Recipe #2: Reading and visualizing an ODIM_H5 polar volume¶
This recipe shows how extract the polar volume data from an ODIM_H5 hdf5 file (KNMI example file from OPERA), contruct a 3-dimensional Cartesian volume and produce a diagnostic plot. The challenge for this file is that for each elevation angle, the scan strategy is different.
In [2]:
import datetime as dt
from osgeo import osr
# read the data (sample file in WRADLIB_DATA)
filename = wrl.util.get_wradlib_data_file('hdf5/knmi_polar_volume.h5')
raw = wrl.io.read_opera_hdf5(filename)
# this is the radar position tuple (longitude, latitude, altitude)
sitecoords = (raw["where"]["lon"][0], raw["where"]["lat"][0],
raw["where"]["height"][0])
# define your cartesian reference system
# proj = wradlib.georef.create_osr(32632)
proj = osr.SpatialReference()
proj.ImportFromEPSG(32632)
# containers to hold Cartesian bin coordinates and data
xyz, data = np.array([]).reshape((-1, 3)), np.array([])
# iterate over 14 elevation angles
for i in range(14):
# get the scan metadata for each elevation
where = raw["dataset%d/where" % (i + 1)]
what = raw["dataset%d/data1/what" % (i + 1)]
# define arrays of polar coordinate arrays (azimuth and range)
az = np.arange(0., 360., 360. / where["nrays"])
r = np.arange(where["rstart"],
where["rstart"] + where["nbins"] * where["rscale"],
where["rscale"])
# derive 3-D Cartesian coordinate tuples
xyz_ = wrl.vpr.volcoords_from_polar(sitecoords, where["elangle"],
az, r, proj)
# get the scan data for this elevation
# here, you can do all the processing on the 2-D polar level
# e.g. clutter elimination, attenuation correction, ...
data_ = what["offset"] + what["gain"] * raw[
"dataset%d/data1/data" % (i + 1)]
# transfer to containers
xyz, data = np.vstack((xyz, xyz_)), np.append(data, data_.ravel())
# generate 3-D Cartesian target grid coordinates
maxrange = 200000.
minelev = 0.1
maxelev = 25.
maxalt = 5000.
horiz_res = 2000.
vert_res = 250.
trgxyz, trgshape = wrl.vpr.make_3d_grid(sitecoords, proj, maxrange,
maxalt, horiz_res, vert_res)
# interpolate to Cartesian 3-D volume grid
tstart = dt.datetime.now()
gridder = wrl.vpr.CAPPI(xyz, trgxyz, trgshape, maxrange, minelev,
maxelev)
vol = np.ma.masked_invalid(gridder(data).reshape(trgshape))
print("3-D interpolation took:", dt.datetime.now() - tstart)
# diagnostic plot
trgx = trgxyz[:, 0].reshape(trgshape)[0, 0, :]
trgy = trgxyz[:, 1].reshape(trgshape)[0, :, 0]
trgz = trgxyz[:, 2].reshape(trgshape)[:, 0, 0]
wrl.vis.plot_max_plan_and_vert(trgx, trgy, trgz, vol, unit="dBZH",
levels=range(-32, 60))
3-D interpolation took: 0:05:51.442567

Note
In order to run the recipe code, you need to extract the sample data
into a directory pointed to by environment variable WRADLIB_DATA
.
RADOLAN¶
RADOLAN is abbreviated from the german RAdar-OnLine-ANeichung, which means Radar-Online-Adjustment.
Using it’s network of 17 weather radar the German Weather Service provides many products for high resolution precipitation analysis and forecast. A comprehensive product list can be found in chapter RADOLAN Product Showcase.
These composite products are distributed in the RADOLAN Binary Data Format with an ASCII header. All composites are available in Polar Stereographic Projection which will be discussed in the chapter RADOLAN Grid.
RADOLAN Quick Start¶
All RADOLAN composite products can be read by the following function:
data, metadata = wradlib.io.read_radolan_composite("mydrive:/path/to/my/file/filename")
Here, data
is a two dimensional integer or float array of shape
(number of rows, number of columns). metadata
is a dictionary which
provides metadata from the files header section, e.g. using the keys
producttype
, datetime
, intervalseconds
, nodataflag
.
The RADOLAN Grid coordinates can be calculated with wradlib.georef.get_radolan_grid().
With the following code snippet the RW-product is shown in the Polar Stereographic Projection.
Import modules, filter warnings to avoid cluttering output with DeprecationWarnings and use matplotlib inline or interactive mode if running in ipython or python respectively.
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
In [2]:
# load radolan files
rw_filename = wrl.util.get_wradlib_data_file('radolan/misc/raa01-rw_10000-1408102050-dwd---bin.gz')
rwdata, rwattrs = wrl.io.read_radolan_composite(rw_filename)
# print the available attributes
print("RW Attributes:", rwattrs)
RW Attributes: {'producttype': 'RW', 'datetime': datetime.datetime(2014, 8, 10, 20, 50), 'radarid': '10000', 'datasize': 1620000, 'maxrange': '150 km', 'radolanversion': '2.13.1', 'precision': 0.1, 'intervalseconds': 3600, 'nrow': 900, 'ncol': 900, 'radarlocations': ['boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem'], 'nodataflag': -9999, 'secondary': array([ 799, 800, 801, ..., 806263, 806264, 807163]), 'cluttermask': array([], dtype=int64)}
In [3]:
# do some masking
sec = rwattrs['secondary']
rwdata.flat[sec] = -9999
rwdata = np.ma.masked_equal(rwdata, -9999)
In [4]:
# Get coordinates
radolan_grid_xy = wrl.georef.get_radolan_grid(900,900)
x = radolan_grid_xy[:,:,0]
y = radolan_grid_xy[:,:,1]
In [5]:
# plot function
pl.pcolormesh(x, y, rwdata, cmap="viridis")
cb = pl.colorbar(shrink=0.75)
cb.set_label("mm/h")
pl.title('RADOLAN RW Product Polar Stereo \n' + rwattrs['datetime'].isoformat())
pl.grid(color='r')

A much more comprehensive section using several RADOLAN composites is shown in chapter RADOLAN Product Showcase.
RADOLAN Product Showcase¶
In this notebook an overview over the existing RADOLAN products is given.
Setup Environment¶
Import modules, filter warnings to avoid cluttering output with DeprecationWarnings and use matplotlib inline or interactive mode if running in ipython or python respectively.
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import matplotlib as mpl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
Get RADOLAN Grid and RADOLAN Extended Grid.
In [2]:
# Get coordinates
radolan_grid_xy = wrl.georef.get_radolan_grid(900,900)
radolan_egrid_xy = wrl.georef.get_radolan_grid(1500,1400)
radolan_wgrid_xy = wrl.georef.get_radolan_grid(1100, 900)
x = radolan_grid_xy[:,:,0]
y = radolan_grid_xy[:,:,1]
xe = radolan_egrid_xy[:,:,0]
ye = radolan_egrid_xy[:,:,1]
xw = radolan_wgrid_xy[:,:,0]
yw = radolan_wgrid_xy[:,:,1]
Define data reading function and plotting function.
In [3]:
def read_radolan(radfile):
radfile = wrl.util.get_wradlib_data_file('radolan/showcase/' + radfile)
return wrl.io.read_radolan_composite(radfile)
In [4]:
def plot_radolan(data, attrs, grid, clabel=None):
fig = pl.figure(figsize=(10,8))
ax = fig.add_subplot(111, aspect='equal')
x = grid[:,:,0]
y = grid[:,:,1]
pm = ax.pcolormesh(x, y, data, cmap='viridis')
cb = fig.colorbar(pm, shrink=0.75)
cb.set_label(clabel)
pl.xlabel("x [km]")
pl.ylabel("y [km]")
pl.title('{0} Product\n{1}'.format(attrs['producttype'],
attrs['datetime'].isoformat()))
pl.xlim((x[0,0],x[-1,-1]))
pl.ylim((y[0,0],y[-1,-1]))
pl.grid(color='r')
RADOLAN Composite¶
A few products including RW and SF are available free of charge at this DWD FTP Server. A full list of RADOLAN products can be found in the DWD RADOLAN/RADVOR-OP Kompositformat.
Currently, most of the RADOLAN composites have a spatial resolution of 1km x 1km, with the National Composites (R-, S- and W-series) being 900 x 900 km grids, and the European Composites 1500 x 1400 km grids. The polar-stereographic projection is described in the chapter RADOLAN Grid.
One difference is the extended National Composite (only WX) with a 1100 x 900 km grid.
Also the PG/PC-Product with 460 x 460 km grid and runlength-coding is shortly described.
National Composites¶
ID | INT | avail | Description |
---|---|---|---|
RX/WX | 5 min | 5 min | original radardata in qualitative RVP6-units (1 byte coded) |
RZ | 5 min | 5 min | radardata after correction of PBB converted to rainrate with improved Z-R-relation |
RY | 5 min | 5 min | radardata after correction with Quality-composit (QY) |
RH | 1 h | 5 min | 1 h summation of RZ-composit |
RB | 1 h | hh:50 | 1 h summation with preadjustment |
RW | 1 h | hh:50 | 1 h summation with standard adjustment “best of two” |
RL | 1 h | hh:50 | 1 h summation with adjustment by Merging |
RU | 1 h | hh:50 | 1 h summation with standard and merging adjustment “best of three” |
SQ | 6 h | hh:50 | 6 h summation of RW |
SH | 12 h | hh:50 | 12 h summation of RW |
SF | 24 h | hh:50 | 24 h summation of RW |
W1 | 7 d | 05:50 | 7 d summation of RW |
W2 | 14 d | 05:50 | 14 d summation of RW |
W3 | 21 d | 05:50 | 21 d summation of RW |
W4 | 30 d | 05:50 | 30 d summation of RW |
Load data from data source.
In [5]:
data, attrs = read_radolan('raa01-rx_10000-1408102050-dwd---bin.gz')
Mask data and apply scale and offset
In [6]:
data = np.ma.masked_equal(data, -9999) / 2 - 32.5
In [7]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='dBZ')

Load data from data source
In [8]:
data, attrs = read_radolan('raa01-rz_10000-1408102050-dwd---bin.gz')
Mask data
In [9]:
data = np.ma.masked_equal(data, -9999)
In [10]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [11]:
data, attrs = read_radolan('raa01-ry_10000-1408102050-dwd---bin.gz')
Mask data
In [12]:
data = np.ma.masked_equal(data, -9999)
In [13]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [14]:
data, attrs = read_radolan('raa01-rh_10000-1408102050-dwd---bin.gz')
Mask data
In [15]:
data = np.ma.masked_equal(data, -9999) / 2 - 32.5
In [16]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [17]:
data, attrs = read_radolan('raa01-rb_10000-1408102050-dwd---bin.gz')
Mask data
In [18]:
data = np.ma.masked_equal(data, -9999)
In [19]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [20]:
data, attrs = read_radolan('raa01-rl_10000-1408102050-dwd---bin.gz')
Mask data
In [21]:
data = np.ma.masked_equal(data, -9999)
In [22]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [23]:
data, attrs = read_radolan('raa01-rw_10000-1408102050-dwd---bin.gz')
Mask data
In [24]:
data = np.ma.masked_equal(data, -9999)
In [25]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [26]:
data, attrs = read_radolan('raa01-ru_10000-1408102050-dwd---bin.gz')
Mask data
In [27]:
data = np.ma.masked_equal(data, -9999)
In [28]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [29]:
data, attrs = read_radolan('raa01-sq_10000-1408102050-dwd---bin.gz')
Mask data
In [30]:
data = np.ma.masked_equal(data, -9999)
In [31]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [32]:
data, attrs = read_radolan('raa01-sh_10000-1408102050-dwd---bin.gz')
Mask data
In [33]:
data = np.ma.masked_equal(data, -9999)
In [34]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [35]:
data, attrs = read_radolan('raa01-sf_10000-1408102050-dwd---bin.gz')
Mask data
In [36]:
data = np.ma.masked_equal(data, -9999)
In [37]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [38]:
data, attrs = read_radolan('raa01-w1_10000-1408110550-dwd---bin.gz')
Mask data
In [39]:
data = np.ma.masked_equal(data, -9999)
In [40]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

Load data from data source
In [41]:
data, attrs = read_radolan('raa01-w2_10000-1408110550-dwd---bin.gz')
Mask data
In [42]:
data = np.ma.masked_equal(data, -9999)
In [43]:
plot_radolan(data, attrs, radolan_grid_xy, clabel='mm * h-1')

In [44]:
data, attrs = read_radolan('raa01-wx_10000-1408102050-dwd---bin.gz')
Mask data
In [45]:
data = np.ma.masked_equal(data, -9999) / 2 - 32.5
In [46]:
plot_radolan(data, attrs, radolan_wgrid_xy, clabel='dBZ')

Extended RADOLAN Composites¶
The common central european products with a range of 1500 km by 1400 km are presented in the following table:
ID | INT | avail | Description |
---|---|---|---|
EX | 5 min | 5 min | analogue RX |
EZ | 5 min | 5 min | analogue RZ |
EY | 5 min | 5 min | analogue EY after correction with Quality-composit |
EH | 1 h | hh:50 | analogue RH (no preadjustment) 1 h summation of EY-composite |
EB | 1 h | hh:50 | analogue RB (with preadjustment) 1 h summation |
EW | 1 h | hh:50 | analogue RW (full adjustment) 1 h summation |
Load data from data source
In [47]:
data, attrs = read_radolan('raa01-ex_10000-1408102050-dwd---bin.gz')
Mask data and apply scale and offset
In [48]:
data = np.ma.masked_equal(data, -9999) / 2 - 32.5
In [49]:
plot_radolan(data, attrs, radolan_egrid_xy, clabel='dBZ')

Load data from data source
In [50]:
data, attrs = read_radolan('raa01-ez_10000-1408102050-dwd---bin.gz')
Mask data
In [51]:
data = np.ma.masked_equal(data, -9999)
In [52]:
plot_radolan(data, attrs, radolan_egrid_xy, clabel='mm * h-1')

Load data from data source
In [53]:
data, attrs = read_radolan('raa01-ey_10000-1408102050-dwd---bin.gz')
Mask data
In [54]:
data = np.ma.masked_equal(data, -9999)
In [55]:
plot_radolan(data, attrs, radolan_egrid_xy, clabel='mm * h-1')

Load data from data source
In [56]:
data, attrs = read_radolan('raa01-eh_10000-1408102050-dwd---bin.gz')
Mask data
In [57]:
data = np.ma.masked_equal(data, -9999)
In [58]:
plot_radolan(data, attrs, radolan_egrid_xy, clabel='mm * h-1')

Load data from data source
In [59]:
data, attrs = read_radolan('raa01-eb_10000-1408102050-dwd---bin.gz')
Mask data
In [60]:
data = np.ma.masked_equal(data, -9999)
In [61]:
plot_radolan(data, attrs, radolan_egrid_xy, clabel='mm * h-1')

RADOLAN PG/PC Product¶
The PG/PC product is a bit different from the normal RADOLAN formats. The header is actually the same, but the data is runlength encoded. Also the RADOLAN grid cells have 2km edge length (460x460 cells).
Load data from data source
In [62]:
radfile = 'raa00-pc_10015-1408030905-dwd---bin.gz'
radfile = wrl.util.get_wradlib_data_file('radolan/misc/' + radfile)
data, attrs = wrl.io.read_radolan_composite(radfile, missing=255)
radolan_grid_pc = wrl.georef.get_radolan_grid(460,460)
Mask data
In [63]:
data = np.ma.masked_equal(data, 255)
print(data.shape)
(460, 460)
In [64]:
# plot the images side by side
pl.figure(figsize=(10, 8))
pl.subplot(111, aspect='equal')
X = radolan_grid_pc[:,:,0]
Y = radolan_grid_pc[:,:,1]
# color-scheme taken from DWD "legend_radar_products_pc.pdf"
colors = ['lightgrey', 'yellow', 'lightblue', 'magenta', 'green',
'red', 'darkblue', 'darkred']
cmap = mpl.colors.ListedColormap(colors, name=u'DWD-pc-scheme')
bounds = np.arange(len(colors) + 1)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
pl.pcolormesh(X, Y, data, cmap=cmap, norm=norm)
pl.xlim((X[0,0], X[-1,-1]))
pl.ylim((Y[0,0], Y[-1,-1]))
# add colorbar and do some magic for proper visualisation
cb = pl.colorbar(shrink=0.75, norm=norm, boundaries=bounds)
loc = bounds + .5
cb.set_ticks(loc)
labels = bounds[:-1]
cb.set_ticklabels(labels)
cl = cb.ax.get_yticklabels()
cl[-1].set_text('9')
cb.ax.set_yticklabels([elem.get_text() for elem in cl])
pl.title('RADOLAN PG Product \n' + attrs['datetime'].isoformat())
pl.grid(color='r')

RADOLAN Radar Network¶
In this chapter the RW-product is shown in WGS84 and the RADOLAN Polar Stereographic Projection. All for the compositing process used radars are extracted from the metadata and plotted with their respective maximum range rings and location information.
In [1]:
import wradlib as wrl
import matplotlib.pyplot as pl
import matplotlib as mpl
import warnings
warnings.filterwarnings('ignore')
try:
get_ipython().magic("matplotlib inline")
except:
pl.ion()
import numpy as np
from osgeo import osr
/home/travis/miniconda/envs/wradlib/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
In [2]:
def get_radar_locations():
radars = {}
radar = {'name': 'ASR Dresden', 'wmo': 10487, 'lon': 13.76347,
'lat': 51.12404, 'alt': 261}
radars['ASD'] = radar
radar = {'name': 'Boostedt', 'wmo': 10132, 'lon': 10.04687,
'lat': 54.00438, 'alt': 124.56}
radars['BOO'] = radar
radar = {'name': 'Dresden', 'wmo': 10488, 'lon': 13.76865, 'lat': 51.12465,
'alt': 263.36}
radars['DRS'] = radar
radar = {'name': 'Eisberg', 'wmo': 10780, 'lon': 12.40278, 'lat': 49.54066,
'alt': 798.79}
radars['EIS'] = radar
radar = {'name': 'Emden', 'wmo': 10204, 'lon': 7.02377, 'lat': 53.33872,
'alt': 58}
radars['EMD'] = radar
radar = {'name': 'Essen', 'wmo': 10410, 'lon': 6.96712, 'lat': 51.40563,
'alt': 185.10}
radars['ESS'] = radar
radar = {'name': 'Feldberg', 'wmo': 10908, 'lon': 8.00361, 'lat': 47.87361,
'alt': 1516.10}
radars['FBG'] = radar
radar = {'name': 'Flechtdorf', 'wmo': 10440, 'lon': 8.802, 'lat': 51.3112,
'alt': 627.88}
radars['FLD'] = radar
radar = {'name': 'Hannover', 'wmo': 10339, 'lon': 9.69452, 'lat': 52.46008,
'alt': 97.66}
radars['HNR'] = radar
radar = {'name': 'Neuhaus', 'wmo': 10557, 'lon': 11.13504, 'lat': 50.50012,
'alt': 878.04}
radars['NEU'] = radar
radar = {'name': 'Neuheilenbach', 'wmo': 10605, 'lon': 6.54853,
'lat': 50.10965, 'alt': 585.84}
radars['NHB'] = radar
radar = {'name': 'Offenthal', 'wmo': 10629, 'lon': 8.71293, 'lat': 49.9847,
'alt': 245.80}
radars['OFT'] = radar
radar = {'name': 'Proetzel', 'wmo': 10392, 'lon': 13.85821,
'lat': 52.64867, 'alt': 193.92}
radars['PRO'] = radar
radar = {'name': 'Memmingen', 'wmo': 10950, 'lon': 10.21924,
'lat': 48.04214, 'alt': 724.40}
radars['MEM'] = radar
radar = {'name': 'Rostock', 'wmo': 10169, 'lon': 12.05808, 'lat': 54.17566,
'alt': 37}
radars['ROS'] = radar
radar = {'name': 'Isen', 'wmo': 10873, 'lon': 12.10177, 'lat': 48.1747,
'alt': 677.77}
radars['ISN'] = radar
radar = {'name': 'Tuerkheim', 'wmo': 10832, 'lon': 9.78278,
'lat': 48.58528, 'alt': 767.62}
radars['TUR'] = radar
radar = {'name': 'Ummendorf', 'wmo': 10356, 'lon': 11.17609,
'lat': 52.16009, 'alt': 183}
radars['UMM'] = radar
return radars
In [3]:
# load radolan file
rw_filename = wrl.util.get_wradlib_data_file('radolan/showcase/raa01-rw_10000-1408102050-dwd---bin.gz')
rwdata, rwattrs = wrl.io.read_radolan_composite(rw_filename)
In [4]:
# print the available attributes
print("RW Attributes:", rwattrs)
RW Attributes: {'producttype': 'RW', 'datetime': datetime.datetime(2014, 8, 10, 20, 50), 'radarid': '10000', 'datasize': 1620000, 'maxrange': '150 km', 'radolanversion': '2.13.1', 'precision': 0.1, 'intervalseconds': 3600, 'nrow': 900, 'ncol': 900, 'radarlocations': ['boo', 'ros', 'emd', 'hnr', 'umd', 'pro', 'ess', 'asd', 'neu', 'nhb', 'oft', 'tur', 'isn', 'fbg', 'mem'], 'nodataflag': -9999, 'secondary': array([ 799, 800, 801, ..., 806263, 806264, 807163]), 'cluttermask': array([], dtype=int64)}
In [5]:
# mask data
sec = rwattrs['secondary']
rwdata.flat[sec] = -9999
rwdata = np.ma.masked_equal(rwdata, -9999)
# create radolan projection object
proj_stereo = wrl.georef.create_osr("dwd-radolan")
# create wgs84 projection object
proj_wgs = osr.SpatialReference()
proj_wgs.ImportFromEPSG(4326)
# get radolan grid
radolan_grid_xy = wrl.georef.get_radolan_grid(900, 900)
x1 = radolan_grid_xy[:, :, 0]
y1 = radolan_grid_xy[:, :, 1]
# convert to lonlat
radolan_grid_ll = wrl.georef.reproject(radolan_grid_xy,
projection_source=proj_stereo,
projection_target=proj_wgs)
lon1 = radolan_grid_ll[:, :, 0]
lat1 = radolan_grid_ll[:, :, 1]
In [6]:
# range array 150 km
print("Max Range: ", rwattrs['maxrange'])
r = np.arange(1, 151) * 1000
# azimuth array 1 degree spacing
az = np.linspace(0, 360, 361)[0:-1]
Max Range: 150 km
In [7]:
# get radar dict
radars = get_radar_locations()
In [8]:
def plot_radar(radar, ax, proj):
site = (radar['lon'], radar['lat'], radar['alt'] )
# build polygons for maxrange rangering
polygons = wrl.georef.spherical_to_polyvert(r, az, 0,
site,
proj=proj)
polygons = polygons[..., 0:2]
polygons.shape = (len(az), len(r), 5, 2)
polygons = polygons[:, -1, :, :]
x_loc, y_loc = wrl.georef.reproject(site[0], site[1],
projection_source=proj_wgs,
projection_target=proj)
# create PolyCollections and add to respective axes
polycoll = mpl.collections.PolyCollection(polygons, closed=True,
edgecolors='r',
facecolors='r')
ax.add_collection(polycoll, autolim=True)
# plot radar location and information text
ax.plot(x_loc, y_loc, 'r+')
ax.text(x_loc, y_loc, radar['name'], color='r')
In [9]:
# plot two projections side by side
fig1 = pl.figure(figsize=(10,8))
ax1 = fig1.add_subplot(111, aspect='equal')
pm = ax1.pcolormesh(lon1, lat1, rwdata, cmap='viridis')
cb = fig1.colorbar(pm, shrink=0.75)
cb.set_label("mm/h")
pl.xlabel("Longitude ")
pl.ylabel("Latitude")
pl.title(
'RADOLAN RW Product \n' + rwattrs['datetime'].isoformat() + '\n WGS84')
pl.xlim((lon1[0, 0], lon1[-1, -1]))
pl.ylim((lat1[0, 0], lat1[-1, -1]))
pl.grid(color='r')
for radar_id in rwattrs['radarlocations']:
# get radar coords etc from dict
# repair Ummendorf ID
if radar_id == 'umd':
radar_id = 'umm'
radar = radars[radar_id.upper()]
plot_radar(radar, ax1, proj_wgs)

In [10]:
fig2 = pl.figure(figsize=(10,8))
ax2 = fig2.add_subplot(111, aspect='equal')
pm = ax2.pcolormesh(x1, y1, rwdata, cmap='viridis')
cb = fig2.colorbar(pm, shrink=0.75)
cb.set_label("mm/h")
pl.xlabel("x [km]")
pl.ylabel("y [km]")
pl.title('RADOLAN RW Product \n' + rwattrs[
'datetime'].isoformat() + '\n Polar Stereographic Projection')
pl.xlim((x1[0, 0], x1[-1, -1]))
pl.ylim((y1[0, 0], y1[-1, -1]))
pl.grid(color='r')
for radar_id in rwattrs['radarlocations']:
# get radar coords etc from dict
# repair Ummendorf ID
if radar_id == 'umd':
radar_id = 'umm'
radar = radars[radar_id.upper()]
plot_radar(radar, ax2, proj_stereo)

This notebook tutorial was prepared with material from the DWD RADOLAN/RADVOR-OP Kompositformat. We also wish to thank Elmar Weigl, German Weather Service, for providing the extensive set of example data and his valuable information about the RADOLAN products.
Library Reference¶
Raw Data I/O¶
Please have a look at the tutorial Supported radar data formats for an introduction on how to deal with different file formats.
Read RADOLAN and DX¶
Reading DX and RADOLAN data from German Weather Service
read_dx |
Data reader for German Weather Service DX product raw radar data files. |
read_radolan_composite |
Read quantitative radar composite format of the German Weather Service |
get_radolan_filehandle |
Opens radolan file and returns file handle |
read_radolan_header |
Reads radolan ASCII header and returns it as string |
parse_dwd_composite_header |
Parses the ASCII header of a DWD quantitative composite file |
read_radolan_binary_array |
Read binary data from file given by filehandle |
decode_radolan_runlength_array |
Decodes the binary runlength coded section from DWD composite file and return decoded numpy array with correct shape |
HDF Data I/O¶
read_generic_hdf5 |
Reads hdf5 files according to their structure |
read_opera_hdf5 |
Reads hdf5 files according to OPERA conventions |
read_gamic_hdf5 |
Data reader for hdf5 files produced by the commercial GAMIC Enigma V3 MURAN software |
to_hdf5 |
Quick storage of one <data> array and a <metadata> dict in an hdf5 file |
from_hdf5 |
Loading data from hdf5 files that was stored by to_hdf5 |
read_gpm |
Reads GPM files for matching with GR |
read_trmm |
Reads TRMM files for matching with GR |
Read NetCDF¶
read_edge_netcdf |
Data reader for netCDF files exported by the EDGE radar software |
read_generic_netcdf |
Reads netcdf files and returns a dictionary with corresponding structure. |
Read Rainbow¶
read_rainbow |
Reads Rainbow files files according to their structure |
Raster and Vector I/O using GDAL¶
open_vector |
Open vector file, return gdal.Dataset and OGR.Layer |
open_raster |
Open raster file, return gdal.Dataset |
read_safnwc |
Read MSG SAFNWC hdf5 file into a gdal georeferenced object |
write_raster_dataset |
Write raster dataset to file format |
Read IRIS Data Format¶
Reads data from Vaisala’s IRIS data formats
IRIS (Vaisala Sigmet Interactive Radar Information System)
See M211318EN-F Programming Guide ftp://ftp.sigmet.com/outgoing/manuals/
To read from IRIS files numpy.memmap
is used to get access to
the data. The IRIS header (PRODUCT_HDR, INGEST_HEADER) is read in any case
into dedicated OrderedDict’s. Reading sweep data can be skipped by setting
loaddata=False. By default the data is decoded on the fly.
Using rawdata=True the data will be kept undecoded.
IrisRecord |
Class holding a single record from a Sigmet IRIS file. |
IrisFile |
Class for retrieving data from Sigmet IRIS files. |
IrisRawFile |
Class for retrieving data from Sigmet IRIS RAW files. |
IrisProductFile |
Class for retrieving data from Sigmet IRIS Product files. |
IrisCartesianProductFile |
Class for retrieving data from Sigmet IRIS Cartesian Product files. |
read_iris |
Read Iris file and return dictionary. |
Miscellaneous Data I/O¶
write_polygon_to_text |
Writes Polygons to a Text file which can be interpreted by ESRI ArcGIS’s “Create Features from Text File (Samples)” tool. |
to_pickle |
Pickle object <obj> to file <fpath> |
from_pickle |
Return pickled object from file <fpath> |
Data Transformation¶
Module <trafo> transforms data e.g. from RVP-units to dBZ-values to Z-values and vice versa.
rvp_to_dbz |
Calculates dBZ-values from DWD RVP6 values as given in DX-product files. |
decibel |
Calculates the decibel representation of the input values |
idecibel |
Calculates the inverse of input decibel values |
r_to_depth |
Computes rainfall depth (mm) from rainfall intensity (mm/h) |
kdp_to_r |
Estimating rainfall intensity directly from specific differential phase. |
si_to_kmh |
Conversion from SI wind speed units to km/hr. |
si_to_mph |
Conversion from SI wind speed units to miles/hr |
si_2_kts |
Conversion from SI wind speed units to knots |
kmh_to_si |
Conversion from km/hr to SI wind speed units |
mph_to_si |
Conversion from miles/hr to SI wind speed units |
kts_to_si |
Conversion from knots to SI wind speed units |
KuBandToS |
Class to hold coefficients for Radar Reflectivity Conversion |
SBandToKu |
Class to hold coefficients for Radar Reflectivity Conversion |
Z-R Conversions¶
Module zr takes care of transforming reflectivity into rainfall rates and vice versa
z_to_r |
Conversion from reflectivities to rain rates. |
r_to_z |
Calculates reflectivity from rain rates using a power law Z/R relationship Z = a*R**b |
z_to_r_enhanced |
Calculates rainrates from radar reflectivities using the enhanced three-part Z-R-relationship used by the DWD (as of 2009) |
Georeferencing¶
Miscellaneous¶
bin_altitude |
Calculates the height of a radar bin taking the refractivity of the atmosphere into account. |
bin_distance |
Calculates great circle distance from radar site to radar bin over spherical earth, taking the refractivity of the atmosphere into account. |
site_distance |
Calculates great circle distance from bin at certain altitude to the radar site over spherical earth, taking the refractivity of the atmosphere into account. |
get_earth_radius |
Get the radius of the Earth (in km) for a given Spheroid model (sr) at a given position. |
Polar Grid Functions¶
spherical_to_xyz |
Transforms spherical coordinates (r, phi, theta) to cartesian coordinates (x, y, z) centered at sitecoords (aeqd). |
spherical_to_proj |
Transforms spherical coordinates (r, phi, theta) to projected coordinates centered at sitecoords in given projection. |
spherical_to_polyvert |
Generate 3-D polygon vertices directly from spherical coordinates (r, phi, theta). |
spherical_to_centroids |
Generate 3-D centroids of the radar bins from the sperical coordinates (r, phi, theta). |
centroid_to_polyvert |
Calculates the 2-D Polygon vertices necessary to form a rectangular polygon around the centroid’s coordinates. |
sweep_centroids |
Construct sweep centroids native coordinates. |
Projection Functions¶
reproject |
Transform coordinates from a source projection to a target projection. |
create_osr |
Conveniently supports the construction of osr spatial reference objects |
proj4_to_osr |
Transform a proj4 string to an osr spatial reference object |
epsg_to_osr |
Create osr spatial reference object from EPSG number |
wkt_to_osr |
Create osr spatial reference object from WKT string |
Raster Functions¶
read_gdal_values |
Read values from a gdal object. |
read_gdal_projection |
Get a projection (OSR object) from a GDAL dataset. |
read_gdal_coordinates |
Get the projected coordinates from a GDAL dataset. |
pixel_to_map3d |
Apply a geographical transformation to return 3D map coordinates from pixel coordinates. |
pixel_to_map |
Apply a geographical transformation to return map coordinates from pixel coordinates. |
pixel_coordinates |
Get pixel coordinates from a regular grid with dimension nx by ny. |
reproject_raster_dataset |
Reproject/Resample given dataset according to keyword arguments |
create_raster_dataset |
Create In-Memory Raster Dataset |
set_raster_origin |
Converts Data and Coordinates Origin |
extract_raster_dataset |
Extract data, coordinates and projection information |
Vector Functions (GDAL)¶
get_vector_coordinates |
Function iterates over gdal ogr layer features and packs extracted vector coordinate points into nested ndarray |
get_vector_points |
Extract coordinate points from given ogr geometry as generator object |
transform_geometry |
Perform geotransformation to given destination SpatialReferenceSystem |
ogr_create_layer |
Creates OGR.Layer objects in gdal.Dataset object. |
ogr_copy_layer |
Copy OGR.Layer object. |
ogr_copy_layer_by_name |
Copy OGR.Layer object. |
ogr_add_feature |
Creates OGR.Feature objects in OGR.Layer object. |
ogr_add_geometry |
Copies single OGR.Geometry object to an OGR.Layer object. |
numpy_to_ogr |
Convert a vertex array to gdal/ogr geometry. |
ogr_to_numpy |
Backconvert a gdal/ogr geometry to a numpy vertex array. |
ogr_geocol_to_numpy |
Backconvert a gdal/ogr geometry Collection to a numpy vertex array. |
get_centroid |
Return centroid of a polygon |
Rectangular Grid Functions¶
get_radolan_coords |
Calculates x,y coordinates of radolan grid from lon, lat |
get_radolan_grid |
Calculates x/y coordinates of radolan grid of the German Weather Service |
xyz_to_spherical |
Returns spherical representation (r, theta, phi) of given cartesian coordinates (x, y, z) with respect to the reference altitude (asl) considering earth’s geometry (proj). |
Satellite Functions¶
correct_parallax |
Adjust the geo-locations of the SR pixels |
dist_from_orbit |
Returns range distances of SR bins (in meters) as seen from the orbit |
Interpolation¶
Interpolation allows to transfer data from one set of locations to another. This includes for example:
- interpolating the data from a polar grid to a cartesian grid or irregular points
- interpolating point observations to a grid or a set of irregular points
- filling missing values, e.g. filling clutters
Nearest |
Nearest-neighbour interpolation in N dimensions. |
Idw |
Inverse distance weighting interpolation in N dimensions. |
Linear |
Interface to the scipy.interpolate.LinearNDInterpolator class. |
OrdinaryKriging |
Interpolate using Ordinary Kriging |
ExternalDriftKriging |
ExternalDriftKriging(src, trg, cov=‘1.0 Exp(10000.)’, nnearest=12, drift_src=None, drift_trg=None) |
interpolate |
Convenience function to use the interpolation classes in an efficient way |
interpolate_polar |
Convenience function to interpolate polar data |
cart_to_irregular_interp |
Interpolate array values defined by cartesian coordinate array cartgrid to new coordinates defined by newgrid using nearest neighbour, linear or cubic interpolation |
cart_to_irregular_spline |
Map array values defined by cartesian coordinate array cartgrid to new coordinates defined by newgrid using spline interpolation. |
Data Quality¶
This module will serve two purposes:
- provide routines to create simple radar data quality related fields.
- provide routines to decide which radar pixel to choose based on the competing information in different quality fields.
Data is supposed to be stored in ‘aligned’ arrays. Aligned here means that all fields are structured such that in each field the data for a certain index is representative for the same physical target.
Therefore no assumptions are made on the dimensions or shape of the input fields except that they exhibit the numpy ndarray interface.
pulse_volume |
Calculates the sampling volume of the radar beam per bin depending on range and aperture. |
beam_block_frac |
Partial beam blockage fraction. |
cum_beam_block_frac |
Cumulative beam blockage fraction along a beam. |
get_bb_ratio |
Returns the Bright Band ratio of each PR bin |
Composition¶
Combine data from different radar locations on one common set of locations
extract_circle |
Extract the indices of coords which fall within a circle defined by center and radius . |
togrid |
Interpolate data from a radar location to the composite grid or set of locations |
compose_ko |
Composes grids according to quality information using quality information as a knockout criterion. |
compose_weighted |
Composes grids according to quality information using a weighted averaging approach. |
Clutter Identification¶
filter_gabella |
Clutter identification filter developed by [Gabella et al., 2002]. |
filter_gabella_a |
First part of the Gabella filter looking for large reflectivity gradients. |
filter_gabella_b |
Second part of the Gabella filter comparing area to circumference of contiguous echo regions. |
filter_cloudtype |
Identification of non-meteorological echoes based on cloud type. |
filter_window_distance |
2d filter looking for large reflectivity gradients. |
histo_cut |
Histogram based clutter identification. |
classify_echo_fuzzy |
Fuzzy echo classification and clutter identification based on polarimetric moments. |
Dual-Pol and Differential Phase¶
Overview¶
This module provides algorithms to process polarimetric radar moments, namely the differential phase, \(Phi_{DP}\), and, based on successful \(Phi_{DP}\) retrieval, also the specific differential phase, \(K_{DP}\). Please note that the actual application of polarimetric moments is implemented in the corresponding wradlib modules, e.g.:
- fuzzy echo classification from polarimetric moments (
wradlib.clutter.classify_echo_fuzzy
)- attenuation correction (
wradlib.atten.pia_from_kdp
)- direct precipitation retrieval from Kdp (
wradlib.trafo.kdp_to_r
)
Establishing a valid \(Phi_{DP}\) profile for \(K_{DP}\) retrieval
involves despeckling (linear_despeckle), phase unfolding, and iterative
retrieval of \(Phi_{DP}\) form \(K_{DP}\).
The main workflow and its single steps is based on a publication by
[Vulpiani et al., 2012]. For convenience, the entire workflow has been
put together in the function wradlib.dp.process_raw_phidp_vulpiani
.
Once a valid \(Phi_{DP}\) profile has been established, the kdp_from_phidp functions can be used to retrieve \(K_{DP}\).
Please note that so far, the functions in this module were designed to increase performance. This was mainly achieved by allowing the simultaneous application of functions over multiple array dimensions. The only requirement to apply these function is that the range dimension must be the last dimension of all input arrays.
process_raw_phidp_vulpiani |
Establish consistent \(Phi_{DP}\) profiles from raw data. |
kdp_from_phidp |
Retrieves \(K_{DP}\) from \(Phi_{DP}\). |
unfold_phi_vulpiani |
Alternative phase unfolding which completely relies on \(K_{DP}\). |
unfold_phi |
Unfolds differential phase by adjusting values that exceeded maximum ambiguous range. |
linear_despeckle |
Remove floating pixels in between NaNs in a multi-dimensional array. |
texture |
Compute the texture of data. |
Vertical Profile of Reflectivity (VPR)¶
Precipitation is 3-dimensional in space. The vertical distribution of precipitation (and thus reflectivity) is typically non-uniform. As the height of the radar beam increases with the distance from the radar location (beam elevation, earth curvature), one sweep samples from different heights. The effects of the non-uniform VPR and the different sampling heights need to be accounted for if we are interested in the precipitation near the ground or in defined heights. This module is intended to provide a set of tools to account for these effects.
The first step will normally be to reference the polar volume data in a
3-dimensional Cartesian coordinate system. The three dimensional Cartesian
coordinates of the original polar volume data can be computed using
wradlib.vpr.volcoords_from_polar
.
Then, we can create regular 3-D grids in order to analyse the vertical profile
of reflectivity or rainfall intensity. For some applications you might want
to create so-called Constant Altitude Plan Position Indicators (CAPPI)
in order to make radar observations at different distances from the radar more
comparable. Basically, a CAPPI is simply one slice out of a 3-D volume grid.
Analoguous, we will refer to the elements in a three dimensional Cartesian grid
as voxels. In wradlib, you can create
CAPPIS (CAPPI
) and Pseudo CAPPIs
(PseudoCAPPI
) for different altitudes at once.
Here’s an example how a set of CAPPIs can be created from synthetic polar volume data:
import wradlib
import numpy as np
# define elevation and azimuth angles, ranges, radar site coordinates,
# projection
elevs = np.array([0.5,1.5,2.4,3.4,4.3,5.3,6.2,7.5,8.7,10,12,14,16.7,19.5])
azims = np.arange(0., 360., 1.)
ranges = np.arange(0., 120000., 1000.)
sitecoords = (14.924218,120.255547,500.)
proj = osr.SpatialReference()
proj.ImportFromEPSG(32651)
# create Cartesian coordinates corresponding the location of the
# polar volume bins
polxyz = wradlib.vpr.volcoords_from_polar(sitecoords, elevs,
azims, ranges, proj) # noqa
poldata = wradlib.vpr.synthetic_polar_volume(polxyz)
# this is the shape of our polar volume
polshape = (len(elevs),len(azims),len(ranges))
# now we define the coordinates for the 3-D grid (the CAPPI layers)
x = np.linspace(polxyz[:,0].min(), polxyz[:,0].max(), 120)
y = np.linspace(polxyz[:,1].min(), polxyz[:,1].max(), 120)
z = np.arange(500.,10500.,500.)
xyz = wradlib.util.gridaspoints(x, y, z)
gridshape = (len(x), len(y), len(z))
# create an instance of the CAPPI class and
# use it to create a series of CAPPIs
gridder = wradlib.vpr.CAPPI(polxyz, xyz, maxrange=ranges.max(),
gridshape=gridshape, ipclass=wradlib.ipol.Idw)
gridded = np.ma.masked_invalid( gridder(poldata) ).reshape(gridshape)
# plot results
levels = np.linspace(0,100,25)
wradlib.vis.plot_max_plan_and_vert(x, y, z, gridded, levels=levels,
cmap=pl.cm.viridis)
volcoords_from_polar |
Create Cartesian coordinates for regular polar volumes |
make_3d_grid |
Generate Cartesian coordinates for a regular 3-D grid based on radar specs. |
CartesianVolume |
Create 3-D regular volume grid in Cartesian coordinates from polar data with multiple elevation angles |
CAPPI |
Create a Constant Altitude Plan Position Indicator (CAPPI) |
PseudoCAPPI |
Create a Pseudo-CAPPI Constant Altitude Plan Position Indicator (CAPPI) |
Attenuation Correction¶
correct_attenuation_hb |
Gate-by-Gate attenuation correction according to [Hitschfeld et al., 1954] |
constraint_dbz |
Constraint callback function for correct_attenuation_constrained. |
constraint_pia |
Constraint callback function for correct_attenuation_constrained. |
correct_attenuation_constrained |
Gate-by-Gate attenuation correction based on the iterative approach of [Kraemer et al., 2008] and [Jacobi et al., 2016] with a generalized and scalable number of constraints. |
correct_radome_attenuation_empirical |
Estimate two-way wet radome losses. |
pia_from_kdp |
Retrieving path integrated attenuation from specific differential phase (Kdp). |
Gage adjustment¶
Concept¶
The objective of this module is the adjustment of radar-based rainfall estimates by rain gage observations. However, this module could also be applied to adjust satellite rainfall by rain gage observations, remotely sensed soil moisture patterns by ground truthing moisture sensors, or any dense spatial point pattern which could be adjusted by sparse point measurements (ground truth).
Basically, we only need two data sources:
- point observations (e.g. rain gage observations)
- set of (potentially irregular) unadjusted point values (e.g. remotely sensed rainfall)
[Goudenhoofdt et al., 2009] provide an excellent overview of adjustment procedures. The general idea is that we quantify the error of the remotely sensed rainfall at the rain gage locations, assuming the rain gage observation to be accurate.
The error can be assumed to be purely additive
(AdjustAdd
), purely multiplicative
(AdjustMultiply
, AdjustMFB
)
or a mixture of both (AdjustMixed
).
If the error is assumed to be heterogeneous in space
(AdjustAdd
, AdjustMultiply
,
AdjustMixed
), the error at the rain gage locations is
interpolated to the radar bin locations and then used to adjust (correct)
the raw radar rainfall estimates. In case of the AdjustMFB approach, though,
the multiplicative error is assumed to be homogeneous in space.
Quick start¶
The basic procedure consists of creating an adjustment object from the class
you want to use for adjustment. After that, you can call the object with the
actual data that is to be adjusted. The following example is using the
additive error model with default settings. obs_coords
and
raw_coords
represent arrays with coordinate pairs for the gage
observations and the radar bins, respectively. obs
and raw
are
arrays containing the actual data:
adjuster = AdjustAdd(obs_coords, raw_coords)
adjusted = adjuster(obs, raw)
Both obs
and raw
need to be flat (1-dimensional) arrays of shape (n,)
that have the same length as the the obs_coords
and raw_coords
arrays,
respectively.
The user can specify the approach that should be used to interpolate the error
in space, as well as the keyword arguments which control the behaviour of the
interpolation approach. For this purpose, all interpolation classes from the
wradlib.ipol
module are available and can be passed by using the
ipclass
argument. The default interpolation class is
Inverse Distance Weighting (Idw
). If you want to use
e.g. linear barycentric interpolation:
import wradlib.ipol as ipol
adjuster = AdjustAdd(obs_coords, raw_coords, ipclass=ipol.Linear)
adjusted = adjuster(obs, raw)
Warning
Be aware that there are a lot of control parameters that can dramatically influence the behaviour of the adjustment (which gauges are considered, how is an error interpolation carried out, …). Read the docs carefully and try to experiment with the effects of the different control parameters. There might be situations in which the algorithms decides - based on the control parameter - not to do an adjustment and just return the unadjusted values.
Cross validation¶
Another helpful feature is an easy-to-use method for leave-one-out
cross-validation [B4]. Cross validation is a standard
procedure for verifying rain gage adjustment or interpolation procedures. You
can start the cross validation in the same way as you start the actual
adjustment, however, you call the xvalidate
method instead. The result of the cross validation are pairs of observation
and the corresponding adjustment result at the observation location. Using the
wradlib.verify
module, you can compute error metrics for the cross
validation results:
adjuster = AdjustAdd(obs_coords, raw_coords)
observed, estimated = adjuster.xvalidate(obs, raw)
from wradlib.verify import ErrorMetrics
metrics = ErrorMetrics(observed, estimated)
metrics.report()
AdjustBase |
The basic adjustment class that inherits to all other classes. |
AdjustMFB |
Multiplicative gage adjustment using one correction factor for the entire domain. |
AdjustMultiply |
Gage adjustment using a multiplicative error model |
AdjustAdd |
Gage adjustment using an additive error model. |
AdjustMixed |
Gage adjustment using a mixed error model (additive and multiplicative). |
RawAtObs |
Get the raw values in the neighbourhood of the observation points |
GageOnly |
Same behaviour as the other adjustment classes, but returns an interpolation of rain gage observations |
AdjustNone |
Same behaviour as the other adjustment classes, but simply returns the unadjusted data. |
Verification¶
Verification mainly refers to the comparison of radar-based precipitation estimates to ground truth.
ErrorMetrics |
Compute quality metrics from a set of observations (obs ) and estimates (est ). |
PolarNeighbours |
For a set of projected point coordinates, extract the neighbouring bin values from a data set in polar coordinates. |
Visualisation¶
Standard plotting and mapping procedures
plot_ppi |
Plots a Plan Position Indicator (PPI). |
plot_ppi_crosshair |
Plots a Crosshair for a Plan Position Indicator (PPI). |
plot_rhi |
Plots a Range Height Indicator (RHI). |
create_cg |
Helper function to create curvelinear grid |
plot_scan_strategy |
Plot the vertical scanning strategy |
plot_plan_and_vert |
Plot 2-D plan view of dataxy together with vertical sections dataxz and datazy |
plot_max_plan_and_vert |
Plot according to <plot_plan_and_vert> with the maximum values along the three axes of data |
add_lines |
Add lines (points in the form Nx2) to axes |
add_patches |
Add patches (points in the form Nx2) to axes |
Zonal Statistics¶
This module supports you in computing statistics over spatial zones. A typical application would be to compute mean areal precipitation for a catchment by using precipitation estimates from a radar grid in polar coordinates or from precipitation estimates in a Cartesian grid.
The general usage is similar to the wradlib.ipol
and
wradlib.adjust
:
You have to create an instance of a class (derived from
ZonalDataBase
) by using
the spatial information of your source and target objects (e.g. radar bins and
catchment polygons). The Zonal Data within this object can be saved eg. as an
ESRI Shapefile.
This object is then called with another class to compute zonal statistics for your target objects by calling the class instance with an array of values (one for each source object).
Typically, creating the instance of the ZonalData class will be computationally expensive, but only has to be done once (as long as the geometries do not change).
Calling the objects with actual data, however, will be very fast.
Note
Right now we only support a limited set of 2-dimensional zonal statistics. In the future, we plan to extend this to three dimensions.
DataSource |
DataSource class for handling ogr/gdal vector data |
ZonalDataBase |
Base class for managing 2-dimensional zonal data. |
ZonalDataPoint |
ZonalData object for source points |
ZonalDataPoly |
ZonalData object for source polygons |
ZonalStatsBase |
Base class for all 2-dimensional zonal statistics. |
ZonalStatsPoly |
Compute weighted average for target polygons based on areal weights. |
ZonalStatsPoint |
Compute zonal average from all points in or close to the target polygon. |
mask_from_bbox |
Return 2-d index array based on spatial selection from a bounding box. |
get_bbox |
Return bbox dictionary that represents the extent of the points. |
grid_centers_to_vertices |
Produces array of vertices from grid’s center point coordinates. |
get_clip_mask |
Returns boolean mask of points coords inside polygon clippoly |
Utility functions¶
Module util provides a set of useful helpers which are currently not attributable to the other modules
from_to |
Return a list of timesteps from <tstart> to <tend> of length <tdelta> |
maximum_intensity_projection |
Computes the maximum intensity projection along an arbitrary cut through the ppi from polar data. |
filter_window_polar |
Apply a filter of an approximated square window of half size fsize on a given polar image img. |
filter_window_cartesian |
Apply a filter of square window size fsize on a given cartesian image img. |
find_bbox_indices |
Find min/max-indices for NxMx2 array coords using bbox-values. |
get_raster_origin |
Return raster origin |
calculate_polynomial |
Calculate Polynomial |
Community¶
How to contribute to \(\omega radlib\)?¶
We need your help to enhance the capabilities of \(\omega radlib\)! Is there an algorithm you would consider useful? Please provide code (in any programming language) or documentation. We will it a try to integrate this algorithm in \(\omega radlib\).
However, there is an even better way: Start a Pull Request!
- Step 1: Fork your own \(\omega radlib\) repository from the \(\omega radlib\) main repo.
- Step 2: Implement your changes into the forked repository. Test your code.
- Step 3: Now you want to feed these changes back into the main \(\omega radlib\) development branch? Start a Pull Request!
- Step 4: We will review your changes. On approval, we will merge your fork back into the main \(\omega radlib\) branch.
- Step 5: Now everyone can benefit from your improvements.
A step-by-step tutorial for a pull request can be found here.
Finally, you are welcome to contribute examples of your own \(\boldsymbol \omega radlib\) applications in our recipes section. There, you will also find a guide on how to submit your recipes to the \(\omega radlib\) documentation pages.
Users¶
Your feedback will contribute to the future development of \(\omega radlib\)! To provide feedback, use the issues page and create an issue (bug reports, suggestions, …).
We also encourage you to register to the mailing list wradlib-users. Using this mailing list or forum, you can ask other users and developers for help and help others, and we can notify you about the latest updates and developments.
For Developers¶
Setup¶
The section Getting Started will provide you with detailed guidance on how to install \(\omega radlib\) and the required dependencies for different operating systems (MS Windows, Linux, Mac OS). \(\omega radlib\) 1.0.0 has been tested with the latest Anaconda Python on linux-64, osx-64 and MS Windows 32 and 64 versions.
As a developer, though, you should rather link into \(\omega radlib\)‘s version control. This way, it will be easier for you to track changes and to contribute your changes to \(\omega radlib\)‘s main respository (see next section). Just install Git, then clone the \(\omega radlib\) repository to your local system by executing the following command in your shell: git clone https://github.com/wradlib/wradlib.git
. Do not forget to set the PYTHONPATH
to point to the corresponding directory.
Contributing to \(\omega radlib\)¶
Everyone can contribute to the developement of \(\omega radlib\) by using the Fork and Pull model. For this purpose, you need to set up Git
(see section Setup). Then see section Community for further instructions on how to create a Pull Request.
Building the docs¶
In order to build the documentation, you need to download the wradlib-docs repository. You need to satisfy a few more dependencies which are mainly related to Sphinx. These are specified in the readthedocs_environment.yml.
Once these requirements are met, you can open a console window within the wradlib-docs
-repository and execute sphinx-build -v -b html source/ doc-build
. This will give you the latest documentation under the wradlib-docs/doc-build
directory. Simply open the index.html file to view the documentation.
Testing¶
\(\omega radlib\) uses the unittest framework. New functions should come with corresponding unittests in the wradlib/wradlib/tests
directory. Just have a look at available tests to get an idea. In addition, examples and docstrings are a good way to combine testing and documentation. Have a look at the wradlib-notebooks in order to get an idea on how to set these up correctly. In the docstrings, the Examples
section will be tested by our testing framework. This could look like this:
def foo(a):
"""Docstring to be evaluated by doctest
Examples
--------
>>> from wradlib.some_module import foo
>>> print(foo(3))
4
"""
return a + 1
Continuous Integration¶
We use Travis_CI for Continuous Integration (CI). CI means, in our case, that each commit pushed to \(\omega radlib\)‘s main repository will trigger the test suites on Travis-CI. If all tests pass successfully, a new documentation will be built on https://readthedocs.org and published on http://docs.wradlib.org. In case a new release tag is associated with a commit, a new release will be distributed via PyPI.
Bibliography¶
References
[Goudenhoofdt et al., 2009] | E. Goudenhoofdt and L. Delobbe. Evaluation of radar-gauge merging methods for quantitative precipitation estimates. Hydrology and Earth System Sciences, 13(2):195–203, 2009. doi:10.5194/hess-13-195-2009. |
[Hitschfeld et al., 1954] | Walter Hitschfeld and Jack Bordan. Errors inherent in the radar measurement of rainfall at attenuating wavelengths. Journal of Meteorology, 11(1):58–67, Feb 1954. doi:10.1175/1520-0469(1954)011<0058:EIITRM>2.0.CO;2. |
[Kraemer et al., 2008] | S. Kraemer and H. R. Verworn. 11th International Conference on Urban Drainage, Edinburgh, Scotland, UK, 2008 Improved C-band radar data processing for real time control of urban drainage systems. 2008. URL: https://web.sbe.hw.ac.uk/staffprofiles/bdgsa/11th_International_Conference_on_Urban_Drainage_CD/ICUD08/pdfs/105.pdf. |
[Jacobi et al., 2016] | S. Jacobi and M. Heistermann. Benchmarking attenuation correction procedures for six years of single-polarised c-band weather radar observations in south-west germany. Geomat. Nat. Haz. Risk., 2016. doi:10.1080/19475705.2016.1155080. |
[Gabella et al., 2002] | Marco Gabella and Riccardo Notarpietro. Ground clutter characterization and elimination in mountainous terrain. In Use of radar observations in hydrological and NWP models, 305–311. Katlenburg-Lindau, 2002. Copernicus. URL: http://porto.polito.it/1411995/. |
[Vulpiani et al., 2012] | Gianfranco Vulpiani, Mario Montopoli, Luca Delli Passeri, Antonio G. Gioia, Pietro Giordano, and Frank S. Marzano. On the use of dual-polarized c-band radar for operational rainfall retrieval in mountainous areas. Journal of Applied Meteorology and Climatology, 51(2):405–425, Feb 2012. doi:10.1175/JAMC-D-10-05024.1. |
[Pfaff, 2010] | T. Pfaff. Radargestuetzte Schaetzung von Niederschlagsensembles (in German). Bronstert et al. (Eds.). Operationelle Abfluss- und Hochwasservorhersage in Quellgebieten. Final Project Report, pp. 113-118., 2010. URL: http://www.rimax-hochwasser.de/fileadmin/user_uploads/RIMAX_PUB_22_0015_Abschlussbericht OPAQUE_final.pdf. |
[Merceret et al., 2000] | Francis J. Merceret and Jennifer G. Ward. Attenuation of Weather Radar Signals Due to Wetting of the Radome by Rainwater or Incomplete Filling of the Beam Volume. Final Report, NASA Kennedy Space Center; Cocoa Beach, FL United States, Apr 09 2000. No Copyright; Unclassified; Publicly available; Unlimited. URL: https://ntrs.nasa.gov/search.jsp?R=20020043890. |
[Carey et al., 2000] | Lawrence D. Carey, Steven A. Rutledge, David A. Ahijevych, and Tom D. Keenan. Correcting propagation effects in c-band polarimetric radar observations of tropical convection using differential propagation phase. Journal of Applied Meteorology, 39(9):1405–1433, Sep 2000. doi:10.1175/1520-0450(2000)039<1405:CPEICB>2.0.CO;2. |
[Gourley et al., 2007] | Jonathan J Gourley, Pierre Tabary, and Jacques Parent du Chatelet. A fuzzy logic algorithm for the separation of precipitating from nonprecipitating echoes using polarimetric radar observations. Journal of Atmospheric and Oceanic Technology, 24(8):1439–1451, 2007. |
[Wang et al., 2009] | Yanting Wang and V. Chandrasekar. Algorithm for estimation of the specific differential phase. Journal of Atmospheric and Oceanic Technology, 26(12):2565–2578, Dec 2009. doi:10.1175/2009JTECHA1358.1. |
[Doviak et al., 1993] | R.J. Doviak and D.S. Zrnić. Doppler Radar and Weather Observations. Dover Books on Engineering Series. Dover Publications, 1993. ISBN 9780486450605. URL: https://books.google.de/books?id=ispLkPX9n2UC. |
[DrWeigl et al., 2004] | Elmar Dr. Weigl, Thomas Dr. Reich, Peter Lang, Andreas Wagner, Otfried Kohler, Nicole Gerlach, and MitarbeiterInnen der MeteoSolutions GmbH. Projekt RADOLAN - Routineverfahren zur Online-Aneichung der Radarniederschlagsdaten mit Hilfe von automatischen Bodenniederschlagsstationen (Ombrometer). Final Report, German Weather Service, Offenbach, Germany, 2004. in german. URL: https://www.dwd.de/DE/leistungen/radolan/radolan_info/abschlussbericht_pdf.pdf?__blob=publicationFile&v=2. |
[DWD, 2009] | RADOLAN/RADVOR-OP Beschreibung des Kompositformats. 2009. in German. URL: https://www.dwd.de/DE/leistungen/radolan/radolan.html. |
[Cao et al., 2013] | Qing Cao, Yang Hong, Youcun Qi, Yixin Wen, Jian Zhang, Jonathan J. Gourley, and Liang Liao. Empirical conversion of the vertical profile of reflectivity from ku-band to s-band frequency. Journal of Geophysical Research: Atmospheres, 118(4):1814–1825, 2013. URL: https://dx.doi.org/10.1002/jgrd.50138, doi:10.1002/jgrd.50138. |
[Liao et al., 2009] | Liang Liao and Robert Meneghini. Validation of trmm precipitation radar through comparison of its multiyear measurements with ground-based radar. Journal of Applied Meteorology and Climatology, 48(4):804–817, 2009. URL: https://dx.doi.org/10.1175/2008JAMC1974.1, doi:10.1175/2008JAMC1974.1. |
[Ryzhkov et al., 2005] | Alexander V. Ryzhkov, Scott E. Giangrande, and Terry J. Schuur. Rainfall estimation with a polarimetric prototype of wsr-88d. Journal of Applied Meteorology, 44(4):502–515, Apr 2005. doi:10.1175/JAM2213.1. |
[Bringi et al., 2001] | VN Bringi and V Chandrasekar. Polarimetric Doppler weather radar: principles and applications. Cambridge University Press, 2001. |
[Harrison et al., 2000] | D L Harrison, S J Driscoll, and M Kitchen. Improving precipitation estimates from weather radar using quality control and correction techniques. Meteorological Applications, 7(2):135–144, 2000. doi:10.1017/S1350482700001468. |
[Jacobi et al., 2012] | S. Jacobi, M. Heistermann, and T. Pfaff. Evaluation and improvement of C-band radar attenuation correction for operational flash flood forecasting. In Proceedings of weather radar and hydrology symposium in Exeter, UK, number 351, 33–38. IAHS, 2012. |
[Collier, 1996] | Christopher G. Collier. Applications of weather radar systems : a guide to uses of radar data in meteorology and hydrology. J. Wiley & sons ; Praxis publ., Chichester; New York; Brisbane [etc.]; Chichester, 1996. |
[Schwaller et al., 2011] | Mathew R. Schwaller and K. Robert Morris. A ground validation network for the global precipitation measurement mission. Journal of Atmospheric and Oceanic Technology, 28(3):301–319, 2011. URL: https://dx.doi.org/10.1175/2010JTECHA1403.1, doi:10.1175/2010JTECHA1403.1. |
Links
[B1] | EUMETNET OPERA. Eumetnet opera weather radar information model for implementation with the hdf5 file format. URL: https://www.eol.ucar.edu/system/files/OPERA_2008_03_WP2.1b_ODIM_H5_v2.1.pdf. |
[B2] | StackOverflow. Find large number of consecutive values fulfilling condition in a numpy array. URL: https://stackoverflow.com/questions/4494404/find-large-number-of-consecutive-values-fulfilling-condition-in-a-numpy-array. |
[B3] | StackOverflow. Performing a moving linear fit to 1d data in python. URL: https://stackoverflow.com/questions/7288125/performing-a-moving-linear-fit-to-1d-data-in-python. |
[B4] | Wikipedia. Cross-validation (statistics). URL: https://en.wikipedia.org/wiki/Cross-validation_(statistics). |
[B5] | Wikipedia. Esri grid. URL: https://en.wikipedia.org/wiki/Esri_grid. |
[B6] | Wikipedia. Geotiff. URL: https://en.wikipedia.org/wiki/GeoTIFF. |
Release Notes¶
Please note that \(\omega radlib\) releases follow semantic versioning. API breaks will be announced via deprecation warnings. All \(\omega radlib\) releases come without any warranty. Release notes might be incomplete. See here for a complete record of changes.
You can install the latest \(\omega radlib\) release from PyPI via $ pip install wradlib
or specific version via $ pip install wradlib==x.y.z
. The recommended installation process is described in Getting Started.
Bleeding Edge¶
Nothing, so far
Version 1.0.0¶
Highlights
- export
notebooks
into dedicated wradlib-notebooks - export
doc
into dedicated wradlib-docs - complete rewrite of CI-integration
- complete rework of modules
Pre 1.0.0 Versions¶
Versions before 1.0.0 are available from the wradlib-old repository.