flightplotting 0.2.12__tar.gz → 0.2.13__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 (23) hide show
  1. {flightplotting-0.2.12 → flightplotting-0.2.13}/PKG-INFO +6 -3
  2. {flightplotting-0.2.12 → flightplotting-0.2.13}/pyproject.toml +4 -2
  3. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/plots.py +21 -34
  4. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/templates.py +6 -14
  5. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/traces.py +20 -10
  6. flightplotting-0.2.13/uv.lock +345 -0
  7. flightplotting-0.2.12/uv.lock +0 -476
  8. {flightplotting-0.2.12 → flightplotting-0.2.13}/.github/workflows/publish_pypi.yml +0 -0
  9. {flightplotting-0.2.12 → flightplotting-0.2.13}/.gitignore +0 -0
  10. {flightplotting-0.2.12 → flightplotting-0.2.13}/.vscode/settings.json +0 -0
  11. {flightplotting-0.2.12 → flightplotting-0.2.13}/COPYING +0 -0
  12. {flightplotting-0.2.12 → flightplotting-0.2.13}/MANIFEST.in +0 -0
  13. {flightplotting-0.2.12 → flightplotting-0.2.13}/README.md +0 -0
  14. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/__init__.py +0 -0
  15. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/data/ColdDraftF3APlane.obj +0 -0
  16. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/data/__init__.py +0 -0
  17. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/model.py +0 -0
  18. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/py.typed +0 -0
  19. {flightplotting-0.2.12 → flightplotting-0.2.13}/src/plotting/titlerenderer.py +0 -0
  20. {flightplotting-0.2.12 → flightplotting-0.2.13}/tests/__init__.py +0 -0
  21. {flightplotting-0.2.12 → flightplotting-0.2.13}/tests/data/__init__.py +0 -0
  22. {flightplotting-0.2.12 → flightplotting-0.2.13}/tests/data/p23_flight.json +0 -0
  23. {flightplotting-0.2.12 → flightplotting-0.2.13}/tests/test_plots.py +0 -0
@@ -1,12 +1,15 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: flightplotting
3
- Version: 0.2.12
3
+ Version: 0.2.13
4
4
  Summary: Add your description here
5
5
  Author-email: Thomas David <thomasdavid0@gmail.com>
6
+ License-File: COPYING
6
7
  Requires-Python: >=3.12
7
- Requires-Dist: flightanalysis>=0.3.14
8
+ Requires-Dist: flightdata>=0.3.0
8
9
  Requires-Dist: numpy>=2.1.3
9
10
  Requires-Dist: pandas>=2.2.3
11
+ Requires-Dist: pfc-geometry
12
+ Requires-Dist: pfcschemas
10
13
  Requires-Dist: plotly>=5.24.1
11
14
  Description-Content-Type: text/markdown
12
15
 
@@ -1,15 +1,17 @@
1
1
  [project]
2
2
  name = "flightplotting"
3
- version="v0.2.12"
3
+ version="v0.2.13"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Thomas David", email = "thomasdavid0@gmail.com" }]
7
7
  requires-python = ">=3.12"
8
8
  dependencies = [
9
- "flightanalysis>=0.3.14",
10
9
  "numpy>=2.1.3",
11
10
  "pandas>=2.2.3",
12
11
  "plotly>=5.24.1",
12
+ "flightdata>=0.3.0",
13
+ "pfc-geometry",
14
+ "pfcschemas",
13
15
  ]
14
16
 
15
17
  [build-system]
@@ -15,14 +15,12 @@ from plotting.traces import (
15
15
  )
16
16
 
17
17
  from flightdata import State
18
- from flightdata.base.labeling import get_appended_id
19
18
  from geometry import Coord
20
19
  from plotting.model import obj
21
20
  import numpy.typing as npt
22
21
  import numpy as np
23
22
  import pandas as pd
24
23
  from typing import List, Union
25
- from flightanalysis.scoring.box import Box
26
24
 
27
25
 
28
26
  def plotsec(
@@ -37,6 +35,7 @@ def plotsec(
37
35
  show_axes=False,
38
36
  ribb: bool = False,
39
37
  tips: bool = True,
38
+ ribbonhover="t",
40
39
  origin=False,
41
40
  ):
42
41
  traces = []
@@ -53,16 +52,18 @@ def plotsec(
53
52
  showkeys = False
54
53
 
55
54
  for i, sec in enumerate(secs):
56
- text = sec.data.t #- sec.data.t.iloc[0]
55
+ text = sec.data.t # - sec.data.t.iloc[0]
57
56
  _color = color if color is not None else px.colors.qualitative.Plotly[i]
58
57
  if ribb:
59
- traces += ribbon(sec, scale * 1.85, _color, name=keys[i])
58
+ traces += ribbon(sec, 0.5 * scale * 1.85, "grey", name=keys[i], opacity=0.5, hover=ribbonhover)
60
59
  if tips:
61
60
  traces += tiptrace(sec, scale * 1.85, text=text, name=keys[i])
62
61
  if nmodels > 0:
63
62
  traces += meshes(nmodels, sec, _color, scale)
64
63
  if cg:
65
- traces.append(cgtrace(sec, line=dict(color=_color, width=2), name=keys[i], text=text))
64
+ traces.append(
65
+ cgtrace(sec, line=dict(color=_color, width=2), name=keys[i], text=text)
66
+ )
66
67
 
67
68
  if origin:
68
69
  traces += axestrace(Coord.zero(), 50)
@@ -136,47 +137,33 @@ def plotdtw(sec: State, manoeuvres: List[str], span=3, fig=None):
136
137
 
137
138
 
138
139
  def plot_regions(
139
- st: State, lab_cols: list[str], span=3, colours=None, fig=None, box:Box=None, **kwargs
140
+ st: State,
141
+ label_group_name: str,
142
+ span=3,
143
+ colours=None,
144
+ fig=None,
145
+ ribbonhover="t",
146
+ **kwargs,
140
147
  ):
141
148
  colours = px.colors.qualitative.Plotly if colours is None else colours
142
- lab_cols = [lab_cols] if isinstance(lab_cols, str) else lab_cols
143
-
144
- st = st.label(clabs=st.cumulative_labels(*lab_cols))
145
-
146
- colmap = {}
147
149
 
148
150
  traces = []
149
- for i, (k, seg) in enumerate(st.split_labels("clabs").items()):
151
+ for i, k in enumerate(st.labels[label_group_name].keys()):
152
+ seg = getattr(st, label_group_name)[k]
150
153
  if len(seg) < 3:
151
154
  continue
152
- blab, id = get_appended_id(k)
153
- if blab not in colmap:
154
- colmap[blab] = colours[len(colmap) % len(colours)]
155
155
  traces += ribbon(
156
156
  seg,
157
157
  span,
158
- colmap[blab],
159
- name=blab,
160
- showlegend=int(id) == 0,
161
- **kwargs[blab] if blab in kwargs else {},
162
- )
163
- traces.append(
164
- go.Scatter3d(
165
- x=seg.pos.x,
166
- y=seg.pos.y,
167
- z=seg.pos.z,
168
- mode="lines",
169
- line=dict(width=0, color=colmap[blab]),
170
- name=k,
171
- showlegend=False,
172
- )
158
+ colours[i%len(colours)],
159
+ name=k,
160
+ hover=ribbonhover
173
161
  )
174
162
 
163
+
175
164
  if fig is None:
176
165
  fig = go.Figure(layout=go.Layout(template="flight3d+judge_view"))
177
166
  fig.add_traces(traces)
178
- if box:
179
- fig.add_traces(box.plot())
180
167
  return fig
181
168
 
182
169
 
@@ -316,7 +303,7 @@ def multi_y_subplots(data: dict[str, pd.DataFrame], x: npt.NDArray = None):
316
303
  cols=1,
317
304
  shared_xaxes=True,
318
305
  vertical_spacing=0.01,
319
- #subplot_titles=list(data.keys()),
306
+ # subplot_titles=list(data.keys()),
320
307
  )
321
308
 
322
309
  for row, (k, v) in enumerate(data.items(), 1):
@@ -352,7 +339,7 @@ def multi_y_subplots(data: dict[str, pd.DataFrame], x: npt.NDArray = None):
352
339
  yanchor="top",
353
340
  ),
354
341
  f"yaxis{i}": dict(
355
- title=list(data.keys())[i-1],
342
+ title=list(data.keys())[i - 1],
356
343
  showline=True,
357
344
  ),
358
345
  }
@@ -2,21 +2,14 @@
2
2
  import plotly.graph_objects as go
3
3
  import plotly.io as pio
4
4
 
5
- flight3d_template = go.layout.Template(layout=go.Layout(
5
+
6
+ generic3d_template = go.layout.Template(layout=go.Layout(
6
7
  margin=dict(l=0, r=0, t=0, b=0),
7
- scene=dict(
8
- aspectmode='data',
9
- ),
10
- legend=dict(
11
- font=dict(size=20),
12
- yanchor="top",
13
- y=0.99,
14
- xanchor="left",
15
- x=0.01
16
- )
8
+ scene=dict(aspectmode='data')
17
9
  ))
18
10
 
19
- pio.templates["flight3d"] = flight3d_template
11
+ pio.templates["generic3d"] = generic3d_template
12
+ pio.templates["flight3d"] = generic3d_template
20
13
 
21
14
  judges_view_template = go.layout.Template(layout=go.Layout(scene_camera=dict(
22
15
  up=dict(x=0, y=0, z=1),
@@ -32,10 +25,9 @@ pio.templates["judge_view"] = judges_view_template
32
25
  clean_paper_template = go.layout.Template(layout=go.Layout(
33
26
  margin=dict(l=0, r=0, t=0, b=0),
34
27
  scene=dict(
35
- aspectmode='data',
36
28
  xaxis = dict(visible=False),
37
29
  yaxis = dict(visible=False),
38
- zaxis =dict(visible=False)
30
+ zaxis = dict(visible=False)
39
31
  ),
40
32
  legend=dict(
41
33
  font=dict(size=20),
@@ -1,3 +1,4 @@
1
+ from typing import Literal
1
2
  import plotly.graph_objects as go
2
3
  import plotting.templates
3
4
  from geometry import Point, Coord, Transformation
@@ -23,7 +24,7 @@ def boxtrace():
23
24
  )]
24
25
 
25
26
 
26
- def meshes(npoints, seq: State, colour, scale=1, _obj: OBJ=None):
27
+ def meshes(npoints, seq: State | Transformation, colour: str=None, scale=1, _obj: OBJ=None):
27
28
  _obj = obj if _obj is None else _obj
28
29
  if scale != 1:
29
30
  _obj = _obj.scale(scale)
@@ -36,10 +37,10 @@ def meshes(npoints, seq: State, colour, scale=1, _obj: OBJ=None):
36
37
  locs = locs + list(np.cumsum(np.full(npoints-2, len(seq) / (npoints-1))).astype(int))
37
38
 
38
39
  ms = []
39
- for loc in locs:
40
+ for i, loc in enumerate(locs):
40
41
  ms.append(_obj.transform(
41
- Transformation(seq.pos[loc], seq.att[loc])
42
- ).create_mesh(colour,f"{seq.time.t[loc]:.1f}"))
42
+ seq.iloc[loc].transform if isinstance(seq, State) else seq[loc]
43
+ ).create_mesh(colour or "grey",f"{(seq.time.t[loc] if isinstance(seq, State) else i):.1f}"))
43
44
  return ms
44
45
 
45
46
  def vector(origin, direction, **kwargs):
@@ -201,24 +202,25 @@ def aoa_trace(sec, dash="dash", colours = px.colors.qualitative.Plotly):
201
202
  #sec = sec.append_columns(sec.aoa())
202
203
  return sec_col_trace(sec, ["alpha", "beta"], dash, colours, np.degrees)
203
204
 
204
- def axestrace(cid: Coord, length:float=20.0):
205
+ def axestrace(cid: Coord | Transformation, length:float=20.0, **kwargs):
205
206
  ntraces = []
206
207
  colours = {"x":"red", "y":"blue", "z":"green"}
207
208
  for i, ci in enumerate(cid):
209
+ if isinstance(ci, Transformation):
210
+ ci = ci.apply(Coord.zero())
208
211
  for ax, col in zip([ci.x_axis, ci.y_axis, ci.z_axis], list("xyz")):
209
212
  axis = Point.concatenate([ci.origin, ci.origin + ax * length])
210
213
  ntraces.append(go.Scatter3d(
211
214
  x=axis.x, y=axis.y, z=axis.z, mode="lines",
212
215
  line=dict(color=colours[col]),
213
- name=col,
214
- showlegend=True if i==0 else False
216
+ name=f"{i}_{col}",
217
+ **kwargs
215
218
  ))
216
219
 
217
220
  return ntraces
218
221
 
219
222
 
220
223
 
221
-
222
224
  def _npinterzip(a, b):
223
225
  """
224
226
  takes two numpy arrays and zips them.
@@ -243,7 +245,7 @@ def _npinterzip(a, b):
243
245
  return c
244
246
 
245
247
 
246
- def ribbon(sec: State, span: float, color, **kwargs):
248
+ def ribbon(sec: State, span: float, color, hover: Literal["i", "t"]='i', **kwargs):
247
249
  """TODO make the colouring more generic
248
250
  """
249
251
 
@@ -252,7 +254,13 @@ def ribbon(sec: State, span: float, color, **kwargs):
252
254
 
253
255
  points = Point(_npinterzip(left.data, right.data))
254
256
 
255
-
257
+ match hover:
258
+ case "i":
259
+ text=[f"{i}" for i in np.arange(len(sec)*2)]
260
+ case _:
261
+ text=[f"{t:.1f}" for t in _npinterzip(sec.t, sec.t)]
262
+
263
+
256
264
  _i = np.array(range(len(points) - 2)) # 1 2 3 4 5
257
265
 
258
266
  _js = np.array(range(1, len(points), 2))
@@ -265,5 +273,7 @@ def ribbon(sec: State, span: float, color, **kwargs):
265
273
  x=points.x, y=points.y, z=points.z, i=_i, j=_j, k=_k,
266
274
  intensitymode="cell",
267
275
  facecolor=np.full(len(_i), color),
276
+ text=text,
277
+ hovertemplate='i:%{text}<br>',
268
278
  **kwargs
269
279
  )]