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,268 @@
|
|
|
1
|
+
__all__ = ("TransientMetric",)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from .base_metric import BaseMetric
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TransientMetric(BaseMetric):
|
|
10
|
+
"""
|
|
11
|
+
Calculate what fraction of the transients would be detected. Best paired
|
|
12
|
+
with a spatial slicer.
|
|
13
|
+
We are assuming simple light curves with no color evolution.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
trans_duration : float, optional
|
|
18
|
+
How long the transient lasts (days). Default 10.
|
|
19
|
+
peak_time : float, optional
|
|
20
|
+
How long it takes to reach the peak magnitude (days). Default 5.
|
|
21
|
+
rise_slope : float, optional
|
|
22
|
+
Slope of the light curve before peak time (mags/day).
|
|
23
|
+
This should be negative since mags are backwards (magnitudes decrease
|
|
24
|
+
towards brighter fluxes).
|
|
25
|
+
Default 0.
|
|
26
|
+
decline_slope : float, optional
|
|
27
|
+
Slope of the light curve after peak time (mags/day).
|
|
28
|
+
This should be positive since mags are backwards. Default 0.
|
|
29
|
+
uPeak : float, optional
|
|
30
|
+
Peak magnitude in u band. Default 20.
|
|
31
|
+
gPeak : float, optional
|
|
32
|
+
Peak magnitude in g band. Default 20.
|
|
33
|
+
rPeak : float, optional
|
|
34
|
+
Peak magnitude in r band. Default 20.
|
|
35
|
+
iPeak : float, optional
|
|
36
|
+
Peak magnitude in i band. Default 20.
|
|
37
|
+
zPeak : float, optional
|
|
38
|
+
Peak magnitude in z band. Default 20.
|
|
39
|
+
yPeak : float, optional
|
|
40
|
+
Peak magnitude in y band. Default 20.
|
|
41
|
+
survey_duration : float, optional
|
|
42
|
+
Length of survey (years).
|
|
43
|
+
Default 10.
|
|
44
|
+
survey_start : float, optional
|
|
45
|
+
MJD for the survey start date.
|
|
46
|
+
Default None (uses the time of the first observation).
|
|
47
|
+
detect_m5_plus : float, optional
|
|
48
|
+
An observation will be used if the light curve magnitude is brighter
|
|
49
|
+
than m5+detect_m5_plus.
|
|
50
|
+
Default 0.
|
|
51
|
+
n_pre_peak : int, optional
|
|
52
|
+
Number of observations (in any filter(s)) to demand before peak_time,
|
|
53
|
+
before saying a transient has been detected.
|
|
54
|
+
Default 0.
|
|
55
|
+
n_per_lc : int, optional
|
|
56
|
+
Number of sections of the light curve that must be sampled above the
|
|
57
|
+
detect_m5_plus theshold
|
|
58
|
+
(in a single filter) for the light curve to be counted.
|
|
59
|
+
For example, setting n_per_lc = 2 means a light curve is only
|
|
60
|
+
considered detected if there is at least 1 observation in the first
|
|
61
|
+
half of the LC, and at least one in the second half of the LC.
|
|
62
|
+
n_per_lc = 4 means each quarter of the light curve must be detected to
|
|
63
|
+
count.
|
|
64
|
+
Default 1.
|
|
65
|
+
n_filters : int, optional
|
|
66
|
+
Number of filters that need to be observed for an object to be counted
|
|
67
|
+
as detected.
|
|
68
|
+
Default 1.
|
|
69
|
+
n_phase_check : int, optional
|
|
70
|
+
Sets the number of phases that should be checked.
|
|
71
|
+
One can imagine pathological cadences where many objects pass the
|
|
72
|
+
detection criteria,
|
|
73
|
+
but would not if the observations were offset by a phase-shift.
|
|
74
|
+
Default 1.
|
|
75
|
+
count_method : {'full' 'partialLC'}, defaults to 'full'
|
|
76
|
+
Sets the method of counting max number of transients. if 'full', the
|
|
77
|
+
only full light curves that fit the survey duration are counted. If
|
|
78
|
+
'partialLC', then the max number of possible transients is taken to be
|
|
79
|
+
the integer floor
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
metric_name="TransientDetectMetric",
|
|
85
|
+
mjd_col="observationStartMJD",
|
|
86
|
+
m5_col="fiveSigmaDepth",
|
|
87
|
+
filter_col="band",
|
|
88
|
+
trans_duration=10.0,
|
|
89
|
+
peak_time=5.0,
|
|
90
|
+
rise_slope=0.0,
|
|
91
|
+
decline_slope=0.0,
|
|
92
|
+
survey_duration=10.0,
|
|
93
|
+
survey_start=None,
|
|
94
|
+
detect_m5_plus=0.0,
|
|
95
|
+
u_peak=20,
|
|
96
|
+
g_peak=20,
|
|
97
|
+
r_peak=20,
|
|
98
|
+
i_peak=20,
|
|
99
|
+
z_peak=20,
|
|
100
|
+
y_peak=20,
|
|
101
|
+
n_pre_peak=0,
|
|
102
|
+
n_per_lc=1,
|
|
103
|
+
n_filters=1,
|
|
104
|
+
n_phase_check=1,
|
|
105
|
+
count_method="full",
|
|
106
|
+
**kwargs,
|
|
107
|
+
):
|
|
108
|
+
self.mjd_col = mjd_col
|
|
109
|
+
self.m5_col = m5_col
|
|
110
|
+
self.filter_col = filter_col
|
|
111
|
+
super(TransientMetric, self).__init__(
|
|
112
|
+
col=[self.mjd_col, self.m5_col, self.filter_col],
|
|
113
|
+
units="Fraction Detected",
|
|
114
|
+
metric_name=metric_name,
|
|
115
|
+
**kwargs,
|
|
116
|
+
)
|
|
117
|
+
self.peaks = {
|
|
118
|
+
"u": u_peak,
|
|
119
|
+
"g": g_peak,
|
|
120
|
+
"r": r_peak,
|
|
121
|
+
"i": i_peak,
|
|
122
|
+
"z": z_peak,
|
|
123
|
+
"y": y_peak,
|
|
124
|
+
}
|
|
125
|
+
self.trans_duration = trans_duration
|
|
126
|
+
self.peak_time = peak_time
|
|
127
|
+
self.rise_slope = rise_slope
|
|
128
|
+
self.decline_slope = decline_slope
|
|
129
|
+
self.survey_duration = survey_duration
|
|
130
|
+
self.survey_start = survey_start
|
|
131
|
+
self.detect_m5_plus = detect_m5_plus
|
|
132
|
+
self.n_pre_peak = n_pre_peak
|
|
133
|
+
self.n_per_lc = n_per_lc
|
|
134
|
+
self.n_filters = n_filters
|
|
135
|
+
self.n_phase_check = n_phase_check
|
|
136
|
+
self.count_method = count_method
|
|
137
|
+
|
|
138
|
+
def light_curve(self, time, filters):
|
|
139
|
+
"""
|
|
140
|
+
Calculate the magnitude of the object at each time, in each filter.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
time : numpy.ndarray
|
|
145
|
+
The times of the observations.
|
|
146
|
+
filters : numpy.ndarray
|
|
147
|
+
The filters of the observations.
|
|
148
|
+
|
|
149
|
+
Returns
|
|
150
|
+
-------
|
|
151
|
+
numpy.ndarray
|
|
152
|
+
The magnitudes of the object at each time, in each filter.
|
|
153
|
+
"""
|
|
154
|
+
lc_mags = np.zeros(time.size, dtype=float)
|
|
155
|
+
rise = np.where(time <= self.peak_time)
|
|
156
|
+
lc_mags[rise] += self.rise_slope * time[rise] - self.rise_slope * self.peak_time
|
|
157
|
+
decline = np.where(time > self.peak_time)
|
|
158
|
+
lc_mags[decline] += self.decline_slope * (time[decline] - self.peak_time)
|
|
159
|
+
for key in self.peaks:
|
|
160
|
+
f_match = np.where(filters == key)
|
|
161
|
+
lc_mags[f_match] += self.peaks[key]
|
|
162
|
+
return lc_mags
|
|
163
|
+
|
|
164
|
+
def run(self, data_slice, slice_point=None):
|
|
165
|
+
"""
|
|
166
|
+
Calculate the detectability of a transient with the specified
|
|
167
|
+
lightcurve.
|
|
168
|
+
|
|
169
|
+
Parameters
|
|
170
|
+
----------
|
|
171
|
+
data_slice : numpy.array
|
|
172
|
+
Numpy structured array containing the data related to the visits
|
|
173
|
+
provided by the slicer.
|
|
174
|
+
slice_point : dict, optional
|
|
175
|
+
Dictionary containing information about the slice_point currently
|
|
176
|
+
active in the slicer.
|
|
177
|
+
|
|
178
|
+
Returns
|
|
179
|
+
-------
|
|
180
|
+
float
|
|
181
|
+
The total number of transients that could be detected.
|
|
182
|
+
"""
|
|
183
|
+
# Total number of transients that could go off back-to-back
|
|
184
|
+
if self.count_method == "partialLC":
|
|
185
|
+
_n_trans_max = np.ceil(self.survey_duration / (self.trans_duration / 365.25))
|
|
186
|
+
else:
|
|
187
|
+
_n_trans_max = np.floor(self.survey_duration / (self.trans_duration / 365.25))
|
|
188
|
+
tshifts = np.arange(self.n_phase_check) * self.trans_duration / float(self.n_phase_check)
|
|
189
|
+
n_detected = 0
|
|
190
|
+
n_trans_max = 0
|
|
191
|
+
for tshift in tshifts:
|
|
192
|
+
# Compute the total number of back-to-back transients are possible
|
|
193
|
+
# to detect given the survey duration and the transient duration.
|
|
194
|
+
n_trans_max += _n_trans_max
|
|
195
|
+
if tshift != 0:
|
|
196
|
+
n_trans_max -= 1
|
|
197
|
+
if self.survey_start is None:
|
|
198
|
+
survey_start = data_slice[self.mjd_col].min()
|
|
199
|
+
time = (data_slice[self.mjd_col] - survey_start + tshift) % self.trans_duration
|
|
200
|
+
|
|
201
|
+
# Which lightcurve does each point belong to
|
|
202
|
+
lc_number = np.floor((data_slice[self.mjd_col] - survey_start) / self.trans_duration)
|
|
203
|
+
|
|
204
|
+
lc_mags = self.light_curve(time, data_slice[self.filter_col])
|
|
205
|
+
|
|
206
|
+
# How many criteria needs to be passed
|
|
207
|
+
detect_thresh = 0
|
|
208
|
+
|
|
209
|
+
# Flag points that are above the SNR limit
|
|
210
|
+
detected = np.zeros(data_slice.size, dtype=int)
|
|
211
|
+
detected[np.where(lc_mags < data_slice[self.m5_col] + self.detect_m5_plus)] += 1
|
|
212
|
+
detect_thresh += 1
|
|
213
|
+
|
|
214
|
+
# If we demand points on the rise
|
|
215
|
+
if self.n_pre_peak > 0:
|
|
216
|
+
detect_thresh += 1
|
|
217
|
+
ord = np.argsort(data_slice[self.mjd_col])
|
|
218
|
+
data_slice = data_slice[ord]
|
|
219
|
+
detected = detected[ord]
|
|
220
|
+
lc_number = lc_number[ord]
|
|
221
|
+
time = time[ord]
|
|
222
|
+
ulc_number = np.unique(lc_number)
|
|
223
|
+
left = np.searchsorted(lc_number, ulc_number)
|
|
224
|
+
right = np.searchsorted(lc_number, ulc_number, side="right")
|
|
225
|
+
# Note here I'm using np.searchsorted to basically do a
|
|
226
|
+
# 'group by' might be clearer to use
|
|
227
|
+
# scipy.ndimage.measurements.find_objects or pandas, but this
|
|
228
|
+
# numpy function is known for being efficient.
|
|
229
|
+
for le, ri in zip(left, right):
|
|
230
|
+
# Number of points where there are a detection
|
|
231
|
+
good = np.where(time[le:ri] < self.peak_time)
|
|
232
|
+
nd = np.sum(detected[le:ri][good])
|
|
233
|
+
if nd >= self.n_pre_peak:
|
|
234
|
+
detected[le:ri] += 1
|
|
235
|
+
|
|
236
|
+
# Check if we need multiple points per light curve
|
|
237
|
+
# or multiple filters
|
|
238
|
+
if (self.n_per_lc > 1) | (self.n_filters > 1):
|
|
239
|
+
# make sure things are sorted by time
|
|
240
|
+
ord = np.argsort(data_slice[self.mjd_col])
|
|
241
|
+
data_slice = data_slice[ord]
|
|
242
|
+
detected = detected[ord]
|
|
243
|
+
lc_number = lc_number[ord]
|
|
244
|
+
time = time[ord]
|
|
245
|
+
ulc_number = np.unique(lc_number)
|
|
246
|
+
left = np.searchsorted(lc_number, ulc_number)
|
|
247
|
+
right = np.searchsorted(lc_number, ulc_number, side="right")
|
|
248
|
+
detect_thresh += self.n_filters
|
|
249
|
+
|
|
250
|
+
for le, ri in zip(left, right):
|
|
251
|
+
points = np.where(detected[le:ri] > 0)
|
|
252
|
+
ufilters = np.unique(data_slice[self.filter_col][le:ri][points])
|
|
253
|
+
phase_sections = np.floor(time[le:ri][points] / self.trans_duration * self.n_per_lc)
|
|
254
|
+
for filt_name in ufilters:
|
|
255
|
+
good = np.where(data_slice[self.filter_col][le:ri][points] == filt_name)
|
|
256
|
+
if np.size(np.unique(phase_sections[good])) >= self.n_per_lc:
|
|
257
|
+
detected[le:ri] += 1
|
|
258
|
+
|
|
259
|
+
# Find the unique number of light curves that passed the required
|
|
260
|
+
# number of conditions
|
|
261
|
+
n_detected += np.size(np.unique(lc_number[np.where(detected >= detect_thresh)]))
|
|
262
|
+
|
|
263
|
+
# Rather than keeping a single "detected" variable, maybe make a mask
|
|
264
|
+
# for each criteria, then reduce functions like: reduce_singleDetect,
|
|
265
|
+
# reduce_NDetect, reduce_PerLC, reduce_perFilter.
|
|
266
|
+
# The way I'm running now it would speed things up.
|
|
267
|
+
|
|
268
|
+
return float(n_detected) / n_trans_max
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
__all__ = ("SingleLinearMultibandModelMetric", "NestedLinearMultibandModelMetric")
|
|
2
|
+
|
|
3
|
+
import healpy as hp
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from .base_metric import BaseMetric
|
|
7
|
+
from .exgal_m5 import ExgalM5
|
|
8
|
+
from .weak_lensing_systematics_metric import ExgalM5WithCuts, RIZDetectionCoaddExposureTime
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SingleLinearMultibandModelMetric(BaseMetric):
|
|
12
|
+
"""Calculate a single linear combination of depths.
|
|
13
|
+
|
|
14
|
+
This is useful for calculating density or redshift fluctuations
|
|
15
|
+
from depth fluctuations on the sky,
|
|
16
|
+
for a single redshift bins (thus it is a single metric).
|
|
17
|
+
For multiple bins, see NestedLinearMultibandModelMetric.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
arr_of_model_dicts : `dict`
|
|
22
|
+
Linear coefficients to be applied to the M5 depth values.
|
|
23
|
+
Keys should be filter names + 'cst' if there is a constant offset.
|
|
24
|
+
post_processing_fn : lambda
|
|
25
|
+
Post processing function to apply to the linear combination of inputs.
|
|
26
|
+
Default `lambda x: x` simply returns the output.
|
|
27
|
+
extinction_cut : `float`, optional
|
|
28
|
+
E(B-V) cut on extinction (0.2 by default).
|
|
29
|
+
n_filters : `int`, optional
|
|
30
|
+
Cut on the number of filters required (6 by default).
|
|
31
|
+
min_depth_cut : `dict`, optional
|
|
32
|
+
Cut the areas of low depths, based on cuts in this dict.
|
|
33
|
+
Keys should be filter names. Default is no cuts.
|
|
34
|
+
max_depth_cut : `dict`, optional
|
|
35
|
+
Cut the areas of high depths, based on cuts in this dict.
|
|
36
|
+
Keys should be filter names. Default is no cuts.
|
|
37
|
+
mean_depth : `dict`, optional
|
|
38
|
+
Mean depths, which will be subtracted from the inputs
|
|
39
|
+
before applying model.
|
|
40
|
+
Keys should be filter names. Default is zero in each band.
|
|
41
|
+
In a lot of cases, instead of feeding mean_depths,
|
|
42
|
+
one can remove the monopole in the constructed healpix maps.
|
|
43
|
+
m5_col : `str`, optional
|
|
44
|
+
Column name for the m5 depth.
|
|
45
|
+
filter_col : `str`, optional
|
|
46
|
+
Column name for the filter.
|
|
47
|
+
units : `str`, optional
|
|
48
|
+
Label for "units" in the output, for use in plots.
|
|
49
|
+
badval : `float`, optional
|
|
50
|
+
Value to return for metric failure.
|
|
51
|
+
Specified here so that exgalm5 uses the same value.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
result : `float`
|
|
56
|
+
Linear combination of the M5 depths (minus mean depth, if provided).
|
|
57
|
+
result = np.sum([
|
|
58
|
+
model_dict[band] * M5_depth[band]
|
|
59
|
+
for band in ["u", "g", "r", "i", "z", "y"]
|
|
60
|
+
])
|
|
61
|
+
if post_processing_fn is provided:
|
|
62
|
+
result => post_processing_fn(result)
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
model_dict,
|
|
68
|
+
post_processing_fn=lambda x: x,
|
|
69
|
+
extinction_cut=0.2,
|
|
70
|
+
n_filters=6,
|
|
71
|
+
min_depth_cut=None,
|
|
72
|
+
max_depth_cut=None,
|
|
73
|
+
mean_depth=None,
|
|
74
|
+
m5_col="fiveSigmaDepth",
|
|
75
|
+
filter_col="band",
|
|
76
|
+
units="mag",
|
|
77
|
+
badval=np.nan,
|
|
78
|
+
**kwargs,
|
|
79
|
+
):
|
|
80
|
+
if min_depth_cut is None:
|
|
81
|
+
min_depth_cut = {}
|
|
82
|
+
self.min_depth_cut = min_depth_cut
|
|
83
|
+
if max_depth_cut is None:
|
|
84
|
+
max_depth_cut = {}
|
|
85
|
+
self.max_depth_cut = max_depth_cut
|
|
86
|
+
if mean_depth is None:
|
|
87
|
+
# Set mean_depth to 0 if not specified
|
|
88
|
+
mean_depth = dict([(f, 0) for f in "ugrizy"])
|
|
89
|
+
self.mean_depth = mean_depth
|
|
90
|
+
|
|
91
|
+
self.n_filters = n_filters
|
|
92
|
+
self.extinction_cut = extinction_cut
|
|
93
|
+
if "cst" in model_dict:
|
|
94
|
+
self.cst = model_dict["cst"]
|
|
95
|
+
else:
|
|
96
|
+
self.cst = 0.0
|
|
97
|
+
lsst_filters = ["u", "g", "r", "i", "z", "y"]
|
|
98
|
+
self.bands = [x for x in model_dict.keys() if x in lsst_filters]
|
|
99
|
+
self.model_arr = np.array([model_dict[x] for x in self.bands])[:, None]
|
|
100
|
+
|
|
101
|
+
self.m5_col = m5_col
|
|
102
|
+
self.filter_col = filter_col
|
|
103
|
+
self.post_processing_fn = post_processing_fn
|
|
104
|
+
|
|
105
|
+
self.exgal_m5 = ExgalM5(m5_col=m5_col, filter_col=filter_col, badval=badval)
|
|
106
|
+
super().__init__(
|
|
107
|
+
col=[m5_col, filter_col], units=units, maps=self.exgal_m5.maps, badval=badval, **kwargs
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def run(self, data_slice, slice_point=None):
|
|
111
|
+
""" """
|
|
112
|
+
|
|
113
|
+
if slice_point["ebv"] > self.extinction_cut:
|
|
114
|
+
return self.badval
|
|
115
|
+
|
|
116
|
+
n_filters = len(set(data_slice[self.filter_col]))
|
|
117
|
+
if n_filters < self.n_filters:
|
|
118
|
+
return self.badval
|
|
119
|
+
|
|
120
|
+
# add extinction_cut and depth cuts? and n_filters cuts
|
|
121
|
+
depths = np.vstack(
|
|
122
|
+
[
|
|
123
|
+
self.exgal_m5.run(data_slice[data_slice[self.filter_col] == lsst_filter], slice_point)
|
|
124
|
+
for lsst_filter in self.bands
|
|
125
|
+
]
|
|
126
|
+
).T
|
|
127
|
+
for i, lsst_filter in enumerate(self.bands):
|
|
128
|
+
if lsst_filter in self.mean_depth:
|
|
129
|
+
depths[i] -= self.mean_depth[lsst_filter]
|
|
130
|
+
# Don't raise Exceptions in the middle of metrics -
|
|
131
|
+
# assert depths.shape[0] >= 1
|
|
132
|
+
if depths.shape[0] < 1:
|
|
133
|
+
return self.badval
|
|
134
|
+
|
|
135
|
+
if np.any(depths == self.badval):
|
|
136
|
+
return self.badval
|
|
137
|
+
|
|
138
|
+
for i, lsst_filter in enumerate(self.bands):
|
|
139
|
+
if (
|
|
140
|
+
lsst_filter in self.min_depth_cut
|
|
141
|
+
and depths[0, i] < self.min_depth_cut[lsst_filter] - self.mean_depth[lsst_filter]
|
|
142
|
+
):
|
|
143
|
+
return self.badval
|
|
144
|
+
if (
|
|
145
|
+
lsst_filter in self.max_depth_cut
|
|
146
|
+
and depths[0, i] > self.max_depth_cut[lsst_filter] - self.mean_depth[lsst_filter]
|
|
147
|
+
):
|
|
148
|
+
return self.badval
|
|
149
|
+
|
|
150
|
+
val = self.post_processing_fn(self.cst + np.dot(depths, self.model_arr))
|
|
151
|
+
return val
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class NestedLinearMultibandModelMetric(BaseMetric):
|
|
155
|
+
"""Calculate multiple linear combinations of depths.
|
|
156
|
+
|
|
157
|
+
This is useful for calculating density or redshift fluctuations
|
|
158
|
+
from depth fluctuations on the sky,
|
|
159
|
+
for multiple redshift bins (thus it is a nested metric).
|
|
160
|
+
For a single bin, see LinearMultibandModelMetric.
|
|
161
|
+
|
|
162
|
+
Points of contact / contributors: Boris Leistedt
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
arr_of_model_dicts : `list` [ `dicts` ]
|
|
167
|
+
Array of linear coefficients to be applied to the M5 depth values.
|
|
168
|
+
Keys should be filter names + 'cst' if there is a constant offset.
|
|
169
|
+
post_processing_fn : lambda
|
|
170
|
+
Post processing function to apply to the linear combination of inputs.
|
|
171
|
+
Default `lambda x: x` simply returns the output.
|
|
172
|
+
extinction_cut : `float`, optional
|
|
173
|
+
E(B-V) cut on extinction (0.2 by default).
|
|
174
|
+
n_filters : `int`, optional
|
|
175
|
+
Cut on the number of filters required (6 by default).
|
|
176
|
+
min_depth_cut : `dict`, optional
|
|
177
|
+
Cut the areas of low depths, based on cuts in this dict.
|
|
178
|
+
Keys should be filter names. Default is no cuts.
|
|
179
|
+
max_depth_cut : `dict`, optional
|
|
180
|
+
Cut the areas of high depths, based on cuts in this dict.
|
|
181
|
+
Keys should be filter names. Default is no cuts.
|
|
182
|
+
mean_depth : `dict`, optional
|
|
183
|
+
Mean depths, which will be subtracted from the inputs
|
|
184
|
+
before applying model.
|
|
185
|
+
Keys should be filter names. Default is zero in each band.
|
|
186
|
+
In a lot of cases, instead of feeding mean_depths,
|
|
187
|
+
one can remove the monopole in the constructed healpix maps.
|
|
188
|
+
m5_col : `str`, optional
|
|
189
|
+
Column name for the m5 depth.
|
|
190
|
+
filter_col : `str`, optional
|
|
191
|
+
Column name for the filter.
|
|
192
|
+
units : `str`, optional
|
|
193
|
+
Label for "units" in the output, for use in plots.
|
|
194
|
+
badval : `float`, optional
|
|
195
|
+
Value to return for metric failure.
|
|
196
|
+
Specified here so that exgalm5 uses the same value.
|
|
197
|
+
|
|
198
|
+
Returns
|
|
199
|
+
-------
|
|
200
|
+
result : `list` [ `float` ]
|
|
201
|
+
List is the same size as arr_of_model_dicts.
|
|
202
|
+
For each element, return a linear combination of the M5 depths
|
|
203
|
+
(minus mean depth, if provided).
|
|
204
|
+
for i, model_dict in enumerate(arr_of_model_dicts):
|
|
205
|
+
result[i] = np.sum([
|
|
206
|
+
model_dict[band] * M5_depth[band]
|
|
207
|
+
for band in ["u", "g", "r", "i", "z", "y"]
|
|
208
|
+
])
|
|
209
|
+
if post_processing_fn is provided:
|
|
210
|
+
result[i] => post_processing_fn(result[i])
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
def __init__(
|
|
214
|
+
self,
|
|
215
|
+
arr_of_model_dicts,
|
|
216
|
+
post_processing_fn=lambda x: x,
|
|
217
|
+
extinction_cut=0.2,
|
|
218
|
+
n_filters=6,
|
|
219
|
+
min_depth_cut=None,
|
|
220
|
+
max_depth_cut=None,
|
|
221
|
+
mean_depth=None,
|
|
222
|
+
m5_col="fiveSigmaDepth",
|
|
223
|
+
filter_col="band",
|
|
224
|
+
units="mag",
|
|
225
|
+
badval=np.nan,
|
|
226
|
+
**kwargs,
|
|
227
|
+
):
|
|
228
|
+
self.arr_of_model_dicts = arr_of_model_dicts
|
|
229
|
+
self.n_filters = n_filters
|
|
230
|
+
self.extinction_cut = extinction_cut
|
|
231
|
+
if min_depth_cut is None:
|
|
232
|
+
min_depth_cut = {}
|
|
233
|
+
self.min_depth_cut = min_depth_cut
|
|
234
|
+
if max_depth_cut is None:
|
|
235
|
+
max_depth_cut = {}
|
|
236
|
+
self.max_depth_cut = max_depth_cut
|
|
237
|
+
if mean_depth is None:
|
|
238
|
+
mean_depth = {}
|
|
239
|
+
self.mean_depth = mean_depth
|
|
240
|
+
|
|
241
|
+
self.m5_col = m5_col
|
|
242
|
+
self.badval = badval
|
|
243
|
+
self.mask_val = hp.UNSEEN
|
|
244
|
+
self.filter_col = filter_col
|
|
245
|
+
self.post_processing_fn = post_processing_fn
|
|
246
|
+
|
|
247
|
+
self.n_bins = len(self.arr_of_model_dicts)
|
|
248
|
+
self.bad_val_arr = np.repeat(self.badval, self.n_bins)
|
|
249
|
+
|
|
250
|
+
self.exgal_m5 = ExgalM5(
|
|
251
|
+
m5_col=m5_col,
|
|
252
|
+
filter_col=filter_col,
|
|
253
|
+
badval=self.badval,
|
|
254
|
+
)
|
|
255
|
+
super().__init__(
|
|
256
|
+
col=[m5_col, filter_col],
|
|
257
|
+
badval=self.badval,
|
|
258
|
+
units=units,
|
|
259
|
+
maps=self.exgal_m5.maps,
|
|
260
|
+
metric_dtype="object",
|
|
261
|
+
**kwargs,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def run(self, data_slice, slice_point=None):
|
|
265
|
+
# apply extinction and n_filters cut
|
|
266
|
+
if slice_point["ebv"] > self.extinction_cut:
|
|
267
|
+
return self.bad_val_arr
|
|
268
|
+
|
|
269
|
+
n_filters = len(set(data_slice[self.filter_col]))
|
|
270
|
+
if n_filters < self.n_filters:
|
|
271
|
+
return self.bad_val_arr
|
|
272
|
+
|
|
273
|
+
lsst_filters = ["u", "g", "r", "i", "z", "y"]
|
|
274
|
+
|
|
275
|
+
# initialize dictionary of outputs
|
|
276
|
+
# types = [float]*n_bins
|
|
277
|
+
result_arr = np.zeros((self.n_bins,), dtype=float)
|
|
278
|
+
|
|
279
|
+
for binnumber, model_dict in enumerate(self.arr_of_model_dicts):
|
|
280
|
+
|
|
281
|
+
# put together a vector of depths
|
|
282
|
+
depths = np.vstack(
|
|
283
|
+
[
|
|
284
|
+
self.exgal_m5.run(data_slice[data_slice[self.filter_col] == lsst_filter], slice_point)
|
|
285
|
+
for lsst_filter in lsst_filters
|
|
286
|
+
]
|
|
287
|
+
).T
|
|
288
|
+
|
|
289
|
+
# if there are depth cuts, apply them
|
|
290
|
+
for i, lsst_filter in enumerate(lsst_filters):
|
|
291
|
+
if lsst_filter in self.min_depth_cut and depths[0, i] < self.min_depth_cut[lsst_filter]:
|
|
292
|
+
depths[0, i] = self.badval
|
|
293
|
+
if lsst_filter in self.max_depth_cut and depths[0, i] > self.max_depth_cut[lsst_filter]:
|
|
294
|
+
depths[0, i] = self.badval
|
|
295
|
+
|
|
296
|
+
# if provided, subtract the mean
|
|
297
|
+
for i, lsst_filter in enumerate(lsst_filters):
|
|
298
|
+
if lsst_filter in self.mean_depth:
|
|
299
|
+
depths[i] -= self.mean_depth[lsst_filter]
|
|
300
|
+
|
|
301
|
+
# now assemble the results
|
|
302
|
+
model_arr = np.array([model_dict[x] if x in model_dict else 0.0 for x in lsst_filters])
|
|
303
|
+
cst = model_dict["cst"] if "cst" in model_dict else 0.0
|
|
304
|
+
|
|
305
|
+
result_arr[binnumber] = self.post_processing_fn(cst + np.dot(depths, model_arr))
|
|
306
|
+
|
|
307
|
+
# returns array where each element of the original
|
|
308
|
+
# input arr_of_model_dicts contains a scalar value resulting
|
|
309
|
+
# from a linear combination of the six depths
|
|
310
|
+
return result_arr
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
class NestedRIZExptimeExgalM5Metric(BaseMetric):
|
|
314
|
+
"""TODO"""
|
|
315
|
+
|
|
316
|
+
def __init__(
|
|
317
|
+
self,
|
|
318
|
+
m5_col="fiveSigmaDepth",
|
|
319
|
+
filter_col="band",
|
|
320
|
+
exptime_col="visitExposureTime",
|
|
321
|
+
extinction_cut=0.2,
|
|
322
|
+
n_filters=6,
|
|
323
|
+
depth_cut=24,
|
|
324
|
+
metric_name="new_nested_FoM",
|
|
325
|
+
lsst_filter="i",
|
|
326
|
+
badval=np.nan,
|
|
327
|
+
**kwargs,
|
|
328
|
+
):
|
|
329
|
+
maps = ["DustMap"]
|
|
330
|
+
self.m5_col = m5_col
|
|
331
|
+
self.filter_col = filter_col
|
|
332
|
+
self.exptime_col = exptime_col
|
|
333
|
+
self.lsst_filter = lsst_filter
|
|
334
|
+
self.n_filters = n_filters
|
|
335
|
+
|
|
336
|
+
cols = [self.m5_col, self.filter_col, self.exptime_col]
|
|
337
|
+
super().__init__(cols, metric_name=metric_name, maps=maps, badval=badval, **kwargs)
|
|
338
|
+
self.riz_exptime_metric = RIZDetectionCoaddExposureTime(ebvlim=extinction_cut)
|
|
339
|
+
self.exgalm5_metric = ExgalM5WithCuts(
|
|
340
|
+
m5_col=m5_col,
|
|
341
|
+
filter_col=filter_col,
|
|
342
|
+
extinction_cut=extinction_cut,
|
|
343
|
+
depth_cut=depth_cut,
|
|
344
|
+
lsst_filter=lsst_filter,
|
|
345
|
+
badval=badval,
|
|
346
|
+
n_filters=n_filters,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
self.metric_dtype = "object"
|
|
350
|
+
|
|
351
|
+
def run(self, data_slice, slice_point):
|
|
352
|
+
|
|
353
|
+
# set up array to hold the results
|
|
354
|
+
names = ["exgal_m5", "riz_exptime"]
|
|
355
|
+
types = [float] * 2
|
|
356
|
+
result = np.zeros(1, dtype=list(zip(names, types)))
|
|
357
|
+
result["exgal_m5"] = self.exgalm5_metric.run(data_slice, slice_point)
|
|
358
|
+
result["riz_exptime"] = self.riz_exptime_metric.run(
|
|
359
|
+
data_slice[data_slice[self.filter_col] == "i"], slice_point
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
return result
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class MultibandExgalM5(BaseMetric):
|
|
366
|
+
"""Calculate multiple linear combinations of depths."""
|
|
367
|
+
|
|
368
|
+
def __init__(
|
|
369
|
+
self,
|
|
370
|
+
extinction_cut=0.2,
|
|
371
|
+
n_filters=6,
|
|
372
|
+
m5_col="fiveSigmaDepth",
|
|
373
|
+
filter_col="band",
|
|
374
|
+
units="mag",
|
|
375
|
+
badval=np.nan,
|
|
376
|
+
**kwargs,
|
|
377
|
+
):
|
|
378
|
+
self.n_filters = n_filters
|
|
379
|
+
self.extinction_cut = extinction_cut
|
|
380
|
+
|
|
381
|
+
self.m5_col = m5_col
|
|
382
|
+
self.badval = badval
|
|
383
|
+
self.filter_col = filter_col
|
|
384
|
+
|
|
385
|
+
self.lsst_filters = ["u", "g", "r", "i", "z", "y"]
|
|
386
|
+
self.bad_val_arr = np.repeat(self.badval, len(self.lsst_filters))
|
|
387
|
+
|
|
388
|
+
self.exgal_m5 = ExgalM5(
|
|
389
|
+
m5_col=m5_col,
|
|
390
|
+
filter_col=filter_col,
|
|
391
|
+
badval=self.badval,
|
|
392
|
+
)
|
|
393
|
+
super().__init__(
|
|
394
|
+
col=[m5_col, filter_col],
|
|
395
|
+
badval=self.badval,
|
|
396
|
+
units=units,
|
|
397
|
+
maps=self.exgal_m5.maps,
|
|
398
|
+
metric_dtype="object",
|
|
399
|
+
**kwargs,
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
def run(self, data_slice, slice_point=None):
|
|
403
|
+
# apply extinction and n_filters cut
|
|
404
|
+
if slice_point["ebv"] > self.extinction_cut:
|
|
405
|
+
return self.bad_val_arr
|
|
406
|
+
|
|
407
|
+
n_filters = len(set(data_slice[self.filter_col]))
|
|
408
|
+
if n_filters < self.n_filters:
|
|
409
|
+
return self.bad_val_arr
|
|
410
|
+
|
|
411
|
+
depths = np.vstack(
|
|
412
|
+
[
|
|
413
|
+
self.exgal_m5.run(data_slice[data_slice[self.filter_col] == lsst_filter], slice_point)
|
|
414
|
+
for lsst_filter in self.lsst_filters
|
|
415
|
+
]
|
|
416
|
+
).T
|
|
417
|
+
|
|
418
|
+
return depths.ravel()
|