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,710 @@
1
+ """Summary metric plotting functions."""
2
+
3
+ __all__ = (
4
+ "normalize_metric_summaries",
5
+ "plot_run_metric",
6
+ "plot_run_metric_mesh",
7
+ "plot_run_metric_uncert",
8
+ "find_family_lines",
9
+ )
10
+
11
+ # imports
12
+ import warnings
13
+
14
+ import colorcet
15
+ import cycler
16
+ import matplotlib.pyplot as plt
17
+ import numpy as np
18
+ import pandas as pd
19
+
20
+ # constants
21
+
22
+ RUN_COL_NAMES = ["run", "OpsimRun", "run_name"]
23
+ METRIC_COL_NAMES = ["metric"]
24
+
25
+ # exception classes
26
+
27
+ # interface functions
28
+
29
+
30
+ def normalize_metric_summaries(
31
+ baseline_run,
32
+ summary,
33
+ metric_subsets=None,
34
+ ):
35
+ """Create a normalized `pandas.DataFrame` of metric summary values.
36
+
37
+ Parameters
38
+ ----------
39
+ baseline_run : `str` or `list` of `str
40
+ The name of the run that defines a normalized value of 1.
41
+ If a list is provided, the median value of each metric across that
42
+ list is used as the reference.
43
+ summary : `pandas.DataFrame`
44
+ The summary metrics to normalize (as returned by
45
+ `get_metric_summaries`)
46
+ metric_subsets : `pandas.DataFrame`
47
+ Metric metadata as returned by `archive.get_metric_subsets`
48
+
49
+ Returns
50
+ -------
51
+ norm_summary : `pandas.DataFrame`
52
+ Metric summary values are returned in a `pandas.DataFrame`, with each
53
+ column providing the metrics for one run, and each row the values for
54
+ one metric. The metric names constitute the columns, and the
55
+ index names are the canonical run names.
56
+ Values of 1 indicate metric values that match that of the baseline,
57
+ differences with with indicate fractional improvement (if > 1) or
58
+ degradation (if < 1).
59
+ """
60
+
61
+ # If the DataFrame is transposed but the axes are properly
62
+ # labeled, just fix it.
63
+ cols_are_runs = summary.columns.name in RUN_COL_NAMES
64
+ rows_are_metrics = summary.index.name in METRIC_COL_NAMES
65
+ if cols_are_runs or rows_are_metrics:
66
+ summary = summary.T
67
+
68
+ runs = summary.index.values
69
+
70
+ # Use only those metrics present both in the
71
+ # summary and metrics sets dataframe
72
+ if metric_subsets is None:
73
+ summary = summary.copy()
74
+ used_metrics = summary.columns.values
75
+ else:
76
+ used_metrics = [s for s in summary.columns.values if s in metric_subsets.metric.values]
77
+ summary = summary.loc[:, used_metrics].copy()
78
+
79
+ if summary.columns.name is None:
80
+ summary.rename_axis(columns="metric", inplace=True)
81
+
82
+ if summary.index.name in [None] + RUN_COL_NAMES:
83
+ summary.rename_axis("run", inplace=True)
84
+
85
+ # Get rid of duplicate metrics and runs
86
+ summary = summary.T.groupby("metric").first().T.groupby("run").first()
87
+
88
+ # And now create a line just for "baseline" --
89
+ # if baseline_run is >1, this is created from the median values
90
+ # per metric of those runs
91
+ # Make up a nonsense name for the reference, that is not currently
92
+ # in the summary dataframe
93
+ baseline_comparison = "bbb"
94
+ while baseline_comparison in summary.index:
95
+ baseline_comparison += "b"
96
+
97
+ if isinstance(summary.loc[baseline_run], pd.DataFrame):
98
+ summary.loc[baseline_comparison] = summary.loc[baseline_run].median(axis="rows")
99
+ else:
100
+ summary.loc[baseline_comparison] = summary.loc[baseline_run]
101
+
102
+ if metric_subsets is None:
103
+ # If no invert/mag - just do simple normalization (1 + (x-0)/x0)
104
+ norm_summary = 1 + (summary.loc[:, :].sub(summary.loc[baseline_comparison, :], axis="columns")).div(
105
+ summary.loc[baseline_comparison, :], axis="columns"
106
+ )
107
+ else:
108
+ # Reindex metric set and remove duplicates or non-available metrics
109
+ metric_names = [n for n in metric_subsets.index.names if not n == "metric"]
110
+ metric_subsets = (
111
+ metric_subsets.reset_index(metric_names)
112
+ .groupby(level="metric")
113
+ .first()
114
+ .loc[used_metrics, :]
115
+ .copy()
116
+ )
117
+
118
+ norm_summary = pd.DataFrame(
119
+ columns=summary.columns,
120
+ index=summary.index,
121
+ dtype="float",
122
+ )
123
+
124
+ # Direct metrics are those that are neither inverted,
125
+ # nor compared as magnitudes
126
+ # direct = 1 + (value - norm) / norm == value / norm
127
+ direct = ~np.logical_or(metric_subsets["invert"], metric_subsets["mag"])
128
+ norm_summary.loc[:, direct] = summary.loc[:, direct]
129
+
130
+ # invert = 1 + (1/value - 1/norm) / (1/norm) == norm / value
131
+ norm_summary.loc[:, metric_subsets["invert"]] = 1.0 / summary.loc[:, metric_subsets["invert"]]
132
+
133
+ # mag = 1 + (1+value-norm - (1+norm-norm)) / (1+norm-norm)
134
+ # == 1 + (value - norm)
135
+ norm_summary.loc[:, metric_subsets["mag"]] = 1.0 + summary.loc[
136
+ :,
137
+ metric_subsets["mag"],
138
+ ].subtract(summary.loc[baseline_comparison, metric_subsets["mag"]], axis="columns")
139
+
140
+ # Some metrics can be both inverted and magnitudes (eg rms mag values)
141
+ both = np.logical_and(metric_subsets["invert"], metric_subsets["mag"])
142
+ # both = 1 + (1-(value-norm) - (1-(norm-norm))) / (1-(norm-norm))
143
+ # == norm - value
144
+ norm_summary.loc[:, both] = 1.0 - summary.loc[:, both].subtract(
145
+ summary.loc[baseline_comparison, both], axis="columns"
146
+ )
147
+
148
+ # Turn the values above into the fractional difference
149
+ # compared with the baseline
150
+ norm_summary.loc[:, :] = 1 + (
151
+ norm_summary.loc[:, :].sub(norm_summary.loc[baseline_comparison, :], axis="columns")
152
+ ).div(norm_summary.loc[baseline_comparison, :], axis="columns")
153
+
154
+ # Set the index name
155
+ norm_summary.columns.name = "metric"
156
+ norm_summary.index.name = "run"
157
+
158
+ # Make sure we return the rows and metrics in the original order
159
+ norm_summary = norm_summary.loc[runs, used_metrics]
160
+
161
+ return norm_summary
162
+
163
+
164
+ def plot_run_metric(
165
+ summary,
166
+ baseline_run=None,
167
+ vertical_quantity="run",
168
+ horizontal_quantity="value",
169
+ run_label_map=None,
170
+ metric_label_map=None,
171
+ metric_subset=None,
172
+ ax=None,
173
+ cmap=colorcet.glasbey_hv,
174
+ linestyles=None,
175
+ markers=["o"],
176
+ shade_fraction=0.05,
177
+ ):
178
+ """Plot normalized metric values as colored points on a cartesian plane.
179
+
180
+ Parameters
181
+ ----------
182
+ summary : `pandas.DataFrame`
183
+ Values to be plotted. Should only include runs and metrics that
184
+ should actually appear on the plot.
185
+ baseline_run : `str`
186
+ Name of the run to use as the baseline for normalization (see
187
+ (archive.normalize_metric_summaries).
188
+ vertical_quantity : {'run', 'metric', 'value'}
189
+ Should the run, metric name, or metric value be mapped onto the y axis?
190
+ horizontal_quantity : {'run', 'metric', 'value'}
191
+ Should the run, metric name, or metric value be mapped onto the x axis?
192
+ vwidth : `float`
193
+ The width of the plot, in normalized metrics summary units.
194
+ (The limits of the x axis will be 1-vwidth/2 and 1+width/2).
195
+ run_label_map : mapping
196
+ A python `mapping` between canonical run names and run labels as they
197
+ should appear on plot labels. Use of this option is discouraged,
198
+ because it makes it harder to match plots to data.
199
+ run_label_map could be created by
200
+ archive.get_runs().loc[these_runs]['brief']
201
+ metric_label_map : mapping
202
+ A python `mapping` between canonical metric names and metric labels
203
+ as they should appear on plot labels. Use this option carefully,
204
+ because it makes it harder to match plots to metric calculation code..
205
+ metric_label_map could be equivalent to metric_subset['short_name']
206
+ metric_subset : `pandas.DataFrame`
207
+ Metric metadata as returned by `archive.get_metric_subsets`
208
+ ax : `matplotlib.axes.Axes`
209
+ The axes on which to plot the data.
210
+ cmap : `matplotlib.colors.ColorMap`
211
+ The color map to use for point colors.
212
+ linestyles : `list`
213
+ A list of matplotlib linestyles to use to connect the lines
214
+ markers : `list`, opt
215
+ A list of matplotlib markers to use to represent the points
216
+ shade_fraction : `float`, opt
217
+ Add a red/green shading to the plot, starting at 1 +/- shade_fraction.
218
+ Set to 0 or None for no shading.
219
+
220
+ Returns
221
+ -------
222
+ fig : `matplotlib.figure.Figure`
223
+ The plot figure.
224
+ ax : `matplotilb.axes.Axes`
225
+ The plot axes.
226
+
227
+
228
+ The run order and metric order (imposed into the summary dataframe
229
+ passed here as `summary`) are important and preserved in the plot.
230
+ These should be set in the (subset) `summary` dataframe
231
+ passed here; the metric_subset is available, but used for
232
+ normalization and plot styling.
233
+ """
234
+
235
+ # If the metric sets we are passed has a multilevel index,
236
+ # get rid of the levels we do not need.
237
+ if metric_subset is not None and metric_subset.index.nlevels > 1:
238
+ extra_levels = list(set(metric_subset.index.names) - set(["metric"]))
239
+ metric_subset = metric_subset.droplevel(extra_levels).groupby(level="metric").first()
240
+
241
+ # Mark whether we have a default, or whether
242
+ # one was specified
243
+ has_linestyle_arg = linestyles is not None
244
+ if not has_linestyle_arg:
245
+ linestyles = [""]
246
+
247
+ quantities = set(["run", "metric", "value"])
248
+ assert horizontal_quantity in quantities
249
+ assert vertical_quantity in quantities
250
+ assigned_quantities = set([horizontal_quantity, vertical_quantity])
251
+ color_quantity = (quantities - assigned_quantities).pop()
252
+
253
+ # Normalize the summary values, if a baseline was specified
254
+ norm_summary = (
255
+ (
256
+ summary.rename_axis(index="run", columns="metric").copy()
257
+ if baseline_run is None
258
+ else normalize_metric_summaries(baseline_run, summary, metric_subsets=metric_subset)
259
+ )
260
+ .stack(future_stack=True)
261
+ .rename("value")
262
+ .reset_index()
263
+ .rename(columns={"OpsimRun": "run"})
264
+ )
265
+ # Pull original order for metric & runs from summary
266
+ run_order = summary.index.values
267
+ metric_order = summary.columns.values
268
+ if run_label_map is not None:
269
+ run_order = [run_label_map[r] for r in run_order]
270
+ norm_summary["run"] = norm_summary["run"].map(run_label_map)
271
+ if metric_label_map is not None:
272
+ metric_order = [metric_label_map[m] for m in metric_order]
273
+ norm_summary["metric"] = norm_summary["metric"].map(metric_label_map)
274
+ # Create this_metric_subset - equivalent to metric_subset
275
+ # but with updated names.
276
+ if metric_subset is not None:
277
+ this_metric_subset = (
278
+ metric_subset.drop(columns=["metric"])
279
+ .assign(metric=metric_subset["metric"].map(metric_label_map))
280
+ .set_index("metric", drop=False)
281
+ )
282
+ else:
283
+ this_metric_subset = None
284
+ else:
285
+ this_metric_subset = metric_subset
286
+
287
+ plot_df = pd.DataFrame(
288
+ {
289
+ "x": norm_summary[horizontal_quantity],
290
+ "y": norm_summary[vertical_quantity],
291
+ }
292
+ )
293
+
294
+ if color_quantity == "value":
295
+ warnings.warn("plot_run_metric_mesh is probably a better choice")
296
+
297
+ # turn the continuous metric value into a categorical one
298
+ if baseline_run is None:
299
+ # Not normalized, so we have no idea how to scale values.
300
+ # Just let pandas create 7 bins.
301
+ bins = 8
302
+ else:
303
+ bins = (-np.inf, 0, 0.8, 0.95, 1.05, 1.2, 2, np.inf)
304
+
305
+ plot_df["color"] = pd.cut(norm_summary[color_quantity], bins)
306
+ else:
307
+ # At this point, color has to be metric or run
308
+ plot_df["color"] = norm_summary[color_quantity]
309
+
310
+ if ax is None:
311
+ fig, ax = plt.subplots(figsize=(10, 6))
312
+ else:
313
+ fig = plt.Figure(figsize=(6, 10)) if ax is None else ax.get_figure()
314
+
315
+ # make the linestyles and symbols list the same length as cmap
316
+ try:
317
+ num_colors = len(cmap)
318
+ colors = cmap
319
+ except TypeError:
320
+ num_colors = len(cmap.colors)
321
+ colors = cmap.colors
322
+
323
+ ls_grow = int(np.ceil(num_colors / len(linestyles)))
324
+ linestyles = (list(linestyles) * ls_grow)[:num_colors]
325
+ marker_grow = int(np.ceil(num_colors / len(markers)))
326
+ markers = (list(markers) * marker_grow)[:num_colors]
327
+ ax.set_prop_cycle(
328
+ cycler.cycler(color=colors) + cycler.cycler(linestyle=linestyles) + cycler.cycler(marker=markers)
329
+ )
330
+
331
+ plot_df.set_index("color", inplace=True)
332
+
333
+ # 'color' or 'plot_df.index' is now either 'run' or 'metric'
334
+ if color_quantity == "run":
335
+ idx_order = run_order
336
+ if color_quantity == "metric":
337
+ idx_order = metric_order
338
+ for idx in idx_order: # plot_df.index.unique():
339
+ # Due to weirdness with matplotlib arg handling,
340
+ # make sure we get to pass the style argument
341
+ # as a positional argument, whether or not it is
342
+ # specified.
343
+ # Let the user know why some of their plot values might be
344
+ # disappearing
345
+ # (tends to happen if baseline value is 0 or Nan and plot_df
346
+ # being normalized)
347
+ if vertical_quantity == "value" and np.isinf(plot_df.loc[idx, "y"]).any():
348
+ warnings.warn(f"There are infinite values in the plot of {idx}.")
349
+ if horizontal_quantity == "value" and np.isinf(plot_df.loc[idx, "x"]).any():
350
+ warnings.warn(f"There are infinite values in the plot of {idx}.")
351
+ plot_args = [plot_df.loc[idx, "x"], plot_df.loc[idx, "y"]]
352
+ idx_label = f"{str(idx).strip()}"
353
+ if this_metric_subset is not None and idx in this_metric_subset.index:
354
+ # Set the style from the metric_subset if available
355
+ if "style" in this_metric_subset.columns:
356
+ metric_style = this_metric_subset.loc[idx, "style"]
357
+ if metric_style is not None:
358
+ plot_args.append(metric_style)
359
+ # Update the plot label if we inverted the column during
360
+ # normalization
361
+ if "invert" in this_metric_subset.columns and baseline_run is not None:
362
+ inv = this_metric_subset.loc[idx, "invert"]
363
+ if inv:
364
+ idx_label = f"1 / {idx_label}"
365
+ ax.plot(*plot_args, label=idx_label)
366
+
367
+ if vertical_quantity == "value":
368
+ # Set xlim to be exact length of number of runs
369
+ xlim_new = [0, len(summary) - 1]
370
+ ax.set_xlim(xlim_new)
371
+
372
+ if vertical_quantity == "run":
373
+ ylim_new = [0, len(summary) - 1]
374
+ ax.set_ylim(ylim_new)
375
+
376
+ if shade_fraction is not None and shade_fraction > 0:
377
+ if vertical_quantity == "value":
378
+ xlim = ax.get_xlim()
379
+ high_shade_bottom = 1 + shade_fraction
380
+ high_shade_top = ax.get_ylim()[1]
381
+ if high_shade_top > high_shade_bottom:
382
+ ax.fill_between(
383
+ xlim,
384
+ high_shade_bottom,
385
+ high_shade_top,
386
+ color="g",
387
+ alpha=0.1,
388
+ )
389
+
390
+ low_shade_top = 1 - shade_fraction
391
+ low_shade_bottom = ax.get_ylim()[0]
392
+ if low_shade_top > low_shade_bottom:
393
+ ax.fill_between(xlim, low_shade_bottom, low_shade_top, color="r", alpha=0.1)
394
+
395
+ elif horizontal_quantity == "value":
396
+ ylim = ax.get_ylim()
397
+ high_shade_left = 1 + shade_fraction
398
+ high_shade_right = ax.get_xlim()[1]
399
+ if high_shade_right > high_shade_left:
400
+ ax.fill_betweenx(
401
+ ylim,
402
+ high_shade_left,
403
+ high_shade_right,
404
+ color="g",
405
+ alpha=0.1,
406
+ )
407
+
408
+ low_shade_right = 1 - shade_fraction
409
+ low_shade_left = ax.get_xlim()[0]
410
+ if low_shade_right > low_shade_left:
411
+ ax.fill_betweenx(ylim, low_shade_left, low_shade_right, color="r", alpha=0.1)
412
+
413
+ if horizontal_quantity in ["run", "metric"]:
414
+ ax.tick_params("x", labelrotation=90)
415
+
416
+ ax.legend(bbox_to_anchor=(1.0, 1.0))
417
+ ax.grid()
418
+
419
+ return fig, ax
420
+
421
+
422
+ def plot_run_metric_mesh(
423
+ summary,
424
+ metric_subset=None,
425
+ baseline_run=None,
426
+ color_range=1,
427
+ run_label_map=None,
428
+ metric_label_map=None,
429
+ ax=None,
430
+ cmap=colorcet.cm["CET_D1A_r"],
431
+ ):
432
+ """Plot normalized metric values as colored points on a cartesian plane.
433
+
434
+ Parameters
435
+ ----------
436
+ summary : `pandas.DataFrame`
437
+ Values to be plotted. Should only include runs and metrics that
438
+ should actually appear on the plot.
439
+ baseline_run : `str`
440
+ Name of the run to use as the baseline for normalization (see
441
+ (archive.normalize_metric_summaries).
442
+ color_range : `float`
443
+ The color range of the plot, in normalized metrics summary
444
+ units. (The color range will be 1-color_range/2 and
445
+ 1+color_range/2).
446
+ run_label_map : mapping
447
+ A python `mapping` between canonical run names and run labels as they
448
+ should appear on plot labels.
449
+ metric_label_map : mapping
450
+ A python `mapping` between canonical metric names and metric labels
451
+ as they should appear on plot labels.
452
+ ax : `matplotlib.axes.Axes`
453
+ The axes on which to plot the data.
454
+ cmap : `matplotlib.colors.ColorMap`
455
+ The color map to use for point colors.
456
+ A red/blue diverging color map - CET_D1A_r or CET_D1_r
457
+ A rainbow diverging color map - CET_R3_r
458
+
459
+ Returns
460
+ -------
461
+ fig : `matplotlib.figure.Figure`
462
+ The plot figure..
463
+ ax : `matplotilb.axes.Axes`
464
+ The plot axes.
465
+
466
+ """
467
+ cols_are_runs = summary.columns.name in RUN_COL_NAMES
468
+ rows_are_metrics = summary.index.name in METRIC_COL_NAMES
469
+ if cols_are_runs or rows_are_metrics:
470
+ summary = summary.T
471
+
472
+ # Normalize the summary values, if a baseline was specified
473
+ if baseline_run is not None:
474
+ norm_summary = normalize_metric_summaries(baseline_run, summary, metric_subset)
475
+ else:
476
+ norm_summary = summary.rename_axis(index="run", columns="metric").copy()
477
+
478
+ if color_range is not None and (isinstance(color_range, float) or isinstance(color_range, int)):
479
+ vmin = 1 - color_range / 2
480
+ vmax = vmin + color_range
481
+ elif isinstance(color_range, list):
482
+ vmin = color_range[0]
483
+ vmax = color_range[1]
484
+ else:
485
+ vmin = norm_summary.min()
486
+ vmax = norm_summary.max()
487
+
488
+ norm_values = norm_summary.T.values
489
+
490
+ if ax is None:
491
+ fig, ax = plt.subplots(figsize=(6, 6))
492
+ else:
493
+ fig = plt.Figure(figsize=(6, 10)) if ax is None else ax.get_figure()
494
+
495
+ y_nums, x_nums = (
496
+ np.arange(norm_summary.shape[1] + 1),
497
+ np.arange(norm_summary.shape[0] + 1),
498
+ )
499
+ im = ax.pcolormesh(
500
+ x_nums,
501
+ y_nums,
502
+ norm_values,
503
+ vmin=vmin,
504
+ vmax=vmax,
505
+ cmap=cmap,
506
+ )
507
+
508
+ ax.set_yticks(np.arange(0.5, norm_summary.shape[1] + 0.5))
509
+ metrics = norm_summary.columns.tolist()
510
+ if metric_label_map is None:
511
+ metric_labels = metrics
512
+ else:
513
+ try:
514
+ # When there are multiple metric families specified,
515
+ # there might be duplicate elements in the
516
+ # metric_label_map. Remove the duplicates.
517
+ metric_label_map = metric_label_map[~metric_label_map.index.duplicated(keep="first")]
518
+ except AttributeError:
519
+ # if metric_label_map is a dict, it won't have
520
+ # an index attrubute, but there isn't any danger
521
+ # if duplicates either
522
+ pass
523
+
524
+ # Figure out which metrics get inverted
525
+ if baseline_run is not None and metric_subset is not None:
526
+ inverted_metrics = set(metric_subset.query("invert").metric.values)
527
+ else:
528
+ inverted_metrics = set()
529
+
530
+ metric_labels = [
531
+ f"1/{metric_label_map[m]}" if m in inverted_metrics else metric_label_map[m] for m in metrics
532
+ ]
533
+
534
+ ax.set_yticklabels(metric_labels)
535
+
536
+ ax.set_xticks(np.arange(0.5, norm_summary.shape[0] + 0.5))
537
+ runs = norm_summary.index.tolist()
538
+ if run_label_map is None:
539
+ run_labels = runs
540
+ else:
541
+ run_labels = [run_label_map[r] for r in runs]
542
+ ax.set_xticklabels(run_labels, rotation="vertical")
543
+
544
+ if baseline_run is None:
545
+ fig.colorbar(im, ax=ax, label=None)
546
+ else:
547
+ fig.colorbar(im, ax=ax, label="Fractional difference")
548
+
549
+ return fig, ax
550
+
551
+
552
+ def plot_run_metric_uncert(
553
+ summary,
554
+ uncertainty,
555
+ run_label_map=None,
556
+ metric_label_map=None,
557
+ metric_subset=None,
558
+ cmap=None,
559
+ linestyles=["-"],
560
+ markers=["."],
561
+ sep_plots=True,
562
+ ax=None,
563
+ ):
564
+ """Plot normalized metric values as colored points on a cartesian plane.
565
+
566
+ Parameters
567
+ ----------
568
+ summary : `pandas.DataFrame`
569
+ Values to be plotted. Should only include runs and metrics that
570
+ should actually appear on the plot.
571
+ uncertainty : `pandas.DataFrame`
572
+ Uncertainty values to plot on each data point.
573
+ Should match summary metric columns.
574
+ run_label_map : mapping
575
+ A python `mapping` between canonical run names and run labels as they
576
+ should appear on plot labels. Use of this option is discouraged,
577
+ because it makes it harder to match plots to data.
578
+ run_label_map could be created by
579
+ archive.get_runs().loc[these_runs]['brief']
580
+ metric_label_map : mapping
581
+ A python `mapping` between canonical metric names and metric labels
582
+ as they should appear on plot labels. Use this option carefully,
583
+ because it makes it harder to match plots to metric calculation code..
584
+ metric_label_map could be equivalent to metric_subset['short_name']
585
+ metric_subset : `pandas.DataFrame`
586
+ Metric metadata as returned by `archive.get_metric_subsets`
587
+ ax : `matplotlib.axes.Axes`
588
+ The axes on which to plot the data.
589
+ cmap : `matplotlib.colors.ColorMap`
590
+ The color map to use for point colors.
591
+ linestyles : `list`
592
+ A list of matplotlib linestyles to use to connect the lines
593
+ markers : `list`, opt
594
+ A list of matplotlib markers to use to represent the points
595
+
596
+ Returns
597
+ -------
598
+ fig : `matplotlib.figure.Figure`
599
+ The plot figure.
600
+ ax : `matplotilb.axes.Axes`
601
+ The plot axes.
602
+
603
+
604
+ The run order and metric order (imposed into the summary
605
+ dataframe passed here as `summary`) are important and preserved in the
606
+ plot. These should be set in the (subset) `summary` dataframe
607
+ passed here; the metric_subset is available, but used for 'invert'
608
+ and plot styling and alternate labels.
609
+ """
610
+
611
+ # If the metric sets we are passed has a multilevel index,
612
+ # get rid of the levels we do not need.
613
+ if metric_subset is not None and metric_subset.index.nlevels > 1:
614
+ extra_levels = list(set(metric_subset.index.names) - set(["metric"]))
615
+ metric_subset = metric_subset.droplevel(extra_levels).groupby(level="metric").first()
616
+
617
+ # Pull original order for metric & runs from summary
618
+ run_order = summary.index.values
619
+ metric_order = summary.columns.values
620
+ if run_label_map is not None:
621
+ run_order = [run_label_map[r] for r in run_order]
622
+ if metric_label_map is not None:
623
+ metric_order = [metric_label_map[m] for m in metric_order]
624
+
625
+ if ax is None:
626
+ fig, ax = plt.subplots(figsize=(10, 6))
627
+ else:
628
+ fig = ax.get_figure()
629
+
630
+ if cmap is None:
631
+ cmap = colorcet.glasbey_hv
632
+ cmap_default = True
633
+ else:
634
+ cmap_default = False
635
+ # make the linestyles and symbols list the same length as cmap, for cycler
636
+ try:
637
+ num_colors = len(cmap)
638
+ colors = cmap
639
+ except TypeError:
640
+ num_colors = len(cmap.colors)
641
+ colors = cmap.colors
642
+ ls_grow = int(np.ceil(num_colors / len(linestyles)))
643
+ linestyles = (list(linestyles) * ls_grow)[:num_colors]
644
+ marker_grow = int(np.ceil(num_colors / len(markers)))
645
+ markers = (list(markers) * marker_grow)[:num_colors]
646
+
647
+ # But use styles from metric_subset if available
648
+ if metric_subset is not None:
649
+ for i, m in enumerate(summary):
650
+ if m in metric_subset.index:
651
+ style = metric_subset.loc[m, "style"]
652
+ if len(style) > 1:
653
+ ci = style[0]
654
+ # Let user specify color map for override
655
+ if cmap_default:
656
+ colors[i] = ci
657
+ li = style[1]
658
+ linestyles[i] = li
659
+ else:
660
+ li = style[0:]
661
+ linestyles[i] = li
662
+
663
+ ax.set_prop_cycle(
664
+ cycler.cycler(color=colors) + cycler.cycler(linestyle=linestyles) + cycler.cycler(marker=markers)
665
+ )
666
+
667
+ for i, m in enumerate(summary):
668
+ # new plots for each metric?
669
+ if sep_plots and i > 0:
670
+ fig, ax = plt.subplots(figsize=(10, 6))
671
+ cc = [colors[i]]
672
+ ax.set_prop_cycle(
673
+ cycler.cycler(color=cc)
674
+ + cycler.cycler(linestyle=linestyles[i])
675
+ + cycler.cycler(marker=markers[i])
676
+ )
677
+ if metric_label_map is not None:
678
+ label = metric_label_map[m]
679
+ else:
680
+ label = m
681
+ ax.errorbar(run_order, summary[m], yerr=uncertainty[m], label=label)
682
+ ax.set_ylabel(label, fontsize="large")
683
+ if sep_plots:
684
+ if metric_subset is not None:
685
+ if m in metric_subset.index:
686
+ if metric_subset.loc[m, "invert"]:
687
+ ax.invert_yaxis()
688
+ ax.tick_params(axis="x", labelrotation=90, labelsize="large")
689
+ ax.grid(True, alpha=0.5)
690
+ ax.legend()
691
+
692
+ if not sep_plots:
693
+ ax.tick_params(axis="x", labelrotation=90, labelsize="large")
694
+ ax.grid(True, alpha=0.5)
695
+ ax.legend(bbox_to_anchor=(1.0, 1.0))
696
+
697
+ return fig, ax
698
+
699
+
700
+ def find_family_lines(families, family_list):
701
+ lines = []
702
+ for f in family_list:
703
+ lines += [len(families.loc[f]["run"])]
704
+ lines = np.array(lines).cumsum()
705
+ return lines
706
+
707
+
708
+ # classes
709
+
710
+ # internal functions & classes