flightanalysis 0.2.12__tar.gz → 0.2.14__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.
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/PKG-INFO +3 -3
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/f3a_criteria_maker.py +29 -12
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/el_analysis.py +2 -2
- flightanalysis-0.2.14/flightanalysis/analysis/manoeuvre_analysis/__init__.py +14 -0
- flightanalysis-0.2.14/flightanalysis/analysis/manoeuvre_analysis/alignment.py +97 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/manoeuvre_analysis/analysis.py +8 -8
- flightanalysis-0.2.14/flightanalysis/analysis/manoeuvre_analysis/basic.py +131 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/manoeuvre_analysis/complete.py +9 -12
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/manoeuvre_analysis/scored.py +21 -3
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/sch_analysis.py +3 -5
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/IMAC_Unlimited2024_schedule.json +209 -209
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/f3a_a25_schedule.json +166 -166
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/f3a_f25_schedule.json +276 -276
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/f3a_p23_schedule.json +304 -279
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/f3a_p25_schedule.json +278 -278
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/f3auk_clubman_schedule.json +118 -118
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/f3auk_inter_schedule.json +111 -111
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/__init__.py +1 -1
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/builders/elbuilders.py +2 -15
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/collectors.py +6 -2
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/mandef.py +3 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/manparm.py +8 -9
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/operations/operation.py +9 -1
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/scheddef.py +2 -2
- flightanalysis-0.2.14/flightanalysis/definition/scheduleinfo.py +72 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/element.py +6 -6
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/exponential.py +8 -6
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/f3a_criteria.py +13 -13
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/inter/combination.py +1 -1
- flightanalysis-0.2.14/flightanalysis/scoring/criteria/inter/comparison.py +20 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/intra/bounded.py +3 -3
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/intra/continuous.py +3 -3
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/intra/single.py +4 -5
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/downgrade.py +7 -12
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/measurement.py +19 -10
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/results.py +16 -15
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scripts/collect_scores.py +3 -3
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis.egg-info/PKG-INFO +3 -3
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis.egg-info/SOURCES.txt +2 -4
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis.egg-info/requires.txt +2 -2
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/requirements-dev.txt +1 -1
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/requirements.txt +1 -1
- flightanalysis-0.2.12/examples/scoring/temp.py +0 -24
- flightanalysis-0.2.12/flightanalysis/analysis/manoeuvre_analysis/__init__.py +0 -8
- flightanalysis-0.2.12/flightanalysis/analysis/manoeuvre_analysis/alignment.py +0 -81
- flightanalysis-0.2.12/flightanalysis/analysis/manoeuvre_analysis/basic.py +0 -86
- flightanalysis-0.2.12/flightanalysis/definition/scheduleinfo.py +0 -45
- flightanalysis-0.2.12/flightanalysis/scoring/criteria/inter/comparison.py +0 -18
- flightanalysis-0.2.12/tests/test_schedule/test_element/test_split_optimiser.py +0 -15
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/.github/workflows/publish_pypi.yml +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/.gitignore +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/LICENSE +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/MANIFEST.in +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/README.md +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/data/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/data/manual_F3A_F23_22_04_28_00000231.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/data/manual_F3A_P23_22_05_31_00000350.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/data/manual_F3A_P23_23_08_11_00000094.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/judging.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/inter_analysis.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/intra_analysis.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/mans/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/mans/extract_mans.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/mans/tHat.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/examples/scoring/manoeuvres/positioning_analysis.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/data/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/builders/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/builders/lines.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/builders/manbuilder.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/eldef.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/maninfo.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/manoption.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/operations/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/operations/funopp.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/operations/itemopp.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/definition/operations/mathopp.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/autorotation.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/line.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/loop.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/nose_drop.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/pitch_break.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/recovery.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/elements/stall_turn.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/manoeuvre.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/schedule.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/criteria.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/inter/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scoring/criteria/intra/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scripts/batch_analyse.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/scripts/plot_scores.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis.egg-info/dependency_links.txt +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis.egg-info/entry_points.txt +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis.egg-info/top_level.txt +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/pyproject.toml +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/AMA_Intermediate2024.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/create_all.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/f3a_a25.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/f3a_f25.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/f3a_p23.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/f3a_p25.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/f3auk_clubman.py +0 -0
- /flightanalysis-0.2.12/scripts/f3auk_Intermediate.py → /flightanalysis-0.2.14/scripts/f3auk_intermediate.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/imac_sport2024.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/imac_unlim2024.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/make_manoeuvre.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/scripts/nsrca_inter2024.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/setup.cfg +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/EmailedBox.f3a +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/conftest.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/data/manual_F3A_P23.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/data/p23.BIN +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/data/p23_box.f3a +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/data/p23_fc.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/data/p23_flight.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_criiteria.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_data.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_definition/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_definition/test_definition_eldef.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_definition/test_definition_manparm.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_definition/test_definition_mpopp.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_definition/test_schedule_definition.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_definition/test_schedule_definition_maninfo.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/__init__.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/loop_analysis.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/p23_th_e0.csv +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/p23_th_e0.json +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/p23_th_e0_template.csv +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element_line.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element_loop.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element_nose_drop.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element_pitch_break.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element_recovery.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_element/test_schedule_element_stallturn.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_measurement.py +0 -0
- {flightanalysis-0.2.12 → flightanalysis-0.2.14}/tests/test_schedule/test_schedule_manoeuvre.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flightanalysis
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.14
|
|
4
4
|
Summary: A package for analysing flight data
|
|
5
5
|
Author-email: Thomas David <thomasdavid0@gmail.com>
|
|
6
6
|
License: GNU GPL v3
|
|
@@ -16,7 +16,7 @@ Requires-Dist: simplejson
|
|
|
16
16
|
Requires-Dist: loguru
|
|
17
17
|
Requires-Dist: joblib
|
|
18
18
|
Requires-Dist: pfc-geometry>=0.2.6
|
|
19
|
-
Requires-Dist: flightdata>=0.2.
|
|
19
|
+
Requires-Dist: flightdata>=0.2.13
|
|
20
20
|
Provides-Extra: dev
|
|
21
21
|
Requires-Dist: numpy; extra == "dev"
|
|
22
22
|
Requires-Dist: pandas; extra == "dev"
|
|
@@ -26,7 +26,7 @@ Requires-Dist: simplejson; extra == "dev"
|
|
|
26
26
|
Requires-Dist: loguru; extra == "dev"
|
|
27
27
|
Requires-Dist: joblib; extra == "dev"
|
|
28
28
|
Requires-Dist: pfc-geometry>=0.2.6; extra == "dev"
|
|
29
|
-
Requires-Dist: flightdata>=0.2.
|
|
29
|
+
Requires-Dist: flightdata>=0.2.13; extra == "dev"
|
|
30
30
|
Requires-Dist: ardupilot_log_reader>=0.3.1; extra == "dev"
|
|
31
31
|
Requires-Dist: pymavlink; extra == "dev"
|
|
32
32
|
|
|
@@ -4,31 +4,31 @@ import numpy as np
|
|
|
4
4
|
|
|
5
5
|
f3a=dict(
|
|
6
6
|
single=dict(
|
|
7
|
-
track=Single(Exponential.fit_points(np.radians([30, 90]), [2, 6],
|
|
8
|
-
roll=Single(Exponential.fit_points(np.radians([30, 90]), [1, 6],
|
|
9
|
-
angle=Single(Exponential.fit_points(np.radians([30, 90]), [2, 6],
|
|
7
|
+
track=Single(Exponential.fit_points(np.radians([30, 90]), [2, 6], 6)),
|
|
8
|
+
roll=Single(Exponential.fit_points(np.radians([30, 90]), [1, 6], 6)),
|
|
9
|
+
angle=Single(Exponential.fit_points(np.radians([30, 90]), [2, 6], 6)),
|
|
10
10
|
# distance = Single(Exponential.fit_points([20, 40], [0.5, 1]))
|
|
11
11
|
),
|
|
12
12
|
intra=dict(
|
|
13
|
-
track=ContAbs(Exponential.fit_points(np.radians([30, 90]), [2, 6])),
|
|
14
|
-
roll=ContAbs(Exponential.fit_points(np.radians([30, 90]), [1.5, 6])),
|
|
15
|
-
radius=ContRat(Exponential.fit_points([1,5], [0.5, 4],
|
|
13
|
+
track=ContAbs(Exponential.fit_points(np.radians([30, 90]), [2, 6], 6)),
|
|
14
|
+
roll=ContAbs(Exponential.fit_points(np.radians([30, 90]), [1.5, 6], 6)),
|
|
15
|
+
radius=ContRat(Exponential.fit_points([1,5], [0.5, 4], 3)),
|
|
16
16
|
speed=ContRat(Exponential.fit_points([1,5], [0.15, 0.75], 1)),
|
|
17
|
-
roll_rate=ContRat(Exponential.fit_points([1,5], [0.15, 0.75],
|
|
17
|
+
roll_rate=ContRat(Exponential.fit_points([1,5], [0.15, 0.75], 2)),
|
|
18
18
|
stallturn_speed=InsideBound(Exponential.fit_points([2, 5], [0.3,1.5]), [-2,2]),
|
|
19
19
|
stallturn_width=InsideBound(Exponential.fit_points([2, 5], [0.5,2.5]), [-2,2]),
|
|
20
20
|
spin_entry_length=InsideBound(Exponential.fit_points([2, 5], [0.3,1.5]), [-5,5]),
|
|
21
21
|
pitch_break_length=InsideBound(Exponential.fit_points([1, 2], [0.7,3.5]), [-2,2]),
|
|
22
22
|
nose_drop_amount=OutsideBound(Exponential(20,1), [-np.radians(15), np.radians(15)]),
|
|
23
23
|
recovery_length=MaxBound(Exponential.fit_points([1, 2], [0.7,3.5]), 2),
|
|
24
|
-
box=InsideBound(Exponential(10/np.radians(
|
|
24
|
+
box=InsideBound(Exponential(10/np.radians(7.5), 1), [-np.radians(60), np.radians(60)]), # 10 points if the entire manoeuvre is 7.5 degrees outside the box
|
|
25
25
|
depth=MaxBound(Exponential.fit_points([20, 40], [0.5, 1]), 170)
|
|
26
26
|
),
|
|
27
27
|
inter=dict(
|
|
28
|
-
radius=Comparison(Exponential.fit_points([1,
|
|
29
|
-
speed=Comparison(Exponential.fit_points([1,
|
|
30
|
-
roll_rate=Comparison(Exponential.fit_points([1,
|
|
31
|
-
length=Comparison(Exponential.fit_points([1,
|
|
28
|
+
radius=Comparison(Exponential.fit_points([1,2], [1, 2], 2)),
|
|
29
|
+
speed=Comparison(Exponential.fit_points([1,2], [0.25, 0.5], 1)),
|
|
30
|
+
roll_rate=Comparison(Exponential.fit_points([1,2], [0.25, 0.5], 1)),
|
|
31
|
+
length=Comparison(Exponential.fit_points([1,2], [1, 2], 2)),
|
|
32
32
|
free=Comparison(free),
|
|
33
33
|
)
|
|
34
34
|
)
|
|
@@ -47,7 +47,24 @@ def plot_lookup(lu, v0=0, v1=10):
|
|
|
47
47
|
x = np.linspace(v0, v1, 30)
|
|
48
48
|
px.line(x=x,y=lu(x)).show()
|
|
49
49
|
|
|
50
|
+
def plot_all(crits):
|
|
51
|
+
from plotly.subplots import make_subplots
|
|
52
|
+
import plotly.graph_objects as go
|
|
53
|
+
criteria = [cr for crit in crits.values() for cr in crit.values()]
|
|
54
|
+
names = [cr for crit in crits.values() for cr in crit.keys()]
|
|
55
|
+
|
|
56
|
+
nplots = sum([len(cr) for cr in crits.values()])
|
|
57
|
+
ncols=5
|
|
58
|
+
fig = make_subplots(int(np.ceil(nplots / ncols)), ncols, subplot_titles=names)
|
|
59
|
+
|
|
60
|
+
for i, crit in enumerate(criteria):
|
|
61
|
+
row, col = 1 + i // ncols, 1 + i % ncols
|
|
62
|
+
x = np.linspace(0, 10, 30)
|
|
63
|
+
fig.add_trace(go.Scatter(x=x, y=crit.lookup(x), showlegend=False), row=row, col=col)
|
|
64
|
+
fig.show()
|
|
65
|
+
|
|
50
66
|
if __name__ == "__main__":
|
|
51
67
|
#plot_lookup(f3a['intra']['recovery_length'].lookup,-10,10)
|
|
52
68
|
|
|
69
|
+
# plot_all(f3a)
|
|
53
70
|
dump_criteria_to_py(f3a)
|
|
@@ -16,9 +16,9 @@ class ElementAnalysis:
|
|
|
16
16
|
tp: State
|
|
17
17
|
ref_frame: g.Transformation
|
|
18
18
|
|
|
19
|
-
def plot_3d(self,
|
|
19
|
+
def plot_3d(self, **kwargs):
|
|
20
20
|
from flightplotting import plotsec
|
|
21
|
-
return plotsec([self.fl, self.tp],
|
|
21
|
+
return plotsec([self.fl, self.tp], **kwargs)
|
|
22
22
|
|
|
23
23
|
def to_dict(self):
|
|
24
24
|
return {k: v.to_dict() for k, v in self.__dict__.items()}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .analysis import Analysis
|
|
2
|
+
from .basic import Basic
|
|
3
|
+
from .alignment import Alignment
|
|
4
|
+
from .complete import Complete, Scored
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def parse_dict(data: dict) -> Analysis:
|
|
8
|
+
return Scored.from_dict(data)
|
|
9
|
+
|
|
10
|
+
def parse(data: dict) -> Basic | Alignment | Complete | Scored:
|
|
11
|
+
if 'parameters' in data:
|
|
12
|
+
return Basic.from_mindict(data).proceed()
|
|
13
|
+
else:
|
|
14
|
+
return parse_dict(data).proceed()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from flightdata import State
|
|
4
|
+
from flightanalysis.manoeuvre import Manoeuvre
|
|
5
|
+
from loguru import logger
|
|
6
|
+
from .basic import Basic
|
|
7
|
+
from flightanalysis.definition import ManDef, ScheduleInfo
|
|
8
|
+
from ..el_analysis import ElementAnalysis
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class Alignment(Basic):
|
|
12
|
+
manoeuvre: Manoeuvre | None
|
|
13
|
+
template: State | None
|
|
14
|
+
|
|
15
|
+
def __getattr__(self, name) -> ElementAnalysis:
|
|
16
|
+
return ElementAnalysis(
|
|
17
|
+
self.mdef.data[name],
|
|
18
|
+
self.mdef.mps,
|
|
19
|
+
self.manoeuvre.elements.data[name],
|
|
20
|
+
self.flown.get_element(name),
|
|
21
|
+
self.template.get_element(name),
|
|
22
|
+
self.template.get_element(name)[0].transform
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def run_all(self, optimise_aligment=True, force=False) -> Alignment | Complete | Scored:
|
|
26
|
+
if self.__class__.__name__ == 'Scored' and force:
|
|
27
|
+
self = self.downgrade()
|
|
28
|
+
new = self
|
|
29
|
+
while self.__class__.__name__ != 'Scored':
|
|
30
|
+
new = self.run(optimise_aligment) if isinstance(self, Complete) else self.run()
|
|
31
|
+
if new.__class__.__name__ == self.__class__.__name__:
|
|
32
|
+
break
|
|
33
|
+
self = new
|
|
34
|
+
return new
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def from_dict(data: dict, fallback=True):
|
|
38
|
+
ia = Basic.from_dict(data)
|
|
39
|
+
try:
|
|
40
|
+
ia = Alignment(
|
|
41
|
+
manoeuvre=Manoeuvre.from_dict(data['manoeuvre']),
|
|
42
|
+
template=State.from_dict(data['template']),
|
|
43
|
+
**ia.__dict__
|
|
44
|
+
)
|
|
45
|
+
except Exception as e:
|
|
46
|
+
if fallback:
|
|
47
|
+
logger.debug(f'Failed to parse Alignment {repr(e)}')
|
|
48
|
+
else:
|
|
49
|
+
raise e
|
|
50
|
+
return ia
|
|
51
|
+
|
|
52
|
+
def run(self) -> Alignment | Complete:
|
|
53
|
+
if 'element' not in self.flown.data.columns:
|
|
54
|
+
try:
|
|
55
|
+
self = self._run(True)[1]
|
|
56
|
+
except Exception as e:
|
|
57
|
+
logger.error(f'Failed to run alignment stage 1: {repr(e)}')
|
|
58
|
+
return self
|
|
59
|
+
try:
|
|
60
|
+
return self._run(False)[1].proceed()
|
|
61
|
+
except Exception as e:
|
|
62
|
+
logger.error(f'Failed to run alignment stage 2: {repr(e)}')
|
|
63
|
+
return self
|
|
64
|
+
|
|
65
|
+
def _run(self, mirror=False, radius=10) -> Alignment:
|
|
66
|
+
dist, aligned = State.align(self.flown, self.template, radius, mirror)
|
|
67
|
+
return dist, self.update(aligned)
|
|
68
|
+
|
|
69
|
+
def update(self, aligned: State) -> Alignment:
|
|
70
|
+
man, tp = self.manoeuvre.match_intention(self.template[0], aligned)
|
|
71
|
+
mdef = ManDef(self.mdef.info, self.mdef.mps.update_defaults(man), self.mdef.eds)
|
|
72
|
+
return Alignment(self.id, mdef, aligned, self.direction, man, tp)
|
|
73
|
+
|
|
74
|
+
def _proceed(self) -> Complete:
|
|
75
|
+
if 'element' in self.flown.data.columns:
|
|
76
|
+
correction = self.mdef.create(self.template[0].transform)
|
|
77
|
+
return Complete(
|
|
78
|
+
self.id, self.mdef, self.flown, self.direction,
|
|
79
|
+
self.manoeuvre, self.template, correction,
|
|
80
|
+
correction.create_template(self.template[0], self.flown)
|
|
81
|
+
)
|
|
82
|
+
else:
|
|
83
|
+
return self
|
|
84
|
+
|
|
85
|
+
def to_mindict(self, sinfo: ScheduleInfo=None, full=False):
|
|
86
|
+
data = dict(
|
|
87
|
+
els = self.flown.label_ranges('element').to_dict('records')
|
|
88
|
+
)
|
|
89
|
+
if full:
|
|
90
|
+
data = dict(
|
|
91
|
+
**super().to_mindict(sinfo),
|
|
92
|
+
**data
|
|
93
|
+
)
|
|
94
|
+
return data
|
|
95
|
+
|
|
96
|
+
from .complete import Complete # noqa: E402
|
|
97
|
+
from .scored import Scored # noqa: E402
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
|
|
4
|
-
class AlinmentStage:
|
|
5
|
-
SETUP=0
|
|
6
|
-
PRELIM=1
|
|
7
|
-
SECONDARY=2
|
|
8
|
-
OPTIMISED=3
|
|
9
|
-
|
|
3
|
+
from flightanalysis.definition import ScheduleInfo
|
|
10
4
|
|
|
11
5
|
@dataclass
|
|
12
6
|
class Analysis:
|
|
7
|
+
id: int
|
|
8
|
+
|
|
13
9
|
def to_dict(self):
|
|
14
10
|
return {k: (v.to_dict() if hasattr(v, 'to_dict') else v) for k, v in self.__dict__.items()}
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
def to_mindict(self, sinfo: ScheduleInfo):
|
|
13
|
+
return {
|
|
14
|
+
"sinfo": sinfo.__dict__,
|
|
15
|
+
}
|
|
16
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from flightdata import State, Flight, Origin
|
|
4
|
+
from flightanalysis.definition import ManDef, SchedDef, ManOption
|
|
5
|
+
import geometry as g
|
|
6
|
+
from json import load
|
|
7
|
+
from .analysis import Analysis
|
|
8
|
+
from flightanalysis.definition.scheduleinfo import ScheduleInfo
|
|
9
|
+
import numpy as np
|
|
10
|
+
import pandas as pd
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class Basic(Analysis):
|
|
15
|
+
mdef: ManDef | ManOption
|
|
16
|
+
flown: State
|
|
17
|
+
direction: int
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def name(self):
|
|
21
|
+
return self.mdef.uid
|
|
22
|
+
|
|
23
|
+
def run_all(self, optimise_aligment=True, force=False) -> Scored:
|
|
24
|
+
"""Run the analysis to the final stage, for the case where the elements have not been labelled"""
|
|
25
|
+
drs = [r._run(True) for r in self.run()]
|
|
26
|
+
|
|
27
|
+
dr = drs[np.argmin([dr[0] for dr in drs])]
|
|
28
|
+
|
|
29
|
+
return dr[1].run_all(optimise_aligment, force)
|
|
30
|
+
|
|
31
|
+
def proceed(self) -> Complete:
|
|
32
|
+
"""Proceed the analysis to the final stage for the case where the elements have already been labelled"""
|
|
33
|
+
if 'element' not in self.flown.data.columns:
|
|
34
|
+
return self
|
|
35
|
+
mopt = ManOption([self.mdef]) if isinstance(self.mdef, ManDef) else self.mdef
|
|
36
|
+
elnames = self.flown.data.element.unique()
|
|
37
|
+
for md in mopt:
|
|
38
|
+
if np.all(elnames[1:-1] == list( md.eds.data.keys())):
|
|
39
|
+
mdef = md
|
|
40
|
+
break
|
|
41
|
+
else:
|
|
42
|
+
raise ValueError(f"{self.mdef.info.short_name} element sequence doesn't agree with {self.flown.data.element.unique()}")
|
|
43
|
+
|
|
44
|
+
itrans = self.create_itrans()
|
|
45
|
+
man, tp = mdef.create(itrans).add_lines().match_intention(
|
|
46
|
+
State.from_transform(itrans),
|
|
47
|
+
self.flown
|
|
48
|
+
)
|
|
49
|
+
mdef = ManDef(mdef.info, mdef.mps.update_defaults(man), mdef.eds)
|
|
50
|
+
corr = mdef.create(itrans).add_lines()
|
|
51
|
+
return Complete(
|
|
52
|
+
self.id, mdef, self.flown, self.direction,
|
|
53
|
+
man, tp, corr, corr.create_template(itrans, self.flown)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def from_dict(Cls, data:dict) -> Basic:
|
|
58
|
+
return Basic(
|
|
59
|
+
-1,
|
|
60
|
+
ManDef.from_dict(data["mdef"]),
|
|
61
|
+
State.from_dict(data["flown"]),
|
|
62
|
+
data['direction']
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def create_itrans(self) -> g.Transformation:
|
|
66
|
+
return g.Transformation(
|
|
67
|
+
self.flown[0].pos,
|
|
68
|
+
self.mdef.info.start.initial_rotation(self.direction)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def from_fcj(file: str, mid: int):
|
|
73
|
+
with open(file, 'r') as f:
|
|
74
|
+
data = load(f)
|
|
75
|
+
flight = Flight.from_fc_json(data)
|
|
76
|
+
box = Origin.from_fcjson_parmameters(data["parameters"])
|
|
77
|
+
|
|
78
|
+
sdef = SchedDef.load(data["parameters"]["schedule"][1])
|
|
79
|
+
|
|
80
|
+
state = State.from_flight(flight, box).splitter_labels(
|
|
81
|
+
data["mans"],
|
|
82
|
+
[m.info.short_name for m in sdef]
|
|
83
|
+
)
|
|
84
|
+
mdef= sdef[mid]
|
|
85
|
+
return Basic(mid, mdef, state.get_manoeuvre(mdef.uid))
|
|
86
|
+
|
|
87
|
+
def run(self) -> list[Alignment]:
|
|
88
|
+
itrans = self.create_itrans()
|
|
89
|
+
mopt = ManOption([self.mdef]) if isinstance(self.mdef, ManDef) else self.mdef
|
|
90
|
+
|
|
91
|
+
als = []
|
|
92
|
+
for mdef in mopt:
|
|
93
|
+
man = mdef.create(itrans).add_lines()
|
|
94
|
+
als.append(Alignment(
|
|
95
|
+
self.id, mdef, self.flown, self.direction,
|
|
96
|
+
man, man.create_template(itrans)
|
|
97
|
+
))
|
|
98
|
+
return als
|
|
99
|
+
|
|
100
|
+
def to_mindict(self, sinfo: ScheduleInfo):
|
|
101
|
+
data = dict(
|
|
102
|
+
**super().to_mindict(sinfo),
|
|
103
|
+
name=self.name,
|
|
104
|
+
id=self.id,
|
|
105
|
+
data=self.flown._create_json_data().to_dict('records'),
|
|
106
|
+
direction=self.direction,
|
|
107
|
+
)
|
|
108
|
+
return data
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def from_mindict(data: dict):
|
|
112
|
+
info = ScheduleInfo.from_str(data["parameters"]["schedule"][1])
|
|
113
|
+
|
|
114
|
+
st = State.from_flight(
|
|
115
|
+
Flight.from_fc_json(data),
|
|
116
|
+
Origin.from_fcjson_parmameters(data["parameters"])
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
mdef = SchedDef.load(info)[data['id']]
|
|
120
|
+
|
|
121
|
+
if 'els' in data:
|
|
122
|
+
df = pd.DataFrame(data['els'])
|
|
123
|
+
df.columns = ['name', 'start', 'stop', 'length']
|
|
124
|
+
st = st.splitter_labels(df.to_dict('records'), target_col='element').label(manoeuvre=data['name'])
|
|
125
|
+
|
|
126
|
+
return Basic(data['id'], mdef, st, data['direction'])
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
from .alignment import Alignment # noqa: E402
|
|
130
|
+
from .complete import Complete # noqa: E402
|
|
131
|
+
from .scored import Scored # noqa: E402
|
|
@@ -2,13 +2,13 @@ from __future__ import annotations
|
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from ..el_analysis import ElementAnalysis
|
|
4
4
|
from flightdata import State
|
|
5
|
-
from flightanalysis.definition import ManDef
|
|
5
|
+
from flightanalysis.definition import ManDef, ScheduleInfo
|
|
6
6
|
from flightanalysis.manoeuvre import Manoeuvre
|
|
7
7
|
from flightanalysis.scoring import Results, ManoeuvreResults, Measurement
|
|
8
8
|
from flightanalysis.scoring.criteria.f3a_criteria import F3A
|
|
9
9
|
from flightanalysis.definition.maninfo import Position
|
|
10
10
|
import numpy as np
|
|
11
|
-
from .alignment import Alignment
|
|
11
|
+
from .alignment import Alignment
|
|
12
12
|
from loguru import logger
|
|
13
13
|
|
|
14
14
|
|
|
@@ -34,7 +34,7 @@ class Complete(Alignment):
|
|
|
34
34
|
return pa
|
|
35
35
|
|
|
36
36
|
def run(self, optimise_aligment=True) -> Scored:
|
|
37
|
-
if
|
|
37
|
+
if optimise_aligment:
|
|
38
38
|
self = self.optimise_alignment()
|
|
39
39
|
self = self.update_templates()
|
|
40
40
|
return Scored(**self.__dict__,
|
|
@@ -63,6 +63,7 @@ class Complete(Alignment):
|
|
|
63
63
|
tp = el.get_data(self.template).relocate(st.pos[0])
|
|
64
64
|
return ElementAnalysis(edef, self.mdef.mps, el, st, tp, el.ref_frame(tp))
|
|
65
65
|
|
|
66
|
+
|
|
66
67
|
def update_templates(self):
|
|
67
68
|
if not np.all(self.flown.element == self.template.element):
|
|
68
69
|
manoeuvre, template = self.manoeuvre.match_intention(self.template[0], self.flown)
|
|
@@ -70,8 +71,9 @@ class Complete(Alignment):
|
|
|
70
71
|
correction = mdef.create(self.template[0].transform).add_lines()
|
|
71
72
|
|
|
72
73
|
return Complete(
|
|
73
|
-
mdef, self.flown, self.direction,
|
|
74
|
-
manoeuvre, template, correction,
|
|
74
|
+
self.id, mdef, self.flown, self.direction,
|
|
75
|
+
manoeuvre, template, correction,
|
|
76
|
+
correction.create_template(template[0])
|
|
75
77
|
)
|
|
76
78
|
else:
|
|
77
79
|
return self
|
|
@@ -127,13 +129,6 @@ class Complete(Alignment):
|
|
|
127
129
|
Measurement.depth(self.flown)
|
|
128
130
|
)
|
|
129
131
|
|
|
130
|
-
# val = self.flown.pos.y.mean()
|
|
131
|
-
# id = np.abs(self.flown.pos.y - val).argmin()
|
|
132
|
-
# m = Measurement.depth(self.flown[id])
|
|
133
|
-
# error = np.maximum(m.value, 170) - 170
|
|
134
|
-
# dist_dg = F3A.single.distance.lookup(error) * m.visibility
|
|
135
|
-
# return Result("distance", m, m.value, error, dist_dg, [id])
|
|
136
|
-
|
|
137
132
|
def intra(self):
|
|
138
133
|
return self.manoeuvre.analyse(self.flown, self.template)
|
|
139
134
|
|
|
@@ -160,4 +155,6 @@ class Complete(Alignment):
|
|
|
160
155
|
fig = plotdtw(self.flown, self.flown.data.element.unique())
|
|
161
156
|
return plotsec(self.flown, color="blue", nmodels=20, fig=fig, **kwargs)
|
|
162
157
|
|
|
158
|
+
|
|
159
|
+
|
|
163
160
|
from .scored import Scored # noqa: E402
|
{flightanalysis-0.2.12 → flightanalysis-0.2.14}/flightanalysis/analysis/manoeuvre_analysis/scored.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from .complete import Complete
|
|
3
3
|
from flightanalysis.scoring import ManoeuvreResults
|
|
4
|
+
from flightanalysis.definition.scheduleinfo import ScheduleInfo
|
|
4
5
|
from loguru import logger
|
|
5
6
|
|
|
6
7
|
|
|
@@ -8,6 +9,13 @@ from loguru import logger
|
|
|
8
9
|
class Scored(Complete):
|
|
9
10
|
scores: ManoeuvreResults
|
|
10
11
|
|
|
12
|
+
def downgrade(self) -> Complete:
|
|
13
|
+
return Complete(
|
|
14
|
+
self.id, self.mdef, self.flown, self.direction,
|
|
15
|
+
self.manoeuvre, self.template, self.corrected,
|
|
16
|
+
self.corrected_template
|
|
17
|
+
)
|
|
18
|
+
|
|
11
19
|
@staticmethod
|
|
12
20
|
def from_dict(data:dict, fallback=True):
|
|
13
21
|
ca = Complete.from_dict(data, fallback)
|
|
@@ -22,6 +30,16 @@ class Scored(Complete):
|
|
|
22
30
|
else:
|
|
23
31
|
raise e
|
|
24
32
|
return ca
|
|
25
|
-
|
|
26
|
-
def
|
|
27
|
-
|
|
33
|
+
|
|
34
|
+
def to_mindict(self, sinfo: ScheduleInfo=None, full=False):
|
|
35
|
+
data = dict(
|
|
36
|
+
**super().to_mindict(sinfo, full),
|
|
37
|
+
scores=dict(
|
|
38
|
+
**self.scores.summary(),
|
|
39
|
+
total=self.scores.score(),
|
|
40
|
+
k=self.mdef.info.k
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return data
|
|
45
|
+
|
|
@@ -41,16 +41,15 @@ class ScheduleAnalysis(Collection):
|
|
|
41
41
|
|
|
42
42
|
return ScheduleAnalysis(
|
|
43
43
|
[analysis.Basic(
|
|
44
|
+
i,
|
|
44
45
|
mdef,
|
|
45
46
|
state.get_manoeuvre(mdef.uid),
|
|
46
|
-
direction
|
|
47
|
-
|
|
48
|
-
) for mdef in sdef],
|
|
47
|
+
direction
|
|
48
|
+
) for i, mdef in enumerate(sdef)],
|
|
49
49
|
info
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
def run_all(self) -> Self:
|
|
53
|
-
|
|
54
53
|
def parse_analyse_serialise(pad):
|
|
55
54
|
res = analysis.Basic.from_dict(pad).run_all()
|
|
56
55
|
logger.info(f'Completed {res.name}')
|
|
@@ -67,7 +66,6 @@ class ScheduleAnalysis(Collection):
|
|
|
67
66
|
|
|
68
67
|
def parse_analyse_serialise(mad):
|
|
69
68
|
an = analysis.Complete.from_dict(mad)
|
|
70
|
-
an.stage = analysis.AlinmentStage.SECONDARY
|
|
71
69
|
return an.run_all().to_dict()
|
|
72
70
|
|
|
73
71
|
logger.info(f'Starting {os.cpu_count()} alinment optimisation processes')
|