rubin-sim 2.6.1.dev2__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.
- batch/compile_prenight_metadata_cache.sh +34 -0
- batch/run_auxtel_prenight_sims.sh +163 -0
- batch/run_prenight_sims.sh +239 -0
- docs/.gitignore +3 -0
- docs/Makefile +32 -0
- docs/api.rst +25 -0
- docs/conf.py +8 -0
- docs/data-api.rst +12 -0
- docs/data-download.rst +70 -0
- docs/developer.rst +14 -0
- docs/documenteer.toml +11 -0
- docs/index.rst +22 -0
- docs/installation.rst +76 -0
- docs/introduction.rst +37 -0
- docs/maf-api-batches.rst +12 -0
- docs/maf-api-db.rst +12 -0
- docs/maf-api-maf-contrib.rst +12 -0
- docs/maf-api-maps.rst +12 -0
- docs/maf-api-metricbundles.rst +12 -0
- docs/maf-api-metrics.rst +12 -0
- docs/maf-api-plots.rst +12 -0
- docs/maf-api-run-comparison.rst +12 -0
- docs/maf-api-slicers.rst +12 -0
- docs/maf-api-stackers.rst +12 -0
- docs/maf-api-utils.rst +12 -0
- docs/maf-api.rst +22 -0
- docs/maf.rst +60 -0
- docs/metric_list.py +49 -0
- docs/moving-objects-api.rst +12 -0
- docs/moving-objects.rst +22 -0
- docs/phot-utils-api.rst +12 -0
- docs/phot-utils.rst +11 -0
- docs/prenight.rst +117 -0
- docs/protoarchive.rst +276 -0
- docs/satellite-constellations-api.rst +12 -0
- docs/satellite-constellations.rst +13 -0
- docs/selfcal-api.rst +12 -0
- docs/selfcal.rst +15 -0
- docs/sim-archive-api.rst +12 -0
- docs/skybrightness-api.rst +12 -0
- docs/skybrightness.rst +23 -0
- docs/user-guide.rst +28 -0
- docs/vseqarchive-architecture.rst +438 -0
- docs/vseqarchive-setup.rst +238 -0
- docs/vseqarchive.rst +225 -0
- rubin_sim/__init__.py +7 -0
- rubin_sim/data/__init__.py +1 -0
- rubin_sim/data/rs_download_data.py +155 -0
- rubin_sim/maf/__init__.py +34 -0
- rubin_sim/maf/batches/__init__.py +18 -0
- rubin_sim/maf/batches/altaz_batch.py +161 -0
- rubin_sim/maf/batches/col_map_dict.py +274 -0
- rubin_sim/maf/batches/common.py +388 -0
- rubin_sim/maf/batches/ddf_batch.py +728 -0
- rubin_sim/maf/batches/filterchange_batch.py +182 -0
- rubin_sim/maf/batches/glance_batch.py +591 -0
- rubin_sim/maf/batches/hourglass_batch.py +79 -0
- rubin_sim/maf/batches/info_batch.py +114 -0
- rubin_sim/maf/batches/metadata_batch.py +558 -0
- rubin_sim/maf/batches/moving_objects_batch.py +1587 -0
- rubin_sim/maf/batches/openshutter_batch.py +100 -0
- rubin_sim/maf/batches/radar_limited.py +1100 -0
- rubin_sim/maf/batches/science_radar_batch.py +1910 -0
- rubin_sim/maf/batches/skycoverage.py +155 -0
- rubin_sim/maf/batches/slew_batch.py +146 -0
- rubin_sim/maf/batches/srd_batch.py +637 -0
- rubin_sim/maf/batches/time_batch.py +757 -0
- rubin_sim/maf/batches/time_sci_batch.py +105 -0
- rubin_sim/maf/batches/visitdepth_batch.py +485 -0
- rubin_sim/maf/db/__init__.py +2 -0
- rubin_sim/maf/db/add_run.py +34 -0
- rubin_sim/maf/db/results_db.py +1074 -0
- rubin_sim/maf/db/tracking_db.py +332 -0
- rubin_sim/maf/ddf_dir.py +53 -0
- rubin_sim/maf/generate_ss.py +218 -0
- rubin_sim/maf/glance_dir.py +58 -0
- rubin_sim/maf/maf_contrib/__init__.py +25 -0
- rubin_sim/maf/maf_contrib/calculate_lsst_field_visibility_astropy.py +170 -0
- rubin_sim/maf/maf_contrib/depth_limited_num_gal_metric.py +109 -0
- rubin_sim/maf/maf_contrib/example_new_metrics.py +40 -0
- rubin_sim/maf/maf_contrib/filter_pair_t_gaps_metric.py +208 -0
- rubin_sim/maf/maf_contrib/grb_transient_metric.py +249 -0
- rubin_sim/maf/maf_contrib/gw170817_det_metric.py +72 -0
- rubin_sim/maf/maf_contrib/intervals_between_obs_metric.py +68 -0
- rubin_sim/maf/maf_contrib/kne_metrics.py +473 -0
- rubin_sim/maf/maf_contrib/lss_metrics.py +45 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/__init__.py +3 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/constants_for_pipeline.py +73 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_metric_extended.py +205 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_with_pixel_calibration.py +171 -0
- rubin_sim/maf/maf_contrib/lv_dwarfs/__init__.py +1 -0
- rubin_sim/maf/maf_contrib/lv_dwarfs/lv_dwarfs_metrics.py +388 -0
- rubin_sim/maf/maf_contrib/microlensing_metric.py +593 -0
- rubin_sim/maf/maf_contrib/num_obs_in_survey_time_overlap_metric.py +43 -0
- rubin_sim/maf/maf_contrib/periodic_metric.py +51 -0
- rubin_sim/maf/maf_contrib/periodic_star_metric.py +186 -0
- rubin_sim/maf/maf_contrib/periodic_star_modulation_metric.py +236 -0
- rubin_sim/maf/maf_contrib/presto_color_kne_pop_metric.py +441 -0
- rubin_sim/maf/maf_contrib/selfcal_uniformity_metric.py +171 -0
- rubin_sim/maf/maf_contrib/star_count_mass_metric.py +64 -0
- rubin_sim/maf/maf_contrib/star_count_metric.py +56 -0
- rubin_sim/maf/maf_contrib/star_counts/__init__.py +8 -0
- rubin_sim/maf/maf_contrib/star_counts/abs_mag.py +324 -0
- rubin_sim/maf/maf_contrib/star_counts/coords.py +99 -0
- rubin_sim/maf/maf_contrib/star_counts/readme.txt +1 -0
- rubin_sim/maf/maf_contrib/star_counts/spec_type.py +91 -0
- rubin_sim/maf/maf_contrib/star_counts/starcount.py +30 -0
- rubin_sim/maf/maf_contrib/star_counts/starcount_bymass.py +93 -0
- rubin_sim/maf/maf_contrib/star_counts/stellardensity.py +59 -0
- rubin_sim/maf/maf_contrib/static_probes_fom_summary_metric.py +386 -0
- rubin_sim/maf/maf_contrib/tdes_pop_metric.py +362 -0
- rubin_sim/maf/maf_contrib/transient_ascii_sed_metric.py +652 -0
- rubin_sim/maf/maf_contrib/triplet_metric.py +156 -0
- rubin_sim/maf/maf_contrib/var_depth_metric.py +157 -0
- rubin_sim/maf/maf_contrib/xrb_metrics.py +523 -0
- rubin_sim/maf/maf_contrib/young_stellar_objects_metric.py +200 -0
- rubin_sim/maf/maf_night_report.py +200 -0
- rubin_sim/maf/make_fbs_tracking_db.py +90 -0
- rubin_sim/maf/maps/__init__.py +8 -0
- rubin_sim/maf/maps/base_map.py +72 -0
- rubin_sim/maf/maps/create_gaia_density_map.py +158 -0
- rubin_sim/maf/maps/dust_map.py +66 -0
- rubin_sim/maf/maps/dust_map_3d.py +190 -0
- rubin_sim/maf/maps/ebv_3d_hp.py +170 -0
- rubin_sim/maf/maps/ebv_hp.py +64 -0
- rubin_sim/maf/maps/gal_coords_map.py +22 -0
- rubin_sim/maf/maps/galactic_plane_priority_maps.py +210 -0
- rubin_sim/maf/maps/stellar_density_map.py +73 -0
- rubin_sim/maf/maps/trilegal_map.py +82 -0
- rubin_sim/maf/metadata_dir.py +90 -0
- rubin_sim/maf/metric_bundles/__init__.py +3 -0
- rubin_sim/maf/metric_bundles/metric_bundle.py +816 -0
- rubin_sim/maf/metric_bundles/metric_bundle_group.py +834 -0
- rubin_sim/maf/metric_bundles/mo_metric_bundle.py +646 -0
- rubin_sim/maf/metrics/__init__.py +52 -0
- rubin_sim/maf/metrics/agn_time_lag_metric.py +118 -0
- rubin_sim/maf/metrics/agnstructure.py +141 -0
- rubin_sim/maf/metrics/area_summary_metrics.py +120 -0
- rubin_sim/maf/metrics/base_metric.py +215 -0
- rubin_sim/maf/metrics/brown_dwarf_metric.py +162 -0
- rubin_sim/maf/metrics/cadence_metrics.py +400 -0
- rubin_sim/maf/metrics/calibration_metrics.py +618 -0
- rubin_sim/maf/metrics/chip_vendor_metric.py +43 -0
- rubin_sim/maf/metrics/color_slope_metrics.py +189 -0
- rubin_sim/maf/metrics/cosmology_summary_metrics.py +1212 -0
- rubin_sim/maf/metrics/coverage_metric.py +48 -0
- rubin_sim/maf/metrics/crowding_metric.py +255 -0
- rubin_sim/maf/metrics/cumulative_metric.py +46 -0
- rubin_sim/maf/metrics/dcr_metric.py +93 -0
- rubin_sim/maf/metrics/exgal_m5.py +57 -0
- rubin_sim/maf/metrics/fft_metric.py +27 -0
- rubin_sim/maf/metrics/galactic_plane_metrics.py +375 -0
- rubin_sim/maf/metrics/galplane_time_sampling_metrics.py +236 -0
- rubin_sim/maf/metrics/hourglass_metric.py +130 -0
- rubin_sim/maf/metrics/incremental_template_metric.py +255 -0
- rubin_sim/maf/metrics/kuiper_metrics.py +26 -0
- rubin_sim/maf/metrics/mo_metrics.py +1496 -0
- rubin_sim/maf/metrics/mo_summary_metrics.py +464 -0
- rubin_sim/maf/metrics/night_pointing_metric.py +70 -0
- rubin_sim/maf/metrics/optimal_m5_metric.py +94 -0
- rubin_sim/maf/metrics/pair_metric.py +69 -0
- rubin_sim/maf/metrics/periodic_detect_metric.py +133 -0
- rubin_sim/maf/metrics/phase_gap_metric.py +172 -0
- rubin_sim/maf/metrics/qso_number_counts_metric.py +138 -0
- rubin_sim/maf/metrics/scaling_metrics.py +148 -0
- rubin_sim/maf/metrics/schedview_metrics.py +39 -0
- rubin_sim/maf/metrics/season_metrics.py +344 -0
- rubin_sim/maf/metrics/simple_metrics.py +546 -0
- rubin_sim/maf/metrics/sky_sat_metric.py +18 -0
- rubin_sim/maf/metrics/sn_cadence_metric.py +104 -0
- rubin_sim/maf/metrics/sn_n_sn_metric.py +1364 -0
- rubin_sim/maf/metrics/sn_sl_metric.py +216 -0
- rubin_sim/maf/metrics/sn_snr_metric.py +715 -0
- rubin_sim/maf/metrics/snr_weight.py +24 -0
- rubin_sim/maf/metrics/star_density.py +77 -0
- rubin_sim/maf/metrics/string_count_metric.py +95 -0
- rubin_sim/maf/metrics/summary_metrics.py +201 -0
- rubin_sim/maf/metrics/surfb_metric.py +175 -0
- rubin_sim/maf/metrics/technical_metrics.py +271 -0
- rubin_sim/maf/metrics/tgaps.py +412 -0
- rubin_sim/maf/metrics/tomography_models.py +2034 -0
- rubin_sim/maf/metrics/transient_metrics.py +268 -0
- rubin_sim/maf/metrics/uniformity_metrics.py +418 -0
- rubin_sim/maf/metrics/use_metrics.py +55 -0
- rubin_sim/maf/metrics/vector_metrics.py +190 -0
- rubin_sim/maf/metrics/visit_groups_metric.py +341 -0
- rubin_sim/maf/metrics/weak_lensing_systematics_metric.py +210 -0
- rubin_sim/maf/plots/__init__.py +14 -0
- rubin_sim/maf/plots/hg_plotters.py +1117 -0
- rubin_sim/maf/plots/hourglass_plotters.py +120 -0
- rubin_sim/maf/plots/mo_plotters.py +358 -0
- rubin_sim/maf/plots/nd_plotters.py +220 -0
- rubin_sim/maf/plots/neo_distance_plotter.py +140 -0
- rubin_sim/maf/plots/night_pointing_plotter.py +96 -0
- rubin_sim/maf/plots/oned_plotters.py +114 -0
- rubin_sim/maf/plots/perceptual_rainbow.py +30 -0
- rubin_sim/maf/plots/plot_handler.py +766 -0
- rubin_sim/maf/plots/skyproj_plotters.py +540 -0
- rubin_sim/maf/plots/spatial_plotters.py +1029 -0
- rubin_sim/maf/plots/special_plotters.py +256 -0
- rubin_sim/maf/plots/two_d_plotters.py +177 -0
- rubin_sim/maf/plots/xyplotter.py +37 -0
- rubin_sim/maf/run_comparison/__init__.py +5 -0
- rubin_sim/maf/run_comparison/archive.py +584 -0
- rubin_sim/maf/run_comparison/gather_summaries.py +125 -0
- rubin_sim/maf/run_comparison/microlensing_compare.py +514 -0
- rubin_sim/maf/run_comparison/radar_plot.py +202 -0
- rubin_sim/maf/run_comparison/summary_plots.py +710 -0
- rubin_sim/maf/run_moving_calc.py +239 -0
- rubin_sim/maf/run_moving_fractions.py +128 -0
- rubin_sim/maf/run_moving_join.py +103 -0
- rubin_sim/maf/run_selfcal_metric.py +92 -0
- rubin_sim/maf/scimaf_dir.py +87 -0
- rubin_sim/maf/show_maf.py +227 -0
- rubin_sim/maf/slicers/__init__.py +13 -0
- rubin_sim/maf/slicers/base_slicer.py +513 -0
- rubin_sim/maf/slicers/base_spatial_slicer.py +202 -0
- rubin_sim/maf/slicers/healpix_sdss_slicer.py +118 -0
- rubin_sim/maf/slicers/healpix_slicer.py +189 -0
- rubin_sim/maf/slicers/healpix_subset_slicer.py +293 -0
- rubin_sim/maf/slicers/hourglass_slicer.py +37 -0
- rubin_sim/maf/slicers/mo_slicer.py +171 -0
- rubin_sim/maf/slicers/movie_slicer.py +288 -0
- rubin_sim/maf/slicers/nd_slicer.py +147 -0
- rubin_sim/maf/slicers/one_d_slicer.py +210 -0
- rubin_sim/maf/slicers/time_interval_slicers.py +283 -0
- rubin_sim/maf/slicers/uni_slicer.py +57 -0
- rubin_sim/maf/slicers/user_points_slicer.py +141 -0
- rubin_sim/maf/stackers/__init__.py +13 -0
- rubin_sim/maf/stackers/base_stacker.py +221 -0
- rubin_sim/maf/stackers/coord_stackers.py +224 -0
- rubin_sim/maf/stackers/date_stackers.py +192 -0
- rubin_sim/maf/stackers/general_stackers.py +683 -0
- rubin_sim/maf/stackers/get_col_info.py +104 -0
- rubin_sim/maf/stackers/label_stackers.py +114 -0
- rubin_sim/maf/stackers/m5_optimal_stacker.py +126 -0
- rubin_sim/maf/stackers/mo_phase.py +265 -0
- rubin_sim/maf/stackers/mo_stackers.py +486 -0
- rubin_sim/maf/stackers/n_follow_stacker.py +187 -0
- rubin_sim/maf/stackers/neo_dist_stacker.py +126 -0
- rubin_sim/maf/stackers/sdss_stackers.py +30 -0
- rubin_sim/maf/stackers/sn_stacker.py +152 -0
- rubin_sim/maf/stackers/teff_stacker.py +154 -0
- rubin_sim/maf/utils/__init__.py +6 -0
- rubin_sim/maf/utils/astrometry_utils.py +93 -0
- rubin_sim/maf/utils/generate_fov_map.py +58 -0
- rubin_sim/maf/utils/get_date_version.py +28 -0
- rubin_sim/maf/utils/maf_utils.py +212 -0
- rubin_sim/maf/utils/opsim_utils.py +259 -0
- rubin_sim/maf/utils/output_utils.py +34 -0
- rubin_sim/maf/utils/sn_n_sn_utils.py +894 -0
- rubin_sim/maf/utils/sn_utils.py +369 -0
- rubin_sim/maf/utils/stellar_mags.py +197 -0
- rubin_sim/maf/web/__init__.py +2 -0
- rubin_sim/maf/web/favicon.ico +0 -0
- rubin_sim/maf/web/maf_run_results.py +645 -0
- rubin_sim/maf/web/maf_tracking.py +139 -0
- rubin_sim/maf/web/sorttable.js +496 -0
- rubin_sim/maf/web/templates/allmetricresults.html +72 -0
- rubin_sim/maf/web/templates/configs.html +28 -0
- rubin_sim/maf/web/templates/macros.html +243 -0
- rubin_sim/maf/web/templates/master.html +294 -0
- rubin_sim/maf/web/templates/metricselect.html +91 -0
- rubin_sim/maf/web/templates/multicolor.html +147 -0
- rubin_sim/maf/web/templates/results.html +82 -0
- rubin_sim/maf/web/templates/runselect.html +58 -0
- rubin_sim/maf/web/templates/stats.html +50 -0
- rubin_sim/moving_objects/__init__.py +8 -0
- rubin_sim/moving_objects/base_obs.py +468 -0
- rubin_sim/moving_objects/cheby_fits.py +689 -0
- rubin_sim/moving_objects/cheby_values.py +231 -0
- rubin_sim/moving_objects/chebyshev_utils.py +365 -0
- rubin_sim/moving_objects/direct_obs.py +376 -0
- rubin_sim/moving_objects/make_lsst_obs.py +282 -0
- rubin_sim/moving_objects/ooephemerides.py +643 -0
- rubin_sim/moving_objects/orbits.py +507 -0
- rubin_sim/moving_objects/pre_generate.py +37 -0
- rubin_sim/moving_objects/utils.py +61 -0
- rubin_sim/phot_utils/__init__.py +7 -0
- rubin_sim/phot_utils/bandpass.py +425 -0
- rubin_sim/phot_utils/photometric_parameters.py +449 -0
- rubin_sim/phot_utils/physical_parameters.py +50 -0
- rubin_sim/phot_utils/predicted_zeropoints.py +245 -0
- rubin_sim/phot_utils/sed.py +1773 -0
- rubin_sim/phot_utils/sed_utils.py +52 -0
- rubin_sim/phot_utils/signaltonoise.py +695 -0
- rubin_sim/phot_utils/spectral_resampling.py +161 -0
- rubin_sim/satellite_constellations/__init__.py +3 -0
- rubin_sim/satellite_constellations/basis_function.py +40 -0
- rubin_sim/satellite_constellations/model_observatory.py +157 -0
- rubin_sim/satellite_constellations/sat_utils.py +488 -0
- rubin_sim/selfcal/__init__.py +4 -0
- rubin_sim/selfcal/generate_catalog.py +188 -0
- rubin_sim/selfcal/offsets.py +119 -0
- rubin_sim/selfcal/solver.py +143 -0
- rubin_sim/selfcal/star_tools.py +42 -0
- rubin_sim/sim_archive/__init__.py +14 -0
- rubin_sim/sim_archive/conda_packages.py +65 -0
- rubin_sim/sim_archive/future_vsarch.py +480 -0
- rubin_sim/sim_archive/make_snapshot.py +255 -0
- rubin_sim/sim_archive/prenight.py +216 -0
- rubin_sim/sim_archive/prenightindex.py +229 -0
- rubin_sim/sim_archive/prototype.py +1029 -0
- rubin_sim/sim_archive/sim_archive.py +680 -0
- rubin_sim/sim_archive/tempdb.py +56 -0
- rubin_sim/sim_archive/util.py +146 -0
- rubin_sim/sim_archive/vseqarchive.py +965 -0
- rubin_sim/sim_archive/vseqmetadata.py +1721 -0
- rubin_sim/skybrightness/__init__.py +5 -0
- rubin_sim/skybrightness/allsky_db.py +93 -0
- rubin_sim/skybrightness/data/ESO_Spectra/eso_tools.py +505 -0
- rubin_sim/skybrightness/data/solarSpec/package.py +22 -0
- rubin_sim/skybrightness/generate_hdf5.py +243 -0
- rubin_sim/skybrightness/interp_components.py +798 -0
- rubin_sim/skybrightness/sky_model.py +771 -0
- rubin_sim/skybrightness/twilight_func.py +83 -0
- rubin_sim/skybrightness/utils.py +91 -0
- rubin_sim-2.6.1.dev2.dist-info/METADATA +95 -0
- rubin_sim-2.6.1.dev2.dist-info/RECORD +387 -0
- rubin_sim-2.6.1.dev2.dist-info/WHEEL +5 -0
- rubin_sim-2.6.1.dev2.dist-info/entry_points.txt +24 -0
- rubin_sim-2.6.1.dev2.dist-info/licenses/LICENSE +674 -0
- rubin_sim-2.6.1.dev2.dist-info/top_level.txt +5 -0
- sql/make_vseqmeta.sql +251 -0
- tests/data/test_data.py +26 -0
- tests/data/test_ddf_grid.py +17 -0
- tests/maf/test_3x2fom.py +68 -0
- tests/maf/test_archive.py +162 -0
- tests/maf/test_basemetrics.py +99 -0
- tests/maf/test_batchcommon.py +36 -0
- tests/maf/test_batches.py +159 -0
- tests/maf/test_cadencemetrics.py +388 -0
- tests/maf/test_calibrationmetrics.py +242 -0
- tests/maf/test_color_slopes.py +71 -0
- tests/maf/test_cosmology_summaries.py +20 -0
- tests/maf/test_gathersummaries.py +48 -0
- tests/maf/test_healpixslicer.py +439 -0
- tests/maf/test_healpixsubsetslicer.py +273 -0
- tests/maf/test_hgplotters.py +145 -0
- tests/maf/test_hourglassmetric.py +33 -0
- tests/maf/test_io.py +187 -0
- tests/maf/test_json.py +169 -0
- tests/maf/test_maps.py +199 -0
- tests/maf/test_metricbundle.py +69 -0
- tests/maf/test_mometrics.py +422 -0
- tests/maf/test_movieslicer.py +216 -0
- tests/maf/test_ndslicer.py +240 -0
- tests/maf/test_neodistanceplotter.py +41 -0
- tests/maf/test_onedslicer.py +245 -0
- tests/maf/test_opsimutils.py +80 -0
- tests/maf/test_plotters.py +134 -0
- tests/maf/test_resultsdb.py +145 -0
- tests/maf/test_schedviewmetrics.py +14 -0
- tests/maf/test_simplemetrics.py +200 -0
- tests/maf/test_snmetrics.py +335 -0
- tests/maf/test_snmetrics_nsn.py +123 -0
- tests/maf/test_stackers.py +423 -0
- tests/maf/test_stellarmags.py +50 -0
- tests/maf/test_stringcount.py +26 -0
- tests/maf/test_summary_plots.py +197 -0
- tests/maf/test_summarymetrics.py +82 -0
- tests/maf/test_technicalmetrics.py +267 -0
- tests/maf/test_templatemetrics.py +86 -0
- tests/maf/test_timeintervalslicers.py +97 -0
- tests/maf/test_trackingdb.py +88 -0
- tests/maf/test_unislicer.py +116 -0
- tests/maf/test_vectormetrics.py +225 -0
- tests/maf/test_visitgroupsmetric.py +181 -0
- tests/moving_objects/test_camera.py +39 -0
- tests/moving_objects/test_chebyfits.py +188 -0
- tests/moving_objects/test_chebyshevutils.py +76 -0
- tests/moving_objects/test_chebyvalues.py +245 -0
- tests/moving_objects/test_ephemerides.py +219 -0
- tests/moving_objects/test_orbits.py +170 -0
- tests/moving_objects/test_sed_data.py +61 -0
- tests/phot_utils/test_approximatebandpasses.py +91 -0
- tests/phot_utils/test_photometricparameters.py +268 -0
- tests/phot_utils/test_photometry.py +61 -0
- tests/phot_utils/test_predicted_zeropoints.py +53 -0
- tests/phot_utils/test_read_bandpasses.py +29 -0
- tests/phot_utils/test_sed.py +368 -0
- tests/phot_utils/test_snr.py +370 -0
- tests/satellite_constellations/test_satellites.py +36 -0
- tests/sim_archive/test_make_snapshot.py +24 -0
- tests/sim_archive/test_prototype_sim_archive.py +204 -0
- tests/sim_archive/test_vseqarchive.py +947 -0
- tests/skybrightness/test_skymodel.py +359 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import tempfile
|
|
4
|
+
import unittest
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from rubin_scheduler.data import get_data_dir
|
|
9
|
+
|
|
10
|
+
from rubin_sim.moving_objects import ChebyFits, Orbits
|
|
11
|
+
|
|
12
|
+
ROOT = os.path.abspath(os.path.dirname(__file__))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@unittest.skip("Temporary skip until ephemerides replaced")
|
|
16
|
+
class TestChebyFits(unittest.TestCase):
|
|
17
|
+
def setUp(self):
|
|
18
|
+
self.testdir = os.path.join(get_data_dir(), "tests", "orbits_testdata")
|
|
19
|
+
self.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="TestChebyFits-")
|
|
20
|
+
self.orbits = Orbits()
|
|
21
|
+
self.orbits.read_orbits(os.path.join(self.testdir, "test_orbitsMBA.s3m"))
|
|
22
|
+
self.cheb = ChebyFits(
|
|
23
|
+
self.orbits,
|
|
24
|
+
54800,
|
|
25
|
+
30,
|
|
26
|
+
ngran=64,
|
|
27
|
+
sky_tolerance=2.5,
|
|
28
|
+
n_decimal=10,
|
|
29
|
+
n_coeff_position=14,
|
|
30
|
+
)
|
|
31
|
+
self.assertEqual(self.cheb.ngran, 64)
|
|
32
|
+
|
|
33
|
+
def tearDown(self):
|
|
34
|
+
del self.orbits
|
|
35
|
+
del self.cheb
|
|
36
|
+
if os.path.exists(self.scratch_dir):
|
|
37
|
+
shutil.rmtree(self.scratch_dir)
|
|
38
|
+
|
|
39
|
+
def test_precompute_multipliers(self):
|
|
40
|
+
# Precompute multipliers is done as an automatic step in __init__.
|
|
41
|
+
# After setting up self.cheb, these multipliers should all exist.
|
|
42
|
+
for key in self.cheb.n_coeff:
|
|
43
|
+
self.assertTrue(key in self.cheb.multipliers)
|
|
44
|
+
|
|
45
|
+
def test_set_segment_length(self):
|
|
46
|
+
# Expect MBAs with standard ngran and tolerance to have
|
|
47
|
+
# length ~2.0 days.
|
|
48
|
+
self.cheb.calc_segment_length()
|
|
49
|
+
self.assertAlmostEqual(self.cheb.length, 2.0)
|
|
50
|
+
# Test that we can set it to other values which fit into
|
|
51
|
+
# the 30 day window.
|
|
52
|
+
self.cheb.calc_segment_length(length=1.5)
|
|
53
|
+
self.assertEqual(self.cheb.length, 1.5)
|
|
54
|
+
# Test that we if we try to set it to a value which does not
|
|
55
|
+
# fit into the 30 day window,
|
|
56
|
+
# that the actual value used is different - and smaller.
|
|
57
|
+
self.cheb.calc_segment_length(length=1.9)
|
|
58
|
+
self.assertTrue(self.cheb.length < 1.9)
|
|
59
|
+
# Test that we get a warning about the residuals if we try
|
|
60
|
+
# to set the length to be too long.
|
|
61
|
+
with warnings.catch_warnings(record=True) as w:
|
|
62
|
+
self.cheb.calc_segment_length(length=5.0)
|
|
63
|
+
self.assertTrue(len(w), 1)
|
|
64
|
+
# Now check granularity works for other orbit types
|
|
65
|
+
# (which would have other standard lengths).
|
|
66
|
+
# Check for multiple orbit types.
|
|
67
|
+
for orbit_file in [
|
|
68
|
+
"test_orbitsMBA.s3m",
|
|
69
|
+
"test_orbitsOuter.s3m",
|
|
70
|
+
"test_orbitsNEO.s3m",
|
|
71
|
+
]:
|
|
72
|
+
self.orbits.read_orbits(os.path.join(self.testdir, orbit_file))
|
|
73
|
+
t_start = self.orbits.orbits["epoch"].iloc[0]
|
|
74
|
+
cheb = ChebyFits(self.orbits, t_start, 30, ngran=64, n_decimal=2)
|
|
75
|
+
# And that we should converge for a variety of other tolerances.
|
|
76
|
+
for sky_tolerance in (2.5, 5.0, 10.0, 100.0, 1000.0, 20000.0):
|
|
77
|
+
cheb.sky_tolerance = sky_tolerance
|
|
78
|
+
cheb.calc_segment_length()
|
|
79
|
+
pos_resid, ratio = cheb._test_residuals(cheb.length)
|
|
80
|
+
self.assertTrue(pos_resid < sky_tolerance)
|
|
81
|
+
self.assertEqual((cheb.length * 100) % 1, 0)
|
|
82
|
+
# print('final', orbit_file, sky_tolerance, pos_resid,
|
|
83
|
+
# cheb.length, ratio)
|
|
84
|
+
# And check for challenging 'impactors'.
|
|
85
|
+
for orbit_file in ["test_orbitsImpactors.s3m"]:
|
|
86
|
+
self.orbits.read_orbits(os.path.join(self.testdir, orbit_file))
|
|
87
|
+
t_start = self.orbits.orbits["epoch"].iloc[0]
|
|
88
|
+
cheb = ChebyFits(self.orbits, t_start, 30, ngran=64, n_decimal=10)
|
|
89
|
+
# And that we should converge for a variety of other tolerances.
|
|
90
|
+
for sky_tolerance in (2.5, 10.0, 100.0):
|
|
91
|
+
cheb.sky_tolerance = sky_tolerance
|
|
92
|
+
cheb.calc_segment_length()
|
|
93
|
+
pos_resid, ratio = cheb._test_residuals(cheb.length)
|
|
94
|
+
self.assertTrue(pos_resid < sky_tolerance)
|
|
95
|
+
# print('final', orbit_file, sky_tolerance, pos_resid,
|
|
96
|
+
# cheb.length, ratio)
|
|
97
|
+
|
|
98
|
+
@unittest.skip("Skipping because it has a strange platform-dependent failure")
|
|
99
|
+
def test_segments(self):
|
|
100
|
+
# Test that we can create segments.
|
|
101
|
+
self.cheb.calc_segment_length(length=1.0)
|
|
102
|
+
times = self.cheb.make_all_times()
|
|
103
|
+
self.cheb.generate_ephemerides(times)
|
|
104
|
+
self.cheb.calc_segments()
|
|
105
|
+
# We expect calculated coefficients to have the following keys:
|
|
106
|
+
coeff_keys = [
|
|
107
|
+
"obj_id",
|
|
108
|
+
"t_start",
|
|
109
|
+
"t_end",
|
|
110
|
+
"ra",
|
|
111
|
+
"dec",
|
|
112
|
+
"geo_dist",
|
|
113
|
+
"vmag",
|
|
114
|
+
"elongation",
|
|
115
|
+
]
|
|
116
|
+
for k in coeff_keys:
|
|
117
|
+
self.assertTrue(k in self.cheb.coeffs.keys())
|
|
118
|
+
# And in this case, we had a 30 day timespan with 1 day segments
|
|
119
|
+
# (one day segments should be more than enough to meet
|
|
120
|
+
# 2.5mas tolerance, so not subdivided)
|
|
121
|
+
self.assertEqual(len(self.cheb.coeffs["t_start"]), 30 * len(self.orbits))
|
|
122
|
+
# And we used 14 coefficients for ra and dec.
|
|
123
|
+
self.assertEqual(len(self.cheb.coeffs["ra"][0]), 14)
|
|
124
|
+
self.assertEqual(len(self.cheb.coeffs["dec"][0]), 14)
|
|
125
|
+
|
|
126
|
+
def test_write(self):
|
|
127
|
+
# Test that we can write the output to files.
|
|
128
|
+
self.cheb.calc_segment_length()
|
|
129
|
+
self.cheb.generate_ephemerides(self.cheb.make_all_times())
|
|
130
|
+
self.cheb.calc_segments()
|
|
131
|
+
coeff_name = os.path.join(self.scratch_dir, "coeff1.txt")
|
|
132
|
+
resid_name = os.path.join(self.scratch_dir, "resid1.txt")
|
|
133
|
+
failed_name = os.path.join(self.scratch_dir, "failed1.txt")
|
|
134
|
+
self.cheb.write(coeff_name, resid_name, failed_name)
|
|
135
|
+
self.assertTrue(os.path.isfile(coeff_name))
|
|
136
|
+
self.assertTrue(os.path.isfile(resid_name))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@unittest.skip("Temporary skip until ephemerides replaced")
|
|
140
|
+
class TestRun(unittest.TestCase):
|
|
141
|
+
def setUp(self):
|
|
142
|
+
self.testdir = os.path.join(get_data_dir(), "tests", "orbits_testdata")
|
|
143
|
+
self.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="TestChebyFits-")
|
|
144
|
+
self.orbits = Orbits()
|
|
145
|
+
self.orbits.read_orbits(os.path.join(self.testdir, "test_orbitsMBA.s3m"))
|
|
146
|
+
|
|
147
|
+
def tearDown(self):
|
|
148
|
+
del self.orbits
|
|
149
|
+
if os.path.exists(self.scratch_dir):
|
|
150
|
+
shutil.rmtree(self.scratch_dir)
|
|
151
|
+
|
|
152
|
+
def test_run_through(self):
|
|
153
|
+
# Set up chebyshev fitter.
|
|
154
|
+
t_start = self.orbits.orbits.epoch.iloc[0]
|
|
155
|
+
interval = 30
|
|
156
|
+
cheb = ChebyFits(self.orbits, t_start, interval, ngran=64, sky_tolerance=2.5, n_decimal=10)
|
|
157
|
+
# Set granularity. Use an value that will be too long,
|
|
158
|
+
# to trigger recursion below.
|
|
159
|
+
with warnings.catch_warnings():
|
|
160
|
+
warnings.simplefilter("ignore")
|
|
161
|
+
cheb.calc_segment_length(length=10.0)
|
|
162
|
+
# Run through segments.
|
|
163
|
+
cheb.calc_segments()
|
|
164
|
+
self.assertEqual(len(np.unique(cheb.coeffs["obj_id"])), len(self.orbits))
|
|
165
|
+
# Write outputs.
|
|
166
|
+
coeff_name = os.path.join(self.scratch_dir, "coeff2.txt")
|
|
167
|
+
resid_name = os.path.join(self.scratch_dir, "resid2.txt")
|
|
168
|
+
failed_name = os.path.join(self.scratch_dir, "failed2.txt")
|
|
169
|
+
cheb.write(coeff_name, resid_name, failed_name)
|
|
170
|
+
# Test that the segments for each individual object fit
|
|
171
|
+
# together start/end.
|
|
172
|
+
for k in cheb.coeffs:
|
|
173
|
+
cheb.coeffs[k] = np.array(cheb.coeffs[k])
|
|
174
|
+
for obj_id in np.unique(cheb.coeffs["obj_id"]):
|
|
175
|
+
condition = cheb.coeffs["obj_id"] == obj_id
|
|
176
|
+
te_prev = t_start
|
|
177
|
+
for ts, te in zip(cheb.coeffs["t_start"][condition], cheb.coeffs["t_end"][condition]):
|
|
178
|
+
# Test that the start of the current interval =
|
|
179
|
+
# the end of the previous interval.
|
|
180
|
+
self.assertEqual(te_prev, ts)
|
|
181
|
+
te_prev = te
|
|
182
|
+
# Test that the end of the last interval is equal to the end
|
|
183
|
+
# of the total interval
|
|
184
|
+
self.assertEqual(te, t_start + interval)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if __name__ == "__main__":
|
|
188
|
+
unittest.main()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from rubin_sim.moving_objects import chebeval, chebfit, make_cheb_matrix
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestChebgrid(unittest.TestCase):
|
|
9
|
+
def test_raise_error(self):
|
|
10
|
+
x = np.linspace(-1, 1, 9)
|
|
11
|
+
y = np.sin(x)
|
|
12
|
+
dy = np.cos(x)
|
|
13
|
+
p, resid, rms, maxresid = chebfit(x, y, dy, n_poly=4)
|
|
14
|
+
with self.assertRaises(RuntimeError):
|
|
15
|
+
chebeval(np.linspace(-1, 1, 17), p, interval=[1, 2, 3])
|
|
16
|
+
|
|
17
|
+
def test_eval(self):
|
|
18
|
+
x = np.linspace(-1, 1, 9)
|
|
19
|
+
y = np.sin(x)
|
|
20
|
+
dy = np.cos(x)
|
|
21
|
+
p, resid, rms, maxresid = chebfit(x, y, dy, n_poly=4)
|
|
22
|
+
yy_w_vel, vv = chebeval(np.linspace(-1, 1, 17), p)
|
|
23
|
+
yy_wout_vel, vv = chebeval(np.linspace(-1, 1, 17), p, do_velocity=False)
|
|
24
|
+
self.assertTrue(np.allclose(yy_wout_vel, yy_w_vel))
|
|
25
|
+
# Test that we get a nan for a value outside the range of the
|
|
26
|
+
# 'interval', if mask=True
|
|
27
|
+
yy_w_vel, vv = chebeval(np.linspace(-2, 1, 17), p, mask=True)
|
|
28
|
+
self.assertTrue(
|
|
29
|
+
np.isnan(yy_w_vel[0]),
|
|
30
|
+
msg="Expected NaN for masked/out of range value, but got %.2e" % (yy_w_vel[0]),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def test_ends_locked(self):
|
|
34
|
+
x = np.linspace(-1, 1, 9)
|
|
35
|
+
y = np.sin(x)
|
|
36
|
+
dy = np.cos(x)
|
|
37
|
+
for polynomial in range(4, 10):
|
|
38
|
+
p, resid, rms, maxresid = chebfit(x, y, dy, n_poly=4)
|
|
39
|
+
yy, vv = chebeval(np.linspace(-1, 1, 17), p)
|
|
40
|
+
self.assertAlmostEqual(yy[0], y[0], places=13)
|
|
41
|
+
self.assertAlmostEqual(yy[-1], y[-1], places=13)
|
|
42
|
+
self.assertAlmostEqual(vv[0], dy[0], places=13)
|
|
43
|
+
self.assertAlmostEqual(vv[-1], dy[-1], places=13)
|
|
44
|
+
|
|
45
|
+
def test_accuracy(self):
|
|
46
|
+
"""If n_poly is greater than number of values being fit,
|
|
47
|
+
then fit should be exact."""
|
|
48
|
+
x = np.linspace(0, np.pi, 9)
|
|
49
|
+
y = np.sin(x)
|
|
50
|
+
dy = np.cos(x)
|
|
51
|
+
p, resid, rms, maxresid = chebfit(x, y, dy, n_poly=16)
|
|
52
|
+
yy, vv = chebeval(x, p, interval=np.array([0, np.pi]))
|
|
53
|
+
self.assertTrue(np.allclose(yy, y, rtol=1e-13))
|
|
54
|
+
self.assertTrue(np.allclose(vv, dy, rtol=1e-13))
|
|
55
|
+
self.assertLess(np.sum(resid), 1e-13)
|
|
56
|
+
|
|
57
|
+
def test_accuracy_prefit_c1c2(self):
|
|
58
|
+
"""If n_poly is greater than number of values being fit,
|
|
59
|
+
then fit should be exact."""
|
|
60
|
+
NPOINTS = 8
|
|
61
|
+
NPOLY = 16
|
|
62
|
+
x = np.linspace(0, np.pi, NPOINTS + 1)
|
|
63
|
+
y = np.sin(x)
|
|
64
|
+
dy = np.cos(x)
|
|
65
|
+
xmatrix, dxmatrix = make_cheb_matrix(NPOINTS + 1, NPOLY)
|
|
66
|
+
p, resid, rms, maxresid = chebfit(
|
|
67
|
+
x, y, dy, x_multiplier=xmatrix, dx_multiplier=dxmatrix, n_poly=NPOLY
|
|
68
|
+
)
|
|
69
|
+
yy, vv = chebeval(x, p, interval=np.array([0, np.pi]))
|
|
70
|
+
self.assertTrue(np.allclose(yy, y, rtol=1e-13))
|
|
71
|
+
self.assertTrue(np.allclose(vv, dy, rtol=1e-13))
|
|
72
|
+
self.assertLess(np.sum(resid), 1e-13)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
unittest.main()
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import tempfile
|
|
4
|
+
import unittest
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
from astropy.time import Time
|
|
10
|
+
from rubin_scheduler.data import get_data_dir
|
|
11
|
+
|
|
12
|
+
from rubin_sim.moving_objects import ChebyFits, ChebyValues, Orbits, PyOrbEphemerides
|
|
13
|
+
|
|
14
|
+
ROOT = os.path.abspath(os.path.dirname(__file__))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@unittest.skip("Temporary skip until ephemerides replaced")
|
|
18
|
+
class TestChebyValues(unittest.TestCase):
|
|
19
|
+
def setUp(self):
|
|
20
|
+
self.testdatadir = os.path.join(get_data_dir(), "tests", "orbits_testdata")
|
|
21
|
+
self.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="TestChebyValues-")
|
|
22
|
+
self.coeff_file = os.path.join(self.scratch_dir, "test_coeffs")
|
|
23
|
+
self.resid_file = os.path.join(self.scratch_dir, "test_resids")
|
|
24
|
+
self.failed_file = os.path.join(self.scratch_dir, "test_failed")
|
|
25
|
+
self.orbits = Orbits()
|
|
26
|
+
self.orbits.read_orbits(os.path.join(self.testdatadir, "test_orbitsNEO.s3m"), skiprows=1)
|
|
27
|
+
self.pyephems = PyOrbEphemerides()
|
|
28
|
+
self.pyephems.set_orbits(self.orbits)
|
|
29
|
+
self.t_start = self.orbits.orbits.epoch.iloc[0]
|
|
30
|
+
self.interval = 30
|
|
31
|
+
self.n_coeffs = 14
|
|
32
|
+
self.n_decimal = 13
|
|
33
|
+
|
|
34
|
+
self.cheby_fits = ChebyFits(
|
|
35
|
+
self.orbits,
|
|
36
|
+
self.t_start,
|
|
37
|
+
self.interval,
|
|
38
|
+
ngran=64,
|
|
39
|
+
sky_tolerance=2.5,
|
|
40
|
+
n_decimal=self.n_decimal,
|
|
41
|
+
n_coeff_position=self.n_coeffs,
|
|
42
|
+
obscode=807,
|
|
43
|
+
time_scale="TAI",
|
|
44
|
+
)
|
|
45
|
+
self.set_length = 0.5
|
|
46
|
+
self.cheby_fits.calc_segment_length(length=self.set_length)
|
|
47
|
+
self.cheby_fits.calc_segments()
|
|
48
|
+
self.cheby_fits.write(self.coeff_file, self.resid_file, self.failed_file, append=False)
|
|
49
|
+
self.coeff_keys = [
|
|
50
|
+
"obj_id",
|
|
51
|
+
"t_start",
|
|
52
|
+
"t_end",
|
|
53
|
+
"ra",
|
|
54
|
+
"dec",
|
|
55
|
+
"geo_dist",
|
|
56
|
+
"vmag",
|
|
57
|
+
"elongation",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
def tearDown(self):
|
|
61
|
+
del self.orbits
|
|
62
|
+
del self.cheby_fits
|
|
63
|
+
if os.path.exists(self.scratch_dir):
|
|
64
|
+
shutil.rmtree(self.scratch_dir)
|
|
65
|
+
|
|
66
|
+
def test_set_coeff(self):
|
|
67
|
+
# Test setting coefficients directly from chebyFits outputs.
|
|
68
|
+
cheby_values = ChebyValues()
|
|
69
|
+
cheby_values.set_coefficients(self.cheby_fits)
|
|
70
|
+
for k in self.coeff_keys:
|
|
71
|
+
self.assertTrue(k in cheby_values.coeffs)
|
|
72
|
+
self.assertTrue(isinstance(cheby_values.coeffs[k], np.ndarray))
|
|
73
|
+
self.assertEqual(len(np.unique(cheby_values.coeffs["obj_id"])), len(self.orbits))
|
|
74
|
+
# This will only be true for carefully selected length/orbit type,
|
|
75
|
+
# where subdivision did not occur.
|
|
76
|
+
# For the test MBAs, a len=1day will work.
|
|
77
|
+
# For the test NEOs, a len=0.25 day will work (with 2.5mas skyTol).
|
|
78
|
+
# self.assertEqual(len(cheby_values.coeffs['tStart']),
|
|
79
|
+
# (self.interval / self.set_length) * len(self.orbits))
|
|
80
|
+
self.assertEqual(len(cheby_values.coeffs["ra"][0]), self.n_coeffs)
|
|
81
|
+
self.assertTrue("meanRA" in cheby_values.coeffs)
|
|
82
|
+
self.assertTrue("meanDec" in cheby_values.coeffs)
|
|
83
|
+
|
|
84
|
+
def test_read_coeffs(self):
|
|
85
|
+
# Test reading the coefficients from disk.
|
|
86
|
+
cheby_values = ChebyValues()
|
|
87
|
+
cheby_values.read_coefficients(self.coeff_file)
|
|
88
|
+
cheby_values2 = ChebyValues()
|
|
89
|
+
cheby_values2.set_coefficients(self.cheby_fits)
|
|
90
|
+
for k in cheby_values.coeffs:
|
|
91
|
+
if k == "obj_id":
|
|
92
|
+
# Can't test strings with np.test.assert_almost_equal.
|
|
93
|
+
np.testing.assert_equal(cheby_values.coeffs[k], cheby_values2.coeffs[k])
|
|
94
|
+
else:
|
|
95
|
+
# All of these will only be accurate to 2 less decimal places
|
|
96
|
+
# than they are print out with in chebyFits. Since vmag,
|
|
97
|
+
# delta and elongation only use 7
|
|
98
|
+
# decimal places, this means we can test to 5 decimal
|
|
99
|
+
# places for those.
|
|
100
|
+
np.testing.assert_allclose(cheby_values.coeffs[k], cheby_values2.coeffs[k], rtol=0, atol=1e-5)
|
|
101
|
+
|
|
102
|
+
def test_get_ephemerides(self):
|
|
103
|
+
# Test that get_ephemerides works and is accurate.
|
|
104
|
+
cheby_values = ChebyValues()
|
|
105
|
+
cheby_values.set_coefficients(self.cheby_fits)
|
|
106
|
+
|
|
107
|
+
# Multiple times, all objects, all within interval.
|
|
108
|
+
tstep = self.interval / 10.0
|
|
109
|
+
time = np.arange(self.t_start, self.t_start + self.interval, tstep)
|
|
110
|
+
# Test for a single time, but all the objects.
|
|
111
|
+
ephemerides = cheby_values.get_ephemerides(time)
|
|
112
|
+
pyephemerides = self.pyephems.generate_ephemerides(
|
|
113
|
+
time, obscode=807, time_scale="TAI", by_object=True
|
|
114
|
+
)
|
|
115
|
+
# Looks like there's some weird hardware dependent issue
|
|
116
|
+
# where cheby_fits is failing to fit some orbits.
|
|
117
|
+
|
|
118
|
+
# RA and Dec should agree to 2.5mas (sky_tolerance above)
|
|
119
|
+
pos_residuals = np.sqrt(
|
|
120
|
+
(ephemerides["ra"] - pyephemerides["ra"]) ** 2
|
|
121
|
+
+ ((ephemerides["dec"] - pyephemerides["dec"]) * np.cos(np.radians(ephemerides["dec"]))) ** 2
|
|
122
|
+
)
|
|
123
|
+
pos_residuals *= 3600.0 * 1000.0
|
|
124
|
+
if not np.all(np.isfinite(ephemerides["ra"])):
|
|
125
|
+
warnings.warn("NaN values from ChebyValues.get_ephemerides, skipping some tests")
|
|
126
|
+
else:
|
|
127
|
+
# Let's just look at the max residuals in all quantities.
|
|
128
|
+
for k in ("ra", "dec", "dradt", "ddecdt", "geo_dist"):
|
|
129
|
+
resids = np.abs(ephemerides[k] - pyephemerides[k])
|
|
130
|
+
if k != "geo_dist":
|
|
131
|
+
resids *= 3600.0 * 1000.0
|
|
132
|
+
print("max diff", k, np.max(resids))
|
|
133
|
+
resids = np.abs(ephemerides["elongation"] - pyephemerides["solarelon"])
|
|
134
|
+
print("max diff elongation", np.max(resids))
|
|
135
|
+
resids = np.abs(ephemerides["vmag"] - pyephemerides["magV"])
|
|
136
|
+
print("max diff vmag", np.max(resids))
|
|
137
|
+
self.assertLessEqual(np.nanmax(pos_residuals), 2.5)
|
|
138
|
+
# Test for single time, but for a subset of the objects.
|
|
139
|
+
obj_ids = self.orbits.orbits.obj_id.head(3).values
|
|
140
|
+
ephemerides = cheby_values.get_ephemerides(time, obj_ids)
|
|
141
|
+
self.assertEqual(len(ephemerides["ra"]), 3)
|
|
142
|
+
# Test for time outside of segment range.
|
|
143
|
+
obj_ids = self.orbits.orbits.obj_id.head(3).values
|
|
144
|
+
ephemerides = cheby_values.get_ephemerides(
|
|
145
|
+
self.t_start + self.interval * 2, obj_ids, extrapolate=False
|
|
146
|
+
)
|
|
147
|
+
self.assertTrue(
|
|
148
|
+
np.isnan(ephemerides["ra"][0]),
|
|
149
|
+
msg=f"Expected Nan for out of range ephemeris, got {ephemerides['ra'][0]}",
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@unittest.skip("Temporary skip until ephemerides replaced")
|
|
154
|
+
class TestJPLValues(unittest.TestCase):
|
|
155
|
+
# Test the interpolation-generated RA/Dec values against JPL
|
|
156
|
+
# generated RA/Dec values.
|
|
157
|
+
# The resulting errors should be similar to the errors reported
|
|
158
|
+
# from testEphemerides when testing against JPL values.
|
|
159
|
+
def setUp(self):
|
|
160
|
+
# Read orbits.
|
|
161
|
+
self.orbits = Orbits()
|
|
162
|
+
self.jpl_dir = os.path.join(get_data_dir(), "tests", "jpl_testdata")
|
|
163
|
+
self.orbits.read_orbits(os.path.join(self.jpl_dir, "S0_n747.des"), skiprows=1)
|
|
164
|
+
# Read JPL ephems.
|
|
165
|
+
self.jpl = pd.read_table(os.path.join(self.jpl_dir, "807_n747.txt"), sep=r"\s+")
|
|
166
|
+
self.jpl["obj_id"] = self.jpl["objId"]
|
|
167
|
+
# Add times in TAI and UTC, because.
|
|
168
|
+
t = Time(self.jpl["epoch_mjd"], format="mjd", scale="utc")
|
|
169
|
+
self.jpl["mjdTAI"] = t.tai.mjd
|
|
170
|
+
self.jpl["mjdUTC"] = t.utc.mjd
|
|
171
|
+
self.jpl = self.jpl.to_records(index=False)
|
|
172
|
+
# Generate interpolation coefficients for the time period
|
|
173
|
+
# in the JPL catalog.
|
|
174
|
+
self.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="TestJPLValues-")
|
|
175
|
+
self.coeff_file = os.path.join(self.scratch_dir, "test_coeffs")
|
|
176
|
+
self.resid_file = os.path.join(self.scratch_dir, "test_resids")
|
|
177
|
+
self.failed_file = os.path.join(self.scratch_dir, "test_failed")
|
|
178
|
+
t_start = self.jpl["mjdTAI"].min() - 0.2
|
|
179
|
+
t_end = self.jpl["mjdTAI"].max() + 0.2 - self.jpl["mjdTAI"].min()
|
|
180
|
+
self.cheby_fits = ChebyFits(
|
|
181
|
+
self.orbits,
|
|
182
|
+
t_start,
|
|
183
|
+
t_end,
|
|
184
|
+
ngran=64,
|
|
185
|
+
sky_tolerance=2.5,
|
|
186
|
+
n_decimal=14,
|
|
187
|
+
obscode=807,
|
|
188
|
+
)
|
|
189
|
+
self.cheby_fits.calc_segment_length()
|
|
190
|
+
self.cheby_fits.calc_segments()
|
|
191
|
+
|
|
192
|
+
self.coeff_keys = [
|
|
193
|
+
"obj_id",
|
|
194
|
+
"t_start",
|
|
195
|
+
"t_end",
|
|
196
|
+
"ra",
|
|
197
|
+
"dec",
|
|
198
|
+
"geo_dist",
|
|
199
|
+
"vmag",
|
|
200
|
+
"elongation",
|
|
201
|
+
]
|
|
202
|
+
self.cheby_values = ChebyValues()
|
|
203
|
+
self.cheby_values.set_coefficients(self.cheby_fits)
|
|
204
|
+
|
|
205
|
+
def tearDown(self):
|
|
206
|
+
del self.orbits
|
|
207
|
+
del self.jpl
|
|
208
|
+
if os.path.exists(self.scratch_dir):
|
|
209
|
+
shutil.rmtree(self.scratch_dir)
|
|
210
|
+
|
|
211
|
+
def test_ra_dec(self):
|
|
212
|
+
# We won't compare Vmag, because this also needs
|
|
213
|
+
# information on trailing losses.
|
|
214
|
+
times = np.unique(self.jpl["mjdTAI"])
|
|
215
|
+
delta_ra = np.zeros(len(times), float)
|
|
216
|
+
delta_dec = np.zeros(len(times), float)
|
|
217
|
+
for i, t in enumerate(times):
|
|
218
|
+
# Find the JPL obj_ids visible at this time.
|
|
219
|
+
j = self.jpl[np.where(self.jpl["mjdTAI"] == t)]
|
|
220
|
+
ephs = self.cheby_values.get_ephemerides(t, obj_ids=j["obj_id"])
|
|
221
|
+
ephorder = np.argsort(ephs["obj_id"])
|
|
222
|
+
# Sometimes I've had to reorder both, sometimes just the ephs. ??
|
|
223
|
+
jorder = np.argsort(j["obj_id"])
|
|
224
|
+
jorder = np.arange(0, len(jorder))
|
|
225
|
+
d_ra = np.abs(ephs["ra"][ephorder][:, 0] - j["ra_deg"][jorder]) * 3600.0 * 1000.0
|
|
226
|
+
d_dec = np.abs(ephs["dec"][ephorder][:, 0] - j["dec_deg"][jorder]) * 3600.0 * 1000.0
|
|
227
|
+
delta_ra[i] = d_ra.max()
|
|
228
|
+
delta_dec[i] = d_dec.max()
|
|
229
|
+
# Should be (given OOrb direct prediction):
|
|
230
|
+
# Much of the time we're closer than 1mas, but there are a
|
|
231
|
+
# few which hit higher values.
|
|
232
|
+
# This is consistent with the errors/values reported by oorb
|
|
233
|
+
# directly in testEphemerides.
|
|
234
|
+
|
|
235
|
+
# # XXX--units?
|
|
236
|
+
print("max JPL errors", delta_ra.max(), delta_dec.max())
|
|
237
|
+
print("std of JPL errors", np.std(delta_ra), np.std(delta_dec))
|
|
238
|
+
self.assertLess(np.max(delta_ra), 25)
|
|
239
|
+
self.assertLess(np.max(delta_dec), 25)
|
|
240
|
+
self.assertLess(np.std(delta_ra), 3)
|
|
241
|
+
self.assertLess(np.std(delta_dec), 3)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
unittest.main()
|