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,546 @@
1
+ __all__ = (
2
+ "PassMetric",
3
+ "Coaddm5Metric",
4
+ "MaxMetric",
5
+ "AbsMaxMetric",
6
+ "MeanMetric",
7
+ "AbsMeanMetric",
8
+ "MedianMetric",
9
+ "AbsMedianMetric",
10
+ "MinMetric",
11
+ "FullRangeMetric",
12
+ "RmsMetric",
13
+ "RelRmsMetric",
14
+ "SumMetric",
15
+ "CountUniqueMetric",
16
+ "CountMetric",
17
+ "CountRatioMetric",
18
+ "CountSubsetMetric",
19
+ "CountBeyondThreshold",
20
+ "RobustRmsMetric",
21
+ "MaxPercentMetric",
22
+ "AbsMaxPercentMetric",
23
+ "BinaryMetric",
24
+ "FracAboveMetric",
25
+ "FracBelowMetric",
26
+ "PercentileMetric",
27
+ "NoutliersNsigmaMetric",
28
+ "UniqueRatioMetric",
29
+ "MeanAngleMetric",
30
+ "RmsAngleMetric",
31
+ "FullRangeAngleMetric",
32
+ "CountExplimMetric",
33
+ "AngularSpreadMetric",
34
+ "RealMeanMetric",
35
+ )
36
+
37
+ import numpy as np
38
+
39
+ from .base_metric import BaseMetric
40
+
41
+ # A collection of commonly used simple metrics,
42
+ # operating on a single column and returning a float.
43
+
44
+ twopi = 2.0 * np.pi
45
+
46
+
47
+ class PassMetric(BaseMetric):
48
+ """Pass the entire dataslice array back to the MetricBundle.
49
+
50
+ This is most likely useful while prototyping metrics and wanting to
51
+ just 'get the data at a point in the sky', while using a HealpixSlicer
52
+ or a UserPointSlicer.
53
+ """
54
+
55
+ def __init__(self, cols=None, **kwargs):
56
+ if cols is None:
57
+ cols = []
58
+ super(PassMetric, self).__init__(col=cols, metric_dtype="object", **kwargs)
59
+
60
+ def run(self, data_slice, slice_point=None):
61
+ return data_slice
62
+
63
+
64
+ class Coaddm5Metric(BaseMetric):
65
+ """Calculate the coadded m5 value.
66
+
67
+ Parameters
68
+ ----------
69
+ m5_col : `str`, optional
70
+ Name of the m5 column. Default fiveSigmaDepth.
71
+ metric_name : `str`, optional
72
+ Name to associate with the metric output. Default "CoaddM5".
73
+ filter_name : `str`, optional
74
+ Optionally specify a filter to sub-select visits.
75
+ Default None, does no sub-selection or checking.
76
+ filter_col : `str`, optional
77
+ Name of the filter column.
78
+ units : `str`, optional
79
+ Units for the metric. Default "mag".
80
+ """
81
+
82
+ def __init__(
83
+ self,
84
+ m5_col="fiveSigmaDepth",
85
+ metric_name="CoaddM5",
86
+ filter_name=None,
87
+ filter_col="Filter",
88
+ units="mag",
89
+ **kwargs,
90
+ ):
91
+ self.filter_name = filter_name
92
+ self.filter_col = filter_col
93
+ self.m5_col = m5_col
94
+ super().__init__(col=m5_col, metric_name=metric_name, units=units, **kwargs)
95
+
96
+ @staticmethod
97
+ def coadd(single_visit_m5s):
98
+ return 1.25 * np.log10(np.sum(10.0 ** (0.8 * single_visit_m5s)))
99
+
100
+ def run(self, data_slice, slice_point=None):
101
+ if len(data_slice) == 0:
102
+ return self.badval
103
+ if self.filter_name is not None:
104
+ matched = np.where(data_slice[self.filter_col] == self.filter_name)
105
+ coadd = self.coadd(data_slice[matched][self.m5_col])
106
+ else:
107
+ coadd = self.coadd(data_slice[self.m5_col])
108
+ return coadd
109
+
110
+
111
+ class MaxMetric(BaseMetric):
112
+ """Calculate the maximum of a simData column slice."""
113
+
114
+ def run(self, data_slice, slice_point=None):
115
+ return np.max(data_slice[self.colname])
116
+
117
+
118
+ class AbsMaxMetric(BaseMetric):
119
+ """Calculate the max of the absolute value of a simData column slice."""
120
+
121
+ def run(self, data_slice, slice_point=None):
122
+ return np.max(np.abs(data_slice[self.colname]))
123
+
124
+
125
+ class MeanMetric(BaseMetric):
126
+ """Calculate the mean of a simData column slice."""
127
+
128
+ def run(self, data_slice, slice_point=None):
129
+ return np.mean(data_slice[self.colname])
130
+
131
+
132
+ class AbsMeanMetric(BaseMetric):
133
+ """Calculate the mean of the absolute value of a simData column slice."""
134
+
135
+ def run(self, data_slice, slice_point=None):
136
+ return np.mean(np.abs(data_slice[self.colname]))
137
+
138
+
139
+ class MedianMetric(BaseMetric):
140
+ """Calculate the median of a simData column slice."""
141
+
142
+ def run(self, data_slice, slice_point=None):
143
+ return np.median(data_slice[self.colname])
144
+
145
+
146
+ class AbsMedianMetric(BaseMetric):
147
+ """Calculate the median of the absolute value of a simData column slice."""
148
+
149
+ def run(self, data_slice, slice_point=None):
150
+ return np.median(np.abs(data_slice[self.colname]))
151
+
152
+
153
+ class MinMetric(BaseMetric):
154
+ """Calculate the minimum of a simData column slice."""
155
+
156
+ def run(self, data_slice, slice_point=None):
157
+ return np.min(data_slice[self.colname])
158
+
159
+
160
+ class FullRangeMetric(BaseMetric):
161
+ """Calculate the range of a simData column slice."""
162
+
163
+ def run(self, data_slice, slice_point=None):
164
+ return np.max(data_slice[self.colname]) - np.min(data_slice[self.colname])
165
+
166
+
167
+ class RmsMetric(BaseMetric):
168
+ """Calculate the standard deviation of a simData column slice."""
169
+
170
+ def run(self, data_slice, slice_point=None):
171
+ return np.std(data_slice[self.colname])
172
+
173
+
174
+ class RelRmsMetric(BaseMetric):
175
+ """Calculate the relative scatter metric (RMS divided by median)."""
176
+
177
+ def run(self, data_slice, slice_point=None):
178
+ return np.std(data_slice[self.colname]) / np.median(data_slice[self.colname])
179
+
180
+
181
+ class SumMetric(BaseMetric):
182
+ """Calculate the sum of a simData column slice."""
183
+
184
+ def run(self, data_slice, slice_point=None):
185
+ return np.sum(data_slice[self.colname])
186
+
187
+
188
+ class CountUniqueMetric(BaseMetric):
189
+ """Return the number of unique values."""
190
+
191
+ def run(self, data_slice, slice_point=None):
192
+ return np.size(np.unique(data_slice[self.colname]))
193
+
194
+
195
+ class UniqueRatioMetric(BaseMetric):
196
+ """Return the number of unique values divided by the
197
+ total number of values."""
198
+
199
+ def run(self, data_slice, slice_point=None):
200
+ ntot = float(np.size(data_slice[self.colname]))
201
+ result = np.size(np.unique(data_slice[self.colname])) / ntot
202
+ return result
203
+
204
+
205
+ class CountMetric(BaseMetric):
206
+ """Count the length of a simData column slice."""
207
+
208
+ def __init__(self, col=None, units="#", **kwargs):
209
+ super().__init__(col=col, units=units, **kwargs)
210
+ self.metric_dtype = "int"
211
+
212
+ def run(self, data_slice, slice_point=None):
213
+ return len(data_slice[self.colname])
214
+
215
+
216
+ class CountExplimMetric(BaseMetric):
217
+ """Count the number of x second visits.
218
+ Useful for rejecting very short exposures
219
+ and counting 60s exposures as 2 visits.
220
+
221
+ Parameters
222
+ ----------
223
+ min_exp : `float`, optional
224
+ Minimum exposure time to consider as a "visit".
225
+ Exposures shorter than this will not be counted (count as 0).
226
+ expected_exp : `float`, optional
227
+ Typical exposure time to expect.
228
+ Exposures longer than this will be counted as
229
+ round(visit exposure time / expected_exp). (i.e. 40s = 1, 50s = 2).
230
+ exp_col : `str`, optional
231
+ Column name to use for visit exposure time.
232
+
233
+ Returns
234
+ -------
235
+ value : `int`
236
+ The number of visits longer than min_exp and weighted by expected_exp.
237
+ """
238
+
239
+ def __init__(self, min_exp=20.0, expected_exp=30.0, exp_col="visitExposureTime", **kwargs):
240
+ self.min_exp = min_exp
241
+ self.expected_exp = expected_exp
242
+ self.exp_col = exp_col
243
+ if "col" in kwargs:
244
+ del kwargs["col"]
245
+ super().__init__(col=[exp_col], **kwargs)
246
+ self.metric_dtype = "int"
247
+
248
+ def run(self, data_slice, slice_point=None):
249
+ nv = data_slice[self.exp_col] / self.expected_exp
250
+ nv[np.where(data_slice[self.exp_col] < self.min_exp)[0]] = 0
251
+ nv = np.round(nv)
252
+ return int(np.sum(nv))
253
+
254
+
255
+ class CountRatioMetric(BaseMetric):
256
+ """Count the length of a column slice, then divide by `norm_val`."""
257
+
258
+ def __init__(self, col=None, norm_val=1.0, metric_name=None, units="", **kwargs):
259
+ self.norm_val = float(norm_val)
260
+ if metric_name is None:
261
+ metric_name = "CountRatio %s div %.1f" % (col, norm_val)
262
+ super(CountRatioMetric, self).__init__(col=col, metric_name=metric_name, **kwargs)
263
+
264
+ def run(self, data_slice, slice_point=None):
265
+ return len(data_slice[self.colname]) / self.norm_val
266
+
267
+
268
+ class CountSubsetMetric(BaseMetric):
269
+ """Count the length of a column slice which matches `subset`."""
270
+
271
+ def __init__(self, col=None, subset=None, units="#", **kwargs):
272
+ super(CountSubsetMetric, self).__init__(col=col, units=units, **kwargs)
273
+ self.metric_dtype = "int"
274
+ self.badval = 0
275
+ self.subset = subset
276
+
277
+ def run(self, data_slice, slice_point=None):
278
+ count = len(np.where(data_slice[self.colname] == self.subset)[0])
279
+ return count
280
+
281
+
282
+ class CountBeyondThreshold(BaseMetric):
283
+ """Count the number of entries in a data column above or below
284
+ the `threshold`."""
285
+
286
+ def __init__(self, col=None, lower_threshold=None, upper_threshold=None, **kwargs):
287
+ super().__init__(col=col, **kwargs)
288
+ self.lower_threshold = lower_threshold
289
+ self.upper_threshold = upper_threshold
290
+
291
+ def run(self, data_slice, slice_point=None):
292
+ # Look for data values which match the criteria for the thresholds
293
+ if self.upper_threshold is None and self.lower_threshold is None:
294
+ count = len(data_slice)
295
+ elif self.upper_threshold is None:
296
+ count = len(np.where(data_slice[self.colname] > self.lower_threshold)[0])
297
+ elif self.lower_threshold is None:
298
+ count = len(np.where(data_slice[self.colname] < self.upper_threshold)[0])
299
+ else:
300
+ count = len(
301
+ np.where(
302
+ (data_slice[self.colname] > self.lower_threshold)
303
+ and (data_slice[self.colname] < self.upper_threshold)
304
+ )[0]
305
+ )
306
+ return count
307
+
308
+
309
+ class RobustRmsMetric(BaseMetric):
310
+ """Use the inter-quartile range of the data to estimate the RMS.
311
+ Robust, as this calculation does not include outliers in the distribution.
312
+ """
313
+
314
+ def run(self, data_slice, slice_point=None):
315
+ iqr = np.percentile(data_slice[self.colname], 75) - np.percentile(data_slice[self.colname], 25)
316
+ rms = iqr / 1.349 # approximation
317
+ return rms
318
+
319
+
320
+ class MaxPercentMetric(BaseMetric):
321
+ """Return the percent of data which matches the maximum value
322
+ of the data.
323
+ """
324
+
325
+ def run(self, data_slice, slice_point=None):
326
+ n_max = np.size(np.where(data_slice[self.colname] == np.max(data_slice[self.colname]))[0])
327
+ percent = n_max / float(data_slice[self.colname].size) * 100.0
328
+ return percent
329
+
330
+
331
+ class AbsMaxPercentMetric(BaseMetric):
332
+ """Return the percent of data which matches the absolute value of the
333
+ max value of the data.
334
+ """
335
+
336
+ def run(self, data_slice, slice_point=None):
337
+ max_val = np.abs(np.max(data_slice[self.colname]))
338
+ n_max = np.size(np.where(np.abs(data_slice[self.colname]) == max_val)[0])
339
+ percent = n_max / float(data_slice[self.colname].size) * 100.0
340
+ return percent
341
+
342
+
343
+ class BinaryMetric(BaseMetric):
344
+ """Return 1 if there is data, `badval` otherwise."""
345
+
346
+ def run(self, data_slice, slice_point=None):
347
+ if data_slice.size > 0:
348
+ return 1
349
+ else:
350
+ return self.badval
351
+
352
+
353
+ class FracAboveMetric(BaseMetric):
354
+ """Find the fraction of data values above a given `cutoff`."""
355
+
356
+ def __init__(self, col=None, cutoff=0.5, scale=1, metric_name=None, **kwargs):
357
+ # Col could just get passed in bundle with kwargs,
358
+ # by explicitly pulling it out first, we support use cases where
359
+ # class instantiated without explicit 'col=').
360
+ if metric_name is None:
361
+ metric_name = "FracAbove %.2f in %s" % (cutoff, col)
362
+ super(FracAboveMetric, self).__init__(col, metric_name=metric_name, **kwargs)
363
+ self.cutoff = cutoff
364
+ self.scale = scale
365
+
366
+ def run(self, data_slice, slice_point=None):
367
+ good = np.where(data_slice[self.colname] >= self.cutoff)[0]
368
+ frac_above = np.size(good) / float(np.size(data_slice[self.colname]))
369
+ frac_above = frac_above * self.scale
370
+ return frac_above
371
+
372
+
373
+ class FracBelowMetric(BaseMetric):
374
+ """Find the fraction of data values below a given `cutoff`."""
375
+
376
+ def __init__(self, col=None, cutoff=0.5, scale=1, metric_name=None, **kwargs):
377
+ if metric_name is None:
378
+ metric_name = "FracBelow %.2f %s" % (cutoff, col)
379
+ super(FracBelowMetric, self).__init__(col, metric_name=metric_name, **kwargs)
380
+ self.cutoff = cutoff
381
+ self.scale = scale
382
+
383
+ def run(self, data_slice, slice_point=None):
384
+ good = np.where(data_slice[self.colname] <= self.cutoff)[0]
385
+ frac_below = np.size(good) / float(np.size(data_slice[self.colname]))
386
+ frac_below = frac_below * self.scale
387
+ return frac_below
388
+
389
+
390
+ class PercentileMetric(BaseMetric):
391
+ """Find the value of a column at a given `percentile`."""
392
+
393
+ def __init__(self, col=None, percentile=90, metric_name=None, **kwargs):
394
+ if metric_name is None:
395
+ metric_name = "%.0fth%sile %s" % (percentile, "%", col)
396
+ super(PercentileMetric, self).__init__(col=col, metric_name=metric_name, **kwargs)
397
+ self.percentile = percentile
398
+
399
+ def run(self, data_slice, slice_point=None):
400
+ pval = np.percentile(data_slice[self.colname], self.percentile)
401
+ return pval
402
+
403
+
404
+ class NoutliersNsigmaMetric(BaseMetric):
405
+ """Calculate the # of visits less than n_sigma below the mean (n_sigma<0)
406
+ or more than n_sigma above the mean.
407
+ """
408
+
409
+ def __init__(self, col=None, n_sigma=3.0, metric_name=None, **kwargs):
410
+ self.n_sigma = n_sigma
411
+ self.col = col
412
+ if metric_name is None:
413
+ metric_name = "Noutliers %.1f %s" % (self.n_sigma, self.col)
414
+ super(NoutliersNsigmaMetric, self).__init__(col=col, metric_name=metric_name, **kwargs)
415
+ self.metric_dtype = "int"
416
+
417
+ def run(self, data_slice, slice_point=None):
418
+ med = np.mean(data_slice[self.colname])
419
+ std = np.std(data_slice[self.colname])
420
+ boundary = med + self.n_sigma * std
421
+ # If nsigma is positive, look for outliers above median.
422
+ if self.n_sigma >= 0:
423
+ outsiders = np.where(data_slice[self.colname] > boundary)
424
+ # Else look for outliers below median.
425
+ else:
426
+ outsiders = np.where(data_slice[self.colname] < boundary)
427
+ return len(data_slice[self.colname][outsiders])
428
+
429
+
430
+ def _rotate_angles(angles):
431
+ """Private utility for the '*Angle' Metrics below.
432
+
433
+ This takes a series of angles between 0-2pi and rotates them so that the
434
+ first angle is at 0, ensuring the biggest 'gap' is at the end of the
435
+ series.
436
+ This simplifies calculations like the 'mean' and 'rms' or 'fullrange',
437
+ removing the discontinuity at 0/2pi.
438
+ """
439
+ angleidx = np.argsort(angles)
440
+ diffangles = np.diff(angles[angleidx])
441
+ start_to_end = np.array([twopi - angles[angleidx][-1] + angles[angleidx][0]], float)
442
+ if start_to_end < -2.0 * np.pi:
443
+ raise ValueError("Angular metrics expect radians, this seems to be in degrees")
444
+ diffangles = np.concatenate([diffangles, start_to_end])
445
+ maxdiff = np.where(diffangles == diffangles.max())[0]
446
+ if len(maxdiff) > 1:
447
+ maxdiff = maxdiff[-1:]
448
+ if maxdiff == (len(angles) - 1):
449
+ rotation = angles[angleidx][0]
450
+ else:
451
+ rotation = angles[angleidx][maxdiff + 1][0]
452
+ return (rotation, (angles - rotation) % twopi)
453
+
454
+
455
+ class MeanAngleMetric(BaseMetric):
456
+ """Calculate the mean of an angular (degree) column slice.
457
+
458
+ 'MeanAngle' differs from 'Mean' in that it accounts for wraparound at 2pi.
459
+ """
460
+
461
+ def run(self, data_slice, slice_point=None):
462
+ """Calculate mean angle via unit vectors.
463
+ If unit vector 'strength' is less than 0.1,
464
+ then just set mean to 180 degrees
465
+ (as this indicates nearly uniformly distributed angles).
466
+ """
467
+ x = np.cos(np.radians(data_slice[self.colname]))
468
+ y = np.sin(np.radians(data_slice[self.colname]))
469
+ meanx = np.mean(x)
470
+ meany = np.mean(y)
471
+ angle = np.arctan2(meany, meanx)
472
+ radius = np.sqrt(meanx**2 + meany**2)
473
+ mean = angle % twopi
474
+ if radius < 0.1:
475
+ mean = np.pi
476
+ return np.degrees(mean)
477
+
478
+
479
+ class RmsAngleMetric(BaseMetric):
480
+ """Calculate the standard deviation of an angular (degrees) column slice.
481
+
482
+ 'RmsAngle' differs from 'Rms' in that it accounts for wraparound at 2pi.
483
+ """
484
+
485
+ def run(self, data_slice, slice_point=None):
486
+ rotation, angles = _rotate_angles(np.radians(data_slice[self.colname]))
487
+ return np.std(np.degrees(angles))
488
+
489
+
490
+ class FullRangeAngleMetric(BaseMetric):
491
+ """Calculate the full range of an angular (degrees) column slice.
492
+
493
+ 'FullRangeAngle' differs from 'FullRange' in that it accounts for
494
+ wraparound at 2pi.
495
+ """
496
+
497
+ def run(self, data_slice, slice_point=None):
498
+ rotation, angles = _rotate_angles(np.radians(data_slice[self.colname]))
499
+ return np.degrees(angles.max() - angles.min())
500
+
501
+
502
+ class AngularSpreadMetric(BaseMetric):
503
+ """Compute the angular spread statistic which measures
504
+ uniformity of a distribution angles accounting for 2pi periodicity.
505
+
506
+ The strategy is to first map angles into unit vectors on the unit circle,
507
+ and then compute the 2D centroid of those vectors.
508
+ A uniform distribution of angles will lead to a distribution of
509
+ unit vectors with mean that approaches the origin.
510
+ In contrast, a delta function distribution of angles leads to a
511
+ delta function distribution of unit vectors with a mean that lands on the
512
+ unit circle.
513
+
514
+ The angular spread statistic is then defined as 1 - R,
515
+ where R is the radial offset of the mean
516
+ of the unit vectors derived from the input angles.
517
+ R approaches 1 for a uniform distribution
518
+ of angles and 0 for a delta function distribution of angles.
519
+
520
+ The optional parameter `period` may be used to specificy periodicity
521
+ other than 2 pi.
522
+ """
523
+
524
+ def __init__(self, col=None, period=2.0 * np.pi, **kwargs):
525
+ # https://en.wikipedia.org/wiki/Directional_statistics
526
+ # #Measures_of_location_and_spread
527
+ # jmeyers314@gmail.com
528
+ self.period = period
529
+ super(AngularSpreadMetric, self).__init__(col=col, **kwargs)
530
+
531
+ def run(self, data_slice, slice_point=None):
532
+ # Unit vectors; unwrapped at specified period
533
+ x = np.cos(data_slice[self.colname] * 2.0 * np.pi / self.period)
534
+ y = np.sin(data_slice[self.colname] * 2.0 * np.pi / self.period)
535
+ meanx = np.mean(x)
536
+ meany = np.mean(y)
537
+ # radial offset (i.e., length) of the mean unit vector
538
+ R = np.hypot(meanx, meany)
539
+ return 1.0 - R
540
+
541
+
542
+ class RealMeanMetric(BaseMetric):
543
+ """Calculate the mean of a column with no nans or infs."""
544
+
545
+ def run(self, data_slice, slice_point=None):
546
+ return np.mean(data_slice[self.colname][np.isfinite(data_slice[self.colname])])
@@ -0,0 +1,18 @@
1
+ __all__ = ("SkySaturationMetric",)
2
+
3
+ import numpy as np
4
+
5
+ from .base_metric import BaseMetric
6
+
7
+
8
+ class SkySaturationMetric(BaseMetric):
9
+ """Check if the sky would saturate a visit in an exposure"""
10
+
11
+ def __init__(self, metric_name="SkySaturation", units="#", **kwargs):
12
+ super().__init__(col=["saturation_mag"], units=units, metric_name=metric_name, **kwargs)
13
+
14
+ def run(self, data_slice, slice_point):
15
+ # Saturation stacker returns NaN if the sky saturates
16
+ finite = np.isfinite(data_slice["saturation_mag"])
17
+ result = np.size(data_slice["saturation_mag"]) - np.size(np.where(finite)[0])
18
+ return result
@@ -0,0 +1,104 @@
1
+ __all__ = ("SNCadenceMetric",)
2
+
3
+ import numpy as np
4
+
5
+ import rubin_sim.maf.metrics as metrics
6
+
7
+
8
+ class SNCadenceMetric(metrics.BaseMetric):
9
+ """
10
+ Metric to estimate the redshift limit for faint supernovae
11
+ (x1,color) = (-2.0,0.2)
12
+
13
+ Parameters
14
+ ----------
15
+ list : `str`, optional
16
+ Name of the columns used to estimate the metric
17
+ coadd : `bool`, optional
18
+ to make "coaddition" per night (uses snStacker)
19
+ Default True
20
+ lim_sn : `class`, optional
21
+ Reference data used to estimate redshift values (interpolation)
22
+ """
23
+
24
+ def __init__(
25
+ self,
26
+ metric_name="SNCadenceMetric",
27
+ mjd_col="observationStartMJD",
28
+ ra_col="fieldRA",
29
+ dec_col="fieldDec",
30
+ filter_col="band",
31
+ m5_col="fiveSigmaDepth",
32
+ exptime_col="visitExposureTime",
33
+ night_col="night",
34
+ obsid_col="observationId",
35
+ nexp_col="numExposures",
36
+ vistime_col="visitTime",
37
+ coadd=True,
38
+ lim_sn=None,
39
+ **kwargs,
40
+ ):
41
+ self.mjd_col = mjd_col
42
+ self.m5_col = m5_col
43
+ self.filter_col = filter_col
44
+ self.ra_col = ra_col
45
+ self.dec_col = dec_col
46
+ self.exptime_col = exptime_col
47
+ self.season_col = "season"
48
+ self.night_col = night_col
49
+ self.obsid_col = obsid_col
50
+ self.nexp_col = nexp_col
51
+ self.vistime_col = vistime_col
52
+
53
+ cols = [
54
+ self.night_col,
55
+ self.m5_col,
56
+ self.filter_col,
57
+ self.mjd_col,
58
+ self.obsid_col,
59
+ self.nexp_col,
60
+ self.vistime_col,
61
+ self.exptime_col,
62
+ self.season_col,
63
+ ]
64
+ if coadd:
65
+ cols += ["coadd"]
66
+
67
+ super(SNCadenceMetric, self).__init__(col=cols, metric_name=metric_name, **kwargs)
68
+
69
+ self.filter_names = np.array(["u", "g", "r", "i", "z", "y"])
70
+
71
+ self.lim_sn = lim_sn
72
+
73
+ def run(self, data_slice, slice_point=None):
74
+ # Cut down to only include filters in correct wave range.
75
+
76
+ good_filters = np.isin(data_slice["filter"], self.filter_names)
77
+ data_slice = data_slice[good_filters]
78
+ if data_slice.size == 0:
79
+ return None
80
+ data_slice.sort(order=self.mjd_col)
81
+
82
+ r = []
83
+ field_ra = np.mean(data_slice[self.ra_col])
84
+ field_dec = np.mean(data_slice[self.dec_col])
85
+ band = np.unique(data_slice[self.filter_col])[0]
86
+
87
+ sel = data_slice
88
+ bins = np.arange(np.floor(sel[self.mjd_col].min()), np.ceil(sel[self.mjd_col].max()), 1.0)
89
+ c, b = np.histogram(sel[self.mjd_col], bins=bins)
90
+ if (c.mean() < 1.0e-8) | np.isnan(c).any() | np.isnan(c.mean()):
91
+ cadence = 0.0
92
+ else:
93
+ cadence = 1.0 / c.mean()
94
+ # time_diff = sel[self.mjd_col][1:]-sel[self.mjd_col][:-1]
95
+ r.append((field_ra, field_dec, band, np.mean(sel[self.m5_col]), cadence))
96
+
97
+ res = np.rec.fromrecords(r, names=["field_ra", "field_dec", "band", "m5_mean", "cadence_mean"])
98
+
99
+ zref = self.lim_sn.interp_griddata(res)
100
+
101
+ if np.isnan(zref):
102
+ zref = self.badval
103
+
104
+ return zref