nrl-tracker 1.9.0__py3-none-any.whl → 1.9.2__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 (61) hide show
  1. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/METADATA +4 -4
  2. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/RECORD +61 -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 +1 -1
  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/gravity/clenshaw.py +60 -0
  38. pytcl/gravity/egm.py +47 -0
  39. pytcl/gravity/models.py +34 -0
  40. pytcl/gravity/spherical_harmonics.py +73 -0
  41. pytcl/gravity/tides.py +34 -0
  42. pytcl/mathematical_functions/numerical_integration/quadrature.py +85 -0
  43. pytcl/mathematical_functions/special_functions/bessel.py +55 -0
  44. pytcl/mathematical_functions/special_functions/elliptic.py +42 -0
  45. pytcl/mathematical_functions/special_functions/error_functions.py +49 -0
  46. pytcl/mathematical_functions/special_functions/gamma_functions.py +43 -0
  47. pytcl/mathematical_functions/special_functions/lambert_w.py +5 -0
  48. pytcl/mathematical_functions/special_functions/marcum_q.py +16 -0
  49. pytcl/navigation/geodesy.py +101 -2
  50. pytcl/navigation/great_circle.py +71 -0
  51. pytcl/navigation/rhumb.py +74 -0
  52. pytcl/performance_evaluation/estimation_metrics.py +70 -0
  53. pytcl/performance_evaluation/track_metrics.py +30 -0
  54. pytcl/static_estimation/maximum_likelihood.py +54 -0
  55. pytcl/static_estimation/robust.py +57 -0
  56. pytcl/terrain/dem.py +69 -0
  57. pytcl/terrain/visibility.py +65 -0
  58. pytcl/trackers/hypothesis.py +65 -0
  59. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/LICENSE +0 -0
  60. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/WHEEL +0 -0
  61. {nrl_tracker-1.9.0.dist-info → nrl_tracker-1.9.2.dist-info}/top_level.txt +0 -0
pytcl/gravity/clenshaw.py CHANGED
@@ -106,6 +106,17 @@ def clenshaw_sum_order(
106
106
  Sum of C terms weighted by Legendre functions.
107
107
  sum_S : float
108
108
  Sum of S terms weighted by Legendre functions.
109
+
110
+ Examples
111
+ --------
112
+ >>> import numpy as np
113
+ >>> C = np.zeros((5, 5))
114
+ >>> S = np.zeros((5, 5))
115
+ >>> C[2, 0] = 1.0 # Only C20 term
116
+ >>> cos_theta, sin_theta = np.cos(np.pi/4), np.sin(np.pi/4)
117
+ >>> sum_C, sum_S = clenshaw_sum_order(0, cos_theta, sin_theta, C, S, 4)
118
+ >>> isinstance(sum_C, float)
119
+ True
109
120
  """
110
121
  # Handle edge case
111
122
  if m > n_max:
@@ -187,6 +198,18 @@ def clenshaw_sum_order_derivative(
187
198
  Derivative of sum_C with respect to theta.
188
199
  dsum_S : float
189
200
  Derivative of sum_S with respect to theta.
201
+
202
+ Examples
203
+ --------
204
+ >>> import numpy as np
205
+ >>> C = np.zeros((5, 5))
206
+ >>> S = np.zeros((5, 5))
207
+ >>> C[2, 0] = -0.0005 # J2-like term
208
+ >>> cos_theta, sin_theta = np.cos(np.pi/4), np.sin(np.pi/4)
209
+ >>> sum_C, sum_S, dsum_C, dsum_S = clenshaw_sum_order_derivative(
210
+ ... 0, cos_theta, sin_theta, C, S, 4)
211
+ >>> len([sum_C, sum_S, dsum_C, dsum_S])
212
+ 4
190
213
  """
191
214
  if m > n_max:
192
215
  return 0.0, 0.0, 0.0, 0.0
@@ -298,6 +321,19 @@ def clenshaw_geoid(
298
321
  \\sum_{m=0}^{n} P_n^m(\\sin\\phi) (C_{nm}\\cos m\\lambda + S_{nm}\\sin m\\lambda)
299
322
 
300
323
  The n=0 and n=1 terms are excluded as they represent the reference field.
324
+
325
+ Examples
326
+ --------
327
+ >>> import numpy as np
328
+ >>> C = np.zeros((5, 5))
329
+ >>> S = np.zeros((5, 5))
330
+ >>> C[0, 0] = 1.0
331
+ >>> R = 6.378e6
332
+ >>> GM = 3.986e14
333
+ >>> gamma = 9.81
334
+ >>> N = clenshaw_geoid(0, 0, C, S, R, GM, gamma)
335
+ >>> isinstance(N, float)
336
+ True
301
337
  """
302
338
  if n_max is None:
303
339
  n_max = C.shape[0] - 1
@@ -381,6 +417,18 @@ def clenshaw_potential(
381
417
  -------
382
418
  float
383
419
  Gravitational potential in m^2/s^2.
420
+
421
+ Examples
422
+ --------
423
+ >>> import numpy as np
424
+ >>> C = np.zeros((5, 5))
425
+ >>> S = np.zeros((5, 5))
426
+ >>> C[0, 0] = 1.0 # Central term only
427
+ >>> R = 6.378e6
428
+ >>> GM = 3.986e14
429
+ >>> V = clenshaw_potential(0, 0, R, C, S, R, GM)
430
+ >>> abs(V - GM/R) / (GM/R) < 0.01 # ~GM/r for central term
431
+ True
384
432
  """
385
433
  if n_max is None:
386
434
  n_max = C.shape[0] - 1
@@ -464,6 +512,18 @@ def clenshaw_gravity(
464
512
  Northward component of gravity disturbance in m/s^2.
465
513
  g_lon : float
466
514
  Eastward component of gravity disturbance in m/s^2.
515
+
516
+ Examples
517
+ --------
518
+ >>> import numpy as np
519
+ >>> C = np.zeros((5, 5))
520
+ >>> S = np.zeros((5, 5))
521
+ >>> C[0, 0] = 1.0
522
+ >>> R = 6.378e6
523
+ >>> GM = 3.986e14
524
+ >>> g_r, g_lat, g_lon = clenshaw_gravity(0, 0, R, C, S, R, GM)
525
+ >>> g_r < 0 # Gravity points inward
526
+ True
467
527
  """
468
528
  if n_max is None:
469
529
  n_max = C.shape[0] - 1
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