
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "examples/quickstart_low_level_api.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_examples_quickstart_low_level_api.py>`
        to download the full example code

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_examples_quickstart_low_level_api.py:


Quickstart guide low-level api
==============================

This notebook is designed as quickstart guide for the low-level api
of :py:mod:`pylawr`.

.. GENERATED FROM PYTHON SOURCE LINES 12-16

Introduction
------------
In the following, we will use the low-level api to process data from the
``HHG`` X-band weather radar.

.. GENERATED FROM PYTHON SOURCE LINES 18-26

The following processing steps are:
1. Read in data with pre-defined data handler for data,
2. Define a corresponding grid which represents the position of the data,
3. Remove noise,
4. Filter out clutter,
5. Interpolate missing values,
6. Remap the data to a new grid, and
7. Plot the data.

.. GENERATED FROM PYTHON SOURCE LINES 28-31

Import packages
---------------
Package including the LawrHandler

.. GENERATED FROM PYTHON SOURCE LINES 31-56

.. code-block:: default

    import pylawr.datahandler
    # Package including all grids
    import pylawr.grid
    # For filters
    import pylawr.transform
    # For beamexpansion tag
    import pylawr.transform.spatial.beamexpansion
    # For interpolation
    import pylawr.remap
    # For plotting
    import pylawr.plot
    import pylawr.plot.layer

    # For filters from wradlib
    import wradlib

    # For array operations
    import numpy as np

    # For plotting purpose
    import matplotlib.colors as mpl_colors

    # For georeferencing within plotting
    import cartopy.crs as ccrs








.. GENERATED FROM PYTHON SOURCE LINES 57-63

1. Read in data
---------------
To read in the ascii data, we will use a pre-defined ascii data handler.
For examples to read in other file types, please take a look to other
examples.This data handler will get an opened file handler such that
we have to open the file beforehand.

.. GENERATED FROM PYTHON SOURCE LINES 63-67

.. code-block:: default


    file_path = '../tests/data/lawr_data.txt'
    opened_file = open(file_path, mode='r')








.. GENERATED FROM PYTHON SOURCE LINES 68-71

Different data handlers are available in the ``datahandler`` subpackage of
:py:mod:`pylawr`. To read in ascii files generated with Universität
Hamburg weather radar, we will use ``LawrHandler``

.. GENERATED FROM PYTHON SOURCE LINES 71-74

.. code-block:: default


    data_handler = pylawr.datahandler.LawrHandler(opened_file)








.. GENERATED FROM PYTHON SOURCE LINES 75-78

The next step is to decode the data. Every data handler has a unified
method (``get_reflectivity``) to get the reflectivity as xarray.DataArray
in ``dBZ`` from the opened file.

.. GENERATED FROM PYTHON SOURCE LINES 78-82

.. code-block:: default


    refl_raw = data_handler.get_reflectivity()
    print(refl_raw)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    <xarray.DataArray 'dbz' (time: 1, azimuth: 360, range: 333)>
    array([[[-30.5125,  39.5594,  36.9296, ...,  22.7212,  23.1982,
              22.7786],
            [-30.3187,  39.5143,  36.2365, ...,  22.7075,  22.4898,
              22.6836],
            [-30.0702,  39.485 ,  35.9452, ...,  22.5073,  22.5032,
              22.5006],
            ...,
            [-30.3587,  39.4875,  37.1375, ...,  22.6017,  22.9643,
              23.0368],
            [-30.4531,  39.3453,  37.0415, ...,  22.7306,  23.7097,
              23.6428],
            [-30.5855,  39.4076,  37.017 , ...,  22.6635,  24.0049,
              23.4478]]], dtype=float32)
    Coordinates:
      * time     (time) datetime64[ns] 2017-07-20T08:46:30
      * azimuth  (azimuth) int64 0 1 2 3 4 5 6 7 ... 352 353 354 355 356 357 358 359
      * range    (range) int64 0 1 2 3 4 5 6 7 8 ... 325 326 327 328 329 330 331 332
    Attributes: (12/28)
        unit:                 dBZ
        radartype:            LAWR
        datestr:              170720084630
        timezone:             UTC
        ave:                  30.0
        smpl:                 5000000.0
        ...                   ...
        Elevation:            3
        institution:          Meteorological Institute, Hamburg, Germany
        title:                LAWR data
        latitude:             53.56833
        longitude:            9.973997
        corr_offset:          29.5364




.. GENERATED FROM PYTHON SOURCE LINES 83-88

As we can see, the data handler decodes the data into three dimensions.
The time is inferred from ``datestr`` within the metadata of the file.
The data handler couldn't decode the azimuth and range from this
ascii-file and we have to set them later with a grid. The metadata within
the file are set as attributes of this data array.

.. GENERATED FROM PYTHON SOURCE LINES 90-94

As last step in this read in procedure, we need to close the opened file.
For the opened text file, this doesn't matter but for binary files, like
netCDF or HDF5-files, this is a crucial step because else the file will
be corrupted.

.. GENERATED FROM PYTHON SOURCE LINES 94-97

.. code-block:: default


    opened_file.close()








.. GENERATED FROM PYTHON SOURCE LINES 98-104

2. Define a grid
----------------
The next large step is to define a grid, which is used as georeference of
the data. Some data handlers can decode the grid from the metadata of the
opened file. Within the ascii-file there is not enough information to
decode the grid and we have to define it manually.

.. GENERATED FROM PYTHON SOURCE LINES 106-116

Almost every weather radar works in polar coordinates. For this,
we can use ``PolarGrid``. The center of this grid describes the origin
of this grid. For ``PolarGrid``, this is the position of the radar
in (center=(latitude, longitude, height)). We further need to define the
beam elevation (beam_ele) in degrees from the earth,
number of ranges (nr_ranges), the range resolution in meters (range_res)
and the number of azimuth angles (nr_azi). We further can set an offset
for the azimuth angles (azi_offset, in degrees) and the
ranges (range_offset, in meters) if the radar is rotated or
valid only after some meters.

.. GENERATED FROM PYTHON SOURCE LINES 116-128

.. code-block:: default


    center = (53.56796, 9.97451, 95)
    grid = pylawr.grid.PolarGrid(
        center=center,
        beam_ele=3,
        nr_ranges=333,
        range_res=60,
        range_offset=0,
        nr_azi=360,
        azi_offset=0
    )








.. GENERATED FROM PYTHON SOURCE LINES 129-132

We now defined a grid to the corresponding data. We can now set the
coordinates of this grid to our data with
``lawr.set_grid_coordinates(grid)``.

.. GENERATED FROM PYTHON SOURCE LINES 132-136

.. code-block:: default


    refl_raw = refl_raw.lawr.set_grid_coordinates(grid)
    print(refl_raw)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    <xarray.DataArray 'dbz' (time: 1, azimuth: 360, range: 333)>
    array([[[-30.5125,  39.5594,  36.9296, ...,  22.7212,  23.1982,
              22.7786],
            [-30.3187,  39.5143,  36.2365, ...,  22.7075,  22.4898,
              22.6836],
            [-30.0702,  39.485 ,  35.9452, ...,  22.5073,  22.5032,
              22.5006],
            ...,
            [-30.3587,  39.4875,  37.1375, ...,  22.6017,  22.9643,
              23.0368],
            [-30.4531,  39.3453,  37.0415, ...,  22.7306,  23.7097,
              23.6428],
            [-30.5855,  39.4076,  37.017 , ...,  22.6635,  24.0049,
              23.4478]]], dtype=float32)
    Coordinates:
      * time     (time) datetime64[ns] 2017-07-20T08:46:30
      * azimuth  (azimuth) float64 0.5 1.5 2.5 3.5 4.5 ... 356.5 357.5 358.5 359.5
      * range    (range) float64 30.0 90.0 150.0 ... 1.983e+04 1.989e+04 1.995e+04
    Attributes: (12/28)
        unit:                 dBZ
        radartype:            LAWR
        datestr:              170720084630
        timezone:             UTC
        ave:                  30.0
        smpl:                 5000000.0
        ...                   ...
        Elevation:            3
        institution:          Meteorological Institute, Hamburg, Germany
        title:                LAWR data
        latitude:             53.56833
        longitude:            9.973997
        corr_offset:          29.5364




.. GENERATED FROM PYTHON SOURCE LINES 137-141

3. Remove noise
---------------
In this package, noise is defined as the 10. percentile of the raw
uncorrected reflectivity.

.. GENERATED FROM PYTHON SOURCE LINES 143-150

Caused by beam expansion the radar beam losses its intensity through the
ranges. In the raw ASCII-data, this effect is already corrected.
The data array has a tagging system, where tags can be added and
removed from the data array. The next step is to tag the array that it
is already corrected. This tag is necessary for the beam expansion
filter to determine the direction of the correction.
To add a tag to the DataArray, we will use ``lawr.add_tag(TAG_NAME)``.

.. GENERATED FROM PYTHON SOURCE LINES 150-156

.. code-block:: default


    refl_raw.lawr.add_tag(
        pylawr.transform.spatial.beamexpansion.TAG_BEAM_EXPANSION_CORR
    )
    print(refl_raw)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    <xarray.DataArray 'dbz' (time: 1, azimuth: 360, range: 333)>
    array([[[-30.5125,  39.5594,  36.9296, ...,  22.7212,  23.1982,
              22.7786],
            [-30.3187,  39.5143,  36.2365, ...,  22.7075,  22.4898,
              22.6836],
            [-30.0702,  39.485 ,  35.9452, ...,  22.5073,  22.5032,
              22.5006],
            ...,
            [-30.3587,  39.4875,  37.1375, ...,  22.6017,  22.9643,
              23.0368],
            [-30.4531,  39.3453,  37.0415, ...,  22.7306,  23.7097,
              23.6428],
            [-30.5855,  39.4076,  37.017 , ...,  22.6635,  24.0049,
              23.4478]]], dtype=float32)
    Coordinates:
      * time     (time) datetime64[ns] 2017-07-20T08:46:30
      * azimuth  (azimuth) float64 0.5 1.5 2.5 3.5 4.5 ... 356.5 357.5 358.5 359.5
      * range    (range) float64 30.0 90.0 150.0 ... 1.983e+04 1.989e+04 1.995e+04
    Attributes: (12/29)
        unit:                 dBZ
        radartype:            LAWR
        datestr:              170720084630
        timezone:             UTC
        ave:                  30.0
        smpl:                 5000000.0
        ...                   ...
        institution:          Meteorological Institute, Hamburg, Germany
        title:                LAWR data
        latitude:             53.56833
        longitude:            9.973997
        corr_offset:          29.5364
        tags:                 beam-expansion-corr




.. GENERATED FROM PYTHON SOURCE LINES 157-160

In the output, we can see that the beam expansion tag is added to the
DataArray as attribute. These tags can be used to track the processing
steps of this DataArray.

.. GENERATED FROM PYTHON SOURCE LINES 162-166

The noise is calculated and removed in the raw, uncorrected data and we
need to revert the beam expansion correction. For this, we will use the
``BeamExpansion`` filter, which determines the direction of the correction
automatically based on set tags.

.. GENERATED FROM PYTHON SOURCE LINES 166-169

.. code-block:: default


    beam_expansion = pylawr.transform.spatial.BeamExpansion()








.. GENERATED FROM PYTHON SOURCE LINES 170-173

Every filter within ``pylawr.filter`` has a ``transform`` method, which
applies the filter to given DataArray. Normally, the transform method
returns a data array as first value.

.. GENERATED FROM PYTHON SOURCE LINES 173-177

.. code-block:: default


    refl_uncorr = beam_expansion.transform(refl_raw.lawr.to_z())
    print(refl_uncorr)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    <xarray.DataArray 'z' (time: 1, azimuth: 360, range: 333)>
    array([[[9.87432690e-07, 1.11546200e+00, 2.19168186e-01, ...,
             4.75854912e-07, 5.27898419e-07, 4.76402894e-07],
            [1.03249357e-06, 1.10393892e+00, 1.86839019e-01, ...,
             4.74356230e-07, 4.48446337e-07, 4.66094612e-07],
            [1.09329535e-06, 1.09651632e+00, 1.74717969e-01, ...,
             4.52985833e-07, 4.49832044e-07, 4.46862869e-07],
            ...,
            [1.02302777e-06, 1.09714735e+00, 2.29915148e-01, ...,
             4.62939832e-07, 5.00219414e-07, 5.05584953e-07],
            [1.00103091e-06, 1.06180495e+00, 2.24888585e-01, ...,
             4.76886085e-07, 5.93882371e-07, 5.81291803e-07],
            [9.70973504e-07, 1.07714735e+00, 2.23623372e-01, ...,
             4.69574589e-07, 6.35653533e-07, 5.55768802e-07]]])
    Coordinates:
      * time     (time) datetime64[ns] 2017-07-20T08:46:30
      * azimuth  (azimuth) float64 0.5 1.5 2.5 3.5 4.5 ... 356.5 357.5 358.5 359.5
      * range    (range) float64 30.0 90.0 150.0 ... 1.983e+04 1.989e+04 1.995e+04
    Attributes: (12/29)
        unit:                 dBZ
        radartype:            LAWR
        datestr:              170720084630
        timezone:             UTC
        ave:                  30.0
        smpl:                 5000000.0
        ...                   ...
        institution:          Meteorological Institute, Hamburg, Germany
        title:                LAWR data
        latitude:             53.56833
        longitude:            9.973997
        corr_offset:          29.5364
        tags:                 beam-expansion-uncorr




.. GENERATED FROM PYTHON SOURCE LINES 178-185

After, we uncorrected the beam expansion, we can remove noise from our
radar field. The noise is removed with a ``pylawr.filter.NoiseRemover``.
A noise remover needs an appropriate noise level. For this, the noise
remover can be fitted. In current implementation, the noise level is a
running median of the last ten determined noise levels. For this single
test case, the noise level equals the determined noise level from given
reflectivity.

.. GENERATED FROM PYTHON SOURCE LINES 185-191

.. code-block:: default


    noise_remover = pylawr.transform.temporal.NoiseRemover()
    print('Before fit: {0:.3E}'.format(noise_remover.noiselevel))
    noise_remover.fit(refl_uncorr)
    print('After fit: {0:.3E}'.format(noise_remover.noiselevel))





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Before fit: 8.000E-07
    After fit: 4.607E-07




.. GENERATED FROM PYTHON SOURCE LINES 192-196

After, we fitted the noise remover, we can use it to remove the noise from
given reflectivity field. After we removed the noise, we need to recorrect
the beam expansion. Finally, we translate our radar field into dbZ
with `field.lawr.to_dbz()`.

.. GENERATED FROM PYTHON SOURCE LINES 196-200

.. code-block:: default


    refl_wo_noise_uncorr = noise_remover.transform(refl_uncorr)
    refl_wo_noise = beam_expansion.transform(refl_wo_noise_uncorr).lawr.to_dbz()








.. GENERATED FROM PYTHON SOURCE LINES 201-210

4. Filter out clutter
---------------------
After we removed noise from our radar field, we can filter out clutter.
For this we use techniques from computer vision to identify measured points,
where the values and/or gradients are jumping. These points are removed
by the TDBZ and SPIN filter and replaced with a NaN value. To further
filter out clutter, we also use another clutter filter from `wradlib`
called "Gabella filter". This should show how a clutter filter outside
of pylawr can be used to filter clutter.

.. GENERATED FROM PYTHON SOURCE LINES 212-215

In our package, clutter filters create a map, which will be translated to
a binary clutter map via thresholding. The created cluttermaps can be
combined such that different combinations of cluttermaps are possible.

.. GENERATED FROM PYTHON SOURCE LINES 217-219

As first step, we need to initialize the clutter filters, here the
TDBZ and SPIN filter.

.. GENERATED FROM PYTHON SOURCE LINES 219-223

.. code-block:: default


    tdbz_filter = pylawr.transform.filter.TDBZFilter()
    spin_filter = pylawr.transform.filter.SPINFilter()








.. GENERATED FROM PYTHON SOURCE LINES 224-226

Every clutter filter has `create_cluttermap` as method, which
creates a `ClutterMap` object, where the the cluttermap is saved as array.

.. GENERATED FROM PYTHON SOURCE LINES 226-230

.. code-block:: default


    tdbz_cmap = tdbz_filter.create_cluttermap(refl_wo_noise)
    spin_cmap = spin_filter.create_cluttermap(refl_wo_noise)








.. GENERATED FROM PYTHON SOURCE LINES 231-238

As previously written, we further want to use a clutter filter, which
is not within our package. For this example, we use the "Gabella filter"
from `wradlib`. This filter returns a boolean clutter map, which is then
converted into a `ClutterMap` object. For this, the clutter map needs to
be translated into an integer array and need to have three dimensions
(time, grid_dim_1, grid_dim_2). After, we converted the clutter map into
a `ClutterMap` object, we can use this object as native clutter map.

.. GENERATED FROM PYTHON SOURCE LINES 238-247

.. code-block:: default


    gabella_arr = wradlib.clutter.filter_gabella(
        refl_wo_noise.values[0], wsize=7, thrsnorain=0.,
        tr1=6., n_p=12, tr2=1.3, rm_nans=False,
        radial=False, cartesian=False
    )[np.newaxis, ...]
    gabella_cmap = pylawr.transform.filter.ClutterMap('Gabella',
                                                      gabella_arr.astype(int))








.. GENERATED FROM PYTHON SOURCE LINES 248-253

Cluttermaps can be combined via `append()`. This method appends a given
cluttermap to existing cluttermaps. To get a clean cluttermap, we
initialize an empty `ClutterMap` object, where then the other cluttermaps
are appended. The fuzzy threshold can be set to get a fuzzy
identification of clutter.

.. GENERATED FROM PYTHON SOURCE LINES 253-260

.. code-block:: default


    cluttermap = pylawr.transform.filter.ClutterMap('ClutterMap',
                                                    fuzzy_threshold=0.)
    cluttermap.append(tdbz_cmap)
    cluttermap.append(spin_cmap)
    cluttermap.append(gabella_cmap)








.. GENERATED FROM PYTHON SOURCE LINES 261-263

After we appended all clutter maps, we can transform a given radar
field with this clutter map. This will set all clutter pixels to NaN.

.. GENERATED FROM PYTHON SOURCE LINES 263-266

.. code-block:: default


    refl_filtered = cluttermap.transform(refl_wo_noise)








.. GENERATED FROM PYTHON SOURCE LINES 267-274

5. Interpolate missing values
-----------------------------
After, we filtered out clutter values, we need to interpolate missing
values. To interpolate missing values, we can use an ``Interpolator``,
defined in ``pylawr.filter``. This interpolator uses a given remapping
algorithm to interpolate missing values. If no remapping algorithm is set,
the interpolator uses a single nearest neighbor interpolation.

.. GENERATED FROM PYTHON SOURCE LINES 276-279

In this example, we use a nearest neighbor interpolation with five
neighbors, which are then averaged with a median. After we defined
the algorithm, we initialize an `Interpolator`.

.. GENERATED FROM PYTHON SOURCE LINES 279-283

.. code-block:: default


    int_remapper = pylawr.remap.NearestNeighbor(5, max_dist=500)
    int_transformer = pylawr.transform.spatial.Interpolator(algorithm=int_remapper)








.. GENERATED FROM PYTHON SOURCE LINES 284-289

The interpolator is then used to fill missing values via
``Interpolator.transform()``. This method refits given remapper and
interpolates from existing to missing grid points. This interpolated
result is then used to fill missing values. This step may take several
seconds, because the remapping algorithm is refitted.

.. GENERATED FROM PYTHON SOURCE LINES 289-292

.. code-block:: default


    refl_interpolated = int_transformer.transform(refl_filtered)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    /home/docs/checkouts/readthedocs.org/user_builds/pylawr/conda/stable/lib/python3.11/site-packages/xarray/core/coordinates.py:41: FutureWarning: Updating MultiIndexed coordinate 'grid_cell' would corrupt indices for other variables: ['azimuth', 'range']. This will raise an error in the future. Use `.drop_vars({'range', 'azimuth', 'grid_cell'})` before assigning new coordinate values.
      self.update({key: value})
    /home/docs/checkouts/readthedocs.org/user_builds/pylawr/conda/stable/lib/python3.11/site-packages/pylawr/remap/nearest.py:45: RuntimeWarning: All-NaN slice encountered
      remapped_data = np.nanmedian(neighbor_values, axis=-1)
    /home/docs/checkouts/readthedocs.org/user_builds/pylawr/conda/stable/lib/python3.11/site-packages/xarray/core/coordinates.py:41: FutureWarning: Updating MultiIndexed coordinate 'grid_cell' would corrupt indices for other variables: ['grid_lat', 'grid_lon']. This will raise an error in the future. Use `.drop_vars({'grid_lat', 'grid_lon', 'grid_cell'})` before assigning new coordinate values.
      self.update({key: value})




.. GENERATED FROM PYTHON SOURCE LINES 293-299

6. Remap the data to a new grid
-------------------------------
After we interpolated missing values, we can remap our data to a new grid,
e.g. a cartesian grid. This is needed to combine different radar fields
and for nowcasting purpose. In this example, we will used it to
visualize the remapping effects.

.. GENERATED FROM PYTHON SOURCE LINES 301-303

As first step for remapping, we need to initialize a remapping object,
here nearest neighbour with six averaged neighbors.

.. GENERATED FROM PYTHON SOURCE LINES 303-306

.. code-block:: default


    grid_remapper = pylawr.remap.NearestNeighbor(1, max_dist=300)








.. GENERATED FROM PYTHON SOURCE LINES 307-312

This remapping algorithm need to be fitted to translate given radar
field with given old grid to a target grid with ``fit()``. As target grid,
a cartesian grid is used here. This fit procedure is necessary because
the finding of the nearest neighbors is the most time-expensive step
within the fitting algorithms.

.. GENERATED FROM PYTHON SOURCE LINES 312-316

.. code-block:: default


    target_grid = pylawr.grid.CartesianGrid(start=-25000)
    grid_remapper.fit(grid, target_grid)








.. GENERATED FROM PYTHON SOURCE LINES 317-319

After we found the nearest neighbors with ``fit()``, we can use ``remap()``
to remap given radar field from old grid to a new target grid.

.. GENERATED FROM PYTHON SOURCE LINES 319-323

.. code-block:: default


    refl_remapped = grid_remapper.remap(refl_interpolated)
    print(refl_remapped)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    /home/docs/checkouts/readthedocs.org/user_builds/pylawr/conda/stable/lib/python3.11/site-packages/pylawr/remap/nearest.py:45: RuntimeWarning: All-NaN slice encountered
      remapped_data = np.nanmedian(neighbor_values, axis=-1)
    <xarray.DataArray 'dbz' (time: 1, y: 401, x: 401)>
    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]]])
    Coordinates:
      * y        (y) float64 -2.5e+04 -2.49e+04 -2.48e+04 ... 1.49e+04 1.5e+04
      * x        (x) float64 -2.5e+04 -2.49e+04 -2.48e+04 ... 1.49e+04 1.5e+04
      * time     (time) datetime64[ns] 2017-07-20T08:46:30
    Attributes: (12/29)
        unit:                 dBZ
        radartype:            LAWR
        datestr:              170720084630
        timezone:             UTC
        ave:                  30.0
        smpl:                 5000000.0
        ...                   ...
        institution:          Meteorological Institute, Hamburg, Germany
        title:                LAWR data
        latitude:             53.56833
        longitude:            9.973997
        corr_offset:          29.5364
        tags:                 neg-lin-refl-repl-0.0;noise-filtered;beam-expansion...




.. GENERATED FROM PYTHON SOURCE LINES 324-326

This remapping is the last processing step within this example.
As last step, we will plot this processed data.

.. GENERATED FROM PYTHON SOURCE LINES 328-337

7. Plot the data
----------------
Our plotting system is based on an object-oriented approach and
matplotlib. As main plotting tool, we introduced a ``Plotter``,
which is the main plot and can be split in several subplots. This
main plot has a given grid (e.g. 14x14 grid points) and we can define
different grid slices, which are translate into subplots. The main
plotting logic is hidden into plotting layers. They can be added to a
subplot and are then plotted on this specified subplot.

.. GENERATED FROM PYTHON SOURCE LINES 339-344

As first step, we will translate our logarithmic reflectivity into a
rain rate. For this, we use a z-r relationship with ``zr_convert``.
There, the scale (a) and polynomial grade factor (b) can be specified.
After this conversion, we set all values below 0.1 mm/h to
NaN for plotting purpose.

.. GENERATED FROM PYTHON SOURCE LINES 344-348

.. code-block:: default


    rain_rate = refl_remapped.lawr.to_z().lawr.zr_convert(a=256, b=1.42)
    rain_rate = rain_rate.where(rain_rate>=0.1, np.nan)








.. GENERATED FROM PYTHON SOURCE LINES 349-353

We need to initialize a plotter and we need to specify the grid size for
this plotter. In this example, we will use a 14x14 grid. We further can
specify the names and grid slices for different subplots (here
`map` and `colorbar`).

.. GENERATED FROM PYTHON SOURCE LINES 353-369

.. code-block:: default


    default_gridspec_slices = {
        'map': [
            slice(None, None),
            slice(12),
        ],
        'colorbar': [
            slice(None, None),
            slice(12, None),
        ],
    }
    plotter = pylawr.plot.Plotter(
        grid_size=(14, 14), grid_slices=default_gridspec_slices,
        backend_name='agg', figsize=(13, 9)
    )








.. GENERATED FROM PYTHON SOURCE LINES 370-373

Within pylawr, we implemented different colormaps, which are used
for our plots. Here, we will use a pre-specified rain colormap and set
all NaN values to transparent. We further specify a logarithmic colorscale.

.. GENERATED FROM PYTHON SOURCE LINES 373-379

.. code-block:: default


    cmap = pylawr.plot.available_cmaps['rain']
    cmap.set_bad((0, 0, 0, 0))

    norm = mpl_colors.LogNorm(vmin=0.1, vmax=200)








.. GENERATED FROM PYTHON SOURCE LINES 380-381

In our next steps, we define our plotting layers.

.. GENERATED FROM PYTHON SOURCE LINES 383-386

To plot a background map, we can use a `BackgroundLayer`, which will plot
an openstreetmap as background (here we will use ``cartopy`` implicit).
The zoom level of this openstreetmap layer can be set via `resolution`.

.. GENERATED FROM PYTHON SOURCE LINES 386-389

.. code-block:: default


    # l_bg = pylawr.plot.layer.BackgroundLayer(resolution=10)








.. GENERATED FROM PYTHON SOURCE LINES 390-395

As next layer, we define a ``RadarFieldLayer``, which is used to plot a
given array and grid on a subplot. Here, we define our rain rate as
plotting array with our defined cartesian grid as underlying grid.
The previously defined colormap and colorscale are used for this
radar layer.

.. GENERATED FROM PYTHON SOURCE LINES 395-401

.. code-block:: default


    l_radar = pylawr.plot.layer.RadarFieldLayer(radar_field=rain_rate,
                                                grid=target_grid, zorder=1)
    l_radar['cmap'] = cmap
    l_radar['norm'] = norm








.. GENERATED FROM PYTHON SOURCE LINES 402-406

As additional information, we want to add a colorbar. For this, we can
use ``ColorbarLayer``, we will plot a colorbar for given radar field.
The settings of this colorbar are changed after plotting,
which will create this colorbar.

.. GENERATED FROM PYTHON SOURCE LINES 406-409

.. code-block:: default


    l_cbar = pylawr.plot.layer.ColorbarLayer(l_radar)








.. GENERATED FROM PYTHON SOURCE LINES 410-414

These three layers are added to specified subplots. These subplots are
automatically generated based on the names of the slices
(here, `map` and `colorbar`). The background and radar field are added
to the `map` subplot, while the colorbar is added to `colorbar` subplot.

.. GENERATED FROM PYTHON SOURCE LINES 414-419

.. code-block:: default


    # plotter.add_layer('map', l_bg)
    plotter.add_layer('map', l_radar)
    plotter.add_layer('colorbar', l_cbar)








.. GENERATED FROM PYTHON SOURCE LINES 420-422

Our map subplot should be a georeferenced subplot. For this, we define
a cartopy projection (here a rotated pole).

.. GENERATED FROM PYTHON SOURCE LINES 422-425

.. code-block:: default


    rotated_pole = ccrs.RotatedPole(-170.415, 36.063)








.. GENERATED FROM PYTHON SOURCE LINES 426-429

All subplots are saved in the plotter under ``Plotter.subplots`` as
dictionary. The projection of the ``map`` subplot is then set to
the previously defined projection.

.. GENERATED FROM PYTHON SOURCE LINES 429-433

.. code-block:: default


    map_subplot = plotter.subplots.get('map')
    map_subplot.projection = rotated_pole








.. GENERATED FROM PYTHON SOURCE LINES 434-438

We need to specify the extent of this mapping subplot. We can set the
extent as dictionary with latitude and longitude values. If
auto_extent of this subplot is set to true, the extent will be
extended during plotting to preserve the geometry of this subplot.

.. GENERATED FROM PYTHON SOURCE LINES 438-447

.. code-block:: default


    map_subplot.auto_extent = True
    map_subplot.extent = dict(
        lon_min=9.6,
        lon_max=10.3,
        lat_min=53.35,
        lat_max=53.76
    )








.. GENERATED FROM PYTHON SOURCE LINES 448-451

The trigger the plotting commands, we have to call ``Plotter.plot()``.
This method creates the figure and subplots and plot the layers
on created subplots.

.. GENERATED FROM PYTHON SOURCE LINES 451-454

.. code-block:: default


    plotter.plot()








.. GENERATED FROM PYTHON SOURCE LINES 455-458

After, we plotted our layers, subplots and plotter, we can
manipulate the figure, axes etc. Here, we manipulate the ticks
of the colorbar.

.. GENERATED FROM PYTHON SOURCE LINES 458-463

.. code-block:: default


    l_cbar.colorbar.set_ticks([0.1, 0.5, 1, 2, 5, 10, 100])
    _ = l_cbar.colorbar.ax.set_yticklabels(['0.1', '0.5', '1',
                                            '2', '5', '10', '>100'])








.. GENERATED FROM PYTHON SOURCE LINES 464-467

After ``plot()`` was called, the plotter has all methods from the
underlying figure. Then, ``Plotter.savefig()`` can be used to save the
plotted figure to a specified path.

.. GENERATED FROM PYTHON SOURCE LINES 467-471

.. code-block:: default


    plotter.savefig('/tmp/quickstart_low_level.png')
    plotter.show()




.. image-sg:: /examples/images/sphx_glr_quickstart_low_level_api_001.png
   :alt: quickstart low level api
   :srcset: /examples/images/sphx_glr_quickstart_low_level_api_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 472-477

We can see the effect of remapping in our saved plot. The
remapping decreased the resolution to 100 meters from 60 meters
and interpolated values, where no values are available. This is caused
by nearest neighbor remapping. A more advanced algorithm, e.g.
Kriging, can be used to avoid these artifacts.

.. GENERATED FROM PYTHON SOURCE LINES 479-483

After we saved the figure, this quickstart example for the low-level
api is finished and showed that different components of :py:mod:`pylawr`
can be used to read-in, process and plot radar data. Further examples
show how the plotter can be used for comparison plots and how
different subpackages can interact.


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  1.415 seconds)


.. _sphx_glr_download_examples_quickstart_low_level_api.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example




    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: quickstart_low_level_api.py <quickstart_low_level_api.py>`

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: quickstart_low_level_api.ipynb <quickstart_low_level_api.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
