flightdata 0.3.2__tar.gz → 0.3.4__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.
- {flightdata-0.3.2 → flightdata-0.3.4}/PKG-INFO +3 -3
- {flightdata-0.3.2 → flightdata-0.3.4}/pyproject.toml +3 -3
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/collection.py +31 -4
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/labelgroup.py +39 -18
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/flight/flight.py +16 -11
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/flight/parameters.py +1 -1
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/state/state.py +3 -2
- {flightdata-0.3.2 → flightdata-0.3.4}/test/base/test_labels.py +32 -5
- flightdata-0.3.2/src/flightdata/base/labeling.py +0 -9
- {flightdata-0.3.2 → flightdata-0.3.4}/.github/workflows/publish_pypi.yml +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/.gitignore +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/.vscode/launch.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/.vscode/settings.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/LICENSE +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/README.md +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/data/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/data/manual_F3A_F23_22_04_28_00000231.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/data/manual_F3A_P23_22_05_31_00000350.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/data/manual_F3A_P23_23_08_11_00000094.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/flight_dynamics/00000150.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/flight_dynamics/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/flight_dynamics/box.f3a +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/flight_dynamics/param_id.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/interpolation/slice_linear_interpolation.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/interpolation/st.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/interpolation/temp.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/state_analysis/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/state_analysis/axes.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/examples/state_analysis/state_fill_plot.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/numpy_encoder.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/constructs.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/label.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/labelgroups.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/slicer.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/base/table/table.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/bindata.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/coefficients.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/environment/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/environment/environment.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/environment/wind.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/flight/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/flight/ardupilot.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/flight/fields.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/flow.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/model/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/model/aerodynamic.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/model/thrust.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/origin.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/py.typed +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/scripts/collect_logs.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/scripts/flightline.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/state/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/state/alignment.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/state/kinematics.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/src/flightdata/state_maker.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/EmailedBox.f3a +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/base/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/base/test_base_constructs.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/base/test_table.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/conftest.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/bin_parser_GPS.csv +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/bin_parser_POS.csv +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/make_inputs.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/manual_F3A_P23.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/old_state.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/p23.BIN +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/p23.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/p23_box.f3a +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/p23_fc.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/p23_flight.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/script_tests/c6_on_0001.BIN +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/script_tests/center_0003.bin +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/script_tests/pilot_0004.BIN +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/vtol_hover.bin +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/vtol_hover.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/data/web_bin_parse.json +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_bindata.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_dtw.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_environment/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_environment/test_environment.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_environment/test_environment_wind.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_fields.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_flight.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_model/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_model/test_model_coefficients.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_model/test_model_flow.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_origin.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_scripts.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_state/__init__.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_state/test_state.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_state/test_state_builders.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_state/test_state_conversions.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/test/test_state/test_state_measurements.py +0 -0
- {flightdata-0.3.2 → flightdata-0.3.4}/uv.lock +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flightdata
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Python tools for handling flight data
|
|
5
5
|
Author-email: Thomas David <thomasdavid0@gmail.com>
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.12
|
|
8
8
|
Requires-Dist: numpy>=2.1.3
|
|
9
9
|
Requires-Dist: pandas>=2.2.3
|
|
10
|
-
Requires-Dist: pfc-geometry>=0.2.
|
|
11
|
-
Requires-Dist: pfcschemas>=0.1.
|
|
10
|
+
Requires-Dist: pfc-geometry>=0.2.19
|
|
11
|
+
Requires-Dist: pfcschemas>=0.1.12
|
|
12
12
|
Requires-Dist: simplejson>=3.20.1
|
|
13
13
|
Provides-Extra: dataflash
|
|
14
14
|
Requires-Dist: ardupilot-log-reader; extra == 'dataflash'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flightdata"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.4"
|
|
4
4
|
description = "Python tools for handling flight data"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "Thomas David", email = "thomasdavid0@gmail.com" }]
|
|
@@ -8,8 +8,8 @@ requires-python = ">=3.12"
|
|
|
8
8
|
dependencies = [
|
|
9
9
|
"numpy>=2.1.3",
|
|
10
10
|
"pandas>=2.2.3",
|
|
11
|
-
"pfc-geometry>=0.2.
|
|
12
|
-
"pfcschemas>=0.1.
|
|
11
|
+
"pfc-geometry>=0.2.19",
|
|
12
|
+
"pfcschemas>=0.1.12",
|
|
13
13
|
"simplejson>=3.20.1",
|
|
14
14
|
]
|
|
15
15
|
|
|
@@ -70,6 +70,11 @@ class Collection:
|
|
|
70
70
|
|
|
71
71
|
def filter_items(self, fun: Callable[[str, T], bool]):
|
|
72
72
|
return self.__class__({k: v for k, v in self.items() if fun(k, v)})
|
|
73
|
+
|
|
74
|
+
def index(self, key: str) -> int:
|
|
75
|
+
if key in self.data:
|
|
76
|
+
return list(self.data.keys()).index(key)
|
|
77
|
+
raise KeyError(f"{key} not found in {self.__class__}")
|
|
73
78
|
|
|
74
79
|
def to_list(self) -> list[T]:
|
|
75
80
|
return list(self.values())
|
|
@@ -93,17 +98,18 @@ class Collection:
|
|
|
93
98
|
if isinstance(v, self.VType):
|
|
94
99
|
odata[getattr(v, self.uid)] = v
|
|
95
100
|
elif isinstance(v, self.__class__):
|
|
96
|
-
odata = dict(**odata, **v.data)
|
|
101
|
+
odata = odata | v.data #dict(**odata, **v.data)
|
|
97
102
|
elif isinstance(v, list):
|
|
98
|
-
odata =
|
|
103
|
+
odata = odata | {getattr(d, self.uid): d for d in v}
|
|
99
104
|
if inplace:
|
|
100
105
|
self.data = odata
|
|
101
106
|
return v
|
|
102
107
|
else:
|
|
103
108
|
return self.__class__(odata)
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
@classmethod
|
|
111
|
+
def concat(Cls, vs: list) -> Self:
|
|
112
|
+
coll = Cls([])
|
|
107
113
|
for v in vs:
|
|
108
114
|
coll.add(v)
|
|
109
115
|
return coll
|
|
@@ -144,6 +150,27 @@ class Collection:
|
|
|
144
150
|
def __len__(self) -> int:
|
|
145
151
|
return len(self.data)
|
|
146
152
|
|
|
153
|
+
def remove(self, key_or_id: str | int) -> Self:
|
|
154
|
+
if isinstance(key_or_id, int):
|
|
155
|
+
key_or_id = list(self.data.keys())[key_or_id]
|
|
156
|
+
return self.__class__({k: v for k, v in self.data.items() if k != key_or_id})
|
|
157
|
+
|
|
158
|
+
def replace(self, key_or_id: str | int, v: T, inplace=False) -> Self:
|
|
159
|
+
if isinstance(key_or_id, int):
|
|
160
|
+
key_or_id = list(self.data.keys())[key_or_id]
|
|
161
|
+
if not hasattr(v, self.uid):
|
|
162
|
+
raise ValueError(f"Value {v} does not have a {self.uid} attribute")
|
|
163
|
+
if not inplace:
|
|
164
|
+
new_data = self.data.copy()
|
|
165
|
+
new_data[key_or_id] = v
|
|
166
|
+
return self.__class__(new_data)
|
|
167
|
+
else:
|
|
168
|
+
if key_or_id in self.data:
|
|
169
|
+
self.data[key_or_id] = v
|
|
170
|
+
else:
|
|
171
|
+
raise KeyError(f"{key_or_id} not found in {self.__class__}")
|
|
172
|
+
return self
|
|
173
|
+
|
|
147
174
|
@property
|
|
148
175
|
def uids(self) -> list[str]:
|
|
149
176
|
return list(self.data.keys())
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
import enum
|
|
2
3
|
import numpy as np
|
|
3
4
|
import pandas as pd
|
|
4
5
|
import numpy.typing as npt
|
|
@@ -73,6 +74,20 @@ class LabelGroup:
|
|
|
73
74
|
if len(labels) == len(t):
|
|
74
75
|
labels= labels[:-1]
|
|
75
76
|
assert len(labels) == len(t) - 1
|
|
77
|
+
labels=labels.astype(object)
|
|
78
|
+
change_ids = np.where(labels[:-1] != labels[1:])[0] + 1
|
|
79
|
+
|
|
80
|
+
newlabnames = [labels[0]]
|
|
81
|
+
for i, oldlabname in enumerate(labels[change_ids]):
|
|
82
|
+
newlabname = oldlabname
|
|
83
|
+
suffix=1
|
|
84
|
+
while newlabname in newlabnames:
|
|
85
|
+
newlabname = f"{oldlabname}_{suffix}"
|
|
86
|
+
suffix+=1
|
|
87
|
+
newlabnames.append(newlabname)
|
|
88
|
+
if not newlabname == oldlabname:
|
|
89
|
+
labels[change_ids[i]:change_ids[i+1] if i+1<len(change_ids) else None] = newlabname
|
|
90
|
+
|
|
76
91
|
labnames = pd.unique(labels)
|
|
77
92
|
data = {}
|
|
78
93
|
for i, label_name in enumerate(labnames):
|
|
@@ -173,7 +188,7 @@ class LabelGroup:
|
|
|
173
188
|
)
|
|
174
189
|
|
|
175
190
|
#st: Self = flown.__class__(flown.data).label(**mans.to_dict(orient="list"))
|
|
176
|
-
return LabelGroup.read_array(b, mans.a)
|
|
191
|
+
return LabelGroup.read_array(b, mans.a.values)
|
|
177
192
|
# return self.update(lambda v: v.transfer(a, b, path))
|
|
178
193
|
@property
|
|
179
194
|
def widths(self):
|
|
@@ -181,7 +196,7 @@ class LabelGroup:
|
|
|
181
196
|
|
|
182
197
|
@property
|
|
183
198
|
def boundaries(self) -> list[float]:
|
|
184
|
-
return [v.stop for v in self.values()]
|
|
199
|
+
return np.array([v.stop for v in self.values()])
|
|
185
200
|
|
|
186
201
|
@property
|
|
187
202
|
def boundary_dict(self) -> dict[str, float]:
|
|
@@ -220,13 +235,13 @@ class LabelGroup:
|
|
|
220
235
|
def step_boundary(self, key: str | int, steps: int, t: npt.NDArray, min_len: int):
|
|
221
236
|
"""Step the stop time of a label, and the start of the next label by steps timesteps"""
|
|
222
237
|
ilg = self.to_iloc(t)
|
|
223
|
-
iboundaries = [0]
|
|
238
|
+
iboundaries = np.concatenate([np.array([0]), ilg.boundaries])
|
|
224
239
|
lengths = [b1-b0 for b0, b1 in zip(iboundaries[:-1], iboundaries[1:])]
|
|
225
240
|
index = list(self.keys()).index(key) if isinstance(key, str) else key
|
|
226
241
|
# new_iloc = np.where(t==self[index].stop)[0][0] + steps
|
|
227
242
|
|
|
228
243
|
|
|
229
|
-
if lengths[index]
|
|
244
|
+
if lengths[index] + steps + 1 >= min_len and lengths[index+1] - steps + 1>= min_len :
|
|
230
245
|
|
|
231
246
|
ilg[index].stop = ilg[index].stop + steps
|
|
232
247
|
if index < len(ilg) - 1:
|
|
@@ -275,7 +290,10 @@ class LabelGroup:
|
|
|
275
290
|
"""
|
|
276
291
|
|
|
277
292
|
if len(names) > 1:
|
|
278
|
-
|
|
293
|
+
new = self.copy()
|
|
294
|
+
for i, name in enumerate(names):
|
|
295
|
+
new = new.insert(loc+i, [name])
|
|
296
|
+
return new
|
|
279
297
|
|
|
280
298
|
new_labels = {}
|
|
281
299
|
for i, (k, v) in enumerate(self.items()):
|
|
@@ -297,7 +315,7 @@ class LabelGroup:
|
|
|
297
315
|
inserts = []
|
|
298
316
|
new_labs = {}
|
|
299
317
|
while ii < len(keys):
|
|
300
|
-
if labs[il] == keys[ii]:
|
|
318
|
+
if il<len(labs) and labs[il] == keys[ii]:
|
|
301
319
|
if len(inserts):
|
|
302
320
|
new_labs[il] = inserts
|
|
303
321
|
inserts = []
|
|
@@ -306,6 +324,9 @@ class LabelGroup:
|
|
|
306
324
|
else:
|
|
307
325
|
inserts.append(keys[ii])
|
|
308
326
|
ii += 1
|
|
327
|
+
else:
|
|
328
|
+
if len(inserts):
|
|
329
|
+
new_labs[il] = inserts
|
|
309
330
|
for loc in list(new_labs.keys())[::-1]:
|
|
310
331
|
self=self.insert(loc, new_labs[loc])
|
|
311
332
|
return self
|
|
@@ -324,24 +345,24 @@ class LabelGroup:
|
|
|
324
345
|
elif index == len(self) - 1:
|
|
325
346
|
side = "start"
|
|
326
347
|
else:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
348
|
+
next_space_stop = np.argwhere(np.array(widths[index+1:]) > min_len)
|
|
349
|
+
next_space_stop = next_space_stop[0][0] if len(next_space_stop) and len(next_space_stop[0]) else None
|
|
350
|
+
next_space_start = np.argwhere(np.array(widths[:index][::-1]) > min_len)
|
|
351
|
+
next_space_start = next_space_start[0][0] if len(next_space_start) and len(next_space_start[0]) else None
|
|
331
352
|
|
|
332
|
-
if
|
|
353
|
+
if next_space_stop is None and next_space_start is None:
|
|
333
354
|
raise ValueError(f"Cannot expand label {name}")
|
|
334
|
-
elif
|
|
355
|
+
elif next_space_stop is None:
|
|
335
356
|
side = "start"
|
|
336
|
-
elif
|
|
357
|
+
elif next_space_start is None:
|
|
337
358
|
side= "stop"
|
|
338
|
-
elif
|
|
339
|
-
side = "stop"
|
|
340
|
-
elif next_space_bck < next_space_fwd:
|
|
359
|
+
elif next_space_stop > 0 and next_space_start == 0:
|
|
341
360
|
side = "start"
|
|
361
|
+
elif next_space_start > 0 and next_space_stop == 0:
|
|
362
|
+
side = "stop"
|
|
342
363
|
else:
|
|
343
|
-
#either
|
|
344
|
-
side = "stop" if widths[:index][::-1][
|
|
364
|
+
#either next_space_stop == next_space_start
|
|
365
|
+
side = "stop" if widths[:index][::-1][next_space_start] < widths[index+1:][next_space_stop] else "start"
|
|
345
366
|
|
|
346
367
|
if side=="start":
|
|
347
368
|
boundaries[index-1] -= 1
|
|
@@ -11,20 +11,25 @@ this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from json import dump, load
|
|
17
|
+
from numbers import Number
|
|
14
18
|
from typing import Self, Union
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
15
21
|
import numpy as np
|
|
16
22
|
import pandas as pd
|
|
17
|
-
from
|
|
18
|
-
from geometry import GPS, Point, P0
|
|
23
|
+
from geometry import GPS, P0, Point
|
|
19
24
|
from geometry.checks import assert_almost_equal
|
|
20
|
-
from
|
|
25
|
+
from schemas import fcj
|
|
26
|
+
from scipy.signal import butter, filtfilt
|
|
27
|
+
|
|
28
|
+
from flightdata import Origin
|
|
21
29
|
from flightdata.base.numpy_encoder import NumpyEncoder
|
|
30
|
+
|
|
22
31
|
from .ardupilot import flightmodes
|
|
23
|
-
from
|
|
24
|
-
from schemas import fcj
|
|
25
|
-
from numbers import Number
|
|
26
|
-
from scipy.signal import filtfilt, butter
|
|
27
|
-
from datetime import datetime
|
|
32
|
+
from .fields import Field, fields
|
|
28
33
|
|
|
29
34
|
|
|
30
35
|
def filter(data, cutoff=25, order=5, fs=25):
|
|
@@ -311,13 +316,13 @@ class Flight:
|
|
|
311
316
|
return False
|
|
312
317
|
|
|
313
318
|
def boot_time(self):
|
|
314
|
-
timestamp = self.time_actual.iloc[0]
|
|
319
|
+
timestamp = self.time_actual.iloc[0]
|
|
315
320
|
return datetime.fromtimestamp(timestamp) if not np.isnan(timestamp) else None
|
|
316
321
|
|
|
317
322
|
@staticmethod
|
|
318
323
|
def from_log(
|
|
319
|
-
log: str,
|
|
320
|
-
extra_types: list[str] = None,
|
|
324
|
+
log: str | Path,
|
|
325
|
+
extra_types: list[str] | None = None,
|
|
321
326
|
ppsource: str = "pos",
|
|
322
327
|
imu_instance=0,
|
|
323
328
|
**kwargs,
|
|
@@ -167,10 +167,10 @@ class State(Table):
|
|
|
167
167
|
|
|
168
168
|
return plotsec(self, **(dict(nmodels=10, ribb=True) | kwargs))
|
|
169
169
|
|
|
170
|
-
def plotlabels(self, label: str):
|
|
170
|
+
def plotlabels(self, label: str, **kwargs):
|
|
171
171
|
from plotting import plot_regions
|
|
172
172
|
|
|
173
|
-
return plot_regions(self, label)
|
|
173
|
+
return plot_regions(self, label, **kwargs)
|
|
174
174
|
|
|
175
175
|
def extrapolate(self, duration: float, min_len=3) -> State:
|
|
176
176
|
"""Extrapolate the input state assuming uniform circular motion and small angles"""
|
|
@@ -586,6 +586,7 @@ class State(Table):
|
|
|
586
586
|
)
|
|
587
587
|
|
|
588
588
|
def move(self: State, transform: g.Transformation) -> State:
|
|
589
|
+
"""Move the state by a transformation"""
|
|
589
590
|
return State.from_constructs(
|
|
590
591
|
time=self.time,
|
|
591
592
|
pos=transform.point(self.pos),
|
|
@@ -45,6 +45,12 @@ def test_labelgroup_read_array(tab_full, label_array):
|
|
|
45
45
|
assert lg.a2.stop == tab_full.data.index[-1]
|
|
46
46
|
|
|
47
47
|
|
|
48
|
+
def test_labelgroup_read_array_repeats(tab_full):
|
|
49
|
+
label_array = np.array(["a0", "a0", "a1", "a1", "a0", "a0"])
|
|
50
|
+
lg = LabelGroup.read_array(tab_full.t, label_array)
|
|
51
|
+
assert len(lg) == 3
|
|
52
|
+
|
|
53
|
+
|
|
48
54
|
def test_label_array(tab_lab):
|
|
49
55
|
assert len(tab_lab.labels) == 1
|
|
50
56
|
assert isinstance(tab_lab.labels.a, LabelGroup)
|
|
@@ -181,26 +187,47 @@ def test_from_boundaries():
|
|
|
181
187
|
lg = LabelGroup.from_boundaries(0, dict(a=2, b=5))
|
|
182
188
|
assert lg.a.start == 0
|
|
183
189
|
assert lg.a.stop == 2
|
|
184
|
-
assert lg.b.start==2
|
|
190
|
+
assert lg.b.start == 2
|
|
185
191
|
assert lg.b.stop == 5
|
|
186
192
|
assert lg.is_tesselated(np.arange(5))
|
|
187
193
|
|
|
194
|
+
|
|
188
195
|
def test_expand_one():
|
|
189
196
|
lg = LabelGroup.from_boundaries(0, dict(a=2, b=2, c=6))
|
|
190
|
-
lg = lg.expand_one(
|
|
191
|
-
np.testing.assert_array_equal(lg.boundaries, [2,3,6])
|
|
197
|
+
lg = lg.expand_one("b", 1)
|
|
198
|
+
np.testing.assert_array_equal(lg.boundaries, [2, 3, 6])
|
|
199
|
+
|
|
192
200
|
|
|
193
201
|
def test_expand():
|
|
194
202
|
lg = LabelGroup.from_boundaries(0, dict(a=2, b=2, c=6))
|
|
195
203
|
lg = lg.expand(2)
|
|
196
204
|
np.testing.assert_array_equal(lg.boundaries, [2, 4, 6])
|
|
197
205
|
|
|
206
|
+
|
|
198
207
|
def test_expand_difficult():
|
|
199
208
|
lg = LabelGroup.from_boundaries(0, dict(a=0, b=1, c=7))
|
|
200
|
-
|
|
209
|
+
|
|
201
210
|
np.testing.assert_array_equal(lg.expand(1).boundaries, [1, 2, 7])
|
|
202
211
|
np.testing.assert_array_equal(lg.expand(2).boundaries, [2, 4, 7])
|
|
203
212
|
|
|
213
|
+
|
|
204
214
|
def test_expand_infinite_loop():
|
|
205
215
|
lg = LabelGroup.from_boundaries(0, dict(a=1, b=5, c=6, d=8))
|
|
206
|
-
np.testing.assert_array_equal(lg.expand(2).boundaries, [2, 4, 6, 8])
|
|
216
|
+
np.testing.assert_array_equal(lg.expand(2).boundaries, [2, 4, 6, 8])
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def test_labelgroup_insert_list(tab_lab: Table):
|
|
220
|
+
np.testing.assert_array_equal(
|
|
221
|
+
list(tab_lab.labels.a.insert_list(["a0", "a1", "new", "a2"]).keys()),
|
|
222
|
+
["a0", "a1", "new", "a2"],
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
np.testing.assert_array_equal(
|
|
226
|
+
list(tab_lab.labels.a.insert_list(["a0", "a1", "a2", "new"]).keys()),
|
|
227
|
+
["a0", "a1", "a2", "new"],
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
np.testing.assert_array_equal(
|
|
231
|
+
list(tab_lab.labels.a.insert_list(["a0", "a1", "a2", "new", "new2"]).keys()),
|
|
232
|
+
["a0", "a1", "a2", "new", "new2"],
|
|
233
|
+
)
|
|
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
|
|
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
|
|
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
|