nrl-tracker 1.7.1__tar.gz → 1.7.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. {nrl_tracker-1.7.1/nrl_tracker.egg-info → nrl_tracker-1.7.3}/PKG-INFO +42 -3
  2. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/README.md +41 -2
  3. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3/nrl_tracker.egg-info}/PKG-INFO +42 -3
  4. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pyproject.toml +1 -1
  5. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/__init__.py +1 -1
  6. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/__init__.py +3 -3
  7. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/projections/__init__.py +1 -1
  8. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/conftest.py +3 -1
  9. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_assignment_algorithms.py +1 -1
  10. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_astronomical.py +3 -1
  11. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_coordinate_systems.py +6 -2
  12. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_coverage_boost.py +3 -1
  13. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_coverage_boost_2.py +9 -3
  14. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_egm.py +54 -18
  15. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_emm.py +42 -14
  16. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_ephemerides.py +6 -2
  17. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_gaussian_mixtures.py +2 -1
  18. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_gaussian_sum_filter.py +3 -1
  19. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_great_circle.py +3 -1
  20. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_ins.py +3 -1
  21. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_ins_gnss.py +9 -3
  22. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_nd_assignment.py +9 -3
  23. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_nrlmsise00.py +114 -19
  24. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_projections.py +3 -1
  25. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_rbpf.py +46 -15
  26. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_relativity.py +9 -3
  27. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_smoothers.py +12 -4
  28. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_special_functions_phase12.py +1 -1
  29. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_static_estimation.py +9 -3
  30. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_tides.py +12 -4
  31. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_trackers.py +12 -4
  32. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_v030_comprehensive.py +9 -3
  33. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_v030_features.py +3 -1
  34. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/CONTRIBUTING.md +0 -0
  35. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/LICENSE +0 -0
  36. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/MANIFEST.in +0 -0
  37. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/nrl_tracker.egg-info/SOURCES.txt +0 -0
  38. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/nrl_tracker.egg-info/dependency_links.txt +0 -0
  39. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/nrl_tracker.egg-info/requires.txt +0 -0
  40. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/nrl_tracker.egg-info/top_level.txt +0 -0
  41. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/__init__.py +0 -0
  42. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/data_association.py +0 -0
  43. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/gating.py +0 -0
  44. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/jpda.py +0 -0
  45. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/nd_assignment.py +0 -0
  46. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/network_flow.py +0 -0
  47. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/three_dimensional/__init__.py +0 -0
  48. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/three_dimensional/assignment.py +0 -0
  49. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/two_dimensional/__init__.py +0 -0
  50. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/two_dimensional/assignment.py +0 -0
  51. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/assignment_algorithms/two_dimensional/kbest.py +0 -0
  52. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/ephemerides.py +0 -0
  53. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/lambert.py +0 -0
  54. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/orbital_mechanics.py +0 -0
  55. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/reference_frames.py +0 -0
  56. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/relativity.py +0 -0
  57. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/sgp4.py +0 -0
  58. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/special_orbits.py +0 -0
  59. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/time_systems.py +0 -0
  60. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/astronomical/tle.py +0 -0
  61. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/atmosphere/__init__.py +0 -0
  62. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/atmosphere/ionosphere.py +0 -0
  63. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/atmosphere/models.py +0 -0
  64. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/atmosphere/nrlmsise00.py +0 -0
  65. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/clustering/__init__.py +0 -0
  66. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/clustering/dbscan.py +0 -0
  67. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/clustering/gaussian_mixture.py +0 -0
  68. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/clustering/hierarchical.py +0 -0
  69. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/clustering/kmeans.py +0 -0
  70. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/__init__.py +0 -0
  71. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/base.py +0 -0
  72. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/cluster_set.py +0 -0
  73. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/covertree.py +0 -0
  74. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/kd_tree.py +0 -0
  75. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/measurement_set.py +0 -0
  76. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/rtree.py +0 -0
  77. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/track_list.py +0 -0
  78. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/containers/vptree.py +0 -0
  79. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/__init__.py +0 -0
  80. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/conversions/__init__.py +0 -0
  81. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/conversions/geodetic.py +0 -0
  82. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/conversions/spherical.py +0 -0
  83. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/jacobians/__init__.py +0 -0
  84. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/jacobians/jacobians.py +0 -0
  85. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/projections/projections.py +0 -0
  86. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/rotations/__init__.py +0 -0
  87. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/coordinate_systems/rotations/rotations.py +0 -0
  88. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/core/__init__.py +0 -0
  89. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/core/array_utils.py +0 -0
  90. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/core/constants.py +0 -0
  91. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/core/validation.py +0 -0
  92. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/__init__.py +0 -0
  93. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/batch_estimation/__init__.py +0 -0
  94. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/gaussian_sum_filter.py +0 -0
  95. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/imm.py +0 -0
  96. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/information_filter.py +0 -0
  97. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/__init__.py +0 -0
  98. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/constrained.py +0 -0
  99. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/extended.py +0 -0
  100. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/h_infinity.py +0 -0
  101. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/linear.py +0 -0
  102. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/square_root.py +0 -0
  103. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/sr_ukf.py +0 -0
  104. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/ud_filter.py +0 -0
  105. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/kalman/unscented.py +0 -0
  106. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/measurement_update/__init__.py +0 -0
  107. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/particle_filters/__init__.py +0 -0
  108. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/particle_filters/bootstrap.py +0 -0
  109. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/rbpf.py +0 -0
  110. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_estimation/smoothers.py +0 -0
  111. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/__init__.py +0 -0
  112. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/continuous_time/__init__.py +0 -0
  113. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/continuous_time/dynamics.py +0 -0
  114. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/discrete_time/__init__.py +0 -0
  115. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/discrete_time/coordinated_turn.py +0 -0
  116. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/discrete_time/polynomial.py +0 -0
  117. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/discrete_time/singer.py +0 -0
  118. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/process_noise/__init__.py +0 -0
  119. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/process_noise/coordinated_turn.py +0 -0
  120. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/process_noise/polynomial.py +0 -0
  121. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/dynamic_models/process_noise/singer.py +0 -0
  122. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/gravity/__init__.py +0 -0
  123. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/gravity/clenshaw.py +0 -0
  124. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/gravity/egm.py +0 -0
  125. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/gravity/models.py +0 -0
  126. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/gravity/spherical_harmonics.py +0 -0
  127. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/gravity/tides.py +0 -0
  128. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/logging_config.py +0 -0
  129. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/magnetism/__init__.py +0 -0
  130. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/magnetism/emm.py +0 -0
  131. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/magnetism/igrf.py +0 -0
  132. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/magnetism/wmm.py +0 -0
  133. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/__init__.py +0 -0
  134. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/basic_matrix/__init__.py +0 -0
  135. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/basic_matrix/decompositions.py +0 -0
  136. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/basic_matrix/special_matrices.py +0 -0
  137. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/combinatorics/__init__.py +0 -0
  138. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/combinatorics/combinatorics.py +0 -0
  139. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/continuous_optimization/__init__.py +0 -0
  140. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/geometry/__init__.py +0 -0
  141. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/geometry/geometry.py +0 -0
  142. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/interpolation/__init__.py +0 -0
  143. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/interpolation/interpolation.py +0 -0
  144. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/numerical_integration/__init__.py +0 -0
  145. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/numerical_integration/quadrature.py +0 -0
  146. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/polynomials/__init__.py +0 -0
  147. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/signal_processing/__init__.py +0 -0
  148. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/signal_processing/detection.py +0 -0
  149. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/signal_processing/filters.py +0 -0
  150. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/signal_processing/matched_filter.py +0 -0
  151. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/__init__.py +0 -0
  152. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/bessel.py +0 -0
  153. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/debye.py +0 -0
  154. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/elliptic.py +0 -0
  155. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/error_functions.py +0 -0
  156. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/gamma_functions.py +0 -0
  157. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/hypergeometric.py +0 -0
  158. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/lambert_w.py +0 -0
  159. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/special_functions/marcum_q.py +0 -0
  160. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/statistics/__init__.py +0 -0
  161. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/statistics/distributions.py +0 -0
  162. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/statistics/estimators.py +0 -0
  163. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/transforms/__init__.py +0 -0
  164. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/transforms/fourier.py +0 -0
  165. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/transforms/stft.py +0 -0
  166. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/mathematical_functions/transforms/wavelets.py +0 -0
  167. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/misc/__init__.py +0 -0
  168. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/navigation/__init__.py +0 -0
  169. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/navigation/geodesy.py +0 -0
  170. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/navigation/great_circle.py +0 -0
  171. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/navigation/ins.py +0 -0
  172. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/navigation/ins_gnss.py +0 -0
  173. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/navigation/rhumb.py +0 -0
  174. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/performance_evaluation/__init__.py +0 -0
  175. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/performance_evaluation/estimation_metrics.py +0 -0
  176. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/performance_evaluation/track_metrics.py +0 -0
  177. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/physical_values/__init__.py +0 -0
  178. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/plotting/__init__.py +0 -0
  179. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/plotting/coordinates.py +0 -0
  180. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/plotting/ellipses.py +0 -0
  181. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/plotting/metrics.py +0 -0
  182. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/plotting/tracks.py +0 -0
  183. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/scheduling/__init__.py +0 -0
  184. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/static_estimation/__init__.py +0 -0
  185. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/static_estimation/least_squares.py +0 -0
  186. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/static_estimation/maximum_likelihood.py +0 -0
  187. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/static_estimation/robust.py +0 -0
  188. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/terrain/__init__.py +0 -0
  189. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/terrain/dem.py +0 -0
  190. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/terrain/loaders.py +0 -0
  191. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/terrain/visibility.py +0 -0
  192. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/trackers/__init__.py +0 -0
  193. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/trackers/hypothesis.py +0 -0
  194. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/trackers/mht.py +0 -0
  195. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/trackers/multi_target.py +0 -0
  196. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/trackers/single_target.py +0 -0
  197. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/pytcl/transponders/__init__.py +0 -0
  198. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/setup.cfg +0 -0
  199. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/__init__.py +0 -0
  200. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_additional_trees.py +0 -0
  201. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_clustering.py +0 -0
  202. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_constrained_ekf.py +0 -0
  203. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_dynamic_models.py +0 -0
  204. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_geophysical.py +0 -0
  205. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_h_infinity.py +0 -0
  206. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_kalman_filters.py +0 -0
  207. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_mathematical_functions.py +0 -0
  208. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_maximum_likelihood.py +0 -0
  209. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_mht.py +0 -0
  210. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_network_flow.py +0 -0
  211. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_performance_evaluation.py +0 -0
  212. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_phase6_specialized.py +0 -0
  213. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_plotting.py +0 -0
  214. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_rhumb.py +0 -0
  215. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_sgp4.py +0 -0
  216. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_signal_processing.py +0 -0
  217. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_spatial_containers_parametrized.py +0 -0
  218. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_spatial_structures.py +0 -0
  219. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_special_orbits.py +0 -0
  220. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_terrain.py +0 -0
  221. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_terrain_loaders.py +0 -0
  222. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_tod_mod.py +0 -0
  223. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_tracking_containers.py +0 -0
  224. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_transforms.py +0 -0
  225. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/test_validation.py +0 -0
  226. {nrl_tracker-1.7.1 → nrl_tracker-1.7.3}/tests/unit/test_core.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nrl-tracker
3
- Version: 1.7.1
3
+ Version: 1.7.3
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
@@ -63,7 +63,7 @@ Requires-Dist: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualizati
63
63
 
64
64
  # Tracker Component Library (Python)
65
65
 
66
- [![PyPI version](https://img.shields.io/badge/pypi-v1.7.1-blue.svg)](https://pypi.org/project/nrl-tracker/)
66
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.7.2-blue.svg)](https://pypi.org/project/nrl-tracker/)
67
67
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
68
68
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
69
69
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
@@ -209,7 +209,46 @@ pytcl/
209
209
 
210
210
  - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
211
211
  - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
212
- - [Examples](examples/)
212
+ - [Examples](examples/) - 29 validated example scripts
213
+ - [Tutorials](docs/tutorials/) - 10 interactive tutorial modules
214
+
215
+ ## Examples & Tutorials
216
+
217
+ The library includes 39 runnable code examples demonstrating all major features:
218
+
219
+ ### Examples (29 files in `/examples/`)
220
+
221
+ Comprehensive demonstrations of library functionality:
222
+ - **Tracking & Estimation**: Kalman filters, particle filters, smoothers
223
+ - **Assignment**: Hungarian algorithm, k-best assignments, 3D assignment
224
+ - **Coordinates**: Frame conversions, transformations, geodetic calculations
225
+ - **Dynamics**: State models, motion models, dynamic systems
226
+ - **Filtering**: Uncertainty visualization, multi-target tracking
227
+ - **Astronomy**: Ephemerides, orbital mechanics, relativistic corrections
228
+ - **Navigation**: INS/GNSS integration, geophysical modeling
229
+ - **Signal Processing**: Detection, filtering, transforms
230
+ - **Terrain & Atmosphere**: Elevation models, atmospheric properties
231
+
232
+ **Status**: ✅ All 29 examples validated and passing (100% execution success)
233
+
234
+ ### Tutorials (10 modules in `/docs/tutorials/`)
235
+
236
+ Interactive learning modules with visualizations:
237
+ - Assignment algorithms and 3D assignment problems
238
+ - Atmospheric and geophysical models
239
+ - Dynamical systems and reference frames
240
+ - Filtering and smoothing techniques
241
+ - Sensor fusion and advanced filtering
242
+ - Special functions and mathematical tools
243
+
244
+ **Status**: ✅ All 10 tutorials validated and passing (100% execution success)
245
+
246
+ ## Documentation
247
+
248
+ - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
249
+ - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
250
+ - [Examples](examples/) - 29 validated example scripts
251
+ - [Tutorials](docs/tutorials/) - 10 interactive tutorial modules
213
252
 
214
253
  ## Comparison with Original MATLAB Library
215
254
 
@@ -1,6 +1,6 @@
1
1
  # Tracker Component Library (Python)
2
2
 
3
- [![PyPI version](https://img.shields.io/badge/pypi-v1.7.1-blue.svg)](https://pypi.org/project/nrl-tracker/)
3
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.7.2-blue.svg)](https://pypi.org/project/nrl-tracker/)
4
4
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
5
5
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
6
6
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
@@ -146,7 +146,46 @@ pytcl/
146
146
 
147
147
  - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
148
148
  - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
149
- - [Examples](examples/)
149
+ - [Examples](examples/) - 29 validated example scripts
150
+ - [Tutorials](docs/tutorials/) - 10 interactive tutorial modules
151
+
152
+ ## Examples & Tutorials
153
+
154
+ The library includes 39 runnable code examples demonstrating all major features:
155
+
156
+ ### Examples (29 files in `/examples/`)
157
+
158
+ Comprehensive demonstrations of library functionality:
159
+ - **Tracking & Estimation**: Kalman filters, particle filters, smoothers
160
+ - **Assignment**: Hungarian algorithm, k-best assignments, 3D assignment
161
+ - **Coordinates**: Frame conversions, transformations, geodetic calculations
162
+ - **Dynamics**: State models, motion models, dynamic systems
163
+ - **Filtering**: Uncertainty visualization, multi-target tracking
164
+ - **Astronomy**: Ephemerides, orbital mechanics, relativistic corrections
165
+ - **Navigation**: INS/GNSS integration, geophysical modeling
166
+ - **Signal Processing**: Detection, filtering, transforms
167
+ - **Terrain & Atmosphere**: Elevation models, atmospheric properties
168
+
169
+ **Status**: ✅ All 29 examples validated and passing (100% execution success)
170
+
171
+ ### Tutorials (10 modules in `/docs/tutorials/`)
172
+
173
+ Interactive learning modules with visualizations:
174
+ - Assignment algorithms and 3D assignment problems
175
+ - Atmospheric and geophysical models
176
+ - Dynamical systems and reference frames
177
+ - Filtering and smoothing techniques
178
+ - Sensor fusion and advanced filtering
179
+ - Special functions and mathematical tools
180
+
181
+ **Status**: ✅ All 10 tutorials validated and passing (100% execution success)
182
+
183
+ ## Documentation
184
+
185
+ - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
186
+ - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
187
+ - [Examples](examples/) - 29 validated example scripts
188
+ - [Tutorials](docs/tutorials/) - 10 interactive tutorial modules
150
189
 
151
190
  ## Comparison with Original MATLAB Library
152
191
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nrl-tracker
3
- Version: 1.7.1
3
+ Version: 1.7.3
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
@@ -63,7 +63,7 @@ Requires-Dist: nrl-tracker[astronomy,dev,geodesy,optimization,signal,visualizati
63
63
 
64
64
  # Tracker Component Library (Python)
65
65
 
66
- [![PyPI version](https://img.shields.io/badge/pypi-v1.7.1-blue.svg)](https://pypi.org/project/nrl-tracker/)
66
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.7.2-blue.svg)](https://pypi.org/project/nrl-tracker/)
67
67
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
68
68
  [![License: Public Domain](https://img.shields.io/badge/License-Public%20Domain-brightgreen.svg)](https://en.wikipedia.org/wiki/Public_domain)
69
69
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
@@ -209,7 +209,46 @@ pytcl/
209
209
 
210
210
  - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
211
211
  - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
212
- - [Examples](examples/)
212
+ - [Examples](examples/) - 29 validated example scripts
213
+ - [Tutorials](docs/tutorials/) - 10 interactive tutorial modules
214
+
215
+ ## Examples & Tutorials
216
+
217
+ The library includes 39 runnable code examples demonstrating all major features:
218
+
219
+ ### Examples (29 files in `/examples/`)
220
+
221
+ Comprehensive demonstrations of library functionality:
222
+ - **Tracking & Estimation**: Kalman filters, particle filters, smoothers
223
+ - **Assignment**: Hungarian algorithm, k-best assignments, 3D assignment
224
+ - **Coordinates**: Frame conversions, transformations, geodetic calculations
225
+ - **Dynamics**: State models, motion models, dynamic systems
226
+ - **Filtering**: Uncertainty visualization, multi-target tracking
227
+ - **Astronomy**: Ephemerides, orbital mechanics, relativistic corrections
228
+ - **Navigation**: INS/GNSS integration, geophysical modeling
229
+ - **Signal Processing**: Detection, filtering, transforms
230
+ - **Terrain & Atmosphere**: Elevation models, atmospheric properties
231
+
232
+ **Status**: ✅ All 29 examples validated and passing (100% execution success)
233
+
234
+ ### Tutorials (10 modules in `/docs/tutorials/`)
235
+
236
+ Interactive learning modules with visualizations:
237
+ - Assignment algorithms and 3D assignment problems
238
+ - Atmospheric and geophysical models
239
+ - Dynamical systems and reference frames
240
+ - Filtering and smoothing techniques
241
+ - Sensor fusion and advanced filtering
242
+ - Special functions and mathematical tools
243
+
244
+ **Status**: ✅ All 10 tutorials validated and passing (100% execution success)
245
+
246
+ ## Documentation
247
+
248
+ - [API Reference](https://pytcl.readthedocs.io/en/latest/api/)
249
+ - [User Guides](https://pytcl.readthedocs.io/en/latest/user_guide/)
250
+ - [Examples](examples/) - 29 validated example scripts
251
+ - [Tutorials](docs/tutorials/) - 10 interactive tutorial modules
213
252
 
214
253
  ## Comparison with Original MATLAB Library
215
254
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nrl-tracker"
7
- version = "1.7.1"
7
+ version = "1.7.3"
8
8
  description = "Python port of the U.S. Naval Research Laboratory's Tracker Component Library for target tracking algorithms"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -20,7 +20,7 @@ References
20
20
  no. 5, pp. 18-27, May 2017.
21
21
  """
22
22
 
23
- __version__ = "1.7.1"
23
+ __version__ = "1.7.3"
24
24
  __author__ = "Python Port Contributors"
25
25
  __original_author__ = "David F. Crouse, Naval Research Laboratory"
26
26
 
@@ -77,10 +77,10 @@ from pytcl.astronomical.orbital_mechanics import (
77
77
  vis_viva,
78
78
  )
79
79
  from pytcl.astronomical.reference_frames import (
80
- earth_rotation_angle, # Time utilities; Precession; Nutation; Earth rotation; Polar motion; Full transformations; Ecliptic/equatorial
80
+ earth_rotation_angle, # Time utilities; Precession; Nutation
81
81
  )
82
+ from pytcl.astronomical.reference_frames import ecef_to_eci # Time utilities
82
83
  from pytcl.astronomical.reference_frames import (
83
- ecef_to_eci,
84
84
  eci_to_ecef,
85
85
  ecliptic_to_equatorial,
86
86
  equation_of_equinoxes,
@@ -116,7 +116,7 @@ from pytcl.astronomical.reference_frames import (
116
116
  true_obliquity,
117
117
  )
118
118
  from pytcl.astronomical.relativity import (
119
- C_LIGHT, # Physical constants; Schwarzschild metric; Time dilation; Shapiro delay; Precession; PN effects; Range corrections
119
+ C_LIGHT, # Physical constants; Schwarzschild metric; Time dilation
120
120
  )
121
121
  from pytcl.astronomical.relativity import (
122
122
  G_GRAV,
@@ -27,7 +27,7 @@ Examples
27
27
  """
28
28
 
29
29
  from pytcl.coordinate_systems.projections.projections import (
30
- WGS84_A, # Constants; Result types; Azimuthal Equidistant; UTM; Lambert Conformal Conic; Mercator; Stereographic; Transverse Mercator
30
+ WGS84_A, # Constants; Result types
31
31
  )
32
32
  from pytcl.coordinate_systems.projections.projections import (
33
33
  WGS84_B,
@@ -82,7 +82,9 @@ class NumpyTestCase:
82
82
 
83
83
  def assert_shape(self, arr, expected_shape):
84
84
  """Assert array has expected shape."""
85
- assert arr.shape == expected_shape, f"Expected shape {expected_shape}, got {arr.shape}"
85
+ assert (
86
+ arr.shape == expected_shape
87
+ ), f"Expected shape {expected_shape}, got {arr.shape}"
86
88
 
87
89
  def assert_symmetric(self, arr, rtol=1e-10):
88
90
  """Assert matrix is symmetric."""
@@ -3,7 +3,7 @@
3
3
  import numpy as np
4
4
  from numpy.testing import assert_allclose
5
5
 
6
- from pytcl.assignment_algorithms import ( # 2D Assignment; K-Best 2D Assignment; 3D Assignment; Gating; Data Association
6
+ from pytcl.assignment_algorithms import ( # 2D Assignment
7
7
  Assignment3DResult,
8
8
  AssignmentResult,
9
9
  AssociationResult,
@@ -150,7 +150,9 @@ class TestOrbitalElementConversions:
150
150
 
151
151
  def test_roundtrip_elements_state(self):
152
152
  """Test elements -> state -> elements roundtrip."""
153
- elements_orig = OrbitalElements(a=8000, e=0.2, i=0.5, raan=0.3, omega=0.8, nu=1.0)
153
+ elements_orig = OrbitalElements(
154
+ a=8000, e=0.2, i=0.5, raan=0.3, omega=0.8, nu=1.0
155
+ )
154
156
  state = orbital_elements_to_state(elements_orig)
155
157
  elements_back = state_to_orbital_elements(state)
156
158
 
@@ -403,7 +403,9 @@ class TestSlerp:
403
403
 
404
404
  # Should be 45 deg rotation about z
405
405
  expected_angle = angle / 2
406
- expected = np.array([np.cos(expected_angle / 2), 0, 0, np.sin(expected_angle / 2)])
406
+ expected = np.array(
407
+ [np.cos(expected_angle / 2), 0, 0, np.sin(expected_angle / 2)]
408
+ )
407
409
  np.testing.assert_allclose(result, expected, atol=1e-10)
408
410
 
409
411
 
@@ -1315,4 +1317,6 @@ class TestSEZConversions:
1315
1317
  # For northward target, the magnitude should be large and east component small
1316
1318
  total_distance = np.linalg.norm(sez)
1317
1319
  assert total_distance > 100000, "Distance should be significant"
1318
- assert abs(sez[1]) < abs(sez[0]), "East component should be smaller than meridional"
1320
+ assert abs(sez[1]) < abs(
1321
+ sez[0]
1322
+ ), "East component should be smaller than meridional"
@@ -438,7 +438,9 @@ class TestCoordinatedTurnProcessNoise:
438
438
  T = 0.1
439
439
  sigma_a = 1.0
440
440
  sigma_omega = 0.01
441
- Q = q_coord_turn_2d(T, sigma_a, sigma_omega, state_type="position_velocity_omega")
441
+ Q = q_coord_turn_2d(
442
+ T, sigma_a, sigma_omega, state_type="position_velocity_omega"
443
+ )
442
444
  assert Q.shape == (5, 5)
443
445
  np.testing.assert_allclose(Q, Q.T)
444
446
 
@@ -121,7 +121,9 @@ class TestParticleFilters:
121
121
  def likelihood_func(z, x):
122
122
  return gaussian_likelihood(z, x, R)
123
123
 
124
- new_weights, log_lik = bootstrap_pf_update(particles, weights, z, likelihood_func)
124
+ new_weights, log_lik = bootstrap_pf_update(
125
+ particles, weights, z, likelihood_func
126
+ )
125
127
 
126
128
  assert new_weights.shape == weights.shape
127
129
  assert np.isclose(np.sum(new_weights), 1.0)
@@ -325,7 +327,9 @@ class TestParticleFilters:
325
327
 
326
328
  mean = particle_mean(particles, weights)
327
329
 
328
- expected = 0.5 * np.array([0, 0]) + 0.3 * np.array([1, 1]) + 0.2 * np.array([2, 2])
330
+ expected = (
331
+ 0.5 * np.array([0, 0]) + 0.3 * np.array([1, 1]) + 0.2 * np.array([2, 2])
332
+ )
329
333
  assert np.allclose(mean, expected)
330
334
 
331
335
  def test_particle_covariance(self):
@@ -991,7 +995,9 @@ class TestNavigationCoverage:
991
995
  tdoa12 = 0.0
992
996
  tdoa13 = 0.0
993
997
 
994
- result1, result2 = great_circle_tdoa_loc(lat1, lon1, lat2, lon2, lat3, lon3, tdoa12, tdoa13)
998
+ result1, result2 = great_circle_tdoa_loc(
999
+ lat1, lon1, lat2, lon2, lat3, lon3, tdoa12, tdoa13
1000
+ )
995
1001
 
996
1002
  # Should return at least one solution
997
1003
  assert result1 is not None or result2 is not None
@@ -98,7 +98,9 @@ class TestClenshawSumOrderDerivative:
98
98
  cos_theta = 0.5
99
99
  sin_theta = np.sqrt(1 - cos_theta**2)
100
100
 
101
- result = clenshaw_sum_order_derivative(0, cos_theta, sin_theta, coef.C, coef.S, 10)
101
+ result = clenshaw_sum_order_derivative(
102
+ 0, cos_theta, sin_theta, coef.C, coef.S, 10
103
+ )
102
104
 
103
105
  assert isinstance(result, tuple)
104
106
  assert len(result) == 4
@@ -140,8 +142,12 @@ class TestClenshawPotential:
140
142
  lat = np.radians(30)
141
143
  lon = 0
142
144
 
143
- V_close = clenshaw_potential(lat, lon, coef.R, coef.C, coef.S, coef.R, coef.GM, 10)
144
- V_far = clenshaw_potential(lat, lon, coef.R * 1.1, coef.C, coef.S, coef.R, coef.GM, 10)
145
+ V_close = clenshaw_potential(
146
+ lat, lon, coef.R, coef.C, coef.S, coef.R, coef.GM, 10
147
+ )
148
+ V_far = clenshaw_potential(
149
+ lat, lon, coef.R * 1.1, coef.C, coef.S, coef.R, coef.GM, 10
150
+ )
145
151
 
146
152
  # Potential magnitude should decrease with distance
147
153
  assert abs(V_far) < abs(V_close)
@@ -152,8 +158,12 @@ class TestClenshawPotential:
152
158
  lon = 0
153
159
  r = coef.R
154
160
 
155
- V_north = clenshaw_potential(np.radians(45), lon, r, coef.C, coef.S, coef.R, coef.GM, 10)
156
- V_south = clenshaw_potential(np.radians(-45), lon, r, coef.C, coef.S, coef.R, coef.GM, 10)
161
+ V_north = clenshaw_potential(
162
+ np.radians(45), lon, r, coef.C, coef.S, coef.R, coef.GM, 10
163
+ )
164
+ V_south = clenshaw_potential(
165
+ np.radians(-45), lon, r, coef.C, coef.S, coef.R, coef.GM, 10
166
+ )
157
167
 
158
168
  # For Earth's gravity field (with small asymmetries), should be close
159
169
  # The potential is dominated by the central term, so relative difference is small
@@ -185,7 +195,9 @@ class TestClenshawGravity:
185
195
  lon = np.radians(0)
186
196
  r = coef.R
187
197
 
188
- g_r, g_lat, g_lon = clenshaw_gravity(lat, lon, r, coef.C, coef.S, coef.R, coef.GM, 10)
198
+ g_r, g_lat, g_lon = clenshaw_gravity(
199
+ lat, lon, r, coef.C, coef.S, coef.R, coef.GM, 10
200
+ )
189
201
 
190
202
  # Full gravity includes the central term GM/r^2 which is about 9.8 m/s^2
191
203
  # The sign depends on convention - we compute -dV/dr
@@ -245,7 +257,9 @@ class TestAssociatedLegendreScaled:
245
257
  for m in range(n + 1):
246
258
  # exp is indexed by degree only (1D array)
247
259
  P_reconstructed = P_scaled[n, m] * (10.0 ** exp[n])
248
- assert_allclose(P_reconstructed, P_unscaled[n, m], rtol=1e-8, atol=1e-12)
260
+ assert_allclose(
261
+ P_reconstructed, P_unscaled[n, m], rtol=1e-8, atol=1e-12
262
+ )
249
263
 
250
264
  def test_no_overflow_high_degree(self):
251
265
  """High degree computation doesn't overflow."""
@@ -306,7 +320,9 @@ class TestGeoidHeight:
306
320
  # Test several locations
307
321
  for lat in [0, 45, -45, 90]:
308
322
  for lon in [0, 90, -90, 180]:
309
- N = geoid_height(np.radians(lat), np.radians(lon), coefficients=coef, n_max=36)
323
+ N = geoid_height(
324
+ np.radians(lat), np.radians(lon), coefficients=coef, n_max=36
325
+ )
310
326
  assert not np.isnan(N)
311
327
  assert not np.isinf(N)
312
328
 
@@ -332,7 +348,9 @@ class TestGeoidHeights:
332
348
  lon = np.radians(-75)
333
349
 
334
350
  N_single = geoid_height(lat, lon, coefficients=coef, n_max=10)
335
- N_batch = geoid_heights(np.array([lat]), np.array([lon]), coefficients=coef, n_max=10)
351
+ N_batch = geoid_heights(
352
+ np.array([lat]), np.array([lon]), coefficients=coef, n_max=10
353
+ )
336
354
 
337
355
  assert_allclose(N_batch[0], N_single)
338
356
 
@@ -362,7 +380,9 @@ class TestGravityDisturbance:
362
380
  np.radians(30), np.radians(60), h=0.0, coefficients=coef, n_max=10
363
381
  )
364
382
 
365
- expected_mag = np.sqrt(result.delta_g_r**2 + result.delta_g_lat**2 + result.delta_g_lon**2)
383
+ expected_mag = np.sqrt(
384
+ result.delta_g_r**2 + result.delta_g_lat**2 + result.delta_g_lon**2
385
+ )
366
386
  assert_allclose(result.magnitude, expected_mag)
367
387
 
368
388
  def test_disturbance_decreases_with_altitude(self):
@@ -372,7 +392,9 @@ class TestGravityDisturbance:
372
392
  lon = np.radians(0)
373
393
 
374
394
  result_0 = gravity_disturbance(lat, lon, h=0.0, coefficients=coef, n_max=20)
375
- result_10km = gravity_disturbance(lat, lon, h=10000.0, coefficients=coef, n_max=20)
395
+ result_10km = gravity_disturbance(
396
+ lat, lon, h=10000.0, coefficients=coef, n_max=20
397
+ )
376
398
 
377
399
  # Disturbance magnitude should decrease with altitude
378
400
  assert result_10km.magnitude < result_0.magnitude
@@ -385,7 +407,9 @@ class TestGravityAnomaly:
385
407
  """gravity_anomaly returns a float."""
386
408
  coef = create_test_coefficients(n_max=10)
387
409
 
388
- anom = gravity_anomaly(np.radians(45), np.radians(-75), h=0.0, coefficients=coef, n_max=10)
410
+ anom = gravity_anomaly(
411
+ np.radians(45), np.radians(-75), h=0.0, coefficients=coef, n_max=10
412
+ )
389
413
 
390
414
  assert isinstance(anom, float)
391
415
  assert not np.isnan(anom)
@@ -394,7 +418,9 @@ class TestGravityAnomaly:
394
418
  """Gravity anomaly computation produces finite values."""
395
419
  coef = create_test_coefficients(n_max=36)
396
420
 
397
- anom = gravity_anomaly(np.radians(45), np.radians(0), h=0.0, coefficients=coef, n_max=36)
421
+ anom = gravity_anomaly(
422
+ np.radians(45), np.radians(0), h=0.0, coefficients=coef, n_max=36
423
+ )
398
424
 
399
425
  # Note: With test coefficients (including full J2), values are large
400
426
  # because J2 represents the equatorial bulge which is part of the
@@ -423,7 +449,9 @@ class TestDeflectionOfVertical:
423
449
  """Deflection values are finite."""
424
450
  coef = create_test_coefficients(n_max=36)
425
451
 
426
- xi, eta = deflection_of_vertical(np.radians(45), np.radians(0), coefficients=coef, n_max=36)
452
+ xi, eta = deflection_of_vertical(
453
+ np.radians(45), np.radians(0), coefficients=coef, n_max=36
454
+ )
427
455
 
428
456
  # Note: Test coefficients include full J2, so deflections are larger
429
457
  # than real-world values which are typically < 60 arcseconds.
@@ -493,12 +521,16 @@ class TestClenshawVsNaive:
493
521
  r = coef.R
494
522
 
495
523
  # Compute potential using Clenshaw
496
- V_clenshaw = clenshaw_potential(lat, lon, r, coef.C, coef.S, coef.R, coef.GM, 10)
524
+ V_clenshaw = clenshaw_potential(
525
+ lat, lon, r, coef.C, coef.S, coef.R, coef.GM, 10
526
+ )
497
527
 
498
528
  # Compute using naive spherical harmonic sum
499
529
  # spherical_harmonic_sum takes (lat, lon, r, C, S, R, GM, n_max)
500
530
  # and returns (V, dV_r, dV_lat)
501
- V_naive, _, _ = spherical_harmonic_sum(lat, lon, r, coef.C, coef.S, coef.R, coef.GM, 10)
531
+ V_naive, _, _ = spherical_harmonic_sum(
532
+ lat, lon, r, coef.C, coef.S, coef.R, coef.GM, 10
533
+ )
502
534
 
503
535
  # Should match to reasonable precision
504
536
  # (Clenshaw and naive may have different numerical properties)
@@ -546,8 +578,12 @@ class TestEdgeCases:
546
578
  """Negative longitude works correctly."""
547
579
  coef = create_test_coefficients(n_max=20)
548
580
 
549
- N_pos = geoid_height(np.radians(45), np.radians(90), coefficients=coef, n_max=20)
550
- N_neg = geoid_height(np.radians(45), np.radians(-270), coefficients=coef, n_max=20)
581
+ N_pos = geoid_height(
582
+ np.radians(45), np.radians(90), coefficients=coef, n_max=20
583
+ )
584
+ N_neg = geoid_height(
585
+ np.radians(45), np.radians(-270), coefficients=coef, n_max=20
586
+ )
551
587
 
552
588
  # 90° and -270° are the same longitude
553
589
  assert_allclose(N_pos, N_neg, rtol=1e-10)
@@ -130,31 +130,41 @@ class TestEMMFunction:
130
130
 
131
131
  def test_total_intensity_reasonable(self, test_coefficients):
132
132
  """Total field intensity should be in expected range."""
133
- result = emm(np.radians(45), np.radians(0), 0, 2020.0, coefficients=test_coefficients)
133
+ result = emm(
134
+ np.radians(45), np.radians(0), 0, 2020.0, coefficients=test_coefficients
135
+ )
134
136
  # Field intensity typically 25,000-65,000 nT at mid-latitudes
135
137
  # but can exceed this at high latitudes, allow up to 100,000 nT
136
138
  assert 20000 < result.F < 100000
137
139
 
138
140
  def test_horizontal_intensity_formula(self, test_coefficients):
139
141
  """H = sqrt(X^2 + Y^2)."""
140
- result = emm(np.radians(40), np.radians(-75), 0, 2020.0, coefficients=test_coefficients)
142
+ result = emm(
143
+ np.radians(40), np.radians(-75), 0, 2020.0, coefficients=test_coefficients
144
+ )
141
145
  H_calc = np.sqrt(result.X**2 + result.Y**2)
142
146
  assert_allclose(result.H, H_calc, rtol=1e-10)
143
147
 
144
148
  def test_total_intensity_formula(self, test_coefficients):
145
149
  """F = sqrt(H^2 + Z^2)."""
146
- result = emm(np.radians(40), np.radians(-75), 0, 2020.0, coefficients=test_coefficients)
150
+ result = emm(
151
+ np.radians(40), np.radians(-75), 0, 2020.0, coefficients=test_coefficients
152
+ )
147
153
  F_calc = np.sqrt(result.H**2 + result.Z**2)
148
154
  assert_allclose(result.F, F_calc, rtol=1e-10)
149
155
 
150
156
  def test_declination_range(self, test_coefficients):
151
157
  """Declination should be within -180 to 180 degrees."""
152
- result = emm(np.radians(45), np.radians(-75), 0, 2020.0, coefficients=test_coefficients)
158
+ result = emm(
159
+ np.radians(45), np.radians(-75), 0, 2020.0, coefficients=test_coefficients
160
+ )
153
161
  assert -np.pi <= result.D <= np.pi
154
162
 
155
163
  def test_inclination_range(self, test_coefficients):
156
164
  """Inclination should be within -90 to 90 degrees."""
157
- result = emm(np.radians(45), np.radians(-75), 0, 2020.0, coefficients=test_coefficients)
165
+ result = emm(
166
+ np.radians(45), np.radians(-75), 0, 2020.0, coefficients=test_coefficients
167
+ )
158
168
  assert -np.pi / 2 <= result.I <= np.pi / 2
159
169
 
160
170
 
@@ -219,7 +229,9 @@ class TestWMMHR:
219
229
 
220
230
  def test_wmmhr_returns_result(self, test_coefficients):
221
231
  """WMMHR returns MagneticResult."""
222
- result = wmmhr(np.radians(45), np.radians(-75), 0, 2025.0, coefficients=test_coefficients)
232
+ result = wmmhr(
233
+ np.radians(45), np.radians(-75), 0, 2025.0, coefficients=test_coefficients
234
+ )
223
235
  assert hasattr(result, "F")
224
236
  assert hasattr(result, "D")
225
237
  assert hasattr(result, "I")
@@ -259,7 +271,9 @@ class TestConvenienceFunctions:
259
271
 
260
272
  def test_emm_declination(self, test_coefficients):
261
273
  """emm_declination returns correct value."""
262
- result = emm(np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients)
274
+ result = emm(
275
+ np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients
276
+ )
263
277
  D = emm_declination(
264
278
  np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients
265
279
  )
@@ -267,7 +281,9 @@ class TestConvenienceFunctions:
267
281
 
268
282
  def test_emm_inclination(self, test_coefficients):
269
283
  """emm_inclination returns correct value."""
270
- result = emm(np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients)
284
+ result = emm(
285
+ np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients
286
+ )
271
287
  incl = emm_inclination(
272
288
  np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients
273
289
  )
@@ -275,7 +291,9 @@ class TestConvenienceFunctions:
275
291
 
276
292
  def test_emm_intensity(self, test_coefficients):
277
293
  """emm_intensity returns correct value."""
278
- result = emm(np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients)
294
+ result = emm(
295
+ np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients
296
+ )
279
297
  F = emm_intensity(
280
298
  np.radians(40), np.radians(-105), 0, 2020.0, coefficients=test_coefficients
281
299
  )
@@ -313,8 +331,12 @@ class TestSecularVariation:
313
331
 
314
332
  def test_field_changes_with_time(self, test_coefficients):
315
333
  """Field should change slightly between years."""
316
- result_2020 = emm(np.radians(45), np.radians(0), 0, 2020.0, coefficients=test_coefficients)
317
- result_2022 = emm(np.radians(45), np.radians(0), 0, 2022.0, coefficients=test_coefficients)
334
+ result_2020 = emm(
335
+ np.radians(45), np.radians(0), 0, 2020.0, coefficients=test_coefficients
336
+ )
337
+ result_2022 = emm(
338
+ np.radians(45), np.radians(0), 0, 2022.0, coefficients=test_coefficients
339
+ )
318
340
  # Small but non-zero change expected
319
341
  # Secular variation is ~50-100 nT/year at mid-latitudes
320
342
  assert result_2020.F != result_2022.F
@@ -389,7 +411,9 @@ class TestHighDegreeEvaluation:
389
411
  def test_higher_degree_coefficients(self):
390
412
  """Test with higher degree coefficients (n_max=50)."""
391
413
  coef = create_emm_test_coefficients(n_max=50)
392
- result = emm(np.radians(40), np.radians(-105), 0, 2020.0, coefficients=coef, n_max=50)
414
+ result = emm(
415
+ np.radians(40), np.radians(-105), 0, 2020.0, coefficients=coef, n_max=50
416
+ )
393
417
  assert not np.isnan(result.F)
394
418
  assert result.F > 0
395
419
 
@@ -398,8 +422,12 @@ class TestHighDegreeEvaluation:
398
422
  coef = create_emm_test_coefficients(n_max=50)
399
423
 
400
424
  # Evaluate at different n_max values
401
- result_12 = emm(np.radians(40), np.radians(-105), 0, 2020.0, coefficients=coef, n_max=12)
402
- result_50 = emm(np.radians(40), np.radians(-105), 0, 2020.0, coefficients=coef, n_max=50)
425
+ result_12 = emm(
426
+ np.radians(40), np.radians(-105), 0, 2020.0, coefficients=coef, n_max=12
427
+ )
428
+ result_50 = emm(
429
+ np.radians(40), np.radians(-105), 0, 2020.0, coefficients=coef, n_max=50
430
+ )
403
431
 
404
432
  # Both should be valid
405
433
  assert result_12.F > 0
@@ -155,7 +155,9 @@ class TestMoonPosition:
155
155
  def test_moon_position_earth_centered(self):
156
156
  """Test Moon position relative to Earth."""
157
157
  jd = 2451545.0
158
- r_earth_centered, v_earth_centered = self.eph.moon_position(jd, frame="earth_centered")
158
+ r_earth_centered, v_earth_centered = self.eph.moon_position(
159
+ jd, frame="earth_centered"
160
+ )
159
161
 
160
162
  # Moon is about 385,000 km = 0.00257 AU from Earth
161
163
  distance = np.linalg.norm(r_earth_centered)
@@ -163,7 +165,9 @@ class TestMoonPosition:
163
165
  distance_km = distance * au_to_km
164
166
 
165
167
  # Should be roughly 380,000-390,000 km
166
- assert 370000 < distance_km < 400000, f"Moon distance {distance_km:.0f} km is unexpected"
168
+ assert (
169
+ 370000 < distance_km < 400000
170
+ ), f"Moon distance {distance_km:.0f} km is unexpected"
167
171
 
168
172
  def test_moon_position_frames_consistency(self):
169
173
  """Test that Moon positions are consistent across frames."""