nrl-tracker 0.21.4__py3-none-any.whl → 0.22.0__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 (138) hide show
  1. {nrl_tracker-0.21.4.dist-info → nrl_tracker-0.22.0.dist-info}/METADATA +2 -2
  2. nrl_tracker-0.22.0.dist-info/RECORD +150 -0
  3. pytcl/__init__.py +9 -11
  4. pytcl/assignment_algorithms/__init__.py +32 -42
  5. pytcl/assignment_algorithms/data_association.py +9 -10
  6. pytcl/assignment_algorithms/gating.py +7 -5
  7. pytcl/assignment_algorithms/jpda.py +10 -14
  8. pytcl/assignment_algorithms/three_dimensional/__init__.py +6 -8
  9. pytcl/assignment_algorithms/three_dimensional/assignment.py +6 -2
  10. pytcl/assignment_algorithms/two_dimensional/__init__.py +9 -13
  11. pytcl/assignment_algorithms/two_dimensional/assignment.py +5 -2
  12. pytcl/assignment_algorithms/two_dimensional/kbest.py +9 -9
  13. pytcl/astronomical/__init__.py +130 -89
  14. pytcl/astronomical/ephemerides.py +524 -0
  15. pytcl/astronomical/lambert.py +6 -15
  16. pytcl/astronomical/orbital_mechanics.py +1 -3
  17. pytcl/astronomical/reference_frames.py +1 -3
  18. pytcl/astronomical/relativity.py +466 -0
  19. pytcl/astronomical/time_systems.py +2 -1
  20. pytcl/atmosphere/__init__.py +12 -14
  21. pytcl/atmosphere/models.py +5 -5
  22. pytcl/clustering/__init__.py +28 -36
  23. pytcl/clustering/dbscan.py +5 -2
  24. pytcl/clustering/gaussian_mixture.py +10 -10
  25. pytcl/clustering/hierarchical.py +7 -7
  26. pytcl/clustering/kmeans.py +7 -5
  27. pytcl/containers/__init__.py +29 -43
  28. pytcl/containers/cluster_set.py +13 -20
  29. pytcl/containers/covertree.py +8 -2
  30. pytcl/containers/kd_tree.py +6 -2
  31. pytcl/containers/measurement_set.py +11 -16
  32. pytcl/containers/rtree.py +8 -7
  33. pytcl/containers/track_list.py +13 -13
  34. pytcl/containers/vptree.py +7 -2
  35. pytcl/coordinate_systems/__init__.py +69 -74
  36. pytcl/coordinate_systems/conversions/__init__.py +20 -24
  37. pytcl/coordinate_systems/conversions/geodetic.py +7 -17
  38. pytcl/coordinate_systems/conversions/spherical.py +4 -2
  39. pytcl/coordinate_systems/jacobians/__init__.py +10 -12
  40. pytcl/coordinate_systems/jacobians/jacobians.py +2 -1
  41. pytcl/coordinate_systems/projections/__init__.py +27 -23
  42. pytcl/coordinate_systems/projections/projections.py +14 -39
  43. pytcl/coordinate_systems/rotations/__init__.py +20 -22
  44. pytcl/coordinate_systems/rotations/rotations.py +3 -4
  45. pytcl/core/__init__.py +16 -22
  46. pytcl/core/array_utils.py +7 -7
  47. pytcl/core/constants.py +1 -3
  48. pytcl/core/validation.py +13 -19
  49. pytcl/dynamic_estimation/__init__.py +77 -86
  50. pytcl/dynamic_estimation/imm.py +10 -15
  51. pytcl/dynamic_estimation/information_filter.py +8 -6
  52. pytcl/dynamic_estimation/kalman/__init__.py +40 -48
  53. pytcl/dynamic_estimation/kalman/extended.py +4 -5
  54. pytcl/dynamic_estimation/kalman/linear.py +7 -3
  55. pytcl/dynamic_estimation/kalman/square_root.py +7 -8
  56. pytcl/dynamic_estimation/kalman/unscented.py +8 -6
  57. pytcl/dynamic_estimation/particle_filters/__init__.py +12 -14
  58. pytcl/dynamic_estimation/particle_filters/bootstrap.py +8 -8
  59. pytcl/dynamic_estimation/smoothers.py +9 -10
  60. pytcl/dynamic_models/__init__.py +37 -41
  61. pytcl/dynamic_models/continuous_time/__init__.py +11 -11
  62. pytcl/dynamic_models/continuous_time/dynamics.py +4 -2
  63. pytcl/dynamic_models/discrete_time/__init__.py +11 -17
  64. pytcl/dynamic_models/process_noise/__init__.py +11 -17
  65. pytcl/dynamic_models/process_noise/polynomial.py +2 -6
  66. pytcl/gravity/__init__.py +55 -65
  67. pytcl/gravity/clenshaw.py +4 -7
  68. pytcl/gravity/egm.py +9 -6
  69. pytcl/gravity/models.py +1 -3
  70. pytcl/gravity/spherical_harmonics.py +6 -11
  71. pytcl/gravity/tides.py +9 -17
  72. pytcl/magnetism/__init__.py +26 -36
  73. pytcl/magnetism/emm.py +7 -13
  74. pytcl/magnetism/igrf.py +5 -6
  75. pytcl/magnetism/wmm.py +4 -10
  76. pytcl/mathematical_functions/__init__.py +69 -87
  77. pytcl/mathematical_functions/basic_matrix/__init__.py +25 -19
  78. pytcl/mathematical_functions/basic_matrix/decompositions.py +6 -5
  79. pytcl/mathematical_functions/basic_matrix/special_matrices.py +2 -1
  80. pytcl/mathematical_functions/combinatorics/__init__.py +18 -14
  81. pytcl/mathematical_functions/combinatorics/combinatorics.py +5 -4
  82. pytcl/mathematical_functions/geometry/__init__.py +15 -15
  83. pytcl/mathematical_functions/geometry/geometry.py +10 -15
  84. pytcl/mathematical_functions/interpolation/__init__.py +11 -13
  85. pytcl/mathematical_functions/interpolation/interpolation.py +8 -5
  86. pytcl/mathematical_functions/numerical_integration/__init__.py +16 -10
  87. pytcl/mathematical_functions/numerical_integration/quadrature.py +6 -2
  88. pytcl/mathematical_functions/signal_processing/__init__.py +42 -30
  89. pytcl/mathematical_functions/signal_processing/detection.py +9 -9
  90. pytcl/mathematical_functions/signal_processing/filters.py +7 -8
  91. pytcl/mathematical_functions/signal_processing/matched_filter.py +8 -7
  92. pytcl/mathematical_functions/special_functions/__init__.py +75 -77
  93. pytcl/mathematical_functions/special_functions/bessel.py +2 -1
  94. pytcl/mathematical_functions/special_functions/debye.py +4 -2
  95. pytcl/mathematical_functions/special_functions/elliptic.py +3 -4
  96. pytcl/mathematical_functions/special_functions/error_functions.py +2 -1
  97. pytcl/mathematical_functions/special_functions/gamma_functions.py +3 -4
  98. pytcl/mathematical_functions/special_functions/hypergeometric.py +2 -1
  99. pytcl/mathematical_functions/special_functions/lambert_w.py +3 -4
  100. pytcl/mathematical_functions/special_functions/marcum_q.py +2 -1
  101. pytcl/mathematical_functions/statistics/__init__.py +27 -31
  102. pytcl/mathematical_functions/statistics/distributions.py +21 -40
  103. pytcl/mathematical_functions/statistics/estimators.py +3 -4
  104. pytcl/mathematical_functions/transforms/__init__.py +45 -51
  105. pytcl/mathematical_functions/transforms/fourier.py +5 -2
  106. pytcl/mathematical_functions/transforms/stft.py +8 -11
  107. pytcl/mathematical_functions/transforms/wavelets.py +13 -20
  108. pytcl/navigation/__init__.py +96 -102
  109. pytcl/navigation/geodesy.py +13 -33
  110. pytcl/navigation/great_circle.py +7 -13
  111. pytcl/navigation/ins.py +12 -16
  112. pytcl/navigation/ins_gnss.py +24 -37
  113. pytcl/navigation/rhumb.py +7 -12
  114. pytcl/performance_evaluation/__init__.py +21 -25
  115. pytcl/performance_evaluation/estimation_metrics.py +3 -1
  116. pytcl/performance_evaluation/track_metrics.py +4 -4
  117. pytcl/plotting/__init__.py +30 -38
  118. pytcl/plotting/coordinates.py +8 -18
  119. pytcl/plotting/ellipses.py +5 -2
  120. pytcl/plotting/metrics.py +5 -10
  121. pytcl/plotting/tracks.py +7 -12
  122. pytcl/static_estimation/__init__.py +37 -41
  123. pytcl/static_estimation/least_squares.py +5 -4
  124. pytcl/static_estimation/maximum_likelihood.py +8 -5
  125. pytcl/static_estimation/robust.py +5 -2
  126. pytcl/terrain/__init__.py +28 -34
  127. pytcl/terrain/dem.py +6 -9
  128. pytcl/terrain/loaders.py +9 -14
  129. pytcl/terrain/visibility.py +4 -8
  130. pytcl/trackers/__init__.py +17 -25
  131. pytcl/trackers/hypothesis.py +8 -8
  132. pytcl/trackers/mht.py +18 -24
  133. pytcl/trackers/multi_target.py +8 -6
  134. pytcl/trackers/single_target.py +5 -2
  135. nrl_tracker-0.21.4.dist-info/RECORD +0 -148
  136. {nrl_tracker-0.21.4.dist-info → nrl_tracker-0.22.0.dist-info}/LICENSE +0 -0
  137. {nrl_tracker-0.21.4.dist-info → nrl_tracker-0.22.0.dist-info}/WHEEL +0 -0
  138. {nrl_tracker-0.21.4.dist-info → nrl_tracker-0.22.0.dist-info}/top_level.txt +0 -0
@@ -24,11 +24,14 @@ References
24
24
  Systems, 19(4), 608-621.
25
25
  """
26
26
 
27
- from typing import NamedTuple, Optional
27
+ from typing import NamedTuple
28
+ from typing import Optional
28
29
 
29
30
  import numpy as np
30
- from numba import njit, prange
31
- from numpy.typing import ArrayLike, NDArray
31
+ from numba import njit
32
+ from numba import prange
33
+ from numpy.typing import ArrayLike
34
+ from numpy.typing import NDArray
32
35
 
33
36
  # =============================================================================
34
37
  # Result Types
@@ -410,8 +413,7 @@ def _cfar_2d_ca_kernel(
410
413
  for ri in range(row_min, row_max):
411
414
  for ci in range(col_min, col_max):
412
415
  if not (
413
- guard_row_min <= ri < guard_row_max
414
- and guard_col_min <= ci < guard_col_max
416
+ guard_row_min <= ri < guard_row_max and guard_col_min <= ci < guard_col_max
415
417
  ):
416
418
  ref_sum += image[ri, ci]
417
419
  n_cells += 1
@@ -460,8 +462,7 @@ def _cfar_2d_go_kernel(
460
462
  for ri in range(row_min, row_max):
461
463
  for ci in range(col_min, col_max):
462
464
  if not (
463
- guard_row_min <= ri < guard_row_max
464
- and guard_col_min <= ci < guard_col_max
465
+ guard_row_min <= ri < guard_row_max and guard_col_min <= ci < guard_col_max
465
466
  ):
466
467
  if ri < i:
467
468
  top_sum += image[ri, ci]
@@ -512,8 +513,7 @@ def _cfar_2d_so_kernel(
512
513
  for ri in range(row_min, row_max):
513
514
  for ci in range(col_min, col_max):
514
515
  if not (
515
- guard_row_min <= ri < guard_row_max
516
- and guard_col_min <= ci < guard_col_max
516
+ guard_row_min <= ri < guard_row_max and guard_col_min <= ci < guard_col_max
517
517
  ):
518
518
  if ri < i:
519
519
  top_sum += image[ri, ci]
@@ -24,10 +24,13 @@ References
24
24
  Wiley-Interscience.
25
25
  """
26
26
 
27
- from typing import NamedTuple, Optional, Union
27
+ from typing import NamedTuple
28
+ from typing import Optional
29
+ from typing import Union
28
30
 
29
31
  import numpy as np
30
- from numpy.typing import ArrayLike, NDArray
32
+ from numpy.typing import ArrayLike
33
+ from numpy.typing import NDArray
31
34
  from scipy import signal as scipy_signal
32
35
 
33
36
  # =============================================================================
@@ -606,13 +609,9 @@ def filtfilt(
606
609
 
607
610
  if isinstance(coeffs, FilterCoefficients):
608
611
  if coeffs.sos is not None:
609
- return scipy_signal.sosfiltfilt(
610
- coeffs.sos, x, padtype=padtype, padlen=padlen
611
- )
612
+ return scipy_signal.sosfiltfilt(coeffs.sos, x, padtype=padtype, padlen=padlen)
612
613
  else:
613
- return scipy_signal.filtfilt(
614
- coeffs.b, coeffs.a, x, padtype=padtype, padlen=padlen
615
- )
614
+ return scipy_signal.filtfilt(coeffs.b, coeffs.a, x, padtype=padtype, padlen=padlen)
616
615
  elif isinstance(coeffs, tuple) and len(coeffs) == 2:
617
616
  b, a = coeffs
618
617
  return scipy_signal.filtfilt(b, a, x, padtype=padtype, padlen=padlen)
@@ -21,11 +21,14 @@ References
21
21
  IRE Transactions on Information Theory, 6(3), 311-329.
22
22
  """
23
23
 
24
- from typing import NamedTuple, Optional
24
+ from typing import NamedTuple
25
+ from typing import Optional
25
26
 
26
27
  import numpy as np
27
- from numba import njit, prange
28
- from numpy.typing import ArrayLike, NDArray
28
+ from numba import njit
29
+ from numba import prange
30
+ from numpy.typing import ArrayLike
31
+ from numpy.typing import NDArray
29
32
  from scipy import fft as scipy_fft
30
33
  from scipy import signal as scipy_signal
31
34
 
@@ -590,8 +593,7 @@ def _ambiguity_function_kernel(
590
593
  for k in range(n_signal - delay_samples):
591
594
  s1 = signal[k]
592
595
  s2_conj = (
593
- shifted[delay_samples + k].real
594
- - 1j * shifted[delay_samples + k].imag
596
+ shifted[delay_samples + k].real - 1j * shifted[delay_samples + k].imag
595
597
  )
596
598
  result += s1 * s2_conj
597
599
 
@@ -638,8 +640,7 @@ def _cross_ambiguity_kernel(
638
640
  for k in range(n_signal - delay_samples):
639
641
  s1 = signal1[k]
640
642
  s2_conj = (
641
- shifted[delay_samples + k].real
642
- - 1j * shifted[delay_samples + k].imag
643
+ shifted[delay_samples + k].real - 1j * shifted[delay_samples + k].imag
643
644
  )
644
645
  result += s1 * s2_conj
645
646
 
@@ -13,98 +13,96 @@ physics, signal processing, and statistical applications:
13
13
  - Debye functions (thermodynamics)
14
14
  """
15
15
 
16
- from pytcl.mathematical_functions.special_functions.bessel import (
17
- airy,
18
- bessel_deriv,
19
- bessel_ratio,
20
- bessel_zeros,
21
- besselh,
22
- besseli,
23
- besselj,
24
- besselk,
25
- bessely,
26
- kelvin,
27
- spherical_in,
28
- spherical_jn,
29
- spherical_kn,
30
- spherical_yn,
31
- struve_h,
32
- struve_l,
33
- )
34
- from pytcl.mathematical_functions.special_functions.debye import (
35
- debye,
36
- debye_1,
37
- debye_2,
38
- debye_3,
39
- debye_4,
40
- debye_entropy,
41
- debye_heat_capacity,
42
- )
43
- from pytcl.mathematical_functions.special_functions.elliptic import ( # noqa: E501
44
- ellipe,
45
- ellipeinc,
46
- ellipk,
47
- ellipkinc,
48
- ellipkm1,
49
- elliprc,
50
- elliprd,
51
- elliprf,
52
- elliprg,
53
- elliprj,
54
- )
16
+ from pytcl.mathematical_functions.special_functions.bessel import airy
17
+ from pytcl.mathematical_functions.special_functions.bessel import bessel_deriv
18
+ from pytcl.mathematical_functions.special_functions.bessel import bessel_ratio
19
+ from pytcl.mathematical_functions.special_functions.bessel import bessel_zeros
20
+ from pytcl.mathematical_functions.special_functions.bessel import besselh
21
+ from pytcl.mathematical_functions.special_functions.bessel import besseli
22
+ from pytcl.mathematical_functions.special_functions.bessel import besselj
23
+ from pytcl.mathematical_functions.special_functions.bessel import besselk
24
+ from pytcl.mathematical_functions.special_functions.bessel import bessely
25
+ from pytcl.mathematical_functions.special_functions.bessel import kelvin
26
+ from pytcl.mathematical_functions.special_functions.bessel import spherical_in
27
+ from pytcl.mathematical_functions.special_functions.bessel import spherical_jn
28
+ from pytcl.mathematical_functions.special_functions.bessel import spherical_kn
29
+ from pytcl.mathematical_functions.special_functions.bessel import spherical_yn
30
+ from pytcl.mathematical_functions.special_functions.bessel import struve_h
31
+ from pytcl.mathematical_functions.special_functions.bessel import struve_l
32
+ from pytcl.mathematical_functions.special_functions.debye import debye
33
+ from pytcl.mathematical_functions.special_functions.debye import debye_1
34
+ from pytcl.mathematical_functions.special_functions.debye import debye_2
35
+ from pytcl.mathematical_functions.special_functions.debye import debye_3
36
+ from pytcl.mathematical_functions.special_functions.debye import debye_4
37
+ from pytcl.mathematical_functions.special_functions.debye import debye_entropy
38
+ from pytcl.mathematical_functions.special_functions.debye import debye_heat_capacity
39
+ from pytcl.mathematical_functions.special_functions.elliptic import ellipe # noqa: E501
40
+ from pytcl.mathematical_functions.special_functions.elliptic import ellipeinc
41
+ from pytcl.mathematical_functions.special_functions.elliptic import ellipk
42
+ from pytcl.mathematical_functions.special_functions.elliptic import ellipkinc
43
+ from pytcl.mathematical_functions.special_functions.elliptic import ellipkm1
44
+ from pytcl.mathematical_functions.special_functions.elliptic import elliprc
45
+ from pytcl.mathematical_functions.special_functions.elliptic import elliprd
46
+ from pytcl.mathematical_functions.special_functions.elliptic import elliprf
47
+ from pytcl.mathematical_functions.special_functions.elliptic import elliprg
48
+ from pytcl.mathematical_functions.special_functions.elliptic import elliprj
55
49
  from pytcl.mathematical_functions.special_functions.error_functions import ( # noqa: E501
56
50
  dawsn,
57
- erf,
58
- erfc,
59
- erfcinv,
60
- erfcx,
61
- erfi,
62
- erfinv,
63
- fresnel,
64
- voigt_profile,
65
- wofz,
66
51
  )
52
+ from pytcl.mathematical_functions.special_functions.error_functions import erf
53
+ from pytcl.mathematical_functions.special_functions.error_functions import erfc
54
+ from pytcl.mathematical_functions.special_functions.error_functions import erfcinv
55
+ from pytcl.mathematical_functions.special_functions.error_functions import erfcx
56
+ from pytcl.mathematical_functions.special_functions.error_functions import erfi
57
+ from pytcl.mathematical_functions.special_functions.error_functions import erfinv
58
+ from pytcl.mathematical_functions.special_functions.error_functions import fresnel
59
+ from pytcl.mathematical_functions.special_functions.error_functions import voigt_profile
60
+ from pytcl.mathematical_functions.special_functions.error_functions import wofz
67
61
  from pytcl.mathematical_functions.special_functions.gamma_functions import ( # noqa: E501
68
62
  beta,
69
- betainc,
70
- betaincinv,
71
- betaln,
72
- comb,
73
- digamma,
74
- factorial,
75
- factorial2,
76
- gamma,
77
- gammainc,
78
- gammaincc,
79
- gammaincinv,
80
- gammaln,
81
- perm,
82
- polygamma,
83
63
  )
64
+ from pytcl.mathematical_functions.special_functions.gamma_functions import betainc
65
+ from pytcl.mathematical_functions.special_functions.gamma_functions import betaincinv
66
+ from pytcl.mathematical_functions.special_functions.gamma_functions import betaln
67
+ from pytcl.mathematical_functions.special_functions.gamma_functions import comb
68
+ from pytcl.mathematical_functions.special_functions.gamma_functions import digamma
69
+ from pytcl.mathematical_functions.special_functions.gamma_functions import factorial
70
+ from pytcl.mathematical_functions.special_functions.gamma_functions import factorial2
71
+ from pytcl.mathematical_functions.special_functions.gamma_functions import gamma
72
+ from pytcl.mathematical_functions.special_functions.gamma_functions import gammainc
73
+ from pytcl.mathematical_functions.special_functions.gamma_functions import gammaincc
74
+ from pytcl.mathematical_functions.special_functions.gamma_functions import gammaincinv
75
+ from pytcl.mathematical_functions.special_functions.gamma_functions import gammaln
76
+ from pytcl.mathematical_functions.special_functions.gamma_functions import perm
77
+ from pytcl.mathematical_functions.special_functions.gamma_functions import polygamma
84
78
  from pytcl.mathematical_functions.special_functions.hypergeometric import (
85
79
  falling_factorial,
80
+ )
81
+ from pytcl.mathematical_functions.special_functions.hypergeometric import (
86
82
  generalized_hypergeometric,
87
- hyp0f1,
88
- hyp1f1,
83
+ )
84
+ from pytcl.mathematical_functions.special_functions.hypergeometric import hyp0f1
85
+ from pytcl.mathematical_functions.special_functions.hypergeometric import hyp1f1
86
+ from pytcl.mathematical_functions.special_functions.hypergeometric import (
89
87
  hyp1f1_regularized,
90
- hyp2f1,
91
- hyperu,
92
- pochhammer,
93
88
  )
89
+ from pytcl.mathematical_functions.special_functions.hypergeometric import hyp2f1
90
+ from pytcl.mathematical_functions.special_functions.hypergeometric import hyperu
91
+ from pytcl.mathematical_functions.special_functions.hypergeometric import pochhammer
92
+ from pytcl.mathematical_functions.special_functions.lambert_w import lambert_w
93
+ from pytcl.mathematical_functions.special_functions.lambert_w import lambert_w_real
94
+ from pytcl.mathematical_functions.special_functions.lambert_w import omega_constant
94
95
  from pytcl.mathematical_functions.special_functions.lambert_w import (
95
- lambert_w,
96
- lambert_w_real,
97
- omega_constant,
98
96
  solve_exponential_equation,
99
- time_delay_equation,
100
- wright_omega,
101
97
  )
98
+ from pytcl.mathematical_functions.special_functions.lambert_w import time_delay_equation
99
+ from pytcl.mathematical_functions.special_functions.lambert_w import wright_omega
100
+ from pytcl.mathematical_functions.special_functions.marcum_q import log_marcum_q
101
+ from pytcl.mathematical_functions.special_functions.marcum_q import marcum_q
102
+ from pytcl.mathematical_functions.special_functions.marcum_q import marcum_q1
103
+ from pytcl.mathematical_functions.special_functions.marcum_q import marcum_q_inv
104
+ from pytcl.mathematical_functions.special_functions.marcum_q import nuttall_q
102
105
  from pytcl.mathematical_functions.special_functions.marcum_q import (
103
- log_marcum_q,
104
- marcum_q,
105
- marcum_q1,
106
- marcum_q_inv,
107
- nuttall_q,
108
106
  swerling_detection_probability,
109
107
  )
110
108
 
@@ -9,7 +9,8 @@ from typing import Union
9
9
 
10
10
  import numpy as np
11
11
  import scipy.special as sp
12
- from numpy.typing import ArrayLike, NDArray
12
+ from numpy.typing import ArrayLike
13
+ from numpy.typing import NDArray
13
14
 
14
15
 
15
16
  def besselj(
@@ -7,7 +7,8 @@ thermodynamic properties of solids (heat capacity, entropy).
7
7
 
8
8
  import numpy as np
9
9
  import scipy.integrate as integrate
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def debye(
@@ -77,7 +78,8 @@ def debye(
77
78
  result[i] = 1.0 - n * xi / (2 * (n + 1))
78
79
  elif xi > 100:
79
80
  # Large x asymptotic
80
- from scipy.special import factorial, zeta
81
+ from scipy.special import factorial
82
+ from scipy.special import zeta
81
83
 
82
84
  result[i] = factorial(n) * zeta(n + 1) * n / (xi**n)
83
85
  else:
@@ -7,7 +7,8 @@ applications including orbits, pendulums, and electromagnetic calculations.
7
7
 
8
8
  import numpy as np
9
9
  import scipy.special as sp
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def ellipk(m: ArrayLike) -> NDArray[np.floating]:
@@ -243,9 +244,7 @@ def elliprg(x: ArrayLike, y: ArrayLike, z: ArrayLike) -> NDArray[np.floating]:
243
244
  return np.asarray(sp.elliprg(x, y, z), dtype=np.float64)
244
245
 
245
246
 
246
- def elliprj(
247
- x: ArrayLike, y: ArrayLike, z: ArrayLike, p: ArrayLike
248
- ) -> NDArray[np.floating]:
247
+ def elliprj(x: ArrayLike, y: ArrayLike, z: ArrayLike, p: ArrayLike) -> NDArray[np.floating]:
249
248
  """
250
249
  Carlson symmetric elliptic integral R_J.
251
250
 
@@ -7,7 +7,8 @@ in probability theory and statistical analysis.
7
7
 
8
8
  import numpy as np
9
9
  import scipy.special as sp
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def erf(x: ArrayLike) -> NDArray[np.floating]:
@@ -7,7 +7,8 @@ functions used in statistics and probability calculations.
7
7
 
8
8
  import numpy as np
9
9
  import scipy.special as sp
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def gamma(x: ArrayLike) -> NDArray[np.floating]:
@@ -421,9 +422,7 @@ def comb(
421
422
  --------
422
423
  scipy.special.comb : Combinations.
423
424
  """
424
- return np.asarray(
425
- sp.comb(n, k, exact=exact, repetition=repetition), dtype=np.float64
426
- )
425
+ return np.asarray(sp.comb(n, k, exact=exact, repetition=repetition), dtype=np.float64)
427
426
 
428
427
 
429
428
  def perm(n: ArrayLike, k: ArrayLike, exact: bool = False) -> NDArray:
@@ -7,7 +7,8 @@ mathematical physics, probability theory, and special function evaluation.
7
7
 
8
8
  import numpy as np
9
9
  import scipy.special as sp
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def hyp0f1(
@@ -7,7 +7,8 @@ delay differential equations, combinatorics, and physics.
7
7
 
8
8
  import numpy as np
9
9
  import scipy.special as sp
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def lambert_w(
@@ -108,9 +109,7 @@ def lambert_w_real(
108
109
  raise ValueError(f"For branch 0, x must be >= -1/e ≈ {branch_point:.6f}")
109
110
  elif branch == -1:
110
111
  if np.any((x < branch_point) | (x >= 0)):
111
- raise ValueError(
112
- f"For branch -1, x must be in [-1/e, 0) ≈ [{branch_point:.6f}, 0)"
113
- )
112
+ raise ValueError(f"For branch -1, x must be in [-1/e, 0) ≈ [{branch_point:.6f}, 0)")
114
113
  else:
115
114
  raise ValueError(f"branch must be 0 or -1, got {branch}")
116
115
 
@@ -7,7 +7,8 @@ analyzing detection probabilities and signal statistics.
7
7
 
8
8
  import numpy as np
9
9
  import scipy.special as sp
10
- from numpy.typing import ArrayLike, NDArray
10
+ from numpy.typing import ArrayLike
11
+ from numpy.typing import NDArray
11
12
 
12
13
 
13
14
  def marcum_q(
@@ -8,37 +8,33 @@ This module provides:
8
8
  - Filter consistency metrics (NEES, NIS)
9
9
  """
10
10
 
11
- from pytcl.mathematical_functions.statistics.distributions import (
12
- Beta,
13
- ChiSquared,
14
- Distribution,
15
- Exponential,
16
- Gamma,
17
- Gaussian,
18
- MultivariateGaussian,
19
- Poisson,
20
- StudentT,
21
- Uniform,
22
- VonMises,
23
- Wishart,
24
- )
25
- from pytcl.mathematical_functions.statistics.estimators import (
26
- iqr,
27
- kurtosis,
28
- mad,
29
- median,
30
- moment,
31
- nees,
32
- nis,
33
- sample_corr,
34
- sample_cov,
35
- sample_mean,
36
- sample_var,
37
- skewness,
38
- weighted_cov,
39
- weighted_mean,
40
- weighted_var,
41
- )
11
+ from pytcl.mathematical_functions.statistics.distributions import Beta
12
+ from pytcl.mathematical_functions.statistics.distributions import ChiSquared
13
+ from pytcl.mathematical_functions.statistics.distributions import Distribution
14
+ from pytcl.mathematical_functions.statistics.distributions import Exponential
15
+ from pytcl.mathematical_functions.statistics.distributions import Gamma
16
+ from pytcl.mathematical_functions.statistics.distributions import Gaussian
17
+ from pytcl.mathematical_functions.statistics.distributions import MultivariateGaussian
18
+ from pytcl.mathematical_functions.statistics.distributions import Poisson
19
+ from pytcl.mathematical_functions.statistics.distributions import StudentT
20
+ from pytcl.mathematical_functions.statistics.distributions import Uniform
21
+ from pytcl.mathematical_functions.statistics.distributions import VonMises
22
+ from pytcl.mathematical_functions.statistics.distributions import Wishart
23
+ from pytcl.mathematical_functions.statistics.estimators import iqr
24
+ from pytcl.mathematical_functions.statistics.estimators import kurtosis
25
+ from pytcl.mathematical_functions.statistics.estimators import mad
26
+ from pytcl.mathematical_functions.statistics.estimators import median
27
+ from pytcl.mathematical_functions.statistics.estimators import moment
28
+ from pytcl.mathematical_functions.statistics.estimators import nees
29
+ from pytcl.mathematical_functions.statistics.estimators import nis
30
+ from pytcl.mathematical_functions.statistics.estimators import sample_corr
31
+ from pytcl.mathematical_functions.statistics.estimators import sample_cov
32
+ from pytcl.mathematical_functions.statistics.estimators import sample_mean
33
+ from pytcl.mathematical_functions.statistics.estimators import sample_var
34
+ from pytcl.mathematical_functions.statistics.estimators import skewness
35
+ from pytcl.mathematical_functions.statistics.estimators import weighted_cov
36
+ from pytcl.mathematical_functions.statistics.estimators import weighted_mean
37
+ from pytcl.mathematical_functions.statistics.estimators import weighted_var
42
38
 
43
39
  __all__ = [
44
40
  # Distributions
@@ -6,12 +6,16 @@ for PDF, CDF, sampling, and moment calculations. These wrap scipy.stats
6
6
  distributions with additional functionality useful for tracking applications.
7
7
  """
8
8
 
9
- from abc import ABC, abstractmethod
10
- from typing import Optional, Tuple, Union
9
+ from abc import ABC
10
+ from abc import abstractmethod
11
+ from typing import Optional
12
+ from typing import Tuple
13
+ from typing import Union
11
14
 
12
15
  import numpy as np
13
16
  import scipy.stats as stats
14
- from numpy.typing import ArrayLike, NDArray
17
+ from numpy.typing import ArrayLike
18
+ from numpy.typing import NDArray
15
19
 
16
20
 
17
21
  class Distribution(ABC):
@@ -43,9 +47,7 @@ class Distribution(ABC):
43
47
  pass
44
48
 
45
49
  @abstractmethod
46
- def sample(
47
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
48
- ) -> NDArray[np.floating]:
50
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
49
51
  """Generate random samples."""
50
52
  pass
51
53
 
@@ -104,9 +106,7 @@ class Gaussian(Distribution):
104
106
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
105
107
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
106
108
 
107
- def sample(
108
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
109
- ) -> NDArray[np.floating]:
109
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
110
110
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
111
111
 
112
112
  def mean(self) -> float:
@@ -167,9 +167,7 @@ class MultivariateGaussian(Distribution):
167
167
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
168
168
  raise NotImplementedError("PPF not available for multivariate normal")
169
169
 
170
- def sample(
171
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
172
- ) -> NDArray[np.floating]:
170
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
173
171
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
174
172
 
175
173
  def mean(self) -> NDArray[np.floating]:
@@ -239,9 +237,7 @@ class Uniform(Distribution):
239
237
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
240
238
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
241
239
 
242
- def sample(
243
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
244
- ) -> NDArray[np.floating]:
240
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
245
241
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
246
242
 
247
243
  def mean(self) -> float:
@@ -279,9 +275,7 @@ class Exponential(Distribution):
279
275
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
280
276
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
281
277
 
282
- def sample(
283
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
284
- ) -> NDArray[np.floating]:
278
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
285
279
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
286
280
 
287
281
  def mean(self) -> float:
@@ -347,9 +341,7 @@ class Gamma(Distribution):
347
341
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
348
342
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
349
343
 
350
- def sample(
351
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
352
- ) -> NDArray[np.floating]:
344
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
353
345
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
354
346
 
355
347
  def mean(self) -> float:
@@ -387,9 +379,7 @@ class ChiSquared(Distribution):
387
379
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
388
380
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
389
381
 
390
- def sample(
391
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
392
- ) -> NDArray[np.floating]:
382
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
393
383
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
394
384
 
395
385
  def mean(self) -> float:
@@ -436,9 +426,7 @@ class StudentT(Distribution):
436
426
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
437
427
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
438
428
 
439
- def sample(
440
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
441
- ) -> NDArray[np.floating]:
429
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
442
430
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
443
431
 
444
432
  def mean(self) -> float:
@@ -485,9 +473,7 @@ class Beta(Distribution):
485
473
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
486
474
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
487
475
 
488
- def sample(
489
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
490
- ) -> NDArray[np.floating]:
476
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
491
477
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
492
478
 
493
479
  def mean(self) -> float:
@@ -528,9 +514,7 @@ class Poisson(Distribution):
528
514
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
529
515
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
530
516
 
531
- def sample(
532
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
533
- ) -> NDArray[np.floating]:
517
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
534
518
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
535
519
 
536
520
  def mean(self) -> float:
@@ -573,9 +557,7 @@ class VonMises(Distribution):
573
557
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
574
558
  return np.asarray(self._dist.ppf(q), dtype=np.float64)
575
559
 
576
- def sample(
577
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
578
- ) -> NDArray[np.floating]:
560
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
579
561
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
580
562
 
581
563
  def mean(self) -> float:
@@ -583,7 +565,8 @@ class VonMises(Distribution):
583
565
 
584
566
  def var(self) -> float:
585
567
  # Circular variance: 1 - I_1(kappa)/I_0(kappa)
586
- from scipy.special import i0, i1
568
+ from scipy.special import i0
569
+ from scipy.special import i1
587
570
 
588
571
  return 1 - i1(self._kappa) / i0(self._kappa)
589
572
 
@@ -628,9 +611,7 @@ class Wishart(Distribution):
628
611
  def ppf(self, q: ArrayLike) -> NDArray[np.floating]:
629
612
  raise NotImplementedError("PPF not available for Wishart distribution")
630
613
 
631
- def sample(
632
- self, size: Optional[Union[int, Tuple[int, ...]]] = None
633
- ) -> NDArray[np.floating]:
614
+ def sample(self, size: Optional[Union[int, Tuple[int, ...]]] = None) -> NDArray[np.floating]:
634
615
  return np.asarray(self._dist.rvs(size=size), dtype=np.float64)
635
616
 
636
617
  def mean(self) -> NDArray[np.floating]:
@@ -8,7 +8,8 @@ robust estimators, and related quantities used in tracking applications.
8
8
  from typing import Optional
9
9
 
10
10
  import numpy as np
11
- from numpy.typing import ArrayLike, NDArray
11
+ from numpy.typing import ArrayLike
12
+ from numpy.typing import NDArray
12
13
 
13
14
 
14
15
  def weighted_mean(
@@ -364,9 +365,7 @@ def kurtosis(
364
365
  """
365
366
  from scipy.stats import kurtosis as scipy_kurtosis
366
367
 
367
- return np.asarray(
368
- scipy_kurtosis(x, axis=axis, fisher=fisher, bias=bias), dtype=np.float64
369
- )
368
+ return np.asarray(scipy_kurtosis(x, axis=axis, fisher=fisher, bias=bias), dtype=np.float64)
370
369
 
371
370
 
372
371
  def moment(