flightdata 0.2.10__tar.gz → 0.2.12__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.
Files changed (84) hide show
  1. {flightdata-0.2.10 → flightdata-0.2.12}/.github/workflows/publish_pypi.yml +1 -1
  2. {flightdata-0.2.10/flightdata.egg-info → flightdata-0.2.12}/PKG-INFO +14 -1
  3. {flightdata-0.2.10 → flightdata-0.2.12}/README.md +13 -0
  4. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/base/table.py +37 -35
  5. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/flight/flight.py +13 -5
  6. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/scripts/collect_logs.py +4 -1
  7. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/scripts/flightline.py +4 -1
  8. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/state.py +1 -1
  9. {flightdata-0.2.10 → flightdata-0.2.12/flightdata.egg-info}/PKG-INFO +14 -1
  10. {flightdata-0.2.10 → flightdata-0.2.12}/test/base/test_table.py +16 -13
  11. {flightdata-0.2.10 → flightdata-0.2.12}/.gitignore +0 -0
  12. {flightdata-0.2.10 → flightdata-0.2.12}/.vscode/launch.json +0 -0
  13. {flightdata-0.2.10 → flightdata-0.2.12}/.vscode/settings.json +0 -0
  14. {flightdata-0.2.10 → flightdata-0.2.12}/LICENSE +0 -0
  15. {flightdata-0.2.10 → flightdata-0.2.12}/examples/__init__.py +0 -0
  16. {flightdata-0.2.10 → flightdata-0.2.12}/examples/axis_rates.ipynb +0 -0
  17. {flightdata-0.2.10 → flightdata-0.2.12}/examples/data/__init__.py +0 -0
  18. {flightdata-0.2.10 → flightdata-0.2.12}/examples/data/manual_F3A_F23_22_04_28_00000231.json +0 -0
  19. {flightdata-0.2.10 → flightdata-0.2.12}/examples/data/manual_F3A_P23_22_05_31_00000350.json +0 -0
  20. {flightdata-0.2.10 → flightdata-0.2.12}/examples/data/manual_F3A_P23_23_08_11_00000094.json +0 -0
  21. {flightdata-0.2.10 → flightdata-0.2.12}/examples/flight_data.py +0 -0
  22. {flightdata-0.2.10 → flightdata-0.2.12}/examples/flight_dynamics/00000150.json +0 -0
  23. {flightdata-0.2.10 → flightdata-0.2.12}/examples/flight_dynamics/__init__.py +0 -0
  24. {flightdata-0.2.10 → flightdata-0.2.12}/examples/flight_dynamics/box.f3a +0 -0
  25. {flightdata-0.2.10 → flightdata-0.2.12}/examples/flight_dynamics/param_id.py +0 -0
  26. {flightdata-0.2.10 → flightdata-0.2.12}/examples/state_analysis/__init__.py +0 -0
  27. {flightdata-0.2.10 → flightdata-0.2.12}/examples/state_analysis/axes.py +0 -0
  28. {flightdata-0.2.10 → flightdata-0.2.12}/examples/state_analysis/state_fill_plot.py +0 -0
  29. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/__init__.py +0 -0
  30. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/base/__init__.py +0 -0
  31. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/base/collection.py +0 -0
  32. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/base/constructs.py +0 -0
  33. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/base/labeling.py +0 -0
  34. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/base/numpy_encoder.py +0 -0
  35. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/coefficients.py +0 -0
  36. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/environment/__init__.py +0 -0
  37. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/environment/environment.py +0 -0
  38. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/environment/wind.py +0 -0
  39. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/flight/__init__.py +0 -0
  40. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/flight/ardupilot.py +0 -0
  41. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/flight/fields.py +0 -0
  42. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/flight/parameters.py +0 -0
  43. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/flow.py +0 -0
  44. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/model/__init__.py +0 -0
  45. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/model/aerodynamic.py +0 -0
  46. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/model/thrust.py +0 -0
  47. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata/origin.py +0 -0
  48. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata.egg-info/SOURCES.txt +0 -0
  49. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata.egg-info/dependency_links.txt +0 -0
  50. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata.egg-info/entry_points.txt +0 -0
  51. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata.egg-info/requires.txt +0 -0
  52. {flightdata-0.2.10 → flightdata-0.2.12}/flightdata.egg-info/top_level.txt +0 -0
  53. {flightdata-0.2.10 → flightdata-0.2.12}/pyproject.toml +0 -0
  54. {flightdata-0.2.10 → flightdata-0.2.12}/requirements-dev.txt +0 -0
  55. {flightdata-0.2.10 → flightdata-0.2.12}/requirements.txt +0 -0
  56. {flightdata-0.2.10 → flightdata-0.2.12}/setup.cfg +0 -0
  57. {flightdata-0.2.10 → flightdata-0.2.12}/test/EmailedBox.f3a +0 -0
  58. {flightdata-0.2.10 → flightdata-0.2.12}/test/__init__.py +0 -0
  59. {flightdata-0.2.10 → flightdata-0.2.12}/test/base/__init__.py +0 -0
  60. {flightdata-0.2.10 → flightdata-0.2.12}/test/base/test_base_constructs.py +0 -0
  61. {flightdata-0.2.10 → flightdata-0.2.12}/test/conftest.py +0 -0
  62. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/make_inputs.py +0 -0
  63. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/manual_F3A_P23.json +0 -0
  64. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/p23.BIN +0 -0
  65. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/p23.json +0 -0
  66. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/p23_box.f3a +0 -0
  67. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/p23_fc.json +0 -0
  68. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/p23_flight.json +0 -0
  69. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/vtol_hover.bin +0 -0
  70. {flightdata-0.2.10 → flightdata-0.2.12}/test/data/vtol_hover.json +0 -0
  71. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_environment/__init__.py +0 -0
  72. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_environment/test_environment.py +0 -0
  73. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_environment/test_environment_wind.py +0 -0
  74. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_fields.py +0 -0
  75. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_flight.py +0 -0
  76. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_model/__init__.py +0 -0
  77. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_model/test_model_coefficients.py +0 -0
  78. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_model/test_model_flow.py +0 -0
  79. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_origin.py +0 -0
  80. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_state/__init__.py +0 -0
  81. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_state/test_state.py +0 -0
  82. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_state/test_state_builders.py +0 -0
  83. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_state/test_state_conversions.py +0 -0
  84. {flightdata-0.2.10 → flightdata-0.2.12}/test/test_state/test_state_measurements.py +0 -0
@@ -4,7 +4,7 @@ name: Publish to PyPI and TestPyPI
4
4
  on:
5
5
  push:
6
6
  tags:
7
- - '**'
7
+ - 'v[0-9]+.[0-9]+.[0-9]+'
8
8
  jobs:
9
9
  build:
10
10
  name: Build distribution
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flightdata
3
- Version: 0.2.10
3
+ Version: 0.2.12
4
4
  Summary: Module for handling UAV flight log data
5
5
  Author-email: Thomas David <thomasdavid0@gmail.com>
6
6
  License: GNU GPL v3
@@ -34,3 +34,16 @@ The State object is a table representing the position and orientation of the air
34
34
 
35
35
 
36
36
  Further documentation will be provided here: https://pfcdocumentation.readthedocs.io/pyflightcoach/flightdata.html
37
+
38
+
39
+ ### Installation
40
+
41
+ ```bash
42
+ pip install pfc-geometry
43
+ ```
44
+
45
+ ### Setup from source
46
+
47
+ ```bash
48
+ pip install .
49
+ ```
@@ -12,3 +12,16 @@ The State object is a table representing the position and orientation of the air
12
12
 
13
13
 
14
14
  Further documentation will be provided here: https://pfcdocumentation.readthedocs.io/pyflightcoach/flightdata.html
15
+
16
+
17
+ ### Installation
18
+
19
+ ```bash
20
+ pip install pfc-geometry
21
+ ```
22
+
23
+ ### Setup from source
24
+
25
+ ```bash
26
+ pip install .
27
+ ```
@@ -21,7 +21,6 @@ class Table:
21
21
  self.label_cols = [c for c in data.columns if c not in self.constructs.cols()]
22
22
 
23
23
  self.data = data
24
- #self.data.index = self.data.index - self.data.index[0]
25
24
 
26
25
  if fill:
27
26
  missing = self.constructs.missing(self.data.columns)
@@ -81,40 +80,16 @@ class Table:
81
80
  else:
82
81
  raise TypeError(f"Expected Number or slice, got {sli.__class__.__name__}")
83
82
 
84
-
85
83
  def slice_raw_t(self, sli):
86
84
  inds = self.data.reset_index(names="t2").set_index("t").loc[sli].t2.to_numpy()#set_index("t", drop=False).columns
87
85
 
88
86
  return self.__class__(self.data.loc[inds])
89
87
 
90
- @classmethod
91
- def stack(Cls, sections: list, overlap: int=1) -> Self:
92
- """Stack a list of Tables on top of each other.
93
- The overlap is the number of rows to overlap between each section
94
- """
95
- # first build list of index offsets, to be added to each dataframe
96
- if overlap > 0:
97
- offsets = np.cumsum([0] + [sec.data.index[-overlap] for sec in sections[:-1]])
98
- dfs = [section.data.iloc[:-overlap] for section in sections[:-1]] + [sections[-1].data]
99
- elif overlap == 0:
100
- offsets = np.cumsum([0] + [sec.duration + sec.dt[-1] for sec in sections[:-1]])
101
- dfs = [section.data for section in sections]
102
- else:
103
- raise AttributeError("Overlap must be >= 0")
104
-
105
- for df, offset in zip(dfs, offsets):
106
- df.index = np.array(df.index) - df.index[0] + offset
107
- combo = pd.concat(dfs)
108
- combo.index.name = "t"
109
-
110
- combo["t"] = combo.index
111
-
112
- return Cls(combo)
113
-
114
88
  def __iter__(self):
115
89
  for ind in list(self.data.index):
116
90
  yield self[ind]
117
91
 
92
+
118
93
  @classmethod
119
94
  def from_constructs(cls, *args,**kwargs) -> Self:
120
95
  kwargs = dict(
@@ -133,7 +108,7 @@ class Table:
133
108
  )
134
109
 
135
110
  return cls(df)
136
-
111
+
137
112
  def __repr__(self):
138
113
  return f"{self.__class__.__name__} Table(duration = {self.duration})"
139
114
 
@@ -161,6 +136,30 @@ class Table:
161
136
  ignore_index=True
162
137
  ).set_index("t", drop=False))
163
138
 
139
+ @classmethod
140
+ def stack(Cls, sections: list, overlap: int=1) -> Self:
141
+ """Stack a list of Tables on top of each other.
142
+ The overlap is the number of rows to overlap between each section
143
+ """
144
+ # first build list of index offsets, to be added to each dataframe
145
+ if overlap > 0:
146
+ offsets = np.cumsum([0] + [sec.data.index[-overlap] for sec in sections[:-1]])
147
+ dfs = [section.data.iloc[:-overlap] for section in sections[:-1]] + [sections[-1].data]
148
+ elif overlap == 0:
149
+ offsets = np.cumsum([0] + [sec.duration + sec.dt[-1] for sec in sections[:-1]])
150
+ dfs = [section.data for section in sections]
151
+ else:
152
+ raise AttributeError("Overlap must be >= 0")
153
+
154
+ for df, offset in zip(dfs, offsets):
155
+ df.index = np.array(df.index) - df.index[0] + offset
156
+ combo = pd.concat(dfs)
157
+ combo.index.name = "t"
158
+
159
+ combo["t"] = combo.index
160
+
161
+ return Cls(combo)
162
+
164
163
  def label(self, **kwargs) -> Self:
165
164
  return self.__class__(self.data.assign(**kwargs))
166
165
 
@@ -177,9 +176,11 @@ class Table:
177
176
 
178
177
  def get_subset_df(self, **kwargs) -> pd.DataFrame:
179
178
  dfo = self.data
179
+ sel = np.full(len(self.data), True)
180
180
  for k, v in kwargs.items():
181
- dfo = dfo.loc[dfo[k] == v, :]
182
- return dfo
181
+ sel = sel & (dfo[k] == v)
182
+
183
+ return self.data.loc[sel + (sel.astype(int).diff() == -1)]
183
184
 
184
185
  def get_label_subset(self, min_len=1, **kwargs) -> Self:
185
186
  return self.__class__(self.get_subset_df(**kwargs), min_len=min_len)
@@ -244,13 +245,14 @@ class Table:
244
245
  return self.label(**labels.to_dict(orient='list'))
245
246
 
246
247
  @classmethod
247
- def shift_multi(Cls, steps: int, tb1: Self, tb2: Self, min_len=2) -> Tuple(Self, Self):
248
+ def shift_multi(Cls, steps: int, tb1: Self, tb2: Self, min_len=1) -> Tuple[Self, Self]:
248
249
  '''Take datapoints off the start of tb2 and add to the end tb1'''
249
- if (steps>0 and len(tb2)-min_len<steps) or (steps<0 and min_len - len(tb1) > steps):
250
- raise ValueError(f'Cannot Squash a Table to less than {min_len} datapoints')
251
- dfj = Cls.stack([tb1, tb2], overlap=0).data
252
- return Cls(dfj.iloc[:len(tb1)+steps, :]), \
253
- Cls(dfj.iloc[len(tb1)+steps:, :])
250
+ #if (steps>0 and len(tb2)-min_len<steps) or (steps<0 and min_len - len(tb1) > steps):
251
+ # raise ValueError(f'Cannot Squash a Table to less than {min_len} datapoints')
252
+ tj = Cls.stack([tb1, tb2]).shift_label(steps, min_len, **dict(tb1.labels.iloc[0]))
253
+
254
+ return Cls(tj.get_subset_df(**dict(tb1.labels.iloc[0]))), \
255
+ Cls(tj.get_subset_df(**dict(tb2.labels.iloc[0])))
254
256
 
255
257
  def shift_label_ratio(self, ratio: float, min_len=None, **kwargs) -> Self:
256
258
  '''shift a label within its allowable bounds, with a ratio of
@@ -473,11 +473,19 @@ class Flight:
473
473
  wind_N = df['wN'] if 'wN' in df.columns else None,
474
474
  wind_E = df['wE'] if 'wE' in df.columns else None,
475
475
  )
476
- origin = Origin('fcj_origin',GPS(
477
- fc_json['parameters']['originLat'],
478
- fc_json['parameters']['originLng'],
479
- fc_json['parameters']['originAlt']
480
- ), 0)
476
+ origin = Origin(
477
+ 'fcj_origin',
478
+ GPS(
479
+ float(fc_json['parameters']['pilotLat']),
480
+ float(fc_json['parameters']['pilotLng']),
481
+ float(fc_json['parameters']['pilotAlt'])
482
+ ).offset(-Point(
483
+ fc_json['parameters']['moveNorth'],
484
+ fc_json['parameters']['moveEast'],
485
+ 0,
486
+ )),
487
+ 0
488
+ )
481
489
 
482
490
  return Flight(df.set_index('time_flight', drop=False), None, origin, 'position')#.remove_time_flutter()
483
491
 
@@ -25,4 +25,7 @@ def main():
25
25
  if not (folder / file.name).exists():
26
26
  print(f'copying {file} to {folder / file.name}')
27
27
  shutil.copyfile(file, folder / file.name )
28
-
28
+
29
+
30
+ if __name__ == '__main__':
31
+ main()
@@ -54,4 +54,7 @@ def main():
54
54
  else:
55
55
  box = box_from_log(Flight.from_log(plog), args.input)
56
56
 
57
- box.to_f3a_zone(Path(args.logdir) / f'box_{plog.stem}.f3a')
57
+ box.to_f3a_zone(Path(args.logdir) / f'box_{plog.stem}.f3a')
58
+
59
+ if __name__ == '__main__':
60
+ main()
@@ -217,7 +217,7 @@ class State(Table):
217
217
 
218
218
  def get_meid(self: State, manid: int, elid: int=None):
219
219
  st = self.get_manoeuvre(manid)
220
- if not elid is None:
220
+ if elid is not None:
221
221
  return st.get_element(elid)
222
222
  else:
223
223
  return st
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flightdata
3
- Version: 0.2.10
3
+ Version: 0.2.12
4
4
  Summary: Module for handling UAV flight log data
5
5
  Author-email: Thomas David <thomasdavid0@gmail.com>
6
6
  License: GNU GPL v3
@@ -34,3 +34,16 @@ The State object is a table representing the position and orientation of the air
34
34
 
35
35
 
36
36
  Further documentation will be provided here: https://pfcdocumentation.readthedocs.io/pyflightcoach/flightdata.html
37
+
38
+
39
+ ### Installation
40
+
41
+ ```bash
42
+ pip install pfc-geometry
43
+ ```
44
+
45
+ ### Setup from source
46
+
47
+ ```bash
48
+ pip install .
49
+ ```
@@ -8,7 +8,7 @@ from pytest import fixture
8
8
 
9
9
  @fixture
10
10
  def df():
11
- df = pd.DataFrame(np.linspace(0,100, 100), columns=['t'])
11
+ df = pd.DataFrame(np.linspace(0,5, 6), columns=['t'])
12
12
  return df.set_index("t", drop=False)
13
13
 
14
14
  @fixture
@@ -54,12 +54,15 @@ def test_get_subset_df(tab_full, labst):
54
54
  assert len(tab_full) == len(df)
55
55
 
56
56
 
57
- def test_shift_labels_ratios(tab_full):
58
- tf = tab_full.label(element='e0', manoeuvre='m0')
59
- tf.data.loc[tf.duration/2:,'element'] = 'e1'
60
-
57
+ def test_shift_labels_ratios(tab_full: Table):
58
+ tf: Table = Table.stack([
59
+ tab_full.label(element='e0', manoeuvre='m0'),
60
+ tab_full.label(element='e1', manoeuvre='m0')
61
+
62
+ ])
63
+
61
64
  assert sum(tf.shift_labels_ratios([0.5],2).element == 'e1') < sum(tf.element == 'e1')
62
- tf
65
+
63
66
 
64
67
  def test_stack(tab_full):
65
68
  tfn = Table.stack([tab_full.label(element='e0'), tab_full.label(element='e1')], overlap=0)
@@ -72,18 +75,18 @@ def test_stack(tab_full):
72
75
 
73
76
 
74
77
  def test_shift_multi(tab_full):
75
- t1, t2 = tab_full.label(element='e1'), tab_full.label(element='e2')
76
- tb1, tb2 = Table.shift_multi(2, t1, t2)
78
+ tabs = Table.stack([tab_full.label(element='e0'), tab_full.label(element='e1')], overlap=1).split_labels()
79
+ tb1, tb2 = Table.shift_multi(2, tabs['e0'], tabs['e1'])
77
80
 
78
81
  assert len(tb1) == len(tab_full) + 2
79
82
  assert len(tb2) == len(tab_full) - 2
80
83
  assert tb2.duration == tab_full.data.index[-3]
81
84
 
82
- tb1, tb2 = Table.shift_multi(-5, t1, t2)
85
+ tb1, tb2 = Table.shift_multi(-3, tabs['e0'], tabs['e1'])
83
86
 
84
- assert len(tb1) == len(tab_full) - 5
85
- assert len(tb2) == len(tab_full) + 5
86
- assert tb1.duration == tab_full.data.index[-6]
87
+ assert len(tb1) == len(tab_full) - 3
88
+ assert len(tb2) == len(tab_full) + 3
89
+ assert tb1.duration == tab_full.data.index[-4]
87
90
 
88
91
 
89
92
  def test_table_cumulative_labels(tab_full):
@@ -102,6 +105,6 @@ def test_table_cumulative_labels(tab_full):
102
105
  indexes = np.unique(res, return_index=True)[1]
103
106
  np.testing.assert_array_equal(
104
107
  [res[index] for index in sorted(indexes)],
105
- np.array(['a1_b1', 'a2_b1', 'a2_b2', 'a1_b1_1'])
108
+ np.array(['a1_b1_0', 'a2_b1_0', 'a2_b2_0', 'a1_b1_1'])
106
109
  )
107
110
  pass
File without changes
File without changes
File without changes
File without changes