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.
Files changed (387) hide show
  1. batch/compile_prenight_metadata_cache.sh +34 -0
  2. batch/run_auxtel_prenight_sims.sh +163 -0
  3. batch/run_prenight_sims.sh +239 -0
  4. docs/.gitignore +3 -0
  5. docs/Makefile +32 -0
  6. docs/api.rst +25 -0
  7. docs/conf.py +8 -0
  8. docs/data-api.rst +12 -0
  9. docs/data-download.rst +70 -0
  10. docs/developer.rst +14 -0
  11. docs/documenteer.toml +11 -0
  12. docs/index.rst +22 -0
  13. docs/installation.rst +76 -0
  14. docs/introduction.rst +37 -0
  15. docs/maf-api-batches.rst +12 -0
  16. docs/maf-api-db.rst +12 -0
  17. docs/maf-api-maf-contrib.rst +12 -0
  18. docs/maf-api-maps.rst +12 -0
  19. docs/maf-api-metricbundles.rst +12 -0
  20. docs/maf-api-metrics.rst +12 -0
  21. docs/maf-api-plots.rst +12 -0
  22. docs/maf-api-run-comparison.rst +12 -0
  23. docs/maf-api-slicers.rst +12 -0
  24. docs/maf-api-stackers.rst +12 -0
  25. docs/maf-api-utils.rst +12 -0
  26. docs/maf-api.rst +22 -0
  27. docs/maf.rst +60 -0
  28. docs/metric_list.py +49 -0
  29. docs/moving-objects-api.rst +12 -0
  30. docs/moving-objects.rst +22 -0
  31. docs/phot-utils-api.rst +12 -0
  32. docs/phot-utils.rst +11 -0
  33. docs/prenight.rst +117 -0
  34. docs/protoarchive.rst +276 -0
  35. docs/satellite-constellations-api.rst +12 -0
  36. docs/satellite-constellations.rst +13 -0
  37. docs/selfcal-api.rst +12 -0
  38. docs/selfcal.rst +15 -0
  39. docs/sim-archive-api.rst +12 -0
  40. docs/skybrightness-api.rst +12 -0
  41. docs/skybrightness.rst +23 -0
  42. docs/user-guide.rst +28 -0
  43. docs/vseqarchive-architecture.rst +438 -0
  44. docs/vseqarchive-setup.rst +238 -0
  45. docs/vseqarchive.rst +225 -0
  46. rubin_sim/__init__.py +7 -0
  47. rubin_sim/data/__init__.py +1 -0
  48. rubin_sim/data/rs_download_data.py +155 -0
  49. rubin_sim/maf/__init__.py +34 -0
  50. rubin_sim/maf/batches/__init__.py +18 -0
  51. rubin_sim/maf/batches/altaz_batch.py +161 -0
  52. rubin_sim/maf/batches/col_map_dict.py +274 -0
  53. rubin_sim/maf/batches/common.py +388 -0
  54. rubin_sim/maf/batches/ddf_batch.py +728 -0
  55. rubin_sim/maf/batches/filterchange_batch.py +182 -0
  56. rubin_sim/maf/batches/glance_batch.py +591 -0
  57. rubin_sim/maf/batches/hourglass_batch.py +79 -0
  58. rubin_sim/maf/batches/info_batch.py +114 -0
  59. rubin_sim/maf/batches/metadata_batch.py +558 -0
  60. rubin_sim/maf/batches/moving_objects_batch.py +1587 -0
  61. rubin_sim/maf/batches/openshutter_batch.py +100 -0
  62. rubin_sim/maf/batches/radar_limited.py +1100 -0
  63. rubin_sim/maf/batches/science_radar_batch.py +1910 -0
  64. rubin_sim/maf/batches/skycoverage.py +155 -0
  65. rubin_sim/maf/batches/slew_batch.py +146 -0
  66. rubin_sim/maf/batches/srd_batch.py +637 -0
  67. rubin_sim/maf/batches/time_batch.py +757 -0
  68. rubin_sim/maf/batches/time_sci_batch.py +105 -0
  69. rubin_sim/maf/batches/visitdepth_batch.py +485 -0
  70. rubin_sim/maf/db/__init__.py +2 -0
  71. rubin_sim/maf/db/add_run.py +34 -0
  72. rubin_sim/maf/db/results_db.py +1074 -0
  73. rubin_sim/maf/db/tracking_db.py +332 -0
  74. rubin_sim/maf/ddf_dir.py +53 -0
  75. rubin_sim/maf/generate_ss.py +218 -0
  76. rubin_sim/maf/glance_dir.py +58 -0
  77. rubin_sim/maf/maf_contrib/__init__.py +25 -0
  78. rubin_sim/maf/maf_contrib/calculate_lsst_field_visibility_astropy.py +170 -0
  79. rubin_sim/maf/maf_contrib/depth_limited_num_gal_metric.py +109 -0
  80. rubin_sim/maf/maf_contrib/example_new_metrics.py +40 -0
  81. rubin_sim/maf/maf_contrib/filter_pair_t_gaps_metric.py +208 -0
  82. rubin_sim/maf/maf_contrib/grb_transient_metric.py +249 -0
  83. rubin_sim/maf/maf_contrib/gw170817_det_metric.py +72 -0
  84. rubin_sim/maf/maf_contrib/intervals_between_obs_metric.py +68 -0
  85. rubin_sim/maf/maf_contrib/kne_metrics.py +473 -0
  86. rubin_sim/maf/maf_contrib/lss_metrics.py +45 -0
  87. rubin_sim/maf/maf_contrib/lss_obs_strategy/__init__.py +3 -0
  88. rubin_sim/maf/maf_contrib/lss_obs_strategy/constants_for_pipeline.py +73 -0
  89. rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_metric_extended.py +205 -0
  90. rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_with_pixel_calibration.py +171 -0
  91. rubin_sim/maf/maf_contrib/lv_dwarfs/__init__.py +1 -0
  92. rubin_sim/maf/maf_contrib/lv_dwarfs/lv_dwarfs_metrics.py +388 -0
  93. rubin_sim/maf/maf_contrib/microlensing_metric.py +593 -0
  94. rubin_sim/maf/maf_contrib/num_obs_in_survey_time_overlap_metric.py +43 -0
  95. rubin_sim/maf/maf_contrib/periodic_metric.py +51 -0
  96. rubin_sim/maf/maf_contrib/periodic_star_metric.py +186 -0
  97. rubin_sim/maf/maf_contrib/periodic_star_modulation_metric.py +236 -0
  98. rubin_sim/maf/maf_contrib/presto_color_kne_pop_metric.py +441 -0
  99. rubin_sim/maf/maf_contrib/selfcal_uniformity_metric.py +171 -0
  100. rubin_sim/maf/maf_contrib/star_count_mass_metric.py +64 -0
  101. rubin_sim/maf/maf_contrib/star_count_metric.py +56 -0
  102. rubin_sim/maf/maf_contrib/star_counts/__init__.py +8 -0
  103. rubin_sim/maf/maf_contrib/star_counts/abs_mag.py +324 -0
  104. rubin_sim/maf/maf_contrib/star_counts/coords.py +99 -0
  105. rubin_sim/maf/maf_contrib/star_counts/readme.txt +1 -0
  106. rubin_sim/maf/maf_contrib/star_counts/spec_type.py +91 -0
  107. rubin_sim/maf/maf_contrib/star_counts/starcount.py +30 -0
  108. rubin_sim/maf/maf_contrib/star_counts/starcount_bymass.py +93 -0
  109. rubin_sim/maf/maf_contrib/star_counts/stellardensity.py +59 -0
  110. rubin_sim/maf/maf_contrib/static_probes_fom_summary_metric.py +386 -0
  111. rubin_sim/maf/maf_contrib/tdes_pop_metric.py +362 -0
  112. rubin_sim/maf/maf_contrib/transient_ascii_sed_metric.py +652 -0
  113. rubin_sim/maf/maf_contrib/triplet_metric.py +156 -0
  114. rubin_sim/maf/maf_contrib/var_depth_metric.py +157 -0
  115. rubin_sim/maf/maf_contrib/xrb_metrics.py +523 -0
  116. rubin_sim/maf/maf_contrib/young_stellar_objects_metric.py +200 -0
  117. rubin_sim/maf/maf_night_report.py +200 -0
  118. rubin_sim/maf/make_fbs_tracking_db.py +90 -0
  119. rubin_sim/maf/maps/__init__.py +8 -0
  120. rubin_sim/maf/maps/base_map.py +72 -0
  121. rubin_sim/maf/maps/create_gaia_density_map.py +158 -0
  122. rubin_sim/maf/maps/dust_map.py +66 -0
  123. rubin_sim/maf/maps/dust_map_3d.py +190 -0
  124. rubin_sim/maf/maps/ebv_3d_hp.py +170 -0
  125. rubin_sim/maf/maps/ebv_hp.py +64 -0
  126. rubin_sim/maf/maps/gal_coords_map.py +22 -0
  127. rubin_sim/maf/maps/galactic_plane_priority_maps.py +210 -0
  128. rubin_sim/maf/maps/stellar_density_map.py +73 -0
  129. rubin_sim/maf/maps/trilegal_map.py +82 -0
  130. rubin_sim/maf/metadata_dir.py +90 -0
  131. rubin_sim/maf/metric_bundles/__init__.py +3 -0
  132. rubin_sim/maf/metric_bundles/metric_bundle.py +816 -0
  133. rubin_sim/maf/metric_bundles/metric_bundle_group.py +834 -0
  134. rubin_sim/maf/metric_bundles/mo_metric_bundle.py +646 -0
  135. rubin_sim/maf/metrics/__init__.py +52 -0
  136. rubin_sim/maf/metrics/agn_time_lag_metric.py +118 -0
  137. rubin_sim/maf/metrics/agnstructure.py +141 -0
  138. rubin_sim/maf/metrics/area_summary_metrics.py +120 -0
  139. rubin_sim/maf/metrics/base_metric.py +215 -0
  140. rubin_sim/maf/metrics/brown_dwarf_metric.py +162 -0
  141. rubin_sim/maf/metrics/cadence_metrics.py +400 -0
  142. rubin_sim/maf/metrics/calibration_metrics.py +618 -0
  143. rubin_sim/maf/metrics/chip_vendor_metric.py +43 -0
  144. rubin_sim/maf/metrics/color_slope_metrics.py +189 -0
  145. rubin_sim/maf/metrics/cosmology_summary_metrics.py +1212 -0
  146. rubin_sim/maf/metrics/coverage_metric.py +48 -0
  147. rubin_sim/maf/metrics/crowding_metric.py +255 -0
  148. rubin_sim/maf/metrics/cumulative_metric.py +46 -0
  149. rubin_sim/maf/metrics/dcr_metric.py +93 -0
  150. rubin_sim/maf/metrics/exgal_m5.py +57 -0
  151. rubin_sim/maf/metrics/fft_metric.py +27 -0
  152. rubin_sim/maf/metrics/galactic_plane_metrics.py +375 -0
  153. rubin_sim/maf/metrics/galplane_time_sampling_metrics.py +236 -0
  154. rubin_sim/maf/metrics/hourglass_metric.py +130 -0
  155. rubin_sim/maf/metrics/incremental_template_metric.py +255 -0
  156. rubin_sim/maf/metrics/kuiper_metrics.py +26 -0
  157. rubin_sim/maf/metrics/mo_metrics.py +1496 -0
  158. rubin_sim/maf/metrics/mo_summary_metrics.py +464 -0
  159. rubin_sim/maf/metrics/night_pointing_metric.py +70 -0
  160. rubin_sim/maf/metrics/optimal_m5_metric.py +94 -0
  161. rubin_sim/maf/metrics/pair_metric.py +69 -0
  162. rubin_sim/maf/metrics/periodic_detect_metric.py +133 -0
  163. rubin_sim/maf/metrics/phase_gap_metric.py +172 -0
  164. rubin_sim/maf/metrics/qso_number_counts_metric.py +138 -0
  165. rubin_sim/maf/metrics/scaling_metrics.py +148 -0
  166. rubin_sim/maf/metrics/schedview_metrics.py +39 -0
  167. rubin_sim/maf/metrics/season_metrics.py +344 -0
  168. rubin_sim/maf/metrics/simple_metrics.py +546 -0
  169. rubin_sim/maf/metrics/sky_sat_metric.py +18 -0
  170. rubin_sim/maf/metrics/sn_cadence_metric.py +104 -0
  171. rubin_sim/maf/metrics/sn_n_sn_metric.py +1364 -0
  172. rubin_sim/maf/metrics/sn_sl_metric.py +216 -0
  173. rubin_sim/maf/metrics/sn_snr_metric.py +715 -0
  174. rubin_sim/maf/metrics/snr_weight.py +24 -0
  175. rubin_sim/maf/metrics/star_density.py +77 -0
  176. rubin_sim/maf/metrics/string_count_metric.py +95 -0
  177. rubin_sim/maf/metrics/summary_metrics.py +201 -0
  178. rubin_sim/maf/metrics/surfb_metric.py +175 -0
  179. rubin_sim/maf/metrics/technical_metrics.py +271 -0
  180. rubin_sim/maf/metrics/tgaps.py +412 -0
  181. rubin_sim/maf/metrics/tomography_models.py +2034 -0
  182. rubin_sim/maf/metrics/transient_metrics.py +268 -0
  183. rubin_sim/maf/metrics/uniformity_metrics.py +418 -0
  184. rubin_sim/maf/metrics/use_metrics.py +55 -0
  185. rubin_sim/maf/metrics/vector_metrics.py +190 -0
  186. rubin_sim/maf/metrics/visit_groups_metric.py +341 -0
  187. rubin_sim/maf/metrics/weak_lensing_systematics_metric.py +210 -0
  188. rubin_sim/maf/plots/__init__.py +14 -0
  189. rubin_sim/maf/plots/hg_plotters.py +1117 -0
  190. rubin_sim/maf/plots/hourglass_plotters.py +120 -0
  191. rubin_sim/maf/plots/mo_plotters.py +358 -0
  192. rubin_sim/maf/plots/nd_plotters.py +220 -0
  193. rubin_sim/maf/plots/neo_distance_plotter.py +140 -0
  194. rubin_sim/maf/plots/night_pointing_plotter.py +96 -0
  195. rubin_sim/maf/plots/oned_plotters.py +114 -0
  196. rubin_sim/maf/plots/perceptual_rainbow.py +30 -0
  197. rubin_sim/maf/plots/plot_handler.py +766 -0
  198. rubin_sim/maf/plots/skyproj_plotters.py +540 -0
  199. rubin_sim/maf/plots/spatial_plotters.py +1029 -0
  200. rubin_sim/maf/plots/special_plotters.py +256 -0
  201. rubin_sim/maf/plots/two_d_plotters.py +177 -0
  202. rubin_sim/maf/plots/xyplotter.py +37 -0
  203. rubin_sim/maf/run_comparison/__init__.py +5 -0
  204. rubin_sim/maf/run_comparison/archive.py +584 -0
  205. rubin_sim/maf/run_comparison/gather_summaries.py +125 -0
  206. rubin_sim/maf/run_comparison/microlensing_compare.py +514 -0
  207. rubin_sim/maf/run_comparison/radar_plot.py +202 -0
  208. rubin_sim/maf/run_comparison/summary_plots.py +710 -0
  209. rubin_sim/maf/run_moving_calc.py +239 -0
  210. rubin_sim/maf/run_moving_fractions.py +128 -0
  211. rubin_sim/maf/run_moving_join.py +103 -0
  212. rubin_sim/maf/run_selfcal_metric.py +92 -0
  213. rubin_sim/maf/scimaf_dir.py +87 -0
  214. rubin_sim/maf/show_maf.py +227 -0
  215. rubin_sim/maf/slicers/__init__.py +13 -0
  216. rubin_sim/maf/slicers/base_slicer.py +513 -0
  217. rubin_sim/maf/slicers/base_spatial_slicer.py +202 -0
  218. rubin_sim/maf/slicers/healpix_sdss_slicer.py +118 -0
  219. rubin_sim/maf/slicers/healpix_slicer.py +189 -0
  220. rubin_sim/maf/slicers/healpix_subset_slicer.py +293 -0
  221. rubin_sim/maf/slicers/hourglass_slicer.py +37 -0
  222. rubin_sim/maf/slicers/mo_slicer.py +171 -0
  223. rubin_sim/maf/slicers/movie_slicer.py +288 -0
  224. rubin_sim/maf/slicers/nd_slicer.py +147 -0
  225. rubin_sim/maf/slicers/one_d_slicer.py +210 -0
  226. rubin_sim/maf/slicers/time_interval_slicers.py +283 -0
  227. rubin_sim/maf/slicers/uni_slicer.py +57 -0
  228. rubin_sim/maf/slicers/user_points_slicer.py +141 -0
  229. rubin_sim/maf/stackers/__init__.py +13 -0
  230. rubin_sim/maf/stackers/base_stacker.py +221 -0
  231. rubin_sim/maf/stackers/coord_stackers.py +224 -0
  232. rubin_sim/maf/stackers/date_stackers.py +192 -0
  233. rubin_sim/maf/stackers/general_stackers.py +683 -0
  234. rubin_sim/maf/stackers/get_col_info.py +104 -0
  235. rubin_sim/maf/stackers/label_stackers.py +114 -0
  236. rubin_sim/maf/stackers/m5_optimal_stacker.py +126 -0
  237. rubin_sim/maf/stackers/mo_phase.py +265 -0
  238. rubin_sim/maf/stackers/mo_stackers.py +486 -0
  239. rubin_sim/maf/stackers/n_follow_stacker.py +187 -0
  240. rubin_sim/maf/stackers/neo_dist_stacker.py +126 -0
  241. rubin_sim/maf/stackers/sdss_stackers.py +30 -0
  242. rubin_sim/maf/stackers/sn_stacker.py +152 -0
  243. rubin_sim/maf/stackers/teff_stacker.py +154 -0
  244. rubin_sim/maf/utils/__init__.py +6 -0
  245. rubin_sim/maf/utils/astrometry_utils.py +93 -0
  246. rubin_sim/maf/utils/generate_fov_map.py +58 -0
  247. rubin_sim/maf/utils/get_date_version.py +28 -0
  248. rubin_sim/maf/utils/maf_utils.py +212 -0
  249. rubin_sim/maf/utils/opsim_utils.py +259 -0
  250. rubin_sim/maf/utils/output_utils.py +34 -0
  251. rubin_sim/maf/utils/sn_n_sn_utils.py +894 -0
  252. rubin_sim/maf/utils/sn_utils.py +369 -0
  253. rubin_sim/maf/utils/stellar_mags.py +197 -0
  254. rubin_sim/maf/web/__init__.py +2 -0
  255. rubin_sim/maf/web/favicon.ico +0 -0
  256. rubin_sim/maf/web/maf_run_results.py +645 -0
  257. rubin_sim/maf/web/maf_tracking.py +139 -0
  258. rubin_sim/maf/web/sorttable.js +496 -0
  259. rubin_sim/maf/web/templates/allmetricresults.html +72 -0
  260. rubin_sim/maf/web/templates/configs.html +28 -0
  261. rubin_sim/maf/web/templates/macros.html +243 -0
  262. rubin_sim/maf/web/templates/master.html +294 -0
  263. rubin_sim/maf/web/templates/metricselect.html +91 -0
  264. rubin_sim/maf/web/templates/multicolor.html +147 -0
  265. rubin_sim/maf/web/templates/results.html +82 -0
  266. rubin_sim/maf/web/templates/runselect.html +58 -0
  267. rubin_sim/maf/web/templates/stats.html +50 -0
  268. rubin_sim/moving_objects/__init__.py +8 -0
  269. rubin_sim/moving_objects/base_obs.py +468 -0
  270. rubin_sim/moving_objects/cheby_fits.py +689 -0
  271. rubin_sim/moving_objects/cheby_values.py +231 -0
  272. rubin_sim/moving_objects/chebyshev_utils.py +365 -0
  273. rubin_sim/moving_objects/direct_obs.py +376 -0
  274. rubin_sim/moving_objects/make_lsst_obs.py +282 -0
  275. rubin_sim/moving_objects/ooephemerides.py +643 -0
  276. rubin_sim/moving_objects/orbits.py +507 -0
  277. rubin_sim/moving_objects/pre_generate.py +37 -0
  278. rubin_sim/moving_objects/utils.py +61 -0
  279. rubin_sim/phot_utils/__init__.py +7 -0
  280. rubin_sim/phot_utils/bandpass.py +425 -0
  281. rubin_sim/phot_utils/photometric_parameters.py +449 -0
  282. rubin_sim/phot_utils/physical_parameters.py +50 -0
  283. rubin_sim/phot_utils/predicted_zeropoints.py +245 -0
  284. rubin_sim/phot_utils/sed.py +1773 -0
  285. rubin_sim/phot_utils/sed_utils.py +52 -0
  286. rubin_sim/phot_utils/signaltonoise.py +695 -0
  287. rubin_sim/phot_utils/spectral_resampling.py +161 -0
  288. rubin_sim/satellite_constellations/__init__.py +3 -0
  289. rubin_sim/satellite_constellations/basis_function.py +40 -0
  290. rubin_sim/satellite_constellations/model_observatory.py +157 -0
  291. rubin_sim/satellite_constellations/sat_utils.py +488 -0
  292. rubin_sim/selfcal/__init__.py +4 -0
  293. rubin_sim/selfcal/generate_catalog.py +188 -0
  294. rubin_sim/selfcal/offsets.py +119 -0
  295. rubin_sim/selfcal/solver.py +143 -0
  296. rubin_sim/selfcal/star_tools.py +42 -0
  297. rubin_sim/sim_archive/__init__.py +14 -0
  298. rubin_sim/sim_archive/conda_packages.py +65 -0
  299. rubin_sim/sim_archive/future_vsarch.py +480 -0
  300. rubin_sim/sim_archive/make_snapshot.py +255 -0
  301. rubin_sim/sim_archive/prenight.py +216 -0
  302. rubin_sim/sim_archive/prenightindex.py +229 -0
  303. rubin_sim/sim_archive/prototype.py +1029 -0
  304. rubin_sim/sim_archive/sim_archive.py +680 -0
  305. rubin_sim/sim_archive/tempdb.py +56 -0
  306. rubin_sim/sim_archive/util.py +146 -0
  307. rubin_sim/sim_archive/vseqarchive.py +965 -0
  308. rubin_sim/sim_archive/vseqmetadata.py +1721 -0
  309. rubin_sim/skybrightness/__init__.py +5 -0
  310. rubin_sim/skybrightness/allsky_db.py +93 -0
  311. rubin_sim/skybrightness/data/ESO_Spectra/eso_tools.py +505 -0
  312. rubin_sim/skybrightness/data/solarSpec/package.py +22 -0
  313. rubin_sim/skybrightness/generate_hdf5.py +243 -0
  314. rubin_sim/skybrightness/interp_components.py +798 -0
  315. rubin_sim/skybrightness/sky_model.py +771 -0
  316. rubin_sim/skybrightness/twilight_func.py +83 -0
  317. rubin_sim/skybrightness/utils.py +91 -0
  318. rubin_sim-2.6.1.dev2.dist-info/METADATA +95 -0
  319. rubin_sim-2.6.1.dev2.dist-info/RECORD +387 -0
  320. rubin_sim-2.6.1.dev2.dist-info/WHEEL +5 -0
  321. rubin_sim-2.6.1.dev2.dist-info/entry_points.txt +24 -0
  322. rubin_sim-2.6.1.dev2.dist-info/licenses/LICENSE +674 -0
  323. rubin_sim-2.6.1.dev2.dist-info/top_level.txt +5 -0
  324. sql/make_vseqmeta.sql +251 -0
  325. tests/data/test_data.py +26 -0
  326. tests/data/test_ddf_grid.py +17 -0
  327. tests/maf/test_3x2fom.py +68 -0
  328. tests/maf/test_archive.py +162 -0
  329. tests/maf/test_basemetrics.py +99 -0
  330. tests/maf/test_batchcommon.py +36 -0
  331. tests/maf/test_batches.py +159 -0
  332. tests/maf/test_cadencemetrics.py +388 -0
  333. tests/maf/test_calibrationmetrics.py +242 -0
  334. tests/maf/test_color_slopes.py +71 -0
  335. tests/maf/test_cosmology_summaries.py +20 -0
  336. tests/maf/test_gathersummaries.py +48 -0
  337. tests/maf/test_healpixslicer.py +439 -0
  338. tests/maf/test_healpixsubsetslicer.py +273 -0
  339. tests/maf/test_hgplotters.py +145 -0
  340. tests/maf/test_hourglassmetric.py +33 -0
  341. tests/maf/test_io.py +187 -0
  342. tests/maf/test_json.py +169 -0
  343. tests/maf/test_maps.py +199 -0
  344. tests/maf/test_metricbundle.py +69 -0
  345. tests/maf/test_mometrics.py +422 -0
  346. tests/maf/test_movieslicer.py +216 -0
  347. tests/maf/test_ndslicer.py +240 -0
  348. tests/maf/test_neodistanceplotter.py +41 -0
  349. tests/maf/test_onedslicer.py +245 -0
  350. tests/maf/test_opsimutils.py +80 -0
  351. tests/maf/test_plotters.py +134 -0
  352. tests/maf/test_resultsdb.py +145 -0
  353. tests/maf/test_schedviewmetrics.py +14 -0
  354. tests/maf/test_simplemetrics.py +200 -0
  355. tests/maf/test_snmetrics.py +335 -0
  356. tests/maf/test_snmetrics_nsn.py +123 -0
  357. tests/maf/test_stackers.py +423 -0
  358. tests/maf/test_stellarmags.py +50 -0
  359. tests/maf/test_stringcount.py +26 -0
  360. tests/maf/test_summary_plots.py +197 -0
  361. tests/maf/test_summarymetrics.py +82 -0
  362. tests/maf/test_technicalmetrics.py +267 -0
  363. tests/maf/test_templatemetrics.py +86 -0
  364. tests/maf/test_timeintervalslicers.py +97 -0
  365. tests/maf/test_trackingdb.py +88 -0
  366. tests/maf/test_unislicer.py +116 -0
  367. tests/maf/test_vectormetrics.py +225 -0
  368. tests/maf/test_visitgroupsmetric.py +181 -0
  369. tests/moving_objects/test_camera.py +39 -0
  370. tests/moving_objects/test_chebyfits.py +188 -0
  371. tests/moving_objects/test_chebyshevutils.py +76 -0
  372. tests/moving_objects/test_chebyvalues.py +245 -0
  373. tests/moving_objects/test_ephemerides.py +219 -0
  374. tests/moving_objects/test_orbits.py +170 -0
  375. tests/moving_objects/test_sed_data.py +61 -0
  376. tests/phot_utils/test_approximatebandpasses.py +91 -0
  377. tests/phot_utils/test_photometricparameters.py +268 -0
  378. tests/phot_utils/test_photometry.py +61 -0
  379. tests/phot_utils/test_predicted_zeropoints.py +53 -0
  380. tests/phot_utils/test_read_bandpasses.py +29 -0
  381. tests/phot_utils/test_sed.py +368 -0
  382. tests/phot_utils/test_snr.py +370 -0
  383. tests/satellite_constellations/test_satellites.py +36 -0
  384. tests/sim_archive/test_make_snapshot.py +24 -0
  385. tests/sim_archive/test_prototype_sim_archive.py +204 -0
  386. tests/sim_archive/test_vseqarchive.py +947 -0
  387. 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()