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,118 @@
|
|
|
1
|
+
__all__ = ("AgnTimeLagMetric",)
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from rubin_sim.phot_utils import DustValues
|
|
6
|
+
|
|
7
|
+
from .base_metric import BaseMetric
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AgnTimeLagMetric(BaseMetric):
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
lag=100,
|
|
14
|
+
z=1,
|
|
15
|
+
log=False,
|
|
16
|
+
threshold=2.2,
|
|
17
|
+
calc_type="mean",
|
|
18
|
+
mjd_col="observationStartMJD",
|
|
19
|
+
filter_col="band",
|
|
20
|
+
m5_col="fiveSigmaDepth",
|
|
21
|
+
dust=True,
|
|
22
|
+
g_cutoff=22.0,
|
|
23
|
+
r_cutoff=21.8,
|
|
24
|
+
metric_name=None,
|
|
25
|
+
**kwargs,
|
|
26
|
+
):
|
|
27
|
+
self.lag = lag
|
|
28
|
+
self.z = z
|
|
29
|
+
self.log = log
|
|
30
|
+
self.threshold = threshold
|
|
31
|
+
self.calc_type = calc_type
|
|
32
|
+
self.mjd_col = mjd_col
|
|
33
|
+
self.filter_col = filter_col
|
|
34
|
+
self.m5_col = m5_col
|
|
35
|
+
if metric_name is None:
|
|
36
|
+
metric_name = f"AGN_TimeLag_{lag}_days"
|
|
37
|
+
self.dust = dust
|
|
38
|
+
self.g_cutoff = g_cutoff
|
|
39
|
+
self.r_cutoff = r_cutoff
|
|
40
|
+
if dust:
|
|
41
|
+
maps = ["DustMap"]
|
|
42
|
+
dust_properties = DustValues()
|
|
43
|
+
self.ax1 = dust_properties.ax1
|
|
44
|
+
else:
|
|
45
|
+
maps = []
|
|
46
|
+
super().__init__(
|
|
47
|
+
col=[self.mjd_col, self.filter_col, self.m5_col],
|
|
48
|
+
metric_name=metric_name,
|
|
49
|
+
maps=maps,
|
|
50
|
+
**kwargs,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Calculate NQUIST value for time-lag and sampling time
|
|
54
|
+
# (redshift is included in formula if desired)
|
|
55
|
+
def _get_nquist_value(self, caden, lag, z):
|
|
56
|
+
return lag / ((1 + z) * caden)
|
|
57
|
+
|
|
58
|
+
def run(self, data_slice, slice_point=None):
|
|
59
|
+
# Dust extinction
|
|
60
|
+
filterlist = np.unique(data_slice[self.filter_col])
|
|
61
|
+
if self.dust:
|
|
62
|
+
m5 = np.zeros(len(data_slice))
|
|
63
|
+
for filtername in filterlist:
|
|
64
|
+
in_filt = np.where(data_slice[self.filter_col] == filtername)[0]
|
|
65
|
+
a_x = self.ax1[data_slice[self.filter_col][0]] * slice_point["ebv"]
|
|
66
|
+
m5[in_filt] = data_slice[self.m5_col][in_filt] - a_x
|
|
67
|
+
else:
|
|
68
|
+
m5 = data_slice[self.m5_col]
|
|
69
|
+
|
|
70
|
+
# Identify times which pass magnitude cuts (chosen by AGN contributors)
|
|
71
|
+
mjds = np.zeros(len(data_slice))
|
|
72
|
+
for filtername in filterlist:
|
|
73
|
+
in_filt = np.where(data_slice[self.filter_col] == filtername)[0]
|
|
74
|
+
if filtername in ("u", "i", "z", "y", "r", "g"):
|
|
75
|
+
mjds[in_filt] = data_slice[self.mjd_col][in_filt]
|
|
76
|
+
elif filtername == "g":
|
|
77
|
+
faint = np.where(m5[in_filt] > self.g_cutoff)
|
|
78
|
+
mjds[in_filt][faint] = data_slice[self.mjd_col][in_filt][faint]
|
|
79
|
+
elif filtername == "r":
|
|
80
|
+
faint = np.where(m5[in_filt] > self.r_cutoff)
|
|
81
|
+
mjds[in_filt][faint] = data_slice[self.mjd_col][in_filt][faint]
|
|
82
|
+
# Remove the visits which were not faint enough
|
|
83
|
+
mjds = mjds[np.where(mjds > 0)]
|
|
84
|
+
|
|
85
|
+
# Calculate differences in time between visits
|
|
86
|
+
mv = np.sort(mjds)
|
|
87
|
+
val = np.diff(mv)
|
|
88
|
+
# If there was only one visit; bail out now.
|
|
89
|
+
if len(val) == 0:
|
|
90
|
+
return self.badval
|
|
91
|
+
|
|
92
|
+
# Otherwise summarize the time differences as:
|
|
93
|
+
if self.calc_type == "mean":
|
|
94
|
+
val = np.mean(val)
|
|
95
|
+
elif self.calc_type == "min":
|
|
96
|
+
val = np.min(val)
|
|
97
|
+
elif self.calc_type == "max":
|
|
98
|
+
val = np.max(val)
|
|
99
|
+
else:
|
|
100
|
+
# find the greatest common divisor
|
|
101
|
+
val = np.rint(val).astype(int)
|
|
102
|
+
val = np.gcd.reduce(val)
|
|
103
|
+
|
|
104
|
+
# Will always have a value at this point
|
|
105
|
+
nquist = self._get_nquist_value(val, self.lag, self.z)
|
|
106
|
+
if self.log:
|
|
107
|
+
nquist = np.log(nquist)
|
|
108
|
+
|
|
109
|
+
# Threshold nquist value is 2.2,
|
|
110
|
+
# hence we are aiming to show values higher than threshold (2.2) value
|
|
111
|
+
threshold = self.threshold
|
|
112
|
+
if self.log:
|
|
113
|
+
threshold = np.log(threshold)
|
|
114
|
+
|
|
115
|
+
if nquist < threshold:
|
|
116
|
+
nquist = self.badval
|
|
117
|
+
|
|
118
|
+
return nquist
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
__all__ = ("SFUncertMetric",)
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from astropy.stats import mad_std
|
|
7
|
+
|
|
8
|
+
from rubin_sim.maf.utils import m52snr
|
|
9
|
+
from rubin_sim.phot_utils import DustValues
|
|
10
|
+
|
|
11
|
+
from .base_metric import BaseMetric
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SFUncertMetric(BaseMetric):
|
|
15
|
+
"""Structure Function (SF) Uncertainty Metric.
|
|
16
|
+
Developed on top of LogTGaps
|
|
17
|
+
|
|
18
|
+
Adapted from Weixiang Yu & Gordon Richards at:
|
|
19
|
+
https://github.com/RichardsGroup/
|
|
20
|
+
LSST_SF_Metric/blob/main/notebooks/00_SFErrorMetric.ipynb
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
mag : `float`
|
|
25
|
+
The magnitude of the fiducial object. Default 22.
|
|
26
|
+
times_col : `str`
|
|
27
|
+
Time column name. Defaults to "observationStartMJD".
|
|
28
|
+
all_gaps : `bool`
|
|
29
|
+
Whether to use all gaps (between any two pairs of observations).
|
|
30
|
+
If False, only use consecutive paris. Defaults to True.
|
|
31
|
+
units : `str`
|
|
32
|
+
Unit of this metric. Defaults to "mag".
|
|
33
|
+
bins : `object`
|
|
34
|
+
An array of bin edges.
|
|
35
|
+
Defaults to "np.logspace(0, np.log10(3650), 16)" for a
|
|
36
|
+
total of 15 (final) bins.
|
|
37
|
+
weight : `object`
|
|
38
|
+
The weight assigned to each delta_t bin for deriving the final metric.
|
|
39
|
+
Defaults to flat weighting with sum of 1.
|
|
40
|
+
Should have length 1 less than bins.
|
|
41
|
+
snr_cut : `float`
|
|
42
|
+
Ignore observations below an SNR limit, default 5.
|
|
43
|
+
dust : `bool`
|
|
44
|
+
Apply dust extinction to the fiducial object magnitude. Default True.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
mag=22,
|
|
50
|
+
times_col="observationStartMJD",
|
|
51
|
+
m5_col="fiveSigmaDepth",
|
|
52
|
+
all_gaps=True,
|
|
53
|
+
units="mag",
|
|
54
|
+
bins=np.logspace(0, np.log10(3650), 16),
|
|
55
|
+
weight=None,
|
|
56
|
+
metric_name="Structure Function Uncert",
|
|
57
|
+
snr_cut=5,
|
|
58
|
+
filter_col="band",
|
|
59
|
+
dust=True,
|
|
60
|
+
**kwargs,
|
|
61
|
+
):
|
|
62
|
+
# Assign metric parameters to instance object
|
|
63
|
+
self.times_col = times_col
|
|
64
|
+
self.m5_col = m5_col
|
|
65
|
+
self.filter_col = filter_col
|
|
66
|
+
self.all_gaps = all_gaps
|
|
67
|
+
self.bins = bins
|
|
68
|
+
if weight is None:
|
|
69
|
+
# If weight is none, set weight so that sum over bins = 1
|
|
70
|
+
self.weight = np.ones(len(self.bins) - 1)
|
|
71
|
+
self.weight /= self.weight.sum()
|
|
72
|
+
self.metric_name = metric_name
|
|
73
|
+
self.mag = mag
|
|
74
|
+
self.snr_cut = snr_cut
|
|
75
|
+
self.dust = dust
|
|
76
|
+
|
|
77
|
+
maps = ["DustMap"]
|
|
78
|
+
super(SFUncertMetric, self).__init__(
|
|
79
|
+
col=[self.times_col, m5_col, filter_col],
|
|
80
|
+
metric_name=self.metric_name,
|
|
81
|
+
units=units,
|
|
82
|
+
maps=maps,
|
|
83
|
+
**kwargs,
|
|
84
|
+
)
|
|
85
|
+
dust_properties = DustValues()
|
|
86
|
+
self.ax1 = dust_properties.ax1
|
|
87
|
+
|
|
88
|
+
def run(self, data_slice, slice_point=None):
|
|
89
|
+
"""Code executed at each healpix pixel to compute the metric"""
|
|
90
|
+
|
|
91
|
+
df = np.unique(data_slice[self.filter_col])
|
|
92
|
+
if np.size(df) > 1:
|
|
93
|
+
msg = """Running structure function on multiple filters simultaneously.
|
|
94
|
+
Should probably change your SQL query to limit to a single filter."""
|
|
95
|
+
warnings.warn(msg)
|
|
96
|
+
if self.dust:
|
|
97
|
+
a_x = self.ax1[data_slice[self.filter_col][0]] * slice_point["ebv"]
|
|
98
|
+
extincted_mag = self.mag + a_x
|
|
99
|
+
else:
|
|
100
|
+
extincted_mag = self.mag
|
|
101
|
+
snr = m52snr(extincted_mag, data_slice[self.m5_col])
|
|
102
|
+
bright_enough = np.where(snr > self.snr_cut)[0]
|
|
103
|
+
|
|
104
|
+
# If the total number of visits < 2, mask as bad pixel
|
|
105
|
+
if data_slice[bright_enough].size < 2:
|
|
106
|
+
return self.badval
|
|
107
|
+
|
|
108
|
+
# sort data by time column
|
|
109
|
+
order = np.argsort(data_slice[self.times_col][bright_enough])
|
|
110
|
+
times = data_slice[self.times_col][bright_enough][order]
|
|
111
|
+
# Using the simple Gaussian approximation for magnitude uncertainty.
|
|
112
|
+
mag_err = 2.5 * np.log10(1.0 + 1.0 / snr[bright_enough][order])
|
|
113
|
+
|
|
114
|
+
# check if use all gaps (between any pairs of observations)
|
|
115
|
+
if self.all_gaps:
|
|
116
|
+
# use the vectorized method
|
|
117
|
+
dt_matrix = times.reshape((1, times.size)) - times.reshape((times.size, 1))
|
|
118
|
+
dts = dt_matrix[dt_matrix > 0].flatten().astype(np.float16)
|
|
119
|
+
else:
|
|
120
|
+
dts = np.diff(times)
|
|
121
|
+
|
|
122
|
+
# bin delta_t using provided bins;
|
|
123
|
+
# if zero pair found at any delta_t bin,
|
|
124
|
+
# replace 0 with 0.01 to avoid the exploding 1/sqrt(n) term
|
|
125
|
+
# in this metric
|
|
126
|
+
result, bins = np.histogram(dts, self.bins)
|
|
127
|
+
new_result = np.where(result > 0, result, 0.01)
|
|
128
|
+
|
|
129
|
+
# compute photometric_error^2 population variance and population mean
|
|
130
|
+
# note that variance is replaced by median_absolute_deviate^2
|
|
131
|
+
# mean is replaced by median in this implementation to make it robust
|
|
132
|
+
# to outliers in simulations (e.g., dcr simulations)
|
|
133
|
+
err_var = mag_err**2
|
|
134
|
+
err_var_mu = np.median(err_var)
|
|
135
|
+
err_var_std = mad_std(err_var)
|
|
136
|
+
|
|
137
|
+
# compute SF error
|
|
138
|
+
sf_var_dt = 2 * (err_var_mu + err_var_std / np.sqrt(new_result))
|
|
139
|
+
sf_var_metric = np.sum(sf_var_dt * self.weight)
|
|
140
|
+
|
|
141
|
+
return sf_var_metric
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
__all__ = ("AreaSummaryMetric", "AreaThresholdMetric")
|
|
2
|
+
|
|
3
|
+
import healpy as hp
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from .base_metric import BaseMetric
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AreaSummaryMetric(BaseMetric):
|
|
10
|
+
"""
|
|
11
|
+
Find the min/max of a value over the area with the 'best' results
|
|
12
|
+
in the metric.
|
|
13
|
+
This is a handy substitute for when users want to know "the WFD value".
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
area : `float`
|
|
18
|
+
The area to consider (sq degrees)
|
|
19
|
+
decreasing : `bool`
|
|
20
|
+
Should the values be sorted by increasing or decreasing order.
|
|
21
|
+
For values where "larger is better", decreasing (True) is probably
|
|
22
|
+
what you want. For metrics where "smaller is better"
|
|
23
|
+
(e.g., astrometric precission), set decreasing to False.
|
|
24
|
+
reduce_func : None
|
|
25
|
+
The function to reduce the clipped values by.
|
|
26
|
+
Will default to min/max depending on the bool val of the decreasing
|
|
27
|
+
kwarg.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
col="metricdata",
|
|
33
|
+
metric_name="AreaSummary",
|
|
34
|
+
area=18000.0,
|
|
35
|
+
decreasing=True,
|
|
36
|
+
reduce_func=None,
|
|
37
|
+
**kwargs,
|
|
38
|
+
):
|
|
39
|
+
super().__init__(col=col, metric_name=metric_name, **kwargs)
|
|
40
|
+
self.area = area
|
|
41
|
+
self.decreasing = decreasing
|
|
42
|
+
self.reduce_func = reduce_func
|
|
43
|
+
self.mask_val = np.nan # Include so all values get passed
|
|
44
|
+
self.col = col
|
|
45
|
+
if reduce_func is None:
|
|
46
|
+
if decreasing:
|
|
47
|
+
self.reduce_func = np.min
|
|
48
|
+
else:
|
|
49
|
+
self.reduce_func = np.max
|
|
50
|
+
else:
|
|
51
|
+
self.reduce_func = reduce_func
|
|
52
|
+
|
|
53
|
+
def run(self, data_slice, slice_point=None):
|
|
54
|
+
# find out what nside we have
|
|
55
|
+
nside = hp.npix2nside(data_slice[self.col].size)
|
|
56
|
+
pix_area = hp.nside2pixarea(nside, degrees=True)
|
|
57
|
+
n_pix_needed = int(np.ceil(self.area / pix_area))
|
|
58
|
+
|
|
59
|
+
# Only use the finite data
|
|
60
|
+
data = data_slice[self.col][np.isfinite(data_slice[self.col].astype(float))]
|
|
61
|
+
order = np.argsort(data)
|
|
62
|
+
if self.decreasing:
|
|
63
|
+
order = order[::-1]
|
|
64
|
+
result = self.reduce_func(data[order][0:n_pix_needed])
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class AreaThresholdMetric(BaseMetric):
|
|
69
|
+
"""Find the amount of area on the sky that meets a given threshold value.
|
|
70
|
+
|
|
71
|
+
The area per pixel is determined from the size of the metric_values
|
|
72
|
+
array passed to the summary metric.
|
|
73
|
+
This assumes that both all values are passed and that the metric was
|
|
74
|
+
calculated with a healpix slicer.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
upper_threshold : `float` or None
|
|
79
|
+
The metric value must be below this threshold to count toward the area.
|
|
80
|
+
Default None implies no upper bound.
|
|
81
|
+
lower_threshold : `float` or None, opt
|
|
82
|
+
The metric value must be above this threshold to count toward the area.
|
|
83
|
+
Default None implies no lower bound.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
col="metricdata",
|
|
89
|
+
metric_name="AreaThreshold",
|
|
90
|
+
upper_threshold=None,
|
|
91
|
+
lower_threshold=None,
|
|
92
|
+
**kwargs,
|
|
93
|
+
):
|
|
94
|
+
super().__init__(col=col, metric_name=metric_name, **kwargs)
|
|
95
|
+
self.upper_threshold = upper_threshold
|
|
96
|
+
self.lower_threshold = lower_threshold
|
|
97
|
+
self.mask_val = np.nan # Include so all values get passed
|
|
98
|
+
self.col = col
|
|
99
|
+
self.units = "square degrees"
|
|
100
|
+
|
|
101
|
+
def run(self, data_slice, slice_point=None):
|
|
102
|
+
# find out what nside we have
|
|
103
|
+
nside = hp.npix2nside(data_slice.size)
|
|
104
|
+
pix_area = hp.nside2pixarea(nside, degrees=True)
|
|
105
|
+
# Look for pixels which match the critera for the thresholds
|
|
106
|
+
if self.upper_threshold is None and self.lower_threshold is None:
|
|
107
|
+
npix = len(data_slice)
|
|
108
|
+
elif self.upper_threshold is None:
|
|
109
|
+
npix = len(np.where(data_slice[self.col] > self.lower_threshold)[0])
|
|
110
|
+
elif self.lower_threshold is None:
|
|
111
|
+
npix = len(np.where(data_slice[self.col] < self.upper_threshold)[0])
|
|
112
|
+
else:
|
|
113
|
+
npix = len(
|
|
114
|
+
np.where(
|
|
115
|
+
(data_slice[self.col] > self.lower_threshold)
|
|
116
|
+
& (data_slice[self.col] < self.upper_threshold)
|
|
117
|
+
)[0]
|
|
118
|
+
)
|
|
119
|
+
area = pix_area * npix
|
|
120
|
+
return area
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Base class for metrics - defines methods which must be implemented.
|
|
2
|
+
|
|
3
|
+
__all__ = ("MetricRegistry", "BaseMetric", "ColRegistry")
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
import warnings
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from rubin_sim.maf.stackers.get_col_info import ColInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MetricRegistry(type):
|
|
14
|
+
"""
|
|
15
|
+
Meta class for metrics, to build a registry of metric classes.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(cls, name, bases, dict):
|
|
19
|
+
super(MetricRegistry, cls).__init__(name, bases, dict)
|
|
20
|
+
if not hasattr(cls, "registry"):
|
|
21
|
+
cls.registry = {}
|
|
22
|
+
modname = inspect.getmodule(cls).__name__
|
|
23
|
+
if modname.startswith("rubin_sim.maf.metrics"):
|
|
24
|
+
modname = ""
|
|
25
|
+
else:
|
|
26
|
+
if len(modname.split(".")) > 1:
|
|
27
|
+
modname = ".".join(modname.split(".")[:-1]) + "."
|
|
28
|
+
else:
|
|
29
|
+
modname = modname + "."
|
|
30
|
+
metricname = modname + name
|
|
31
|
+
if metricname in cls.registry:
|
|
32
|
+
warnings.warn("Redefining metric %s! (there are >1 metrics with the same name)" % (metricname))
|
|
33
|
+
if metricname not in ["BaseMetric", "SimpleScalarMetric"]:
|
|
34
|
+
cls.registry[metricname] = cls
|
|
35
|
+
|
|
36
|
+
def get_class(cls, metricname):
|
|
37
|
+
return cls.registry[metricname]
|
|
38
|
+
|
|
39
|
+
def help(cls, doc=False):
|
|
40
|
+
for metricname in sorted(cls.registry):
|
|
41
|
+
if not doc:
|
|
42
|
+
print(metricname)
|
|
43
|
+
if doc:
|
|
44
|
+
print("---- ", metricname, " ----")
|
|
45
|
+
print(inspect.getdoc(cls.registry[metricname]))
|
|
46
|
+
|
|
47
|
+
def help_metric(cls, metricname):
|
|
48
|
+
print(metricname)
|
|
49
|
+
print(inspect.getdoc(cls.registry[metricname]))
|
|
50
|
+
k = inspect.signature(cls.registry[metricname])
|
|
51
|
+
print(" Metric __init__ keyword args and defaults: ")
|
|
52
|
+
print(k)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ColRegistry:
|
|
56
|
+
"""
|
|
57
|
+
ColRegistry tracks the columns needed for all metric objects
|
|
58
|
+
(kept internally in a set).
|
|
59
|
+
|
|
60
|
+
ColRegistry.col_set : a set of all unique columns required for metrics.
|
|
61
|
+
ColRegistry.dbCols : the subset of these which come from the database.
|
|
62
|
+
ColRegistry.stackerCols : the dictionary of [columns: stacker class].
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
col_info = ColInfo()
|
|
66
|
+
|
|
67
|
+
def __init__(self):
|
|
68
|
+
self.col_set = set()
|
|
69
|
+
self.db_set = set()
|
|
70
|
+
self.stacker_dict = {}
|
|
71
|
+
|
|
72
|
+
def clear_reg(self):
|
|
73
|
+
"""Clear the registry"""
|
|
74
|
+
self.__init__()
|
|
75
|
+
|
|
76
|
+
def add_cols(self, col_array):
|
|
77
|
+
"""Add the columns in ColArray into the ColRegistry.
|
|
78
|
+
|
|
79
|
+
Add the columns in col_array into the ColRegistry set (self.col_set)
|
|
80
|
+
and identifies their source, using ColInfo
|
|
81
|
+
(rubin_sim.maf.stackers.getColInfo).
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
col_array : `list`
|
|
86
|
+
list of columns used in a metric.
|
|
87
|
+
"""
|
|
88
|
+
for col in col_array:
|
|
89
|
+
if col is not None:
|
|
90
|
+
self.col_set.add(col)
|
|
91
|
+
source = self.col_info.get_data_source(col)
|
|
92
|
+
if source == self.col_info.default_data_source:
|
|
93
|
+
self.db_set.add(col)
|
|
94
|
+
else:
|
|
95
|
+
if col not in self.stacker_dict:
|
|
96
|
+
self.stacker_dict[col] = source
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class BaseMetric(metaclass=MetricRegistry):
|
|
100
|
+
"""
|
|
101
|
+
Base class for the metrics.
|
|
102
|
+
Sets up some basic functionality for the MAF framework:
|
|
103
|
+
after __init__ every metric will record the columns (and stackers)
|
|
104
|
+
it requires into the column registry, and the metric_name,
|
|
105
|
+
metric_dtype, and units for the metric will be set.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
col : `str` or `list` [`str`]
|
|
110
|
+
Names of the data columns that the metric will use.
|
|
111
|
+
The columns required for each metric is tracked in the ColRegistry,
|
|
112
|
+
and used to retrieve data from the opsim database.
|
|
113
|
+
Can be a single string or a list.
|
|
114
|
+
metric_name : `str`
|
|
115
|
+
Name to use for the metric (optional - if not set, will be derived).
|
|
116
|
+
maps : `list` [`rubin_sim.maf.maps`]
|
|
117
|
+
The maps that the metric will need (passed from the slicer).
|
|
118
|
+
units : `str`
|
|
119
|
+
The units for the value returned by the metric (optional - if not set,
|
|
120
|
+
will be derived from the ColInfo).
|
|
121
|
+
metric_dtype : `str`
|
|
122
|
+
The type of value returned by the metric - 'int', 'float', 'object'.
|
|
123
|
+
If not set, will be derived by introspection.
|
|
124
|
+
badval : `float`
|
|
125
|
+
The value indicating "bad" values calculated by the metric.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
col_registry = ColRegistry()
|
|
129
|
+
col_info = ColInfo()
|
|
130
|
+
|
|
131
|
+
def __init__(
|
|
132
|
+
self,
|
|
133
|
+
col=None,
|
|
134
|
+
metric_name=None,
|
|
135
|
+
maps=None,
|
|
136
|
+
units=None,
|
|
137
|
+
metric_dtype=None,
|
|
138
|
+
badval=-666,
|
|
139
|
+
mask_val=None,
|
|
140
|
+
):
|
|
141
|
+
# Turn cols into numpy array so we know
|
|
142
|
+
# we can iterate over the columns.
|
|
143
|
+
self.col_name_arr = np.array(col, copy=True, ndmin=1)
|
|
144
|
+
# To support simple metrics operating on a single column,
|
|
145
|
+
# set self.colname
|
|
146
|
+
if len(self.col_name_arr) == 1:
|
|
147
|
+
self.colname = self.col_name_arr[0]
|
|
148
|
+
# Add the columns to the colRegistry.
|
|
149
|
+
self.col_registry.add_cols(self.col_name_arr)
|
|
150
|
+
# Set the maps that are needed:
|
|
151
|
+
if maps is None:
|
|
152
|
+
maps = []
|
|
153
|
+
self.maps = maps
|
|
154
|
+
# Value to return if the metric can't be computed
|
|
155
|
+
self.badval = badval
|
|
156
|
+
if mask_val is not None:
|
|
157
|
+
self.mask_val = mask_val
|
|
158
|
+
# Save a unique name for the metric.
|
|
159
|
+
self.name = metric_name
|
|
160
|
+
if self.name is None:
|
|
161
|
+
# If none provided, construct our own from the class name
|
|
162
|
+
# and the data columns.
|
|
163
|
+
self.name = (
|
|
164
|
+
self.__class__.__name__.replace("Metric", "", 1)
|
|
165
|
+
+ " "
|
|
166
|
+
+ ", ".join(map(str, self.col_name_arr))
|
|
167
|
+
)
|
|
168
|
+
# Set up dictionary of reduce functions (may be empty).
|
|
169
|
+
self.reduce_funcs = {}
|
|
170
|
+
self.reduce_order = {}
|
|
171
|
+
for i, r in enumerate(inspect.getmembers(self, predicate=inspect.ismethod)):
|
|
172
|
+
if r[0].startswith("reduce"):
|
|
173
|
+
# Remove the "reduce_" part of the reduce functions names.
|
|
174
|
+
reducename = r[0].replace("reduce_", "", 1)
|
|
175
|
+
self.reduce_funcs[reducename] = r[1]
|
|
176
|
+
self.reduce_order[reducename] = i
|
|
177
|
+
# Identify type of metric return value.
|
|
178
|
+
if metric_dtype is not None:
|
|
179
|
+
self.metric_dtype = metric_dtype
|
|
180
|
+
elif len(list(self.reduce_funcs.keys())) > 0:
|
|
181
|
+
self.metric_dtype = "object"
|
|
182
|
+
else:
|
|
183
|
+
self.metric_dtype = "float"
|
|
184
|
+
# Set physical units, for plotting purposes.
|
|
185
|
+
if units is None:
|
|
186
|
+
units = " ".join([self.col_info.get_units(col_name) for col_name in self.col_name_arr])
|
|
187
|
+
if len(units.replace(" ", "")) == 0:
|
|
188
|
+
units = ""
|
|
189
|
+
self.units = units
|
|
190
|
+
# Add the ability to set a comment
|
|
191
|
+
# (that could be propagated automatically to a benchmark's
|
|
192
|
+
# display caption).
|
|
193
|
+
self.comment = None
|
|
194
|
+
|
|
195
|
+
# Default to only return one metric value per slice
|
|
196
|
+
self.shape = 1
|
|
197
|
+
|
|
198
|
+
def run(self, data_slice, slice_point):
|
|
199
|
+
"""Calculate metric values.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
data_slice : `numpy.ndarray`, (N,)
|
|
204
|
+
Values passed to metric by the slicer, which the metric will
|
|
205
|
+
use to calculate metric values at each slice_point.
|
|
206
|
+
slice_point : `dict` or None
|
|
207
|
+
Dictionary of slice_point metadata passed to each metric.
|
|
208
|
+
E.g. the ra/dec of the healpix pixel.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
metricValue : `int` `float` or `object`
|
|
213
|
+
The metric value at each slice_point.
|
|
214
|
+
"""
|
|
215
|
+
raise NotImplementedError("Please implement your metric calculation.")
|