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,816 @@
1
+ __all__ = ("MetricBundle", "create_empty_metric_bundle")
2
+
3
+ import os
4
+ import warnings
5
+ from copy import deepcopy
6
+
7
+ import numpy as np
8
+ import numpy.ma as ma
9
+
10
+ import rubin_sim.maf.maps as maps
11
+ import rubin_sim.maf.metrics as metrics
12
+ import rubin_sim.maf.plots as plots
13
+ import rubin_sim.maf.slicers as slicers
14
+ import rubin_sim.maf.stackers as stackers
15
+ import rubin_sim.maf.utils as utils
16
+ from rubin_sim.maf.stackers import ColInfo
17
+
18
+
19
+ def create_empty_metric_bundle():
20
+ """Create an empty metric bundle.
21
+
22
+ Returns
23
+ -------
24
+ MetricBundle : `MetricBundle`
25
+ An empty metric bundle,
26
+ configured with just the :class:`BaseMetric` and :class:`BaseSlicer`.
27
+ """
28
+ return MetricBundle(metrics.BaseMetric(), slicers.BaseSlicer(), "")
29
+
30
+
31
+ class MetricBundle:
32
+ """Define a metric bundle combination of metric, slicer, and constraint.
33
+
34
+ Parameters
35
+ ----------
36
+ metric : `~rubin_sim.maf.metric`
37
+ The Metric class to run per slice_point
38
+ slicer : `~rubin_sim.maf.slicer`
39
+ The Slicer to apply to the incoming visit data (the observations).
40
+ constraint : `str` or None, opt
41
+ A (sql-style) constraint to apply to the visit data, to apply a
42
+ broad sub-selection.
43
+ stacker_list : `list` [`~rubin_sim.maf.stacker`], opt
44
+ A list of pre-configured stackers to use to generate additional
45
+ columns per visit.
46
+ These will be generated automatically if needed, but pre-configured
47
+ versions will override these.
48
+ run_name : `str`, opt
49
+ The name of the simulation being run.
50
+ This will be added to output files and plots.
51
+ Setting it prevents file conflicts when running the same
52
+ metric on multiple simulations, and
53
+ provides a way to identify which simulation is being analyzed.
54
+ metadata : `str`, opt
55
+ A deprecated version of info_label (below).
56
+ Values set by metadata will be used for info_label.
57
+ If both are set, info_label is used.
58
+ info_label : `str` or None, opt
59
+ Information to add to the output metric data file name and plot labels.
60
+ If this is not provided, it will be auto-generated from the
61
+ constraint (if any).
62
+ Setting this provides an easy way to specify different
63
+ configurations of a metric, a slicer,
64
+ or just to rewrite your constraint into friendlier terms.
65
+ (i.e. a constraint like 'scheduler_note not like "%DD%"' can become
66
+ "non-DD" in the file name and plot labels
67
+ by specifying info_label).
68
+ plot_dict : `dict` of plotting parameters, opt
69
+ Specify general plotting parameters, such as x/y/color limits.
70
+ display_dict : `dict` of display parameters, opt
71
+ Specify parameters for show_maf web pages, such as the
72
+ side bar labels and figure captions.
73
+ Keys: 'group', 'subgroup', 'caption', and 'order'
74
+ (such as to set metrics in filter order, etc)
75
+ summary_metrics : `list` of `~rubin_sim.maf.metrics`
76
+ A list of summary metrics to run to summarize the
77
+ primary metric, such as MedianMetric, etc.
78
+ maps_list : `list` of `~rubin_sim.maf.maps`
79
+ A list of pre-configured maps to use for the metric.
80
+ This will be auto-generated if specified
81
+ by the metric class, but pre-configured versions will override these.
82
+
83
+ Notes
84
+ -----
85
+ Define the "thing" you are measuring, with a combination of
86
+ * metric (calculated per data_slice)
87
+ * slicer (how to create the data_slices)
88
+ * constraint (an optional definition of a large subset of data)
89
+
90
+ Together these define a unique combination of an opsim benchmark,
91
+ or "metric bundle".
92
+ An example would be:
93
+ a CountMetric, a HealpixSlicer, and a constraint of "filter='r'".
94
+
95
+ After the metric is evaluated at each slice_point created by the
96
+ slicer, the resulting metric values are saved in the MetricBundle.
97
+
98
+ The MetricBundle also saves the summary metrics to be used
99
+ to generate summary statistics over those metric values,
100
+ as well as the resulting summary statistic values.
101
+
102
+ Plotting parameters and display parameters (for show_maf) are saved
103
+ in the MetricBundle, as well as additional info_label such as the
104
+ opsim run name, and relevant stackers and maps
105
+ to apply when calculating the metric values.
106
+ """
107
+
108
+ col_info = ColInfo()
109
+
110
+ def __init__(
111
+ self,
112
+ metric,
113
+ slicer,
114
+ constraint=None,
115
+ stacker_list=None,
116
+ run_name="run name",
117
+ metadata=None,
118
+ info_label=None,
119
+ plot_dict=None,
120
+ display_dict=None,
121
+ summary_metrics=None,
122
+ maps_list=None,
123
+ file_root=None,
124
+ plot_funcs=None,
125
+ ):
126
+ # Set the metric.
127
+ if not isinstance(metric, metrics.BaseMetric):
128
+ raise ValueError("metric must be an rubin_sim.maf.metrics object")
129
+ self.metric = metric
130
+ # Set the slicer.
131
+ if not isinstance(slicer, slicers.BaseSlicer):
132
+ raise ValueError("slicer must be an rubin_sim.maf.slicers object")
133
+ self.slicer = slicer
134
+ # Set the constraint.
135
+ self.constraint = constraint
136
+ if self.constraint is None:
137
+ self.constraint = ""
138
+ # Set the stacker_list if applicable.
139
+ if stacker_list is not None:
140
+ if isinstance(stacker_list, stackers.BaseStacker):
141
+ self.stacker_list = [
142
+ stacker_list,
143
+ ]
144
+ else:
145
+ self.stacker_list = []
146
+ for s in stacker_list:
147
+ if s is None:
148
+ pass
149
+ else:
150
+ if not isinstance(s, stackers.BaseStacker):
151
+ raise ValueError("stacker_list must only contain rubin_sim.maf.stackers objs")
152
+ self.stacker_list.append(s)
153
+ else:
154
+ self.stacker_list = []
155
+ # Set the 'maps' to apply to the slicer, if applicable.
156
+ if maps_list is not None:
157
+ if isinstance(maps_list, maps.BaseMap):
158
+ self.known_cols = [
159
+ maps_list,
160
+ ]
161
+ else:
162
+ self.maps_list = []
163
+ for m in maps_list:
164
+ if not isinstance(m, maps.BaseMap):
165
+ raise ValueError("maps_list must only contain rubin_sim.maf.maps objects")
166
+ self.maps_list.append(m)
167
+ else:
168
+ self.maps_list = []
169
+ # If the metric knows it needs a particular map, add it to the list.
170
+ map_names = [map_name.__class__.__name__ for map_name in self.maps_list]
171
+ if hasattr(self.metric, "maps"):
172
+ for map_needed in self.metric.maps:
173
+ if isinstance(map_needed, str):
174
+ if map_needed not in map_names:
175
+ temp_map = getattr(maps, map_needed)()
176
+ self.maps_list.append(temp_map)
177
+ map_names.append(map_needed)
178
+ else:
179
+ if map_needed not in self.maps_list:
180
+ self.maps_list.append(map_needed)
181
+ map_names.append(map_needed.__class__.__name__)
182
+
183
+ # Add the summary stats, if applicable.
184
+ self.set_summary_metrics(summary_metrics)
185
+ # Set the provenance/info_label.
186
+ self._build_metadata(info_label, metadata)
187
+ # Set the run name and build the output filename base (fileRoot).
188
+ self.set_run_name(run_name)
189
+ # Reset fileRoot, if provided.
190
+ if file_root is not None:
191
+ self.file_root = file_root
192
+ # Determine the columns needed from the database.
193
+ self._find_req_cols()
194
+ # Set the plotting classes/functions.
195
+ self.set_plot_funcs(plot_funcs)
196
+ # Set the plot_dict and displayDicts.
197
+ self.plot_dict = {}
198
+ self.set_plot_dict(plot_dict)
199
+ # Update/set display_dict.
200
+ self.display_dict = {}
201
+ self.set_display_dict(display_dict)
202
+ # This is where we store the metric values and summary stats.
203
+ self.metric_values = None
204
+ self.summary_values = None
205
+
206
+ def _reset_metric_bundle(self):
207
+ """Reset all properties of MetricBundle."""
208
+ self.metric = None
209
+ self.slicer = None
210
+ self.constraint = None
211
+ self.stacker_list = []
212
+ self.summary_metrics = []
213
+ self.plot_funcs = []
214
+ self.maps_list = None
215
+ self.run_name = "run name"
216
+ self.info_label = ""
217
+ self.db_cols = None
218
+ self.file_root = None
219
+ self.plot_dict = {}
220
+ self.display_dict = {}
221
+ self.metric_values = None
222
+ self.summary_values = None
223
+
224
+ def _setup_metric_values(self):
225
+ """Set up the numpy masked array to store the metric value data."""
226
+ dtype = self.metric.metric_dtype
227
+ # Can't store healpix slicer mask values in an int array.
228
+ if dtype == "int":
229
+ dtype = "float"
230
+ if self.metric.shape == 1:
231
+ shape = self.slicer.shape
232
+ else:
233
+ shape = (self.slicer.shape, self.metric.shape)
234
+ self.metric_values = ma.MaskedArray(
235
+ data=np.empty(shape, dtype),
236
+ mask=np.zeros(shape, "bool"),
237
+ fill_value=self.slicer.badval,
238
+ )
239
+ if hasattr(self.slicer, "mask"):
240
+ self.metric_values.mask = self.slicer.mask
241
+
242
+ def _build_metadata(self, info_label, metadata=None):
243
+ """If no info_label is provided, process the constraint
244
+ (by removing extra spaces, quotes, the word 'filter' and equal signs)
245
+ to make a info_label version.
246
+ e.g. "filter = 'r'" becomes 'r'
247
+ """
248
+ # Pass the deprecated version into info_label if info_label is not set
249
+ if metadata is not None and info_label is None:
250
+ warnings.warn(
251
+ 'Use of "metadata" as a kwarg is deprecated, please use info_label instead.'
252
+ f" (copying {metadata} into info_label). "
253
+ )
254
+ info_label = metadata
255
+ if info_label is None:
256
+ self.info_label = self.constraint.replace("=", "").replace("filter", "").replace("'", "")
257
+ self.info_label = self.info_label.replace("band", "")
258
+ self.info_label = self.info_label.replace('"', "").replace(" ", " ")
259
+ self.info_label = self.info_label.strip(" ")
260
+ else:
261
+ self.info_label = info_label
262
+
263
+ def _build_file_root(self):
264
+ """
265
+ Build an auto-generated output filename root
266
+ (i.e. minus the plot type or .npz ending).
267
+ """
268
+ # Build basic version.
269
+ self.file_root = "_".join(
270
+ [
271
+ self.run_name,
272
+ self.metric.name,
273
+ self.info_label,
274
+ self.slicer.slicer_name[:4].upper(),
275
+ ]
276
+ )
277
+ # Sanitize output name if needed.
278
+ self.file_root = utils.name_sanitize(self.file_root)
279
+
280
+ def _find_req_cols(self):
281
+ """Find the columns needed by the metrics, slicers, and stackers.
282
+ If there are any additional stackers required, instantiate them
283
+ and add them to the self.stackers list.
284
+ (default stackers have to be instantiated to determine
285
+ what additional columns are needed from database).
286
+ """
287
+ # Find all the columns needed by metric and slicer.
288
+ known_cols = self.slicer.columns_needed + list(self.metric.col_name_arr)
289
+ # For the stackers already set up, find their required columns.
290
+ for s in self.stacker_list:
291
+ known_cols += s.cols_req
292
+ known_cols = set(known_cols)
293
+ # Track sources of all of these columns.
294
+ self.db_cols = set()
295
+ new_stackers = set()
296
+ for col in known_cols:
297
+ if self.col_info.get_data_source(col) == self.col_info.default_data_source:
298
+ self.db_cols.add(col)
299
+ else:
300
+ # New default stackers could come from metric/slicer
301
+ # or stackers.
302
+ new_stackers.add(self.col_info.get_data_source(col))
303
+ # Remove already-specified stackers from default list.
304
+ for s in self.stacker_list:
305
+ if s.__class__ in new_stackers:
306
+ new_stackers.remove(s.__class__)
307
+ # Loop and check if stackers are introducing new columns or stackers.
308
+ while len(new_stackers) > 0:
309
+ # Check for the sources of the columns in any of the new stackers.
310
+ new_cols = []
311
+ for s in new_stackers:
312
+ new_stacker = s()
313
+ new_cols += new_stacker.cols_req
314
+ self.stacker_list.append(new_stacker)
315
+ new_cols = set(new_cols)
316
+ new_stackers = set()
317
+ for col in new_cols:
318
+ if self.col_info.get_data_source(col) == self.col_info.default_data_source:
319
+ self.db_cols.add(col)
320
+ else:
321
+ new_stackers.add(self.col_info.get_data_source(col))
322
+ for s in self.stacker_list:
323
+ if s.__class__ in new_stackers:
324
+ new_stackers.remove(s.__class__)
325
+ # A Bit of cleanup.
326
+ # Remove 'metricdata' from dbcols if it ended here by default.
327
+ if "metricdata" in self.db_cols:
328
+ self.db_cols.remove("metricdata")
329
+ if "None" in self.db_cols:
330
+ self.db_cols.remove("None")
331
+
332
+ def set_summary_metrics(self, summary_metrics):
333
+ """Set (or reset) the summary metrics for the metricbundle.
334
+
335
+ Parameters
336
+ ----------
337
+ summary_metrics : `List` [`BaseMetric`]
338
+ Instantiated summary metrics to use to calculate
339
+ summary statistics for this metric.
340
+ """
341
+ if summary_metrics is not None:
342
+ if isinstance(summary_metrics, metrics.BaseMetric):
343
+ self.summary_metrics = [summary_metrics]
344
+ else:
345
+ self.summary_metrics = []
346
+ for s in summary_metrics:
347
+ if not isinstance(s, metrics.BaseMetric):
348
+ raise ValueError("SummaryStats must only contain rubin_sim.maf.metrics objects")
349
+ self.summary_metrics.append(s)
350
+ else:
351
+ # Add identity metric to unislicer metric values
352
+ # (to get them into resultsDB).
353
+ if self.slicer.slicer_name == "UniSlicer":
354
+ self.summary_metrics = [metrics.IdentityMetric()]
355
+ else:
356
+ self.summary_metrics = []
357
+
358
+ def set_plot_funcs(self, plot_funcs):
359
+ """Set or reset the plotting functions.
360
+
361
+ The default is to use all the plotFuncs associated with the slicer,
362
+ which is what happens in self.plot if setPlotFuncs is not used to
363
+ override self.plotFuncs.
364
+
365
+ Parameters
366
+ ----------
367
+ plot_funcs : `List` [`BasePlotter`]
368
+ The plotter or plotters to use to generate visuals for this metric.
369
+ """
370
+ if plot_funcs is not None:
371
+ if plot_funcs is isinstance(plot_funcs, plots.BasePlotter):
372
+ self.plot_funcs = [plot_funcs]
373
+ else:
374
+ self.plot_funcs = []
375
+ for p_func in plot_funcs:
376
+ if not isinstance(p_func, plots.BasePlotter):
377
+ raise ValueError(
378
+ "plotFuncs should contain instantiated " + "rubin_sim.maf.plotter objects."
379
+ )
380
+ self.plot_funcs.append(p_func)
381
+ else:
382
+ self.plot_funcs = []
383
+ for p_func in self.slicer.plot_funcs:
384
+ if isinstance(p_func, plots.BasePlotter):
385
+ self.plot_funcs.append(p_func)
386
+ else:
387
+ self.plot_funcs.append(p_func())
388
+
389
+ def set_plot_dict(self, plot_dict):
390
+ """Set or update any property of plot_dict.
391
+
392
+ Parameters
393
+ ----------
394
+ plot_dict : dict
395
+ A dictionary of plotting parameters.
396
+ The usable keywords vary with each rubin_sim.maf.plots Plotter.
397
+ """
398
+ # Don't auto-generate anything here - the plotHandler does it.
399
+ if plot_dict is not None:
400
+ self.plot_dict.update(plot_dict)
401
+ # Check for bad zp or norm_val values.
402
+ if "zp" in self.plot_dict:
403
+ if self.plot_dict["zp"] is not None:
404
+ if not np.isfinite(self.plot_dict["zp"]):
405
+ warnings.warn(
406
+ "Warning! Plot zp for %s was infinite: removing zp from plot_dict" % (self.file_root)
407
+ )
408
+ del self.plot_dict["zp"]
409
+ if "norm_val" in self.plot_dict:
410
+ if self.plot_dict["norm_val"] == 0:
411
+ warnings.warn(
412
+ "Warning! Plot normalization value for %s was 0: removing norm_val from plot_dict"
413
+ % (self.file_root)
414
+ )
415
+ del self.plot_dict["norm_val"]
416
+
417
+ def set_display_dict(self, display_dict=None, results_db=None):
418
+ """Set or update any property of display_dict.
419
+
420
+ Parameters
421
+ ----------
422
+ display_dict : `dict` of `str`
423
+ Dictionary of display parameters for show_maf.
424
+ Expected keys are: 'group', 'subgroup', 'order', 'caption'.
425
+ 'group', 'subgroup', and 'order' control where the
426
+ metric results are shown on the show_maf page.
427
+ 'caption' provides a caption to use with the metric results.
428
+ These values are saved in the results database.
429
+ results_db : `maf.ResultsDb`
430
+ A MAF results database, used to save the display parameters.
431
+ """
432
+ # Set up a temporary dictionary with the default values.
433
+ tmp_display_dict = {
434
+ "group": None,
435
+ "subgroup": None,
436
+ "order": 0,
437
+ "caption": None,
438
+ }
439
+ # Update from self.display_dict (to use existing values, if present).
440
+ tmp_display_dict.update(self.display_dict)
441
+ # And then update from any values being passed now.
442
+ if display_dict is not None:
443
+ tmp_display_dict.update(display_dict)
444
+ # Reset self.display_dict to this updated dictionary.
445
+ self.display_dict = tmp_display_dict
446
+ # If we still need to auto-generate a caption, do it.
447
+ if self.display_dict["caption"] is None:
448
+ if self.metric.comment is None:
449
+ caption = self.metric.name + " calculated on a %s basis" % (self.slicer.slicer_name)
450
+ if self.constraint != "" and self.constraint is not None:
451
+ caption += " using a subset of data selected via %s." % (self.constraint)
452
+ else:
453
+ caption += "."
454
+ else:
455
+ caption = self.metric.comment
456
+ if "zp" in self.plot_dict:
457
+ caption += " Values plotted with a zeropoint of %.2f." % (self.plot_dict["zp"])
458
+ if "norm_val" in self.plot_dict:
459
+ caption += " Values plotted with a normalization value of %.2f." % (
460
+ self.plot_dict["norm_val"]
461
+ )
462
+ self.display_dict["caption"] = caption
463
+ if results_db:
464
+ # Update the display values in the results_db.
465
+ metric_id = results_db.update_metric(
466
+ self.metric.name,
467
+ self.slicer.slicer_name,
468
+ self.run_name,
469
+ self.constraint,
470
+ self.info_label,
471
+ None,
472
+ )
473
+ results_db.update_display(metric_id, self.display_dict)
474
+
475
+ def set_run_name(self, run_name, update_file_root=True):
476
+ """Set (or reset) the run_name.
477
+ FileRoot will be updated accordingly if desired.
478
+
479
+ Parameters
480
+ ----------
481
+ run_name : `str`
482
+ Run Name, which will become part of the fileRoot.
483
+ fileRoot : `bool`, optional
484
+ Flag to update the fileRoot with the run_name.
485
+ """
486
+ self.run_name = run_name
487
+ if update_file_root:
488
+ self._build_file_root()
489
+
490
+ def write_db(self, results_db=None, outfile_suffix=None):
491
+ """Write the metric information to the results database"""
492
+ if outfile_suffix is not None:
493
+ outfile = self.file_root + "_" + outfile_suffix + ".npz"
494
+ else:
495
+ outfile = self.file_root + ".npz"
496
+ if results_db is not None:
497
+ metric_id = results_db.update_metric(
498
+ self.metric.name,
499
+ self.slicer.slicer_name,
500
+ self.run_name,
501
+ self.constraint,
502
+ self.info_label,
503
+ outfile,
504
+ )
505
+ results_db.update_display(metric_id, self.display_dict)
506
+
507
+ def write(self, comment="", out_dir=".", outfile_suffix=None, results_db=None):
508
+ """Write metric_values (and associated info_label) to disk.
509
+
510
+ Parameters
511
+ ----------
512
+ comment : `str`
513
+ Any additional comments to add to the output file
514
+ out_dir : `str`
515
+ The output directory
516
+ outfile_suffix :`str`
517
+ Additional suffix to add to the output files
518
+ (typically a numerical suffix for movies)
519
+ results_db : `maf.ResultsDb`
520
+ Results database to store information on the file output
521
+ """
522
+ if outfile_suffix is not None:
523
+ outfile = self.file_root + "_" + outfile_suffix + ".npz"
524
+ else:
525
+ outfile = self.file_root + ".npz"
526
+ self.slicer.write_data(
527
+ os.path.join(out_dir, outfile),
528
+ self.metric_values,
529
+ metric_name=self.metric.name,
530
+ sim_data_name=self.run_name,
531
+ constraint=self.constraint,
532
+ info_label=self.info_label + comment,
533
+ display_dict=self.display_dict,
534
+ plot_dict=self.plot_dict,
535
+ summary_values=self.summary_values,
536
+ )
537
+ if results_db is not None:
538
+ self.write_db(results_db=results_db)
539
+
540
+ def output_json(self):
541
+ """Set up and call the baseSlicer outputJSON method,
542
+ to output to IO string.
543
+
544
+ Returns
545
+ -------
546
+ io
547
+ IO object containing JSON data representing the metric bundle data.
548
+ """
549
+ io = self.slicer.output_json(
550
+ self.metric_values,
551
+ metric_name=self.metric.name,
552
+ simDataName=self.run_name,
553
+ info_label=self.info_label,
554
+ plot_dict=self.plot_dict,
555
+ )
556
+ return io
557
+
558
+ def read(self, filename):
559
+ """Read metric data from disk.
560
+ Overwrites any data currently in metricbundle.
561
+
562
+ Parameters
563
+ ----------
564
+ filename : `str`
565
+ The file from which to read the metric bundle data.
566
+ """
567
+ if not os.path.isfile(filename):
568
+ raise IOError("%s not found" % filename)
569
+
570
+ self._reset_metric_bundle()
571
+ # Set up a base slicer to read data (we don't know type yet).
572
+ baseslicer = slicers.BaseSlicer()
573
+ # Use baseslicer to read file.
574
+ metric_values, slicer, header = baseslicer.read_data(filename)
575
+ self.slicer = slicer
576
+ self.metric_values = metric_values
577
+ self.metric_values.fill_value = slicer.badval
578
+ # It's difficult to reinstantiate the metric object, as we don't
579
+ # know what it is necessarily -- the metric_name can be changed.
580
+ self.metric = metrics.BaseMetric()
581
+ # But, for plot label building, we do need to try to recreate the
582
+ # metric name and units.
583
+ self.metric.units = ""
584
+ if header is not None:
585
+ self.metric.name = header["metric_name"]
586
+ if "plot_dict" in header:
587
+ if "units" in header["plot_dict"]:
588
+ self.metric.units = header["plot_dict"]["units"]
589
+ self.run_name = header["sim_data_name"]
590
+ try:
591
+ self.constraint = header["constraint"]
592
+ except KeyError:
593
+ self.constraint = header["sqlconstraint"]
594
+ # and then use info_label if it's there instead
595
+ if "info_label" in header:
596
+ self.info_label = header["info_label"]
597
+ if "plot_dict" in header:
598
+ self.set_plot_dict(header["plot_dict"])
599
+ if "display_dict" in header:
600
+ self.set_display_dict(header["display_dict"])
601
+ if "summary_values" in header:
602
+ self.summary_values = header["summary_values"]
603
+ if self.info_label is None:
604
+ self._build_metadata()
605
+ path, head = os.path.split(filename)
606
+ self.file_root = head.replace(".npz", "")
607
+ self.set_plot_funcs(None)
608
+
609
+ @classmethod
610
+ def load(cls, filename):
611
+ """Create a metric bundle and load its content from disk.
612
+
613
+ Parameters
614
+ ----------
615
+ filename : `str`
616
+ The file from which to read the metric bundle data.
617
+ """
618
+ metric_bundle = cls(metrics.BaseMetric(), slicers.BaseSlicer(), "")
619
+ metric_bundle.read(filename)
620
+ return metric_bundle
621
+
622
+ def compute_summary_stats(self, results_db=None):
623
+ """Compute summary statistics on metric_values,
624
+ using summaryMetrics (metricbundle list).
625
+
626
+ Parameters
627
+ ----------
628
+ results_db : Optional[ResultsDb]
629
+ ResultsDb object to use to store the
630
+ summary statistic values on disk.
631
+ """
632
+ if self.summary_values is None:
633
+ self.summary_values = {}
634
+ if self.summary_metrics is not None:
635
+ # Build array of metric values, to use for summary statistics.
636
+ arr = self.metric_values.compressed()
637
+ rarr_std = np.empty(arr.shape, dtype=[("metricdata", arr.dtype)])
638
+ rarr_std["metricdata"] = arr
639
+ for m in self.summary_metrics:
640
+ # The summary metric colname should already be set
641
+ # to 'metricdata', but in case it's not:
642
+ m.colname = "metricdata"
643
+ summary_name = m.name.replace(" metricdata", "").replace(" None", "")
644
+ if hasattr(m, "mask_val"):
645
+ # summary metric requests to use the mask value,
646
+ # as specified by itself,
647
+ # rather than skipping masked vals.
648
+ arr = self.metric_values.filled(m.mask_val)
649
+ rarr = np.empty(arr.shape, dtype=[("metricdata", arr.dtype)])
650
+ rarr["metricdata"] = arr
651
+ else:
652
+ rarr = rarr_std
653
+ if np.size(rarr) == 0:
654
+ summary_val = self.slicer.badval
655
+ else:
656
+ summary_val = m.run(rarr)
657
+ self.summary_values[summary_name] = summary_val
658
+ # Add summary metric info to results database, if applicable.
659
+ if results_db:
660
+ metric_id = results_db.update_metric(
661
+ self.metric.name,
662
+ self.slicer.slicer_name,
663
+ self.run_name,
664
+ self.constraint,
665
+ self.info_label,
666
+ None,
667
+ )
668
+ results_db.update_summary_stat(
669
+ metric_id, summary_name=summary_name, summary_value=summary_val
670
+ )
671
+
672
+ def reduce_metric(
673
+ self,
674
+ reduce_func,
675
+ reduce_func_name=None,
676
+ reduce_plot_dict=None,
677
+ reduce_display_dict=None,
678
+ ):
679
+ """Run 'reduceFunc' (any function that operates on self.metric_values).
680
+
681
+ Typically reduceFunc will be the metric reduce functions,
682
+ as they are tailored to expect the metric_values format.
683
+ reduceDisplayDict and reducePlotDicts are displayDicts
684
+ and plotDicts to be applied to the new metricBundle.
685
+
686
+ Parameters
687
+ ----------
688
+ reduce_func : `Func`
689
+ Any function that will operate on self.metric_values
690
+ (typically metric.reduce* function).
691
+ reduce_plot_dict : `dict`, opt
692
+ Plot dictionary for the results of the reduce function.
693
+ reduce_display_dict : `dict`, opt
694
+ Display dictionary for the results of the reduce function.
695
+
696
+ Returns
697
+ -------
698
+ newmetric_bundle: `MetricBundle`
699
+ New metric bundle, inheriting info_label from this metric bundle,
700
+ but containing the new metric values calculated with
701
+ the 'reduceFunc'.
702
+ """
703
+ # Generate a name for the metric values processed by the reduceFunc.
704
+ if reduce_func_name is not None:
705
+ r_name = reduce_func_name.replace("reduce_", "")
706
+ else:
707
+ r_name = reduce_func.__name__.replace("reduce_", "")
708
+ reduce_name = self.metric.name + "_" + r_name
709
+ # Set up metricBundle to store new metric values,
710
+ # and add plot_dict/display_dict.
711
+ newmetric = deepcopy(self.metric)
712
+ newmetric.name = reduce_name
713
+ newmetric.metric_dtype = "float"
714
+ if reduce_plot_dict is not None:
715
+ if "units" in reduce_plot_dict:
716
+ newmetric.units = reduce_plot_dict["units"]
717
+ newmetric_bundle = MetricBundle(
718
+ metric=newmetric,
719
+ slicer=self.slicer,
720
+ stacker_list=self.stacker_list,
721
+ constraint=self.constraint,
722
+ info_label=self.info_label,
723
+ run_name=self.run_name,
724
+ plot_dict=None,
725
+ plot_funcs=self.plot_funcs,
726
+ display_dict=None,
727
+ summary_metrics=self.summary_metrics,
728
+ maps_list=self.maps_list,
729
+ file_root="",
730
+ )
731
+ # Build a new output file root name.
732
+ newmetric_bundle._build_file_root()
733
+ # Add existing plot_dict (except for title/xlabels etc)
734
+ # into new plot_dict.
735
+ for k, v in self.plot_dict.items():
736
+ if k not in newmetric_bundle.plot_dict:
737
+ newmetric_bundle.plot_dict[k] = v
738
+ # Update newmetric_bundle's plot dictionary with
739
+ # any set explicitly by reducePlotDict.
740
+ newmetric_bundle.set_plot_dict(reduce_plot_dict)
741
+ # Copy the parent metric's display dict into the reduce display dict.
742
+ newmetric_bundle.set_display_dict(self.display_dict)
743
+ # Set the reduce function display 'order'
744
+ # (this is set in the BaseMetric by default,
745
+ # but can be overriden in a metric).
746
+ order = newmetric.reduce_order[r_name]
747
+ newmetric_bundle.display_dict["order"] = order
748
+ # And then update the newmetric_bundle's
749
+ # display dictionary with any set
750
+ # explicitly by reduceDisplayDict.
751
+ newmetric_bundle.set_display_dict(reduce_display_dict)
752
+ # Set up new metricBundle's metric_values masked arrays,
753
+ # copying metricValue's mask.
754
+ newmetric_bundle.metric_values = ma.MaskedArray(
755
+ data=np.empty(len(self.slicer), "float"),
756
+ mask=self.metric_values.mask.copy(),
757
+ fill_value=self.slicer.badval,
758
+ )
759
+ # Fill the reduced metric data using the reduce function.
760
+ for i, (mVal, mMask) in enumerate(zip(self.metric_values.data, self.metric_values.mask)):
761
+ if not mMask:
762
+ val = reduce_func(mVal)
763
+ newmetric_bundle.metric_values.data[i] = val
764
+ if val == newmetric.badval:
765
+ newmetric_bundle.metric_values.mask[i] = True
766
+
767
+ return newmetric_bundle
768
+
769
+ def plot(self, plot_handler=None, plot_func=None, outfile_suffix=None, savefig=False):
770
+ """
771
+ Create all plots available from the slicer.
772
+ plotHandler holds the output directory info, etc.
773
+
774
+ Parameters
775
+ ----------
776
+ plot_handler : `~maf.plots.plot_handler`, opt
777
+ The plot_handler saves the output location
778
+ and results_db connection for a set of plots.
779
+ plot_func : `maf.plots.BasePlotter`, opt
780
+ Any plotter function.
781
+ If not specified, the plotters in self.plotFuncs will be used.
782
+ outfile_suffix : `str`, opt
783
+ Optional string to append to the end of the plot output files.
784
+ Useful when creating sequences of images for movies.
785
+ savefig : `bool`, opt
786
+ Flag indicating whether or not to save the figure to disk.
787
+ Default is False.
788
+
789
+ Returns
790
+ -------
791
+ made_plots : `dict`
792
+ Dictionary of plot_type:figure key/value pairs,
793
+ indicating what plots were created
794
+ and what matplotlib figures were used.
795
+ """
796
+ # Generate a plot_handler if none was set.
797
+ if plot_handler is None:
798
+ plot_handler = plots.PlotHandler(savefig=savefig)
799
+ # Make plots.
800
+ if plot_func is not None:
801
+ if isinstance(plot_func, plots.BasePlotter):
802
+ plot_func = plot_func
803
+ else:
804
+ plot_func = plot_func()
805
+
806
+ plot_handler.set_metric_bundles([self])
807
+ plot_handler.set_plot_dicts(plot_dicts=[self.plot_dict], reset=True)
808
+ made_plots = {}
809
+ if plot_func is not None:
810
+ fig = plot_handler.plot(plot_func, outfile_suffix=outfile_suffix)
811
+ made_plots[plot_func.plotType] = fig
812
+ else:
813
+ for plot_func in self.plot_funcs:
814
+ fig = plot_handler.plot(plot_func, outfile_suffix=outfile_suffix)
815
+ made_plots[plot_func.plot_type] = fig
816
+ return made_plots