Skip to content

Repository files navigation

peakTree

DOI

Software for converting multi-peaked (cloud) radar Doppler spectra into a binary tree structure.

Important

At the moment a refactoring is ongoing, aiming for a more flexible structure and utilizing xarray for generic data handling. The original version is still available peakTree_legacy

Technical documentation is available at peakTree-doc

Binary tree structure

Binary tree nomenclature and conventions

Usage

Atomic functions

ds_example = xr.open_dataset('single_example_spectrum.nc')

>>> <xarray.Dataset> Size: 6kB
>>> Dimensions:  (doppler: 512)
>>> Coordinates:
>>>   * doppler  (doppler) float32 2kB -10.52 -10.47 -10.43 ... 10.47 10.52 10.56
>>>     range    float32 4B 1.465e+03
>>>     time     datetime64[us] 8B 2023-12-28T09:00:32.200000
>>> Data variables:
>>>     Z        (doppler) float32 2kB 3.595e-06 3.595e-06 ... 3.595e-06 3.595e-06
>>>     Zcx      (doppler) float32 2kB 3.152e-06 3.152e-06 ... 3.152e-06 3.152e-06
>>>     noise    float32 4B 2.353e-06

First, the binary tree is generated:

vel_step = (ds_example['doppler'][1] - ds_example['doppler'][0]).values
tree = peakTree.generate_tree.spectrum_to_tree(
    vel_step,                                                # Velocity resolution
    ds_example['Z'].values,                                  # Spectral reflectivity (linear units, 1D numpy array)
    ds_example['Z'].values < ds_example['noise'].values*1.3, # Mask for noise floor
    {'width_thres': 0.1, 'prom_thres': 1}                    # Peak finding parameters
)

>>> {0: {'coords': [0],
>>>   'bounds_left': 227,
>>>   'bounds_right': 267,
>>>   'thres': np.float32(3.311432e-06),
>>>   'parent_id': -1},
>>>  1: {'coords': [0, 0],
>>>   'bounds_left': 227,
>>>   'bounds_right': np.int64(247),
>>>   'thres': np.float32(3.5196229e-06),
>>>   'parent_id': 0},
>>>  2: {'coords': [0, 1],
>>>   'bounds_left': np.int64(247),
>>>   'bounds_right': 267,
>>>   'thres': np.float32(3.5196229e-06),
>>>   'parent_id': 0}}

The moments for the single moments can be added into the tree:

ds_example_array = ds_example.to_array(dim="inputvar")

tree = peakTree.generate_tree.add_moments(
    tree,
    ds_example['doppler'].values,
    ds_example_array.values,
    ds_example_array.coords["inputvar"].values,
    {'Z': ['M0', 'M1', 'M2', 'M3', 'P']},
)

>>> {0: {'coords': [0],
>>>   'bounds_left': 227,
>>>   'bounds_right': 267,
>>>   'thres': np.float32(3.311432e-06),
>>>   'id_parent': -1,
>>>   'moments': {'Z': {'M0': np.float32(0.014677452),
>>>     'M1': np.float32(-0.6109322),
>>>     'M2': np.float32(0.2462034),
>>>     'M3': np.float32(1.9973509),
>>>     'P': np.float32(890.377)}}},
>>>  1: {'coords': [0, 0],
>>>   'bounds_left': 227,
>>>   'bounds_right': np.int64(247),
>>>   'thres': np.float32(3.5196229e-06),
>>>   'id_parent': 0,
>>>   'moments': {'Z': {'M0': np.float32(0.012891835),
>>>     'M1': np.float32(-0.69831896),
>>>     'M2': np.float32(0.07468125),
>>>     'M3': np.float32(-0.16253266),
>>>     'P': np.float32(837.7099)}}},
>>> ...

In preparation of processing larger chunks of data, these functions are combined into a wrapper, which returns an array instead of the pure python dictionary tree

peakTree.generate_tree.ufunc_wrapper(
    ds_example['doppler'].values,
    ds_example_array.coords["inputvar"].values,
    ds_example_array.values,
    (ds_example['Z'] < ds_example['noise']*1.3).values,
    var_peak='Z',
    vel_step=vel_step,
    params={'width_thres': 0.1, 'prom_thres': 1},
    meta={
        'Z': ['M0', 'M1', 'M2', 'M3', 'P'],
        'Zcx': ['M0', 'P'],
        }
)

Processing larger datasets

Note

See the example notebooks for mira and rpgfmcw for more comprehensive examples.

A convenience function exists to process large datasets:

ds_input['noise_mask'] = ds_input['Z'] < ds_input['noise']*1.3
ds_input = ds_input.drop_vars('noise')

meta={
    'Z': ['M0', 'M1', 'M2', 'M3', 'P'],
    'Zcx': ['M0', 'P'],
    }

ds_rect = peakTree.ds_to_tree(
    ds_input,
    {'width_thres': 0.1, 'prom_thres': 1},
    meta
)

dt = ds_rect.time.values[0].astype('datetime64[us]').astype('O')
ds_rect.to_netcdf(
    path=f'{dt:%Y%m%d_%H%M}_mira_peakTree.nc4'
)

Literature

Radenz, M., Bühl, J., Seifert, P., Griesche, H., and Engelmann, R.: peakTree: a framework for structure-preserving radar Doppler spectra analysis, Atmos. Meas. Tech., 12, 4813–4828, https://doi.org/10.5194/amt-12-4813-2019, 2019.

Vogl, T., Radenz, M., Ramelli, F., Gierens, R., and Kalesse-Los, H.: PEAKO and peakTree: tools for detecting and interpreting peaks in cloud radar Doppler spectra – capabilities and limitations, Atmos. Meas. Tech., 17, 6547–6568, https://doi.org/10.5194/amt-17-6547-2024, 2024.

License

Copyright 2026, Martin Radenz, Teresa Vogl MIT License

About

Software for converting multi-peaked cloud radar Doppler spectra into a binary tree structure.

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages