nrl-tracker 0.22.2__py3-none-any.whl → 0.22.4__py3-none-any.whl

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 (69) hide show
  1. {nrl_tracker-0.22.2.dist-info → nrl_tracker-0.22.4.dist-info}/METADATA +1 -1
  2. {nrl_tracker-0.22.2.dist-info → nrl_tracker-0.22.4.dist-info}/RECORD +69 -69
  3. pytcl/__init__.py +1 -1
  4. pytcl/assignment_algorithms/gating.py +3 -3
  5. pytcl/assignment_algorithms/jpda.py +12 -4
  6. pytcl/assignment_algorithms/two_dimensional/kbest.py +3 -1
  7. pytcl/astronomical/ephemerides.py +17 -9
  8. pytcl/astronomical/lambert.py +14 -4
  9. pytcl/astronomical/orbital_mechanics.py +3 -1
  10. pytcl/astronomical/reference_frames.py +3 -1
  11. pytcl/astronomical/relativity.py +8 -2
  12. pytcl/atmosphere/models.py +3 -1
  13. pytcl/clustering/gaussian_mixture.py +8 -4
  14. pytcl/clustering/hierarchical.py +5 -1
  15. pytcl/clustering/kmeans.py +3 -1
  16. pytcl/containers/cluster_set.py +9 -3
  17. pytcl/containers/measurement_set.py +6 -2
  18. pytcl/containers/rtree.py +5 -2
  19. pytcl/coordinate_systems/conversions/geodetic.py +15 -3
  20. pytcl/coordinate_systems/projections/projections.py +38 -11
  21. pytcl/coordinate_systems/rotations/rotations.py +3 -1
  22. pytcl/core/array_utils.py +4 -1
  23. pytcl/core/constants.py +3 -1
  24. pytcl/core/validation.py +17 -6
  25. pytcl/dynamic_estimation/imm.py +9 -3
  26. pytcl/dynamic_estimation/kalman/square_root.py +6 -2
  27. pytcl/dynamic_estimation/particle_filters/bootstrap.py +6 -2
  28. pytcl/dynamic_estimation/smoothers.py +3 -1
  29. pytcl/dynamic_models/process_noise/polynomial.py +6 -2
  30. pytcl/gravity/clenshaw.py +6 -2
  31. pytcl/gravity/egm.py +3 -1
  32. pytcl/gravity/models.py +3 -1
  33. pytcl/gravity/spherical_harmonics.py +10 -4
  34. pytcl/gravity/tides.py +16 -7
  35. pytcl/magnetism/emm.py +12 -3
  36. pytcl/magnetism/wmm.py +9 -2
  37. pytcl/mathematical_functions/basic_matrix/decompositions.py +3 -1
  38. pytcl/mathematical_functions/combinatorics/combinatorics.py +3 -1
  39. pytcl/mathematical_functions/geometry/geometry.py +12 -4
  40. pytcl/mathematical_functions/interpolation/interpolation.py +3 -1
  41. pytcl/mathematical_functions/signal_processing/detection.py +6 -3
  42. pytcl/mathematical_functions/signal_processing/filters.py +6 -2
  43. pytcl/mathematical_functions/signal_processing/matched_filter.py +4 -2
  44. pytcl/mathematical_functions/special_functions/elliptic.py +3 -1
  45. pytcl/mathematical_functions/special_functions/gamma_functions.py +3 -1
  46. pytcl/mathematical_functions/special_functions/lambert_w.py +3 -1
  47. pytcl/mathematical_functions/statistics/distributions.py +36 -12
  48. pytcl/mathematical_functions/statistics/estimators.py +3 -1
  49. pytcl/mathematical_functions/transforms/stft.py +9 -3
  50. pytcl/mathematical_functions/transforms/wavelets.py +18 -6
  51. pytcl/navigation/geodesy.py +31 -9
  52. pytcl/navigation/great_circle.py +12 -4
  53. pytcl/navigation/ins.py +8 -2
  54. pytcl/navigation/ins_gnss.py +25 -7
  55. pytcl/navigation/rhumb.py +10 -3
  56. pytcl/performance_evaluation/track_metrics.py +3 -1
  57. pytcl/plotting/coordinates.py +17 -5
  58. pytcl/plotting/metrics.py +9 -3
  59. pytcl/plotting/tracks.py +11 -3
  60. pytcl/static_estimation/least_squares.py +2 -1
  61. pytcl/static_estimation/maximum_likelihood.py +3 -3
  62. pytcl/terrain/dem.py +8 -2
  63. pytcl/terrain/loaders.py +13 -5
  64. pytcl/terrain/visibility.py +7 -2
  65. pytcl/trackers/hypothesis.py +7 -2
  66. pytcl/trackers/mht.py +15 -5
  67. {nrl_tracker-0.22.2.dist-info → nrl_tracker-0.22.4.dist-info}/LICENSE +0 -0
  68. {nrl_tracker-0.22.2.dist-info → nrl_tracker-0.22.4.dist-info}/WHEEL +0 -0
  69. {nrl_tracker-0.22.2.dist-info → nrl_tracker-0.22.4.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nrl-tracker
3
- Version: 0.22.2
3
+ Version: 0.22.4
4
4
  Summary: Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms
5
5
  Author: Original: David F. Crouse, Naval Research Laboratory
6
6
  Maintainer: Python Port Contributors
@@ -1,62 +1,62 @@
1
- pytcl/__init__.py,sha256=wsoRU91PW_MW6Xa1ssvY8wOik6jvivqV0KZxHLwrbqY,1894
1
+ pytcl/__init__.py,sha256=uwpLiSYxFSvCeykvejvHVAGffLi6OxFvWNGHWqN3p4w,1894
2
2
  pytcl/assignment_algorithms/__init__.py,sha256=f9V-TkEVmiKYYyth4PTpDfJvA7yYV_ys6Zix-QwWIYY,2136
3
3
  pytcl/assignment_algorithms/data_association.py,sha256=tsRxWJZk9aAPmE99BKXGouEpFfZrjPjb4HXvgxFUHhU,11405
4
- pytcl/assignment_algorithms/gating.py,sha256=wm4NO7hR7YPgaovX6eiJ2kHmXORHIpFqYGC0sTis_DU,10815
5
- pytcl/assignment_algorithms/jpda.py,sha256=-hQNxCGYE5SmhVw0JAX81SFqB0ljO3RYdutmpkV00m4,19492
4
+ pytcl/assignment_algorithms/gating.py,sha256=fN_oAOkv7nYYOWE1oPOLrcCn3xEpKdMVlFSbRMAURxY,10815
5
+ pytcl/assignment_algorithms/jpda.py,sha256=Hv55j3J9qVwzlUfWdXdSasodTyB1ZKdgEpo5dBh95O8,19582
6
6
  pytcl/assignment_algorithms/three_dimensional/__init__.py,sha256=1Q40OUlUQoo7YKEucwdrSNo3D4A0Zibvkr8z4TpueBg,526
7
7
  pytcl/assignment_algorithms/three_dimensional/assignment.py,sha256=9BJhwlYu3JJ0kZ9sRyKKfpdvQdL4WYYHCtLbvaWycBw,19212
8
8
  pytcl/assignment_algorithms/two_dimensional/__init__.py,sha256=4Evsn__9hTfI2i8m8Ngl-Zy0Fa2OydKmDKlZlH6jaao,778
9
9
  pytcl/assignment_algorithms/two_dimensional/assignment.py,sha256=eh87MBb-uiUSI1MXj4HrreRKB6Z8rxAyDkNQ8-u4SbM,11848
10
- pytcl/assignment_algorithms/two_dimensional/kbest.py,sha256=iDtLbKr0eh6Gd5wuyKrjBm2Qr3DeH2OOxtzf9eSR76E,17262
10
+ pytcl/assignment_algorithms/two_dimensional/kbest.py,sha256=yiTToLuP7xWxQlQ8E-fpgXg-5iu0nnXcJXStjUB0nOE,17284
11
11
  pytcl/astronomical/__init__.py,sha256=Dtf6hqXyKyFL5VP-sqI7m2QGK6l-rqRGxVIhgDuYHOg,7182
12
- pytcl/astronomical/ephemerides.py,sha256=RU5Mk3tj10LoL1eOY3XiGsKwuPzHJdypORf3jU6eMZk,16397
13
- pytcl/astronomical/lambert.py,sha256=iMxqG7cFdfcN5AOI-9FF6t1Qgj_443_c0BwAwlaPqm8,15493
14
- pytcl/astronomical/orbital_mechanics.py,sha256=f3Vqn2bWzxbMQO60SlHXf3515j3LSA2fd_MHZE5z5h0,19951
15
- pytcl/astronomical/reference_frames.py,sha256=R_bdfXYYoeNjgYU1deIynB0IBjpy4xc9Tlq8Q4W9FKc,15783
16
- pytcl/astronomical/relativity.py,sha256=cqMR0oZJXNXYiEwnC8QrABkAAcu4c8MLoX74iNpZwfM,15418
12
+ pytcl/astronomical/ephemerides.py,sha256=x2500S0rF1D2h0dMR_2BnZaChbBZTooHLdrevttxlAc,16471
13
+ pytcl/astronomical/lambert.py,sha256=Lc8FT1JmpI9WSXsG2s5vIRkSoBSV7r5hd3o2bGh2Ojo,15607
14
+ pytcl/astronomical/orbital_mechanics.py,sha256=8GssRanwTowCl6PJYqmB_SDnNznLUq5gkPa3j6iEo3U,19965
15
+ pytcl/astronomical/reference_frames.py,sha256=GDak7af6BqOwGnCUxkvFoeqd_H2TMubdjG9lGPCoUB4,15799
16
+ pytcl/astronomical/relativity.py,sha256=YPsXLD-VRh-nqs1laC-wKpRO00fflm4GkyLhojPydbo,15441
17
17
  pytcl/astronomical/time_systems.py,sha256=Jg0Zaq60hc4Ts1aQtb5bK4KSZhz-uQse8gYC89Y0-TA,15243
18
18
  pytcl/atmosphere/__init__.py,sha256=TTVz4hAM48Xd3jr6GKrR2GAABpx2z0aWvtzb9uIQiHk,737
19
- pytcl/atmosphere/models.py,sha256=hOfUjM4jNLLfkzd_9J_utR04tkwyBT8KsyjVMrVQJ6k,9570
19
+ pytcl/atmosphere/models.py,sha256=pMLv8D7qoFqLZrlbTHLJJULOdDdhPskJ1m7KVKLV63E,9584
20
20
  pytcl/clustering/__init__.py,sha256=bYdhC_XJEt6KUUni9bIPxaddXNEGmIJQvGkA14rK4J8,1697
21
21
  pytcl/clustering/dbscan.py,sha256=PS6QlOwHFerbZNEb3zcNhN4oNQpgOOw5y0WskQzyKIo,7364
22
- pytcl/clustering/gaussian_mixture.py,sha256=5ucepT-vNcs1cOimykOWGkhO1Q-UgfRbUJ19H585Qa0,22813
23
- pytcl/clustering/hierarchical.py,sha256=-ZEEDSJ4RBMyXOgHD7CZJmIHS8DbS80pagoko9asBIo,14156
24
- pytcl/clustering/kmeans.py,sha256=84n4v04m7PiRehdj3n0mPisou1eM6Z9-p8ztbDTyoWQ,10683
22
+ pytcl/clustering/gaussian_mixture.py,sha256=U5U0Z46tZWdTLNdNNNJenoeviwZRAOvexVFYVLt4QMc,22865
23
+ pytcl/clustering/hierarchical.py,sha256=Hw9BFCn5df_ATpJX63R3B31MHz27ztCw9ihMDIlI688,14202
24
+ pytcl/clustering/kmeans.py,sha256=250FQyDol5S_Y4TznNn9cEuE96UDp7wvEkPZJ1DLul8,10697
25
25
  pytcl/containers/__init__.py,sha256=-hnqSMKlMugj2RRssx3p_48HWnfqLSrF6BCChsinCOg,1627
26
- pytcl/containers/cluster_set.py,sha256=t-n5Fn7KnIMyeIA_xmYS-LisKvzG0e1SCyVLZIuKnIY,22657
26
+ pytcl/containers/cluster_set.py,sha256=y36D5TNzvCN6xjg6taP2SD_MC-O5iLq9ncBlHsQ5IBs,22723
27
27
  pytcl/containers/covertree.py,sha256=1JWqXxoUFLxuMnjwj2qf0iz2uPzdujQYdwJW3l5qsOs,13282
28
28
  pytcl/containers/kd_tree.py,sha256=pxRC62RYkqz9zXPz6c1fubmtPPBDLYA5I9AXMAoGanw,16348
29
- pytcl/containers/measurement_set.py,sha256=EqijbnQZzF3fwNT9An7KVXJTvT4m_kjQDnQeEkxlLwM,12618
30
- pytcl/containers/rtree.py,sha256=5jPy8NxZnmmpTgyRScwwj4L7U5Vq4NfChKotdzVcW6w,15400
29
+ pytcl/containers/measurement_set.py,sha256=87AbdoZIUspn1yJsiMpyQ5LoEVcerUnXefXGGPtFTJg,12654
30
+ pytcl/containers/rtree.py,sha256=gv2EztvPnaAXEa6OoFnOYBY1MfTwjNMYh_BCiIomHJk,15450
31
31
  pytcl/containers/track_list.py,sha256=6q9Qgcwm-8H_JqtOCsMssF27av4XaSkhfDl-MWb1ABc,12520
32
32
  pytcl/containers/vptree.py,sha256=6fBNHrezkmj7L2nH0-2bONRN92f5cZAhS-5vaI1JZnA,8814
33
33
  pytcl/coordinate_systems/__init__.py,sha256=jwYhu_-9AvOeP9WLG9PYtyDwfe0GjxNZ9-xCqiLymW4,3909
34
34
  pytcl/coordinate_systems/conversions/__init__.py,sha256=PkNevB78vBw0BkalydJBbQO91AyiMJxKRrgJNt4HsYc,1100
35
- pytcl/coordinate_systems/conversions/geodetic.py,sha256=HrSacirnucwrviDjX5KuqxyFlFqgnGpFWFux2XBhdBM,15635
35
+ pytcl/coordinate_systems/conversions/geodetic.py,sha256=qQSnJRt3jg5KiostvzyslPIbfn-1xBluo1r12oavWTQ,15737
36
36
  pytcl/coordinate_systems/conversions/spherical.py,sha256=q7k9l5mJbVzVdNj9Gcq4ibFxax8z_mVpJfITRBzx630,10812
37
37
  pytcl/coordinate_systems/jacobians/__init__.py,sha256=CRGB8GzvGT_sr4Ynm51S7gSX8grqt1pO1Pq1MWmHPTs,890
38
38
  pytcl/coordinate_systems/jacobians/jacobians.py,sha256=1KufIoktm9mXLO34X9KjysdMpu7itGwfssRyAdkTTN8,11703
39
39
  pytcl/coordinate_systems/projections/__init__.py,sha256=eWNtezPO62IUWxv7jymenIXsWS1MC66Q12u5KRUnqNE,2503
40
- pytcl/coordinate_systems/projections/projections.py,sha256=cqYd0zb_6DZFQfGQ8IAzBoAhKpbkxw_1MLt5JiT8TEI,32877
40
+ pytcl/coordinate_systems/projections/projections.py,sha256=yODS7n1gA4jsCJcU8EaeclHrbUBsZI9O2M_XJs2HOXs,33169
41
41
  pytcl/coordinate_systems/rotations/__init__.py,sha256=nqAz4iJd2hEOX_r7Tz4cE524sShyxdbtcQ5m56RrDLg,1047
42
- pytcl/coordinate_systems/rotations/rotations.py,sha256=i5OtHxCLwq9k4gBIMb_n8HWq5EfMyyq3znlTenKjus0,18213
42
+ pytcl/coordinate_systems/rotations/rotations.py,sha256=FAYHkShQcpOlWJjtvLfNvtCx-a56pr-cbpo0QjC5W9U,18227
43
43
  pytcl/core/__init__.py,sha256=H5JJPS-43DfF1UG7fSgV-VMTcZFBO8GuzDW1lM_1sm4,1152
44
- pytcl/core/array_utils.py,sha256=kLZII_6Yk2C4Gin6i_PFiklkJ_P_OyHDhVG7EN2iTLg,13971
45
- pytcl/core/constants.py,sha256=v--FHNYH441t2tfZeNpPbTxZDqiyql6ehA9Z3iTsnxw,8687
46
- pytcl/core/validation.py,sha256=9O7rs8bZP9gFT98AD8S-chPcx5uZOh7b_KTBeDGNzFg,12931
44
+ pytcl/core/array_utils.py,sha256=SsgEiAoRCWxAVKq1aa5-nPdOi-2AB6XNObu0IaGClUk,13983
45
+ pytcl/core/constants.py,sha256=lZVDK5zsSR02_4b2Nqx9KDtZT9QaYhkZ9wuoODbifd4,8693
46
+ pytcl/core/validation.py,sha256=WRlzMlUihtqc3XZoWOTFK0sBAZVDIwTMGCiWcX5OZVY,13093
47
47
  pytcl/dynamic_estimation/__init__.py,sha256=jA5FF6kHYklY5LMOfZaKcCeiPTpVe8vHIMp3ECDOmsc,4582
48
- pytcl/dynamic_estimation/imm.py,sha256=6Skq7HOABQ9XCTM8lEHLqBp_OqDm7srl_hVuYCp4ZPw,22009
48
+ pytcl/dynamic_estimation/imm.py,sha256=IbKmouUiyzaYJbhWty63r3n_xV8thD-wd0qgZP1SxOI,22067
49
49
  pytcl/dynamic_estimation/information_filter.py,sha256=x7iQwO_iJT1dCSvDws5LqD3yAtjw9QVGUfMPcXn1IA4,17349
50
- pytcl/dynamic_estimation/smoothers.py,sha256=NlQ3aCLRGZE5O_pJn0at6xyK1TNf8-KlSYYZhSrnWIw,18900
50
+ pytcl/dynamic_estimation/smoothers.py,sha256=x2j-nR--EI5JNZvMywPeDHcrfW8b5PYK0DCU4Rmig_g,18914
51
51
  pytcl/dynamic_estimation/batch_estimation/__init__.py,sha256=JQ0s76Enov5a7plA4EnUua4t-7etikQrwr5z4WIjUeo,46
52
52
  pytcl/dynamic_estimation/kalman/__init__.py,sha256=yoFLj0n-NRkdZnRVL-BkHBlATk8pfZEVlsY3BhSYgKc,2387
53
53
  pytcl/dynamic_estimation/kalman/extended.py,sha256=51uhCqkZmErCx6MBfMq8eIQW8bD7n34zCe4v4dxNiMQ,10384
54
54
  pytcl/dynamic_estimation/kalman/linear.py,sha256=1Zgg9gZya0Vxs9im7sPUqLj0Luo463vS-RSa6GCReFI,12248
55
- pytcl/dynamic_estimation/kalman/square_root.py,sha256=jUsyfX9JGRUWiSZMt1JfSiIbnM37FB5kID0yMNnDJ_k,26871
55
+ pytcl/dynamic_estimation/kalman/square_root.py,sha256=Hw1F4_Zc7IA6Mt1WCkjx1UuLAUmNhM5vPLvueb7oRSA,26931
56
56
  pytcl/dynamic_estimation/kalman/unscented.py,sha256=RDK6USkko9lj1K4-WYydh3_8GMZNng_PJVjfc-c_OwM,15427
57
57
  pytcl/dynamic_estimation/measurement_update/__init__.py,sha256=8rlyJwVpxf0fZj-AFo1hlewvryZRhUzcy3F8uMe6I8c,48
58
58
  pytcl/dynamic_estimation/particle_filters/__init__.py,sha256=-DRF5rVF2749suLlArmkTvVkqeMcV_mIx0eLeTj6wNU,906
59
- pytcl/dynamic_estimation/particle_filters/bootstrap.py,sha256=QdqQME3ye5qCjoyJEbGfzI9r80GT_NLSj1pldZnmziw,13343
59
+ pytcl/dynamic_estimation/particle_filters/bootstrap.py,sha256=FcF4W_NM5ZqJnw5fq4rq6fLY9X1r4uFJOiAX9a-NGG8,13371
60
60
  pytcl/dynamic_models/__init__.py,sha256=Cd8MyyYuB8gMnepkPA-HSwTaKFPThnqoKOhdjVOsXWg,2783
61
61
  pytcl/dynamic_models/continuous_time/__init__.py,sha256=dAkfEddLkfMvDalK9v2GRBvaZV1KgqYpFBLOnoiFClw,1023
62
62
  pytcl/dynamic_models/continuous_time/dynamics.py,sha256=CDwqn-66eUwXA5xfIjaG6A4EDBqtOyQ3aWarJr9QH4g,12858
@@ -66,85 +66,85 @@ pytcl/dynamic_models/discrete_time/polynomial.py,sha256=zv5V-AbuaXlIj36n-YkOEyC7
66
66
  pytcl/dynamic_models/discrete_time/singer.py,sha256=wZS3Nad-YyPZp8Mle8Sf5GgW0-t4TxMRcnbc42HtQnA,3861
67
67
  pytcl/dynamic_models/process_noise/__init__.py,sha256=ZRYgV40qmBkPwU3yTbIMvxorr4nVz0_FEP2oCeVjXoM,933
68
68
  pytcl/dynamic_models/process_noise/coordinated_turn.py,sha256=w7bHUImLPL5m3KYenfNgAnHPCRtAyYESbsFc6lQKXRg,4768
69
- pytcl/dynamic_models/process_noise/polynomial.py,sha256=Rb7LITSZ1kbOnd0Q8TWRdUR_4sl9RCqfcsf0OawJl9U,7574
69
+ pytcl/dynamic_models/process_noise/polynomial.py,sha256=natfpsdN3qM9VzPeXF_nBpsbRI74S1WkkRCaaem6EQo,7620
70
70
  pytcl/dynamic_models/process_noise/singer.py,sha256=lsJDT6xOvcS_qQKFtgHX0L7Ukpy4D7HgvPT8Q3I0ibU,3901
71
71
  pytcl/gravity/__init__.py,sha256=5xNdQSrrkt7-1-JPOYqR38CqvNJ7qKlPyMK36DGm6-I,3693
72
- pytcl/gravity/clenshaw.py,sha256=k201ZPG-sOgCnLFP3Phe-N45V9bUYgiAOUyxyJSrGQA,15320
73
- pytcl/gravity/egm.py,sha256=uFRXsDAv_emZRs5dizbNTnyeW1cKiPag6iwISrbW57k,18061
74
- pytcl/gravity/models.py,sha256=Vws1dZPt0lqXnF12Y1PZ-YUd3onXMHI8TLxSJrapxxw,11145
75
- pytcl/gravity/spherical_harmonics.py,sha256=Q7I1w3gAcDM7rhdBO_4dG0Pnx9hiUQF-n65nsqWw5Ds,14588
76
- pytcl/gravity/tides.py,sha256=RpDM5hyKe7S3sjwgxQpnVK4bYIL38Rsgo9EslZMuHSU,27663
72
+ pytcl/gravity/clenshaw.py,sha256=1BdxzU8IfGGd68H_U35soIJkiOHphY35e9mLElhPTOg,15364
73
+ pytcl/gravity/egm.py,sha256=QTRuvCiMjuNQdZF163OGwjxuivpGu2dB6E0zQLbKPP8,18083
74
+ pytcl/gravity/models.py,sha256=rdY3Do4M1eRFO74gu3xy-bBn7tox3zM49wYbfnsIQWw,11159
75
+ pytcl/gravity/spherical_harmonics.py,sha256=uZasz-w2K16sWT6xrNIPyTEP6MSlMQSe_BCWpXhRkWY,14722
76
+ pytcl/gravity/tides.py,sha256=hef_BGewFGD7dJwg0t09Z6tfWLco_avATLuu66rnTpI,27733
77
77
  pytcl/magnetism/__init__.py,sha256=hE2BvberFSmimYuuwCYJ0g7ByxJAdj844vZJNkEotws,2502
78
- pytcl/magnetism/emm.py,sha256=NHTuHLwuMOp3Tw0RoizTa-F00WCZxT2BGYseTCisfFc,22130
78
+ pytcl/magnetism/emm.py,sha256=5Jwl99wvdKYtx1-3LBB7x-w5KT-fqLiRg7uBW0Ai_Gw,22292
79
79
  pytcl/magnetism/igrf.py,sha256=3g0PsH8IdbwQQS28OR5XWD-g-QxvfUva7jOkKToxndQ,13384
80
- pytcl/magnetism/wmm.py,sha256=6LgYkis-PaNVmgRQvYyCkK-VZT_yzs4hSdCHymRLndM,15851
80
+ pytcl/magnetism/wmm.py,sha256=p0H7Eo02iB6nEMvGyvjsrAWOSKrIye6PGwQtNKfHaNw,15999
81
81
  pytcl/mathematical_functions/__init__.py,sha256=zeJ1ffRRl83k2NHn3HTn-fgtFoWNPq6LCALc3xRo4Do,3767
82
82
  pytcl/mathematical_functions/basic_matrix/__init__.py,sha256=kZv3kMAEHBdVxhbyMxTyM0s-4XJP1tK6po82UsIE4tc,1318
83
- pytcl/mathematical_functions/basic_matrix/decompositions.py,sha256=GB8l54uOFEZ1uNvARFrSu6ISvE1c7HueBCy6wk8rBTU,12238
83
+ pytcl/mathematical_functions/basic_matrix/decompositions.py,sha256=PWJsFDiXM2T78RHdxBJZPFnl8kFbNZQpHrbpw0mhE00,12268
84
84
  pytcl/mathematical_functions/basic_matrix/special_matrices.py,sha256=kOozwP2CHAj4qyO7Z9ct6GwDMkmHkk1bQa0e9G98FgA,13499
85
85
  pytcl/mathematical_functions/combinatorics/__init__.py,sha256=byuHI0WkxOkQF8egrfjEr-awB2visWDXlGMnDux5IBg,1043
86
- pytcl/mathematical_functions/combinatorics/combinatorics.py,sha256=U4wd_eNKpZNHNp4-wJLGtQCgaogoUJrrXyJ6gBnD0ls,12300
86
+ pytcl/mathematical_functions/combinatorics/combinatorics.py,sha256=3EgkWdBqQ9e6JU34bec9EeCEmB-46tUSXXTAJrckSO4,12314
87
87
  pytcl/mathematical_functions/continuous_optimization/__init__.py,sha256=lck60eeCUOsRpEzPHBY3kiLKwNz_fhmYoUGP3lTmTwk,55
88
88
  pytcl/mathematical_functions/geometry/__init__.py,sha256=DhCmux9-6zxYRzlhQ9du18kvUL-leiiZwdd3Cmb5WX0,1092
89
- pytcl/mathematical_functions/geometry/geometry.py,sha256=niwXZyXQCA8Z4nhlEERvmR0wkEmr9LNIhYwW_rDbil8,16327
89
+ pytcl/mathematical_functions/geometry/geometry.py,sha256=l63wQnhCtJwVHZOJeONX1qyJ5Sedji8etgxwJCFtH8Y,16403
90
90
  pytcl/mathematical_functions/interpolation/__init__.py,sha256=lK4Rs0Ds_fzf9q0n6id5epdN0U8V7yD87dS-w1hvN8I,741
91
- pytcl/mathematical_functions/interpolation/interpolation.py,sha256=el_kw87Q7qngHomg8ZHBPOuFFN8k3paBV6AanSHd_V4,12596
91
+ pytcl/mathematical_functions/interpolation/interpolation.py,sha256=2cXMDgWBjWDGHnK1K_lawFlJL8oPl5AQGf9MNgsESfo,12610
92
92
  pytcl/mathematical_functions/numerical_integration/__init__.py,sha256=iXiHzyV_KIhCv7tXErXlN1_fUEACN6yN3CYDHRA7esw,974
93
93
  pytcl/mathematical_functions/numerical_integration/quadrature.py,sha256=ZRMKs0vbcgFDe1Sr8sjyEOkALLmJU4zKRJjoPEcXrUc,15670
94
94
  pytcl/mathematical_functions/polynomials/__init__.py,sha256=WJWZcoQhnvy5f59-kncMTgD9mCtgwfDgULvDYYHS5ys,43
95
95
  pytcl/mathematical_functions/signal_processing/__init__.py,sha256=_SzzBVtxmSvP8FKeogRdNmFo8FOVDDoexVOqd-lE7do,2325
96
- pytcl/mathematical_functions/signal_processing/detection.py,sha256=RvnSl1-VM6lX7jmVaV40hH1zdS2Hh3Zvm0FsSLHDpic,30305
97
- pytcl/mathematical_functions/signal_processing/filters.py,sha256=ellpwrdKHp3wuKDQeRa8htE6rzq2Kwc0RVPuXTJj5rM,23375
98
- pytcl/mathematical_functions/signal_processing/matched_filter.py,sha256=bwWXKizv4ok-C6D7gMR9GGCj9CakqVdRS7di_kHwLmk,22837
96
+ pytcl/mathematical_functions/signal_processing/detection.py,sha256=9F0xdy3hMat1czSWAQYMExn0kY5DBRpyBneAfjjHUVI,30377
97
+ pytcl/mathematical_functions/signal_processing/filters.py,sha256=8Ojf4h4rfiucBXqUmB1odvHH41Gf3rPwmWCMKb-qzWk,23435
98
+ pytcl/mathematical_functions/signal_processing/matched_filter.py,sha256=AahJZRZk2IIXzRL7www0n8bc0XoKabaLOe8yYNSjuDY,22893
99
99
  pytcl/mathematical_functions/special_functions/__init__.py,sha256=AJBCKj32daQxdahUQckW0bWowzOoapxni2eZnVXERdg,3859
100
100
  pytcl/mathematical_functions/special_functions/bessel.py,sha256=M0mwLQBaUXEHA8wyKReJ2D66I1v1XR7y-txAipd-WDs,14377
101
101
  pytcl/mathematical_functions/special_functions/debye.py,sha256=Nchjwkl1vzSL1L7nQpslb-lvT49LgTfdTIQMeSNn4vQ,6689
102
- pytcl/mathematical_functions/special_functions/elliptic.py,sha256=vRMIcvOOywH8xd2zPTeo3cJ3ckOEimFGWRr5gV-0L_o,7412
102
+ pytcl/mathematical_functions/special_functions/elliptic.py,sha256=WyzBkrfZufIR5dUmCKGcxp6KNpVDrU89NGLDyRrZOqQ,7418
103
103
  pytcl/mathematical_functions/special_functions/error_functions.py,sha256=a3SS8FYAMRv1KdCmebOZL95yjvVt9gZRF2XOjHvQ9M8,6253
104
- pytcl/mathematical_functions/special_functions/gamma_functions.py,sha256=vbXaZTsVZDpbAM6aVbLab6Cq0QHjuDeawWxKuXcv38w,10177
104
+ pytcl/mathematical_functions/special_functions/gamma_functions.py,sha256=xXN_9SCokH10HjE8PpaPKHYVK_RZRHRAbZgR2mZYIAA,10191
105
105
  pytcl/mathematical_functions/special_functions/hypergeometric.py,sha256=gKn_tXboEst7pVDiW15IbKFAANM4XVqKtDc1dmWL-2A,9768
106
- pytcl/mathematical_functions/special_functions/lambert_w.py,sha256=FToYtwoI14H7kuO-it8a8jJbpMDjuTWcL3Ff3Eg5OxI,6825
106
+ pytcl/mathematical_functions/special_functions/lambert_w.py,sha256=ivRc4KH5Lwoxb_yijrJEwG0ITa0hhcYF7_gCfVBBNW4,6855
107
107
  pytcl/mathematical_functions/special_functions/marcum_q.py,sha256=OZ5QjIB1e_XvRG8A-3dbZ13YXHtdk2EYVEPaqtgVr14,9580
108
108
  pytcl/mathematical_functions/statistics/__init__.py,sha256=dfypStgmnFmOrnWcm-3CEvLinONHraFgx9O66_37bqw,1278
109
- pytcl/mathematical_functions/statistics/distributions.py,sha256=djSEnCZtUmfi9JIVo5gGdPtUF6JiBYBlgfbm3nOVB7k,19205
110
- pytcl/mathematical_functions/statistics/estimators.py,sha256=73wt5uUuE4gfpEzqpAk4yHeqWZCQpg9pFqj0Dutey7M,10817
109
+ pytcl/mathematical_functions/statistics/distributions.py,sha256=icfFIIKCEFzkpFHuYGWL197nm8wvS7UPJlr9kd_uEgw,19373
110
+ pytcl/mathematical_functions/statistics/estimators.py,sha256=TLnYXSwk5MzBakZrzDBupbOB3ONmJI7q1-oB2xuSVQM,10831
111
111
  pytcl/mathematical_functions/transforms/__init__.py,sha256=SPXSKHjqR6B_8pvgtbtOnEiCpU-u0JF2s7hAlhb0BbI,2343
112
112
  pytcl/mathematical_functions/transforms/fourier.py,sha256=QH6OaTzw4kN6M-DuSmwB_5b-wu_4yP5I2CUmNEyLORM,20737
113
- pytcl/mathematical_functions/transforms/stft.py,sha256=NoCPEsQPBDf2it-uH-FKFeMV9pnqhVNFjGHTVj0bv4s,18577
114
- pytcl/mathematical_functions/transforms/wavelets.py,sha256=rL7AiWLNoHreCbCL0v0oy_M_RbqUjys7KgS5jCLCSZ0,21524
113
+ pytcl/mathematical_functions/transforms/stft.py,sha256=zQapXl-v69_RDPwMqci83jah17GyAfnr3gx0budv2Cg,18619
114
+ pytcl/mathematical_functions/transforms/wavelets.py,sha256=dm273Z_t13BlEVSlHTaGE7jR1ocugL7lEkcO499U7bY,21656
115
115
  pytcl/misc/__init__.py,sha256=SCHf_lQVfdl2gwUluHBiIloTF8HRH8EkgYfbNr7zOug,33
116
116
  pytcl/navigation/__init__.py,sha256=k1_x_FnnPrIzGeNu7zejPtPubIhweBgCfwqlZJEMw0I,6042
117
- pytcl/navigation/geodesy.py,sha256=1zSzWJUwjRjj8cUzbaXze9nr_nSqm-NQmXiCoN8dwQ4,16961
118
- pytcl/navigation/great_circle.py,sha256=ZJ3anzmkmO-qvCTjq3gJlVnAnDK-CSEibShrlVyTJMc,20859
119
- pytcl/navigation/ins.py,sha256=ZavoBknLiWXCTWrlTyaGmkJgaggkSxUanwwACPzrrTg,31097
120
- pytcl/navigation/ins_gnss.py,sha256=t0LzQ3G80aqyRdESA8RF6Dv3blae0zF_ZUyw-uT15hw,29963
121
- pytcl/navigation/rhumb.py,sha256=AJ9WfIh2OKw1ppZHAvRyfI6nkBrs3hQrYj6A1Cj7ZPg,18150
117
+ pytcl/navigation/geodesy.py,sha256=M9XXfBTMCRdaWMV2-ViDSTEt94WZnMtxMeJQ1FAgQHY,17227
118
+ pytcl/navigation/great_circle.py,sha256=TtlkWZbzr-HzSt4ultG_h137ZnX0pJZx_87kr3uvpjI,20923
119
+ pytcl/navigation/ins.py,sha256=OIi8_RjrgEYl0MFpJEFMjIlpgX8DYGTEhdLEvqG-ABU,31151
120
+ pytcl/navigation/ins_gnss.py,sha256=euKF5JGgwmVBsw3jBf7_wa2z1BpZeVbSNmBuwzhGS6c,30157
121
+ pytcl/navigation/rhumb.py,sha256=lr1c3iEXfoOSfIyyXSRWv6He5TlaxEHbJy-dhqM1gRw,18224
122
122
  pytcl/performance_evaluation/__init__.py,sha256=tM2pnBfDb2XbnLt4Y5MQ6w6XBwFy_5bf_y0toZmxx88,1859
123
123
  pytcl/performance_evaluation/estimation_metrics.py,sha256=X1ZCpp8m6DV14N2wbMvlRwfORRKga8DgKmG3dROyJqA,12351
124
- pytcl/performance_evaluation/track_metrics.py,sha256=UuGapygdhHP22xkp-ep7k6icJgL3g0yazP5VIpe1e_8,13328
124
+ pytcl/performance_evaluation/track_metrics.py,sha256=Nd3royJkAelZV-Qggl8i72e7WocCxWomgliArvVAEkc,13342
125
125
  pytcl/physical_values/__init__.py,sha256=SGbg6b0d4dWebE3baW4OlJshL00grG5E4wABw6jxl20,44
126
126
  pytcl/plotting/__init__.py,sha256=YtYnKYHL5lN6EaT_bwwR3h89NW0HSMToIWHhHBxcidY,3126
127
- pytcl/plotting/coordinates.py,sha256=KFMUEkrTk5yJ6ZVH7gLaWD9-YQHoGdHzJnO8jgJVYxE,17002
127
+ pytcl/plotting/coordinates.py,sha256=h39H855Qjqtcly62m09demaOFpfMs_8EF_nXhoLBSBs,17198
128
128
  pytcl/plotting/ellipses.py,sha256=bcns6dfNK4bwA_QBshscYhbAz_5wegwyqjDzzoUdWsQ,12465
129
- pytcl/plotting/metrics.py,sha256=B-PTVPuZ2Rl8EtV53he8O1iYw6nWuw_gQ-qUUIX4V5Y,18050
130
- pytcl/plotting/tracks.py,sha256=FsDpaWPsD5FCed6zUy_Kzhln4DEyfr7Kle_BfeDOrl8,22894
129
+ pytcl/plotting/metrics.py,sha256=zbJr5P2kQg7-rGpGHsN7rC02S0JLOpPUZeoscQem7uQ,18148
130
+ pytcl/plotting/tracks.py,sha256=cqZG71ZHM-wDSzjH4I4kCESORIiZjmGesQtADmAi4gc,23034
131
131
  pytcl/scheduling/__init__.py,sha256=jTqMSKcsCrWU_Fh6WaT6BW5WatNHyyEYjFbsv6X18Oc,39
132
132
  pytcl/static_estimation/__init__.py,sha256=sSEhqq35jq_MpRLnBtWjKXwGZ9dqIw71iwji-TNwXmc,2222
133
- pytcl/static_estimation/least_squares.py,sha256=tZ10srMCvCWw1RwjJD6xtLxiN5XP7LIjOiBwJRf5v8M,13420
134
- pytcl/static_estimation/maximum_likelihood.py,sha256=Y5kmef55FDIAEVY-Gc2eO7PUipcJGLhtGNEALTEtyh8,21581
133
+ pytcl/static_estimation/least_squares.py,sha256=8ouOyRGC7K-W8fynZMWlc2-KAFojvTbuzcqi5uS_sVA,13432
134
+ pytcl/static_estimation/maximum_likelihood.py,sha256=P6BKMcuzzDu_Qc6mX9KLI-zPWFX_NabbA6AKYjkNBcY,21581
135
135
  pytcl/static_estimation/robust.py,sha256=egBLKWmo6d9PzP6LDh0J7ee4j6hYZh8kAb9TR5uC2so,18527
136
136
  pytcl/terrain/__init__.py,sha256=e7plNQI5Y_jpZ24r82AgqdX0ChmmyYoeT7HReclnGXc,3228
137
- pytcl/terrain/dem.py,sha256=1cOmjhKTr0isYXOw2O12YbjVq2MN0lns9-Sdza_lep4,20726
138
- pytcl/terrain/loaders.py,sha256=1vbzd1F709QH3okjNhkaP9Hg0TUAUulwbgV-twONA5E,26946
139
- pytcl/terrain/visibility.py,sha256=Ko5r7JnliIwraVKQLxBCALhdiejtXXVyC0iBILGvLH0,22701
137
+ pytcl/terrain/dem.py,sha256=rg2o0h0ZDrfxvtYhnE2A5tdzRnCmqcihu4w1uNJdH3Y,20814
138
+ pytcl/terrain/loaders.py,sha256=KBs1vdYUYW-0ETIujRv4-WxO-bExZk-FvPLY5l6gyTc,27028
139
+ pytcl/terrain/visibility.py,sha256=nIJr9AVk7C8GCpJV4UDvUjhmAieycWD8BLepAMUBMIQ,22739
140
140
  pytcl/trackers/__init__.py,sha256=Gw79xlSIUzdPV8bN1slNWUlGxE3d-NsVmbMygkYVV20,1151
141
- pytcl/trackers/hypothesis.py,sha256=Q50LcD63rGDv4RwEpbamw4Y2nOXBsZTlVCCkV34ZU4I,17287
142
- pytcl/trackers/mht.py,sha256=kMomduNVkKbXoBEQmuLkX0xOMb8U52z2o1ezOmzqEpU,20489
141
+ pytcl/trackers/hypothesis.py,sha256=RApWfji-f0-a68KnAJela0BvPdIlOY_FV_cYJFmVUoE,17353
142
+ pytcl/trackers/mht.py,sha256=7mwhMmja3ri2wnx7W1wueDGn2r3ArwAxJDPUJ7IZAkQ,20617
143
143
  pytcl/trackers/multi_target.py,sha256=hvt89ERhMwpcHcIJeKHnkQSKdE3_LoRiX-gbaGoo300,10516
144
144
  pytcl/trackers/single_target.py,sha256=Yy3FwaNTArMWcaod-0HVeiioNV4xLWxNDn_7ZPVqQYs,6562
145
145
  pytcl/transponders/__init__.py,sha256=5fL4u3lKCYgPLo5uFeuZbtRZkJPABntuKYGUvVgMMEI,41
146
- nrl_tracker-0.22.2.dist-info/LICENSE,sha256=rB5G4WppIIUzMOYr2N6uyYlNJ00hRJqE5tie6BMvYuE,1612
147
- nrl_tracker-0.22.2.dist-info/METADATA,sha256=BX9uSaIH5fYqbHedxDMu8np1dR_02LISxWy1-P5Q5WY,10005
148
- nrl_tracker-0.22.2.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
149
- nrl_tracker-0.22.2.dist-info/top_level.txt,sha256=17megxcrTPBWwPZTh6jTkwTKxX7No-ZqRpyvElnnO-s,6
150
- nrl_tracker-0.22.2.dist-info/RECORD,,
146
+ nrl_tracker-0.22.4.dist-info/LICENSE,sha256=rB5G4WppIIUzMOYr2N6uyYlNJ00hRJqE5tie6BMvYuE,1612
147
+ nrl_tracker-0.22.4.dist-info/METADATA,sha256=zfUsmYNc37YRmgFjm4DZak-rSDMSPsQM3KhO0Syr8sQ,10005
148
+ nrl_tracker-0.22.4.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
149
+ nrl_tracker-0.22.4.dist-info/top_level.txt,sha256=17megxcrTPBWwPZTh6jTkwTKxX7No-ZqRpyvElnnO-s,6
150
+ nrl_tracker-0.22.4.dist-info/RECORD,,
pytcl/__init__.py CHANGED
@@ -20,7 +20,7 @@ References
20
20
  no. 5, pp. 18-27, May 2017.
21
21
  """
22
22
 
23
- __version__ = "0.22.2"
23
+ __version__ = "0.22.4"
24
24
  __author__ = "Python Port Contributors"
25
25
  __original_author__ = "David F. Crouse, Naval Research Laboratory"
26
26
 
@@ -19,9 +19,9 @@ def _mahalanobis_distance_2d(
19
19
  S_inv: np.ndarray,
20
20
  ) -> float:
21
21
  """JIT-compiled Mahalanobis distance for 2D innovations."""
22
- return innovation[0] * (S_inv[0, 0] * innovation[0] + S_inv[0, 1] * innovation[1]) + innovation[
23
- 1
24
- ] * (S_inv[1, 0] * innovation[0] + S_inv[1, 1] * innovation[1])
22
+ return innovation[0] * (
23
+ S_inv[0, 0] * innovation[0] + S_inv[0, 1] * innovation[1]
24
+ ) + innovation[1] * (S_inv[1, 0] * innovation[0] + S_inv[1, 1] * innovation[1])
25
25
 
26
26
 
27
27
  @njit(cache=True, fastmath=True)
@@ -94,7 +94,9 @@ def compute_measurement_likelihood(
94
94
  return 0.0
95
95
 
96
96
  mahal_sq = innovation @ np.linalg.solve(innovation_cov, innovation)
97
- likelihood = detection_prob * np.exp(-0.5 * mahal_sq) / np.sqrt((2 * np.pi) ** m * det_S)
97
+ likelihood = (
98
+ detection_prob * np.exp(-0.5 * mahal_sq) / np.sqrt((2 * np.pi) ** m * det_S)
99
+ )
98
100
 
99
101
  return likelihood
100
102
 
@@ -208,7 +210,9 @@ def jpda_probabilities(
208
210
  if n_tracks <= 5 and n_meas <= 5:
209
211
  beta = _jpda_exact(likelihood_matrix, gated, detection_prob, clutter_density)
210
212
  else:
211
- beta = _jpda_approximate(likelihood_matrix, gated, detection_prob, clutter_density)
213
+ beta = _jpda_approximate(
214
+ likelihood_matrix, gated, detection_prob, clutter_density
215
+ )
212
216
 
213
217
  return beta
214
218
 
@@ -254,7 +258,9 @@ def _jpda_exact(
254
258
  if gated[track_idx, meas_idx] and track_idx not in used_tracks:
255
259
  current_assignment.append(track_idx)
256
260
  used_tracks.add(track_idx)
257
- yield from generate_hypotheses(meas_idx + 1, current_assignment, used_tracks)
261
+ yield from generate_hypotheses(
262
+ meas_idx + 1, current_assignment, used_tracks
263
+ )
258
264
  used_tracks.remove(track_idx)
259
265
  current_assignment.pop()
260
266
 
@@ -292,7 +298,9 @@ def _jpda_exact(
292
298
  hypothesis_probs = [p / total_prob for p in hypothesis_probs]
293
299
 
294
300
  # Compute marginal association probabilities
295
- for h_idx, (assignment, prob) in enumerate(zip(hypothesis_assignments, hypothesis_probs)):
301
+ for h_idx, (assignment, prob) in enumerate(
302
+ zip(hypothesis_assignments, hypothesis_probs)
303
+ ):
296
304
  detected_tracks = set()
297
305
  for j, track_idx in enumerate(assignment):
298
306
  if track_idx >= 0:
@@ -335,7 +335,9 @@ def _partition_solution(
335
335
 
336
336
  for i in range(start_idx, n_assigned):
337
337
  # Require assignments 0..i-1, forbid assignment i
338
- new_required = required + [(row_ind[j], col_ind[j]) for j in range(start_idx, i)]
338
+ new_required = required + [
339
+ (row_ind[j], col_ind[j]) for j in range(start_idx, i)
340
+ ]
339
341
  new_forbidden = forbidden + [(row_ind[i], col_ind[i])]
340
342
 
341
343
  # Solve constrained problem
@@ -137,14 +137,16 @@ class DEEphemeris:
137
137
  """
138
138
  if version not in self._VALID_VERSIONS:
139
139
  raise ValueError(
140
- f"Ephemeris version must be one of {self._VALID_VERSIONS}, " f"got '{version}'"
140
+ f"Ephemeris version must be one of {self._VALID_VERSIONS}, "
141
+ f"got '{version}'"
141
142
  )
142
143
 
143
144
  try:
144
145
  import jplephem
145
146
  except ImportError as e:
146
147
  raise ImportError(
147
- "jplephem is required for ephemeris access. " "Install with: pip install jplephem"
148
+ "jplephem is required for ephemeris access. "
149
+ "Install with: pip install jplephem"
148
150
  ) from e
149
151
 
150
152
  self.version = version
@@ -170,9 +172,7 @@ class DEEphemeris:
170
172
 
171
173
  # Try to construct kernel filename
172
174
  kernel_name = f"de{self.version[2:]}.bsp"
173
- kernel_url = (
174
- f"https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/{kernel_name}"
175
- )
175
+ kernel_url = f"https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/{kernel_name}"
176
176
 
177
177
  # Try to download if not exists
178
178
  kernel_path = os.path.expanduser(f"~/.jplephem/{kernel_name}")
@@ -296,7 +296,9 @@ class DEEphemeris:
296
296
 
297
297
  # Get Moon position relative to Earth
298
298
  moon_segment = self.kernel[3, 301]
299
- moon_rel_earth_pos, moon_rel_earth_vel = moon_segment.compute_and_differentiate(jd)
299
+ moon_rel_earth_pos, moon_rel_earth_vel = (
300
+ moon_segment.compute_and_differentiate(jd)
301
+ )
300
302
 
301
303
  # Moon position relative to SSB
302
304
  position = earth_pos + moon_rel_earth_pos
@@ -316,7 +318,9 @@ class DEEphemeris:
316
318
 
317
319
  def planet_position(
318
320
  self,
319
- planet: Literal["mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune"],
321
+ planet: Literal[
322
+ "mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune"
323
+ ],
320
324
  jd: float,
321
325
  frame: Literal["icrf", "ecliptic"] = "icrf",
322
326
  ) -> Tuple[np.ndarray, np.ndarray]:
@@ -373,7 +377,9 @@ class DEEphemeris:
373
377
 
374
378
  return position, velocity
375
379
 
376
- def barycenter_position(self, body: str, jd: float) -> Tuple[np.ndarray, np.ndarray]:
380
+ def barycenter_position(
381
+ self, body: str, jd: float
382
+ ) -> Tuple[np.ndarray, np.ndarray]:
377
383
  """Compute position of any body relative to Solar System Barycenter.
378
384
 
379
385
  Parameters
@@ -471,7 +477,9 @@ def moon_position(
471
477
 
472
478
 
473
479
  def planet_position(
474
- planet: Literal["mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune"],
480
+ planet: Literal[
481
+ "mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune"
482
+ ],
475
483
  jd: float,
476
484
  frame: Literal["icrf", "ecliptic"] = "icrf",
477
485
  ) -> Tuple[np.ndarray, np.ndarray]:
@@ -198,7 +198,9 @@ def lambert_universal(
198
198
  psi = (psi_low + psi_high) / 2
199
199
 
200
200
  else:
201
- raise ValueError(f"Lambert's problem did not converge after {max_iter} iterations")
201
+ raise ValueError(
202
+ f"Lambert's problem did not converge after {max_iter} iterations"
203
+ )
202
204
 
203
205
  # Compute f, g, f_dot, g_dot
204
206
  f = 1 - y / r1_mag
@@ -286,7 +288,11 @@ def lambert_izzo(
286
288
 
287
289
  # Cross product for angular momentum direction
288
290
  cross = np.cross(r1, r2)
289
- h_hat = cross / np.linalg.norm(cross) if np.linalg.norm(cross) > 1e-10 else np.array([0, 0, 1])
291
+ h_hat = (
292
+ cross / np.linalg.norm(cross)
293
+ if np.linalg.norm(cross) > 1e-10
294
+ else np.array([0, 0, 1])
295
+ )
290
296
 
291
297
  # Transfer angle
292
298
  cos_dnu = np.dot(r1_hat, r2_hat)
@@ -329,9 +335,13 @@ def lambert_izzo(
329
335
 
330
336
  # Time of flight equation
331
337
  if x < 1:
332
- psi = np.arccos(x * lambda_param + y * np.sqrt(1 - lambda_param * lambda_param))
338
+ psi = np.arccos(
339
+ x * lambda_param + y * np.sqrt(1 - lambda_param * lambda_param)
340
+ )
333
341
  else:
334
- psi = np.arccosh(x * lambda_param + y * np.sqrt(lambda_param * lambda_param - 1))
342
+ psi = np.arccosh(
343
+ x * lambda_param + y * np.sqrt(lambda_param * lambda_param - 1)
344
+ )
335
345
 
336
346
  T_x = (
337
347
  psi + multi_rev * np.pi - (x - lambda_param * y) * np.sqrt(abs(1 - x * x))
@@ -176,7 +176,9 @@ def mean_to_hyperbolic_anomaly(
176
176
  if abs(delta) < tol:
177
177
  return H
178
178
 
179
- raise ValueError(f"Hyperbolic Kepler's equation did not converge after {max_iter} iterations")
179
+ raise ValueError(
180
+ f"Hyperbolic Kepler's equation did not converge after {max_iter} iterations"
181
+ )
180
182
 
181
183
 
182
184
  def eccentric_to_true_anomaly(E: float, e: float) -> float:
@@ -292,7 +292,9 @@ def gmst_iau82(jd_ut1: float) -> float:
292
292
  T_u = (jd_0h - JD_J2000) / 36525.0
293
293
 
294
294
  # GMST at 0h UT1 (seconds)
295
- gmst_0h_sec = 24110.54841 + 8640184.812866 * T_u + 0.093104 * T_u**2 - 6.2e-6 * T_u**3
295
+ gmst_0h_sec = (
296
+ 24110.54841 + 8640184.812866 * T_u + 0.093104 * T_u**2 - 6.2e-6 * T_u**3
297
+ )
296
298
 
297
299
  # Add UT1 fraction
298
300
  ut1_fraction = (jd_ut1 - jd_0h) * 86400.0
@@ -323,7 +323,9 @@ def post_newtonian_acceleration(
323
323
  return a_newt + a_1pn
324
324
 
325
325
 
326
- def geodetic_precession(a: float, e: float, inclination: float, gm: float = GM_EARTH) -> float:
326
+ def geodetic_precession(
327
+ a: float, e: float, inclination: float, gm: float = GM_EARTH
328
+ ) -> float:
327
329
  """Compute geodetic (de Sitter) precession rate of orbital plane.
328
330
 
329
331
  The orbital plane of a satellite precesses due to frame-dragging effects
@@ -363,7 +365,11 @@ def geodetic_precession(a: float, e: float, inclination: float, gm: float = GM_E
363
365
 
364
366
 
365
367
  def lense_thirring_precession(
366
- a: float, e: float, inclination: float, angular_momentum: float, gm: float = GM_EARTH
368
+ a: float,
369
+ e: float,
370
+ inclination: float,
371
+ angular_momentum: float,
372
+ gm: float = GM_EARTH,
367
373
  ) -> float:
368
374
  """Compute Lense-Thirring (frame-dragging) precession of orbital node.
369
375
 
@@ -218,7 +218,9 @@ def isa_atmosphere(
218
218
  strat_mask = altitude > h_trop
219
219
  temperature[strat_mask] = T_trop + temperature_offset
220
220
  # Pressure at tropopause
221
- P_trop = P0 * ((T0 + temperature_offset) / (T_trop + temperature_offset)) ** (G0 / (R * L))
221
+ P_trop = P0 * ((T0 + temperature_offset) / (T_trop + temperature_offset)) ** (
222
+ G0 / (R * L)
223
+ )
222
224
  pressure[strat_mask] = P_trop * np.exp(
223
225
  -G0 * (altitude[strat_mask] - h_trop) / (R * (T_trop + temperature_offset))
224
226
  )
@@ -297,7 +297,8 @@ def prune_mixture(
297
297
  total_weight = sum(c.weight for c in surviving)
298
298
  if total_weight > 0:
299
299
  surviving = [
300
- GaussianComponent(c.weight / total_weight, c.mean, c.covariance) for c in surviving
300
+ GaussianComponent(c.weight / total_weight, c.mean, c.covariance)
301
+ for c in surviving
301
302
  ]
302
303
 
303
304
  return surviving
@@ -391,7 +392,8 @@ def reduce_mixture_runnalls(
391
392
  total_weight = sum(c.weight for c in working)
392
393
  if total_weight > 0:
393
394
  working = [
394
- GaussianComponent(c.weight / total_weight, c.mean, c.covariance) for c in working
395
+ GaussianComponent(c.weight / total_weight, c.mean, c.covariance)
396
+ for c in working
395
397
  ]
396
398
 
397
399
  return ReductionResult(working, n_original, len(working), total_cost)
@@ -531,7 +533,8 @@ def reduce_mixture_west(
531
533
  total_weight = sum(c.weight for c in working)
532
534
  if total_weight > 0:
533
535
  working = [
534
- GaussianComponent(c.weight / total_weight, c.mean, c.covariance) for c in working
536
+ GaussianComponent(c.weight / total_weight, c.mean, c.covariance)
537
+ for c in working
535
538
  ]
536
539
 
537
540
  return ReductionResult(working, n_original, len(working), total_cost)
@@ -602,7 +605,8 @@ class GaussianMixture:
602
605
  total = sum(c.weight for c in self.components)
603
606
  if total > 0:
604
607
  self.components = [
605
- GaussianComponent(c.weight / total, c.mean, c.covariance) for c in self.components
608
+ GaussianComponent(c.weight / total, c.mean, c.covariance)
609
+ for c in self.components
606
610
  ]
607
611
 
608
612
  @property
@@ -152,7 +152,11 @@ def _ward_linkage(
152
152
  """Ward's linkage: minimum variance merge."""
153
153
  total = size_i + size_j + size_k
154
154
  return np.sqrt(
155
- ((size_i + size_k) * dist_i**2 + (size_j + size_k) * dist_j**2 - size_k * dist_ij**2)
155
+ (
156
+ (size_i + size_k) * dist_i**2
157
+ + (size_j + size_k) * dist_j**2
158
+ - size_k * dist_ij**2
159
+ )
156
160
  / total
157
161
  )
158
162
 
@@ -250,7 +250,9 @@ def kmeans(
250
250
  raise ValueError(f"n_clusters ({n_clusters}) > n_samples ({n_samples})")
251
251
 
252
252
  # Check if initial centers are provided
253
- if isinstance(init, np.ndarray) or (isinstance(init, (list, tuple)) and len(init) > 0):
253
+ if isinstance(init, np.ndarray) or (
254
+ isinstance(init, (list, tuple)) and len(init) > 0
255
+ ):
254
256
  init_centers = np.asarray(init, dtype=np.float64)
255
257
  if init_centers.shape != (n_clusters, n_features):
256
258
  raise ValueError(
@@ -290,7 +290,9 @@ class ClusterSet:
290
290
  self._clusters = list(clusters)
291
291
 
292
292
  # Build lookups
293
- self._id_to_idx: Dict[int, int] = {c.id: i for i, c in enumerate(self._clusters)}
293
+ self._id_to_idx: Dict[int, int] = {
294
+ c.id: i for i, c in enumerate(self._clusters)
295
+ }
294
296
  self._track_to_cluster: Dict[int, int] = {}
295
297
  for cluster in self._clusters:
296
298
  for track_id in cluster.track_ids:
@@ -407,7 +409,9 @@ class ClusterSet:
407
409
  return self.get_cluster(cluster_id)
408
410
  return None
409
411
 
410
- def clusters_in_region(self, center: ArrayLike, radius: float) -> List[TrackCluster]:
412
+ def clusters_in_region(
413
+ self, center: ArrayLike, radius: float
414
+ ) -> List[TrackCluster]:
411
415
  """
412
416
  Get clusters with centroids within a spatial region.
413
417
 
@@ -556,7 +560,9 @@ class ClusterSet:
556
560
  """
557
561
  result = {}
558
562
  for cluster in self._clusters:
559
- stats = self.cluster_stats(cluster.id, tracks, state_indices, velocity_indices)
563
+ stats = self.cluster_stats(
564
+ cluster.id, tracks, state_indices, velocity_indices
565
+ )
560
566
  if stats is not None:
561
567
  result[cluster.id] = stats
562
568
  return result
@@ -203,7 +203,9 @@ class MeasurementSet:
203
203
  MeasurementSet
204
204
  Measurements at the specified time.
205
205
  """
206
- measurements = [m for m in self._measurements if abs(m.time - time) <= tolerance]
206
+ measurements = [
207
+ m for m in self._measurements if abs(m.time - time) <= tolerance
208
+ ]
207
209
  return MeasurementSet(measurements)
208
210
 
209
211
  def in_time_window(self, start: float, end: float) -> MeasurementSet:
@@ -344,7 +346,9 @@ class MeasurementSet:
344
346
  return np.zeros((0, 0))
345
347
  return np.array([m.value for m in self._measurements])
346
348
 
347
- def values_at_time(self, time: float, tolerance: float = 1e-9) -> NDArray[np.float64]:
349
+ def values_at_time(
350
+ self, time: float, tolerance: float = 1e-9
351
+ ) -> NDArray[np.float64]:
348
352
  """
349
353
  Extract measurement values at a specific time.
350
354