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,439 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
import healpy as hp
|
|
4
|
+
import matplotlib
|
|
5
|
+
import numpy as np
|
|
6
|
+
import numpy.lib.recfunctions as rfn
|
|
7
|
+
import numpy.ma as ma
|
|
8
|
+
|
|
9
|
+
from rubin_sim.maf.slicers import HealpixSlicer
|
|
10
|
+
|
|
11
|
+
matplotlib.use("Agg")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def make_data_values(
|
|
15
|
+
size=100,
|
|
16
|
+
minval=0.0,
|
|
17
|
+
maxval=1.0,
|
|
18
|
+
ramin=0,
|
|
19
|
+
ramax=2 * np.pi,
|
|
20
|
+
decmin=-np.pi,
|
|
21
|
+
decmax=np.pi,
|
|
22
|
+
random=1172,
|
|
23
|
+
):
|
|
24
|
+
"""Generate a simple array of numbers, evenly arranged between min/max,
|
|
25
|
+
in 1 dimensions (optionally sorted), together with RA/Dec values
|
|
26
|
+
for each data value."""
|
|
27
|
+
data = []
|
|
28
|
+
# Generate data values min - max.
|
|
29
|
+
datavalues = np.arange(0, size, dtype="float")
|
|
30
|
+
datavalues *= (float(maxval) - float(minval)) / (datavalues.max() - datavalues.min())
|
|
31
|
+
datavalues += minval
|
|
32
|
+
rng = np.random.RandomState(random)
|
|
33
|
+
randorder = rng.rand(size)
|
|
34
|
+
randind = np.argsort(randorder)
|
|
35
|
+
datavalues = datavalues[randind]
|
|
36
|
+
datavalues = np.array(list(zip(datavalues)), dtype=[("testdata", "float")])
|
|
37
|
+
data.append(datavalues)
|
|
38
|
+
# Generate RA/Dec values equally spaces on sphere between
|
|
39
|
+
# ramin/max, decmin/max.
|
|
40
|
+
ra = np.arange(0, size, dtype="float")
|
|
41
|
+
ra *= (float(ramax) - float(ramin)) / (ra.max() - ra.min())
|
|
42
|
+
randorder = rng.rand(size)
|
|
43
|
+
randind = np.argsort(randorder)
|
|
44
|
+
ra = ra[randind]
|
|
45
|
+
ra = np.array(list(zip(ra)), dtype=[("ra", "float")])
|
|
46
|
+
data.append(ra)
|
|
47
|
+
v = np.arange(0, size, dtype="float")
|
|
48
|
+
v *= ((np.cos(decmax + np.pi) + 1.0) / 2.0 - (np.cos(decmin + np.pi) + 1.0) / 2.0) / (v.max() - v.min())
|
|
49
|
+
v += (np.cos(decmin + np.pi) + 1.0) / 2.0
|
|
50
|
+
dec = np.arccos(2 * v - 1) - np.pi
|
|
51
|
+
randorder = rng.rand(size)
|
|
52
|
+
randind = np.argsort(randorder)
|
|
53
|
+
dec = dec[randind]
|
|
54
|
+
dec = np.array(list(zip(dec)), dtype=[("dec", "float")])
|
|
55
|
+
data.append(dec)
|
|
56
|
+
# Add in rotation angle
|
|
57
|
+
rot = rng.rand(len(dec)) * 2 * np.pi
|
|
58
|
+
data.append(np.array(rot, dtype=[("rotSkyPos", "float")]))
|
|
59
|
+
mjd = np.arange(len(dec)) * 0.1
|
|
60
|
+
data.append(np.array(mjd, dtype=[("observationStartMJD", "float")]))
|
|
61
|
+
data = rfn.merge_arrays(data, flatten=True, usemask=False)
|
|
62
|
+
return data
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def calc_dist_vincenty(ra1, dec1, ra2, dec2):
|
|
66
|
+
"""Calculates distance on a sphere using the Vincenty formula.
|
|
67
|
+
Give this function RA/Dec values in radians.
|
|
68
|
+
Returns angular distance(s), in radians.
|
|
69
|
+
Note that since this is all numpy, you could input arrays of RA/Decs."""
|
|
70
|
+
d1 = (np.cos(dec2) * np.sin(ra2 - ra1)) ** 2 + (
|
|
71
|
+
np.cos(dec1) * np.sin(dec2) - np.sin(dec1) * np.cos(dec2) * np.cos(ra2 - ra1)
|
|
72
|
+
) ** 2
|
|
73
|
+
d1 = np.sqrt(d1)
|
|
74
|
+
d2 = np.sin(dec1) * np.sin(dec2) + np.cos(dec1) * np.cos(dec2) * np.cos(ra2 - ra1)
|
|
75
|
+
D = np.arctan2(d1, d2)
|
|
76
|
+
return D
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class TestHealpixSlicerSetup(unittest.TestCase):
|
|
80
|
+
def test_slicertype(self):
|
|
81
|
+
"""Test instantiation of slicer sets slicer type as expected."""
|
|
82
|
+
testslicer = HealpixSlicer(nside=16, verbose=False)
|
|
83
|
+
self.assertEqual(testslicer.slicer_name, testslicer.__class__.__name__)
|
|
84
|
+
self.assertEqual(testslicer.slicer_name, "HealpixSlicer")
|
|
85
|
+
|
|
86
|
+
def test_nsides_nbins(self):
|
|
87
|
+
"""Test that number of sides passed to slicer produces expected
|
|
88
|
+
number of bins."""
|
|
89
|
+
nsides = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
|
|
90
|
+
npixx = [12, 48, 192, 768, 3072, 12288, 49152, 196608, 786432, 3145728]
|
|
91
|
+
for nside, npix in zip(nsides, npixx):
|
|
92
|
+
testslicer = HealpixSlicer(
|
|
93
|
+
nside=nside,
|
|
94
|
+
verbose=False,
|
|
95
|
+
)
|
|
96
|
+
self.assertEqual(testslicer.nslice, npix)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class TestHealpixSlicerEqual(unittest.TestCase):
|
|
100
|
+
def setUp(self):
|
|
101
|
+
self.nside = 16
|
|
102
|
+
self.testslicer = HealpixSlicer(
|
|
103
|
+
nside=self.nside,
|
|
104
|
+
verbose=False,
|
|
105
|
+
lon_col="ra",
|
|
106
|
+
lat_col="dec",
|
|
107
|
+
)
|
|
108
|
+
nvalues = 10000
|
|
109
|
+
self.dv = make_data_values(
|
|
110
|
+
size=nvalues,
|
|
111
|
+
minval=0.0,
|
|
112
|
+
maxval=1.0,
|
|
113
|
+
ramin=0,
|
|
114
|
+
ramax=2 * np.pi,
|
|
115
|
+
decmin=-np.pi,
|
|
116
|
+
decmax=0,
|
|
117
|
+
random=22,
|
|
118
|
+
)
|
|
119
|
+
self.testslicer.setup_slicer(self.dv)
|
|
120
|
+
|
|
121
|
+
def tearDown(self):
|
|
122
|
+
del self.testslicer
|
|
123
|
+
del self.dv
|
|
124
|
+
self.testslicer = None
|
|
125
|
+
|
|
126
|
+
def test_slicer_equivalence(self):
|
|
127
|
+
"""Test that slicers are marked equal when appropriate,
|
|
128
|
+
and unequal when appropriate."""
|
|
129
|
+
# Note that they are judged equal based on nsides
|
|
130
|
+
# (not on data in ra/dec spatial tree).
|
|
131
|
+
testslicer2 = HealpixSlicer(
|
|
132
|
+
nside=self.nside,
|
|
133
|
+
verbose=False,
|
|
134
|
+
lon_col="ra",
|
|
135
|
+
lat_col="dec",
|
|
136
|
+
)
|
|
137
|
+
self.assertEqual(self.testslicer, testslicer2)
|
|
138
|
+
assert (self.testslicer != testslicer2) is False
|
|
139
|
+
testslicer2 = HealpixSlicer(
|
|
140
|
+
nside=self.nside / 2.0,
|
|
141
|
+
verbose=False,
|
|
142
|
+
lon_col="ra",
|
|
143
|
+
lat_col="dec",
|
|
144
|
+
)
|
|
145
|
+
self.assertNotEqual(self.testslicer, testslicer2)
|
|
146
|
+
assert (self.testslicer != testslicer2) is True
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class TestHealpixSlicerIteration(unittest.TestCase):
|
|
150
|
+
def setUp(self):
|
|
151
|
+
self.nside = 8
|
|
152
|
+
self.testslicer = HealpixSlicer(
|
|
153
|
+
nside=self.nside,
|
|
154
|
+
verbose=False,
|
|
155
|
+
lon_col="ra",
|
|
156
|
+
lat_col="dec",
|
|
157
|
+
)
|
|
158
|
+
nvalues = 10000
|
|
159
|
+
self.dv = make_data_values(
|
|
160
|
+
size=nvalues,
|
|
161
|
+
minval=0.0,
|
|
162
|
+
maxval=1.0,
|
|
163
|
+
ramin=0,
|
|
164
|
+
ramax=2 * np.pi,
|
|
165
|
+
decmin=-np.pi,
|
|
166
|
+
decmax=0,
|
|
167
|
+
random=33,
|
|
168
|
+
)
|
|
169
|
+
self.testslicer.setup_slicer(self.dv)
|
|
170
|
+
|
|
171
|
+
def tearDown(self):
|
|
172
|
+
del self.testslicer
|
|
173
|
+
self.testslicer = None
|
|
174
|
+
|
|
175
|
+
def test_iteration(self):
|
|
176
|
+
"""Test iteration goes through expected range and ra/dec
|
|
177
|
+
are in expected range (radians)."""
|
|
178
|
+
npix = hp.nside2npix(self.nside)
|
|
179
|
+
for i, s in enumerate(self.testslicer):
|
|
180
|
+
self.assertEqual(i, s["slice_point"]["sid"])
|
|
181
|
+
ra = s["slice_point"]["ra"]
|
|
182
|
+
dec = s["slice_point"]["dec"]
|
|
183
|
+
self.assertGreaterEqual(ra, 0)
|
|
184
|
+
self.assertLessEqual(ra, 2 * np.pi)
|
|
185
|
+
self.assertGreaterEqual(dec, -np.pi)
|
|
186
|
+
self.assertLessEqual(dec, np.pi)
|
|
187
|
+
# npix would count starting at 1, while i counts starting at 0 ..
|
|
188
|
+
# so add one to check end point
|
|
189
|
+
self.assertEqual(i + 1, npix)
|
|
190
|
+
|
|
191
|
+
def test_get_item(self):
|
|
192
|
+
"""Test getting indexed value."""
|
|
193
|
+
for i, s in enumerate(self.testslicer):
|
|
194
|
+
np.testing.assert_equal(self.testslicer[i], s)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class TestHealpixSlicerSlicing(unittest.TestCase):
|
|
198
|
+
# Note that this is really testing baseSpatialSlicer,
|
|
199
|
+
# as slicing is done there for healpix grid
|
|
200
|
+
|
|
201
|
+
def setUp(self):
|
|
202
|
+
self.nside = 8
|
|
203
|
+
self.radius = 1.8
|
|
204
|
+
self.testslicer = HealpixSlicer(
|
|
205
|
+
nside=self.nside,
|
|
206
|
+
verbose=False,
|
|
207
|
+
lon_col="ra",
|
|
208
|
+
lat_col="dec",
|
|
209
|
+
lat_lon_deg=False,
|
|
210
|
+
radius=self.radius,
|
|
211
|
+
use_camera=False,
|
|
212
|
+
)
|
|
213
|
+
nvalues = 10000
|
|
214
|
+
self.dv = make_data_values(
|
|
215
|
+
size=nvalues,
|
|
216
|
+
minval=0.0,
|
|
217
|
+
maxval=1.0,
|
|
218
|
+
ramin=0,
|
|
219
|
+
ramax=2 * np.pi,
|
|
220
|
+
decmin=-np.pi,
|
|
221
|
+
decmax=0,
|
|
222
|
+
random=44,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
def tearDown(self):
|
|
226
|
+
del self.testslicer
|
|
227
|
+
self.testslicer = None
|
|
228
|
+
|
|
229
|
+
def test_slicing(self):
|
|
230
|
+
"""Test slicing returns (all) data points which are within
|
|
231
|
+
'radius' of bin point."""
|
|
232
|
+
# Test that slicing fails before setup_slicer
|
|
233
|
+
self.assertRaises(NotImplementedError, self.testslicer._slice_sim_data, 0)
|
|
234
|
+
# Set up and test actual slicing.
|
|
235
|
+
self.testslicer.setup_slicer(self.dv)
|
|
236
|
+
for s in self.testslicer:
|
|
237
|
+
ra = s["slice_point"]["ra"]
|
|
238
|
+
dec = s["slice_point"]["dec"]
|
|
239
|
+
distances = calc_dist_vincenty(ra, dec, self.dv["ra"], self.dv["dec"])
|
|
240
|
+
didxs = np.where(distances <= np.radians(self.radius))
|
|
241
|
+
sidxs = s["idxs"]
|
|
242
|
+
self.assertEqual(len(sidxs), len(didxs[0]))
|
|
243
|
+
if len(sidxs) > 0:
|
|
244
|
+
didxs = np.sort(didxs[0])
|
|
245
|
+
sidxs = np.sort(sidxs)
|
|
246
|
+
np.testing.assert_equal(self.dv["testdata"][didxs], self.dv["testdata"][sidxs])
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class TestHealpixChipGap(unittest.TestCase):
|
|
250
|
+
# Note that this is really testing baseSpatialSlicer,
|
|
251
|
+
# as slicing is done there for healpix grid
|
|
252
|
+
|
|
253
|
+
def setUp(self):
|
|
254
|
+
self.nside = 8
|
|
255
|
+
self.radius = 2.041
|
|
256
|
+
self.testslicer = HealpixSlicer(
|
|
257
|
+
nside=self.nside,
|
|
258
|
+
verbose=False,
|
|
259
|
+
lon_col="ra",
|
|
260
|
+
lat_col="dec",
|
|
261
|
+
lat_lon_deg=False,
|
|
262
|
+
radius=self.radius,
|
|
263
|
+
use_camera=True,
|
|
264
|
+
)
|
|
265
|
+
nvalues = 1000
|
|
266
|
+
self.dv = make_data_values(
|
|
267
|
+
size=nvalues,
|
|
268
|
+
minval=0.0,
|
|
269
|
+
maxval=1.0,
|
|
270
|
+
ramin=0,
|
|
271
|
+
ramax=2 * np.pi,
|
|
272
|
+
decmin=-np.pi,
|
|
273
|
+
decmax=0,
|
|
274
|
+
random=55,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
def tearDown(self):
|
|
278
|
+
del self.testslicer
|
|
279
|
+
self.testslicer = None
|
|
280
|
+
|
|
281
|
+
def test_slicing(self):
|
|
282
|
+
"""Test slicing returns (most) data points which are
|
|
283
|
+
within 'radius' of bin point."""
|
|
284
|
+
# Test that slicing fails before setup_slicer
|
|
285
|
+
self.assertRaises(NotImplementedError, self.testslicer._slice_sim_data, 0)
|
|
286
|
+
# Set up and test actual slicing.
|
|
287
|
+
self.testslicer.setup_slicer(self.dv)
|
|
288
|
+
for s in self.testslicer:
|
|
289
|
+
ra = s["slice_point"]["ra"]
|
|
290
|
+
dec = s["slice_point"]["dec"]
|
|
291
|
+
# Find the points of 'dv' which are within self.radius of
|
|
292
|
+
# this slice_point
|
|
293
|
+
distances = calc_dist_vincenty(ra, dec, self.dv["ra"], self.dv["dec"])
|
|
294
|
+
didxs = np.where(distances <= np.radians(self.radius))
|
|
295
|
+
# find the indexes of dv which the slicer says are in the
|
|
296
|
+
# camera footprint
|
|
297
|
+
sidxs = s["idxs"]
|
|
298
|
+
self.assertLessEqual(len(sidxs), len(didxs[0]))
|
|
299
|
+
if len(sidxs) > 0:
|
|
300
|
+
for indx in sidxs:
|
|
301
|
+
self.assertIn(self.dv["testdata"][indx], self.dv["testdata"][didxs])
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class TestHealpixCameraRadius(unittest.TestCase):
|
|
305
|
+
# Check that setting the camera radius to a smaller value
|
|
306
|
+
# reduces the number of points matched (that we are using
|
|
307
|
+
# LsstCameraFootprint correctly)
|
|
308
|
+
|
|
309
|
+
def setUp(self):
|
|
310
|
+
self.nside = 8
|
|
311
|
+
self.radius = 2.041
|
|
312
|
+
self.testslicer = HealpixSlicer(
|
|
313
|
+
nside=self.nside,
|
|
314
|
+
verbose=False,
|
|
315
|
+
lon_col="ra",
|
|
316
|
+
lat_col="dec",
|
|
317
|
+
lat_lon_deg=False,
|
|
318
|
+
radius=self.radius,
|
|
319
|
+
use_camera=True,
|
|
320
|
+
)
|
|
321
|
+
self.camera_radius = 0.5
|
|
322
|
+
self.testsmallslicer = HealpixSlicer(
|
|
323
|
+
nside=self.nside,
|
|
324
|
+
verbose=False,
|
|
325
|
+
lon_col="ra",
|
|
326
|
+
lat_col="dec",
|
|
327
|
+
lat_lon_deg=False,
|
|
328
|
+
radius=self.radius,
|
|
329
|
+
use_camera=True,
|
|
330
|
+
camera_radius=self.camera_radius,
|
|
331
|
+
)
|
|
332
|
+
nvalues = 100
|
|
333
|
+
self.dv = make_data_values(
|
|
334
|
+
size=nvalues * hp.nside2npix(self.nside),
|
|
335
|
+
minval=0.0,
|
|
336
|
+
maxval=1.0,
|
|
337
|
+
ramin=0,
|
|
338
|
+
ramax=2 * np.pi,
|
|
339
|
+
decmin=-np.pi,
|
|
340
|
+
decmax=0,
|
|
341
|
+
random=55,
|
|
342
|
+
)
|
|
343
|
+
# Replace ra/dec to make them close to healpix points
|
|
344
|
+
hpix = np.arange(0, hp.nside2npix(self.nside))
|
|
345
|
+
ra, dec = hp.pix2ang(nside=self.nside, ipix=hpix, lonlat=True)
|
|
346
|
+
rng = np.random.RandomState(1147)
|
|
347
|
+
rr = rng.rand(nvalues) * 1.5
|
|
348
|
+
ra = (ra[:, np.newaxis] + rr).reshape(len(ra) * len(rr))
|
|
349
|
+
dec = (dec[:, np.newaxis] + rr).reshape(len(dec) * len(rr))
|
|
350
|
+
self.dv["ra"] = np.radians(ra)
|
|
351
|
+
self.dv["dec"] = np.radians(dec)
|
|
352
|
+
|
|
353
|
+
def tearDown(self):
|
|
354
|
+
del self.testslicer
|
|
355
|
+
self.testslicer = None
|
|
356
|
+
del self.testsmallslicer
|
|
357
|
+
self.testsmallslicer = None
|
|
358
|
+
|
|
359
|
+
def test_slicing(self):
|
|
360
|
+
"""Test slicing returns (most) data points which are
|
|
361
|
+
within 'radius' of bin point or camera_radius for small slicer"""
|
|
362
|
+
# Test that slicing fails before setup_slicer
|
|
363
|
+
self.assertRaises(NotImplementedError, self.testslicer._slice_sim_data, 0)
|
|
364
|
+
# Set up and test actual slicing.
|
|
365
|
+
self.testslicer.setup_slicer(self.dv)
|
|
366
|
+
self.testsmallslicer.setup_slicer(self.dv)
|
|
367
|
+
for s, ss in zip(self.testslicer, self.testsmallslicer):
|
|
368
|
+
ra = s["slice_point"]["ra"]
|
|
369
|
+
dec = s["slice_point"]["dec"]
|
|
370
|
+
# Find the points of 'dv' which are within self.radius of
|
|
371
|
+
# this slice_point
|
|
372
|
+
distances = calc_dist_vincenty(ra, dec, self.dv["ra"], self.dv["dec"])
|
|
373
|
+
didxs = np.where(distances <= np.radians(self.radius))
|
|
374
|
+
# find the indexes of dv which the slicer says are in the
|
|
375
|
+
# camera footprint
|
|
376
|
+
sidxs = s["idxs"]
|
|
377
|
+
self.assertLessEqual(len(sidxs), len(didxs[0]))
|
|
378
|
+
if len(sidxs) > 0:
|
|
379
|
+
for indx in sidxs:
|
|
380
|
+
self.assertIn(self.dv["testdata"][indx], self.dv["testdata"][didxs])
|
|
381
|
+
# find the indexes of dv which the slicer says are in the
|
|
382
|
+
# camera footprint
|
|
383
|
+
sidxs = ss["idxs"]
|
|
384
|
+
self.assertLessEqual(len(sidxs), len(didxs[0]))
|
|
385
|
+
if len(sidxs) > 0:
|
|
386
|
+
for indx in sidxs:
|
|
387
|
+
self.assertIn(self.dv["testdata"][indx], self.dv["testdata"][didxs])
|
|
388
|
+
self.assertLess(len(ss["idxs"]), len(s["idxs"]))
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
class TestHealpixSlicerPlotting(unittest.TestCase):
|
|
392
|
+
def setUp(self):
|
|
393
|
+
rng = np.random.RandomState(713244122)
|
|
394
|
+
self.nside = 16
|
|
395
|
+
self.radius = 1.8
|
|
396
|
+
self.testslicer = HealpixSlicer(
|
|
397
|
+
nside=self.nside,
|
|
398
|
+
verbose=False,
|
|
399
|
+
lat_lon_deg=False,
|
|
400
|
+
lon_col="ra",
|
|
401
|
+
lat_col="dec",
|
|
402
|
+
radius=self.radius,
|
|
403
|
+
)
|
|
404
|
+
nvalues = 10000
|
|
405
|
+
self.dv = make_data_values(
|
|
406
|
+
size=nvalues,
|
|
407
|
+
minval=0.0,
|
|
408
|
+
maxval=1.0,
|
|
409
|
+
ramin=0,
|
|
410
|
+
ramax=2 * np.pi,
|
|
411
|
+
decmin=-np.pi,
|
|
412
|
+
decmax=0,
|
|
413
|
+
random=66,
|
|
414
|
+
)
|
|
415
|
+
self.testslicer.setup_slicer(self.dv)
|
|
416
|
+
self.metricdata = ma.MaskedArray(
|
|
417
|
+
data=np.zeros(len(self.testslicer), dtype="float"),
|
|
418
|
+
mask=np.zeros(len(self.testslicer), "bool"),
|
|
419
|
+
fill_value=self.testslicer.badval,
|
|
420
|
+
)
|
|
421
|
+
for i, b in enumerate(self.testslicer):
|
|
422
|
+
idxs = b["idxs"]
|
|
423
|
+
if len(idxs) > 0:
|
|
424
|
+
self.metricdata.data[i] = np.mean(self.dv["testdata"][idxs])
|
|
425
|
+
else:
|
|
426
|
+
self.metricdata.mask[i] = True
|
|
427
|
+
self.metricdata2 = ma.MaskedArray(
|
|
428
|
+
data=rng.rand(len(self.testslicer)),
|
|
429
|
+
mask=np.zeros(len(self.testslicer), "bool"),
|
|
430
|
+
fill_value=self.testslicer.badval,
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
def tearDown(self):
|
|
434
|
+
del self.testslicer
|
|
435
|
+
self.testslicer = None
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
if __name__ == "__main__":
|
|
439
|
+
unittest.main()
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
import healpy as hp
|
|
4
|
+
import numpy as np
|
|
5
|
+
import numpy.lib.recfunctions as rfn
|
|
6
|
+
|
|
7
|
+
from rubin_sim.maf.slicers import HealpixSubsetSlicer
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def make_data_values(
|
|
11
|
+
size=100,
|
|
12
|
+
minval=0.0,
|
|
13
|
+
maxval=1.0,
|
|
14
|
+
ramin=0,
|
|
15
|
+
ramax=2 * np.pi,
|
|
16
|
+
decmin=-np.pi,
|
|
17
|
+
decmax=np.pi,
|
|
18
|
+
random=1172,
|
|
19
|
+
):
|
|
20
|
+
"""Generate a simple array of numbers, evenly arranged between min/max,
|
|
21
|
+
in 1 dimensions (optionally sorted), together with RA/Dec values
|
|
22
|
+
for each data value."""
|
|
23
|
+
data = []
|
|
24
|
+
# Generate data values min - max.
|
|
25
|
+
datavalues = np.arange(0, size, dtype="float")
|
|
26
|
+
datavalues *= (float(maxval) - float(minval)) / (datavalues.max() - datavalues.min())
|
|
27
|
+
datavalues += minval
|
|
28
|
+
rng = np.random.RandomState(random)
|
|
29
|
+
randorder = rng.rand(size)
|
|
30
|
+
randind = np.argsort(randorder)
|
|
31
|
+
datavalues = datavalues[randind]
|
|
32
|
+
datavalues = np.array(list(zip(datavalues)), dtype=[("testdata", "float")])
|
|
33
|
+
data.append(datavalues)
|
|
34
|
+
# Generate RA/Dec values equally spaces on sphere between ramin/max,
|
|
35
|
+
# decmin/max.
|
|
36
|
+
ra = np.arange(0, size, dtype="float")
|
|
37
|
+
ra *= (float(ramax) - float(ramin)) / (ra.max() - ra.min())
|
|
38
|
+
randorder = rng.rand(size)
|
|
39
|
+
randind = np.argsort(randorder)
|
|
40
|
+
ra = ra[randind]
|
|
41
|
+
ra = np.array(list(zip(ra)), dtype=[("ra", "float")])
|
|
42
|
+
data.append(ra)
|
|
43
|
+
v = np.arange(0, size, dtype="float")
|
|
44
|
+
v *= ((np.cos(decmax + np.pi) + 1.0) / 2.0 - (np.cos(decmin + np.pi) + 1.0) / 2.0) / (v.max() - v.min())
|
|
45
|
+
v += (np.cos(decmin + np.pi) + 1.0) / 2.0
|
|
46
|
+
dec = np.arccos(2 * v - 1) - np.pi
|
|
47
|
+
randorder = rng.rand(size)
|
|
48
|
+
randind = np.argsort(randorder)
|
|
49
|
+
dec = dec[randind]
|
|
50
|
+
dec = np.array(list(zip(dec)), dtype=[("dec", "float")])
|
|
51
|
+
data.append(dec)
|
|
52
|
+
# Add in rotation angle
|
|
53
|
+
rot = rng.rand(len(dec)) * 2 * np.pi
|
|
54
|
+
data.append(np.array(rot, dtype=[("rotSkyPos", "float")]))
|
|
55
|
+
mjd = np.arange(len(dec)) * 0.1
|
|
56
|
+
data.append(np.array(mjd, dtype=[("observationStartMJD", "float")]))
|
|
57
|
+
data = rfn.merge_arrays(data, flatten=True, usemask=False)
|
|
58
|
+
return data
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def calc_dist_vincenty(ra1, dec1, ra2, dec2):
|
|
62
|
+
"""Calculates distance on a sphere using the Vincenty formula.
|
|
63
|
+
Give this function RA/Dec values in radians.
|
|
64
|
+
Returns angular distance(s), in radians.
|
|
65
|
+
Note that since this is all numpy, you could input arrays of RA/Decs.
|
|
66
|
+
"""
|
|
67
|
+
d1 = (np.cos(dec2) * np.sin(ra2 - ra1)) ** 2 + (
|
|
68
|
+
np.cos(dec1) * np.sin(dec2) - np.sin(dec1) * np.cos(dec2) * np.cos(ra2 - ra1)
|
|
69
|
+
) ** 2
|
|
70
|
+
d1 = np.sqrt(d1)
|
|
71
|
+
d2 = np.sin(dec1) * np.sin(dec2) + np.cos(dec1) * np.cos(dec2) * np.cos(ra2 - ra1)
|
|
72
|
+
D = np.arctan2(d1, d2)
|
|
73
|
+
return D
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class TestHealpixSubsetSlicerSetup(unittest.TestCase):
|
|
77
|
+
def setUp(self):
|
|
78
|
+
self.nside = 16
|
|
79
|
+
idxs = np.arange(0, hp.nside2npix(self.nside))
|
|
80
|
+
self.idxs = idxs[np.where(idxs < idxs.max() / 2)]
|
|
81
|
+
|
|
82
|
+
def test_slicertype(self):
|
|
83
|
+
"""Test instantiation of slicer sets slicer type as expected."""
|
|
84
|
+
testslicer = HealpixSubsetSlicer(
|
|
85
|
+
nside=self.nside,
|
|
86
|
+
hpid=self.idxs,
|
|
87
|
+
verbose=False,
|
|
88
|
+
)
|
|
89
|
+
self.assertEqual(testslicer.slicer_name, testslicer.__class__.__name__)
|
|
90
|
+
self.assertEqual(testslicer.slicer_name, "HealpixSubsetSlicer")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TestHealpixSlicerEqual(unittest.TestCase):
|
|
94
|
+
def setUp(self):
|
|
95
|
+
self.nside = 16
|
|
96
|
+
self.testslicer = HealpixSubsetSlicer(
|
|
97
|
+
nside=self.nside,
|
|
98
|
+
hpid=np.arange(0, 10),
|
|
99
|
+
verbose=False,
|
|
100
|
+
lon_col="ra",
|
|
101
|
+
lat_col="dec",
|
|
102
|
+
)
|
|
103
|
+
nvalues = 10000
|
|
104
|
+
self.dv = make_data_values(
|
|
105
|
+
size=nvalues,
|
|
106
|
+
minval=0.0,
|
|
107
|
+
maxval=1.0,
|
|
108
|
+
ramin=0,
|
|
109
|
+
ramax=2 * np.pi,
|
|
110
|
+
decmin=-np.pi,
|
|
111
|
+
decmax=0,
|
|
112
|
+
random=22,
|
|
113
|
+
)
|
|
114
|
+
self.testslicer.setup_slicer(self.dv)
|
|
115
|
+
|
|
116
|
+
def tearDown(self):
|
|
117
|
+
del self.testslicer
|
|
118
|
+
del self.dv
|
|
119
|
+
self.testslicer = None
|
|
120
|
+
|
|
121
|
+
def test_slicer_equivalence(self):
|
|
122
|
+
"""Test that slicers are marked equal when appropriate,
|
|
123
|
+
and unequal when appropriate.
|
|
124
|
+
"""
|
|
125
|
+
# Note that they are judged equal based on nsides
|
|
126
|
+
# (not on data in ra/dec spatial tree).
|
|
127
|
+
testslicer2 = HealpixSubsetSlicer(
|
|
128
|
+
nside=self.nside,
|
|
129
|
+
hpid=np.arange(0, 10),
|
|
130
|
+
verbose=False,
|
|
131
|
+
lon_col="ra",
|
|
132
|
+
lat_col="dec",
|
|
133
|
+
)
|
|
134
|
+
self.assertEqual(self.testslicer, testslicer2)
|
|
135
|
+
assert (self.testslicer != testslicer2) is False
|
|
136
|
+
testslicer2 = HealpixSubsetSlicer(
|
|
137
|
+
nside=self.nside,
|
|
138
|
+
hpid=np.arange(10, 20),
|
|
139
|
+
verbose=False,
|
|
140
|
+
lon_col="ra",
|
|
141
|
+
lat_col="dec",
|
|
142
|
+
)
|
|
143
|
+
self.assertNotEqual(self.testslicer, testslicer2)
|
|
144
|
+
assert (self.testslicer != testslicer2) is True
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class TestHealpixSlicerIteration(unittest.TestCase):
|
|
148
|
+
def setUp(self):
|
|
149
|
+
self.nside = 8
|
|
150
|
+
self.hpid = np.arange(10, 20)
|
|
151
|
+
self.testslicer = HealpixSubsetSlicer(
|
|
152
|
+
nside=self.nside,
|
|
153
|
+
hpid=self.hpid,
|
|
154
|
+
verbose=False,
|
|
155
|
+
lon_col="ra",
|
|
156
|
+
lat_col="dec",
|
|
157
|
+
)
|
|
158
|
+
nvalues = 10000
|
|
159
|
+
self.dv = make_data_values(
|
|
160
|
+
size=nvalues,
|
|
161
|
+
minval=0.0,
|
|
162
|
+
maxval=1.0,
|
|
163
|
+
ramin=0,
|
|
164
|
+
ramax=2 * np.pi,
|
|
165
|
+
decmin=-np.pi,
|
|
166
|
+
decmax=0,
|
|
167
|
+
random=33,
|
|
168
|
+
)
|
|
169
|
+
self.testslicer.setup_slicer(self.dv)
|
|
170
|
+
|
|
171
|
+
def tearDown(self):
|
|
172
|
+
del self.testslicer
|
|
173
|
+
self.testslicer = None
|
|
174
|
+
|
|
175
|
+
def test_iteration(self):
|
|
176
|
+
"""Test iteration goes through expected range and ra/dec
|
|
177
|
+
are in expected range (radians).
|
|
178
|
+
"""
|
|
179
|
+
for i, s in enumerate(self.testslicer):
|
|
180
|
+
# We do not expect testslicer.slice_point['sid'] to == i ..
|
|
181
|
+
# The slicer will only iterate over the subset
|
|
182
|
+
self.assertEqual(self.hpid[i], s["slice_point"]["sid"])
|
|
183
|
+
ra = s["slice_point"]["ra"]
|
|
184
|
+
dec = s["slice_point"]["dec"]
|
|
185
|
+
self.assertGreaterEqual(ra, 0)
|
|
186
|
+
self.assertLessEqual(ra, 2 * np.pi)
|
|
187
|
+
self.assertGreaterEqual(dec, -np.pi)
|
|
188
|
+
self.assertLessEqual(dec, np.pi)
|
|
189
|
+
self.assertEqual(i + 1, len(self.hpid))
|
|
190
|
+
|
|
191
|
+
def test_get_item(self):
|
|
192
|
+
"""Test getting indexed value."""
|
|
193
|
+
for i, s in enumerate(self.testslicer):
|
|
194
|
+
np.testing.assert_equal(self.testslicer[self.hpid[i]], s)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class TestHealpixSlicerSlicing(unittest.TestCase):
|
|
198
|
+
# Note that this is really testing baseSpatialSlicer,
|
|
199
|
+
# as slicing is done there for healpix grid
|
|
200
|
+
|
|
201
|
+
def setUp(self):
|
|
202
|
+
self.nside = 8
|
|
203
|
+
self.radius = 1.8
|
|
204
|
+
self.testslicer = HealpixSubsetSlicer(
|
|
205
|
+
nside=self.nside,
|
|
206
|
+
hpid=np.arange(0, hp.nside2npix(self.nside)),
|
|
207
|
+
verbose=False,
|
|
208
|
+
lon_col="ra",
|
|
209
|
+
lat_col="dec",
|
|
210
|
+
lat_lon_deg=False,
|
|
211
|
+
radius=self.radius,
|
|
212
|
+
use_camera=False,
|
|
213
|
+
)
|
|
214
|
+
nvalues = 10000
|
|
215
|
+
self.dv = make_data_values(
|
|
216
|
+
size=nvalues,
|
|
217
|
+
minval=0.0,
|
|
218
|
+
maxval=1.0,
|
|
219
|
+
ramin=0,
|
|
220
|
+
ramax=2 * np.pi,
|
|
221
|
+
decmin=-np.pi,
|
|
222
|
+
decmax=0,
|
|
223
|
+
random=44,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def tearDown(self):
|
|
227
|
+
del self.testslicer
|
|
228
|
+
self.testslicer = None
|
|
229
|
+
|
|
230
|
+
def test_slicing(self):
|
|
231
|
+
"""Test slicing returns (all) data points which are within
|
|
232
|
+
'radius' of bin point."""
|
|
233
|
+
# Test that slicing fails before setup_slicer
|
|
234
|
+
self.assertRaises(NotImplementedError, self.testslicer._slice_sim_data, 0)
|
|
235
|
+
# Set up and test actual slicing.
|
|
236
|
+
self.testslicer.setup_slicer(self.dv)
|
|
237
|
+
for s in self.testslicer:
|
|
238
|
+
ra = s["slice_point"]["ra"]
|
|
239
|
+
dec = s["slice_point"]["dec"]
|
|
240
|
+
distances = calc_dist_vincenty(ra, dec, self.dv["ra"], self.dv["dec"])
|
|
241
|
+
didxs = np.where(distances <= np.radians(self.radius))
|
|
242
|
+
sidxs = s["idxs"]
|
|
243
|
+
self.assertEqual(len(sidxs), len(didxs[0]))
|
|
244
|
+
if len(sidxs) > 0:
|
|
245
|
+
didxs = np.sort(didxs[0])
|
|
246
|
+
sidxs = np.sort(sidxs)
|
|
247
|
+
np.testing.assert_equal(self.dv["testdata"][didxs], self.dv["testdata"][sidxs])
|
|
248
|
+
|
|
249
|
+
def test_subset_slice(self):
|
|
250
|
+
testslicer = HealpixSubsetSlicer(
|
|
251
|
+
nside=self.nside,
|
|
252
|
+
hpid=np.arange(0, 2),
|
|
253
|
+
verbose=False,
|
|
254
|
+
lon_col="ra",
|
|
255
|
+
lat_col="dec",
|
|
256
|
+
lat_lon_deg=False,
|
|
257
|
+
radius=self.radius,
|
|
258
|
+
use_camera=False,
|
|
259
|
+
)
|
|
260
|
+
testslicer.setup_slicer(self.dv)
|
|
261
|
+
self.testslicer.setup_slicer(self.dv)
|
|
262
|
+
# For points which return values when used with the full set
|
|
263
|
+
# of points (self.testslicer)
|
|
264
|
+
# there will be no data when used with the subset of points
|
|
265
|
+
for s in self.testslicer:
|
|
266
|
+
if s["slice_point"]["sid"] > 2:
|
|
267
|
+
if len(s["idxs"]) > 0:
|
|
268
|
+
islice = s["slice_point"]["sid"]
|
|
269
|
+
self.assertTrue(len(testslicer[islice]["idxs"]) == 0)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
if __name__ == "__main__":
|
|
273
|
+
unittest.main()
|