doppy 0.3.1__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of doppy might be problematic. Click here for more details.
- {doppy-0.3.1 → doppy-0.3.3}/Cargo.lock +2 -2
- {doppy-0.3.1 → doppy-0.3.3}/Cargo.toml +1 -1
- {doppy-0.3.1 → doppy-0.3.3}/PKG-INFO +66 -64
- doppy-0.3.3/README.md +99 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/netcdf.py +2 -1
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/product/stare.py +83 -0
- doppy-0.3.3/src/doppy/product/stare_depol.py +281 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/product/wind.py +69 -0
- doppy-0.3.1/README.md +0 -97
- doppy-0.3.1/src/doppy/product/stare_depol.py +0 -83
- {doppy-0.3.1 → doppy-0.3.3}/LICENSE +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doppy_rs/Cargo.toml +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doppy_rs/src/lib.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doppy_rs/src/raw/halo_hpl.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doppy_rs/src/raw/wls70.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doppy_rs/src/raw.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/.gitignore +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/Cargo.toml +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/src/lib.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/src/raw/error.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/src/raw/halo_hpl.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/src/raw/wls70.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/crates/doprs/src/raw.rs +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/pyproject.toml +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/__init__.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/__main__.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/bench.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/data/__init__.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/data/api.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/data/cache.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/data/exceptions.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/defaults.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/exceptions.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/options.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/product/__init__.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/py.typed +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/raw/__init__.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/raw/halo_bg.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/raw/halo_hpl.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/raw/halo_sys_params.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/raw/windcube.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/raw/wls70.py +0 -0
- {doppy-0.3.1 → doppy-0.3.3}/src/doppy/utils.py +0 -0
|
@@ -106,7 +106,7 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
|
|
106
106
|
|
|
107
107
|
[[package]]
|
|
108
108
|
name = "doppy_rs"
|
|
109
|
-
version = "0.3.
|
|
109
|
+
version = "0.3.3"
|
|
110
110
|
dependencies = [
|
|
111
111
|
"doprs",
|
|
112
112
|
"numpy",
|
|
@@ -115,7 +115,7 @@ dependencies = [
|
|
|
115
115
|
|
|
116
116
|
[[package]]
|
|
117
117
|
name = "doprs"
|
|
118
|
-
version = "0.3.
|
|
118
|
+
version = "0.3.3"
|
|
119
119
|
dependencies = [
|
|
120
120
|
"chrono",
|
|
121
121
|
"rayon",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: doppy
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -44,8 +44,8 @@ Project-URL: Bug Tracker, https://github.com/actris-cloudnet/doppy/issues
|
|
|
44
44
|
|
|
45
45
|
## Products
|
|
46
46
|
|
|
47
|
-
- [
|
|
48
|
-
- [
|
|
47
|
+
- Stare: [src](https://github.com/actris-cloudnet/doppy/blob/main/src/doppy/product/stare.py), [Cloudnet examples](https://cloudnet.fmi.fi/search/visualizations?experimental=true&product=doppler-lidar&dateFrom=2024-06-05&dateTo=2024-06-05)
|
|
48
|
+
- Wind: [src](https://github.com/actris-cloudnet/doppy/blob/main/src/doppy/product/wind.py), [Cloudnet examples](https://cloudnet.fmi.fi/search/visualizations?experimental=true&product=doppler-lidar-wind&dateFrom=2024-06-05&dateTo=2024-06-05)
|
|
49
49
|
|
|
50
50
|
## Instruments
|
|
51
51
|
|
|
@@ -61,6 +61,8 @@ pip install doppy
|
|
|
61
61
|
|
|
62
62
|
## Usage
|
|
63
63
|
|
|
64
|
+
### Stare
|
|
65
|
+
|
|
64
66
|
```python
|
|
65
67
|
import doppy
|
|
66
68
|
|
|
@@ -70,68 +72,68 @@ stare = doppy.product.Stare.from_halo_data(
|
|
|
70
72
|
bg_correction_method=doppy.options.BgCorrectionMethod.FIT,
|
|
71
73
|
)
|
|
72
74
|
|
|
75
|
+
stare.write_to_netcdf(FILENAME)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Stare with depolarisation
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import doppy
|
|
82
|
+
|
|
83
|
+
stare_depol = doppy.product.StareDepol.from_halo_data(
|
|
84
|
+
co_data=LIST_OF_STARE_CO_FILE_PATHS,
|
|
85
|
+
co_data_bg=LIST_OF_BACKGROUND_CO_FILE_PATHS,
|
|
86
|
+
cross_data=LIST_OF_STARE_CROSS_FILE_PATHS,
|
|
87
|
+
cross_data_bg=LIST_OF_BACKGROUND_CROSS_FILE_PATHS,
|
|
88
|
+
bg_correction_method=doppy.options.BgCorrectionMethod.FIT,
|
|
89
|
+
polariser_bleed_through=0,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
stare_depol.write_to_netcdf(FILENAME)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Wind
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import doppy
|
|
99
|
+
|
|
100
|
+
wind = doppy.product.Wind.from_halo_data(
|
|
101
|
+
data=LIST_OF_WIND_SCAN_HPL_FILES,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# You can also pass instrument azimuth offset in degrees as an option
|
|
105
|
+
wind = doppy.product.Wind.from_halo_data(
|
|
106
|
+
data=LIST_OF_WIND_SCAN_HPL_FILES,
|
|
107
|
+
options=doppy.product.wind.Options(azimuth_offset_deg=30),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# For windcube wls200s use
|
|
111
|
+
wind = doppy.product.Wind.from_windcube_data(
|
|
112
|
+
data=LIST_OF_VAD_NETCDF_FILES,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# For windcube wls70 use
|
|
116
|
+
wind = doppy.product.Wind.from_wls70_data(
|
|
117
|
+
data=LIST_OF_RTD_FILES,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
wind.write_to_netcdf(FILENAME)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Raw files
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
import doppy
|
|
127
|
+
|
|
128
|
+
# Halo
|
|
129
|
+
raws_hpl = doppy.raw.HaloHpl.from_srcs(LIST_OF_HPL_FILES)
|
|
130
|
+
raws_bg = doppy.raw.HaloBg.from_srcs(LIST_OF_BACKGROUND_FILES)
|
|
131
|
+
raw_system_params = doppy.raw.HaloSysParams.from_src(SYSTEM_PARAMS_FILENAME)
|
|
73
132
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
.add_dimension("time")
|
|
77
|
-
.add_dimension("range")
|
|
78
|
-
.add_time(
|
|
79
|
-
name="time",
|
|
80
|
-
dimensions=("time",),
|
|
81
|
-
standard_name="time",
|
|
82
|
-
long_name="Time UTC",
|
|
83
|
-
data=stare.time,
|
|
84
|
-
dtype="f8",
|
|
85
|
-
)
|
|
86
|
-
.add_variable(
|
|
87
|
-
name="range",
|
|
88
|
-
dimensions=("range",),
|
|
89
|
-
units="m",
|
|
90
|
-
data=stare.radial_distance,
|
|
91
|
-
dtype="f4",
|
|
92
|
-
)
|
|
93
|
-
.add_variable(
|
|
94
|
-
name="elevation",
|
|
95
|
-
dimensions=("time",),
|
|
96
|
-
units="degrees",
|
|
97
|
-
data=stare.elevation,
|
|
98
|
-
dtype="f4",
|
|
99
|
-
long_name="elevation from horizontal",
|
|
100
|
-
)
|
|
101
|
-
.add_variable(
|
|
102
|
-
name="beta_raw",
|
|
103
|
-
dimensions=("time", "range"),
|
|
104
|
-
units="sr-1 m-1",
|
|
105
|
-
data=stare.beta,
|
|
106
|
-
dtype="f4",
|
|
107
|
-
)
|
|
108
|
-
.add_variable(
|
|
109
|
-
name="beta",
|
|
110
|
-
dimensions=("time", "range"),
|
|
111
|
-
units="sr-1 m-1",
|
|
112
|
-
data=stare.beta,
|
|
113
|
-
dtype="f4",
|
|
114
|
-
mask=stare.mask,
|
|
115
|
-
)
|
|
116
|
-
.add_variable(
|
|
117
|
-
name="v",
|
|
118
|
-
dimensions=("time", "range"),
|
|
119
|
-
units="m s-1",
|
|
120
|
-
long_name="Doppler velocity",
|
|
121
|
-
data=stare.radial_velocity,
|
|
122
|
-
dtype="f4",
|
|
123
|
-
mask=stare.mask,
|
|
124
|
-
)
|
|
125
|
-
.add_scalar_variable(
|
|
126
|
-
name="wavelength",
|
|
127
|
-
units="m",
|
|
128
|
-
standard_name="radiation_wavelength",
|
|
129
|
-
data=stare.wavelength,
|
|
130
|
-
dtype="f4",
|
|
131
|
-
)
|
|
132
|
-
.add_attribute("serial_number", stare.system_id)
|
|
133
|
-
.add_attribute("doppy_version", doppy.__version__)
|
|
134
|
-
).close()
|
|
133
|
+
# Windcube WLS200S
|
|
134
|
+
raws_wls200s = doppy.raw.WindCube.from_vad_srcs(LIST_OF_VAD_NETCDF_FILES)
|
|
135
135
|
|
|
136
|
+
# Windcube WLS70
|
|
137
|
+
raws_wls70 = doppy.raw.Wls70.from_srcs(LIST_OF_RTD_FILES)
|
|
136
138
|
```
|
|
137
139
|
|
doppy-0.3.3/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Doppy – Doppler wind lidar processing
|
|
2
|
+
|
|
3
|
+
[](https://github.com/actris-cloudnet/doppy/actions/workflows/ci.yml)
|
|
4
|
+
[](https://badge.fury.io/py/doppy)
|
|
5
|
+
|
|
6
|
+
## Products
|
|
7
|
+
|
|
8
|
+
- Stare: [src](https://github.com/actris-cloudnet/doppy/blob/main/src/doppy/product/stare.py), [Cloudnet examples](https://cloudnet.fmi.fi/search/visualizations?experimental=true&product=doppler-lidar&dateFrom=2024-06-05&dateTo=2024-06-05)
|
|
9
|
+
- Wind: [src](https://github.com/actris-cloudnet/doppy/blob/main/src/doppy/product/wind.py), [Cloudnet examples](https://cloudnet.fmi.fi/search/visualizations?experimental=true&product=doppler-lidar-wind&dateFrom=2024-06-05&dateTo=2024-06-05)
|
|
10
|
+
|
|
11
|
+
## Instruments
|
|
12
|
+
|
|
13
|
+
- HALO Photonics Streamline lidars (stare, wind)
|
|
14
|
+
- Leosphere WindCube WLS200S (wind)
|
|
15
|
+
- Leosphere WindCube WLS70 (wind)
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pip install doppy
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Stare
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import doppy
|
|
29
|
+
|
|
30
|
+
stare = doppy.product.Stare.from_halo_data(
|
|
31
|
+
data=LIST_OF_STARE_FILE_PATHS,
|
|
32
|
+
data_bg=LIST_OF_BACKGROUND_FILE_PATHS,
|
|
33
|
+
bg_correction_method=doppy.options.BgCorrectionMethod.FIT,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
stare.write_to_netcdf(FILENAME)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Stare with depolarisation
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import doppy
|
|
43
|
+
|
|
44
|
+
stare_depol = doppy.product.StareDepol.from_halo_data(
|
|
45
|
+
co_data=LIST_OF_STARE_CO_FILE_PATHS,
|
|
46
|
+
co_data_bg=LIST_OF_BACKGROUND_CO_FILE_PATHS,
|
|
47
|
+
cross_data=LIST_OF_STARE_CROSS_FILE_PATHS,
|
|
48
|
+
cross_data_bg=LIST_OF_BACKGROUND_CROSS_FILE_PATHS,
|
|
49
|
+
bg_correction_method=doppy.options.BgCorrectionMethod.FIT,
|
|
50
|
+
polariser_bleed_through=0,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
stare_depol.write_to_netcdf(FILENAME)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Wind
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
import doppy
|
|
60
|
+
|
|
61
|
+
wind = doppy.product.Wind.from_halo_data(
|
|
62
|
+
data=LIST_OF_WIND_SCAN_HPL_FILES,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# You can also pass instrument azimuth offset in degrees as an option
|
|
66
|
+
wind = doppy.product.Wind.from_halo_data(
|
|
67
|
+
data=LIST_OF_WIND_SCAN_HPL_FILES,
|
|
68
|
+
options=doppy.product.wind.Options(azimuth_offset_deg=30),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# For windcube wls200s use
|
|
72
|
+
wind = doppy.product.Wind.from_windcube_data(
|
|
73
|
+
data=LIST_OF_VAD_NETCDF_FILES,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# For windcube wls70 use
|
|
77
|
+
wind = doppy.product.Wind.from_wls70_data(
|
|
78
|
+
data=LIST_OF_RTD_FILES,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
wind.write_to_netcdf(FILENAME)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Raw files
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import doppy
|
|
88
|
+
|
|
89
|
+
# Halo
|
|
90
|
+
raws_hpl = doppy.raw.HaloHpl.from_srcs(LIST_OF_HPL_FILES)
|
|
91
|
+
raws_bg = doppy.raw.HaloBg.from_srcs(LIST_OF_BACKGROUND_FILES)
|
|
92
|
+
raw_system_params = doppy.raw.HaloSysParams.from_src(SYSTEM_PARAMS_FILENAME)
|
|
93
|
+
|
|
94
|
+
# Windcube WLS200S
|
|
95
|
+
raws_wls200s = doppy.raw.WindCube.from_vad_srcs(LIST_OF_VAD_NETCDF_FILES)
|
|
96
|
+
|
|
97
|
+
# Windcube WLS70
|
|
98
|
+
raws_wls70 = doppy.raw.Wls70.from_srcs(LIST_OF_RTD_FILES)
|
|
99
|
+
```
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import pathlib
|
|
3
4
|
import warnings
|
|
4
5
|
from types import TracebackType
|
|
5
6
|
from typing import Literal, TypeAlias
|
|
@@ -12,7 +13,7 @@ NetCDFDataType: TypeAlias = Literal["f4", "f8", "i4", "i8", "u4", "u8"]
|
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class Dataset:
|
|
15
|
-
def __init__(self, filename: str) -> None:
|
|
16
|
+
def __init__(self, filename: str | pathlib.Path) -> None:
|
|
16
17
|
self.nc = netCDF4.Dataset(filename, mode="w")
|
|
17
18
|
|
|
18
19
|
def __enter__(self) -> Dataset:
|
|
@@ -29,6 +29,28 @@ class Stare:
|
|
|
29
29
|
wavelength: float
|
|
30
30
|
system_id: str
|
|
31
31
|
|
|
32
|
+
def __getitem__(
|
|
33
|
+
self,
|
|
34
|
+
index: int
|
|
35
|
+
| slice
|
|
36
|
+
| list[int]
|
|
37
|
+
| npt.NDArray[np.int64]
|
|
38
|
+
| npt.NDArray[np.bool_]
|
|
39
|
+
| tuple[slice, slice],
|
|
40
|
+
) -> Stare:
|
|
41
|
+
if isinstance(index, (int, slice, list, np.ndarray)):
|
|
42
|
+
return Stare(
|
|
43
|
+
time=self.time[index],
|
|
44
|
+
radial_distance=self.radial_distance,
|
|
45
|
+
elevation=self.elevation[index],
|
|
46
|
+
beta=self.beta[index],
|
|
47
|
+
radial_velocity=self.radial_velocity[index],
|
|
48
|
+
mask=self.mask[index],
|
|
49
|
+
wavelength=self.wavelength,
|
|
50
|
+
system_id=self.system_id,
|
|
51
|
+
)
|
|
52
|
+
raise TypeError
|
|
53
|
+
|
|
32
54
|
@classmethod
|
|
33
55
|
def from_halo_data(
|
|
34
56
|
cls,
|
|
@@ -93,6 +115,67 @@ class Stare:
|
|
|
93
115
|
system_id=raw.header.system_id,
|
|
94
116
|
)
|
|
95
117
|
|
|
118
|
+
def write_to_netcdf(self, filename: str | Path) -> None:
|
|
119
|
+
with doppy.netcdf.Dataset(filename) as nc:
|
|
120
|
+
nc.add_dimension("time")
|
|
121
|
+
nc.add_dimension("range")
|
|
122
|
+
nc.add_time(
|
|
123
|
+
name="time",
|
|
124
|
+
dimensions=("time",),
|
|
125
|
+
standard_name="time",
|
|
126
|
+
long_name="Time UTC",
|
|
127
|
+
data=self.time,
|
|
128
|
+
dtype="f8",
|
|
129
|
+
)
|
|
130
|
+
nc.add_variable(
|
|
131
|
+
name="range",
|
|
132
|
+
dimensions=("range",),
|
|
133
|
+
units="m",
|
|
134
|
+
data=self.radial_distance,
|
|
135
|
+
dtype="f4",
|
|
136
|
+
)
|
|
137
|
+
nc.add_variable(
|
|
138
|
+
name="elevation",
|
|
139
|
+
dimensions=("time",),
|
|
140
|
+
units="degrees",
|
|
141
|
+
data=self.elevation,
|
|
142
|
+
dtype="f4",
|
|
143
|
+
long_name="elevation from horizontal",
|
|
144
|
+
)
|
|
145
|
+
nc.add_variable(
|
|
146
|
+
name="beta_raw",
|
|
147
|
+
dimensions=("time", "range"),
|
|
148
|
+
units="sr-1 m-1",
|
|
149
|
+
data=self.beta,
|
|
150
|
+
dtype="f4",
|
|
151
|
+
)
|
|
152
|
+
nc.add_variable(
|
|
153
|
+
name="beta",
|
|
154
|
+
dimensions=("time", "range"),
|
|
155
|
+
units="sr-1 m-1",
|
|
156
|
+
data=self.beta,
|
|
157
|
+
dtype="f4",
|
|
158
|
+
mask=self.mask,
|
|
159
|
+
)
|
|
160
|
+
nc.add_variable(
|
|
161
|
+
name="v",
|
|
162
|
+
dimensions=("time", "range"),
|
|
163
|
+
units="m s-1",
|
|
164
|
+
long_name="Doppler velocity",
|
|
165
|
+
data=self.radial_velocity,
|
|
166
|
+
dtype="f4",
|
|
167
|
+
mask=self.mask,
|
|
168
|
+
)
|
|
169
|
+
nc.add_scalar_variable(
|
|
170
|
+
name="wavelength",
|
|
171
|
+
units="m",
|
|
172
|
+
standard_name="radiation_wavelength",
|
|
173
|
+
data=self.wavelength,
|
|
174
|
+
dtype="f4",
|
|
175
|
+
)
|
|
176
|
+
nc.add_attribute("serial_number", self.system_id)
|
|
177
|
+
nc.add_attribute("doppy_version", doppy.__version__)
|
|
178
|
+
|
|
96
179
|
|
|
97
180
|
def _compute_noise_mask(
|
|
98
181
|
intensity: npt.NDArray[np.float64],
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from io import BufferedIOBase
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Sequence
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import numpy.typing as npt
|
|
10
|
+
|
|
11
|
+
import doppy
|
|
12
|
+
from doppy import options
|
|
13
|
+
from doppy.product.stare import Stare
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class StareDepol:
|
|
18
|
+
"""
|
|
19
|
+
Stare product with depolarisation ratio derived from co-polarised and
|
|
20
|
+
cross-polarised stare data.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
-----------
|
|
24
|
+
time
|
|
25
|
+
An array of datetime64 objects representing the observation times.
|
|
26
|
+
radial_distance
|
|
27
|
+
An array of radial distances from the observation point, in meters.
|
|
28
|
+
elevation
|
|
29
|
+
An array of elevation angles corresponding to the observation points, in
|
|
30
|
+
degrees.
|
|
31
|
+
beta
|
|
32
|
+
An array of backscatter coefficients for the co-polarised signal, in
|
|
33
|
+
sr-1 m-1.
|
|
34
|
+
beta_cross
|
|
35
|
+
An array of backscatter coefficients for the cross-polarised signal, in
|
|
36
|
+
sr-1 m-1.
|
|
37
|
+
radial_velocity
|
|
38
|
+
An array of radial velocities of the co-polarised signal, in m s-1.
|
|
39
|
+
mask
|
|
40
|
+
A boolean array indicating signal (True) or noise (False) data points.
|
|
41
|
+
depolarisation
|
|
42
|
+
An array of depolarisation ratios calculated as the ratio of
|
|
43
|
+
co-polarised to cross-polarised backscatter coefficients.
|
|
44
|
+
wavelength
|
|
45
|
+
The wavelength of the lidar, in meters.
|
|
46
|
+
system_id
|
|
47
|
+
A string identifier for the lidar.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Raises
|
|
51
|
+
------
|
|
52
|
+
ValueError
|
|
53
|
+
If the input `co` and `cross` products have mismatched wavelengths,
|
|
54
|
+
system IDs, radial distances, or elevation angles, this exception is
|
|
55
|
+
raised.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
References
|
|
59
|
+
----------
|
|
60
|
+
Aerosol particle depolarization ratio at 1565 nm measured with a Halo Doppler lidar
|
|
61
|
+
authors: Ville Vakkari, Holger Baars, Stephanie Bohlmann, Johannes Bühl,
|
|
62
|
+
Mika Komppula, Rodanthi-Elisavet Mamouri, and Ewan James O'Connor
|
|
63
|
+
doi: https://doi.org/10.5194/acp-21-5807-2021
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
time: npt.NDArray[np.datetime64]
|
|
67
|
+
radial_distance: npt.NDArray[np.float64]
|
|
68
|
+
elevation: npt.NDArray[np.float64]
|
|
69
|
+
beta: npt.NDArray[np.float64]
|
|
70
|
+
beta_cross: npt.NDArray[np.float64]
|
|
71
|
+
radial_velocity: npt.NDArray[np.float64]
|
|
72
|
+
mask: npt.NDArray[np.bool_]
|
|
73
|
+
depolarisation: npt.NDArray[np.float64]
|
|
74
|
+
mask_depolarisation: npt.NDArray[np.bool_]
|
|
75
|
+
mask_beta_cross: npt.NDArray[np.bool_]
|
|
76
|
+
polariser_bleed_through: float
|
|
77
|
+
wavelength: float
|
|
78
|
+
system_id: str
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
co: Stare,
|
|
83
|
+
cross: Stare,
|
|
84
|
+
polariser_bleed_through: float = 0.0,
|
|
85
|
+
):
|
|
86
|
+
"""
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
co: Stare
|
|
90
|
+
The co-polarised data.
|
|
91
|
+
cross: Stare
|
|
92
|
+
The cross-polarised data. The `cross.time` array is expected to be sorted.
|
|
93
|
+
polariser_bleed_through: float, default=0.0
|
|
94
|
+
The amount of bleed-through from the polariser.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
if not np.isclose(co.wavelength, cross.wavelength):
|
|
98
|
+
raise ValueError(
|
|
99
|
+
"Different wavelength in co and cross: "
|
|
100
|
+
f"{co.wavelength} vs {cross.wavelength}"
|
|
101
|
+
)
|
|
102
|
+
if co.system_id != cross.system_id:
|
|
103
|
+
raise ValueError(
|
|
104
|
+
"Different system ID in co and cross: "
|
|
105
|
+
f"{co.system_id} vs {cross.system_id}"
|
|
106
|
+
)
|
|
107
|
+
if not np.allclose(co.radial_distance, cross.radial_distance, atol=1):
|
|
108
|
+
raise ValueError("Different radial distance in co and cross")
|
|
109
|
+
|
|
110
|
+
if co.beta.shape[1] != cross.beta.shape[1]:
|
|
111
|
+
raise ValueError(
|
|
112
|
+
"Range dimension mismatch in co and cross: "
|
|
113
|
+
f"{co.beta.shape[1]} vs {cross.beta.shape[1]}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
ind = np.searchsorted(cross.time, co.time, side="left")
|
|
117
|
+
pick_ind = ind < len(cross.time)
|
|
118
|
+
time_diff_threshold = 2 * np.median(np.diff(co.time))
|
|
119
|
+
co_cross_timediff_below_threshold = (
|
|
120
|
+
cross.time[ind[pick_ind]] - co.time[pick_ind] < time_diff_threshold
|
|
121
|
+
)
|
|
122
|
+
pick_ind[pick_ind] &= co_cross_timediff_below_threshold
|
|
123
|
+
|
|
124
|
+
if not np.allclose(
|
|
125
|
+
co.elevation[pick_ind], cross.elevation[ind[pick_ind]], atol=1
|
|
126
|
+
):
|
|
127
|
+
raise ValueError("Different elevation in co and cross")
|
|
128
|
+
|
|
129
|
+
depolarisation = np.full_like(co.beta, np.nan)
|
|
130
|
+
co_beta = co.beta[pick_ind]
|
|
131
|
+
depolarisation[pick_ind] = (
|
|
132
|
+
cross.beta[ind[pick_ind]] - polariser_bleed_through * co_beta
|
|
133
|
+
) / co_beta
|
|
134
|
+
cross_beta = np.full_like(co.beta, np.nan)
|
|
135
|
+
cross_beta[pick_ind] = cross.beta[ind[pick_ind]]
|
|
136
|
+
|
|
137
|
+
self.time = co.time
|
|
138
|
+
self.radial_distance = co.radial_distance
|
|
139
|
+
self.elevation = co.elevation
|
|
140
|
+
self.beta = co.beta
|
|
141
|
+
self.beta_cross = cross_beta
|
|
142
|
+
self.radial_velocity = co.radial_velocity
|
|
143
|
+
self.mask = co.mask
|
|
144
|
+
self.depolarisation = depolarisation
|
|
145
|
+
self.mask_depolarisation = np.isnan(depolarisation)
|
|
146
|
+
self.mask_beta_cross = np.isnan(self.beta_cross)
|
|
147
|
+
self.polariser_bleed_through = polariser_bleed_through
|
|
148
|
+
self.wavelength = co.wavelength
|
|
149
|
+
self.system_id = co.system_id
|
|
150
|
+
|
|
151
|
+
@classmethod
|
|
152
|
+
def from_halo_data(
|
|
153
|
+
cls,
|
|
154
|
+
co_data: Sequence[str]
|
|
155
|
+
| Sequence[Path]
|
|
156
|
+
| Sequence[bytes]
|
|
157
|
+
| Sequence[BufferedIOBase],
|
|
158
|
+
co_data_bg: Sequence[str]
|
|
159
|
+
| Sequence[Path]
|
|
160
|
+
| Sequence[tuple[bytes, str]]
|
|
161
|
+
| Sequence[tuple[BufferedIOBase, str]],
|
|
162
|
+
cross_data: Sequence[str]
|
|
163
|
+
| Sequence[Path]
|
|
164
|
+
| Sequence[bytes]
|
|
165
|
+
| Sequence[BufferedIOBase],
|
|
166
|
+
cross_data_bg: Sequence[str]
|
|
167
|
+
| Sequence[Path]
|
|
168
|
+
| Sequence[tuple[bytes, str]]
|
|
169
|
+
| Sequence[tuple[BufferedIOBase, str]],
|
|
170
|
+
bg_correction_method: options.BgCorrectionMethod,
|
|
171
|
+
polariser_bleed_through: float = 0,
|
|
172
|
+
) -> StareDepol:
|
|
173
|
+
co = Stare.from_halo_data(
|
|
174
|
+
data=co_data, data_bg=co_data_bg, bg_correction_method=bg_correction_method
|
|
175
|
+
)
|
|
176
|
+
cross = Stare.from_halo_data(
|
|
177
|
+
data=cross_data,
|
|
178
|
+
data_bg=cross_data_bg,
|
|
179
|
+
bg_correction_method=bg_correction_method,
|
|
180
|
+
)
|
|
181
|
+
return cls(co, cross, polariser_bleed_through)
|
|
182
|
+
|
|
183
|
+
def write_to_netcdf(self, filename: str | Path) -> None:
|
|
184
|
+
with doppy.netcdf.Dataset(filename) as nc:
|
|
185
|
+
nc.add_dimension("time")
|
|
186
|
+
nc.add_dimension("range")
|
|
187
|
+
nc.add_time(
|
|
188
|
+
name="time",
|
|
189
|
+
dimensions=("time",),
|
|
190
|
+
standard_name="time",
|
|
191
|
+
long_name="Time UTC",
|
|
192
|
+
data=self.time,
|
|
193
|
+
dtype="f8",
|
|
194
|
+
)
|
|
195
|
+
nc.add_variable(
|
|
196
|
+
name="range",
|
|
197
|
+
dimensions=("range",),
|
|
198
|
+
units="m",
|
|
199
|
+
data=self.radial_distance,
|
|
200
|
+
dtype="f4",
|
|
201
|
+
)
|
|
202
|
+
nc.add_variable(
|
|
203
|
+
name="elevation",
|
|
204
|
+
dimensions=("time",),
|
|
205
|
+
units="degrees",
|
|
206
|
+
data=self.elevation,
|
|
207
|
+
dtype="f4",
|
|
208
|
+
long_name="elevation from horizontal",
|
|
209
|
+
)
|
|
210
|
+
nc.add_variable(
|
|
211
|
+
name="beta_raw",
|
|
212
|
+
dimensions=("time", "range"),
|
|
213
|
+
units="sr-1 m-1",
|
|
214
|
+
data=self.beta,
|
|
215
|
+
dtype="f4",
|
|
216
|
+
)
|
|
217
|
+
nc.add_variable(
|
|
218
|
+
name="beta",
|
|
219
|
+
dimensions=("time", "range"),
|
|
220
|
+
units="sr-1 m-1",
|
|
221
|
+
data=self.beta,
|
|
222
|
+
dtype="f4",
|
|
223
|
+
mask=self.mask,
|
|
224
|
+
)
|
|
225
|
+
nc.add_variable(
|
|
226
|
+
name="v",
|
|
227
|
+
dimensions=("time", "range"),
|
|
228
|
+
units="m s-1",
|
|
229
|
+
long_name="Doppler velocity",
|
|
230
|
+
data=self.radial_velocity,
|
|
231
|
+
dtype="f4",
|
|
232
|
+
mask=self.mask,
|
|
233
|
+
)
|
|
234
|
+
nc.add_scalar_variable(
|
|
235
|
+
name="wavelength",
|
|
236
|
+
units="m",
|
|
237
|
+
standard_name="radiation_wavelength",
|
|
238
|
+
data=self.wavelength,
|
|
239
|
+
dtype="f4",
|
|
240
|
+
)
|
|
241
|
+
nc.add_variable(
|
|
242
|
+
name="depolarisation_raw",
|
|
243
|
+
dimensions=("time", "range"),
|
|
244
|
+
units="1",
|
|
245
|
+
data=self.depolarisation,
|
|
246
|
+
dtype="f4",
|
|
247
|
+
mask=self.mask_depolarisation,
|
|
248
|
+
)
|
|
249
|
+
nc.add_variable(
|
|
250
|
+
name="depolarisation",
|
|
251
|
+
dimensions=("time", "range"),
|
|
252
|
+
units="1",
|
|
253
|
+
data=self.depolarisation,
|
|
254
|
+
dtype="f4",
|
|
255
|
+
mask=self.mask | self.mask_depolarisation,
|
|
256
|
+
)
|
|
257
|
+
nc.add_variable(
|
|
258
|
+
name="beta_cross_raw",
|
|
259
|
+
dimensions=("time", "range"),
|
|
260
|
+
units="sr-1 m-1",
|
|
261
|
+
data=self.beta_cross,
|
|
262
|
+
mask=self.mask_beta_cross,
|
|
263
|
+
dtype="f4",
|
|
264
|
+
)
|
|
265
|
+
nc.add_variable(
|
|
266
|
+
name="beta_cross",
|
|
267
|
+
dimensions=("time", "range"),
|
|
268
|
+
units="sr-1 m-1",
|
|
269
|
+
data=self.beta_cross,
|
|
270
|
+
mask=self.mask | self.mask_beta_cross,
|
|
271
|
+
dtype="f4",
|
|
272
|
+
)
|
|
273
|
+
nc.add_scalar_variable(
|
|
274
|
+
name="polariser_bleed_through",
|
|
275
|
+
units="1",
|
|
276
|
+
long_name="Polariser bleed-through",
|
|
277
|
+
data=self.polariser_bleed_through,
|
|
278
|
+
dtype="f4",
|
|
279
|
+
)
|
|
280
|
+
nc.add_attribute("serial_number", self.system_id)
|
|
281
|
+
nc.add_attribute("doppy_version", doppy.__version__)
|
|
@@ -32,6 +32,7 @@ class Wind:
|
|
|
32
32
|
vertical_wind: npt.NDArray[np.float64]
|
|
33
33
|
mask: npt.NDArray[np.bool_]
|
|
34
34
|
system_id: str
|
|
35
|
+
options: Options | None
|
|
35
36
|
|
|
36
37
|
@functools.cached_property
|
|
37
38
|
def horizontal_wind_speed(self) -> npt.NDArray[np.float64]:
|
|
@@ -104,6 +105,7 @@ class Wind:
|
|
|
104
105
|
vertical_wind=wind[:, :, 2],
|
|
105
106
|
mask=mask,
|
|
106
107
|
system_id=raw.header.system_id,
|
|
108
|
+
options=options,
|
|
107
109
|
)
|
|
108
110
|
|
|
109
111
|
@classmethod
|
|
@@ -163,6 +165,7 @@ class Wind:
|
|
|
163
165
|
vertical_wind=wind[:, :, 2],
|
|
164
166
|
mask=mask,
|
|
165
167
|
system_id=raw.system_id,
|
|
168
|
+
options=options,
|
|
166
169
|
)
|
|
167
170
|
|
|
168
171
|
@classmethod
|
|
@@ -211,8 +214,74 @@ class Wind:
|
|
|
211
214
|
vertical_wind=raw.vertical_wind,
|
|
212
215
|
mask=mask,
|
|
213
216
|
system_id=raw.system_id,
|
|
217
|
+
options=options,
|
|
214
218
|
)
|
|
215
219
|
|
|
220
|
+
def write_to_netcdf(self, filename: str | Path) -> None:
|
|
221
|
+
with doppy.netcdf.Dataset(filename) as nc:
|
|
222
|
+
nc.add_dimension("time")
|
|
223
|
+
nc.add_dimension("height")
|
|
224
|
+
nc.add_time(
|
|
225
|
+
name="time",
|
|
226
|
+
dimensions=("time",),
|
|
227
|
+
standard_name="time",
|
|
228
|
+
long_name="Time UTC",
|
|
229
|
+
data=self.time,
|
|
230
|
+
dtype="f8",
|
|
231
|
+
)
|
|
232
|
+
nc.add_variable(
|
|
233
|
+
name="height",
|
|
234
|
+
dimensions=("height",),
|
|
235
|
+
units="m",
|
|
236
|
+
data=self.height,
|
|
237
|
+
dtype="f4",
|
|
238
|
+
)
|
|
239
|
+
nc.add_variable(
|
|
240
|
+
name="uwind_raw",
|
|
241
|
+
dimensions=("time", "height"),
|
|
242
|
+
units="m s-1",
|
|
243
|
+
data=self.zonal_wind,
|
|
244
|
+
dtype="f4",
|
|
245
|
+
long_name="Non-screened zonal wind",
|
|
246
|
+
)
|
|
247
|
+
nc.add_variable(
|
|
248
|
+
name="uwind",
|
|
249
|
+
dimensions=("time", "height"),
|
|
250
|
+
units="m s-1",
|
|
251
|
+
data=self.zonal_wind,
|
|
252
|
+
mask=self.mask,
|
|
253
|
+
dtype="f4",
|
|
254
|
+
long_name="Zonal wind",
|
|
255
|
+
)
|
|
256
|
+
nc.add_variable(
|
|
257
|
+
name="vwind_raw",
|
|
258
|
+
dimensions=("time", "height"),
|
|
259
|
+
units="m s-1",
|
|
260
|
+
data=self.meridional_wind,
|
|
261
|
+
dtype="f4",
|
|
262
|
+
long_name="Non-screened meridional wind",
|
|
263
|
+
)
|
|
264
|
+
nc.add_variable(
|
|
265
|
+
name="vwind",
|
|
266
|
+
dimensions=("time", "height"),
|
|
267
|
+
units="m s-1",
|
|
268
|
+
data=self.meridional_wind,
|
|
269
|
+
mask=self.mask,
|
|
270
|
+
dtype="f4",
|
|
271
|
+
long_name="Meridional wind",
|
|
272
|
+
)
|
|
273
|
+
nc.add_attribute("serial_number", self.system_id)
|
|
274
|
+
nc.add_attribute("doppy_version", doppy.__version__)
|
|
275
|
+
if self.options is not None and self.options.azimuth_offset_deg is not None:
|
|
276
|
+
nc.add_scalar_variable(
|
|
277
|
+
name="azimuth_offset",
|
|
278
|
+
units="degrees",
|
|
279
|
+
data=self.options.azimuth_offset_deg,
|
|
280
|
+
dtype="f4",
|
|
281
|
+
long_name="Azimuth offset of the instrument "
|
|
282
|
+
"(positive clockwise from north)",
|
|
283
|
+
)
|
|
284
|
+
|
|
216
285
|
|
|
217
286
|
def _compute_wind(
|
|
218
287
|
raw: doppy.raw.HaloHpl | doppy.raw.WindCube,
|
doppy-0.3.1/README.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# Doppy – Doppler wind lidar processing
|
|
2
|
-
|
|
3
|
-
[](https://github.com/actris-cloudnet/doppy/actions/workflows/ci.yml)
|
|
4
|
-
[](https://badge.fury.io/py/doppy)
|
|
5
|
-
|
|
6
|
-
## Products
|
|
7
|
-
|
|
8
|
-
- [Stare](https://github.com/actris-cloudnet/doppy/blob/main/src/doppy/product/stare.py): [Examples](https://cloudnet.fmi.fi/search/visualizations?experimental=true&product=doppler-lidar&dateFrom=2024-06-05&dateTo=2024-06-05)
|
|
9
|
-
- [Wind](https://github.com/actris-cloudnet/doppy/blob/main/src/doppy/product/wind.py): [Examples](https://cloudnet.fmi.fi/search/visualizations?experimental=true&product=doppler-lidar-wind&dateFrom=2024-06-05&dateTo=2024-06-05)
|
|
10
|
-
|
|
11
|
-
## Instruments
|
|
12
|
-
|
|
13
|
-
- HALO Photonics Streamline lidars (stare, wind)
|
|
14
|
-
- Leosphere WindCube WLS200S (wind)
|
|
15
|
-
- Leosphere WindCube WLS70 (wind)
|
|
16
|
-
|
|
17
|
-
## Install
|
|
18
|
-
|
|
19
|
-
```sh
|
|
20
|
-
pip install doppy
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Usage
|
|
24
|
-
|
|
25
|
-
```python
|
|
26
|
-
import doppy
|
|
27
|
-
|
|
28
|
-
stare = doppy.product.Stare.from_halo_data(
|
|
29
|
-
data=LIST_OF_STARE_FILE_PATHS,
|
|
30
|
-
data_bg=LIST_OF_BACKGROUND_FILE_PATHS,
|
|
31
|
-
bg_correction_method=doppy.options.BgCorrectionMethod.FIT,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
(
|
|
36
|
-
doppy.netcdf.Dataset(FILENAME)
|
|
37
|
-
.add_dimension("time")
|
|
38
|
-
.add_dimension("range")
|
|
39
|
-
.add_time(
|
|
40
|
-
name="time",
|
|
41
|
-
dimensions=("time",),
|
|
42
|
-
standard_name="time",
|
|
43
|
-
long_name="Time UTC",
|
|
44
|
-
data=stare.time,
|
|
45
|
-
dtype="f8",
|
|
46
|
-
)
|
|
47
|
-
.add_variable(
|
|
48
|
-
name="range",
|
|
49
|
-
dimensions=("range",),
|
|
50
|
-
units="m",
|
|
51
|
-
data=stare.radial_distance,
|
|
52
|
-
dtype="f4",
|
|
53
|
-
)
|
|
54
|
-
.add_variable(
|
|
55
|
-
name="elevation",
|
|
56
|
-
dimensions=("time",),
|
|
57
|
-
units="degrees",
|
|
58
|
-
data=stare.elevation,
|
|
59
|
-
dtype="f4",
|
|
60
|
-
long_name="elevation from horizontal",
|
|
61
|
-
)
|
|
62
|
-
.add_variable(
|
|
63
|
-
name="beta_raw",
|
|
64
|
-
dimensions=("time", "range"),
|
|
65
|
-
units="sr-1 m-1",
|
|
66
|
-
data=stare.beta,
|
|
67
|
-
dtype="f4",
|
|
68
|
-
)
|
|
69
|
-
.add_variable(
|
|
70
|
-
name="beta",
|
|
71
|
-
dimensions=("time", "range"),
|
|
72
|
-
units="sr-1 m-1",
|
|
73
|
-
data=stare.beta,
|
|
74
|
-
dtype="f4",
|
|
75
|
-
mask=stare.mask,
|
|
76
|
-
)
|
|
77
|
-
.add_variable(
|
|
78
|
-
name="v",
|
|
79
|
-
dimensions=("time", "range"),
|
|
80
|
-
units="m s-1",
|
|
81
|
-
long_name="Doppler velocity",
|
|
82
|
-
data=stare.radial_velocity,
|
|
83
|
-
dtype="f4",
|
|
84
|
-
mask=stare.mask,
|
|
85
|
-
)
|
|
86
|
-
.add_scalar_variable(
|
|
87
|
-
name="wavelength",
|
|
88
|
-
units="m",
|
|
89
|
-
standard_name="radiation_wavelength",
|
|
90
|
-
data=stare.wavelength,
|
|
91
|
-
dtype="f4",
|
|
92
|
-
)
|
|
93
|
-
.add_attribute("serial_number", stare.system_id)
|
|
94
|
-
.add_attribute("doppy_version", doppy.__version__)
|
|
95
|
-
).close()
|
|
96
|
-
|
|
97
|
-
```
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import numpy.typing as npt
|
|
3
|
-
|
|
4
|
-
from doppy.product.stare import Stare
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class StareDepol:
|
|
8
|
-
"""
|
|
9
|
-
Stare product with depolarisation ratio derived from co-polarised and
|
|
10
|
-
cross-polarised stare data.
|
|
11
|
-
|
|
12
|
-
Attributes:
|
|
13
|
-
-----------
|
|
14
|
-
time
|
|
15
|
-
An array of datetime64 objects representing the observation times.
|
|
16
|
-
radial_distance
|
|
17
|
-
An array of radial distances from the observation point, in meters.
|
|
18
|
-
elevation
|
|
19
|
-
An array of elevation angles corresponding to the observation points, in
|
|
20
|
-
degrees.
|
|
21
|
-
beta
|
|
22
|
-
An array of backscatter coefficients for the co-polarised signal, in
|
|
23
|
-
sr-1 m-1.
|
|
24
|
-
radial_velocity
|
|
25
|
-
An array of radial velocities of the co-polarised signal, in m s-1.
|
|
26
|
-
mask
|
|
27
|
-
A boolean array indicating signal (True) or noise (False) data points.
|
|
28
|
-
depolarisation
|
|
29
|
-
An array of depolarisation ratios calculated as the ratio of
|
|
30
|
-
co-polarised to cross-polarised backscatter coefficients.
|
|
31
|
-
wavelength
|
|
32
|
-
The wavelength of the lidar, in meters.
|
|
33
|
-
system_id
|
|
34
|
-
A string identifier for the lidar.
|
|
35
|
-
|
|
36
|
-
Raises
|
|
37
|
-
------
|
|
38
|
-
ValueError
|
|
39
|
-
If the input `co` and `cross` products have mismatched wavelengths,
|
|
40
|
-
system IDs, radial distances, or elevation angles, this exception is
|
|
41
|
-
raised.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
time: npt.NDArray[np.datetime64]
|
|
45
|
-
radial_distance: npt.NDArray[np.float64]
|
|
46
|
-
elevation: npt.NDArray[np.float64]
|
|
47
|
-
beta: npt.NDArray[np.float64]
|
|
48
|
-
radial_velocity: npt.NDArray[np.float64]
|
|
49
|
-
mask: npt.NDArray[np.bool_]
|
|
50
|
-
depolarisation: npt.NDArray[np.float64]
|
|
51
|
-
wavelength: float
|
|
52
|
-
system_id: str
|
|
53
|
-
|
|
54
|
-
def __init__(self, co: Stare, cross: Stare):
|
|
55
|
-
if co.wavelength != cross.wavelength:
|
|
56
|
-
raise ValueError(
|
|
57
|
-
"Different wavelength in co and cross: "
|
|
58
|
-
f"{co.wavelength} vs {cross.wavelength}"
|
|
59
|
-
)
|
|
60
|
-
if co.system_id != cross.system_id:
|
|
61
|
-
raise ValueError(
|
|
62
|
-
"Different system ID in co and cross: "
|
|
63
|
-
f"{co.system_id} vs {cross.system_id}"
|
|
64
|
-
)
|
|
65
|
-
if not np.allclose(co.radial_distance, cross.radial_distance, atol=1):
|
|
66
|
-
raise ValueError("Different radial distance in co and cross")
|
|
67
|
-
|
|
68
|
-
time_ind = np.argmin(np.abs(co.time - cross.time[:, np.newaxis]), axis=0)
|
|
69
|
-
cross_elevation = cross.elevation[time_ind]
|
|
70
|
-
cross_beta = cross.beta[time_ind, :]
|
|
71
|
-
|
|
72
|
-
if not np.allclose(co.elevation, cross_elevation, atol=1):
|
|
73
|
-
raise ValueError("Different elevation in co and cross")
|
|
74
|
-
|
|
75
|
-
self.time = co.time
|
|
76
|
-
self.radial_distance = co.radial_distance
|
|
77
|
-
self.elevation = co.elevation
|
|
78
|
-
self.beta = co.beta
|
|
79
|
-
self.radial_velocity = co.radial_velocity
|
|
80
|
-
self.mask = co.mask
|
|
81
|
-
self.depolarisation = cross_beta / co.beta
|
|
82
|
-
self.wavelength = co.wavelength
|
|
83
|
-
self.system_id = co.system_id
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|