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,133 @@
1
+ __all__ = ("PeriodicDetectMetric",)
2
+
3
+ import numpy as np
4
+ import scipy
5
+
6
+ from rubin_sim.maf.utils import m52snr, stellar_mags
7
+
8
+ from .base_metric import BaseMetric
9
+
10
+
11
+ class PeriodicDetectMetric(BaseMetric):
12
+ """Determine if we would be able to classify an object as
13
+ periodic/non-uniform, using an F-test.
14
+
15
+ The idea here is that if a periodic source is aliased, it will be
16
+ indistinguishable from a constant source,
17
+ so we can find a best-fit constant, and if the reduced chi-squared is ~1,
18
+ we know we are aliased.
19
+
20
+ Parameters
21
+ ----------
22
+ mjd_col : `str`, opt
23
+ Name of the MJD column in the observations.
24
+ periods : `float` or `np.ndarray`, (N,), opt
25
+ The period of the star (days).
26
+ Can be a single value, or an array.
27
+ If an array, amplitude and starMag should be arrays of equal length.
28
+ amplitudes : `float`, opt
29
+ The amplitude of the stellar variability, (mags).
30
+ m5_col : `str`, opt
31
+ The name of the m5 limiting magnitude column in the observations.
32
+ metric_name : `str`, opt
33
+ The name for the metric.
34
+ starMags : `float`, opt
35
+ The mean magnitude of the star in r (mags).
36
+ sig_level : `float`, opt
37
+ The value to use to compare to the p-value when deciding
38
+ if we can reject the null hypothesis.
39
+ sed_template : `str`, opt
40
+ The stellar SED template to use to generate realistic colors
41
+ (default is an F star, so RR Lyrae-like)
42
+
43
+ Returns
44
+ -------
45
+ flag : `int`
46
+ Returns 1 if we would detect star is variable,
47
+ 0 if it is well-fit by a constant value.
48
+ If using arrays to test multiple period-amplitude-mag combinations,
49
+ will be the sum of the number of detected stars.
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ mjd_col="observationStartMJD",
55
+ periods=2.0,
56
+ amplitudes=0.1,
57
+ m5_col="fiveSigmaDepth",
58
+ metric_name="PeriodicDetectMetric",
59
+ filter_col="band",
60
+ star_mags=20,
61
+ sig_level=0.05,
62
+ sed_template="F",
63
+ **kwargs,
64
+ ):
65
+ self.mjd_col = mjd_col
66
+ self.m5_col = m5_col
67
+ self.filter_col = filter_col
68
+ if np.size(periods) == 1:
69
+ self.periods = [periods]
70
+ # Using the same magnitude for all filters.
71
+ # Could expand to fit the mean in each filter.
72
+ self.star_mags = [star_mags]
73
+ self.amplitudes = [amplitudes]
74
+ else:
75
+ self.periods = periods
76
+ self.star_mags = star_mags
77
+ self.amplitudes = amplitudes
78
+ self.sig_level = sig_level
79
+ self.sed_template = sed_template
80
+
81
+ super(PeriodicDetectMetric, self).__init__(
82
+ [mjd_col, m5_col, filter_col],
83
+ metric_name=metric_name,
84
+ units="N Detected (0, %i)" % np.size(periods),
85
+ **kwargs,
86
+ )
87
+
88
+ def run(self, data_slice, slice_point=None):
89
+ result = 0
90
+ n_pts = np.size(data_slice[self.mjd_col])
91
+ n_filt = np.size(np.unique(data_slice[self.filter_col]))
92
+
93
+ # If we had a correct model with phase, amplitude, period, mean_mags,
94
+ # then chi_squared/DoF would be ~1 with 3+n_filt free parameters.
95
+ # The mean is one free parameter
96
+ p1 = n_filt
97
+ p2 = 3.0 + n_filt
98
+ chi_sq_2 = 1.0 * (n_pts - p2)
99
+
100
+ u_filters = np.unique(data_slice[self.filter_col])
101
+
102
+ if n_pts > p2:
103
+ for period, starMag, amplitude in zip(self.periods, self.star_mags, self.amplitudes):
104
+ chi_sq_1 = 0
105
+ mags = stellar_mags(self.sed_template, rmag=starMag)
106
+ for filtername in u_filters:
107
+ in_filt = np.where(data_slice[self.filter_col] == filtername)[0]
108
+ lc = (
109
+ amplitude * np.sin(data_slice[self.mjd_col][in_filt] * (np.pi * 2) / period)
110
+ + mags[filtername]
111
+ )
112
+ snr = m52snr(lc, data_slice[self.m5_col][in_filt])
113
+ delta_m = 2.5 * np.log10(1.0 + 1.0 / snr)
114
+ weights = 1.0 / (delta_m**2)
115
+ weighted_mean = np.sum(weights * lc) / np.sum(weights)
116
+ chi_sq_1 += np.sum(((lc - weighted_mean) ** 2 / delta_m**2))
117
+ # Yes, I'm fitting magnitudes rather than flux.
118
+ # At least I feel kinda bad about it.
119
+ # F-test for nested models Regression problems:
120
+ # https://en.wikipedia.org/wiki/F-test
121
+ f_numerator = (chi_sq_1 - chi_sq_2) / (p2 - p1)
122
+ f_denom = 1.0
123
+ # This is just reduced chi-squared for the more
124
+ # complicated model, so should be 1.
125
+ f_val = f_numerator / f_denom
126
+ # Has DoF (p2-p1, n-p2)
127
+ # https://stackoverflow.com/questions/21494141/how-do-i-do-a-f-test-in-python/21503346
128
+ p_value = scipy.stats.f.sf(f_val, p2 - p1, n_pts - p2)
129
+ if np.isfinite(p_value):
130
+ if p_value < self.sig_level:
131
+ result += 1
132
+
133
+ return result
@@ -0,0 +1,172 @@
1
+ __all__ = ("PhaseGapMetric", "PeriodicQualityMetric")
2
+
3
+ import numpy as np
4
+
5
+ from rubin_sim.maf.utils import m52snr
6
+
7
+ from .base_metric import BaseMetric
8
+
9
+
10
+ class PhaseGapMetric(BaseMetric):
11
+ """Measure the maximum gap in phase coverage for
12
+ observations of periodic variables.
13
+
14
+ Parameters
15
+ ----------
16
+ col : `str`, optional
17
+ Name of the column to use for the observation times (MJD)
18
+ n_periods : `int`, optional
19
+ Number of periods to test
20
+ period_min : `float`, optional
21
+ Minimum period to test, in days.
22
+ period_max : `float`, optional
23
+ Maximum period to test, in days
24
+ n_visits_min : `int`, optional
25
+ Minimum number of visits necessary before looking for the phase gap.
26
+
27
+ Returns
28
+ -------
29
+ metric_value : `dict` {`periods`: `float`, `maxGaps` : `float`}
30
+ Calculates a dictionary of max gap in phase coverage for each period.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ col="observationStartMJD",
36
+ n_periods=5,
37
+ period_min=3.0,
38
+ period_max=35.0,
39
+ n_visits_min=3,
40
+ metric_name="Phase Gap",
41
+ **kwargs,
42
+ ):
43
+ self.period_min = period_min
44
+ self.period_max = period_max
45
+ self.n_periods = n_periods
46
+ self.n_visits_min = n_visits_min
47
+ super(PhaseGapMetric, self).__init__(col, metric_name=metric_name, units="Fraction, 0-1", **kwargs)
48
+
49
+ def run(self, data_slice, slice_point=None):
50
+ if len(data_slice) < self.n_visits_min:
51
+ return self.badval
52
+ # Create 'nPeriods' evenly spaced periods within range of min to max.
53
+ step = (self.period_max - self.period_min) / self.n_periods
54
+ if step == 0:
55
+ periods = np.array([self.period_min])
56
+ else:
57
+ periods = np.arange(self.n_periods)
58
+ periods = periods / np.max(periods) * (self.period_max - self.period_min) + self.period_min
59
+ max_gap = np.zeros(self.n_periods, float)
60
+
61
+ for i, period in enumerate(periods):
62
+ # For each period, calculate the phases.
63
+ phases = (data_slice[self.colname] % period) / period
64
+ phases = np.sort(phases)
65
+ # Find the largest gap in coverage.
66
+ gaps = np.diff(phases)
67
+ start_to_end = np.array([1.0 - phases[-1] + phases[0]], float)
68
+ gaps = np.concatenate([gaps, start_to_end])
69
+ max_gap[i] = np.max(gaps)
70
+
71
+ return {"periods": periods, "maxGaps": max_gap}
72
+
73
+ def reduce_mean_gap(self, metric_val):
74
+ """
75
+ At each slice_point, return the mean gap value.
76
+ """
77
+ return np.mean(metric_val["maxGaps"])
78
+
79
+ def reduce_median_gap(self, metric_val):
80
+ """
81
+ At each slice_point, return the median gap value.
82
+ """
83
+ return np.median(metric_val["maxGaps"])
84
+
85
+ def reduce_worst_period(self, metric_val):
86
+ """
87
+ At each slice_point, return the period with the largest phase gap.
88
+ """
89
+ worst_p = metric_val["periods"][np.where(metric_val["maxGaps"] == metric_val["maxGaps"].max())]
90
+ return worst_p
91
+
92
+ def reduce_largest_gap(self, metric_val):
93
+ """
94
+ At each slice_point, return the largest phase gap value.
95
+ """
96
+ return np.max(metric_val["maxGaps"])
97
+
98
+
99
+ # To fit a periodic source well, you need to cover the full phase,
100
+ # and fit the amplitude.
101
+ class PeriodicQualityMetric(BaseMetric):
102
+ """Evaluate phase coverage over a given period.
103
+
104
+ Parameters
105
+ ----------
106
+ mjd_col : `str`, opt
107
+ Name of the MJD column in the observations.
108
+ period : `float`, opt
109
+ Period to check.
110
+ m5_col : `str`, opt
111
+ Name of the m5 column in the observations.
112
+ metric_name : `str`, opt
113
+ Name of the metric.
114
+ star_mag : `float`, opt
115
+ Magnitude of the star to simulate coverage for.
116
+
117
+ Returns
118
+ -------
119
+ value : `float`
120
+ Value representing phase_coverage * amplitude_snr.
121
+ Ranges from 0 (poor) to 1.
122
+ """
123
+
124
+ def __init__(
125
+ self,
126
+ mjd_col="observationStartMJD",
127
+ period=2.0,
128
+ m5_col="fiveSigmaDepth",
129
+ metric_name="PhaseCoverageMetric",
130
+ star_mag=20,
131
+ **kwargs,
132
+ ):
133
+ self.mjd_col = mjd_col
134
+ self.m5_col = m5_col
135
+ self.period = period
136
+ self.star_mag = star_mag
137
+ super(PeriodicQualityMetric, self).__init__(
138
+ [mjd_col, m5_col], metric_name=metric_name, units="Fraction, 0-1", **kwargs
139
+ )
140
+
141
+ def _calc_phase(self, data_slice):
142
+ """1 is perfectly balanced phase coverage,
143
+ 0 is no effective coverage.
144
+ """
145
+ angles = data_slice[self.mjd_col] % self.period
146
+ angles = angles / self.period * 2.0 * np.pi
147
+ x = np.cos(angles)
148
+ y = np.sin(angles)
149
+
150
+ snr = m52snr(self.star_mag, data_slice[self.m5_col])
151
+ x_ave = np.average(x, weights=snr)
152
+ y_ave = np.average(y, weights=snr)
153
+
154
+ vector_off = np.sqrt(x_ave**2 + y_ave**2)
155
+ return 1.0 - vector_off
156
+
157
+ def _calc_amp(self, data_slice):
158
+ """Fractional SNR on the amplitude,
159
+ testing for a variety of possible phases.
160
+ """
161
+ phases = np.arange(0, np.pi, np.pi / 8.0)
162
+ snr = m52snr(self.star_mag, data_slice[self.m5_col])
163
+ amp_snrs = np.sin(data_slice[self.mjd_col] / self.period * 2 * np.pi + phases[:, np.newaxis]) * snr
164
+ amp_snr = np.min(np.sqrt(np.sum(amp_snrs**2, axis=1)))
165
+
166
+ max_snr = np.sqrt(np.sum(snr**2))
167
+ return amp_snr / max_snr
168
+
169
+ def run(self, data_slice, slice_point=None):
170
+ amplitude_fraction = self._calc_amp(data_slice)
171
+ phase_fraction = self._calc_phase(data_slice)
172
+ return amplitude_fraction * phase_fraction
@@ -0,0 +1,138 @@
1
+ __all__ = ("QSONumberCountsMetric",)
2
+
3
+ import os
4
+
5
+ import healpy as hp
6
+ import numpy as np
7
+ from rubin_scheduler.data import get_data_dir
8
+ from scipy import interpolate
9
+
10
+ from .base_metric import BaseMetric
11
+ from .exgal_m5 import ExgalM5
12
+
13
+
14
+ class QSONumberCountsMetric(BaseMetric):
15
+ """Calculate the number of quasars expected with SNR>=5
16
+ according to the Shen et al. (2020) QLF - model A in the redshift
17
+ range zmin < z < zmax.
18
+
19
+ The 5 sigma depths are obtained using the ExgalM5 metric.
20
+ Only quasars fainter than the saturation magnitude are counted.
21
+
22
+ By default, zmin is 0.3 and zmax is the minimum between 6.7 and the
23
+ redshift at which the Lyman break matches the effective wavelength
24
+ of the band. For bands izy, zmax is 6.7. This default choice is to
25
+ match Table 10.2 for i-band quasar counts in the LSST Science book.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ lsst_filter,
31
+ m5_col="fiveSigmaDepth",
32
+ units="mag",
33
+ extinction_cut=1.0,
34
+ filter_col="band",
35
+ metric_name="QSONumberCountsMetric",
36
+ qlf_module="Shen20",
37
+ qlf_model="A",
38
+ sed_model="Richards06",
39
+ zmin=0.3,
40
+ zmax=None,
41
+ **kwargs,
42
+ ):
43
+ # Declare the effective wavelengths.
44
+ self.effwavelen = {
45
+ "u": 367.0,
46
+ "g": 482.5,
47
+ "r": 622.2,
48
+ "i": 754.5,
49
+ "z": 869.1,
50
+ "y": 971.0,
51
+ }
52
+
53
+ # Dust Extinction limit.
54
+ # Regions with larger extinction and dropped from the counting.
55
+ self.extinction_cut = extinction_cut
56
+
57
+ # Save the filter information.
58
+ self.filter_col = filter_col
59
+ self.lsst_filter = lsst_filter
60
+
61
+ # Save zmin and zmax, or set zmax to the default value.
62
+ # The default zmax is the lower number between 6.7 and the
63
+ # redshift at which the Lyman break (91.2nm) hits the
64
+ # effective wavelength of the filter.
65
+ # Note that this means that for i, z and y,
66
+ # the default value for zmax is 6.7
67
+ self.zmin = zmin
68
+ if zmax is None:
69
+ zmax = np.min([6.7, self.effwavelen[self.lsst_filter] / 91.2 - 1.0])
70
+ self.zmax = zmax
71
+
72
+ # This calculation uses the ExgalM5 metric. So declare that here.
73
+ self.exgal_m5 = ExgalM5(m5_col=m5_col, units=units, filter_col=filter_col)
74
+
75
+ # Save the input parameters that relate to the QLF model.
76
+ self.qlf_module = qlf_module
77
+ self.qlf_model = qlf_model
78
+ self.sed_model = sed_model
79
+
80
+ # Read the long tables, which the number of quasars expected
81
+ # for a given band, qlf_module and qlf_model in a range of
82
+ # redshifts and magnitudes.
83
+ table_name = "Long_Table.LSST{0}.{1}.{2}.{3}.txt".format(
84
+ self.lsst_filter, self.qlf_module, self.qlf_model, self.sed_model
85
+ )
86
+ data_dir = os.path.join(get_data_dir(), "maf", "quasarNumberCounts")
87
+ filename = os.path.join(data_dir, table_name)
88
+ with open(filename, "r") as f:
89
+ mags = np.array([float(x) for x in f.readline().split()])
90
+ zs = np.array([float(x) for x in f.readline().split()])
91
+ mz_data = np.loadtxt(filename, skiprows=2)
92
+
93
+ # Make the long table cumulative.
94
+ c_mz_data = np.zeros((mz_data.shape[0] + 1, mz_data.shape[1] + 1))
95
+ c_mz_data[1:, 1:] = mz_data
96
+ c_mz_data = np.cumsum(c_mz_data, axis=0)
97
+ c_mz_data = np.cumsum(c_mz_data, axis=1)
98
+
99
+ # Create a 2D interpolation object for the long table.
100
+ # self.nqso_cumulative = interpolate.interp2d(zs[:-1], mags[:-1],
101
+ # #c_mz_data[:-1, :-1], kind="cubic")
102
+ self.nqso_cumulative_aux = interpolate.RectBivariateSpline(
103
+ zs[:-1], mags[:-1], c_mz_data[:-1, :-1].T, kx=3, ky=3
104
+ )
105
+
106
+ self.nqso_cumulative = lambda z_new, m_new: self.nqso_cumulative_aux(z_new, m_new).T[0]
107
+
108
+ super().__init__(
109
+ col=[m5_col, filter_col, "saturation_mag"],
110
+ metric_name=metric_name,
111
+ maps=self.exgal_m5.maps,
112
+ units=units,
113
+ **kwargs,
114
+ )
115
+
116
+ def run(self, data_slice, slice_point=None):
117
+ # exclude areas with high extinction
118
+ if slice_point["ebv"] > self.extinction_cut:
119
+ return self.badval
120
+
121
+ # For the data_slice, get the 5 sigma limiting magnitude.
122
+ d_s = data_slice[data_slice[self.filter_col] == self.lsst_filter]
123
+ mlim5 = self.exgal_m5.run(d_s, slice_point)
124
+
125
+ # Get the slicer pixel area.
126
+ nside = slice_point["nside"]
127
+ pix_area = hp.nside2pixarea(nside, degrees=True)
128
+
129
+ # tranform that limiting magnitude into an expected number of quasars.
130
+ # If there is more than one, take the faintest.
131
+ m_bright = np.max(d_s["saturation_mag"])
132
+ n11 = self.nqso_cumulative(self.zmin, m_bright)
133
+ n12 = self.nqso_cumulative(self.zmin, mlim5)
134
+ n21 = self.nqso_cumulative(self.zmax, m_bright)
135
+ n22 = self.nqso_cumulative(self.zmax, mlim5)
136
+
137
+ nqso = (n22 - n21 - n12 + n11) * pix_area
138
+ return nqso
@@ -0,0 +1,148 @@
1
+ __all__ = ("NgalScaleMetric", "NlcPointsMetric")
2
+
3
+ import healpy as hp
4
+ import numpy as np
5
+
6
+ from rubin_sim.maf.maps import TrilegalDensityMap
7
+ from rubin_sim.phot_utils import DustValues
8
+
9
+ from .base_metric import BaseMetric
10
+
11
+
12
+ class NgalScaleMetric(BaseMetric):
13
+ """Approximate number of galaxies, scaled by median seeing.
14
+
15
+ Parameters
16
+ ----------
17
+ a_max : `float`
18
+ The maximum dust extinction to allow. Anything with higher dust
19
+ extinction is considered to have zero usable galaxies.
20
+ m5min : `float`
21
+ The minimum coadded 5-sigma depth to allow. Anything less is
22
+ considered to have zero usable galaxies.
23
+ filter : `str`
24
+ The filter to use. Any visits in other filters are ignored.
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ seeing_col="seeingFwhmEff",
30
+ m5_col="fiveSigmaDepth",
31
+ metric_name="NgalScale",
32
+ filtername="i",
33
+ a_max=0.2,
34
+ m5min=26.0,
35
+ filter_col="band",
36
+ **kwargs,
37
+ ):
38
+ maps = ["DustMap"]
39
+ units = "N gals"
40
+ self.seeing_col = seeing_col
41
+ self.m5_col = m5_col
42
+ self.filtername = filtername
43
+ self.filter_col = filter_col
44
+ self.a_max = a_max
45
+ self.m5min = m5min
46
+
47
+ super().__init__(
48
+ col=[self.m5_col, self.filter_col, self.seeing_col],
49
+ maps=maps,
50
+ units=units,
51
+ metric_name=metric_name,
52
+ **kwargs,
53
+ )
54
+ dust_properties = DustValues()
55
+ self.ax1 = dust_properties.ax1
56
+
57
+ def run(self, data_slice, slice_point):
58
+ # I'm a little confused why there's a dust cut and an M5 cut,
59
+ # but whatever
60
+ a_x = self.ax1[data_slice[self.filter_col][0]] * slice_point["ebv"]
61
+ if a_x > self.a_max:
62
+ return 0
63
+
64
+ in_filt = np.where(data_slice[self.filter_col] == self.filtername)
65
+ coadd_m5 = 1.25 * np.log10(np.sum(10.0 ** (0.8 * data_slice[self.m5_col][in_filt])))
66
+ if coadd_m5 < self.m5min:
67
+ return 0
68
+
69
+ theta = np.median(data_slice[self.seeing_col])
70
+ # N gals per arcmin2
71
+ ngal_per_arcmin2 = 57 * (0.75 / theta) ** 1.5
72
+
73
+ area = hp.nside2pixarea(slice_point["nside"], degrees=True) * 3600.0
74
+
75
+ ngal = ngal_per_arcmin2 * area
76
+ return ngal
77
+
78
+
79
+ class NlcPointsMetric(BaseMetric):
80
+ """Number of points in stellar light curves
81
+
82
+ Parameters
83
+ ----------
84
+ ndpmin : `int`
85
+ The number of points to demand on a lightcurve in a single
86
+ filter to have that light curve qualify.
87
+ mags : `float`
88
+ The magnitude of our fiducial object (maybe make it a dict in the
89
+ future to support arbitrary colors).
90
+ maps : `list` [`~rubin_sim.maf.map`] or None
91
+ List of stellar density maps to use.
92
+ Default of None loads Trilegal maps.
93
+ nside : `int`
94
+ The nside is needed to make sure the loaded maps
95
+ match the slicer nside.
96
+ """
97
+
98
+ def __init__(
99
+ self,
100
+ ndpmin=10,
101
+ mags=21.0,
102
+ m5_col="fiveSigmaDepth",
103
+ filter_col="band",
104
+ metric_name="NlcPoints",
105
+ maps=None,
106
+ nside=128,
107
+ **kwargs,
108
+ ):
109
+ units = "N LC points"
110
+ self.ndpmin = ndpmin
111
+ self.mags = mags
112
+ self.m5_col = m5_col
113
+ self.filter_col = filter_col
114
+ self.nside = nside
115
+ if maps is None:
116
+ maps = [TrilegalDensityMap(filtername=fn, nside=nside) for fn in "ugrizy"]
117
+ super().__init__(
118
+ col=[self.m5_col, self.filter_col],
119
+ maps=maps,
120
+ units=units,
121
+ metric_name=metric_name,
122
+ **kwargs,
123
+ )
124
+
125
+ def run(self, data_slice, slice_point):
126
+ if self.nside != slice_point["nside"]:
127
+ raise ValueError("nside of metric does not match slicer")
128
+ pix_area = hp.nside2pixarea(slice_point["nside"], degrees=True)
129
+
130
+ nlcpoints = 0
131
+ # Let's do it per filter
132
+ for filtername in np.unique(data_slice[self.filter_col]):
133
+ in_filt = np.where(
134
+ (data_slice[self.filter_col] == filtername) & (data_slice[self.m5_col] > self.mags)
135
+ )[0]
136
+ n_obs = np.size(in_filt)
137
+ if n_obs > self.ndpmin:
138
+ nstars = (
139
+ np.interp(
140
+ self.mags,
141
+ slice_point[f"starMapBins_{filtername}"][1:],
142
+ slice_point[f"starLumFunc_{filtername}"],
143
+ )
144
+ * pix_area
145
+ )
146
+ nlcpoints += n_obs * nstars
147
+
148
+ return nlcpoints
@@ -0,0 +1,39 @@
1
+ """Metrics for scheduler monitoring and progress."""
2
+
3
+ __all__ = ["AgeMetric"]
4
+
5
+ import numpy as np
6
+
7
+ from .base_metric import BaseMetric
8
+
9
+
10
+ class AgeMetric(BaseMetric):
11
+ def __init__(
12
+ self, mjd, mjd_col="observationStartMJD", long_limit=30, metric_name="age", mask_val=np.nan, **kwargs
13
+ ):
14
+ """Metric that shows the time since the previous visit in each slice,
15
+ as of a given time
16
+
17
+ Parameters
18
+ ----------
19
+ mjd : `float`
20
+ Reference time for the age.
21
+ mjd_col : `str`
22
+ Column with the time of visit, by default "observationStartMJD"
23
+ long_limit : `int`
24
+ The age past which to mask values, by default 30
25
+ metric_name : `str`
26
+ The metric name, by default 'age'
27
+ mask_val : `object`
28
+ Name for masked values, by default np.nan
29
+ """
30
+ self.mjd = mjd
31
+ self.mjd_col = mjd_col
32
+ self.long_limit = long_limit
33
+ super().__init__(col=[self.mjd_col], metric_name=metric_name, mask_val=mask_val, **kwargs)
34
+
35
+ def run(self, data_slice, slice_point=None):
36
+ age = self.mjd - np.max(data_slice[self.mjd_col])
37
+ if age > self.long_limit:
38
+ age = self.mask_val
39
+ return age