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

_images/old_radarpic.png

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.

  1. 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
    
  2. Create a new environment from scratch:

    $ conda create --name wradlib python=3.6
    
  3. Activate the \(\omega radlib\) environment

    Linux:

    $ source activate wradlib
    

    Windows:

    > activate wradlib
    
  4. Install \(\omega radlib\) and its dependencies:

    (wradlib) $ conda install wradlib
    
  5. 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%
    
  6. 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 maps keys to values.
  • 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>]
_images/notebooks_python_mplintro_15_1.png
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.

Elements of plot

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()
_images/notebooks_python_mplintro_20_0.png

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)
_images/notebooks_python_timeseries_15_0.png

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>
_images/notebooks_basics_wradlib_workflow_11_1.png

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>
_images/notebooks_basics_wradlib_workflow_17_2.png

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>
_images/notebooks_basics_wradlib_workflow_19_1.png

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>
_images/notebooks_basics_wradlib_workflow_27_1.png

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)
_images/notebooks_basics_wradlib_workflow_58_1.png

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>
_images/notebooks_basics_wradlib_workflow_70_1.png

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>
_images/notebooks_basics_wradlib_get_rainfall_18_1.png

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')
_images/notebooks_visualisation_wradlib_plot_ppi_example_8_0.png
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')
_images/notebooks_visualisation_wradlib_plot_ppi_example_11_0.png

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')
_images/notebooks_visualisation_wradlib_plot_ppi_example_14_0.png
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')
_images/notebooks_visualisation_wradlib_plot_ppi_example_17_0.png
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')
_images/notebooks_visualisation_wradlib_plot_ppi_example_20_0.png
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)
_images/notebooks_visualisation_wradlib_plot_ppi_example_23_0.png

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-grid
  • caax: matplotlib Axes object (twin to cgax), Cartesian Axes (x-y-grid) for plotting cartesian data
  • paax: 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()).

Note 1. Other than most plotting functions you cannot give an axes object as an argument. All necessary axes objects are created on the fly. You may give an figure object and/or an subplot specification as parameter. For further information on howto plot multiple cg plots in one figure, have a look at the special section Plotting on Grids. 2. When using the 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.

Simple CG PPI

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)
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_17_0.png
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]')
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_20_0.png

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
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_22_0.png
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)
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_25_0.png
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>
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_28_1.png
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)
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_31_0.png

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)
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_34_0.png
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)
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_37_0.png
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]')
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_44_0.png
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()
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_47_0.png
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')
_images/notebooks_visualisation_wradlib_plot_curvelinear_grids_54_0.png

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)
_images/notebooks_fileio_wradlib_radar_formats_10_0.png
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>
_images/notebooks_fileio_wradlib_radar_formats_18_2.png
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)
_images/notebooks_fileio_wradlib_radar_formats_26_0.png
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)
_images/notebooks_fileio_wradlib_radar_formats_33_0.png
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)
_images/notebooks_fileio_wradlib_radar_formats_39_0.png
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>
_images/notebooks_fileio_wradlib_reading_dx_14_1.png

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>
_images/notebooks_fileio_wradlib_reading_dx_16_1.png

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>
_images/notebooks_fileio_wradlib_reading_dx_18_2.png

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)
_images/notebooks_fileio_wradlib_reading_dx_20_1.png
_images/notebooks_fileio_wradlib_reading_dx_20_2.png
_images/notebooks_fileio_wradlib_reading_dx_20_3.png

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 + ']')
_images/notebooks_fileio_wradlib_load_rainbow_example_14_0.png

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>
_images/notebooks_attenuation_wradlib_attenuation_9_1.png

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)
_images/notebooks_attenuation_wradlib_attenuation_12_0.png

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()
_images/notebooks_attenuation_wradlib_attenuation_19_0.png

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()
_images/notebooks_attenuation_wradlib_attenuation_25_0.png
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()
_images/notebooks_attenuation_wradlib_attenuation_30_0.png
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()
_images/notebooks_attenuation_wradlib_attenuation_34_0.png

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()
_images/notebooks_attenuation_wradlib_attenuation_37_0.png

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 (in WRADLIB_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)
_images/notebooks_beamblockage_wradlib_beamblock_25_0.png

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)
_images/notebooks_beamblockage_wradlib_beamblock_30_0.png

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')
_images/notebooks_classify_wradlib_clutter_gabella_example_8_1.png

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')
_images/notebooks_classify_wradlib_clutter_cloud_example_16_1.png

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>
_images/notebooks_classify_wradlib_histo_cut_example_8_1.png

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")
_images/notebooks_classify_wradlib_fuzzy_echo_classify_11_0.png
_images/notebooks_classify_wradlib_fuzzy_echo_classify_11_1.png

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)
_images/notebooks_georeferencing_wradlib_georef_example_10_1.png

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)
_images/notebooks_visualisation_wradlib_overlay_10_0.png
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)
_images/notebooks_visualisation_wradlib_overlay_15_1.png
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)
_images/notebooks_visualisation_wradlib_overlay_20_1.png
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)
_images/notebooks_visualisation_wradlib_overlay_22_1.png
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')
_images/notebooks_visualisation_wradlib_overlay_26_1.png
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)
_images/notebooks_visualisation_wradlib_overlay_33_0.png
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)
_images/notebooks_visualisation_wradlib_overlay_39_0.png

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:

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

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: image

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 radar
  • sr 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>
_images/notebooks_match3d_wradlib_match_workflow_31_2.png
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>
_images/notebooks_match3d_wradlib_match_workflow_35_1.png
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>
_images/notebooks_match3d_wradlib_match_workflow_55_2.png
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')
_images/notebooks_match3d_wradlib_match_workflow_71_1.png
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')
_images/notebooks_match3d_wradlib_match_workflow_72_1.png
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')
_images/notebooks_match3d_wradlib_match_workflow_73_1.png
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')
_images/notebooks_match3d_wradlib_match_workflow_74_1.png
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()
_images/notebooks_match3d_wradlib_match_workflow_75_0.png

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')
_images/notebooks_match3d_wradlib_match_workflow_79_1.png
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')
_images/notebooks_match3d_wradlib_match_workflow_80_1.png
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')
_images/notebooks_match3d_wradlib_match_workflow_81_1.png
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')
_images/notebooks_match3d_wradlib_match_workflow_82_1.png
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()
_images/notebooks_match3d_wradlib_match_workflow_83_0.png

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>
_images/notebooks_interpolation_wradlib_ipol_example_4_1.png

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()
_images/notebooks_interpolation_wradlib_ipol_example_6_0.png

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")
_images/notebooks_interpolation_wradlib_ipol_example_8_0.png

(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()
_images/notebooks_interpolation_wradlib_ipol_example_11_0.png

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>
_images/notebooks_interpolation_wradlib_ipol_example_20_1.png

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})
_images/notebooks_multisensor_wradlib_adjust_example_14_0.png
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()
_images/notebooks_multisensor_wradlib_adjust_example_19_0.png

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()
_images/notebooks_multisensor_wradlib_adjust_example_28_0.png
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()
_images/notebooks_multisensor_wradlib_adjust_example_29_0.png
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()
_images/notebooks_verification_wradlib_verify_example_16_0.png

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)")
_images/notebooks_verification_wradlib_verify_example_19_0.png
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}
_images/notebooks_verification_wradlib_verify_example_21_1.png

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:

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>
_images/notebooks_workflow_recipe1_7_1.png

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
_images/notebooks_workflow_recipe2_4_1.png

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')
_images/notebooks_radolan_radolan_quickstart_8_0.png

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
RADOLAN RX Product

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')
_images/notebooks_radolan_radolan_showcase_20_0.png
RADOLAN RZ Product

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')
_images/notebooks_radolan_radolan_showcase_26_0.png
RADOLAN RY Product

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')
_images/notebooks_radolan_radolan_showcase_32_0.png
RADOLAN RH Product

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')
_images/notebooks_radolan_radolan_showcase_38_0.png
RADOLAN RB Product

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')
_images/notebooks_radolan_radolan_showcase_44_0.png
RADOLAN RL Product

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')
_images/notebooks_radolan_radolan_showcase_50_0.png
RADOLAN RW Product

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')
_images/notebooks_radolan_radolan_showcase_56_0.png
RADOLAN RU Product

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')
_images/notebooks_radolan_radolan_showcase_62_0.png
RADOLAN SQ Product

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')
_images/notebooks_radolan_radolan_showcase_68_0.png
RADOLAN SH Product

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')
_images/notebooks_radolan_radolan_showcase_74_0.png
RADOLAN SF Product

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')
_images/notebooks_radolan_radolan_showcase_80_0.png
RADOLAN W1 Product

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')
_images/notebooks_radolan_radolan_showcase_86_0.png
RADOLAN W2 Product

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')
_images/notebooks_radolan_radolan_showcase_92_0.png
RADOLAN WX Product
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')
_images/notebooks_radolan_radolan_showcase_97_0.png
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
RADOLAN EX Product

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')
_images/notebooks_radolan_radolan_showcase_105_0.png
RADOLAN EZ Product

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')
_images/notebooks_radolan_radolan_showcase_111_0.png
RADOLAN EY Product

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')
_images/notebooks_radolan_radolan_showcase_117_0.png
RADOLAN EH Product

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')
_images/notebooks_radolan_radolan_showcase_123_0.png
RADOLAN EB Product

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')
_images/notebooks_radolan_radolan_showcase_129_0.png
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')
_images/notebooks_radolan_radolan_showcase_136_0.png

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)
_images/notebooks_radolan_radolan_network_11_0.png
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)
_images/notebooks_radolan_radolan_network_12_0.png

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:

  1. provide routines to create simple radar data quality related fields.
  2. 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.:

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.

Indices and tables