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,288 @@
1
+ # cumulative one dimensional movie slicer
2
+ __all__ = ("MovieSlicer",)
3
+
4
+ import os
5
+ import subprocess
6
+ import warnings
7
+ from functools import wraps
8
+ from subprocess import CalledProcessError
9
+
10
+ import numpy as np
11
+
12
+ from rubin_sim.maf.stackers import ColInfo
13
+ from rubin_sim.maf.utils import optimal_bins
14
+
15
+ from .base_slicer import BaseSlicer
16
+
17
+
18
+ class MovieSlicer(BaseSlicer):
19
+ def __init__(
20
+ self,
21
+ slice_col_name=None,
22
+ slice_col_units=None,
23
+ bins=None,
24
+ bin_min=None,
25
+ bin_max=None,
26
+ bin_size=None,
27
+ verbose=True,
28
+ badval=0,
29
+ cumulative=True,
30
+ force_no_ffmpeg=False,
31
+ ):
32
+ """The 'movieSlicer' acts similarly to the OneDSlicer
33
+ (slices on one data column).
34
+ However, the data slices from the movieSlicer are intended to be
35
+ fed to another slicer, which then
36
+ (together with a set of Metrics) calculates metric values +
37
+ plots at each slice created by the movieSlicer.
38
+ The job of the movieSlicer is to track those slices and
39
+ put them together into a movie.
40
+
41
+ 'slice_col_name' is the name of the data column to use for slicing.
42
+ 'slice_col_units' lets the user set the units (for plotting purposes)
43
+ of the slice column.
44
+ 'bins' can be a numpy array with the binpoints for sliceCol
45
+ or a single integer value
46
+ (if a single value, this will be used as the number of bins,
47
+ together with data min/max or bin_min/max),
48
+ as in numpy's histogram function.
49
+ If 'bin_size' is used, this will override the bins value and
50
+ will be used together with the data min/max
51
+ or bin_min/Max to set the binpoint values.
52
+
53
+ Bins work like numpy histogram bins: the last 'bin' value is end
54
+ value of last bin; all bins except for last bin are half-open
55
+ ([a, b>), the last one is ([a, b]).
56
+
57
+ The movieSlicer stitches individual frames together into a movie
58
+ using ffmpeg. Thus, on instantiation it checks that ffmpeg is
59
+ available and will raise and exception if not.
60
+ This behavior can be overriden using force_no_ffmpeg = True
61
+ (in order to create a movie later perhaps).
62
+ """
63
+ # Check for ffmpeg.
64
+ if not force_no_ffmpeg:
65
+ try:
66
+ fnull = open(os.devnull, "w")
67
+ subprocess.check_call(["which", "ffmpeg"], stdout=fnull)
68
+ except CalledProcessError:
69
+ raise Exception(
70
+ "Could not find ffmpeg on the system, so will not be able to create movie."
71
+ " Use force_no_ffmpeg=True to override this error and create individual images."
72
+ )
73
+ super().__init__(verbose=verbose, badval=badval)
74
+ self.slice_col_name = slice_col_name
75
+ self.columns_needed = [slice_col_name]
76
+ self.bins = bins
77
+ self.bin_min = bin_min
78
+ self.bin_max = bin_max
79
+ self.bin_size = bin_size
80
+ self.cumulative = cumulative
81
+ if slice_col_units is None:
82
+ co = ColInfo()
83
+ self.slice_col_units = co.get_units(self.slice_col_name)
84
+ self.slicer_init = {
85
+ "slice_col_name": self.slice_col_name,
86
+ "slice_col_units": slice_col_units,
87
+ "badval": badval,
88
+ }
89
+
90
+ def setup_slicer(self, sim_data, maps=None):
91
+ """
92
+ Set up bins in slicer.
93
+ """
94
+ if self.slice_col_name is None:
95
+ raise Exception("slice_col_name was not defined when slicer instantiated.")
96
+ slice_col = sim_data[self.slice_col_name]
97
+ # Set bin min/max values.
98
+ if self.bin_min is None:
99
+ self.bin_min = slice_col.min()
100
+ if self.bin_max is None:
101
+ self.bin_max = slice_col.max()
102
+ # Give warning if bin_min = bin_max, and do something at
103
+ # least slightly reasonable.
104
+ if self.bin_min == self.bin_max:
105
+ warnings.warn(
106
+ "bin_min = bin_max (maybe your data is single-valued?). "
107
+ "Increasing bin_max by 1 (or 2*bin_size, if bin_size set)."
108
+ )
109
+ if self.bin_size is not None:
110
+ self.bin_max = self.bin_max + 2 * self.bin_size
111
+ else:
112
+ self.bin_max = self.bin_max + 1
113
+ # Set bins.
114
+ # Using bin_size.
115
+ if self.bin_size is not None:
116
+ if self.bins is not None:
117
+ warnings.warn(
118
+ "Both bin_size and bins have been set; Using bin_size %f only." % (self.bin_size)
119
+ )
120
+ self.bins = np.arange(
121
+ self.bin_min,
122
+ self.bin_max + self.bin_size / 2.0,
123
+ float(self.bin_size),
124
+ "float",
125
+ )
126
+ # Using bins value.
127
+ else:
128
+ # Bins was a sequence (np array or list)
129
+ if hasattr(self.bins, "__iter__"):
130
+ self.bins = np.sort(self.bins)
131
+ # Or bins was a single value.
132
+ else:
133
+ if self.bins is None:
134
+ self.bins = optimal_bins(slice_col, self.bin_min, self.bin_max)
135
+ nbins = int(self.bins)
136
+ self.bin_size = (self.bin_max - self.bin_min) / float(nbins)
137
+ self.bins = np.arange(
138
+ self.bin_min,
139
+ self.bin_max + self.bin_size / 2.0,
140
+ self.bin_size,
141
+ "float",
142
+ )
143
+ # Set shape / nbins to be one less than # of bins because
144
+ # last binvalue is RH edge only
145
+ self.nslice = len(self.bins) - 1
146
+ self.shape = self.nslice
147
+ # Set slice_point metadata.
148
+ self.slice_points["sid"] = np.arange(self.nslice)
149
+ self.slice_points["bins"] = self.bins
150
+ # Add metadata from maps.
151
+ self._run_maps(maps)
152
+ # Set up data slicing.
153
+ self.sim_idxs = np.argsort(sim_data[self.slice_col_name])
154
+ simFieldsSorted = np.sort(sim_data[self.slice_col_name])
155
+ # "left" values are location where simdata == bin value
156
+ # Note that this setup will place any the visits beyond
157
+ # the last bin into the last bin.
158
+ self.left = np.searchsorted(simFieldsSorted, self.bins[:-1], "left")
159
+ self.left = np.concatenate(
160
+ (
161
+ self.left,
162
+ np.array(
163
+ [
164
+ len(self.sim_idxs),
165
+ ]
166
+ ),
167
+ )
168
+ )
169
+ # Set up _slice_sim_data method for this class.
170
+ if self.cumulative:
171
+
172
+ @wraps(self._slice_sim_data)
173
+ def _slice_sim_data(islice):
174
+ """
175
+ Slice sim_data on oneD sliceCol, to
176
+ return relevant indexes for slice_point.
177
+ """
178
+ # this is the important part.
179
+ # The ids here define the pieces of data that get
180
+ # passed on to subsequent slicers
181
+ # cumulative version of 1D slicing
182
+ idxs = self.sim_idxs[0 : self.left[islice + 1]]
183
+ return {
184
+ "idxs": idxs,
185
+ "slice_point": {
186
+ "sid": islice,
187
+ "bin_left": self.bins[0],
188
+ "bin_right": self.bins[islice + 1],
189
+ },
190
+ }
191
+
192
+ setattr(self, "_slice_sim_data", _slice_sim_data)
193
+ else:
194
+
195
+ @wraps(self._slice_sim_data)
196
+ def _slice_sim_data(islice):
197
+ """
198
+ Slice sim_data on oneD sliceCol,
199
+ to return relevant indexes for slice_point.
200
+ """
201
+ idxs = self.sim_idxs[self.left[islice] : self.left[islice + 1]]
202
+ return {
203
+ "idxs": idxs,
204
+ "slice_point": {
205
+ "sid": islice,
206
+ "bin_left": self.bins[islice],
207
+ "bin_right": self.bins[islice + 1],
208
+ },
209
+ }
210
+
211
+ setattr(self, "_slice_sim_data", _slice_sim_data)
212
+
213
+ def __eq__(self, other_slicer):
214
+ """
215
+ Evaluate if slicers are equivalent.
216
+ """
217
+ if isinstance(other_slicer, MovieSlicer):
218
+ return np.array_equal(other_slicer.slice_points["bins"], self.slice_points["bins"])
219
+ else:
220
+ return False
221
+
222
+ def make_movie(
223
+ self,
224
+ outfileroot,
225
+ sliceformat,
226
+ plot_type,
227
+ fig_format,
228
+ out_dir="Output",
229
+ ips=10.0,
230
+ fps=10.0,
231
+ ):
232
+ """Takes in metric and slicer metadata and calls
233
+ ffmpeg to stitch together output files.
234
+ """
235
+ if not os.path.isdir(out_dir):
236
+ raise Exception("Cannot find output directory %s with movie input files." % (out_dir))
237
+ # make video
238
+ # ffmpeg -r 30 -i [image names - FilterColors_%03d_SkyMap.png] -r 30
239
+ # -pix_fmt yuv420p -crf 18 -preset slower outfile
240
+ callList = [
241
+ "ffmpeg",
242
+ "-r",
243
+ str(ips),
244
+ "-i",
245
+ os.path.join(
246
+ out_dir,
247
+ "%s_%s_%s.%s" % (outfileroot, sliceformat, plot_type, fig_format),
248
+ ),
249
+ "-vf",
250
+ "pad=ceil(iw/2)*2:ceil(ih/2)*2",
251
+ "-r",
252
+ str(fps),
253
+ "-pix_fmt",
254
+ "yuv420p",
255
+ "-crf",
256
+ "18",
257
+ "-preset",
258
+ "slower",
259
+ os.path.join(
260
+ out_dir,
261
+ "%s_%s_%s_%s.mp4" % (outfileroot, plot_type, str(ips), str(fps)),
262
+ ),
263
+ ]
264
+ print("Attempting to call ffmpeg with:")
265
+ print(" ".join(callList))
266
+ subprocess.check_call(callList)
267
+ # make thumbnail gif
268
+ callList = [
269
+ "ffmpeg",
270
+ "-i",
271
+ os.path.join(
272
+ out_dir,
273
+ "%s_%s_%s_%s.mp4" % (outfileroot, plot_type, str(ips), str(fps)),
274
+ ),
275
+ "-vf",
276
+ "pad=ceil(iw/2)*2:ceil(ih/2)*2",
277
+ "-t",
278
+ str(10),
279
+ "-r",
280
+ str(10),
281
+ os.path.join(
282
+ out_dir,
283
+ "%s_%s_%s_%s.gif" % (outfileroot, plot_type, str(ips), str(fps)),
284
+ ),
285
+ ]
286
+ print("converting to animated gif with:")
287
+ print(" ".join(callList))
288
+ subprocess.check_call(callList)
@@ -0,0 +1,147 @@
1
+ __all__ = ("NDSlicer",)
2
+
3
+ import itertools
4
+ import warnings
5
+ from functools import wraps
6
+
7
+ import numpy as np
8
+
9
+ from rubin_sim.maf.plots.nd_plotters import OneDSubsetData, TwoDSubsetData
10
+
11
+ from .base_slicer import BaseSlicer
12
+
13
+ # nd Slicer slices data on N columns in sim_data
14
+
15
+
16
+ class NDSlicer(BaseSlicer):
17
+ """Nd slicer (N dimensions)
18
+
19
+ Parameters
20
+ ==========
21
+ slice_col_list : `list` of `str`
22
+ Names of the data columns for slicing (e.g. 'airmass`, etc)
23
+ bins_list : `int` or `list` of `int` or `np.ndarray`, opt
24
+ Single integer (for same number of slices in each dimension)
25
+ or a list of integers (matching
26
+ slice_col_list) or list of arrays. Default 100, in all dimensions.
27
+
28
+ All bins are half-open ([a, b)).
29
+ """
30
+
31
+ def __init__(self, slice_col_list=None, bins_list=100, verbose=True):
32
+ super().__init__(verbose=verbose)
33
+ self.slice_col_list = slice_col_list
34
+ self.columns_needed = self.slice_col_list
35
+ if self.slice_col_list is not None:
36
+ self.n_d = len(self.slice_col_list)
37
+ else:
38
+ self.n_d = None
39
+ self.bins_list = bins_list
40
+ if not (isinstance(bins_list, float) or isinstance(bins_list, int)):
41
+ if len(self.bins_list) != self.n_d:
42
+ raise Exception(
43
+ "bins_list must be same length as slice_col_names, unless it is a single value"
44
+ )
45
+ self.slicer_init = {"slice_col_list": slice_col_list, "bins_list": bins_list}
46
+ self.plot_funcs = [TwoDSubsetData, OneDSubsetData]
47
+
48
+ def setup_slicer(self, sim_data, maps=None):
49
+ """Set up bins."""
50
+ # Parse input bins choices.
51
+ self.bins = []
52
+ # If we were given a single number for the binsList, convert to list.
53
+ if isinstance(self.bins_list, float) or isinstance(self.bins_list, int):
54
+ self.bins_list = [self.bins_list for c in self.slice_col_list]
55
+ # And then build bins.
56
+ for bl, col in zip(self.bins_list, self.slice_col_list):
57
+ if isinstance(bl, float) or isinstance(bl, int):
58
+ slice_col = sim_data[col]
59
+ bin_min = slice_col.min()
60
+ bin_max = slice_col.max()
61
+ if bin_min == bin_max:
62
+ warnings.warn("bin_min=bin_max for column %s: increasing bin_max by 1." % (col))
63
+ bin_max = bin_max + 1
64
+ bin_size = (bin_max - bin_min) / float(bl)
65
+ bins = np.arange(bin_min, bin_max + bin_size / 2.0, bin_size, "float")
66
+ self.bins.append(bins)
67
+ else:
68
+ self.bins.append(np.sort(bl))
69
+ self.nslice = (np.array(list(map(len, self.bins))) - 1).prod()
70
+ # Count how many bins we have total
71
+ # (not counting last 'RHS' bin values, as in oneDSlicer).
72
+ self.shape = self.nslice
73
+ # Set up slice metadata.
74
+ self.slice_points["sid"] = np.arange(self.nslice)
75
+ # Including multi-D 'leftmost' bin values
76
+ bins_for_iteration = []
77
+ for b in self.bins:
78
+ bins_for_iteration.append(b[:-1])
79
+ biniterator = itertools.product(*bins_for_iteration)
80
+ self.slice_points["bins"] = []
81
+ for b in biniterator:
82
+ self.slice_points["bins"].append(b)
83
+ # and multi-D 'leftmost' bin indexes corresponding to each sid
84
+ self.slice_points["bin_idxs"] = []
85
+ bin_ids_for_iteration = []
86
+ for b in self.bins:
87
+ bin_ids_for_iteration.append(np.arange(len(b[:-1])))
88
+ bin_id_iterator = itertools.product(*bin_ids_for_iteration)
89
+ for bidx in bin_id_iterator:
90
+ self.slice_points["bin_idxs"].append(bidx)
91
+ # Add metadata from maps.
92
+ self._run_maps(maps)
93
+ # Set up indexing for data slicing.
94
+ self.sim_idxs = []
95
+ self.lefts = []
96
+ for slice_col_name, bins in zip(self.slice_col_list, self.bins):
97
+ sim_idxs = np.argsort(sim_data[slice_col_name])
98
+ sim_fields_sorted = np.sort(sim_data[slice_col_name])
99
+ # "left" values are location where simdata == bin value
100
+ left = np.searchsorted(sim_fields_sorted, bins[:-1], "left")
101
+ left = np.concatenate(
102
+ (
103
+ left,
104
+ np.array(
105
+ [
106
+ len(sim_idxs),
107
+ ]
108
+ ),
109
+ )
110
+ )
111
+ # Add these calculated values into the class lists of
112
+ # sim_idxs and lefts.
113
+ self.sim_idxs.append(sim_idxs)
114
+ self.lefts.append(left)
115
+
116
+ @wraps(self._slice_sim_data)
117
+ def _slice_sim_data(islice):
118
+ """Slice sim_data to return relevant indexes for slice_point."""
119
+ # Identify relevant pointings in each dimension.
120
+ sim_idxs_list = []
121
+ # Translate islice into indexes in each bin dimension
122
+ bin_idxs = self.slice_points["bin_idxs"][islice]
123
+ for d, i in zip(list(range(self.n_d)), bin_idxs):
124
+ sim_idxs_list.append(set(self.sim_idxs[d][self.lefts[d][i] : self.lefts[d][i + 1]]))
125
+ idxs = list(set.intersection(*sim_idxs_list))
126
+ return {
127
+ "idxs": idxs,
128
+ "slice_point": {
129
+ "sid": islice,
130
+ "bin_left": self.slice_points["bins"][islice],
131
+ "bin_idxs": self.slice_points["bin_idxs"][islice],
132
+ },
133
+ }
134
+
135
+ setattr(self, "_slice_sim_data", _slice_sim_data)
136
+
137
+ def __eq__(self, other_slicer):
138
+ """Evaluate if grids are equivalent."""
139
+ if isinstance(other_slicer, NDSlicer):
140
+ if other_slicer.n_d != self.n_d:
141
+ return False
142
+ for i in range(self.n_d):
143
+ if not np.array_equal(other_slicer.slice_points["bins"][i], self.slice_points["bins"][i]):
144
+ return False
145
+ return True
146
+ else:
147
+ return False
@@ -0,0 +1,210 @@
1
+ __all__ = ("OneDSlicer",)
2
+
3
+ import warnings
4
+ from functools import wraps
5
+
6
+ import numpy as np
7
+
8
+ from rubin_sim.maf.plots.oned_plotters import OneDBinnedData
9
+ from rubin_sim.maf.stackers import ColInfo
10
+ from rubin_sim.maf.utils import optimal_bins
11
+
12
+ from .base_slicer import BaseSlicer
13
+
14
+
15
+ class OneDSlicer(BaseSlicer):
16
+ """OneD Slicer allows the slicing of data into bins in a single dimension.
17
+
18
+ Parameters
19
+ ----------
20
+ slice_col_name : `str`
21
+ The name of the data column to base slicing on (i.e. 'airmass', etc.)
22
+ slice_col_units : `str`, optional
23
+ Set a name for the units of the sliceCol. Used for plotting labels.
24
+ bins : np.ndarray, optional
25
+ The data will be sliced into 'bins': this can be defined as an
26
+ array here. Default None.
27
+ bin_min : `float`, optional
28
+ bin_max : `float`, optional
29
+ bin_size : `float`, optional
30
+ If bins is not defined, then bin_min/bin_max/bin_size can be chosen
31
+ to anchor the slice points.
32
+ Default None.
33
+ Priority goes: bins >> bin_min/bin_max/bin_size >> data values
34
+ (if none of the above are chosen).
35
+
36
+ Notes
37
+ -----
38
+ All bins except for the last bin are half-open ([a, b)) while the
39
+ last bin is ([a, b]).
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ slice_col_name=None,
45
+ slice_col_units=None,
46
+ bins=None,
47
+ bin_min=None,
48
+ bin_max=None,
49
+ bin_size=None,
50
+ verbose=True,
51
+ badval=0,
52
+ ):
53
+ super().__init__(verbose=verbose, badval=badval)
54
+ if slice_col_name is None:
55
+ raise ValueError("slice_col_name cannot be left None - choose a data column to group data by")
56
+ self.slice_col_name = slice_col_name
57
+ self.columns_needed = [slice_col_name]
58
+ # We could try to set up the self.bins here --
59
+ # but it's also possible that
60
+ # these bin_min/max/size values have not been set and
61
+ # should just be set from the data.
62
+ self.bins = bins
63
+ self.bin_min = bin_min
64
+ self.bin_max = bin_max
65
+ self.bin_size = bin_size
66
+ # Forget binmin/max/stepsize if bins was set
67
+ if self.bins is not None:
68
+ if bin_min is not None or bin_max is not None or bin_size is not None:
69
+ warnings.warning(
70
+ f"Both bins and one of the bin_min/bin_max/bin_size was specified. "
71
+ f"Using bins ({self.bins} values only."
72
+ )
73
+ self.bin_min = None
74
+ self.bin_max = None
75
+ self.bin_size = None
76
+ # Set the column units
77
+ if slice_col_units is not None:
78
+ self.slice_col_units = slice_col_units
79
+ # Try to determine the column units
80
+ else:
81
+ co = ColInfo()
82
+ self.slice_col_units = co.get_units(self.slice_col_name)
83
+ # Set slicer re-initialize values and default plotFunction
84
+ self.slicer_init = {
85
+ "slice_col_name": self.slice_col_name,
86
+ "slice_col_units": slice_col_units,
87
+ "badval": badval,
88
+ "bin_min": self.bin_min,
89
+ "bin_max": self.bin_max,
90
+ "bin_size": self.bin_size,
91
+ "bins": self.bins,
92
+ }
93
+ self.plot_funcs = [
94
+ OneDBinnedData,
95
+ ]
96
+
97
+ def setup_slicer(self, sim_data, maps=None):
98
+ """Set up bins in slicer.
99
+
100
+ This happens AFTER sim_data is defined,
101
+ thus typically in the MetricBundleGroup.
102
+ This maps data into the bins;
103
+ it's not a good idea to reuse a OneDSlicer as a result.
104
+ """
105
+ if "bins" in self.slice_points:
106
+ warning_msg = "Warning: this OneDSlicer was already set up once. "
107
+ warning_msg += (
108
+ "Re-setting up a OneDSlicer is unpredictable; at the very least, it "
109
+ "will change the mapping of the simulated data into the data slices. "
110
+ "A safer choice is to use a separate OneDSlicer for each MetricBundle."
111
+ )
112
+ warnings.warn(warning_msg)
113
+ slice_col = sim_data[self.slice_col_name]
114
+ # Set bins from data or specified values,
115
+ # if they were previously defined.
116
+ if self.bins is None:
117
+ # Set bin min/max values (could have been set in __init__)
118
+ if self.bin_min is None:
119
+ self.bin_min = np.nanmin(slice_col)
120
+ if self.bin_max is None:
121
+ self.bin_max = np.nanmax(slice_col)
122
+ # Give warning if bin_min = bin_max,
123
+ # and do something at least slightly reasonable.
124
+ if self.bin_min == self.bin_max:
125
+ warnings.warn(
126
+ "bin_min = bin_max (maybe your data is single-valued?). "
127
+ "Increasing bin_max by 1 (or 2*bin_size, if bin_size was set)."
128
+ )
129
+ if self.bin_size is not None:
130
+ self.bin_max = self.bin_max + 2 * self.bin_size
131
+ else:
132
+ self.bin_max = self.bin_max + 1
133
+ if self.bin_size is None:
134
+ bins = optimal_bins(slice_col, self.bin_min, self.bin_max)
135
+ nbins = np.round(bins)
136
+ self.bin_size = (self.bin_max - self.bin_min) / float(nbins)
137
+ # Set bins
138
+ self.bins = np.arange(self.bin_min, self.bin_max + self.bin_size / 2.0, self.bin_size, "float")
139
+ # nslice is used to stop iteration and should
140
+ # reflect the usable length of the bins
141
+ self.nslice = len(self.bins) - 1
142
+ # and "shape" refers to the length of the datavalues,
143
+ # and should be one less than # of bins because last
144
+ # binvalue is RH edge only
145
+ self.shape = self.nslice
146
+ # Set slice_point metadata.
147
+ self.slice_points["sid"] = np.arange(self.nslice)
148
+ self.slice_points["bins"] = self.bins
149
+ # Add metadata from map if needed.
150
+ self._run_maps(maps)
151
+
152
+ indxs = np.argsort(sim_data[self.slice_col_name])
153
+ data_sorted = sim_data[self.slice_col_name][indxs]
154
+
155
+ # Setting up slices such that left_edge <= data < right_edge
156
+ # in each slice.
157
+ left = np.searchsorted(data_sorted, self.bins[0:-1], "left")
158
+ right = np.searchsorted(data_sorted, self.bins[1:], "left")
159
+
160
+ self.sim_idxs = [indxs[le:ri] for le, ri in zip(left, right)]
161
+
162
+ # Set up _slice_sim_data method for this class.
163
+ @wraps(self._slice_sim_data)
164
+ def _slice_sim_data(islice):
165
+ """Slice sim_data on oneD sliceCol, to return relevant
166
+ indexes for slice_point.
167
+ """
168
+ idxs = self.sim_idxs[islice]
169
+ bin_left = self.bins[islice]
170
+ bin_right = self.bins[islice + 1]
171
+ return {
172
+ "idxs": idxs,
173
+ "slice_point": {
174
+ "sid": islice,
175
+ "bin_left": bin_left,
176
+ "bin_right": bin_right,
177
+ },
178
+ }
179
+
180
+ setattr(self, "_slice_sim_data", _slice_sim_data)
181
+
182
+ def __eq__(self, other_slicer):
183
+ """Evaluate if slicers are equivalent."""
184
+ result = False
185
+ if isinstance(other_slicer, OneDSlicer):
186
+ if self.slice_col_name == other_slicer.slice_col_name:
187
+ # If slicer restored from disk or setup,
188
+ # then 'bins' in slice_points dict.
189
+ # This is preferred method to see if slicers are equal.
190
+ if ("bins" in self.slice_points) & ("bins" in other_slicer.slice_points):
191
+ result = np.array_equal(other_slicer.slice_points["bins"], self.slice_points["bins"])
192
+ # However, before we 'setup' the slicer with data,
193
+ # the slicers could be equivalent.
194
+ else:
195
+ if (self.bins is not None) and (other_slicer.bins is not None):
196
+ result = np.array_equal(self.bins, other_slicer.bins)
197
+ elif (
198
+ (self.bin_size is not None)
199
+ and (self.bin_min is not None) & (self.bin_max is not None)
200
+ and (other_slicer.bin_size is not None)
201
+ and (other_slicer.bin_min is not None)
202
+ and (other_slicer.bin_max is not None)
203
+ ):
204
+ if (
205
+ (self.bin_size == other_slicer.bin_size)
206
+ and (self.bin_min == other_slicer.bin_min)
207
+ and (self.bin_max == other_slicer.bin_max)
208
+ ):
209
+ result = True
210
+ return result