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,118 @@
1
+ __all__ = ("AgnTimeLagMetric",)
2
+
3
+ import numpy as np
4
+
5
+ from rubin_sim.phot_utils import DustValues
6
+
7
+ from .base_metric import BaseMetric
8
+
9
+
10
+ class AgnTimeLagMetric(BaseMetric):
11
+ def __init__(
12
+ self,
13
+ lag=100,
14
+ z=1,
15
+ log=False,
16
+ threshold=2.2,
17
+ calc_type="mean",
18
+ mjd_col="observationStartMJD",
19
+ filter_col="band",
20
+ m5_col="fiveSigmaDepth",
21
+ dust=True,
22
+ g_cutoff=22.0,
23
+ r_cutoff=21.8,
24
+ metric_name=None,
25
+ **kwargs,
26
+ ):
27
+ self.lag = lag
28
+ self.z = z
29
+ self.log = log
30
+ self.threshold = threshold
31
+ self.calc_type = calc_type
32
+ self.mjd_col = mjd_col
33
+ self.filter_col = filter_col
34
+ self.m5_col = m5_col
35
+ if metric_name is None:
36
+ metric_name = f"AGN_TimeLag_{lag}_days"
37
+ self.dust = dust
38
+ self.g_cutoff = g_cutoff
39
+ self.r_cutoff = r_cutoff
40
+ if dust:
41
+ maps = ["DustMap"]
42
+ dust_properties = DustValues()
43
+ self.ax1 = dust_properties.ax1
44
+ else:
45
+ maps = []
46
+ super().__init__(
47
+ col=[self.mjd_col, self.filter_col, self.m5_col],
48
+ metric_name=metric_name,
49
+ maps=maps,
50
+ **kwargs,
51
+ )
52
+
53
+ # Calculate NQUIST value for time-lag and sampling time
54
+ # (redshift is included in formula if desired)
55
+ def _get_nquist_value(self, caden, lag, z):
56
+ return lag / ((1 + z) * caden)
57
+
58
+ def run(self, data_slice, slice_point=None):
59
+ # Dust extinction
60
+ filterlist = np.unique(data_slice[self.filter_col])
61
+ if self.dust:
62
+ m5 = np.zeros(len(data_slice))
63
+ for filtername in filterlist:
64
+ in_filt = np.where(data_slice[self.filter_col] == filtername)[0]
65
+ a_x = self.ax1[data_slice[self.filter_col][0]] * slice_point["ebv"]
66
+ m5[in_filt] = data_slice[self.m5_col][in_filt] - a_x
67
+ else:
68
+ m5 = data_slice[self.m5_col]
69
+
70
+ # Identify times which pass magnitude cuts (chosen by AGN contributors)
71
+ mjds = np.zeros(len(data_slice))
72
+ for filtername in filterlist:
73
+ in_filt = np.where(data_slice[self.filter_col] == filtername)[0]
74
+ if filtername in ("u", "i", "z", "y", "r", "g"):
75
+ mjds[in_filt] = data_slice[self.mjd_col][in_filt]
76
+ elif filtername == "g":
77
+ faint = np.where(m5[in_filt] > self.g_cutoff)
78
+ mjds[in_filt][faint] = data_slice[self.mjd_col][in_filt][faint]
79
+ elif filtername == "r":
80
+ faint = np.where(m5[in_filt] > self.r_cutoff)
81
+ mjds[in_filt][faint] = data_slice[self.mjd_col][in_filt][faint]
82
+ # Remove the visits which were not faint enough
83
+ mjds = mjds[np.where(mjds > 0)]
84
+
85
+ # Calculate differences in time between visits
86
+ mv = np.sort(mjds)
87
+ val = np.diff(mv)
88
+ # If there was only one visit; bail out now.
89
+ if len(val) == 0:
90
+ return self.badval
91
+
92
+ # Otherwise summarize the time differences as:
93
+ if self.calc_type == "mean":
94
+ val = np.mean(val)
95
+ elif self.calc_type == "min":
96
+ val = np.min(val)
97
+ elif self.calc_type == "max":
98
+ val = np.max(val)
99
+ else:
100
+ # find the greatest common divisor
101
+ val = np.rint(val).astype(int)
102
+ val = np.gcd.reduce(val)
103
+
104
+ # Will always have a value at this point
105
+ nquist = self._get_nquist_value(val, self.lag, self.z)
106
+ if self.log:
107
+ nquist = np.log(nquist)
108
+
109
+ # Threshold nquist value is 2.2,
110
+ # hence we are aiming to show values higher than threshold (2.2) value
111
+ threshold = self.threshold
112
+ if self.log:
113
+ threshold = np.log(threshold)
114
+
115
+ if nquist < threshold:
116
+ nquist = self.badval
117
+
118
+ return nquist
@@ -0,0 +1,141 @@
1
+ __all__ = ("SFUncertMetric",)
2
+
3
+ import warnings
4
+
5
+ import numpy as np
6
+ from astropy.stats import mad_std
7
+
8
+ from rubin_sim.maf.utils import m52snr
9
+ from rubin_sim.phot_utils import DustValues
10
+
11
+ from .base_metric import BaseMetric
12
+
13
+
14
+ class SFUncertMetric(BaseMetric):
15
+ """Structure Function (SF) Uncertainty Metric.
16
+ Developed on top of LogTGaps
17
+
18
+ Adapted from Weixiang Yu & Gordon Richards at:
19
+ https://github.com/RichardsGroup/
20
+ LSST_SF_Metric/blob/main/notebooks/00_SFErrorMetric.ipynb
21
+
22
+ Parameters
23
+ ----------
24
+ mag : `float`
25
+ The magnitude of the fiducial object. Default 22.
26
+ times_col : `str`
27
+ Time column name. Defaults to "observationStartMJD".
28
+ all_gaps : `bool`
29
+ Whether to use all gaps (between any two pairs of observations).
30
+ If False, only use consecutive paris. Defaults to True.
31
+ units : `str`
32
+ Unit of this metric. Defaults to "mag".
33
+ bins : `object`
34
+ An array of bin edges.
35
+ Defaults to "np.logspace(0, np.log10(3650), 16)" for a
36
+ total of 15 (final) bins.
37
+ weight : `object`
38
+ The weight assigned to each delta_t bin for deriving the final metric.
39
+ Defaults to flat weighting with sum of 1.
40
+ Should have length 1 less than bins.
41
+ snr_cut : `float`
42
+ Ignore observations below an SNR limit, default 5.
43
+ dust : `bool`
44
+ Apply dust extinction to the fiducial object magnitude. Default True.
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ mag=22,
50
+ times_col="observationStartMJD",
51
+ m5_col="fiveSigmaDepth",
52
+ all_gaps=True,
53
+ units="mag",
54
+ bins=np.logspace(0, np.log10(3650), 16),
55
+ weight=None,
56
+ metric_name="Structure Function Uncert",
57
+ snr_cut=5,
58
+ filter_col="band",
59
+ dust=True,
60
+ **kwargs,
61
+ ):
62
+ # Assign metric parameters to instance object
63
+ self.times_col = times_col
64
+ self.m5_col = m5_col
65
+ self.filter_col = filter_col
66
+ self.all_gaps = all_gaps
67
+ self.bins = bins
68
+ if weight is None:
69
+ # If weight is none, set weight so that sum over bins = 1
70
+ self.weight = np.ones(len(self.bins) - 1)
71
+ self.weight /= self.weight.sum()
72
+ self.metric_name = metric_name
73
+ self.mag = mag
74
+ self.snr_cut = snr_cut
75
+ self.dust = dust
76
+
77
+ maps = ["DustMap"]
78
+ super(SFUncertMetric, self).__init__(
79
+ col=[self.times_col, m5_col, filter_col],
80
+ metric_name=self.metric_name,
81
+ units=units,
82
+ maps=maps,
83
+ **kwargs,
84
+ )
85
+ dust_properties = DustValues()
86
+ self.ax1 = dust_properties.ax1
87
+
88
+ def run(self, data_slice, slice_point=None):
89
+ """Code executed at each healpix pixel to compute the metric"""
90
+
91
+ df = np.unique(data_slice[self.filter_col])
92
+ if np.size(df) > 1:
93
+ msg = """Running structure function on multiple filters simultaneously.
94
+ Should probably change your SQL query to limit to a single filter."""
95
+ warnings.warn(msg)
96
+ if self.dust:
97
+ a_x = self.ax1[data_slice[self.filter_col][0]] * slice_point["ebv"]
98
+ extincted_mag = self.mag + a_x
99
+ else:
100
+ extincted_mag = self.mag
101
+ snr = m52snr(extincted_mag, data_slice[self.m5_col])
102
+ bright_enough = np.where(snr > self.snr_cut)[0]
103
+
104
+ # If the total number of visits < 2, mask as bad pixel
105
+ if data_slice[bright_enough].size < 2:
106
+ return self.badval
107
+
108
+ # sort data by time column
109
+ order = np.argsort(data_slice[self.times_col][bright_enough])
110
+ times = data_slice[self.times_col][bright_enough][order]
111
+ # Using the simple Gaussian approximation for magnitude uncertainty.
112
+ mag_err = 2.5 * np.log10(1.0 + 1.0 / snr[bright_enough][order])
113
+
114
+ # check if use all gaps (between any pairs of observations)
115
+ if self.all_gaps:
116
+ # use the vectorized method
117
+ dt_matrix = times.reshape((1, times.size)) - times.reshape((times.size, 1))
118
+ dts = dt_matrix[dt_matrix > 0].flatten().astype(np.float16)
119
+ else:
120
+ dts = np.diff(times)
121
+
122
+ # bin delta_t using provided bins;
123
+ # if zero pair found at any delta_t bin,
124
+ # replace 0 with 0.01 to avoid the exploding 1/sqrt(n) term
125
+ # in this metric
126
+ result, bins = np.histogram(dts, self.bins)
127
+ new_result = np.where(result > 0, result, 0.01)
128
+
129
+ # compute photometric_error^2 population variance and population mean
130
+ # note that variance is replaced by median_absolute_deviate^2
131
+ # mean is replaced by median in this implementation to make it robust
132
+ # to outliers in simulations (e.g., dcr simulations)
133
+ err_var = mag_err**2
134
+ err_var_mu = np.median(err_var)
135
+ err_var_std = mad_std(err_var)
136
+
137
+ # compute SF error
138
+ sf_var_dt = 2 * (err_var_mu + err_var_std / np.sqrt(new_result))
139
+ sf_var_metric = np.sum(sf_var_dt * self.weight)
140
+
141
+ return sf_var_metric
@@ -0,0 +1,120 @@
1
+ __all__ = ("AreaSummaryMetric", "AreaThresholdMetric")
2
+
3
+ import healpy as hp
4
+ import numpy as np
5
+
6
+ from .base_metric import BaseMetric
7
+
8
+
9
+ class AreaSummaryMetric(BaseMetric):
10
+ """
11
+ Find the min/max of a value over the area with the 'best' results
12
+ in the metric.
13
+ This is a handy substitute for when users want to know "the WFD value".
14
+
15
+ Parameters
16
+ ----------
17
+ area : `float`
18
+ The area to consider (sq degrees)
19
+ decreasing : `bool`
20
+ Should the values be sorted by increasing or decreasing order.
21
+ For values where "larger is better", decreasing (True) is probably
22
+ what you want. For metrics where "smaller is better"
23
+ (e.g., astrometric precission), set decreasing to False.
24
+ reduce_func : None
25
+ The function to reduce the clipped values by.
26
+ Will default to min/max depending on the bool val of the decreasing
27
+ kwarg.
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ col="metricdata",
33
+ metric_name="AreaSummary",
34
+ area=18000.0,
35
+ decreasing=True,
36
+ reduce_func=None,
37
+ **kwargs,
38
+ ):
39
+ super().__init__(col=col, metric_name=metric_name, **kwargs)
40
+ self.area = area
41
+ self.decreasing = decreasing
42
+ self.reduce_func = reduce_func
43
+ self.mask_val = np.nan # Include so all values get passed
44
+ self.col = col
45
+ if reduce_func is None:
46
+ if decreasing:
47
+ self.reduce_func = np.min
48
+ else:
49
+ self.reduce_func = np.max
50
+ else:
51
+ self.reduce_func = reduce_func
52
+
53
+ def run(self, data_slice, slice_point=None):
54
+ # find out what nside we have
55
+ nside = hp.npix2nside(data_slice[self.col].size)
56
+ pix_area = hp.nside2pixarea(nside, degrees=True)
57
+ n_pix_needed = int(np.ceil(self.area / pix_area))
58
+
59
+ # Only use the finite data
60
+ data = data_slice[self.col][np.isfinite(data_slice[self.col].astype(float))]
61
+ order = np.argsort(data)
62
+ if self.decreasing:
63
+ order = order[::-1]
64
+ result = self.reduce_func(data[order][0:n_pix_needed])
65
+ return result
66
+
67
+
68
+ class AreaThresholdMetric(BaseMetric):
69
+ """Find the amount of area on the sky that meets a given threshold value.
70
+
71
+ The area per pixel is determined from the size of the metric_values
72
+ array passed to the summary metric.
73
+ This assumes that both all values are passed and that the metric was
74
+ calculated with a healpix slicer.
75
+
76
+ Parameters
77
+ ----------
78
+ upper_threshold : `float` or None
79
+ The metric value must be below this threshold to count toward the area.
80
+ Default None implies no upper bound.
81
+ lower_threshold : `float` or None, opt
82
+ The metric value must be above this threshold to count toward the area.
83
+ Default None implies no lower bound.
84
+ """
85
+
86
+ def __init__(
87
+ self,
88
+ col="metricdata",
89
+ metric_name="AreaThreshold",
90
+ upper_threshold=None,
91
+ lower_threshold=None,
92
+ **kwargs,
93
+ ):
94
+ super().__init__(col=col, metric_name=metric_name, **kwargs)
95
+ self.upper_threshold = upper_threshold
96
+ self.lower_threshold = lower_threshold
97
+ self.mask_val = np.nan # Include so all values get passed
98
+ self.col = col
99
+ self.units = "square degrees"
100
+
101
+ def run(self, data_slice, slice_point=None):
102
+ # find out what nside we have
103
+ nside = hp.npix2nside(data_slice.size)
104
+ pix_area = hp.nside2pixarea(nside, degrees=True)
105
+ # Look for pixels which match the critera for the thresholds
106
+ if self.upper_threshold is None and self.lower_threshold is None:
107
+ npix = len(data_slice)
108
+ elif self.upper_threshold is None:
109
+ npix = len(np.where(data_slice[self.col] > self.lower_threshold)[0])
110
+ elif self.lower_threshold is None:
111
+ npix = len(np.where(data_slice[self.col] < self.upper_threshold)[0])
112
+ else:
113
+ npix = len(
114
+ np.where(
115
+ (data_slice[self.col] > self.lower_threshold)
116
+ & (data_slice[self.col] < self.upper_threshold)
117
+ )[0]
118
+ )
119
+ area = pix_area * npix
120
+ return area
@@ -0,0 +1,215 @@
1
+ # Base class for metrics - defines methods which must be implemented.
2
+
3
+ __all__ = ("MetricRegistry", "BaseMetric", "ColRegistry")
4
+
5
+ import inspect
6
+ import warnings
7
+
8
+ import numpy as np
9
+
10
+ from rubin_sim.maf.stackers.get_col_info import ColInfo
11
+
12
+
13
+ class MetricRegistry(type):
14
+ """
15
+ Meta class for metrics, to build a registry of metric classes.
16
+ """
17
+
18
+ def __init__(cls, name, bases, dict):
19
+ super(MetricRegistry, cls).__init__(name, bases, dict)
20
+ if not hasattr(cls, "registry"):
21
+ cls.registry = {}
22
+ modname = inspect.getmodule(cls).__name__
23
+ if modname.startswith("rubin_sim.maf.metrics"):
24
+ modname = ""
25
+ else:
26
+ if len(modname.split(".")) > 1:
27
+ modname = ".".join(modname.split(".")[:-1]) + "."
28
+ else:
29
+ modname = modname + "."
30
+ metricname = modname + name
31
+ if metricname in cls.registry:
32
+ warnings.warn("Redefining metric %s! (there are >1 metrics with the same name)" % (metricname))
33
+ if metricname not in ["BaseMetric", "SimpleScalarMetric"]:
34
+ cls.registry[metricname] = cls
35
+
36
+ def get_class(cls, metricname):
37
+ return cls.registry[metricname]
38
+
39
+ def help(cls, doc=False):
40
+ for metricname in sorted(cls.registry):
41
+ if not doc:
42
+ print(metricname)
43
+ if doc:
44
+ print("---- ", metricname, " ----")
45
+ print(inspect.getdoc(cls.registry[metricname]))
46
+
47
+ def help_metric(cls, metricname):
48
+ print(metricname)
49
+ print(inspect.getdoc(cls.registry[metricname]))
50
+ k = inspect.signature(cls.registry[metricname])
51
+ print(" Metric __init__ keyword args and defaults: ")
52
+ print(k)
53
+
54
+
55
+ class ColRegistry:
56
+ """
57
+ ColRegistry tracks the columns needed for all metric objects
58
+ (kept internally in a set).
59
+
60
+ ColRegistry.col_set : a set of all unique columns required for metrics.
61
+ ColRegistry.dbCols : the subset of these which come from the database.
62
+ ColRegistry.stackerCols : the dictionary of [columns: stacker class].
63
+ """
64
+
65
+ col_info = ColInfo()
66
+
67
+ def __init__(self):
68
+ self.col_set = set()
69
+ self.db_set = set()
70
+ self.stacker_dict = {}
71
+
72
+ def clear_reg(self):
73
+ """Clear the registry"""
74
+ self.__init__()
75
+
76
+ def add_cols(self, col_array):
77
+ """Add the columns in ColArray into the ColRegistry.
78
+
79
+ Add the columns in col_array into the ColRegistry set (self.col_set)
80
+ and identifies their source, using ColInfo
81
+ (rubin_sim.maf.stackers.getColInfo).
82
+
83
+ Parameters
84
+ ----------
85
+ col_array : `list`
86
+ list of columns used in a metric.
87
+ """
88
+ for col in col_array:
89
+ if col is not None:
90
+ self.col_set.add(col)
91
+ source = self.col_info.get_data_source(col)
92
+ if source == self.col_info.default_data_source:
93
+ self.db_set.add(col)
94
+ else:
95
+ if col not in self.stacker_dict:
96
+ self.stacker_dict[col] = source
97
+
98
+
99
+ class BaseMetric(metaclass=MetricRegistry):
100
+ """
101
+ Base class for the metrics.
102
+ Sets up some basic functionality for the MAF framework:
103
+ after __init__ every metric will record the columns (and stackers)
104
+ it requires into the column registry, and the metric_name,
105
+ metric_dtype, and units for the metric will be set.
106
+
107
+ Parameters
108
+ ----------
109
+ col : `str` or `list` [`str`]
110
+ Names of the data columns that the metric will use.
111
+ The columns required for each metric is tracked in the ColRegistry,
112
+ and used to retrieve data from the opsim database.
113
+ Can be a single string or a list.
114
+ metric_name : `str`
115
+ Name to use for the metric (optional - if not set, will be derived).
116
+ maps : `list` [`rubin_sim.maf.maps`]
117
+ The maps that the metric will need (passed from the slicer).
118
+ units : `str`
119
+ The units for the value returned by the metric (optional - if not set,
120
+ will be derived from the ColInfo).
121
+ metric_dtype : `str`
122
+ The type of value returned by the metric - 'int', 'float', 'object'.
123
+ If not set, will be derived by introspection.
124
+ badval : `float`
125
+ The value indicating "bad" values calculated by the metric.
126
+ """
127
+
128
+ col_registry = ColRegistry()
129
+ col_info = ColInfo()
130
+
131
+ def __init__(
132
+ self,
133
+ col=None,
134
+ metric_name=None,
135
+ maps=None,
136
+ units=None,
137
+ metric_dtype=None,
138
+ badval=-666,
139
+ mask_val=None,
140
+ ):
141
+ # Turn cols into numpy array so we know
142
+ # we can iterate over the columns.
143
+ self.col_name_arr = np.array(col, copy=True, ndmin=1)
144
+ # To support simple metrics operating on a single column,
145
+ # set self.colname
146
+ if len(self.col_name_arr) == 1:
147
+ self.colname = self.col_name_arr[0]
148
+ # Add the columns to the colRegistry.
149
+ self.col_registry.add_cols(self.col_name_arr)
150
+ # Set the maps that are needed:
151
+ if maps is None:
152
+ maps = []
153
+ self.maps = maps
154
+ # Value to return if the metric can't be computed
155
+ self.badval = badval
156
+ if mask_val is not None:
157
+ self.mask_val = mask_val
158
+ # Save a unique name for the metric.
159
+ self.name = metric_name
160
+ if self.name is None:
161
+ # If none provided, construct our own from the class name
162
+ # and the data columns.
163
+ self.name = (
164
+ self.__class__.__name__.replace("Metric", "", 1)
165
+ + " "
166
+ + ", ".join(map(str, self.col_name_arr))
167
+ )
168
+ # Set up dictionary of reduce functions (may be empty).
169
+ self.reduce_funcs = {}
170
+ self.reduce_order = {}
171
+ for i, r in enumerate(inspect.getmembers(self, predicate=inspect.ismethod)):
172
+ if r[0].startswith("reduce"):
173
+ # Remove the "reduce_" part of the reduce functions names.
174
+ reducename = r[0].replace("reduce_", "", 1)
175
+ self.reduce_funcs[reducename] = r[1]
176
+ self.reduce_order[reducename] = i
177
+ # Identify type of metric return value.
178
+ if metric_dtype is not None:
179
+ self.metric_dtype = metric_dtype
180
+ elif len(list(self.reduce_funcs.keys())) > 0:
181
+ self.metric_dtype = "object"
182
+ else:
183
+ self.metric_dtype = "float"
184
+ # Set physical units, for plotting purposes.
185
+ if units is None:
186
+ units = " ".join([self.col_info.get_units(col_name) for col_name in self.col_name_arr])
187
+ if len(units.replace(" ", "")) == 0:
188
+ units = ""
189
+ self.units = units
190
+ # Add the ability to set a comment
191
+ # (that could be propagated automatically to a benchmark's
192
+ # display caption).
193
+ self.comment = None
194
+
195
+ # Default to only return one metric value per slice
196
+ self.shape = 1
197
+
198
+ def run(self, data_slice, slice_point):
199
+ """Calculate metric values.
200
+
201
+ Parameters
202
+ ----------
203
+ data_slice : `numpy.ndarray`, (N,)
204
+ Values passed to metric by the slicer, which the metric will
205
+ use to calculate metric values at each slice_point.
206
+ slice_point : `dict` or None
207
+ Dictionary of slice_point metadata passed to each metric.
208
+ E.g. the ra/dec of the healpix pixel.
209
+
210
+ Returns
211
+ -------
212
+ metricValue : `int` `float` or `object`
213
+ The metric value at each slice_point.
214
+ """
215
+ raise NotImplementedError("Please implement your metric calculation.")