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,24 @@
|
|
|
1
|
+
__all__ = ("SnrWeightedMetric",)
|
|
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 SnrWeightedMetric(BaseMetric):
|
|
11
|
+
"""Take the SNR weighted average of a column."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, col, m5_col="fiveSigmaDepth", metric_name=None, **kwargs):
|
|
14
|
+
if metric_name is None:
|
|
15
|
+
metric_name = "SNR Weighted %s" % col
|
|
16
|
+
super(SnrWeightedMetric, self).__init__(col=[m5_col, col], metric_name=metric_name, **kwargs)
|
|
17
|
+
self.m5_col = m5_col
|
|
18
|
+
self.col = col
|
|
19
|
+
self.star_mag = 20.0 # Arbitrary reference, value doesn't matter
|
|
20
|
+
|
|
21
|
+
def run(self, data_slice, slice_point=None):
|
|
22
|
+
snr = m52snr(self.star_mag, data_slice[self.m5_col])
|
|
23
|
+
result = np.average(data_slice[self.col], weights=snr)
|
|
24
|
+
return result
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
__all__ = ("StarDensityMetric",)
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
from scipy.interpolate import interp1d
|
|
6
|
+
|
|
7
|
+
from .base_metric import BaseMetric
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StarDensityMetric(BaseMetric):
|
|
11
|
+
"""Interpolate the stellar luminosity function to return the number of
|
|
12
|
+
stars per square arcsecond brighter than the mag_limit.
|
|
13
|
+
Note that the map is built from CatSim stars in the range 20 < r < 28.
|
|
14
|
+
mag_limit values outside that the range of the map's starMapBins will
|
|
15
|
+
return self.badval
|
|
16
|
+
|
|
17
|
+
The stellar density maps are available in any bandpass, but bandpasses
|
|
18
|
+
other than r band must use a pre-configured StellarDensityMap (not just the
|
|
19
|
+
default). In other words, when setting up the metric bundle for an i-band
|
|
20
|
+
stellar density using (as an example) a HealpixSlicer:
|
|
21
|
+
```
|
|
22
|
+
map = maf.StellarDensityMap(filtername='i')
|
|
23
|
+
metric = maf.StarDensityMetric(filtername='i', mag_limit=25.0)
|
|
24
|
+
slicer = maf.HealpixSlicer()
|
|
25
|
+
bundle = maf.MetricBundle(metric, slicer, "", mapsList=[map])
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
mag_limit : `float`, opt
|
|
31
|
+
Magnitude limit at which to evaluate the stellar luminosity function.
|
|
32
|
+
Returns number of stars per square arcsecond brighter than this limit.
|
|
33
|
+
Default 25.
|
|
34
|
+
filtername : `str`, opt
|
|
35
|
+
Which filter to evaluate the luminosity function in; Note that using
|
|
36
|
+
bands other than r will require setting up a custom (rather than
|
|
37
|
+
default) version of the stellar density map.
|
|
38
|
+
Default r.
|
|
39
|
+
units : `str`, opt
|
|
40
|
+
Units for the output values. Default "stars/sq arcsec".
|
|
41
|
+
maps : `list` of `str`, opt
|
|
42
|
+
Names for the maps required. Default "StellarDensityMap".
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
result : `float`
|
|
47
|
+
Number of stars brighter than mag_limit in filtername, based on the
|
|
48
|
+
stellar density map.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self, mag_limit=25.0, filtername="r", units="stars/sq arcsec", maps=["StellarDensityMap"], **kwargs
|
|
53
|
+
):
|
|
54
|
+
super(StarDensityMetric, self).__init__(col=[], maps=maps, units=units, **kwargs)
|
|
55
|
+
self.mag_limit = mag_limit
|
|
56
|
+
if "rmagLimit" in kwargs:
|
|
57
|
+
warnings.warn(
|
|
58
|
+
"rmagLimit is deprecated; please use mag_limit instead "
|
|
59
|
+
"(will use the provided rmagLimit for now)."
|
|
60
|
+
)
|
|
61
|
+
self.mag_limit = kwargs["rmagLimit"]
|
|
62
|
+
self.filtername = filtername
|
|
63
|
+
|
|
64
|
+
def run(self, data_slice, slice_point=None):
|
|
65
|
+
# Interpolate the data to the requested mag
|
|
66
|
+
interp = interp1d(
|
|
67
|
+
slice_point["starMapBins_%s" % self.filtername][1:],
|
|
68
|
+
slice_point["starLumFunc_%s" % self.filtername],
|
|
69
|
+
)
|
|
70
|
+
# convert from stars/sq degree to stars/sq arcsec
|
|
71
|
+
try:
|
|
72
|
+
result = interp(self.mag_limit) / (3600.0**2)
|
|
73
|
+
except ValueError:
|
|
74
|
+
# This probably means the interpolation went out of range
|
|
75
|
+
# (magLimit <15 or >28)
|
|
76
|
+
return self.badval
|
|
77
|
+
return result
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
__all__ = ("StringCountMetric",)
|
|
2
|
+
|
|
3
|
+
from collections import Counter
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from .base_metric import BaseMetric
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Keylookerupper:
|
|
11
|
+
"""Helper object to unpack dictionary values as reduceFunction results."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, key="blank", name=None):
|
|
14
|
+
self.key = key
|
|
15
|
+
self.__name__ = name
|
|
16
|
+
|
|
17
|
+
def __call__(self, indict):
|
|
18
|
+
return np.max(indict[self.key])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class StringCountMetric(BaseMetric):
|
|
22
|
+
"""Count up the number of times each string appears in a column.
|
|
23
|
+
|
|
24
|
+
Dynamically builds reduce functions for each unique string value,
|
|
25
|
+
so summary stats can be named the same as strings in the
|
|
26
|
+
simData array without knowing the values of those strings ahead of time.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
metric_name : `str`, opt
|
|
32
|
+
Name of the metric.
|
|
33
|
+
col : `str`, opt
|
|
34
|
+
Column name that has strings to look at.
|
|
35
|
+
percent : `bool`, opt
|
|
36
|
+
Normalize and return results as percents rather than raw count.
|
|
37
|
+
clip_end : `bool`
|
|
38
|
+
Clip if the end of a string if it ends with a comma and number.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self, metric_name="stringCountMetric", col="filter", percent=False, clip_end=False, **kwargs
|
|
43
|
+
):
|
|
44
|
+
if percent:
|
|
45
|
+
units = "percent"
|
|
46
|
+
else:
|
|
47
|
+
units = "count"
|
|
48
|
+
self.percent = percent
|
|
49
|
+
cols = [col]
|
|
50
|
+
super().__init__(cols, metric_name, units=units, metric_dtype=object, **kwargs)
|
|
51
|
+
self.col = col
|
|
52
|
+
self.clip_end = clip_end
|
|
53
|
+
|
|
54
|
+
def run(self, data_slice, slice_point=None):
|
|
55
|
+
|
|
56
|
+
# If we need to clip off trailing integer
|
|
57
|
+
if self.clip_end:
|
|
58
|
+
replace_col = []
|
|
59
|
+
for val in data_slice[self.col]:
|
|
60
|
+
if ", " in val:
|
|
61
|
+
chunks = val.split(", ")
|
|
62
|
+
if chunks[-1].isdigit():
|
|
63
|
+
new_val = ", ".join(chunks[0:-1])
|
|
64
|
+
replace_col.append(new_val)
|
|
65
|
+
else:
|
|
66
|
+
replace_col.append(val)
|
|
67
|
+
else:
|
|
68
|
+
replace_col.append(val)
|
|
69
|
+
data_slice[self.col] = replace_col
|
|
70
|
+
|
|
71
|
+
counter = Counter(data_slice[self.col])
|
|
72
|
+
# convert to a numpy array
|
|
73
|
+
lables = list(counter.keys())
|
|
74
|
+
# Numpy can't handle empty string as a dtype
|
|
75
|
+
lables = [x if x != "" else "blank" for x in lables]
|
|
76
|
+
metric_value = np.zeros(1, dtype=list(zip(lables, [float] * len(counter.keys()))))
|
|
77
|
+
for key in counter:
|
|
78
|
+
if key == "":
|
|
79
|
+
metric_value["blank"] = counter[key]
|
|
80
|
+
else:
|
|
81
|
+
metric_value[key] = counter[key]
|
|
82
|
+
if self.percent:
|
|
83
|
+
norm = sum(metric_value[0]) / 100.0
|
|
84
|
+
# Not sure I really like having to loop here,
|
|
85
|
+
# but the dtype is inflexible
|
|
86
|
+
for key in metric_value.dtype.names:
|
|
87
|
+
metric_value[key] = metric_value[key] / norm
|
|
88
|
+
|
|
89
|
+
# Now to dynamically set up the reduce functions
|
|
90
|
+
for i, key in enumerate(metric_value.dtype.names):
|
|
91
|
+
name = key
|
|
92
|
+
self.reduce_funcs[name] = Keylookerupper(key=key, name=name)
|
|
93
|
+
self.reduce_order[name] = i
|
|
94
|
+
|
|
95
|
+
return metric_value
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
__all__ = (
|
|
2
|
+
"FootprintFractionMetric",
|
|
3
|
+
"FOArea",
|
|
4
|
+
"FONv",
|
|
5
|
+
"IdentityMetric",
|
|
6
|
+
"NormalizeMetric",
|
|
7
|
+
"ZeropointMetric",
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import healpy as hp
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from .base_metric import BaseMetric
|
|
15
|
+
|
|
16
|
+
# Metrics which are primarily intended to be used as summary statistics.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class FootprintFractionMetric(BaseMetric):
|
|
20
|
+
"""Calculate fraction of a desired footprint got covered.
|
|
21
|
+
Helpful to check if everything was covered in first year
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
footprint : `np.ndarray`, (N,)
|
|
26
|
+
The HEALpix footprint to compare to.
|
|
27
|
+
Nside of the footprint should match nside of the slicer.
|
|
28
|
+
n_min : `int`
|
|
29
|
+
The number of visits to require to consider an area covered
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, footprint=None, n_min=1, **kwargs):
|
|
33
|
+
super().__init__(**kwargs)
|
|
34
|
+
self.footprint = footprint
|
|
35
|
+
self.nside = hp.npix2nside(footprint.size)
|
|
36
|
+
self.npix = np.where(self.footprint > 0)[0].size
|
|
37
|
+
# get whole array passed
|
|
38
|
+
self.mask_val = 0
|
|
39
|
+
self.n_min = n_min
|
|
40
|
+
|
|
41
|
+
def run(self, data_slice, slice_point=None):
|
|
42
|
+
overlap = np.where((self.footprint > 0) & (data_slice["metricdata"] >= self.n_min))[0]
|
|
43
|
+
result = overlap.size / self.npix
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class FONv(BaseMetric):
|
|
48
|
+
"""Given asky area, what is the minimum and median NVISITS obtained over
|
|
49
|
+
that area?
|
|
50
|
+
(chooses the portion of the sky with the highest number of visits first).
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
col : `str` or `list` of `strs`, optional
|
|
55
|
+
Name of the column in the numpy recarray passed to the summary metric.
|
|
56
|
+
asky : `float`, optional
|
|
57
|
+
Area of the sky to base the evaluation of number of visits over.
|
|
58
|
+
nside : `int`, optional
|
|
59
|
+
Nside parameter from healpix slicer, used to set the physical
|
|
60
|
+
relationship between on-sky area and number of healpixels.
|
|
61
|
+
n_visit : `int`, optional
|
|
62
|
+
Number of visits to use as the benchmark value, if choosing to return
|
|
63
|
+
a normalized n_visit value.
|
|
64
|
+
norm : `bool`, optional
|
|
65
|
+
Normalize the returned "n_visit" (min / median) values by n_visit,
|
|
66
|
+
if true.
|
|
67
|
+
metric_name : `str`, optional
|
|
68
|
+
Name of the summary metric. Default FONv.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(self, col="metricdata", asky=18000.0, nside=128, n_visit=825, norm=False, **kwargs):
|
|
72
|
+
"""asky = square degrees"""
|
|
73
|
+
super().__init__(col=col, **kwargs)
|
|
74
|
+
self.nvisit = n_visit
|
|
75
|
+
self.nside = nside
|
|
76
|
+
# Determine how many healpixels are included in asky sq deg.
|
|
77
|
+
self.asky = asky
|
|
78
|
+
self.scale = hp.nside2pixarea(self.nside, degrees=True)
|
|
79
|
+
self.npix__asky = int(np.ceil(self.asky / self.scale))
|
|
80
|
+
self.norm = norm
|
|
81
|
+
|
|
82
|
+
def run(self, data_slice, slice_point=None):
|
|
83
|
+
result = np.empty(2, dtype=[("name", np.str_, 20), ("value", float)])
|
|
84
|
+
result["name"][0] = "MedianNvis"
|
|
85
|
+
result["name"][1] = "MinNvis"
|
|
86
|
+
# If there is not even as much data as needed to cover Asky:
|
|
87
|
+
if len(data_slice) < self.npix__asky:
|
|
88
|
+
result["value"][0] = self.badval
|
|
89
|
+
result["value"][1] = self.badval
|
|
90
|
+
return result
|
|
91
|
+
# Otherwise, calculate median and mean Nvis:
|
|
92
|
+
nvis_sorted = np.sort(data_slice[self.colname])
|
|
93
|
+
# Find the Asky's worth of healpixels with the largest # of visits.
|
|
94
|
+
nvis__asky = nvis_sorted[-self.npix__asky :]
|
|
95
|
+
result["value"][0] = np.median(nvis__asky)
|
|
96
|
+
result["value"][1] = np.min(nvis__asky)
|
|
97
|
+
if self.norm:
|
|
98
|
+
result["value"] /= float(self.nvisit)
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class FOArea(BaseMetric):
|
|
103
|
+
"""Given an n_visit threshold, how much AREA receives at least that many
|
|
104
|
+
visits?
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
col : `str` or `list` of `strs`, optional
|
|
109
|
+
Name of the column in the numpy recarray passed to the summary metric.
|
|
110
|
+
n_visit : `int`, optional
|
|
111
|
+
Number of visits to use as the minimum required --
|
|
112
|
+
metric calculated area that has this many visits.
|
|
113
|
+
asky : `float`, optional
|
|
114
|
+
Area to use as the benchmark area value,
|
|
115
|
+
if choosing to return a normalized Area value.
|
|
116
|
+
nside : `int`, optional
|
|
117
|
+
Nside parameter from healpix slicer, used to set the physical
|
|
118
|
+
relationship between on-sky area and number of healpixels.
|
|
119
|
+
norm : `bool`, optional
|
|
120
|
+
If true, normalize the returned area value by asky.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
def __init__(
|
|
124
|
+
self,
|
|
125
|
+
col="metricdata",
|
|
126
|
+
n_visit=825,
|
|
127
|
+
asky=18000.0,
|
|
128
|
+
nside=128,
|
|
129
|
+
norm=False,
|
|
130
|
+
**kwargs,
|
|
131
|
+
):
|
|
132
|
+
"""asky = square degrees"""
|
|
133
|
+
super().__init__(col=col, **kwargs)
|
|
134
|
+
self.nvisit = n_visit
|
|
135
|
+
self.nside = nside
|
|
136
|
+
self.asky = asky
|
|
137
|
+
self.scale = hp.nside2pixarea(self.nside, degrees=True)
|
|
138
|
+
self.norm = norm
|
|
139
|
+
|
|
140
|
+
def run(self, data_slice, slice_point=None):
|
|
141
|
+
nvis_sorted = np.sort(data_slice[self.colname])
|
|
142
|
+
# Identify the healpixels with more than Nvisits.
|
|
143
|
+
nvis_min = nvis_sorted[np.where(nvis_sorted >= self.nvisit)]
|
|
144
|
+
if len(nvis_min) == 0:
|
|
145
|
+
result = self.badval
|
|
146
|
+
else:
|
|
147
|
+
result = nvis_min.size * self.scale
|
|
148
|
+
if self.norm:
|
|
149
|
+
result /= float(self.asky)
|
|
150
|
+
return result
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class IdentityMetric(BaseMetric):
|
|
154
|
+
"""Return the metric value.
|
|
155
|
+
|
|
156
|
+
This is primarily useful as a summary statistic for UniSlicer metrics,
|
|
157
|
+
to propagate the ~MetricBundle.metric_value into the results database.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def run(self, data_slice, slice_point=None):
|
|
161
|
+
if len(data_slice[self.colname]) == 1:
|
|
162
|
+
result = data_slice[self.colname][0]
|
|
163
|
+
else:
|
|
164
|
+
result = data_slice[self.colname]
|
|
165
|
+
return result
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class NormalizeMetric(BaseMetric):
|
|
169
|
+
"""
|
|
170
|
+
Return a metric values divided by 'norm_val'.
|
|
171
|
+
Useful for turning summary statistics into fractions.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
def __init__(self, col="metricdata", norm_val=1, **kwargs):
|
|
175
|
+
super(NormalizeMetric, self).__init__(col=col, **kwargs)
|
|
176
|
+
self.norm_val = float(norm_val)
|
|
177
|
+
|
|
178
|
+
def run(self, data_slice, slice_point=None):
|
|
179
|
+
result = data_slice[self.colname] / self.norm_val
|
|
180
|
+
if len(result) == 1:
|
|
181
|
+
return result[0]
|
|
182
|
+
else:
|
|
183
|
+
return result
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ZeropointMetric(BaseMetric):
|
|
187
|
+
"""
|
|
188
|
+
Return a metric values with the addition of 'zp'.
|
|
189
|
+
Useful for altering the zeropoint for summary statistics.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
def __init__(self, col="metricdata", zp=0, **kwargs):
|
|
193
|
+
super(ZeropointMetric, self).__init__(col=col, **kwargs)
|
|
194
|
+
self.zp = zp
|
|
195
|
+
|
|
196
|
+
def run(self, data_slice, slice_point=None):
|
|
197
|
+
result = data_slice[self.colname] + self.zp
|
|
198
|
+
if len(result) == 1:
|
|
199
|
+
return result[0]
|
|
200
|
+
else:
|
|
201
|
+
return result
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
__all__ = ("SurfaceBrightLimitMetric",)
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from rubin_sim.maf.utils import load_inst_zeropoints
|
|
8
|
+
|
|
9
|
+
from .base_metric import BaseMetric
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def surface_brightness_limit_approx(
|
|
13
|
+
zp,
|
|
14
|
+
k,
|
|
15
|
+
airmass,
|
|
16
|
+
mu_sky,
|
|
17
|
+
rn=8.8,
|
|
18
|
+
pixscale=0.2,
|
|
19
|
+
nsigma=3.0,
|
|
20
|
+
t_exp=30.0,
|
|
21
|
+
tot_area=100.0,
|
|
22
|
+
mag_diff_warn=0.1,
|
|
23
|
+
):
|
|
24
|
+
"""Compute surface brightness limit in 3 limiting cases, return the
|
|
25
|
+
brightest.
|
|
26
|
+
|
|
27
|
+
Algerbra worked out in this technote:
|
|
28
|
+
https://github.com/lsst-sims/smtn-016
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
---------
|
|
32
|
+
zp : `float`
|
|
33
|
+
Telescope zeropoint (mags)
|
|
34
|
+
k : `float`
|
|
35
|
+
Atmospheric extinction term
|
|
36
|
+
airmass : `float`
|
|
37
|
+
Airmass
|
|
38
|
+
mu_sky : `float`
|
|
39
|
+
Surface brightness of the sky (mag/sq arcsec)
|
|
40
|
+
rn : `float` (8.8)
|
|
41
|
+
Readnoise in electrons
|
|
42
|
+
pixscale : `float` (0.2)
|
|
43
|
+
Arcseconds per pixel
|
|
44
|
+
nsigma : `float` (3)
|
|
45
|
+
The SNR to demand
|
|
46
|
+
t_exp : `float` (30.)
|
|
47
|
+
Exposure time (seconds)
|
|
48
|
+
tot_area : `float` (100)
|
|
49
|
+
The total area measuring over (sq arcsec)
|
|
50
|
+
mag_diff_warn : `float` (0.1)
|
|
51
|
+
If the limiting cases are within mag_diff_warn, throw a warning
|
|
52
|
+
that the surface brightness limit may be an overestimate.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
surface brightness limit in mags/sq arcsec, aka the surface brightness that
|
|
57
|
+
reaches SNR=nsigma when measured over tot_area.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
a_pix = pixscale**2
|
|
61
|
+
|
|
62
|
+
n_pix = tot_area / a_pix
|
|
63
|
+
|
|
64
|
+
# Sky limited case
|
|
65
|
+
mu_sky_lim = -1.25 * np.log10(nsigma**2 / (a_pix * t_exp * n_pix)) + 0.5 * mu_sky + 0.5 * zp - k * airmass
|
|
66
|
+
|
|
67
|
+
# Source limited case
|
|
68
|
+
# XXX--double check this algerbra. Pretty sure it's right now.
|
|
69
|
+
mu_source_lim = -5 * np.log10(nsigma) + 2.5 * np.log10(n_pix * a_pix * t_exp) + zp - k * airmass
|
|
70
|
+
|
|
71
|
+
# Readnoise limited case
|
|
72
|
+
mu_rn_lim = -2.5 * np.log10(nsigma * rn / (t_exp * a_pix * n_pix**0.5)) + zp - k * airmass
|
|
73
|
+
|
|
74
|
+
d1 = np.min(np.abs(mu_sky_lim - mu_source_lim))
|
|
75
|
+
d2 = np.min(np.abs(mu_sky_lim - mu_rn_lim))
|
|
76
|
+
d3 = np.min(np.abs(mu_rn_lim - mu_source_lim))
|
|
77
|
+
|
|
78
|
+
if np.min([d1, d2, d3]) < mag_diff_warn:
|
|
79
|
+
warnings.warn(
|
|
80
|
+
"Limiting magnitudes in different cases are within %.3f mags, \
|
|
81
|
+
result may be too optimistic by up 0.38 mags/sq arcsec."
|
|
82
|
+
% mag_diff_warn
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
result = np.vstack([mu_sky_lim, mu_source_lim, mu_rn_lim])
|
|
86
|
+
result = np.min(result, axis=0)
|
|
87
|
+
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class SurfaceBrightLimitMetric(BaseMetric):
|
|
92
|
+
"""Gaussian limit, ignoring systematic errors in photometry
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
pixscale : `float` (0.2)
|
|
97
|
+
Pixelscale, Arcseconds per pixel
|
|
98
|
+
nsigma : `float` (3)
|
|
99
|
+
The detection limit (usuall 3 or 5)
|
|
100
|
+
tot_area : `float` (100)
|
|
101
|
+
Total sky area summed over, square arcseconds
|
|
102
|
+
zpt : `dict` of `float` (None)
|
|
103
|
+
telescope zeropoints. If None, computed from phot_utils
|
|
104
|
+
k_atm : `dict` of `float` (None)
|
|
105
|
+
Atmospheric extinction parameters. If None, computed from phot_utils
|
|
106
|
+
readnoise : `float` (8.8)
|
|
107
|
+
Readnoise in electrons
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
def __init__(
|
|
111
|
+
self,
|
|
112
|
+
pixscale=0.2,
|
|
113
|
+
nsigma=3.0,
|
|
114
|
+
tot_area=100.0,
|
|
115
|
+
filter_col="band",
|
|
116
|
+
units="mag/sq arcsec",
|
|
117
|
+
airmass_col="airmass",
|
|
118
|
+
exptime_col="visitExposureTime",
|
|
119
|
+
metric_name="SurfaceBrightLimit",
|
|
120
|
+
skybrightness_col="skyBrightness",
|
|
121
|
+
nexp_col="numExposures",
|
|
122
|
+
zpt=None,
|
|
123
|
+
k_atm=None,
|
|
124
|
+
readnoise=8.8,
|
|
125
|
+
**kwargs,
|
|
126
|
+
):
|
|
127
|
+
super().__init__(
|
|
128
|
+
col=[filter_col, airmass_col, exptime_col, skybrightness_col, nexp_col],
|
|
129
|
+
units=units,
|
|
130
|
+
metric_name=metric_name,
|
|
131
|
+
**kwargs,
|
|
132
|
+
)
|
|
133
|
+
self.filter_col = filter_col
|
|
134
|
+
self.airmass_col = airmass_col
|
|
135
|
+
self.exptime_col = exptime_col
|
|
136
|
+
self.skybrightness_col = skybrightness_col
|
|
137
|
+
self.nexp_col = nexp_col
|
|
138
|
+
|
|
139
|
+
self.readnoise = readnoise
|
|
140
|
+
self.pixscale = pixscale
|
|
141
|
+
self.nsigma = nsigma
|
|
142
|
+
self.tot_area = tot_area
|
|
143
|
+
|
|
144
|
+
# Compute default zeropoints
|
|
145
|
+
if zpt is None:
|
|
146
|
+
zp_inst, k_atm = load_inst_zeropoints()
|
|
147
|
+
self.zpt = zp_inst
|
|
148
|
+
self.k_atm = k_atm
|
|
149
|
+
else:
|
|
150
|
+
self.zpt = zpt
|
|
151
|
+
self.k_atm = k_atm
|
|
152
|
+
|
|
153
|
+
def run(self, data_slice, slice_point):
|
|
154
|
+
filtername = np.unique(data_slice[self.filter_col])
|
|
155
|
+
if np.size(filtername) > 1:
|
|
156
|
+
ValueError("Can only coadd depth in single filter, got filters %s" % filtername)
|
|
157
|
+
filtername = filtername[0]
|
|
158
|
+
|
|
159
|
+
# Scale up readnoise if the visit was split into multiple snaps
|
|
160
|
+
readnoise = self.readnoise * np.sqrt(data_slice[self.nexp_col])
|
|
161
|
+
|
|
162
|
+
sb_per_visit = surface_brightness_limit_approx(
|
|
163
|
+
self.zpt[filtername],
|
|
164
|
+
self.k_atm[filtername],
|
|
165
|
+
data_slice[self.airmass_col],
|
|
166
|
+
data_slice[self.skybrightness_col],
|
|
167
|
+
rn=readnoise,
|
|
168
|
+
pixscale=self.pixscale,
|
|
169
|
+
nsigma=self.nsigma,
|
|
170
|
+
t_exp=data_slice[self.exptime_col],
|
|
171
|
+
tot_area=self.tot_area,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
coadd_sb_limit = 1.25 * np.log10(np.sum(10 ** (0.8 * sb_per_visit)))
|
|
175
|
+
return coadd_sb_limit
|