flightanalysis 0.2.13__tar.gz → 0.2.15__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.13 → flightanalysis-0.2.15}/PKG-INFO +3 -3
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/f3a_criteria_maker.py +12 -12
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/analysis/el_analysis.py +2 -2
- flightanalysis-0.2.15/flightanalysis/analysis/manoeuvre_analysis/__init__.py +14 -0
- flightanalysis-0.2.15/flightanalysis/analysis/manoeuvre_analysis/alignment.py +104 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/analysis/manoeuvre_analysis/analysis.py +8 -8
- flightanalysis-0.2.15/flightanalysis/analysis/manoeuvre_analysis/basic.py +131 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/analysis/manoeuvre_analysis/complete.py +9 -12
- flightanalysis-0.2.15/flightanalysis/analysis/manoeuvre_analysis/scored.py +50 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/analysis/sch_analysis.py +44 -52
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/__init__.py +1 -1
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/mandef.py +3 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/manparm.py +2 -2
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/scheddef.py +2 -2
- flightanalysis-0.2.15/flightanalysis/definition/scheduleinfo.py +72 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/element.py +6 -6
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/exponential.py +8 -6
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/f3a_criteria.py +13 -12
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/inter/combination.py +1 -1
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/inter/comparison.py +1 -1
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/intra/bounded.py +3 -3
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/intra/continuous.py +3 -3
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/intra/single.py +4 -5
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/downgrade.py +7 -12
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/measurement.py +3 -3
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/results.py +64 -18
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scripts/collect_scores.py +3 -3
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis.egg-info/PKG-INFO +3 -3
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis.egg-info/SOURCES.txt +2 -4
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis.egg-info/requires.txt +2 -2
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/requirements-dev.txt +1 -1
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/requirements.txt +1 -1
- flightanalysis-0.2.13/examples/scoring/temp.py +0 -24
- flightanalysis-0.2.13/flightanalysis/analysis/manoeuvre_analysis/__init__.py +0 -8
- flightanalysis-0.2.13/flightanalysis/analysis/manoeuvre_analysis/alignment.py +0 -81
- flightanalysis-0.2.13/flightanalysis/analysis/manoeuvre_analysis/basic.py +0 -86
- flightanalysis-0.2.13/flightanalysis/analysis/manoeuvre_analysis/scored.py +0 -27
- flightanalysis-0.2.13/flightanalysis/definition/scheduleinfo.py +0 -45
- flightanalysis-0.2.13/tests/test_schedule/test_element/test_split_optimiser.py +0 -15
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/.github/workflows/publish_pypi.yml +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/.gitignore +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/LICENSE +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/MANIFEST.in +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/README.md +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/data/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/data/manual_F3A_F23_22_04_28_00000231.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/data/manual_F3A_P23_22_05_31_00000350.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/data/manual_F3A_P23_23_08_11_00000094.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/judging.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/inter_analysis.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/intra_analysis.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/mans/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/mans/extract_mans.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/mans/tHat.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/examples/scoring/manoeuvres/positioning_analysis.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/analysis/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/IMAC_Unlimited2024_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/f3a_a25_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/f3a_f25_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/f3a_p23_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/f3a_p25_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/f3auk_clubman_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/data/f3auk_inter_schedule.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/builders/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/builders/elbuilders.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/builders/lines.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/builders/manbuilder.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/collectors.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/eldef.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/maninfo.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/manoption.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/operations/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/operations/funopp.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/operations/itemopp.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/operations/mathopp.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/definition/operations/operation.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/autorotation.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/line.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/loop.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/nose_drop.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/pitch_break.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/recovery.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/elements/stall_turn.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/manoeuvre.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/schedule.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/criteria.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/inter/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scoring/criteria/intra/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scripts/batch_analyse.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis/scripts/plot_scores.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis.egg-info/dependency_links.txt +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis.egg-info/entry_points.txt +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/flightanalysis.egg-info/top_level.txt +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/pyproject.toml +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/AMA_Intermediate2024.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/create_all.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/f3a_a25.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/f3a_f25.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/f3a_p23.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/f3a_p25.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/f3auk_clubman.py +0 -0
- /flightanalysis-0.2.13/scripts/f3auk_Intermediate.py → /flightanalysis-0.2.15/scripts/f3auk_intermediate.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/imac_sport2024.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/imac_unlim2024.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/make_manoeuvre.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/scripts/nsrca_inter2024.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/setup.cfg +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/EmailedBox.f3a +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/conftest.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/data/manual_F3A_P23.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/data/p23.BIN +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/data/p23_box.f3a +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/data/p23_fc.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/data/p23_flight.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_criiteria.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_data.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_definition/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_definition/test_definition_eldef.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_definition/test_definition_manparm.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_definition/test_definition_mpopp.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_definition/test_schedule_definition.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_definition/test_schedule_definition_maninfo.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/__init__.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/loop_analysis.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/p23_th_e0.csv +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/p23_th_e0.json +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/p23_th_e0_template.csv +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element_line.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element_loop.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element_nose_drop.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element_pitch_break.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element_recovery.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_element/test_schedule_element_stallturn.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/tests/test_schedule/test_measurement.py +0 -0
- {flightanalysis-0.2.13 → flightanalysis-0.2.15}/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.15
|
|
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.14
|
|
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.14; extra == "dev"
|
|
30
30
|
Requires-Dist: ardupilot_log_reader>=0.3.1; extra == "dev"
|
|
31
31
|
Requires-Dist: pymavlink; extra == "dev"
|
|
32
32
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
from flightanalysis.scoring.criteria import Single, Exponential, ContAbs, ContRat, InsideBound, MaxBound, Comparison, free, OutsideBound
|
|
2
2
|
import numpy as np
|
|
3
|
-
|
|
3
|
+
|
|
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]),
|
|
@@ -25,10 +25,10 @@ f3a=dict(
|
|
|
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,2], [1
|
|
29
|
-
speed=Comparison(Exponential.fit_points([1,
|
|
30
|
-
roll_rate=Comparison(Exponential.fit_points([1,
|
|
31
|
-
length=Comparison(Exponential.fit_points([1,2], [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
|
)
|
|
@@ -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,104 @@
|
|
|
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
|
+
def fcj_results(self):
|
|
97
|
+
df = self.flown.label_ranges('element').iloc[:,:3]
|
|
98
|
+
df.columns = ['name', 'start', 'stop']
|
|
99
|
+
return dict(
|
|
100
|
+
els=df.to_dict('records')
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
from .complete import Complete # noqa: E402
|
|
104
|
+
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
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from .complete import Complete
|
|
3
|
+
from flightanalysis.scoring import ManoeuvreResults
|
|
4
|
+
from flightanalysis.definition.scheduleinfo import ScheduleInfo
|
|
5
|
+
from loguru import logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Scored(Complete):
|
|
10
|
+
scores: ManoeuvreResults
|
|
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
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def from_dict(data:dict, fallback=True):
|
|
21
|
+
ca = Complete.from_dict(data, fallback)
|
|
22
|
+
try:
|
|
23
|
+
ca = Scored(
|
|
24
|
+
**ca.__dict__,
|
|
25
|
+
scores=ManoeuvreResults.from_dict(data["scores"])
|
|
26
|
+
)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
if fallback:
|
|
29
|
+
logger.debug(f"Failed to read scores, {repr(e)}")
|
|
30
|
+
else:
|
|
31
|
+
raise e
|
|
32
|
+
return ca
|
|
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
|
+
|
|
46
|
+
def fcj_results(self):
|
|
47
|
+
return dict(
|
|
48
|
+
**super().fcj_results(),
|
|
49
|
+
results=self.scores.fcj_results()
|
|
50
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from typing import Self, Union
|
|
3
|
-
from json import load
|
|
3
|
+
from json import load, dump
|
|
4
4
|
from flightdata import Flight, State, Origin, Collection
|
|
5
5
|
from flightanalysis.definition import SchedDef, ScheduleInfo
|
|
6
6
|
from . import manoeuvre_analysis as analysis
|
|
@@ -9,7 +9,7 @@ from joblib import Parallel, delayed
|
|
|
9
9
|
import os
|
|
10
10
|
import pandas as pd
|
|
11
11
|
from importlib.metadata import version
|
|
12
|
-
import
|
|
12
|
+
from packaging import version as pkgversion
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class ScheduleAnalysis(Collection):
|
|
@@ -22,10 +22,8 @@ class ScheduleAnalysis(Collection):
|
|
|
22
22
|
|
|
23
23
|
@staticmethod
|
|
24
24
|
def from_fcj(file: Union[str, dict], info: ScheduleInfo=None) -> ScheduleAnalysis:
|
|
25
|
-
if isinstance(file, str)
|
|
26
|
-
|
|
27
|
-
else:
|
|
28
|
-
data = file
|
|
25
|
+
data = load(open(file, 'r')) if isinstance(file, str) else file
|
|
26
|
+
|
|
29
27
|
flight = Flight.from_fc_json(data)
|
|
30
28
|
|
|
31
29
|
if info is None:
|
|
@@ -33,26 +31,50 @@ class ScheduleAnalysis(Collection):
|
|
|
33
31
|
|
|
34
32
|
sdef = SchedDef.load(info)
|
|
35
33
|
box = Origin.from_fcjson_parmameters(data["parameters"])
|
|
36
|
-
state = State.from_flight(flight, box).splitter_labels(
|
|
37
|
-
data["mans"],
|
|
38
|
-
sdef.uids
|
|
39
|
-
)
|
|
34
|
+
state = State.from_flight(flight, box).splitter_labels(data["mans"],sdef.uids)
|
|
40
35
|
direction = -state.get_manoeuvre(1)[0].direction()[0]
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
[
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
if 'fcs_scores' in data:
|
|
38
|
+
versions = [pkgversion.parse(res['fa_version']) for res in data['fcs_scores']]
|
|
39
|
+
ilatest = versions.index(max(versions))
|
|
40
|
+
|
|
41
|
+
mas = []
|
|
42
|
+
for i, mdef in enumerate(sdef):
|
|
43
|
+
st = state.get_manoeuvre(mdef.uid)
|
|
44
|
+
|
|
45
|
+
if 'fcs_scores' in data and len(data['fcs_scores']) > 0:
|
|
46
|
+
df = pd.DataFrame(data['fcs_scores'][ilatest]['manresults'][i+1]['els'])
|
|
47
|
+
st = st.splitter_labels(df.to_dict('records'), target_col='element')
|
|
48
|
+
|
|
49
|
+
mas.append(analysis.Basic(i, mdef, st, direction).proceed())
|
|
50
|
+
|
|
51
|
+
return ScheduleAnalysis(mas,info)
|
|
51
52
|
|
|
52
|
-
def
|
|
53
|
+
def append_scores_to_fcj(self, file: Union[str, dict]) -> dict:
|
|
54
|
+
data = load(open(file, 'r')) if isinstance(file, str) else file
|
|
55
|
+
|
|
56
|
+
new_results = dict(
|
|
57
|
+
fa_version = version('flightanalysis'),
|
|
58
|
+
manresults = [None] + \
|
|
59
|
+
[man.fcj_results() if hasattr(man, 'fcj_results') else None for man in self]
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if 'fcs_scores' not in data:
|
|
63
|
+
data['fcs_scores'] = []
|
|
53
64
|
|
|
65
|
+
for res in data['fcs_scores']:
|
|
66
|
+
if res['fa_version'] == new_results['fa_version']:
|
|
67
|
+
res['manresults'] = new_results['manresults']
|
|
68
|
+
break
|
|
69
|
+
else:
|
|
70
|
+
data['fcs_scores'].append(new_results)
|
|
71
|
+
|
|
72
|
+
return data
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def run_all(self) -> Self:
|
|
54
76
|
def parse_analyse_serialise(pad):
|
|
55
|
-
res = analysis.
|
|
77
|
+
res = analysis.parse_dict(pad).run_all()
|
|
56
78
|
logger.info(f'Completed {res.name}')
|
|
57
79
|
return res.to_dict()
|
|
58
80
|
|
|
@@ -67,7 +89,6 @@ class ScheduleAnalysis(Collection):
|
|
|
67
89
|
|
|
68
90
|
def parse_analyse_serialise(mad):
|
|
69
91
|
an = analysis.Complete.from_dict(mad)
|
|
70
|
-
an.stage = analysis.AlinmentStage.SECONDARY
|
|
71
92
|
return an.run_all().to_dict()
|
|
72
93
|
|
|
73
94
|
logger.info(f'Starting {os.cpu_count()} alinment optimisation processes')
|
|
@@ -75,23 +96,6 @@ class ScheduleAnalysis(Collection):
|
|
|
75
96
|
madicts = Parallel(n_jobs=os.cpu_count())(delayed(parse_analyse_serialise)(mad) for mad in inmadicts)
|
|
76
97
|
return ScheduleAnalysis([analysis.Scored.from_dict(mad) for mad in madicts], self.sinfo)
|
|
77
98
|
|
|
78
|
-
@staticmethod
|
|
79
|
-
def from_fcscore(file: Union[str, dict], fallback=True) -> ScheduleAnalysis:
|
|
80
|
-
if isinstance(file, str) or isinstance(file, os.PathLike):
|
|
81
|
-
data = load(open(file, 'r'))
|
|
82
|
-
else:
|
|
83
|
-
data = file
|
|
84
|
-
sinfo = ScheduleInfo(**data['sinfo'])
|
|
85
|
-
sdef = SchedDef.load(sinfo)
|
|
86
|
-
|
|
87
|
-
mas = []
|
|
88
|
-
for mdef in sdef:
|
|
89
|
-
mas.append(analysis.Scored.from_dict(
|
|
90
|
-
data['data'][mdef.info.short_name],
|
|
91
|
-
fallback
|
|
92
|
-
))
|
|
93
|
-
|
|
94
|
-
return ScheduleAnalysis(mas, sinfo)
|
|
95
99
|
|
|
96
100
|
def scores(self):
|
|
97
101
|
scores = {}
|
|
@@ -103,16 +107,4 @@ class ScheduleAnalysis(Collection):
|
|
|
103
107
|
def summarydf(self):
|
|
104
108
|
return pd.DataFrame([ma.scores.summary() if hasattr(ma, 'scores') else {} for ma in self])
|
|
105
109
|
|
|
106
|
-
|
|
107
|
-
total, scores = self.scores()
|
|
108
|
-
|
|
109
|
-
odata = dict(
|
|
110
|
-
name = name,
|
|
111
|
-
client_version = 'Py',
|
|
112
|
-
server_version = version('flightanalysis'),
|
|
113
|
-
sinfo = self.sinfo.__dict__,
|
|
114
|
-
score = total,
|
|
115
|
-
manscores = scores,
|
|
116
|
-
data = self.to_dict()
|
|
117
|
-
)
|
|
118
|
-
return odata
|
|
110
|
+
|
|
@@ -12,6 +12,6 @@ from .manparm import ManParm, ManParms, DummyMPs
|
|
|
12
12
|
from .eldef import ElDef, ElDefs
|
|
13
13
|
from .mandef import ManDef
|
|
14
14
|
from .manoption import ManOption
|
|
15
|
-
from .scheduleinfo import ScheduleInfo,
|
|
15
|
+
from .scheduleinfo import ScheduleInfo, schedule_library
|
|
16
16
|
from .scheddef import SchedDef
|
|
17
17
|
from .builders.manbuilder import ManBuilder, f3amb, MBTags, centred, imacmb, r, c45, dp
|
|
@@ -34,6 +34,9 @@ class ManDef:
|
|
|
34
34
|
self.mps: ManParms = ManParms.create_defaults_f3a() if mps is None else mps
|
|
35
35
|
self.eds: ElDefs = ElDefs() if eds is None else eds
|
|
36
36
|
|
|
37
|
+
def __repr__(self):
|
|
38
|
+
return f"ManDef({self.info.name})"
|
|
39
|
+
|
|
37
40
|
@property
|
|
38
41
|
def uid(self):
|
|
39
42
|
return self.info.short_name
|
|
@@ -25,7 +25,7 @@ class ManParm(Opp):
|
|
|
25
25
|
|
|
26
26
|
"""
|
|
27
27
|
criteria: Criteria
|
|
28
|
-
defaul:
|
|
28
|
+
defaul:Number=None
|
|
29
29
|
collectors:Collectors=field(default_factory=lambda : Collectors())
|
|
30
30
|
|
|
31
31
|
|
|
@@ -78,7 +78,7 @@ class ManParm(Opp):
|
|
|
78
78
|
[c(els) for c in self.collectors],
|
|
79
79
|
self.defaul,
|
|
80
80
|
direction,
|
|
81
|
-
[vis[0]] + [max(va, vb) for va, vb in zip(vis[:-1], vis[1:])],
|
|
81
|
+
np.array([vis[0]] + [max(va, vb) for va, vb in zip(vis[:-1], vis[1:])]),
|
|
82
82
|
[str(c) for c in self.collectors]
|
|
83
83
|
)
|
|
84
84
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from . import ManDef, ManInfo, ManOption, ScheduleInfo
|
|
1
|
+
from . import ManDef, ManInfo, ManOption, ScheduleInfo
|
|
2
2
|
from flightdata import State
|
|
3
3
|
from typing import Tuple, Union, Self
|
|
4
4
|
from geometry import Transformation
|
|
@@ -95,7 +95,7 @@ class SchedDef(Collection):
|
|
|
95
95
|
fcj = self.label_exit_lines(template).create_fc_json(
|
|
96
96
|
[0] + [man.info.k for man in self] + [0],
|
|
97
97
|
sname,
|
|
98
|
-
|
|
98
|
+
kind.lower()
|
|
99
99
|
)
|
|
100
100
|
|
|
101
101
|
with open(path, 'w') as f:
|