grss 4.3.2__tar.gz → 4.3.4__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.
- {grss-4.3.2/grss.egg-info → grss-4.3.4}/PKG-INFO +1 -1
- {grss-4.3.2 → grss-4.3.4}/grss/fit/fit_simulation.py +66 -61
- {grss-4.3.2 → grss-4.3.4}/grss/prop/prop_utils.py +25 -7
- {grss-4.3.2 → grss-4.3.4}/grss/utils.py +2 -2
- grss-4.3.4/grss/version.txt +1 -0
- {grss-4.3.2 → grss-4.3.4/grss.egg-info}/PKG-INFO +1 -1
- {grss-4.3.2 → grss-4.3.4}/include/approach.h +6 -0
- {grss-4.3.2 → grss-4.3.4}/include/grss.h +3 -1
- {grss-4.3.2 → grss-4.3.4}/include/simulation.h +25 -3
- {grss-4.3.2 → grss-4.3.4}/include/utilities.h +10 -0
- grss-4.3.4/src/approach.cpp +1097 -0
- {grss-4.3.2 → grss-4.3.4}/src/force.cpp +102 -0
- {grss-4.3.2 → grss-4.3.4}/src/grss.cpp +67 -5
- {grss-4.3.2 → grss-4.3.4}/src/interpolate.cpp +2 -2
- {grss-4.3.2 → grss-4.3.4}/src/pck.cpp +12 -1
- {grss-4.3.2 → grss-4.3.4}/src/simulation.cpp +37 -7
- grss-4.3.4/tests/python/fit/chesley.ipynb +275 -0
- {grss-4.3.2 → grss-4.3.4}/tests/python/fit/eggl.ipynb +17 -17
- grss-4.3.4/tests/python/fit/farnocchia.ipynb +275 -0
- grss-4.3.4/tests/python/fit/shantanunaidu.ipynb +277 -0
- grss-4.3.2/grss/version.txt +0 -1
- grss-4.3.2/src/approach.cpp +0 -984
- grss-4.3.2/tests/python/fit/chesley.ipynb +0 -275
- grss-4.3.2/tests/python/fit/farnocchia.ipynb +0 -281
- grss-4.3.2/tests/python/fit/shantanunaidu.ipynb +0 -277
- {grss-4.3.2 → grss-4.3.4}/CMakeLists.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/LICENSE +0 -0
- {grss-4.3.2 → grss-4.3.4}/MANIFEST.in +0 -0
- {grss-4.3.2 → grss-4.3.4}/README.md +0 -0
- {grss-4.3.2 → grss-4.3.4}/build_cpp.sh +0 -0
- {grss-4.3.2 → grss-4.3.4}/docs/source/conf.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/extern/get_cspice.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/__init__.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/debias/get_debiasing_data.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/fit/__init__.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/fit/fit_ades.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/fit/fit_optical.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/fit/fit_radar.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/fit/fit_utils.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/kernels/get_kernels.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/prop/__init__.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/prop/prop_parallel.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss/prop/prop_unscented.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss.egg-info/SOURCES.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss.egg-info/dependency_links.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss.egg-info/requires.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/grss.egg-info/top_level.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/elements.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/force.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/gr15.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/interpolate.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/observe.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/parallel.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/pck.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/spk.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/stm.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/include/timeconvert.h +0 -0
- {grss-4.3.2 → grss-4.3.4}/pyproject.toml +0 -0
- {grss-4.3.2 → grss-4.3.4}/requirements.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/setup.cfg +0 -0
- {grss-4.3.2 → grss-4.3.4}/setup.py +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/CMakeLists.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/elements.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/gr15.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/observe.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/parallel.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/spk.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/stm.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/timeconvert.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/src/utilities.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/cpp/prop/CMakeLists.txt +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/cpp/prop/apophis.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/cpp/prop/didymos.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/cpp/prop/pck_map.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/cpp/prop/spk_map.cpp +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/python/prop/apophis.ipynb +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/python/prop/didymos.ipynb +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/python/prop/icarus.ipynb +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/python/prop/moshup.ipynb +0 -0
- {grss-4.3.2 → grss-4.3.4}/tests/python/run_tests.sh +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import sys
|
|
4
4
|
import datetime
|
|
5
5
|
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
6
7
|
import matplotlib.pyplot as plt
|
|
7
8
|
from astropy.time import Time
|
|
8
9
|
|
|
@@ -562,7 +563,7 @@ class FitSimulation:
|
|
|
562
563
|
self.fixed_propsim_params[key] = nongrav_info[key]
|
|
563
564
|
self.fixed_propsim_params['events'] = events if events is not None else []
|
|
564
565
|
self.prior_est = None
|
|
565
|
-
self.
|
|
566
|
+
self.prior_sig = None
|
|
566
567
|
self._priors_given = False
|
|
567
568
|
self._xbar0 = None
|
|
568
569
|
self._info0 = None
|
|
@@ -574,6 +575,7 @@ class FitSimulation:
|
|
|
574
575
|
num_auto_rejected = np.sum(sel_ast == 'D')
|
|
575
576
|
num_force_rejected = np.sum(sel_ast == 'd')
|
|
576
577
|
self.num_rejected = num_auto_rejected + num_force_rejected
|
|
578
|
+
self.info_mats = []
|
|
577
579
|
self.converged = False
|
|
578
580
|
return None
|
|
579
581
|
|
|
@@ -642,10 +644,10 @@ class FitSimulation:
|
|
|
642
644
|
ValueError
|
|
643
645
|
If the prior estimates and sigmas do not have the same length.
|
|
644
646
|
"""
|
|
645
|
-
# check that the keys in self.x_init are the same as in self.prior_est and self.
|
|
646
|
-
if self.prior_est is not None and self.
|
|
647
|
+
# check that the keys in self.x_init are the same as in self.prior_est and self.prior_sig
|
|
648
|
+
if self.prior_est is not None and self.prior_sig is not None:
|
|
647
649
|
self._priors_given = True
|
|
648
|
-
if len(self.prior_est) != len(self.
|
|
650
|
+
if len(self.prior_est) != len(self.prior_sig):
|
|
649
651
|
raise ValueError("Prior estimates and sigmas must have the same length.")
|
|
650
652
|
for key in self.prior_est.keys():
|
|
651
653
|
if key not in self.x_init:
|
|
@@ -654,7 +656,7 @@ class FitSimulation:
|
|
|
654
656
|
self._xbar0 = np.zeros(self.n_fit)
|
|
655
657
|
for key in self.prior_est.keys():
|
|
656
658
|
idx = list(self.x_init.keys()).index(key)
|
|
657
|
-
self._info0[idx, idx] = 1/self.
|
|
659
|
+
self._info0[idx, idx] = 1/self.prior_sig[key]**2
|
|
658
660
|
self._xbar0[idx] = self.prior_est[key] - self.x_init[key]
|
|
659
661
|
self._prior_constant = list(self.x_nom.values())+self._xbar0
|
|
660
662
|
return None
|
|
@@ -693,56 +695,60 @@ class FitSimulation:
|
|
|
693
695
|
raise ValueError("Simulated observation data must have the same length.")
|
|
694
696
|
perm_id = self.obs['permID'][0]
|
|
695
697
|
prov_id = self.obs['provID'][0]
|
|
698
|
+
new_sim_obs = []
|
|
696
699
|
for i, time in enumerate(times):
|
|
697
|
-
|
|
700
|
+
this_obs = {}
|
|
698
701
|
mode = modes[i]
|
|
699
702
|
if mode not in {'SIM_CCD', 'SIM_OCC', 'SIM_RAD_DEL', 'SIM_RAD_DOP'}:
|
|
700
703
|
raise ValueError(f"Unknown simulated observation mode {mode}.")
|
|
701
704
|
weight = weights[i]
|
|
702
705
|
if isinstance(perm_id, str):
|
|
703
|
-
|
|
706
|
+
this_obs['permID'] = f'SIM_{perm_id}'
|
|
704
707
|
if isinstance(prov_id, str):
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
708
|
+
this_obs['provID'] = f'SIM_{prov_id}'
|
|
709
|
+
this_obs['obsTime'] = f'{time.utc.isot}Z'
|
|
710
|
+
this_obs['obsTimeMJD'] = time.utc.mjd
|
|
711
|
+
this_obs['obsTimeMJDTDB'] = time.tdb.mjd
|
|
712
|
+
this_obs['mode'] = mode
|
|
710
713
|
if mode in {'SIM_CCD', 'SIM_OCC'}:
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
714
|
+
this_obs['stn'] = 'SIM'
|
|
715
|
+
this_obs['ra'] = np.nan
|
|
716
|
+
this_obs['rmsRA'] = weight[0]
|
|
717
|
+
this_obs['sigRA'] = weight[0]
|
|
718
|
+
this_obs['dec'] = np.nan
|
|
719
|
+
this_obs['rmsDec'] = weight[1]
|
|
720
|
+
this_obs['sigDec'] = weight[1]
|
|
721
|
+
this_obs['rmsCorr'] = weight[2]
|
|
722
|
+
this_obs['sigCorr'] = weight[2]
|
|
723
|
+
this_obs['cosDec'] = 1.0
|
|
721
724
|
elif mode in {'SIM_RAD_DEL', 'SIM_RAD_DOP'}:
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
+
this_obs['trx'] = 'SIM'
|
|
726
|
+
this_obs['rcv'] = 'SIM'
|
|
727
|
+
this_obs['com'] = 1
|
|
725
728
|
if mode == 'SIM_RAD_DEL':
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
729
|
+
this_obs['delay'] = np.nan
|
|
730
|
+
this_obs['rmsDelay'] = weight[0]
|
|
731
|
+
this_obs['sigDelay'] = weight[0]
|
|
732
|
+
this_obs['doppler'] = np.nan
|
|
733
|
+
this_obs['rmsDoppler'] = np.nan
|
|
734
|
+
this_obs['sigDoppler'] = np.nan
|
|
732
735
|
else:
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
736
|
+
this_obs['delay'] = np.nan
|
|
737
|
+
this_obs['rmsDelay'] = np.nan
|
|
738
|
+
this_obs['sigDelay'] = np.nan
|
|
739
|
+
this_obs['doppler'] = np.nan
|
|
740
|
+
this_obs['rmsDoppler'] = weight[0]
|
|
741
|
+
this_obs['sigDoppler'] = weight[0]
|
|
742
|
+
this_obs['frq'] = 8560.0
|
|
743
|
+
this_obs['ctr'] = 399
|
|
744
|
+
this_obs['sys'] = 'ITRF'
|
|
745
|
+
this_obs['pos1'] = 0.0
|
|
746
|
+
this_obs['pos2'] = 0.0
|
|
747
|
+
this_obs['pos3'] = 0.0
|
|
748
|
+
this_obs['selAst'] = 'a'
|
|
749
|
+
new_sim_obs.append(this_obs)
|
|
750
|
+
sim_obs_df = pd.DataFrame(new_sim_obs)
|
|
751
|
+
self.obs = pd.concat([self.obs, sim_obs_df], ignore_index=True)
|
|
746
752
|
return None
|
|
747
753
|
|
|
748
754
|
def _parse_observation_arrays(self, obs_df):
|
|
@@ -1635,33 +1641,29 @@ class FitSimulation:
|
|
|
1635
1641
|
raise ValueError("Observer info length not recognized.")
|
|
1636
1642
|
resid = residuals[i]
|
|
1637
1643
|
# calculate chi-squared for each residual if after the first iteration
|
|
1638
|
-
if
|
|
1644
|
+
if start_rejecting and size == 2:
|
|
1639
1645
|
obs_cov = self.obs_cov[i]
|
|
1640
1646
|
obs_partials = partials[j:j+size, :]
|
|
1641
1647
|
if sel_ast[i] in {'D', 'd'}:
|
|
1642
1648
|
resid_cov = obs_cov + obs_partials @ full_cov @ obs_partials.T
|
|
1643
1649
|
else:
|
|
1644
1650
|
resid_cov = obs_cov - obs_partials @ full_cov @ obs_partials.T
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
residual_chi_squared = resid @ resid_cov_inv @ resid.T
|
|
1652
|
-
res_chisq_vals[i] = residual_chi_squared
|
|
1653
|
-
# outlier rejection, only reject RA/Dec measurements
|
|
1654
|
-
if start_rejecting and size == 2:
|
|
1655
|
-
if abs(residual_chi_squared) > chi_reject**2 and sel_ast[i] not in {'a', 'd'}:
|
|
1651
|
+
resid_cov_det = resid_cov[0,0]*resid_cov[1,1] - resid_cov[0,1]*resid_cov[1,0]
|
|
1652
|
+
resid_cov_inv = np.array([[resid_cov[1,1], -resid_cov[0,1]],
|
|
1653
|
+
[-resid_cov[1,0], resid_cov[0,0]]])/resid_cov_det
|
|
1654
|
+
outlier_chisq = resid @ resid_cov_inv @ resid.T
|
|
1655
|
+
# outlier rejection, only reject RA/Dec measurements
|
|
1656
|
+
if abs(outlier_chisq) > chi_reject**2 and sel_ast[i] not in {'a', 'd'}:
|
|
1656
1657
|
if sel_ast[i] == 'A':
|
|
1657
1658
|
self.num_rejected += 1
|
|
1658
1659
|
sel_ast[i] = 'D'
|
|
1659
|
-
elif abs(
|
|
1660
|
+
elif abs(outlier_chisq) < chi_recover**2 and sel_ast[i] == 'D':
|
|
1660
1661
|
sel_ast[i] = 'A'
|
|
1661
1662
|
self.num_rejected -= 1
|
|
1663
|
+
res_chisq_vals[i] = resid @ self.obs_weight[i] @ resid.T
|
|
1662
1664
|
if sel_ast[i] not in {'D', 'd'}:
|
|
1663
1665
|
rms_u += resid @ resid.T
|
|
1664
|
-
chi_sq +=
|
|
1666
|
+
chi_sq += res_chisq_vals[i]
|
|
1665
1667
|
j += size
|
|
1666
1668
|
# # write res_chisq_vals to file if any values are negative
|
|
1667
1669
|
# if np.any(res_chisq_vals < 0):
|
|
@@ -1759,6 +1761,7 @@ class FitSimulation:
|
|
|
1759
1761
|
atwb = np.zeros(self.n_fit)
|
|
1760
1762
|
j = 0
|
|
1761
1763
|
sel_ast = self.obs['selAst'].values
|
|
1764
|
+
self.info_mats = []
|
|
1762
1765
|
for i, obs_info_len in enumerate(self.observer_info_lengths):
|
|
1763
1766
|
if obs_info_len in {4, 7}:
|
|
1764
1767
|
size = 2
|
|
@@ -1768,10 +1771,12 @@ class FitSimulation:
|
|
|
1768
1771
|
raise ValueError("Observer info length not recognized.")
|
|
1769
1772
|
if sel_ast[i] in {'D', 'd'}:
|
|
1770
1773
|
j += size
|
|
1774
|
+
self.info_mats.append(atwa.copy())
|
|
1771
1775
|
continue
|
|
1772
1776
|
atwa += partials[j:j+size, :].T @ self.obs_weight[i] @ partials[j:j+size, :]
|
|
1773
1777
|
atwb += partials[j:j+size, :].T @ self.obs_weight[i] @ residuals[i]
|
|
1774
1778
|
j += size
|
|
1779
|
+
self.info_mats.append(atwa.copy())
|
|
1775
1780
|
# use pseudo-inverse if the data arc is less than 7 days
|
|
1776
1781
|
if self.obs.obsTimeMJD.max() - self.obs.obsTimeMJD.min() < 7.0:
|
|
1777
1782
|
self.covariance = np.linalg.pinv(atwa, rcond=1e-20, hermitian=True)
|
|
@@ -2074,7 +2079,7 @@ class FitSimulation:
|
|
|
2074
2079
|
f.write(f" {units_dict[key[:2]]}")
|
|
2075
2080
|
if self._priors_given and key in self.prior_est:
|
|
2076
2081
|
p_val = self.prior_est[key]
|
|
2077
|
-
p_sig = self.
|
|
2082
|
+
p_sig = self.prior_sig[key]
|
|
2078
2083
|
if key in ['om', 'w', 'i']:
|
|
2079
2084
|
p_val *= 180/np.pi
|
|
2080
2085
|
p_sig *= 180/np.pi
|
|
@@ -2114,7 +2119,7 @@ class FitSimulation:
|
|
|
2114
2119
|
f.write(f" {units_dict[key[:2]]}")
|
|
2115
2120
|
if self._priors_given and key in self.prior_est:
|
|
2116
2121
|
p_val = self.prior_est[key]
|
|
2117
|
-
p_sig = self.
|
|
2122
|
+
p_sig = self.prior_sig[key]
|
|
2118
2123
|
if key in ['om', 'w', 'i']:
|
|
2119
2124
|
p_val *= 180/np.pi
|
|
2120
2125
|
p_sig *= 180/np.pi
|
|
@@ -2211,7 +2216,7 @@ class FitSimulation:
|
|
|
2211
2216
|
f.write(f'{final_val:18.11e}{half_tab}')
|
|
2212
2217
|
f.write(f'{final_unc:18.11e}{half_tab}')
|
|
2213
2218
|
f.write(f'{final_val-init_val:+18.11e}{half_tab}')
|
|
2214
|
-
f.write(f'{(final_val-init_val)/
|
|
2219
|
+
f.write(f'{(final_val-init_val)/final_unc:+10.3f}\n')
|
|
2215
2220
|
f.write("\n")
|
|
2216
2221
|
if itrn.iter_number <= self.n_iter:
|
|
2217
2222
|
f.write(subsection_full + '\n')
|
|
@@ -536,27 +536,48 @@ def plot_bplane(ca_list, plot_offset=False, scale_coords=False, n_std=3, units_k
|
|
|
536
536
|
lon = None
|
|
537
537
|
lat = None
|
|
538
538
|
impact_any = lon is not None and lat is not None
|
|
539
|
+
if kizner_nan and opik_nan and scaled_nan and not mtp_nan:
|
|
540
|
+
print("WARNING: Close approaches have some invalid B-planes but do have MTP. "
|
|
541
|
+
"Object might be captured.")
|
|
539
542
|
if len(ca_list) >= 100 or sigma_points is not None:
|
|
543
|
+
# remove nans before converting data to ellipse
|
|
540
544
|
if not kizner_nan:
|
|
541
545
|
kizner_data = data_to_ellipse(kizner_x, kizner_y, n_std, 'kizner',
|
|
542
546
|
print_ellipse_params, units, sigma_points)
|
|
543
547
|
else:
|
|
544
|
-
|
|
548
|
+
print(f"Kizner B-plane nan count: {np.sum(np.isnan(kizner_x))}")
|
|
549
|
+
non_nan_idx = np.where(~np.isnan(kizner_x) & ~np.isnan(kizner_y))[0]
|
|
550
|
+
kizner_data = data_to_ellipse(kizner_x[non_nan_idx], kizner_y[non_nan_idx],
|
|
551
|
+
n_std, 'kizner',
|
|
552
|
+
print_ellipse_params, units, sigma_points)
|
|
545
553
|
if not opik_nan:
|
|
546
554
|
opik_data = data_to_ellipse(opik_x, opik_y, n_std, 'opik',
|
|
547
555
|
print_ellipse_params, units, sigma_points)
|
|
548
556
|
else:
|
|
549
|
-
|
|
557
|
+
print(f"Opik B-plane nan count: {np.sum(np.isnan(opik_x))}")
|
|
558
|
+
non_nan_idx = np.where(~np.isnan(opik_x) & ~np.isnan(opik_y))[0]
|
|
559
|
+
opik_data = data_to_ellipse(opik_x[non_nan_idx], opik_y[non_nan_idx],
|
|
560
|
+
n_std, 'opik',
|
|
561
|
+
print_ellipse_params, units, sigma_points)
|
|
550
562
|
if not scaled_nan:
|
|
551
563
|
scaled_data = data_to_ellipse(scaled_x, scaled_y, n_std, 'scaled',
|
|
552
564
|
print_ellipse_params, units, sigma_points)
|
|
553
565
|
else:
|
|
554
|
-
|
|
566
|
+
print(f"Scaled B-plane nan count: {np.sum(np.isnan(scaled_x))}")
|
|
567
|
+
non_nan_idx = np.where(~np.isnan(scaled_x) & ~np.isnan(scaled_y))[0]
|
|
568
|
+
scaled_data = data_to_ellipse(scaled_x[non_nan_idx], scaled_y[non_nan_idx],
|
|
569
|
+
n_std, 'scaled',
|
|
570
|
+
print_ellipse_params, units, sigma_points)
|
|
555
571
|
if not mtp_nan:
|
|
556
572
|
mtp_data = data_to_ellipse(mtp_x, mtp_y, n_std, 'mtp',
|
|
557
573
|
print_ellipse_params, units, sigma_points)
|
|
558
574
|
else:
|
|
559
|
-
|
|
575
|
+
print(f"MTP B-plane nan count: {np.sum(np.isnan(mtp_x))}")
|
|
576
|
+
non_nan_idx = np.where(~np.isnan(mtp_x) & ~np.isnan(mtp_y))[0]
|
|
577
|
+
mtp_data = data_to_ellipse(mtp_x[non_nan_idx], mtp_y[non_nan_idx],
|
|
578
|
+
n_std, 'mtp',
|
|
579
|
+
print_ellipse_params, units, sigma_points)
|
|
580
|
+
|
|
560
581
|
elif len(ca_list[0].xRel) >= 42 and analytic_info is not None:
|
|
561
582
|
all_data = partials_to_ellipse(ca_list[0], au2units, n_std,
|
|
562
583
|
print_ellipse_params, units, analytic_info)
|
|
@@ -566,9 +587,6 @@ def plot_bplane(ca_list, plot_offset=False, scale_coords=False, n_std=3, units_k
|
|
|
566
587
|
opik_data = None
|
|
567
588
|
scaled_data = None
|
|
568
589
|
mtp_data = None
|
|
569
|
-
if kizner_nan and opik_nan and scaled_nan and not mtp_nan:
|
|
570
|
-
print("WARNING: Close approaches have no valid B-planes but do have MTP. "
|
|
571
|
-
"Object might be captured.")
|
|
572
590
|
fig, axes = plt.subplots(2, 2, figsize=(9, 9), dpi=250)
|
|
573
591
|
plot_single_bplane(axes[0,0], kizner_x, kizner_y, kizner_data, 'kizner',
|
|
574
592
|
focus_factor, show_central_body, plot_offset, scale_coords,
|
|
@@ -12,11 +12,11 @@ __all__ = [ 'default_kernel_path',
|
|
|
12
12
|
grss_path = os.path.dirname(os.path.abspath(__file__))
|
|
13
13
|
default_kernel_path = f'{grss_path}/kernels/'
|
|
14
14
|
|
|
15
|
-
def _connected_to_internet(url='http://www.google.com/', timeout=
|
|
15
|
+
def _connected_to_internet(url='http://www.google.com/', timeout=30):
|
|
16
16
|
try:
|
|
17
17
|
_ = requests.head(url, timeout=timeout)
|
|
18
18
|
return True
|
|
19
|
-
except requests.ConnectionError:
|
|
19
|
+
except (requests.ConnectionError, requests.Timeout):
|
|
20
20
|
print("No internet connection available.")
|
|
21
21
|
return False
|
|
22
22
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.3.4
|
|
@@ -28,6 +28,12 @@ void impact_r_calc(PropSimulation *propSim, const size_t &i, const size_t &j,
|
|
|
28
28
|
std::vector<real> get_rel_state(PropSimulation *propSim, const size_t &i,
|
|
29
29
|
const size_t &j, const real &t);
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @brief Compute partials of B-plane parameters.
|
|
33
|
+
*/
|
|
34
|
+
void get_bplane_partials(PropSimulation *propSim, CloseApproachParameters *ca,
|
|
35
|
+
const real &mu, const real &radius);
|
|
36
|
+
|
|
31
37
|
/**
|
|
32
38
|
* @brief Compute the time of close approach or impact using Brent's method
|
|
33
39
|
* for root finding in a bracketed interval.
|
|
@@ -16,7 +16,9 @@ void PropSimulation::integrate() {
|
|
|
16
16
|
this->map_ephemeris();
|
|
17
17
|
this->preprocess();
|
|
18
18
|
gr15(this);
|
|
19
|
-
this->
|
|
19
|
+
if (!this->unsafePersistentMemoryMap) {
|
|
20
|
+
this->unmap_ephemeris();
|
|
21
|
+
}
|
|
20
22
|
|
|
21
23
|
// flip vectors if integration is backwards in time
|
|
22
24
|
if (this->integParams.t0 > this->integParams.tf) {
|
|
@@ -109,11 +109,17 @@ class Body {
|
|
|
109
109
|
real J2 = 0.0L;
|
|
110
110
|
real poleRA = 0.0L;
|
|
111
111
|
real poleDec = 90.0L;
|
|
112
|
+
size_t nZon = 0;
|
|
113
|
+
size_t nTes = 0;
|
|
114
|
+
std::vector<real> J = {};
|
|
115
|
+
std::vector<std::vector<real>> C = {};
|
|
116
|
+
std::vector<std::vector<real>> S = {};
|
|
112
117
|
std::string name;
|
|
113
118
|
int spiceId;
|
|
114
119
|
real pos[3], vel[3], acc[3];
|
|
115
120
|
bool isPPN = false;
|
|
116
121
|
bool isJ2 = false;
|
|
122
|
+
bool isHarmonic = false;
|
|
117
123
|
bool isNongrav = false;
|
|
118
124
|
bool isMajor = false;
|
|
119
125
|
real caTol = 0.1;
|
|
@@ -121,6 +127,12 @@ class Body {
|
|
|
121
127
|
* @brief Set the J2 for the body.
|
|
122
128
|
*/
|
|
123
129
|
void set_J2(real J2, real poleRA, real poleDec);
|
|
130
|
+
/**
|
|
131
|
+
* @brief Set the harmonic coefficients for the body.
|
|
132
|
+
*/
|
|
133
|
+
void set_harmonics(real poleRA, real poleDec, int nZon, int nTes,
|
|
134
|
+
std::vector<real> J, std::vector<std::vector<real>> C,
|
|
135
|
+
std::vector<std::vector<real>> S);
|
|
124
136
|
};
|
|
125
137
|
|
|
126
138
|
/**
|
|
@@ -376,6 +388,8 @@ class ImpactParameters : public CloseApproachParameters {
|
|
|
376
388
|
real lon;
|
|
377
389
|
real lat;
|
|
378
390
|
real alt;
|
|
391
|
+
std::vector<real> dlon = std::vector<real>(6, std::numeric_limits<real>::quiet_NaN());
|
|
392
|
+
std::vector<real> dlat = std::vector<real>(6, std::numeric_limits<real>::quiet_NaN());
|
|
379
393
|
/**
|
|
380
394
|
* @brief Get the impact parameters.
|
|
381
395
|
*/
|
|
@@ -389,12 +403,19 @@ class ImpactParameters : public CloseApproachParameters {
|
|
|
389
403
|
/**
|
|
390
404
|
* @brief Structure to hold interpolation parameters for a PropSimulation.
|
|
391
405
|
*
|
|
406
|
+
* @param interpIdx Index of the interpolation parameters.
|
|
407
|
+
* @param t0 Initial time of the interpolation window.
|
|
408
|
+
* @param dt0 Timespan of the interpolation window.
|
|
409
|
+
* @param b0 Interpolation coefficients for the interpolation window.
|
|
410
|
+
* @param xInteg0 States at the initial time of the interpolation window.
|
|
411
|
+
* @param accInteg0 Accelerations at the initial time of the interpolation window.
|
|
392
412
|
* @param tStack Stack of integrator epochs.
|
|
393
413
|
* @param xIntegStack Stack of states at integrator epochs.
|
|
394
414
|
* @param bStack Stack of interpolation coefficients at integrator epochs.
|
|
395
415
|
* @param accIntegStack Stack of accelerations at integrator epochs.
|
|
396
416
|
*/
|
|
397
417
|
struct InterpolationParameters {
|
|
418
|
+
size_t interpIdx = 0;
|
|
398
419
|
real t0;
|
|
399
420
|
real dt0;
|
|
400
421
|
std::vector<real> b0;
|
|
@@ -411,7 +432,9 @@ struct InterpolationParameters {
|
|
|
411
432
|
*
|
|
412
433
|
* @param name Name of the simulation.
|
|
413
434
|
* @param DEkernelPath Path to DE kernels.
|
|
414
|
-
* @param
|
|
435
|
+
* @param spkEphem SPK ephemeris object for the simulation.
|
|
436
|
+
* @param pckEphem PCK ephemeris object for the simulation.
|
|
437
|
+
* @param unsafePersistentMemoryMap Flag to indicate if ephemeris memory maps should not be unmapped (unsafe, default: false).
|
|
415
438
|
* @param consts Constants object for the simulation.
|
|
416
439
|
* @param integParams Integration parameters for the simulation.
|
|
417
440
|
* @param spiceBodies Vector of SpiceBody objects in the simulation.
|
|
@@ -423,7 +446,6 @@ struct InterpolationParameters {
|
|
|
423
446
|
* @param t Current time of the simulation.
|
|
424
447
|
* @param xInteg Current state of the simulation.
|
|
425
448
|
* @param interpParams Interpolation parameters for the simulation.
|
|
426
|
-
* @param interpIdx Index of the interpolation parameters.
|
|
427
449
|
* @param tEvalUTC Flag to indicate if the evaluation times are in UTC.
|
|
428
450
|
* @param evalApparentState Flag to indicate if the apparent state is evaluated.
|
|
429
451
|
* @param evalMeasurements Flag to indicate if measurements are evaluated.
|
|
@@ -459,6 +481,7 @@ class PropSimulation {
|
|
|
459
481
|
std::string DEkernelPath;
|
|
460
482
|
SpkEphemeris spkEphem;
|
|
461
483
|
PckEphemeris pckEphem;
|
|
484
|
+
bool unsafePersistentMemoryMap = false;
|
|
462
485
|
/**
|
|
463
486
|
* @brief Construct a new PropSimulation object.
|
|
464
487
|
*/
|
|
@@ -490,7 +513,6 @@ class PropSimulation {
|
|
|
490
513
|
real t;
|
|
491
514
|
std::vector<real> xInteg;
|
|
492
515
|
InterpolationParameters interpParams;
|
|
493
|
-
size_t interpIdx = 0;
|
|
494
516
|
bool tEvalUTC = false;
|
|
495
517
|
bool evalApparentState = false;
|
|
496
518
|
bool evalMeasurements = false;
|
|
@@ -63,6 +63,16 @@ using std::tanh;
|
|
|
63
63
|
*
|
|
64
64
|
*/
|
|
65
65
|
#define EARTH_OBLIQUITY 84381.448 / 3600.0 * DEG2RAD
|
|
66
|
+
/**
|
|
67
|
+
* @brief Value of Earth's WGS84 radius in AU.
|
|
68
|
+
*
|
|
69
|
+
*/
|
|
70
|
+
#define EARTH_RAD_WGS84 6378.137 / 1.495978707e8
|
|
71
|
+
/**
|
|
72
|
+
* @brief Value of Earth's WGS84 flattening.
|
|
73
|
+
*
|
|
74
|
+
*/
|
|
75
|
+
#define EARTH_FLAT_WGS84 1.0 / 298.257223563
|
|
66
76
|
|
|
67
77
|
/**
|
|
68
78
|
* @brief Wrap an angle to the range [0, 2*pi).
|