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,441 @@
1
+ __all__ = ("PrestoColorKNePopMetric", "generate_presto_pop_slicer")
2
+
3
+ import os
4
+ import pickle
5
+ import warnings
6
+ from itertools import combinations
7
+
8
+ import numpy as np
9
+ import pandas as pd
10
+ from rubin_scheduler.data import get_data_dir
11
+ from rubin_scheduler.utils import SURVEY_START_MJD, uniform_sphere
12
+
13
+ import rubin_sim.maf.metrics as metrics
14
+ import rubin_sim.maf.slicers as slicers
15
+ from rubin_sim.phot_utils import DustValues
16
+
17
+ from .kne_metrics import KnLc
18
+
19
+
20
+ def radec2gal(ra, dec):
21
+ """convert from ra/dec to galactic l/b"""
22
+ from astropy import units as u
23
+ from astropy.coordinates import SkyCoord
24
+
25
+ c = SkyCoord(ra=ra, dec=dec, unit=(u.degree, u.degree))
26
+
27
+ gal_l = c.galactic.l.degree
28
+ gal_b = c.galactic.b.degree
29
+ return gal_l, gal_b
30
+
31
+
32
+ def _load_hash(
33
+ file_galactic="TotalCubeNorm_1000Obj.pkl",
34
+ file_extragalactic="TotalCubeNorm_1000Obj.pkl",
35
+ skyregion="extragalactic",
36
+ ):
37
+ """Helper function to load large hash table.
38
+
39
+ Because this is kept outside the metric attributes, it allows easy resuse.
40
+ Note that this does mean running different sky regions at the same
41
+ time may end up thrashing the data in the hash/hash table.
42
+
43
+ Parameters
44
+ ----------
45
+ skyregion : `str`
46
+ The skyregion of interst.
47
+ Only two options: 'galactic' and 'extragalactic'
48
+ filePathGalactic : `str`
49
+ File containing galactic Presto-Color phase space information
50
+ filePathExtragalactic : `str`
51
+ File containing galactic Presto-Color phase space information
52
+ """
53
+
54
+ if hasattr(_load_hash, "InfoDict"):
55
+ if skyregion == _load_hash.skyregion:
56
+ return _load_hash.InfoDict, _load_hash.HashTable
57
+
58
+ data_dir = get_data_dir()
59
+ if skyregion == "galactic":
60
+ file_path = os.path.join(data_dir, "maf", file_galactic)
61
+ elif skyregion == "extragalactic":
62
+ file_path = os.path.join(data_dir, "maf", file_extragalactic)
63
+
64
+ with open(file_path, "rb") as f:
65
+ _load_hash.InfoDict = pickle.load(f)
66
+ _load_hash.HashTable = pickle.load(f)
67
+ _load_hash.skyregion = skyregion
68
+ return _load_hash.InfoDict, _load_hash.HashTable
69
+
70
+
71
+ def generate_presto_pop_slicer(
72
+ skyregion="galactic",
73
+ t_start=1,
74
+ t_end=3652,
75
+ n_events=10000,
76
+ seed=42,
77
+ n_files=100,
78
+ d_min=10,
79
+ d_max=300,
80
+ gb_cut=20,
81
+ ):
82
+ """Generate a population of KNe events, and put the info about them
83
+ into a UserPointSlicer object
84
+
85
+ Parameters
86
+ ----------
87
+ skyregion : `str`
88
+ The skyregion of interest.
89
+ Only two options: 'galactic' and 'extragalactic'
90
+ t_start : `float`
91
+ The night to start kilonova events on (days)
92
+ t_end : `float`
93
+ The final night of kilonova events
94
+ n_events : `int`
95
+ The number of kilonova events to generate
96
+ seed : `float`
97
+ The seed passed to np.random
98
+ n_files : `int`
99
+ The number of different kilonova lightcurves to use
100
+ d_min : `float` or `int`
101
+ Minimum luminosity distance (Mpc)
102
+ d_max : `float` or `int`
103
+ Maximum luminosity distance (Mpc)
104
+
105
+ Returns
106
+ -------
107
+ kne_slicer : `~.maf.UserPointsSlicer`
108
+ """
109
+
110
+ def rndm(a, b, g, size=1):
111
+ """Power-law gen for pdf(x) proportional to x^{g-1} for a<=x<=b"""
112
+ r = np.random.random(size=size)
113
+ ag, bg = a**g, b**g
114
+ return (ag + (bg - ag) * r) ** (1.0 / g)
115
+
116
+ ra, dec = uniform_sphere(n_events, seed=seed)
117
+
118
+ # Convert ra, dec to gl, gb
119
+ gl, gb = radec2gal(ra, dec)
120
+
121
+ # Determine if the object is in the Galaxy plane
122
+ if skyregion == "galactic": # keep the galactic events
123
+ ra = ra[np.abs(gb) < gb_cut]
124
+ dec = dec[np.abs(gb) < gb_cut]
125
+ elif skyregion == "extragalactic": # keep the extragalactic events.
126
+ ra = ra[np.abs(gb) > gb_cut]
127
+ dec = dec[np.abs(gb) > gb_cut]
128
+ else:
129
+ warnings.warn("Skyregion %s not recognized, using whole sky" % skyregion)
130
+
131
+ n_events = len(ra)
132
+
133
+ peak_times = np.random.uniform(low=t_start, high=t_end, size=n_events)
134
+ file_indx = np.floor(np.random.uniform(low=0, high=n_files, size=n_events)).astype(int)
135
+
136
+ # Define the distance
137
+ distance = rndm(d_min, d_max, 4, size=n_events)
138
+
139
+ # Set up the slicer to evaluate the catalog we just made
140
+ slicer = slicers.UserPointsSlicer(ra, dec, lat_lon_deg=True, badval=0)
141
+ # Add any additional information about each object to the slicer
142
+ slicer.slice_points["peak_time"] = peak_times
143
+ slicer.slice_points["file_indx"] = file_indx
144
+ slicer.slice_points["distance"] = distance
145
+ return slicer
146
+
147
+
148
+ class PrestoColorKNePopMetric(metrics.BaseMetric):
149
+ def __init__(
150
+ self,
151
+ metric_name="KNePopMetric",
152
+ mjd_col="observationStartMJD",
153
+ m5_col="fiveSigmaDepth",
154
+ filter_col="band",
155
+ night_col="night",
156
+ pts_needed=2,
157
+ file_list=None,
158
+ mjd0=SURVEY_START_MJD,
159
+ output_lc=False,
160
+ skyregion="galactic",
161
+ thr=0.003,
162
+ **kwargs,
163
+ ):
164
+ """
165
+ Parameters
166
+ ----------
167
+ file_list : `str` or None, optional
168
+ File containing input lightcurves
169
+ mjd0 : `float`, optional
170
+ MJD of the start of the survey.
171
+ output_lc : `bool`, optional
172
+ Flag to whether or not to output lightcurve for each object.
173
+ skyregion : `str`, optional
174
+ The skyregion of interest.
175
+ Only two options: 'galactic' and 'extragalactic'
176
+ thr : `float`, optional
177
+ Threshold for "classification" of events via the Score_S
178
+ """
179
+ maps = ["DustMap"]
180
+ self.mjd_col = mjd_col
181
+ self.m5_col = m5_col
182
+ self.filter_col = filter_col
183
+ self.night_col = night_col
184
+ # Boolean variable, if True the light curve will be exported
185
+ self.output_lc = output_lc
186
+ self.thr = thr
187
+ self.skyregion = skyregion
188
+ # read in file as light curve object;
189
+ self.lightcurves = KnLc(file_list=file_list)
190
+
191
+ self.mjd0 = mjd0
192
+
193
+ dust_properties = DustValues()
194
+ self.ax1 = dust_properties.ax1
195
+
196
+ cols = [self.mjd_col, self.m5_col, self.filter_col, self.night_col]
197
+ super().__init__(col=cols, units="Detected, 0 or 1", metric_name=metric_name, maps=maps, **kwargs)
198
+
199
+ # Unused ..
200
+ self.pts_needed = pts_needed
201
+
202
+ def _presto_color_detect(self, around_peak, filters):
203
+ """Detection criteria of presto cadence:
204
+ at least three detections at two filters;
205
+
206
+ Parameters
207
+ ----------
208
+ around_peak : `np.ndarray`, (N,)
209
+ indexes corresponding to 5sigma detections
210
+ filters : `np.ndarray`, (N,)
211
+ filters in which detections happened
212
+ """
213
+ result = 1
214
+
215
+ if np.size(around_peak) < 3:
216
+ result = 0
217
+
218
+ flts, flts_count = np.unique(
219
+ filters,
220
+ return_counts=True,
221
+ )
222
+ if np.size(flts) < 2:
223
+ result = 0
224
+ elif np.max(flts_count) < 2:
225
+ # if no filters have visits larger than 2, set detection false
226
+ result = 0
227
+
228
+ return result
229
+
230
+ def _enquiry(self, hash_table, info_dict, band1, band2, d_t1, d_t2, d_mag, color):
231
+ """
232
+ Return the value in the probability cube provided the coordinates
233
+ in the Presto-color phase space of an observation triplet.
234
+
235
+ Parameters
236
+ ----------
237
+ hash_table : `np.ndarray`, (N,)
238
+ Contains the values of the 6-D Presto-color phase space
239
+ info_dict : `dict`
240
+ Contains the essential information of the hash_table abobe.
241
+ band1, band2 : `str`, `str`
242
+ The two filters that comprise the Presto-color observation triplet.
243
+ The filters are the 6 bands of LSST: u, g, r, i, z, y.
244
+ Band1 and band2 should be different.
245
+ d_t1, d_t2 : `float`, `float`
246
+ The time gaps of the Presto-color observation triplet.
247
+ d_mag : `float`
248
+ The magnitude change between from the observations of the same band
249
+ color : `float`
250
+ The difference in magnitude of observations in different bands.
251
+
252
+ hash_table and info_dict have to be loaded from premade data
253
+ Presto-color data file.
254
+ """
255
+
256
+ # if abs(d_t1) > abs(d_t1-d_t2):
257
+ # d_t1, d_t2 = d_t1-d_t2, -d_t2
258
+
259
+ if not (
260
+ info_dict["BinMag"][0] <= d_mag < info_dict["BinMag"][-1]
261
+ and info_dict["BinColor"][0] <= color < info_dict["BinColor"][-1]
262
+ ):
263
+ return 0
264
+
265
+ ind1 = info_dict["BandPairs"].index(band1 + band2)
266
+
267
+ time_pair_grid = [
268
+ info_dict["dT1s"][abs(d_t1 - info_dict["dT1s"]).argmin()],
269
+ info_dict["dT2s"][abs(d_t2 - info_dict["dT2s"]).argmin()],
270
+ ]
271
+
272
+ ind2 = np.where((info_dict["TimePairs"] == time_pair_grid).all(axis=1))[0][0]
273
+ ind3 = np.where(d_mag >= info_dict["BinMag"])[0][-1]
274
+ ind4 = np.where(color >= info_dict["BinColor"])[0][-1]
275
+
276
+ return hash_table[ind1, ind2, ind3, ind4]
277
+
278
+ def _get_score(self, result, hash_table, info_dict, thr):
279
+ """Get the score of a strategy from the Presto-color perspective.
280
+
281
+ Parameters
282
+ ----------
283
+ result : `pd.DataFrame`
284
+ Dataframe that contains the results of the observations.
285
+ The columns include
286
+ t: the time of the observation
287
+ mag: the detected magnitude
288
+ maglim: the limit fiveSigmaDepth that can be detected
289
+ filter: the filter used for the observation
290
+ hash_table : `np.ndarray`, (N,)
291
+ Contains the values of the 6-D Presto-color phase space
292
+ info_dict : `dict`
293
+ Contains the essential information of the hash_table abobe.
294
+ scoreType : `str`
295
+ Two types of scores were designed:
296
+ 'S' type involves a threshold,
297
+ 'P' type work without a threshold.
298
+ thr : `float`
299
+ The threashold need for type 'S' score.
300
+ The default value is 0.003 (3-sigma)
301
+
302
+ hash_table and info_dict have to be loaded from the premade
303
+ Presto-color data file.
304
+ """
305
+
306
+ time_lim1 = 8.125 / 24 # 8 h 7.5 min
307
+ time_lim2 = 32.25 / 24 # 32 h 15 min
308
+
309
+ detects = result[result.mag < result.maglim]
310
+
311
+ # reset index
312
+ detects = detects.reset_index(drop=True)
313
+
314
+ # Times for valid detections
315
+ ts = detects.t.values
316
+ # Find out the differences between each pair
317
+ d_ts = ts.reshape(1, len(ts)) - ts.reshape(len(ts), 1)
318
+
319
+ # The time differences should be within 32 hours (2 nights)
320
+ d_tindex0, d_tindex1 = np.where(abs(d_ts) < time_lim2)
321
+
322
+ phase_space_coords = []
323
+
324
+ # loop through the rows of the matrix of valid time differences
325
+ for ii in range(d_ts.shape[0]):
326
+ groups_of_three = np.array(
327
+ [
328
+ [ii] + list(jj)
329
+ for jj in list(combinations(d_tindex1[(d_tindex0 == ii) * (d_tindex1 > ii)], 2))
330
+ ]
331
+ )
332
+
333
+ for indices in groups_of_three:
334
+ bands = detects["filter"][indices].values
335
+
336
+ # print('bands: ', bands)
337
+ if len(np.unique(bands)) != 2:
338
+ continue
339
+
340
+ # The band appears once will be band2
341
+ occurence = np.array([np.count_nonzero(ii == bands) for ii in bands])
342
+ # The index of observation in band2
343
+ index2 = indices[occurence == 1][0]
344
+ # The index of the first observation in band1
345
+ index11 = indices[occurence == 2][0]
346
+ # The index of the second observation in band1
347
+ index12 = indices[occurence == 2][1]
348
+
349
+ if (
350
+ abs(d_ts[index12, index2]) < abs(d_ts[index11, index2])
351
+ and abs(d_ts[index12, index2]) < time_lim1
352
+ ):
353
+ index11, index12 = index12, index11
354
+ elif abs(d_ts[index11, index2]) > time_lim1:
355
+ continue
356
+
357
+ d_t1 = d_ts[index11, index2]
358
+ d_t2 = d_ts[index11, index12]
359
+
360
+ band1 = bands[occurence == 2][0]
361
+ band2 = bands[occurence == 1][0]
362
+
363
+ if band1 + band2 == "uy" or band1 + band2 == "yu":
364
+ continue
365
+
366
+ d_mag = (detects.mag[index11] - detects.mag[index12]) * np.sign(d_t2)
367
+ color = detects.mag[index11] - detects.mag[index2]
368
+
369
+ phase_space_coords.append([band1, band2, d_t1, d_t2, d_mag, color])
370
+
371
+ score_s = 0
372
+ score_p = [0]
373
+
374
+ for phase_space_coord in phase_space_coords:
375
+ rate = self._enquiry(hash_table, info_dict, *phase_space_coord)
376
+
377
+ if score_s == 0 and rate < thr:
378
+ score_s = 1
379
+
380
+ score_p.append((1 - rate))
381
+
382
+ return score_s, max(score_p)
383
+
384
+ def run(self, data_slice, slice_point=None):
385
+ data_slice.sort(order=self.mjd_col)
386
+ result = {}
387
+ t = data_slice[self.mjd_col] - self.mjd0 - slice_point["peak_time"]
388
+ mags = np.zeros(t.size, dtype=float)
389
+
390
+ for filtername in np.unique(data_slice[self.filter_col]):
391
+ infilt = np.where(data_slice[self.filter_col] == filtername)
392
+ mags[infilt] = self.lightcurves.interp(t[infilt], filtername, lc_indx=slice_point["file_indx"])
393
+ # Apply dust extinction on the light curve
394
+ a_x = self.ax1[filtername] * slice_point["ebv"]
395
+ mags[infilt] += a_x
396
+
397
+ distmod = 5 * np.log10(slice_point["distance"] * 1e6) - 5.0
398
+ mags[infilt] += distmod
399
+
400
+ # Find the detected points
401
+ around_peak = np.where((t > 0) & (t < 30) & (mags < data_slice[self.m5_col]))[0]
402
+ # Filters in which the detections happened
403
+ filters = data_slice[self.filter_col][around_peak]
404
+
405
+ # presto color
406
+ result["presto_color_detect"] = self._presto_color_detect(around_peak, filters)
407
+
408
+ # Export the light curve
409
+ idx = np.where(mags < 100)[0]
410
+ lc = {
411
+ "t": data_slice[self.mjd_col][idx],
412
+ "mag": mags[idx],
413
+ "maglim": data_slice[self.m5_col][idx],
414
+ "filter": data_slice[self.filter_col][idx],
415
+ }
416
+
417
+ if self.output_lc is True:
418
+ result["lc"] = lc
419
+ result["slice_point"] = slice_point
420
+
421
+ if result["presto_color_detect"] == 1:
422
+ info_dict, hash_table = _load_hash(skyregion=self.skyregion)
423
+ result["scoreS"], result["scoreP"] = self._get_score(
424
+ pd.DataFrame(lc),
425
+ hash_table=hash_table,
426
+ info_dict=info_dict,
427
+ thr=self.thr,
428
+ )
429
+ else:
430
+ result["scoreS"] = 0
431
+ result["scoreP"] = 0
432
+ return result
433
+
434
+ def reduce_presto_color_detect(self, metric):
435
+ return metric["presto_color_detect"]
436
+
437
+ def reduce_score_s(self, metric):
438
+ return metric["scoreS"]
439
+
440
+ def reduce_score_p(self, metric):
441
+ return metric["scoreP"]
@@ -0,0 +1,171 @@
1
+ __all__ = ("PhotometricSelfCalUniformityMetric",)
2
+
3
+ import os
4
+ import time
5
+
6
+ import healpy as hp
7
+ import numpy as np
8
+ from astropy.coordinates import SkyCoord
9
+ from astropy.table import Table
10
+ from rubin_scheduler.data import get_data_dir
11
+ from rubin_scheduler.utils import healbin
12
+ from scipy.stats import median_abs_deviation
13
+
14
+ from rubin_sim.maf.metrics import BaseMetric
15
+ from rubin_sim.selfcal import LsqrSolver, OffsetSNR, generate_catalog
16
+ from rubin_sim.selfcal.offsets import OffsetSys
17
+
18
+
19
+ def _match(arr1, arr2):
20
+ st1 = np.argsort(arr1)
21
+ sub1 = np.searchsorted(arr1, arr2, sorter=st1)
22
+ if arr2.max() > arr1.max():
23
+ bad = sub1 == arr1.size
24
+ sub1[bad] = arr1.size - 1
25
+
26
+ (sub2,) = np.where(arr1[st1[sub1]] == arr2)
27
+ sub1 = st1[sub1[sub2]]
28
+
29
+ return sub1, sub2
30
+
31
+
32
+ class PhotometricSelfCalUniformityMetric(BaseMetric):
33
+ def __init__(
34
+ self,
35
+ nside_residual=128,
36
+ highglat_cut=30.0,
37
+ outlier_nsig=4.0,
38
+ metric_name="PhotometricSelfCalUniformityMetric",
39
+ filter_name="r",
40
+ ):
41
+ cols = [
42
+ "observationid",
43
+ "fieldra",
44
+ "fielddec",
45
+ "fiveSigmaDepth",
46
+ "rotSkyPos",
47
+ "filter",
48
+ ]
49
+ super().__init__(col=cols, metric_name=metric_name)
50
+
51
+ filename = os.path.join(get_data_dir(), "maf", "monster_stars_uniformity_i15-18_sampled.parquet")
52
+ self.stars = Table.read(filename)
53
+
54
+ # We have to rename dec to decl for the selfcal code.
55
+ if "dec" in self.stars.dtype.names:
56
+ self.stars["decl"] = self.stars["dec"]
57
+
58
+ self.stars = self.stars.as_array()
59
+
60
+ self.nside_residual = nside_residual
61
+ self.highglat_cut = highglat_cut
62
+ self.outlier_nsig = outlier_nsig
63
+
64
+ self.units = "mmag"
65
+ self.filter_name = filter_name
66
+
67
+ def run(self, data_slice, slice_point=None):
68
+ offsets = [OffsetSys(error_sys=0.03), OffsetSNR(lsst_filter=self.filter_name)]
69
+
70
+ visits = np.zeros(
71
+ len(data_slice),
72
+ dtype=[
73
+ ("observationId", "i8"),
74
+ ("ra", "f8"),
75
+ ("dec", "f8"),
76
+ ("fiveSigmaDepth", "f8"),
77
+ ("rotSkyPos", "f8"),
78
+ ],
79
+ )
80
+ visits["observationId"] = data_slice["observationId"]
81
+ visits["ra"] = data_slice["fieldRA"]
82
+ visits["dec"] = data_slice["fieldDec"]
83
+ visits["fiveSigmaDepth"] = data_slice["fiveSigmaDepth"]
84
+ visits["rotSkyPos"] = data_slice["rotSkyPos"]
85
+
86
+ good_stars = np.isfinite(self.stars[f"{self.filter_name}mag"])
87
+ stars = self.stars[good_stars]
88
+
89
+ observed_stars = generate_catalog(
90
+ visits,
91
+ stars,
92
+ offsets=offsets,
93
+ lsst_filter=self.filter_name,
94
+ n_patches=16,
95
+ verbose=False,
96
+ )
97
+
98
+ solver = LsqrSolver(observed_stars)
99
+
100
+ print("Starting solver...")
101
+ t0 = time.time()
102
+
103
+ solver.run()
104
+ fit_patches, fit_stars = solver.return_solution()
105
+
106
+ t1 = time.time()
107
+ dt = (t1 - t0) / 60.0
108
+ print("runtime= %.1f min" % dt)
109
+
110
+ # Trim stars to the ones with solutions.
111
+ a, b = _match(stars["id"], fit_stars["id"])
112
+ stars_trimmed = stars[a]
113
+ fit_stars_trimmed = fit_stars[b]
114
+
115
+ # Residuals after fit, removing floating zeropoint
116
+ resid = stars_trimmed[f"{self.filter_name}mag"] - fit_stars_trimmed["fit_mag"]
117
+ resid = resid - np.median(resid)
118
+
119
+ resid_map = healbin(
120
+ stars_trimmed["ra"],
121
+ stars_trimmed["dec"],
122
+ resid,
123
+ self.nside_residual,
124
+ reduce_func=np.median,
125
+ )
126
+
127
+ (ipring,) = np.where(resid_map > hp.UNSEEN)
128
+
129
+ scatter_full = median_abs_deviation(resid_map[ipring], scale="normal")
130
+
131
+ # Fraction of (4) sigma outliers.
132
+ highscat = np.abs(resid_map[ipring]) > self.outlier_nsig * scatter_full
133
+ outlier_frac_full = highscat.sum() / len(ipring)
134
+
135
+ # Cut to high latitude
136
+ ra, dec = hp.pix2ang(self.nside_residual, ipring, nest=False, lonlat=True)
137
+ coords = SkyCoord(ra, dec, frame="icrs", unit="deg")
138
+ b = coords.galactic.b.value
139
+
140
+ high_glat = np.abs(b) > self.highglat_cut
141
+ scatter_highglat = median_abs_deviation(resid_map[ipring[high_glat]], scale="normal")
142
+
143
+ # Fraction of (4) sigma outliers.
144
+ highscat = np.abs(resid_map[ipring[high_glat]]) > self.outlier_nsig * scatter_highglat
145
+ outlier_frac_highglat = highscat.sum() / len(ipring)
146
+
147
+ # Convert to mmag
148
+ scatter_full = scatter_full * 1000.0
149
+ scatter_highglat = scatter_highglat * 1000.0
150
+
151
+ result = {
152
+ "scatter_full": scatter_full,
153
+ "scatter_highglat": scatter_highglat,
154
+ "outlier_frac_full": outlier_frac_full,
155
+ "outlier_frac_highglat": outlier_frac_highglat,
156
+ "uniformity_map": resid_map,
157
+ }
158
+
159
+ return result
160
+
161
+ def reduce_scatter_full(self, metric_value):
162
+ return metric_value["scatter_full"]
163
+
164
+ def reduce_scatter_highglat(self, metric_value):
165
+ return metric_value["scatter_highglat"]
166
+
167
+ def reduce_outlier_frac_full(self, metric_value):
168
+ return metric_value["outlier_frac_full"]
169
+
170
+ def reduce_outlier_frac_highglat(self, metric_value):
171
+ return metric_value["outlier_frac_highglat"]
@@ -0,0 +1,64 @@
1
+ __all__ = ("StarCountMassMetric",)
2
+
3
+ import numpy as np
4
+
5
+ from rubin_sim.maf.metrics import BaseMetric
6
+
7
+ from .star_counts import starcount_bymass
8
+
9
+ # Example for CountMassMetric
10
+ # Mike Lund - Vanderbilt University
11
+ # mike.lund@gmail.com
12
+ # Last edited 8/15/2015
13
+ # Motivation: The distances to stars in LSST will be significant enough that
14
+ # the structure of the Galaxy will be readily apparent because of its
15
+ # influence on the number of stars in a given field.
16
+ # Any metric concerned with the number of potential objects to be detected
17
+ # will need to feature not only the effects of the cadence but also the
18
+ # number of objects per field.
19
+ # This metric identifies the number of stars in a given field in a particular
20
+ # mass range that will be fainter than the saturation limit of 16th magnitude
21
+ # and still bright enough to have noise less than 0.03 mag.
22
+ # M1 and M2 are the low and high limits of the mass range in solar masses.
23
+ # 'band' is the band for the observations to be made in.
24
+ # Requires StarCounts.StarCounts
25
+
26
+ # NOTE
27
+ # There are stellar luminosity function maps available within MAF
28
+ # that may supersede these StarCount functions
29
+
30
+
31
+ class StarCountMassMetric(BaseMetric):
32
+ """Find the number of stars in a given field in the mass range
33
+ fainter than magnitude 16 and bright enough to have noise less than
34
+ 0.03 in a given band.
35
+ M1 and m2 are the upper and lower limits of the mass range.
36
+ 'band' is the band to be observed.
37
+
38
+ This metric uses the stellar distance and luminosity equations
39
+ contributed by Mike Lund, which are based on the Galfast model.
40
+ There are some imposed limitations on the expected magnitudes
41
+ of the stars included for the metric, based on assuming saturation
42
+ at 16th magnitude and not considering stars with magnitude
43
+ uncertainties greater than 0.03 (based on photometry/m5 alone).
44
+
45
+ Parameters
46
+ ----------
47
+ m1 : `float`
48
+ Lower limit of the mass range.
49
+ m2 : `float`
50
+ Upper limit of the mass range.
51
+ band : `str`
52
+ Bandpass to consider.
53
+ """
54
+
55
+ def __init__(self, m1=0.9, m2=1.0, band="i", **kwargs):
56
+ self.m1 = m1
57
+ self.m2 = m2
58
+ self.band = band
59
+ super(StarCountMassMetric, self).__init__(col=[], **kwargs)
60
+
61
+ def run(self, data_slice, slice_point=None):
62
+ self.dec_col = np.degrees(data_slice[0][3])
63
+ self.ra_col = np.degrees(data_slice[0][2])
64
+ return starcount_bymass.starcount_bymass(self.ra_col, self.dec_col, self.m1, self.m2, self.band)