nrl-tracker 1.9.1__py3-none-any.whl → 1.10.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 (68) hide show
  1. {nrl_tracker-1.9.1.dist-info → nrl_tracker-1.10.0.dist-info}/METADATA +49 -4
  2. {nrl_tracker-1.9.1.dist-info → nrl_tracker-1.10.0.dist-info}/RECORD +68 -60
  3. pytcl/__init__.py +2 -2
  4. pytcl/assignment_algorithms/gating.py +18 -0
  5. pytcl/assignment_algorithms/jpda.py +56 -0
  6. pytcl/assignment_algorithms/nd_assignment.py +65 -0
  7. pytcl/assignment_algorithms/network_flow.py +40 -0
  8. pytcl/astronomical/ephemerides.py +18 -0
  9. pytcl/astronomical/orbital_mechanics.py +131 -0
  10. pytcl/atmosphere/ionosphere.py +44 -0
  11. pytcl/atmosphere/models.py +29 -0
  12. pytcl/clustering/dbscan.py +9 -0
  13. pytcl/clustering/gaussian_mixture.py +20 -0
  14. pytcl/clustering/hierarchical.py +29 -0
  15. pytcl/clustering/kmeans.py +9 -0
  16. pytcl/coordinate_systems/conversions/geodetic.py +46 -0
  17. pytcl/coordinate_systems/conversions/spherical.py +35 -0
  18. pytcl/coordinate_systems/rotations/rotations.py +147 -0
  19. pytcl/core/__init__.py +16 -0
  20. pytcl/core/maturity.py +346 -0
  21. pytcl/core/optional_deps.py +20 -0
  22. pytcl/dynamic_estimation/gaussian_sum_filter.py +55 -0
  23. pytcl/dynamic_estimation/imm.py +29 -0
  24. pytcl/dynamic_estimation/information_filter.py +64 -0
  25. pytcl/dynamic_estimation/kalman/extended.py +56 -0
  26. pytcl/dynamic_estimation/kalman/linear.py +69 -0
  27. pytcl/dynamic_estimation/kalman/unscented.py +81 -0
  28. pytcl/dynamic_estimation/particle_filters/bootstrap.py +146 -0
  29. pytcl/dynamic_estimation/rbpf.py +51 -0
  30. pytcl/dynamic_estimation/smoothers.py +58 -0
  31. pytcl/dynamic_models/continuous_time/dynamics.py +104 -0
  32. pytcl/dynamic_models/discrete_time/coordinated_turn.py +6 -0
  33. pytcl/dynamic_models/discrete_time/singer.py +12 -0
  34. pytcl/dynamic_models/process_noise/coordinated_turn.py +46 -0
  35. pytcl/dynamic_models/process_noise/polynomial.py +6 -0
  36. pytcl/dynamic_models/process_noise/singer.py +52 -0
  37. pytcl/gpu/__init__.py +153 -0
  38. pytcl/gpu/ekf.py +425 -0
  39. pytcl/gpu/kalman.py +543 -0
  40. pytcl/gpu/matrix_utils.py +486 -0
  41. pytcl/gpu/particle_filter.py +568 -0
  42. pytcl/gpu/ukf.py +476 -0
  43. pytcl/gpu/utils.py +582 -0
  44. pytcl/gravity/clenshaw.py +60 -0
  45. pytcl/gravity/egm.py +47 -0
  46. pytcl/gravity/models.py +34 -0
  47. pytcl/gravity/spherical_harmonics.py +73 -0
  48. pytcl/gravity/tides.py +34 -0
  49. pytcl/mathematical_functions/numerical_integration/quadrature.py +85 -0
  50. pytcl/mathematical_functions/special_functions/bessel.py +55 -0
  51. pytcl/mathematical_functions/special_functions/elliptic.py +42 -0
  52. pytcl/mathematical_functions/special_functions/error_functions.py +49 -0
  53. pytcl/mathematical_functions/special_functions/gamma_functions.py +43 -0
  54. pytcl/mathematical_functions/special_functions/lambert_w.py +5 -0
  55. pytcl/mathematical_functions/special_functions/marcum_q.py +16 -0
  56. pytcl/navigation/geodesy.py +101 -2
  57. pytcl/navigation/great_circle.py +71 -0
  58. pytcl/navigation/rhumb.py +74 -0
  59. pytcl/performance_evaluation/estimation_metrics.py +70 -0
  60. pytcl/performance_evaluation/track_metrics.py +30 -0
  61. pytcl/static_estimation/maximum_likelihood.py +54 -0
  62. pytcl/static_estimation/robust.py +57 -0
  63. pytcl/terrain/dem.py +69 -0
  64. pytcl/terrain/visibility.py +65 -0
  65. pytcl/trackers/hypothesis.py +65 -0
  66. {nrl_tracker-1.9.1.dist-info → nrl_tracker-1.10.0.dist-info}/LICENSE +0 -0
  67. {nrl_tracker-1.9.1.dist-info → nrl_tracker-1.10.0.dist-info}/WHEEL +0 -0
  68. {nrl_tracker-1.9.1.dist-info → nrl_tracker-1.10.0.dist-info}/top_level.txt +0 -0
pytcl/gravity/egm.py CHANGED
@@ -131,6 +131,12 @@ def get_data_dir() -> Path:
131
131
  -------
132
132
  Path
133
133
  Path to the data directory.
134
+
135
+ Examples
136
+ --------
137
+ >>> data_dir = get_data_dir()
138
+ >>> str(data_dir).endswith('.pytcl/data') or 'PYTCL_DATA_DIR' in dir()
139
+ True
134
140
  """
135
141
  env_dir = os.environ.get("PYTCL_DATA_DIR")
136
142
  if env_dir:
@@ -242,6 +248,16 @@ def create_test_coefficients(n_max: int = 36) -> EGMCoefficients:
242
248
  -------
243
249
  EGMCoefficients
244
250
  Test coefficient set.
251
+
252
+ Examples
253
+ --------
254
+ >>> coef = create_test_coefficients(n_max=10)
255
+ >>> coef.n_max
256
+ 10
257
+ >>> coef.C[0, 0] # Central term
258
+ 1.0
259
+ >>> abs(coef.C[2, 0]) > 0 # J2 term present
260
+ True
245
261
  """
246
262
  C = np.zeros((n_max + 1, n_max + 1))
247
263
  S = np.zeros((n_max + 1, n_max + 1))
@@ -496,6 +512,16 @@ def geoid_heights(
496
512
  -------
497
513
  ndarray
498
514
  Geoid heights in meters.
515
+
516
+ Examples
517
+ --------
518
+ >>> import numpy as np
519
+ >>> coef = create_test_coefficients(n_max=10)
520
+ >>> lats = np.array([0.0, np.pi/4]) # Equator and 45°N
521
+ >>> lons = np.array([0.0, np.pi/2]) # Prime meridian and 90°E
522
+ >>> heights = geoid_heights(lats, lons, coefficients=coef)
523
+ >>> len(heights)
524
+ 2
499
525
  """
500
526
  # Load coefficients once
501
527
  if coefficients is None:
@@ -543,6 +569,13 @@ def gravity_disturbance(
543
569
  -------
544
570
  GravityDisturbance
545
571
  Gravity disturbance components.
572
+
573
+ Examples
574
+ --------
575
+ >>> coef = create_test_coefficients(n_max=10)
576
+ >>> dist = gravity_disturbance(0, 0, h=0, coefficients=coef)
577
+ >>> isinstance(dist.magnitude, float)
578
+ True
546
579
  """
547
580
  if coefficients is None:
548
581
  coefficients = load_egm_coefficients(model, n_max)
@@ -613,6 +646,13 @@ def gravity_anomaly(
613
646
  -------
614
647
  float
615
648
  Gravity anomaly in m/s^2 (typically reported in mGal = 1e-5 m/s^2).
649
+
650
+ Examples
651
+ --------
652
+ >>> coef = create_test_coefficients(n_max=10)
653
+ >>> anomaly = gravity_anomaly(0, 0, h=0, coefficients=coef)
654
+ >>> isinstance(anomaly, float)
655
+ True
616
656
  """
617
657
  disturbance = gravity_disturbance(lat, lon, h, model, n_max, coefficients)
618
658
 
@@ -657,6 +697,13 @@ def deflection_of_vertical(
657
697
  -----
658
698
  Positive xi means the plumb line points more north than the normal.
659
699
  Positive eta means the plumb line points more east than the normal.
700
+
701
+ Examples
702
+ --------
703
+ >>> coef = create_test_coefficients(n_max=10)
704
+ >>> xi, eta = deflection_of_vertical(0, 0, coefficients=coef)
705
+ >>> isinstance(xi, float) and isinstance(eta, float)
706
+ True
660
707
  """
661
708
  if coefficients is None:
662
709
  coefficients = load_egm_coefficients(model, n_max)
pytcl/gravity/models.py CHANGED
@@ -267,6 +267,12 @@ def gravity_j2(
267
267
  -------
268
268
  result : GravityResult
269
269
  Gravity components and magnitude.
270
+
271
+ Examples
272
+ --------
273
+ >>> result = gravity_j2(0, 0, 0) # At equator, sea level
274
+ >>> abs(result.magnitude - 9.78) < 0.01
275
+ True
270
276
  """
271
277
  GM = constants.GM
272
278
  a = constants.a
@@ -328,6 +334,12 @@ def geoid_height_j2(
328
334
  N : float
329
335
  Geoid height (geoid - ellipsoid) in meters.
330
336
 
337
+ Examples
338
+ --------
339
+ >>> N = geoid_height_j2(0) # At equator
340
+ >>> N > 0 # Equator bulges outward
341
+ True
342
+
331
343
  Notes
332
344
  -----
333
345
  This is a simplified model. For accurate geoid heights,
@@ -371,6 +383,12 @@ def gravitational_potential(
371
383
  -------
372
384
  U : float
373
385
  Gravitational potential (m^2/s^2).
386
+
387
+ Examples
388
+ --------
389
+ >>> U = gravitational_potential(0, 0, 6.4e6) # Near Earth surface
390
+ >>> U < 0 # Potential is negative
391
+ True
374
392
  """
375
393
  GM = constants.GM
376
394
  a = constants.a
@@ -415,6 +433,14 @@ def free_air_anomaly(
415
433
  delta_g : float
416
434
  Free-air anomaly in m/s^2 (or mGal if multiplied by 1e5).
417
435
 
436
+ Examples
437
+ --------
438
+ >>> import numpy as np
439
+ >>> # Observed gravity slightly higher than normal
440
+ >>> delta_g = free_air_anomaly(9.81, np.radians(45), 100)
441
+ >>> isinstance(delta_g, float)
442
+ True
443
+
418
444
  Notes
419
445
  -----
420
446
  The free-air anomaly is the difference between observed gravity
@@ -452,6 +478,14 @@ def bouguer_anomaly(
452
478
  delta_g : float
453
479
  Bouguer anomaly in m/s^2.
454
480
 
481
+ Examples
482
+ --------
483
+ >>> import numpy as np
484
+ >>> # Bouguer anomaly at mountain location
485
+ >>> delta_g = bouguer_anomaly(9.81, np.radians(45), 1000)
486
+ >>> isinstance(delta_g, float)
487
+ True
488
+
455
489
  Notes
456
490
  -----
457
491
  The Bouguer anomaly removes the gravitational effect of the
@@ -157,6 +157,16 @@ def associated_legendre_derivative(
157
157
  -------
158
158
  dP : ndarray
159
159
  Array of shape (n_max+1, m_max+1) containing dP_n^m/dx.
160
+
161
+ Examples
162
+ --------
163
+ >>> import numpy as np
164
+ >>> x = np.cos(np.radians(45)) # cos of 45 degrees
165
+ >>> dP = associated_legendre_derivative(2, 2, x)
166
+ >>> dP.shape
167
+ (3, 3)
168
+ >>> abs(dP[0, 0]) < 1e-10 # dP_0^0/dx = 0
169
+ True
160
170
  """
161
171
  if P is None:
162
172
  P = associated_legendre(n_max, m_max, x, normalized)
@@ -255,6 +265,18 @@ def spherical_harmonic_sum(
255
265
  V = \\frac{GM}{r} \\sum_{n=0}^{N} \\left(\\frac{R}{r}\\right)^n
256
266
  \\sum_{m=0}^{n} \\bar{P}_n^m(\\sin\\phi)
257
267
  (C_{nm}\\cos m\\lambda + S_{nm}\\sin m\\lambda)
268
+
269
+ Examples
270
+ --------
271
+ >>> import numpy as np
272
+ >>> # Simple monopole (degree 0 only)
273
+ >>> C = np.array([[1.0]])
274
+ >>> S = np.array([[0.0]])
275
+ >>> R = 6.378e6 # meters
276
+ >>> GM = 3.986e14 # m^3/s^2
277
+ >>> V, dV_r, dV_lat = spherical_harmonic_sum(0, 0, R, C, S, R, GM, n_max=0)
278
+ >>> abs(V - GM/R) / (GM/R) < 1e-10 # V = GM/r for degree 0
279
+ True
258
280
  """
259
281
  if n_max is None:
260
282
  n_max = C.shape[0] - 1
@@ -382,6 +404,18 @@ def gravity_acceleration(
382
404
  Northward component of gravity.
383
405
  g_lon : float
384
406
  Eastward component of gravity.
407
+
408
+ Examples
409
+ --------
410
+ >>> import numpy as np
411
+ >>> # Simple monopole field
412
+ >>> C = np.array([[1.0]])
413
+ >>> S = np.array([[0.0]])
414
+ >>> R = 6.378e6
415
+ >>> GM = 3.986e14
416
+ >>> g_r, g_lat, g_lon = gravity_acceleration(0, 0, 0, C, S, R, GM, n_max=0)
417
+ >>> g_r < 0 # Gravity points inward (negative radial)
418
+ True
385
419
  """
386
420
  # Approximate radial distance (simplified, ignoring ellipsoid flattening)
387
421
  r = R + h
@@ -427,6 +461,18 @@ def legendre_scaling_factors(n_max: int) -> NDArray[np.floating]:
427
461
  Clenshaw summation and the recursive computation of very high
428
462
  degree and order normalised associated Legendre functions."
429
463
  Journal of Geodesy 76.5 (2002): 279-299.
464
+
465
+ Examples
466
+ --------
467
+ >>> scale = legendre_scaling_factors(100)
468
+ >>> len(scale)
469
+ 101
470
+ >>> scale[0] # No scaling for low degrees
471
+ 1.0
472
+
473
+ >>> scale_high = legendre_scaling_factors(200)
474
+ >>> scale_high[200] < scale_high[0] # Higher degrees scaled down
475
+ True
430
476
  """
431
477
  scale = np.ones(n_max + 1)
432
478
 
@@ -480,6 +526,16 @@ def associated_legendre_scaled(
480
526
 
481
527
  For normal operations (n < 150), scale_exp is all zeros and
482
528
  P_scaled equals the actual Legendre values.
529
+
530
+ Examples
531
+ --------
532
+ >>> import numpy as np
533
+ >>> x = np.cos(np.radians(45))
534
+ >>> P_scaled, scale_exp = associated_legendre_scaled(10, 10, x)
535
+ >>> P_scaled.shape
536
+ (11, 11)
537
+ >>> all(scale_exp == 0) # No scaling needed for n_max < 150
538
+ True
483
539
  """
484
540
  if m_max > n_max:
485
541
  raise ValueError("m_max must be <= n_max")
@@ -538,6 +594,15 @@ def clear_legendre_cache() -> None:
538
594
  Call this function to clear the cached associated Legendre
539
595
  polynomial arrays. Useful when memory is constrained or after
540
596
  processing a batch with different colatitude values.
597
+
598
+ Examples
599
+ --------
600
+ >>> _ = associated_legendre(10, 10, 0.5) # Populate cache
601
+ >>> info = get_legendre_cache_info()
602
+ >>> clear_legendre_cache()
603
+ >>> info_after = get_legendre_cache_info()
604
+ >>> info_after.currsize
605
+ 0
541
606
  """
542
607
  _associated_legendre_cached.cache_clear()
543
608
  _logger.debug("Legendre polynomial cache cleared")
@@ -550,6 +615,14 @@ def get_legendre_cache_info() -> Any:
550
615
  -------
551
616
  CacheInfo
552
617
  Named tuple with hits, misses, maxsize, currsize.
618
+
619
+ Examples
620
+ --------
621
+ >>> clear_legendre_cache() # Start fresh
622
+ >>> _ = associated_legendre(5, 5, 0.5)
623
+ >>> info = get_legendre_cache_info()
624
+ >>> info.currsize >= 1 # At least one entry cached
625
+ True
553
626
  """
554
627
  return _associated_legendre_cached.cache_info()
555
628
 
pytcl/gravity/tides.py CHANGED
@@ -142,6 +142,15 @@ def julian_centuries_j2000(mjd: float) -> float:
142
142
  -------
143
143
  T : float
144
144
  Julian centuries since J2000.0.
145
+
146
+ Examples
147
+ --------
148
+ >>> T = julian_centuries_j2000(51544.5) # J2000.0 epoch
149
+ >>> abs(T) < 1e-10 # Should be zero at J2000
150
+ True
151
+ >>> T = julian_centuries_j2000(51544.5 + 36525) # One century later
152
+ >>> abs(T - 1.0) < 1e-10
153
+ True
145
154
  """
146
155
  # J2000.0 = JD 2451545.0 = MJD 51544.5
147
156
  return (mjd - 51544.5) / 36525.0
@@ -172,6 +181,14 @@ def fundamental_arguments(T: float) -> Tuple[float, float, float, float, float]:
172
181
  Notes
173
182
  -----
174
183
  Based on IERS Conventions (2010) expressions.
184
+
185
+ Examples
186
+ --------
187
+ >>> import numpy as np
188
+ >>> T = 0.0 # J2000.0
189
+ >>> l, lp, F, D, Om = fundamental_arguments(T)
190
+ >>> all(0 <= x < 2*np.pi for x in [l, lp, F, D, Om]) # All in [0, 2pi)
191
+ True
175
192
  """
176
193
  # Convert degrees to radians
177
194
  deg2rad = np.pi / 180.0
@@ -241,6 +258,15 @@ def moon_position_approximate(mjd: float) -> Tuple[float, float, float]:
241
258
  Notes
242
259
  -----
243
260
  Low-precision formula adequate for tidal computations.
261
+
262
+ Examples
263
+ --------
264
+ >>> r, lat, lon = moon_position_approximate(58000)
265
+ >>> 350000e3 < r < 410000e3 # Distance in km range
266
+ True
267
+ >>> import numpy as np
268
+ >>> -np.pi/2 <= lat <= np.pi/2 # Valid latitude
269
+ True
244
270
  """
245
271
  T = julian_centuries_j2000(mjd)
246
272
 
@@ -313,6 +339,14 @@ def sun_position_approximate(mjd: float) -> Tuple[float, float, float]:
313
339
  Notes
314
340
  -----
315
341
  Low-precision formula adequate for tidal computations.
342
+
343
+ Examples
344
+ --------
345
+ >>> r, lat, lon = sun_position_approximate(58000)
346
+ >>> 1.47e11 < r < 1.52e11 # Distance ~1 AU
347
+ True
348
+ >>> lat == 0.0 # Sun on ecliptic
349
+ True
316
350
  """
317
351
  T = julian_centuries_j2000(mjd)
318
352
 
@@ -71,6 +71,14 @@ def gauss_hermite(
71
71
  w : ndarray
72
72
  Quadrature weights of shape (n,).
73
73
 
74
+ Examples
75
+ --------
76
+ >>> x, w = gauss_hermite(5)
77
+ >>> # Compute E[X^2] for X ~ N(0, 1) (exact = 1)
78
+ >>> result = np.sum(w * (np.sqrt(2) * x)**2) / np.sqrt(np.pi)
79
+ >>> abs(result - 1.0) < 1e-10
80
+ True
81
+
74
82
  Notes
75
83
  -----
76
84
  For computing E[f(X)] where X ~ N(μ, σ²):
@@ -105,6 +113,13 @@ def gauss_laguerre(
105
113
  w : ndarray
106
114
  Quadrature weights of shape (n,).
107
115
 
116
+ Examples
117
+ --------
118
+ >>> x, w = gauss_laguerre(5)
119
+ >>> # Integrate x * exp(-x) from 0 to inf (exact = 1)
120
+ >>> np.sum(w * x)
121
+ 1.0
122
+
108
123
  See Also
109
124
  --------
110
125
  numpy.polynomial.laguerre.laggauss : Equivalent function.
@@ -137,6 +152,12 @@ def gauss_chebyshev(
137
152
  w : ndarray
138
153
  Quadrature weights of shape (n,).
139
154
 
155
+ Examples
156
+ --------
157
+ >>> x, w = gauss_chebyshev(5, kind=1)
158
+ >>> x.shape
159
+ (5,)
160
+
140
161
  See Also
141
162
  --------
142
163
  numpy.polynomial.chebyshev.chebgauss : Type 1 Chebyshev.
@@ -232,6 +253,13 @@ def dblquad(
232
253
  error : float
233
254
  Estimate of the absolute error.
234
255
 
256
+ Examples
257
+ --------
258
+ >>> # Integrate x*y over unit square
259
+ >>> result, error = dblquad(lambda y, x: x*y, 0, 1, lambda x: 0, lambda x: 1)
260
+ >>> result # Should be 0.25
261
+ 0.25
262
+
235
263
  See Also
236
264
  --------
237
265
  scipy.integrate.dblquad : Underlying implementation.
@@ -281,6 +309,18 @@ def tplquad(
281
309
  error : float
282
310
  Estimate of the absolute error.
283
311
 
312
+ Examples
313
+ --------
314
+ >>> # Integrate x*y*z over unit cube
315
+ >>> result, error = tplquad(
316
+ ... lambda z, y, x: x*y*z,
317
+ ... 0, 1,
318
+ ... lambda x: 0, lambda x: 1,
319
+ ... lambda x, y: 0, lambda x, y: 1
320
+ ... )
321
+ >>> abs(result - 0.125) < 1e-6 # 1/8
322
+ True
323
+
284
324
  See Also
285
325
  --------
286
326
  scipy.integrate.tplquad : Underlying implementation.
@@ -362,6 +402,13 @@ def romberg(
362
402
  result : float
363
403
  Estimated integral value.
364
404
 
405
+ Examples
406
+ --------
407
+ >>> # Integrate x^2 from 0 to 1 (exact = 1/3)
408
+ >>> result = romberg(lambda x: x**2, 0, 1)
409
+ >>> abs(result - 1/3) < 1e-8
410
+ True
411
+
365
412
  Notes
366
413
  -----
367
414
  This is a native implementation that does not depend on scipy.integrate.romberg,
@@ -417,6 +464,15 @@ def simpson(
417
464
  result : float
418
465
  Estimated integral.
419
466
 
467
+ Examples
468
+ --------
469
+ >>> import numpy as np
470
+ >>> x = np.linspace(0, np.pi, 101)
471
+ >>> y = np.sin(x)
472
+ >>> result = simpson(y, x) # Should be ~2.0
473
+ >>> abs(result - 2.0) < 1e-5
474
+ True
475
+
420
476
  See Also
421
477
  --------
422
478
  scipy.integrate.simpson : Underlying implementation.
@@ -446,6 +502,15 @@ def trapezoid(
446
502
  result : float
447
503
  Estimated integral.
448
504
 
505
+ Examples
506
+ --------
507
+ >>> import numpy as np
508
+ >>> x = np.linspace(0, 1, 11)
509
+ >>> y = x**2 # Integrate x^2 from 0 to 1
510
+ >>> result = trapezoid(y, x)
511
+ >>> abs(result - 1/3) < 0.01 # Approximation
512
+ True
513
+
449
514
  See Also
450
515
  --------
451
516
  scipy.integrate.trapezoid : Underlying implementation.
@@ -534,6 +599,16 @@ def spherical_cubature(
534
599
  References
535
600
  ----------
536
601
  Arasaratnam & Haykin, "Cubature Kalman Filters", IEEE TAC, 2009.
602
+
603
+ Examples
604
+ --------
605
+ >>> points, weights = spherical_cubature(3)
606
+ >>> points.shape # 2*n = 6 points in 3D
607
+ (6, 3)
608
+ >>> weights.shape
609
+ (6,)
610
+ >>> np.sum(weights) # Weights sum to 1
611
+ 1.0
537
612
  """
538
613
  # Points at ±√n along each axis
539
614
  sqrt_n = np.sqrt(n_dim)
@@ -592,6 +667,16 @@ def unscented_transform_points(
592
667
  ----------
593
668
  Julier & Uhlmann, "Unscented Filtering and Nonlinear Estimation",
594
669
  Proc. IEEE, 2004.
670
+
671
+ Examples
672
+ --------
673
+ >>> sigma_points, wm, wc = unscented_transform_points(3)
674
+ >>> sigma_points.shape # 2*n+1 = 7 points in 3D
675
+ (7, 3)
676
+ >>> wm.shape
677
+ (7,)
678
+ >>> np.abs(np.sum(wm) - 1.0) < 1e-10 # Mean weights sum to 1
679
+ True
595
680
  """
596
681
  if kappa is None:
597
682
  kappa = 3.0 - n_dim
@@ -72,6 +72,11 @@ def bessely(
72
72
  -----
73
73
  Y_n(x) is singular at x = 0.
74
74
 
75
+ Examples
76
+ --------
77
+ >>> bessely(0, 1)
78
+ 0.088...
79
+
75
80
  See Also
76
81
  --------
77
82
  scipy.special.yv : Bessel function of second kind of real order.
@@ -137,6 +142,13 @@ def besselk(
137
142
  -----
138
143
  K_n(x) is singular at x = 0.
139
144
 
145
+ Examples
146
+ --------
147
+ >>> besselk(0, 1)
148
+ 0.421...
149
+ >>> besselk(1, 2)
150
+ 0.139...
151
+
140
152
  See Also
141
153
  --------
142
154
  scipy.special.kv : Modified Bessel function of second kind.
@@ -174,6 +186,14 @@ def besselh(
174
186
  H^(1)_n(x) = J_n(x) + i*Y_n(x)
175
187
  H^(2)_n(x) = J_n(x) - i*Y_n(x)
176
188
 
189
+ Examples
190
+ --------
191
+ >>> h = besselh(0, 1, 1) # H^(1)_0(1)
192
+ >>> h.real
193
+ 0.765...
194
+ >>> h.imag
195
+ 0.088...
196
+
177
197
  See Also
178
198
  --------
179
199
  scipy.special.hankel1 : Hankel function of first kind.
@@ -215,6 +235,13 @@ def spherical_jn(
215
235
  -----
216
236
  j_n(x) = sqrt(pi / (2*x)) * J_{n+1/2}(x)
217
237
 
238
+ Examples
239
+ --------
240
+ >>> spherical_jn(0, 1) # sin(1)/1
241
+ 0.841...
242
+ >>> spherical_jn(0, 1, derivative=True) # Derivative
243
+ 0.301...
244
+
218
245
  See Also
219
246
  --------
220
247
  scipy.special.spherical_jn : Spherical Bessel function of first kind.
@@ -246,6 +273,11 @@ def spherical_yn(
246
273
  y : ndarray
247
274
  Values of y_n(x) or y_n'(x).
248
275
 
276
+ Examples
277
+ --------
278
+ >>> spherical_yn(0, 1) # -cos(1)/1
279
+ -0.540...
280
+
249
281
  See Also
250
282
  --------
251
283
  scipy.special.spherical_yn : Spherical Bessel function of second kind.
@@ -277,6 +309,11 @@ def spherical_in(
277
309
  i : ndarray
278
310
  Values of i_n(x) or i_n'(x).
279
311
 
312
+ Examples
313
+ --------
314
+ >>> spherical_in(0, 1) # sinh(1)/1
315
+ 1.175...
316
+
280
317
  See Also
281
318
  --------
282
319
  scipy.special.spherical_in : Modified spherical Bessel function of first kind.
@@ -308,6 +345,11 @@ def spherical_kn(
308
345
  k : ndarray
309
346
  Values of k_n(x) or k_n'(x).
310
347
 
348
+ Examples
349
+ --------
350
+ >>> spherical_kn(0, 1) # (pi/2) * exp(-1)
351
+ 0.578...
352
+
311
353
  See Also
312
354
  --------
313
355
  scipy.special.spherical_kn : Modified spherical Bessel function of second kind.
@@ -344,6 +386,14 @@ def airy(
344
386
  Bip : ndarray
345
387
  Derivative of Airy function Bi'(x).
346
388
 
389
+ Examples
390
+ --------
391
+ >>> Ai, Aip, Bi, Bip = airy(0)
392
+ >>> Ai
393
+ 0.355...
394
+ >>> Bi
395
+ 0.614...
396
+
347
397
  See Also
348
398
  --------
349
399
  scipy.special.airy : Airy functions.
@@ -511,6 +561,11 @@ def struve_l(
511
561
  -------
512
562
  L : ndarray
513
563
  Values of L_n(x).
564
+
565
+ Examples
566
+ --------
567
+ >>> struve_l(0, 1)
568
+ 0.710...
514
569
  """
515
570
  return np.asarray(sp.modstruve(n, x), dtype=np.float64)
516
571
 
@@ -61,6 +61,11 @@ def ellipkm1(p: ArrayLike) -> NDArray[np.floating]:
61
61
  K : ndarray
62
62
  Values of K(1 - p).
63
63
 
64
+ Examples
65
+ --------
66
+ >>> ellipkm1(0.1) # K(0.9)
67
+ 2.578...
68
+
64
69
  See Also
65
70
  --------
66
71
  scipy.special.ellipkm1 : Elliptic integral near m = 1.
@@ -117,6 +122,12 @@ def ellipeinc(phi: ArrayLike, m: ArrayLike) -> NDArray[np.floating]:
117
122
  E : ndarray
118
123
  Values of the incomplete elliptic integral of the second kind.
119
124
 
125
+ Examples
126
+ --------
127
+ >>> import numpy as np
128
+ >>> ellipeinc(np.pi/2, 0) # Same as ellipe(0) = π/2
129
+ 1.5707...
130
+
120
131
  See Also
121
132
  --------
122
133
  scipy.special.ellipeinc : Incomplete elliptic integral of second kind.
@@ -142,6 +153,12 @@ def ellipkinc(phi: ArrayLike, m: ArrayLike) -> NDArray[np.floating]:
142
153
  F : ndarray
143
154
  Values of the incomplete elliptic integral of the first kind.
144
155
 
156
+ Examples
157
+ --------
158
+ >>> import numpy as np
159
+ >>> ellipkinc(np.pi/2, 0) # Same as ellipk(0) = π/2
160
+ 1.5707...
161
+
145
162
  See Also
146
163
  --------
147
164
  scipy.special.ellipkinc : Incomplete elliptic integral of first kind.
@@ -170,6 +187,11 @@ def elliprd(x: ArrayLike, y: ArrayLike, z: ArrayLike) -> NDArray[np.floating]:
170
187
  R_D : ndarray
171
188
  Values of the Carlson R_D integral.
172
189
 
190
+ Examples
191
+ --------
192
+ >>> elliprd(1, 2, 3)
193
+ 0.297...
194
+
173
195
  See Also
174
196
  --------
175
197
  scipy.special.elliprd : Carlson R_D integral.
@@ -204,6 +226,11 @@ def elliprf(x: ArrayLike, y: ArrayLike, z: ArrayLike) -> NDArray[np.floating]:
204
226
  The complete elliptic integral of the first kind is:
205
227
  K(m) = R_F(0, 1-m, 1)
206
228
 
229
+ Examples
230
+ --------
231
+ >>> elliprf(1, 1, 1) # R_F(a, a, a) = 1/sqrt(a)
232
+ 1.0
233
+
207
234
  See Also
208
235
  --------
209
236
  scipy.special.elliprf : Carlson R_F integral.
@@ -236,6 +263,11 @@ def elliprg(x: ArrayLike, y: ArrayLike, z: ArrayLike) -> NDArray[np.floating]:
236
263
  The complete elliptic integral of the second kind is:
237
264
  E(m) = 2 * R_G(0, 1-m, 1)
238
265
 
266
+ Examples
267
+ --------
268
+ >>> elliprg(1, 1, 1) # R_G(a, a, a) = sqrt(a)
269
+ 1.0
270
+
239
271
  See Also
240
272
  --------
241
273
  scipy.special.elliprg : Carlson R_G integral.
@@ -272,6 +304,11 @@ def elliprj(
272
304
  -----
273
305
  The complete elliptic integral of the third kind can be computed using R_J.
274
306
 
307
+ Examples
308
+ --------
309
+ >>> elliprj(1, 2, 3, 4)
310
+ 0.213...
311
+
275
312
  See Also
276
313
  --------
277
314
  scipy.special.elliprj : Carlson R_J integral.
@@ -302,6 +339,11 @@ def elliprc(x: ArrayLike, y: ArrayLike) -> NDArray[np.floating]:
302
339
  - R_C(x, y) = arctan(sqrt((x-y)/y)) / sqrt(x-y) for x > y
303
340
  - R_C(x, y) = arctanh(sqrt((y-x)/y)) / sqrt(y-x) for x < y
304
341
 
342
+ Examples
343
+ --------
344
+ >>> elliprc(1, 1) # R_C(a, a) = 1/sqrt(a)
345
+ 1.0
346
+
305
347
  See Also
306
348
  --------
307
349
  scipy.special.elliprc : Carlson R_C integral.