doppy 0.2.0__tar.gz → 0.2.2__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.2.0 → doppy-0.2.2}/Cargo.lock +2 -2
- {doppy-0.2.0 → doppy-0.2.2}/Cargo.toml +1 -1
- {doppy-0.2.0 → doppy-0.2.2}/PKG-INFO +1 -1
- {doppy-0.2.0 → doppy-0.2.2}/crates/doppy_rs/src/raw/wls70.rs +1 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/src/raw/wls70.rs +9 -0
- doppy-0.2.2/src/doppy/product/__init__.py +5 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/product/stare.py +2 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/product/wind.py +34 -2
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/raw/halo_hpl.py +3 -10
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/raw/windcube.py +6 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/raw/wls70.py +8 -4
- doppy-0.2.2/src/doppy/utils.py +9 -0
- doppy-0.2.0/src/doppy/product/__init__.py +0 -4
- {doppy-0.2.0 → doppy-0.2.2}/LICENSE +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/README.md +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doppy_rs/Cargo.toml +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doppy_rs/src/lib.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doppy_rs/src/raw/halo_hpl.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doppy_rs/src/raw.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/.gitignore +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/Cargo.toml +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/src/lib.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/src/raw/error.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/src/raw/halo_hpl.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/crates/doprs/src/raw.rs +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/pyproject.toml +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/__init__.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/__main__.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/bench.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/data/__init__.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/data/api.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/data/cache.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/data/exceptions.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/defaults.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/exceptions.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/netcdf.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/options.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/py.typed +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/raw/__init__.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/raw/halo_bg.py +0 -0
- {doppy-0.2.0 → doppy-0.2.2}/src/doppy/raw/halo_sys_params.py +0 -0
|
@@ -106,7 +106,7 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
|
|
106
106
|
|
|
107
107
|
[[package]]
|
|
108
108
|
name = "doppy_rs"
|
|
109
|
-
version = "0.2.
|
|
109
|
+
version = "0.2.2"
|
|
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.2.
|
|
118
|
+
version = "0.2.2"
|
|
119
119
|
dependencies = [
|
|
120
120
|
"chrono",
|
|
121
121
|
"rayon",
|
|
@@ -68,6 +68,7 @@ pub fn from_filename_src(py: Python, filename: String) -> PyResult<PyReturnType>
|
|
|
68
68
|
fn convert_to_python(py: Python, raw: doprs::raw::wls70::Wls70) -> PyResult<PyReturnType> {
|
|
69
69
|
let info_dict = PyDict::new(py);
|
|
70
70
|
info_dict.set_item("altitude", raw.info.altitude.as_slice().to_pyarray(py))?;
|
|
71
|
+
info_dict.set_item("system_id", raw.info.system_id)?;
|
|
71
72
|
Ok((
|
|
72
73
|
info_dict,
|
|
73
74
|
PyList::new(py, raw.data_columns),
|
|
@@ -16,6 +16,7 @@ pub struct Wls70 {
|
|
|
16
16
|
#[derive(Debug, Default, Clone)]
|
|
17
17
|
pub struct Info {
|
|
18
18
|
pub altitude: Vec<f64>,
|
|
19
|
+
pub system_id: String,
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
pub fn from_file_src(mut file: &File) -> Result<Wls70, RawParseError> {
|
|
@@ -132,6 +133,14 @@ fn parse_info(info_str: &[u8]) -> Result<Info, RawParseError> {
|
|
|
132
133
|
})
|
|
133
134
|
.collect::<Result<Vec<f64>, _>>()?;
|
|
134
135
|
}
|
|
136
|
+
b if b.starts_with(b"ID System=") => {
|
|
137
|
+
info.system_id = std::str::from_utf8(&line[10..])
|
|
138
|
+
.map(|s| s.trim())
|
|
139
|
+
.map_err(|_| RawParseError {
|
|
140
|
+
message: "UTF-8 conversion error".into(),
|
|
141
|
+
})?
|
|
142
|
+
.to_string();
|
|
143
|
+
}
|
|
135
144
|
_ => (),
|
|
136
145
|
}
|
|
137
146
|
}
|
|
@@ -27,6 +27,7 @@ class Stare:
|
|
|
27
27
|
radial_velocity: npt.NDArray[np.float64]
|
|
28
28
|
mask: npt.NDArray[np.bool_]
|
|
29
29
|
wavelength: float
|
|
30
|
+
system_id: str
|
|
30
31
|
|
|
31
32
|
@classmethod
|
|
32
33
|
def from_halo_data(
|
|
@@ -89,6 +90,7 @@ class Stare:
|
|
|
89
90
|
radial_velocity=raw.radial_velocity,
|
|
90
91
|
mask=mask,
|
|
91
92
|
wavelength=wavelength,
|
|
93
|
+
system_id=raw.header.system_id,
|
|
92
94
|
)
|
|
93
95
|
|
|
94
96
|
|
|
@@ -18,6 +18,11 @@ import doppy
|
|
|
18
18
|
SelectionGroupKeyType: TypeAlias = tuple[int, int, tuple[int, ...]]
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
@dataclass
|
|
22
|
+
class Options:
|
|
23
|
+
azimuth_offset_deg: float | None
|
|
24
|
+
|
|
25
|
+
|
|
21
26
|
@dataclass
|
|
22
27
|
class Wind:
|
|
23
28
|
time: npt.NDArray[np.datetime64]
|
|
@@ -26,6 +31,7 @@ class Wind:
|
|
|
26
31
|
meridional_wind: npt.NDArray[np.float64]
|
|
27
32
|
vertical_wind: npt.NDArray[np.float64]
|
|
28
33
|
mask: npt.NDArray[np.bool_]
|
|
34
|
+
system_id: str
|
|
29
35
|
|
|
30
36
|
@functools.cached_property
|
|
31
37
|
def horizontal_wind_speed(self) -> npt.NDArray[np.float64]:
|
|
@@ -44,6 +50,7 @@ class Wind:
|
|
|
44
50
|
| Sequence[Path]
|
|
45
51
|
| Sequence[bytes]
|
|
46
52
|
| Sequence[BufferedIOBase],
|
|
53
|
+
options: Options | None = None,
|
|
47
54
|
) -> Wind:
|
|
48
55
|
raws = doppy.raw.HaloHpl.from_srcs(data)
|
|
49
56
|
|
|
@@ -59,6 +66,9 @@ class Wind:
|
|
|
59
66
|
if len(raw.time) == 0:
|
|
60
67
|
raise doppy.exceptions.NoDataError("No suitable data for the wind product")
|
|
61
68
|
|
|
69
|
+
if options and options.azimuth_offset_deg:
|
|
70
|
+
raw.azimuth += options.azimuth_offset_deg
|
|
71
|
+
|
|
62
72
|
groups = _group_scans_by_azimuth_rotation(raw)
|
|
63
73
|
time_list = []
|
|
64
74
|
elevation_list = []
|
|
@@ -93,6 +103,7 @@ class Wind:
|
|
|
93
103
|
meridional_wind=wind[:, :, 1],
|
|
94
104
|
vertical_wind=wind[:, :, 2],
|
|
95
105
|
mask=mask,
|
|
106
|
+
system_id=raw.header.system_id,
|
|
96
107
|
)
|
|
97
108
|
|
|
98
109
|
@classmethod
|
|
@@ -102,6 +113,7 @@ class Wind:
|
|
|
102
113
|
| Sequence[Path]
|
|
103
114
|
| Sequence[bytes]
|
|
104
115
|
| Sequence[BufferedIOBase],
|
|
116
|
+
options: Options | None = None,
|
|
105
117
|
) -> Wind:
|
|
106
118
|
raws = doppy.raw.WindCube.from_vad_srcs(data)
|
|
107
119
|
|
|
@@ -117,6 +129,9 @@ class Wind:
|
|
|
117
129
|
if len(raw.time) == 0:
|
|
118
130
|
raise doppy.exceptions.NoDataError("No suitable data for the wind product")
|
|
119
131
|
|
|
132
|
+
if options and options.azimuth_offset_deg:
|
|
133
|
+
raw.azimuth += options.azimuth_offset_deg
|
|
134
|
+
|
|
120
135
|
time_list = []
|
|
121
136
|
elevation_list = []
|
|
122
137
|
wind_list = []
|
|
@@ -147,6 +162,7 @@ class Wind:
|
|
|
147
162
|
meridional_wind=wind[:, :, 1],
|
|
148
163
|
vertical_wind=wind[:, :, 2],
|
|
149
164
|
mask=mask,
|
|
165
|
+
system_id=raw.system_id,
|
|
150
166
|
)
|
|
151
167
|
|
|
152
168
|
@classmethod
|
|
@@ -156,6 +172,7 @@ class Wind:
|
|
|
156
172
|
| Sequence[Path]
|
|
157
173
|
| Sequence[bytes]
|
|
158
174
|
| Sequence[BufferedIOBase],
|
|
175
|
+
options: Options | None = None,
|
|
159
176
|
) -> Wind:
|
|
160
177
|
raws = doppy.raw.Wls70.from_srcs(data)
|
|
161
178
|
|
|
@@ -167,6 +184,20 @@ class Wind:
|
|
|
167
184
|
.sorted_by_time()
|
|
168
185
|
.non_strictly_increasing_timesteps_removed()
|
|
169
186
|
)
|
|
187
|
+
|
|
188
|
+
if options and options.azimuth_offset_deg:
|
|
189
|
+
theta = np.deg2rad(options.azimuth_offset_deg)
|
|
190
|
+
cos_theta = np.cos(theta)
|
|
191
|
+
sin_theta = np.sin(theta)
|
|
192
|
+
|
|
193
|
+
meridional_wind = (
|
|
194
|
+
sin_theta * raw.zonal_wind + cos_theta * raw.meridional_wind
|
|
195
|
+
)
|
|
196
|
+
zonal_wind = cos_theta * raw.zonal_wind - sin_theta * raw.meridional_wind
|
|
197
|
+
else:
|
|
198
|
+
meridional_wind = raw.meridional_wind
|
|
199
|
+
zonal_wind = raw.zonal_wind
|
|
200
|
+
|
|
170
201
|
mask = (
|
|
171
202
|
np.isnan(raw.meridional_wind)
|
|
172
203
|
| np.isnan(raw.zonal_wind)
|
|
@@ -175,10 +206,11 @@ class Wind:
|
|
|
175
206
|
return Wind(
|
|
176
207
|
time=raw.time,
|
|
177
208
|
height=raw.altitude,
|
|
178
|
-
zonal_wind=
|
|
179
|
-
meridional_wind=
|
|
209
|
+
zonal_wind=zonal_wind,
|
|
210
|
+
meridional_wind=meridional_wind,
|
|
180
211
|
vertical_wind=raw.vertical_wind,
|
|
181
212
|
mask=mask,
|
|
213
|
+
system_id=raw.system_id,
|
|
182
214
|
)
|
|
183
215
|
|
|
184
216
|
|
|
@@ -8,7 +8,7 @@ from datetime import datetime, timedelta
|
|
|
8
8
|
from io import BufferedIOBase
|
|
9
9
|
from os.path import commonprefix
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Any, Sequence,
|
|
11
|
+
from typing import Any, Sequence, cast
|
|
12
12
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
import numpy.typing as npt
|
|
@@ -16,8 +16,7 @@ from numpy import datetime64, timedelta64
|
|
|
16
16
|
|
|
17
17
|
import doppy
|
|
18
18
|
from doppy import exceptions
|
|
19
|
-
|
|
20
|
-
T = TypeVar("T")
|
|
19
|
+
from doppy.utils import merge_all_equal
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
@dataclass
|
|
@@ -258,18 +257,12 @@ class HaloHplHeader:
|
|
|
258
257
|
)
|
|
259
258
|
|
|
260
259
|
|
|
261
|
-
def _merger(key: str, lst: list[T]) -> T:
|
|
262
|
-
if len(set(lst)) != 1:
|
|
263
|
-
raise ValueError(f"Cannot merge header key {key} values {lst}")
|
|
264
|
-
return lst[0]
|
|
265
|
-
|
|
266
|
-
|
|
267
260
|
def _merge_headers(headers: list[HaloHplHeader]) -> HaloHplHeader:
|
|
268
261
|
return HaloHplHeader(
|
|
269
262
|
filename=commonprefix([h.filename for h in headers]),
|
|
270
263
|
start_time=np.min([h.start_time for h in headers]),
|
|
271
264
|
**{
|
|
272
|
-
key:
|
|
265
|
+
key: merge_all_equal(key, [getattr(h, key) for h in headers])
|
|
273
266
|
for key in (
|
|
274
267
|
"gate_points",
|
|
275
268
|
"nrays",
|
|
@@ -10,6 +10,8 @@ import numpy.typing as npt
|
|
|
10
10
|
from netCDF4 import Dataset, num2date
|
|
11
11
|
from numpy import datetime64
|
|
12
12
|
|
|
13
|
+
from doppy.utils import merge_all_equal
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
@dataclass
|
|
15
17
|
class WindCube:
|
|
@@ -22,6 +24,7 @@ class WindCube:
|
|
|
22
24
|
radial_velocity: npt.NDArray[np.float64] # dim: (time, radial_distance)
|
|
23
25
|
radial_velocity_confidence: npt.NDArray[np.float64] # dim: (time, radial_distance)
|
|
24
26
|
scan_index: npt.NDArray[np.int64]
|
|
27
|
+
system_id: str
|
|
25
28
|
|
|
26
29
|
@classmethod
|
|
27
30
|
def from_vad_srcs(
|
|
@@ -53,6 +56,7 @@ class WindCube:
|
|
|
53
56
|
[r.radial_velocity_confidence for r in raws]
|
|
54
57
|
),
|
|
55
58
|
cnr=np.concatenate([r.cnr for r in raws]),
|
|
59
|
+
system_id=merge_all_equal("system_id", [r.system_id for r in raws]),
|
|
56
60
|
)
|
|
57
61
|
|
|
58
62
|
def __getitem__(
|
|
@@ -75,6 +79,7 @@ class WindCube:
|
|
|
75
79
|
radial_velocity_confidence=self.radial_velocity_confidence[index],
|
|
76
80
|
cnr=self.cnr[index],
|
|
77
81
|
scan_index=self.scan_index[index],
|
|
82
|
+
system_id=self.system_id,
|
|
78
83
|
)
|
|
79
84
|
raise TypeError
|
|
80
85
|
|
|
@@ -189,6 +194,7 @@ def _from_vad_src(nc: Dataset) -> WindCube:
|
|
|
189
194
|
radial_velocity=np.concatenate(radial_wind_speed_list),
|
|
190
195
|
radial_velocity_confidence=np.concatenate(radial_wind_speed_confidence_list),
|
|
191
196
|
cnr=np.concatenate(cnr_list),
|
|
197
|
+
system_id=nc.instrument_name,
|
|
192
198
|
)
|
|
193
199
|
|
|
194
200
|
|
|
@@ -4,7 +4,7 @@ from dataclasses import dataclass
|
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from io import BufferedIOBase
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Sequence
|
|
7
|
+
from typing import Any, Sequence
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
import numpy.typing as npt
|
|
@@ -12,6 +12,7 @@ from numpy import datetime64
|
|
|
12
12
|
|
|
13
13
|
import doppy
|
|
14
14
|
from doppy import exceptions
|
|
15
|
+
from doppy.utils import merge_all_equal
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
@dataclass
|
|
@@ -31,6 +32,7 @@ class Wls70:
|
|
|
31
32
|
np.float64
|
|
32
33
|
] # v := meridional wind?, dim: (time, altitude)
|
|
33
34
|
vertical_wind: npt.NDArray[np.float64] # w := vertical wind?, dim: (time, altitude)
|
|
35
|
+
system_id: str
|
|
34
36
|
|
|
35
37
|
@classmethod
|
|
36
38
|
def from_srcs(
|
|
@@ -108,6 +110,7 @@ class Wls70:
|
|
|
108
110
|
zonal_wind=self.zonal_wind[index],
|
|
109
111
|
meridional_wind=self.meridional_wind[index],
|
|
110
112
|
vertical_wind=self.vertical_wind[index],
|
|
113
|
+
system_id=self.system_id,
|
|
111
114
|
)
|
|
112
115
|
raise TypeError
|
|
113
116
|
|
|
@@ -133,6 +136,7 @@ class Wls70:
|
|
|
133
136
|
zonal_wind=np.concatenate(tuple(r.zonal_wind for r in raws)),
|
|
134
137
|
meridional_wind=np.concatenate(tuple(r.meridional_wind for r in raws)),
|
|
135
138
|
vertical_wind=np.concatenate(tuple(r.vertical_wind for r in raws)),
|
|
139
|
+
system_id=merge_all_equal("system_id", [r.system_id for r in raws]),
|
|
136
140
|
)
|
|
137
141
|
|
|
138
142
|
def non_strictly_increasing_timesteps_removed(self) -> Wls70:
|
|
@@ -149,12 +153,11 @@ class Wls70:
|
|
|
149
153
|
|
|
150
154
|
|
|
151
155
|
def _raw_rs_to_wls70(
|
|
152
|
-
raw_rs: tuple[
|
|
153
|
-
dict[str, npt.NDArray[np.float64]], list[str], npt.NDArray[np.float64]
|
|
154
|
-
],
|
|
156
|
+
raw_rs: tuple[dict[str, Any], list[str], npt.NDArray[np.float64]],
|
|
155
157
|
) -> Wls70:
|
|
156
158
|
info, cols, data = raw_rs
|
|
157
159
|
altitude = info["altitude"]
|
|
160
|
+
system_id = info["system_id"]
|
|
158
161
|
data = data.reshape(-1, len(cols))
|
|
159
162
|
time_ts = data[:, 0]
|
|
160
163
|
time = np.array([datetime64(datetime.utcfromtimestamp(ts)) for ts in time_ts])
|
|
@@ -185,4 +188,5 @@ def _raw_rs_to_wls70(
|
|
|
185
188
|
zonal_wind=u,
|
|
186
189
|
meridional_wind=v,
|
|
187
190
|
vertical_wind=w,
|
|
191
|
+
system_id=system_id,
|
|
188
192
|
)
|
|
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
|