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,133 @@
|
|
|
1
|
+
__all__ = ("PeriodicDetectMetric",)
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import scipy
|
|
5
|
+
|
|
6
|
+
from rubin_sim.maf.utils import m52snr, stellar_mags
|
|
7
|
+
|
|
8
|
+
from .base_metric import BaseMetric
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PeriodicDetectMetric(BaseMetric):
|
|
12
|
+
"""Determine if we would be able to classify an object as
|
|
13
|
+
periodic/non-uniform, using an F-test.
|
|
14
|
+
|
|
15
|
+
The idea here is that if a periodic source is aliased, it will be
|
|
16
|
+
indistinguishable from a constant source,
|
|
17
|
+
so we can find a best-fit constant, and if the reduced chi-squared is ~1,
|
|
18
|
+
we know we are aliased.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
mjd_col : `str`, opt
|
|
23
|
+
Name of the MJD column in the observations.
|
|
24
|
+
periods : `float` or `np.ndarray`, (N,), opt
|
|
25
|
+
The period of the star (days).
|
|
26
|
+
Can be a single value, or an array.
|
|
27
|
+
If an array, amplitude and starMag should be arrays of equal length.
|
|
28
|
+
amplitudes : `float`, opt
|
|
29
|
+
The amplitude of the stellar variability, (mags).
|
|
30
|
+
m5_col : `str`, opt
|
|
31
|
+
The name of the m5 limiting magnitude column in the observations.
|
|
32
|
+
metric_name : `str`, opt
|
|
33
|
+
The name for the metric.
|
|
34
|
+
starMags : `float`, opt
|
|
35
|
+
The mean magnitude of the star in r (mags).
|
|
36
|
+
sig_level : `float`, opt
|
|
37
|
+
The value to use to compare to the p-value when deciding
|
|
38
|
+
if we can reject the null hypothesis.
|
|
39
|
+
sed_template : `str`, opt
|
|
40
|
+
The stellar SED template to use to generate realistic colors
|
|
41
|
+
(default is an F star, so RR Lyrae-like)
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
flag : `int`
|
|
46
|
+
Returns 1 if we would detect star is variable,
|
|
47
|
+
0 if it is well-fit by a constant value.
|
|
48
|
+
If using arrays to test multiple period-amplitude-mag combinations,
|
|
49
|
+
will be the sum of the number of detected stars.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
mjd_col="observationStartMJD",
|
|
55
|
+
periods=2.0,
|
|
56
|
+
amplitudes=0.1,
|
|
57
|
+
m5_col="fiveSigmaDepth",
|
|
58
|
+
metric_name="PeriodicDetectMetric",
|
|
59
|
+
filter_col="band",
|
|
60
|
+
star_mags=20,
|
|
61
|
+
sig_level=0.05,
|
|
62
|
+
sed_template="F",
|
|
63
|
+
**kwargs,
|
|
64
|
+
):
|
|
65
|
+
self.mjd_col = mjd_col
|
|
66
|
+
self.m5_col = m5_col
|
|
67
|
+
self.filter_col = filter_col
|
|
68
|
+
if np.size(periods) == 1:
|
|
69
|
+
self.periods = [periods]
|
|
70
|
+
# Using the same magnitude for all filters.
|
|
71
|
+
# Could expand to fit the mean in each filter.
|
|
72
|
+
self.star_mags = [star_mags]
|
|
73
|
+
self.amplitudes = [amplitudes]
|
|
74
|
+
else:
|
|
75
|
+
self.periods = periods
|
|
76
|
+
self.star_mags = star_mags
|
|
77
|
+
self.amplitudes = amplitudes
|
|
78
|
+
self.sig_level = sig_level
|
|
79
|
+
self.sed_template = sed_template
|
|
80
|
+
|
|
81
|
+
super(PeriodicDetectMetric, self).__init__(
|
|
82
|
+
[mjd_col, m5_col, filter_col],
|
|
83
|
+
metric_name=metric_name,
|
|
84
|
+
units="N Detected (0, %i)" % np.size(periods),
|
|
85
|
+
**kwargs,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def run(self, data_slice, slice_point=None):
|
|
89
|
+
result = 0
|
|
90
|
+
n_pts = np.size(data_slice[self.mjd_col])
|
|
91
|
+
n_filt = np.size(np.unique(data_slice[self.filter_col]))
|
|
92
|
+
|
|
93
|
+
# If we had a correct model with phase, amplitude, period, mean_mags,
|
|
94
|
+
# then chi_squared/DoF would be ~1 with 3+n_filt free parameters.
|
|
95
|
+
# The mean is one free parameter
|
|
96
|
+
p1 = n_filt
|
|
97
|
+
p2 = 3.0 + n_filt
|
|
98
|
+
chi_sq_2 = 1.0 * (n_pts - p2)
|
|
99
|
+
|
|
100
|
+
u_filters = np.unique(data_slice[self.filter_col])
|
|
101
|
+
|
|
102
|
+
if n_pts > p2:
|
|
103
|
+
for period, starMag, amplitude in zip(self.periods, self.star_mags, self.amplitudes):
|
|
104
|
+
chi_sq_1 = 0
|
|
105
|
+
mags = stellar_mags(self.sed_template, rmag=starMag)
|
|
106
|
+
for filtername in u_filters:
|
|
107
|
+
in_filt = np.where(data_slice[self.filter_col] == filtername)[0]
|
|
108
|
+
lc = (
|
|
109
|
+
amplitude * np.sin(data_slice[self.mjd_col][in_filt] * (np.pi * 2) / period)
|
|
110
|
+
+ mags[filtername]
|
|
111
|
+
)
|
|
112
|
+
snr = m52snr(lc, data_slice[self.m5_col][in_filt])
|
|
113
|
+
delta_m = 2.5 * np.log10(1.0 + 1.0 / snr)
|
|
114
|
+
weights = 1.0 / (delta_m**2)
|
|
115
|
+
weighted_mean = np.sum(weights * lc) / np.sum(weights)
|
|
116
|
+
chi_sq_1 += np.sum(((lc - weighted_mean) ** 2 / delta_m**2))
|
|
117
|
+
# Yes, I'm fitting magnitudes rather than flux.
|
|
118
|
+
# At least I feel kinda bad about it.
|
|
119
|
+
# F-test for nested models Regression problems:
|
|
120
|
+
# https://en.wikipedia.org/wiki/F-test
|
|
121
|
+
f_numerator = (chi_sq_1 - chi_sq_2) / (p2 - p1)
|
|
122
|
+
f_denom = 1.0
|
|
123
|
+
# This is just reduced chi-squared for the more
|
|
124
|
+
# complicated model, so should be 1.
|
|
125
|
+
f_val = f_numerator / f_denom
|
|
126
|
+
# Has DoF (p2-p1, n-p2)
|
|
127
|
+
# https://stackoverflow.com/questions/21494141/how-do-i-do-a-f-test-in-python/21503346
|
|
128
|
+
p_value = scipy.stats.f.sf(f_val, p2 - p1, n_pts - p2)
|
|
129
|
+
if np.isfinite(p_value):
|
|
130
|
+
if p_value < self.sig_level:
|
|
131
|
+
result += 1
|
|
132
|
+
|
|
133
|
+
return result
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
__all__ = ("PhaseGapMetric", "PeriodicQualityMetric")
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from rubin_sim.maf.utils import m52snr
|
|
6
|
+
|
|
7
|
+
from .base_metric import BaseMetric
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PhaseGapMetric(BaseMetric):
|
|
11
|
+
"""Measure the maximum gap in phase coverage for
|
|
12
|
+
observations of periodic variables.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
col : `str`, optional
|
|
17
|
+
Name of the column to use for the observation times (MJD)
|
|
18
|
+
n_periods : `int`, optional
|
|
19
|
+
Number of periods to test
|
|
20
|
+
period_min : `float`, optional
|
|
21
|
+
Minimum period to test, in days.
|
|
22
|
+
period_max : `float`, optional
|
|
23
|
+
Maximum period to test, in days
|
|
24
|
+
n_visits_min : `int`, optional
|
|
25
|
+
Minimum number of visits necessary before looking for the phase gap.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
metric_value : `dict` {`periods`: `float`, `maxGaps` : `float`}
|
|
30
|
+
Calculates a dictionary of max gap in phase coverage for each period.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
col="observationStartMJD",
|
|
36
|
+
n_periods=5,
|
|
37
|
+
period_min=3.0,
|
|
38
|
+
period_max=35.0,
|
|
39
|
+
n_visits_min=3,
|
|
40
|
+
metric_name="Phase Gap",
|
|
41
|
+
**kwargs,
|
|
42
|
+
):
|
|
43
|
+
self.period_min = period_min
|
|
44
|
+
self.period_max = period_max
|
|
45
|
+
self.n_periods = n_periods
|
|
46
|
+
self.n_visits_min = n_visits_min
|
|
47
|
+
super(PhaseGapMetric, self).__init__(col, metric_name=metric_name, units="Fraction, 0-1", **kwargs)
|
|
48
|
+
|
|
49
|
+
def run(self, data_slice, slice_point=None):
|
|
50
|
+
if len(data_slice) < self.n_visits_min:
|
|
51
|
+
return self.badval
|
|
52
|
+
# Create 'nPeriods' evenly spaced periods within range of min to max.
|
|
53
|
+
step = (self.period_max - self.period_min) / self.n_periods
|
|
54
|
+
if step == 0:
|
|
55
|
+
periods = np.array([self.period_min])
|
|
56
|
+
else:
|
|
57
|
+
periods = np.arange(self.n_periods)
|
|
58
|
+
periods = periods / np.max(periods) * (self.period_max - self.period_min) + self.period_min
|
|
59
|
+
max_gap = np.zeros(self.n_periods, float)
|
|
60
|
+
|
|
61
|
+
for i, period in enumerate(periods):
|
|
62
|
+
# For each period, calculate the phases.
|
|
63
|
+
phases = (data_slice[self.colname] % period) / period
|
|
64
|
+
phases = np.sort(phases)
|
|
65
|
+
# Find the largest gap in coverage.
|
|
66
|
+
gaps = np.diff(phases)
|
|
67
|
+
start_to_end = np.array([1.0 - phases[-1] + phases[0]], float)
|
|
68
|
+
gaps = np.concatenate([gaps, start_to_end])
|
|
69
|
+
max_gap[i] = np.max(gaps)
|
|
70
|
+
|
|
71
|
+
return {"periods": periods, "maxGaps": max_gap}
|
|
72
|
+
|
|
73
|
+
def reduce_mean_gap(self, metric_val):
|
|
74
|
+
"""
|
|
75
|
+
At each slice_point, return the mean gap value.
|
|
76
|
+
"""
|
|
77
|
+
return np.mean(metric_val["maxGaps"])
|
|
78
|
+
|
|
79
|
+
def reduce_median_gap(self, metric_val):
|
|
80
|
+
"""
|
|
81
|
+
At each slice_point, return the median gap value.
|
|
82
|
+
"""
|
|
83
|
+
return np.median(metric_val["maxGaps"])
|
|
84
|
+
|
|
85
|
+
def reduce_worst_period(self, metric_val):
|
|
86
|
+
"""
|
|
87
|
+
At each slice_point, return the period with the largest phase gap.
|
|
88
|
+
"""
|
|
89
|
+
worst_p = metric_val["periods"][np.where(metric_val["maxGaps"] == metric_val["maxGaps"].max())]
|
|
90
|
+
return worst_p
|
|
91
|
+
|
|
92
|
+
def reduce_largest_gap(self, metric_val):
|
|
93
|
+
"""
|
|
94
|
+
At each slice_point, return the largest phase gap value.
|
|
95
|
+
"""
|
|
96
|
+
return np.max(metric_val["maxGaps"])
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# To fit a periodic source well, you need to cover the full phase,
|
|
100
|
+
# and fit the amplitude.
|
|
101
|
+
class PeriodicQualityMetric(BaseMetric):
|
|
102
|
+
"""Evaluate phase coverage over a given period.
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
mjd_col : `str`, opt
|
|
107
|
+
Name of the MJD column in the observations.
|
|
108
|
+
period : `float`, opt
|
|
109
|
+
Period to check.
|
|
110
|
+
m5_col : `str`, opt
|
|
111
|
+
Name of the m5 column in the observations.
|
|
112
|
+
metric_name : `str`, opt
|
|
113
|
+
Name of the metric.
|
|
114
|
+
star_mag : `float`, opt
|
|
115
|
+
Magnitude of the star to simulate coverage for.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
value : `float`
|
|
120
|
+
Value representing phase_coverage * amplitude_snr.
|
|
121
|
+
Ranges from 0 (poor) to 1.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
def __init__(
|
|
125
|
+
self,
|
|
126
|
+
mjd_col="observationStartMJD",
|
|
127
|
+
period=2.0,
|
|
128
|
+
m5_col="fiveSigmaDepth",
|
|
129
|
+
metric_name="PhaseCoverageMetric",
|
|
130
|
+
star_mag=20,
|
|
131
|
+
**kwargs,
|
|
132
|
+
):
|
|
133
|
+
self.mjd_col = mjd_col
|
|
134
|
+
self.m5_col = m5_col
|
|
135
|
+
self.period = period
|
|
136
|
+
self.star_mag = star_mag
|
|
137
|
+
super(PeriodicQualityMetric, self).__init__(
|
|
138
|
+
[mjd_col, m5_col], metric_name=metric_name, units="Fraction, 0-1", **kwargs
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def _calc_phase(self, data_slice):
|
|
142
|
+
"""1 is perfectly balanced phase coverage,
|
|
143
|
+
0 is no effective coverage.
|
|
144
|
+
"""
|
|
145
|
+
angles = data_slice[self.mjd_col] % self.period
|
|
146
|
+
angles = angles / self.period * 2.0 * np.pi
|
|
147
|
+
x = np.cos(angles)
|
|
148
|
+
y = np.sin(angles)
|
|
149
|
+
|
|
150
|
+
snr = m52snr(self.star_mag, data_slice[self.m5_col])
|
|
151
|
+
x_ave = np.average(x, weights=snr)
|
|
152
|
+
y_ave = np.average(y, weights=snr)
|
|
153
|
+
|
|
154
|
+
vector_off = np.sqrt(x_ave**2 + y_ave**2)
|
|
155
|
+
return 1.0 - vector_off
|
|
156
|
+
|
|
157
|
+
def _calc_amp(self, data_slice):
|
|
158
|
+
"""Fractional SNR on the amplitude,
|
|
159
|
+
testing for a variety of possible phases.
|
|
160
|
+
"""
|
|
161
|
+
phases = np.arange(0, np.pi, np.pi / 8.0)
|
|
162
|
+
snr = m52snr(self.star_mag, data_slice[self.m5_col])
|
|
163
|
+
amp_snrs = np.sin(data_slice[self.mjd_col] / self.period * 2 * np.pi + phases[:, np.newaxis]) * snr
|
|
164
|
+
amp_snr = np.min(np.sqrt(np.sum(amp_snrs**2, axis=1)))
|
|
165
|
+
|
|
166
|
+
max_snr = np.sqrt(np.sum(snr**2))
|
|
167
|
+
return amp_snr / max_snr
|
|
168
|
+
|
|
169
|
+
def run(self, data_slice, slice_point=None):
|
|
170
|
+
amplitude_fraction = self._calc_amp(data_slice)
|
|
171
|
+
phase_fraction = self._calc_phase(data_slice)
|
|
172
|
+
return amplitude_fraction * phase_fraction
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
__all__ = ("QSONumberCountsMetric",)
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import healpy as hp
|
|
6
|
+
import numpy as np
|
|
7
|
+
from rubin_scheduler.data import get_data_dir
|
|
8
|
+
from scipy import interpolate
|
|
9
|
+
|
|
10
|
+
from .base_metric import BaseMetric
|
|
11
|
+
from .exgal_m5 import ExgalM5
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class QSONumberCountsMetric(BaseMetric):
|
|
15
|
+
"""Calculate the number of quasars expected with SNR>=5
|
|
16
|
+
according to the Shen et al. (2020) QLF - model A in the redshift
|
|
17
|
+
range zmin < z < zmax.
|
|
18
|
+
|
|
19
|
+
The 5 sigma depths are obtained using the ExgalM5 metric.
|
|
20
|
+
Only quasars fainter than the saturation magnitude are counted.
|
|
21
|
+
|
|
22
|
+
By default, zmin is 0.3 and zmax is the minimum between 6.7 and the
|
|
23
|
+
redshift at which the Lyman break matches the effective wavelength
|
|
24
|
+
of the band. For bands izy, zmax is 6.7. This default choice is to
|
|
25
|
+
match Table 10.2 for i-band quasar counts in the LSST Science book.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
lsst_filter,
|
|
31
|
+
m5_col="fiveSigmaDepth",
|
|
32
|
+
units="mag",
|
|
33
|
+
extinction_cut=1.0,
|
|
34
|
+
filter_col="band",
|
|
35
|
+
metric_name="QSONumberCountsMetric",
|
|
36
|
+
qlf_module="Shen20",
|
|
37
|
+
qlf_model="A",
|
|
38
|
+
sed_model="Richards06",
|
|
39
|
+
zmin=0.3,
|
|
40
|
+
zmax=None,
|
|
41
|
+
**kwargs,
|
|
42
|
+
):
|
|
43
|
+
# Declare the effective wavelengths.
|
|
44
|
+
self.effwavelen = {
|
|
45
|
+
"u": 367.0,
|
|
46
|
+
"g": 482.5,
|
|
47
|
+
"r": 622.2,
|
|
48
|
+
"i": 754.5,
|
|
49
|
+
"z": 869.1,
|
|
50
|
+
"y": 971.0,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Dust Extinction limit.
|
|
54
|
+
# Regions with larger extinction and dropped from the counting.
|
|
55
|
+
self.extinction_cut = extinction_cut
|
|
56
|
+
|
|
57
|
+
# Save the filter information.
|
|
58
|
+
self.filter_col = filter_col
|
|
59
|
+
self.lsst_filter = lsst_filter
|
|
60
|
+
|
|
61
|
+
# Save zmin and zmax, or set zmax to the default value.
|
|
62
|
+
# The default zmax is the lower number between 6.7 and the
|
|
63
|
+
# redshift at which the Lyman break (91.2nm) hits the
|
|
64
|
+
# effective wavelength of the filter.
|
|
65
|
+
# Note that this means that for i, z and y,
|
|
66
|
+
# the default value for zmax is 6.7
|
|
67
|
+
self.zmin = zmin
|
|
68
|
+
if zmax is None:
|
|
69
|
+
zmax = np.min([6.7, self.effwavelen[self.lsst_filter] / 91.2 - 1.0])
|
|
70
|
+
self.zmax = zmax
|
|
71
|
+
|
|
72
|
+
# This calculation uses the ExgalM5 metric. So declare that here.
|
|
73
|
+
self.exgal_m5 = ExgalM5(m5_col=m5_col, units=units, filter_col=filter_col)
|
|
74
|
+
|
|
75
|
+
# Save the input parameters that relate to the QLF model.
|
|
76
|
+
self.qlf_module = qlf_module
|
|
77
|
+
self.qlf_model = qlf_model
|
|
78
|
+
self.sed_model = sed_model
|
|
79
|
+
|
|
80
|
+
# Read the long tables, which the number of quasars expected
|
|
81
|
+
# for a given band, qlf_module and qlf_model in a range of
|
|
82
|
+
# redshifts and magnitudes.
|
|
83
|
+
table_name = "Long_Table.LSST{0}.{1}.{2}.{3}.txt".format(
|
|
84
|
+
self.lsst_filter, self.qlf_module, self.qlf_model, self.sed_model
|
|
85
|
+
)
|
|
86
|
+
data_dir = os.path.join(get_data_dir(), "maf", "quasarNumberCounts")
|
|
87
|
+
filename = os.path.join(data_dir, table_name)
|
|
88
|
+
with open(filename, "r") as f:
|
|
89
|
+
mags = np.array([float(x) for x in f.readline().split()])
|
|
90
|
+
zs = np.array([float(x) for x in f.readline().split()])
|
|
91
|
+
mz_data = np.loadtxt(filename, skiprows=2)
|
|
92
|
+
|
|
93
|
+
# Make the long table cumulative.
|
|
94
|
+
c_mz_data = np.zeros((mz_data.shape[0] + 1, mz_data.shape[1] + 1))
|
|
95
|
+
c_mz_data[1:, 1:] = mz_data
|
|
96
|
+
c_mz_data = np.cumsum(c_mz_data, axis=0)
|
|
97
|
+
c_mz_data = np.cumsum(c_mz_data, axis=1)
|
|
98
|
+
|
|
99
|
+
# Create a 2D interpolation object for the long table.
|
|
100
|
+
# self.nqso_cumulative = interpolate.interp2d(zs[:-1], mags[:-1],
|
|
101
|
+
# #c_mz_data[:-1, :-1], kind="cubic")
|
|
102
|
+
self.nqso_cumulative_aux = interpolate.RectBivariateSpline(
|
|
103
|
+
zs[:-1], mags[:-1], c_mz_data[:-1, :-1].T, kx=3, ky=3
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
self.nqso_cumulative = lambda z_new, m_new: self.nqso_cumulative_aux(z_new, m_new).T[0]
|
|
107
|
+
|
|
108
|
+
super().__init__(
|
|
109
|
+
col=[m5_col, filter_col, "saturation_mag"],
|
|
110
|
+
metric_name=metric_name,
|
|
111
|
+
maps=self.exgal_m5.maps,
|
|
112
|
+
units=units,
|
|
113
|
+
**kwargs,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def run(self, data_slice, slice_point=None):
|
|
117
|
+
# exclude areas with high extinction
|
|
118
|
+
if slice_point["ebv"] > self.extinction_cut:
|
|
119
|
+
return self.badval
|
|
120
|
+
|
|
121
|
+
# For the data_slice, get the 5 sigma limiting magnitude.
|
|
122
|
+
d_s = data_slice[data_slice[self.filter_col] == self.lsst_filter]
|
|
123
|
+
mlim5 = self.exgal_m5.run(d_s, slice_point)
|
|
124
|
+
|
|
125
|
+
# Get the slicer pixel area.
|
|
126
|
+
nside = slice_point["nside"]
|
|
127
|
+
pix_area = hp.nside2pixarea(nside, degrees=True)
|
|
128
|
+
|
|
129
|
+
# tranform that limiting magnitude into an expected number of quasars.
|
|
130
|
+
# If there is more than one, take the faintest.
|
|
131
|
+
m_bright = np.max(d_s["saturation_mag"])
|
|
132
|
+
n11 = self.nqso_cumulative(self.zmin, m_bright)
|
|
133
|
+
n12 = self.nqso_cumulative(self.zmin, mlim5)
|
|
134
|
+
n21 = self.nqso_cumulative(self.zmax, m_bright)
|
|
135
|
+
n22 = self.nqso_cumulative(self.zmax, mlim5)
|
|
136
|
+
|
|
137
|
+
nqso = (n22 - n21 - n12 + n11) * pix_area
|
|
138
|
+
return nqso
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
__all__ = ("NgalScaleMetric", "NlcPointsMetric")
|
|
2
|
+
|
|
3
|
+
import healpy as hp
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from rubin_sim.maf.maps import TrilegalDensityMap
|
|
7
|
+
from rubin_sim.phot_utils import DustValues
|
|
8
|
+
|
|
9
|
+
from .base_metric import BaseMetric
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NgalScaleMetric(BaseMetric):
|
|
13
|
+
"""Approximate number of galaxies, scaled by median seeing.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
a_max : `float`
|
|
18
|
+
The maximum dust extinction to allow. Anything with higher dust
|
|
19
|
+
extinction is considered to have zero usable galaxies.
|
|
20
|
+
m5min : `float`
|
|
21
|
+
The minimum coadded 5-sigma depth to allow. Anything less is
|
|
22
|
+
considered to have zero usable galaxies.
|
|
23
|
+
filter : `str`
|
|
24
|
+
The filter to use. Any visits in other filters are ignored.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
seeing_col="seeingFwhmEff",
|
|
30
|
+
m5_col="fiveSigmaDepth",
|
|
31
|
+
metric_name="NgalScale",
|
|
32
|
+
filtername="i",
|
|
33
|
+
a_max=0.2,
|
|
34
|
+
m5min=26.0,
|
|
35
|
+
filter_col="band",
|
|
36
|
+
**kwargs,
|
|
37
|
+
):
|
|
38
|
+
maps = ["DustMap"]
|
|
39
|
+
units = "N gals"
|
|
40
|
+
self.seeing_col = seeing_col
|
|
41
|
+
self.m5_col = m5_col
|
|
42
|
+
self.filtername = filtername
|
|
43
|
+
self.filter_col = filter_col
|
|
44
|
+
self.a_max = a_max
|
|
45
|
+
self.m5min = m5min
|
|
46
|
+
|
|
47
|
+
super().__init__(
|
|
48
|
+
col=[self.m5_col, self.filter_col, self.seeing_col],
|
|
49
|
+
maps=maps,
|
|
50
|
+
units=units,
|
|
51
|
+
metric_name=metric_name,
|
|
52
|
+
**kwargs,
|
|
53
|
+
)
|
|
54
|
+
dust_properties = DustValues()
|
|
55
|
+
self.ax1 = dust_properties.ax1
|
|
56
|
+
|
|
57
|
+
def run(self, data_slice, slice_point):
|
|
58
|
+
# I'm a little confused why there's a dust cut and an M5 cut,
|
|
59
|
+
# but whatever
|
|
60
|
+
a_x = self.ax1[data_slice[self.filter_col][0]] * slice_point["ebv"]
|
|
61
|
+
if a_x > self.a_max:
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
in_filt = np.where(data_slice[self.filter_col] == self.filtername)
|
|
65
|
+
coadd_m5 = 1.25 * np.log10(np.sum(10.0 ** (0.8 * data_slice[self.m5_col][in_filt])))
|
|
66
|
+
if coadd_m5 < self.m5min:
|
|
67
|
+
return 0
|
|
68
|
+
|
|
69
|
+
theta = np.median(data_slice[self.seeing_col])
|
|
70
|
+
# N gals per arcmin2
|
|
71
|
+
ngal_per_arcmin2 = 57 * (0.75 / theta) ** 1.5
|
|
72
|
+
|
|
73
|
+
area = hp.nside2pixarea(slice_point["nside"], degrees=True) * 3600.0
|
|
74
|
+
|
|
75
|
+
ngal = ngal_per_arcmin2 * area
|
|
76
|
+
return ngal
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class NlcPointsMetric(BaseMetric):
|
|
80
|
+
"""Number of points in stellar light curves
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
ndpmin : `int`
|
|
85
|
+
The number of points to demand on a lightcurve in a single
|
|
86
|
+
filter to have that light curve qualify.
|
|
87
|
+
mags : `float`
|
|
88
|
+
The magnitude of our fiducial object (maybe make it a dict in the
|
|
89
|
+
future to support arbitrary colors).
|
|
90
|
+
maps : `list` [`~rubin_sim.maf.map`] or None
|
|
91
|
+
List of stellar density maps to use.
|
|
92
|
+
Default of None loads Trilegal maps.
|
|
93
|
+
nside : `int`
|
|
94
|
+
The nside is needed to make sure the loaded maps
|
|
95
|
+
match the slicer nside.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
ndpmin=10,
|
|
101
|
+
mags=21.0,
|
|
102
|
+
m5_col="fiveSigmaDepth",
|
|
103
|
+
filter_col="band",
|
|
104
|
+
metric_name="NlcPoints",
|
|
105
|
+
maps=None,
|
|
106
|
+
nside=128,
|
|
107
|
+
**kwargs,
|
|
108
|
+
):
|
|
109
|
+
units = "N LC points"
|
|
110
|
+
self.ndpmin = ndpmin
|
|
111
|
+
self.mags = mags
|
|
112
|
+
self.m5_col = m5_col
|
|
113
|
+
self.filter_col = filter_col
|
|
114
|
+
self.nside = nside
|
|
115
|
+
if maps is None:
|
|
116
|
+
maps = [TrilegalDensityMap(filtername=fn, nside=nside) for fn in "ugrizy"]
|
|
117
|
+
super().__init__(
|
|
118
|
+
col=[self.m5_col, self.filter_col],
|
|
119
|
+
maps=maps,
|
|
120
|
+
units=units,
|
|
121
|
+
metric_name=metric_name,
|
|
122
|
+
**kwargs,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def run(self, data_slice, slice_point):
|
|
126
|
+
if self.nside != slice_point["nside"]:
|
|
127
|
+
raise ValueError("nside of metric does not match slicer")
|
|
128
|
+
pix_area = hp.nside2pixarea(slice_point["nside"], degrees=True)
|
|
129
|
+
|
|
130
|
+
nlcpoints = 0
|
|
131
|
+
# Let's do it per filter
|
|
132
|
+
for filtername in np.unique(data_slice[self.filter_col]):
|
|
133
|
+
in_filt = np.where(
|
|
134
|
+
(data_slice[self.filter_col] == filtername) & (data_slice[self.m5_col] > self.mags)
|
|
135
|
+
)[0]
|
|
136
|
+
n_obs = np.size(in_filt)
|
|
137
|
+
if n_obs > self.ndpmin:
|
|
138
|
+
nstars = (
|
|
139
|
+
np.interp(
|
|
140
|
+
self.mags,
|
|
141
|
+
slice_point[f"starMapBins_{filtername}"][1:],
|
|
142
|
+
slice_point[f"starLumFunc_{filtername}"],
|
|
143
|
+
)
|
|
144
|
+
* pix_area
|
|
145
|
+
)
|
|
146
|
+
nlcpoints += n_obs * nstars
|
|
147
|
+
|
|
148
|
+
return nlcpoints
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Metrics for scheduler monitoring and progress."""
|
|
2
|
+
|
|
3
|
+
__all__ = ["AgeMetric"]
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from .base_metric import BaseMetric
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AgeMetric(BaseMetric):
|
|
11
|
+
def __init__(
|
|
12
|
+
self, mjd, mjd_col="observationStartMJD", long_limit=30, metric_name="age", mask_val=np.nan, **kwargs
|
|
13
|
+
):
|
|
14
|
+
"""Metric that shows the time since the previous visit in each slice,
|
|
15
|
+
as of a given time
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
mjd : `float`
|
|
20
|
+
Reference time for the age.
|
|
21
|
+
mjd_col : `str`
|
|
22
|
+
Column with the time of visit, by default "observationStartMJD"
|
|
23
|
+
long_limit : `int`
|
|
24
|
+
The age past which to mask values, by default 30
|
|
25
|
+
metric_name : `str`
|
|
26
|
+
The metric name, by default 'age'
|
|
27
|
+
mask_val : `object`
|
|
28
|
+
Name for masked values, by default np.nan
|
|
29
|
+
"""
|
|
30
|
+
self.mjd = mjd
|
|
31
|
+
self.mjd_col = mjd_col
|
|
32
|
+
self.long_limit = long_limit
|
|
33
|
+
super().__init__(col=[self.mjd_col], metric_name=metric_name, mask_val=mask_val, **kwargs)
|
|
34
|
+
|
|
35
|
+
def run(self, data_slice, slice_point=None):
|
|
36
|
+
age = self.mjd - np.max(data_slice[self.mjd_col])
|
|
37
|
+
if age > self.long_limit:
|
|
38
|
+
age = self.mask_val
|
|
39
|
+
return age
|