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,159 @@
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+
6
+ import numpy as np
7
+ from rubin_scheduler.scheduler.example import example_scheduler, run_sched
8
+ from rubin_scheduler.utils import SURVEY_START_MJD
9
+ from rubin_scheduler.utils.code_utilities import sims_clean_up
10
+
11
+ import rubin_sim.maf.batches as batches
12
+ import rubin_sim.maf.db as db
13
+ import rubin_sim.maf.metric_bundles as metric_bundles
14
+ from rubin_sim.data import get_data_dir
15
+ from rubin_sim.maf.slicers import MoObjSlicer
16
+
17
+
18
+ class TestBatches(unittest.TestCase):
19
+ @classmethod
20
+ def tearDown_class(cls):
21
+ sims_clean_up()
22
+ if os.path.isdir(cls.out_dir):
23
+ shutil.rmtree(cls.out_dir)
24
+ if os.path.exists(cls.example_file):
25
+ os.remove(cls.example_file)
26
+
27
+ @classmethod
28
+ def setUpClass(cls):
29
+ super(TestBatches, cls).setUpClass()
30
+ # Generate a fresh 10-day example database
31
+ cls.example_file = "short_example.db"
32
+ sched = example_scheduler()
33
+ _returned_stuff = run_sched(
34
+ sched, survey_length=10, filename=cls.example_file, mjd_start=SURVEY_START_MJD
35
+ )
36
+
37
+ cls.out_dir = tempfile.mkdtemp(prefix="TMB")
38
+
39
+ @unittest.skipUnless(
40
+ os.path.isdir(os.path.join(get_data_dir(), "maf")),
41
+ "Skip these batches unless MAF data present, required for setup",
42
+ )
43
+ def testload_them_all(self):
44
+ ack = batches.altazHealpix()
45
+ assert ack is not None
46
+ ack = batches.altazLambert()
47
+ assert ack is not None
48
+ ack = batches.astrometryBatch()
49
+ assert ack is not None
50
+ ack = batches.ddfBatch()
51
+ assert ack is not None
52
+ ack = batches.fOBatch()
53
+ assert ack is not None
54
+ ack = batches.standard_summary()
55
+ assert ack is not None
56
+ ack = batches.standard_metrics("night")
57
+ assert ack is not None
58
+ ack = batches.filtersPerNight()
59
+ assert ack is not None
60
+ ack = batches.filtersWholeSurvey()
61
+ assert ack is not None
62
+ ack = batches.glanceBatch()
63
+ assert ack is not None
64
+ ack = batches.hourglassPlots()
65
+ assert ack is not None
66
+ ack = batches.interNight()
67
+ assert ack is not None
68
+ ack = batches.intraNight()
69
+ assert ack is not None
70
+ ack = batches.metadataBasics("airmass")
71
+ assert ack is not None
72
+ ack = batches.metadataBasicsAngle("rotskyPos")
73
+ assert ack is not None
74
+ ack = batches.metadataMaps("fiveSigmaDepth")
75
+ assert ack is not None
76
+ ack = batches.nvisitsM5Maps()
77
+ assert ack is not None
78
+ ack = batches.nvisitsPerNight()
79
+ assert ack is not None
80
+ ack = batches.nvisitsPerSubset()
81
+ assert ack is not None
82
+ ack = batches.openshutterFractions()
83
+ assert ack is not None
84
+ ack = batches.rapidRevisitBatch()
85
+ assert ack is not None
86
+ ack = batches.slewBasics()
87
+ assert ack is not None
88
+ ack = batches.tEffMetrics()
89
+ assert ack is not None
90
+ ack = batches.timeGaps()
91
+ assert ack is not None
92
+
93
+ @unittest.skipUnless(
94
+ os.path.isdir(os.path.join(get_data_dir(), "maf")),
95
+ "Skip these batches unless MAF data present, required for setup",
96
+ )
97
+ def test_moving_objects_batches(self):
98
+ slicer = MoObjSlicer()
99
+ ack = batches.quick_discovery_batch(slicer)
100
+ assert ack is not None
101
+ ack = batches.discovery_batch(slicer)
102
+ assert ack is not None
103
+ ack = batches.characterization_inner_batch(slicer)
104
+ assert ack is not None
105
+ ack = batches.characterization_outer_batch(slicer)
106
+ assert ack is not None
107
+
108
+ def test_moving_fractions(self):
109
+ bdict = {}
110
+ bundle = metric_bundles.create_empty_mo_metric_bundle()
111
+ bundle.run_name = "dummy_name"
112
+ bdict["days"] = bundle
113
+ bdict["days"].slicer = MoObjSlicer()
114
+ bdict["days"].slicer.slice_points["H"] = np.arange(50)
115
+ # This is a start, but the methods below aren't really doing anything
116
+ # without appropriately named/values bundles in the bdict.
117
+ batches.run_completeness_summary(bdict, 0.0, [10, 20], None, None)
118
+ batches.run_fraction_summary(bdict, 0.0, None, None)
119
+ batches.plot_fractions(bdict, out_dir=self.out_dir)
120
+ # This batch takes a single bundle because it plots that single
121
+ # bundle with multiple summary interpretations of the metric
122
+ batches.plot_single(bundle, out_dir=self.out_dir)
123
+ batches.plot_activity(bdict)
124
+
125
+ @unittest.skipUnless(
126
+ os.path.isdir(os.path.join(get_data_dir(), "maps")),
127
+ "Skipping scienceRadarBatch test because operating without full MAF test data",
128
+ )
129
+ def test_science_radar(self):
130
+ # Loading the science radar batch requires reading a significant
131
+ # set of input files
132
+ # This test is skipped if running with the lighter set of test data.
133
+ # batch requires reading a lot of input files for lightcurves
134
+ ack = batches.science_radar_batch()
135
+ assert ack is not None
136
+
137
+ @unittest.skipUnless(
138
+ os.path.isdir(os.path.join(get_data_dir(), "maf")),
139
+ "Skipping glance test because operating without full MAF test data",
140
+ )
141
+ def test_glance(self):
142
+ batch = batches.glanceBatch()
143
+ results_db = db.ResultsDb(out_dir=self.out_dir)
144
+ bgroup = metric_bundles.MetricBundleGroup(
145
+ batch, self.example_file, out_dir=self.out_dir, results_db=results_db, save_early=False
146
+ )
147
+ bgroup.run_all()
148
+
149
+ def test_ddf(self):
150
+ batch = batches.ddfBatch()
151
+ results_db = db.ResultsDb(out_dir=self.out_dir)
152
+ bgroup = metric_bundles.MetricBundleGroup(
153
+ batch, self.example_file, out_dir=self.out_dir, results_db=results_db, save_early=False
154
+ )
155
+ bgroup.run_all()
156
+
157
+
158
+ if __name__ == "__main__":
159
+ unittest.main()
@@ -0,0 +1,388 @@
1
+ import math
2
+ import unittest
3
+
4
+ import numpy as np
5
+
6
+ import rubin_sim.maf.metrics as metrics
7
+
8
+
9
+ class TestCadenceMetrics(unittest.TestCase):
10
+ def test_phase_gap_metric(self):
11
+ """
12
+ Test the phase gap metric
13
+ """
14
+ data = np.zeros(10, dtype=list(zip(["observationStartMJD"], [float])))
15
+ data["observationStartMJD"] += np.arange(10) * 0.25
16
+
17
+ pgm = metrics.PhaseGapMetric(n_periods=1, period_min=0.5, period_max=0.5)
18
+ metric_val = pgm.run(data)
19
+
20
+ mean_gap = pgm.reduce_mean_gap(metric_val)
21
+ median_gap = pgm.reduce_median_gap(metric_val)
22
+ worst_period = pgm.reduce_worst_period(metric_val)
23
+ largest_gap = pgm.reduce_largest_gap(metric_val)
24
+
25
+ self.assertEqual(mean_gap, 0.5)
26
+ self.assertEqual(median_gap, 0.5)
27
+ self.assertEqual(worst_period, 0.5)
28
+ self.assertEqual(largest_gap, 0.5)
29
+
30
+ pgm = metrics.PhaseGapMetric(n_periods=2, period_min=0.25, period_max=0.5)
31
+ metric_val = pgm.run(data)
32
+
33
+ mean_gap = pgm.reduce_mean_gap(metric_val)
34
+ median_gap = pgm.reduce_median_gap(metric_val)
35
+ worst_period = pgm.reduce_worst_period(metric_val)
36
+ largest_gap = pgm.reduce_largest_gap(metric_val)
37
+
38
+ self.assertEqual(mean_gap, 0.75)
39
+ self.assertEqual(median_gap, 0.75)
40
+ self.assertEqual(worst_period, 0.25)
41
+ self.assertEqual(largest_gap, 1.0)
42
+
43
+ def test_template_exists(self):
44
+ """
45
+ Test the TemplateExistsMetric.
46
+ """
47
+ names = ["finSeeing", "observationStartMJD"]
48
+ types = [float, float]
49
+ data = np.zeros(10, dtype=list(zip(names, types)))
50
+ data["finSeeing"] = [2.0, 2.0, 3.0, 1.0, 1.0, 1.0, 0.5, 1.0, 0.4, 1.0]
51
+ data["observationStartMJD"] = np.arange(10)
52
+ slice_point = {"sid": 0}
53
+ # so here we have 4 images w/o good previous templates
54
+ metric = metrics.TemplateExistsMetric(seeing_col="finSeeing")
55
+ result = metric.run(data, slice_point)
56
+ self.assertEqual(result, 6.0 / 10.0)
57
+
58
+ def test_uniformity_metric(self):
59
+ names = ["observationStartMJD"]
60
+ types = [float]
61
+ data = np.zeros(100, dtype=list(zip(names, types)))
62
+ metric = metrics.UniformityMetric()
63
+ result1 = metric.run(data)
64
+ # If all the observations are on the 1st day, should be 1
65
+ self.assertEqual(result1, 1)
66
+ data["observationStartMJD"] = data["observationStartMJD"] + 365.25 * 10
67
+ slice_point = {"sid": 0}
68
+ result2 = metric.run(data, slice_point)
69
+ # All on last day should also be 1
70
+ self.assertEqual(result2, 1)
71
+ # Make a perfectly uniform dist
72
+ data["observationStartMJD"] = np.arange(0.0, 365.25 * 10, 365.25 * 10 / 100)
73
+ result3 = metric.run(data, slice_point)
74
+ # Result should be zero for uniform
75
+ np.testing.assert_almost_equal(result3, 0.0)
76
+ # A single obseravtion should give a result of 1
77
+ data = np.zeros(1, dtype=list(zip(names, types)))
78
+ result4 = metric.run(data, slice_point)
79
+ self.assertEqual(result4, 1)
80
+
81
+ def test_general_uniformity_metric(self):
82
+ names = ["observationStartMJD"]
83
+ types = [float]
84
+ data = np.zeros(100, dtype=list(zip(names, types)))
85
+ metric = metrics.GeneralUniformityMetric(col="observationStartMJD", min_value=0, max_value=1)
86
+ result1 = metric.run(data)
87
+ # If all the observations are at the minimum value, should be 1
88
+ self.assertEqual(result1, 1)
89
+ data["observationStartMJD"] = data["observationStartMJD"] + 1
90
+ slice_point = {"sid": 0}
91
+ result2 = metric.run(data, slice_point)
92
+ # All on max value should also be 1
93
+ self.assertEqual(result2, 1)
94
+ # Make a perfectly uniform dist
95
+ step = 1 / 99
96
+ data["observationStartMJD"] = np.arange(0.0, 1 + step / 2, step)
97
+ result3 = metric.run(data, slice_point)
98
+ # Result should be zero for uniform
99
+ np.testing.assert_almost_equal(result3, 0.0)
100
+ # Test setup with max_value > 1
101
+ metric = metrics.GeneralUniformityMetric(col="observationStartMJD", min_value=0, max_value=10)
102
+ # Make a perfectly uniform dist covering limited range
103
+ # (0-1 out of 0-10 range)
104
+ data["observationStartMJD"] = np.arange(0.0, 1 + step / 2, step)
105
+ result5 = metric.run(data, slice_point)
106
+ self.assertEqual(result5, 0.9)
107
+ # Test setup with max_value None
108
+ metric = metrics.GeneralUniformityMetric(col="observationStartMJD", min_value=None, max_value=None)
109
+ # Make a perfectly uniform dist
110
+ data["observationStartMJD"] = np.arange(0.0, 1 + step / 2, step)
111
+ result5 = metric.run(data, slice_point)
112
+ self.assertAlmostEqual(result5, 0)
113
+ # A single observation should give a result of 1
114
+ data = np.zeros(1, dtype=list(zip(names, types)))
115
+ result4 = metric.run(data, slice_point)
116
+ self.assertEqual(result4, 1)
117
+
118
+ def test_t_gap_metric(self):
119
+ names = ["observationStartMJD"]
120
+ types = [float]
121
+ data = np.zeros(100, dtype=list(zip(names, types)))
122
+ # All 1-day gaps
123
+ data["observationStartMJD"] = np.arange(100)
124
+
125
+ metric = metrics.TgapsMetric(bins=np.arange(1, 100, 1))
126
+ result1 = metric.run(data)
127
+ # By default, should all be in first bin
128
+ self.assertEqual(result1[0], data.size - 1)
129
+ self.assertEqual(np.sum(result1), data.size - 1)
130
+ data["observationStartMJD"] = np.arange(0, 200, 2)
131
+ result2 = metric.run(data)
132
+ self.assertEqual(result2[1], data.size - 1)
133
+ self.assertEqual(np.sum(result2), data.size - 1)
134
+
135
+ data = np.zeros(4, dtype=list(zip(names, types)))
136
+ data["observationStartMJD"] = [10, 20, 30, 40]
137
+ metric = metrics.TgapsMetric(all_gaps=True, bins=np.arange(1, 100, 10))
138
+ result3 = metric.run(data)
139
+ self.assertEqual(result3[1], 2)
140
+ ngaps = math.factorial(data.size - 1)
141
+ self.assertEqual(np.sum(result3), ngaps)
142
+
143
+ def test_t_gaps_percent_metric(self):
144
+ names = ["observationStartMJD"]
145
+ types = [float]
146
+ data = np.zeros(100, dtype=list(zip(names, types)))
147
+
148
+ # All 1-day gaps
149
+ data["observationStartMJD"] = np.arange(100)
150
+ # All intervals are one day, so should be 100% within the gap specified
151
+ metric = metrics.TgapsPercentMetric(min_time=0.5, max_time=1.5, all_gaps=False)
152
+ result1 = metric.run(data)
153
+ self.assertEqual(result1, 100)
154
+
155
+ # All 2 day gaps
156
+ data["observationStartMJD"] = np.arange(0, 200, 2)
157
+ result2 = metric.run(data)
158
+ self.assertEqual(result2, 0)
159
+
160
+ # Run with all_gaps = True
161
+ data = np.zeros(4, dtype=list(zip(names, types)))
162
+ data["observationStartMJD"] = [1, 2, 3, 4]
163
+ metric = metrics.TgapsPercentMetric(min_time=0.5, max_time=1.5, all_gaps=True)
164
+ result3 = metric.run(data)
165
+ # This should be 50% -- 3 gaps of 1 day, 2 gaps of 2 days, and
166
+ # 1 gap of 3 days
167
+ self.assertEqual(result3, 50)
168
+
169
+ def test_night_gap_metric(self):
170
+ names = ["night"]
171
+ types = [float]
172
+ data = np.zeros(100, dtype=list(zip(names, types)))
173
+ # All 1-day gaps
174
+ data["night"] = np.arange(100)
175
+
176
+ metric = metrics.NightgapsMetric(bins=np.arange(1, 100, 1))
177
+ result1 = metric.run(data)
178
+ # By default, should all be in first bin
179
+ self.assertEqual(result1[0], data.size - 1)
180
+ self.assertEqual(np.sum(result1), data.size - 1)
181
+ data["night"] = np.arange(0, 200, 2)
182
+ result2 = metric.run(data)
183
+ self.assertEqual(result2[1], data.size - 1)
184
+ self.assertEqual(np.sum(result2), data.size - 1)
185
+
186
+ data = np.zeros(4, dtype=list(zip(names, types)))
187
+ data["night"] = [10, 20, 30, 40]
188
+ metric = metrics.NightgapsMetric(all_gaps=True, bins=np.arange(1, 100, 10))
189
+ result3 = metric.run(data)
190
+ self.assertEqual(result3[1], 2)
191
+ ngaps = math.factorial(data.size - 1)
192
+ self.assertEqual(np.sum(result3), ngaps)
193
+
194
+ data = np.zeros(6, dtype=list(zip(names, types)))
195
+ data["night"] = [1, 1, 2, 3, 3, 5]
196
+ metric = metrics.NightgapsMetric(bins=np.arange(0, 5, 1))
197
+ result4 = metric.run(data)
198
+ self.assertEqual(result4[0], 0)
199
+ self.assertEqual(result4[1], 2)
200
+ self.assertEqual(result4[2], 1)
201
+
202
+ def test_n_visits_per_night_metric(self):
203
+ names = ["night"]
204
+ types = [float]
205
+ data = np.zeros(100, dtype=list(zip(names, types)))
206
+ # One visit per night.
207
+ data["night"] = np.arange(100)
208
+
209
+ bins = np.arange(0, 5, 1)
210
+ metric = metrics.NVisitsPerNightMetric(bins=bins)
211
+ result = metric.run(data)
212
+ # All nights have one visit.
213
+ expected_result = np.zeros(len(bins) - 1, dtype=int)
214
+ expected_result[1] = len(data)
215
+ np.testing.assert_array_equal(result, expected_result)
216
+
217
+ data["night"] = np.floor(np.arange(0, 100) / 2)
218
+ result = metric.run(data)
219
+ expected_result = np.zeros(len(bins) - 1, dtype=int)
220
+ expected_result[2] = len(data) / 2
221
+ np.testing.assert_array_equal(result, expected_result)
222
+
223
+ def test_rapid_revisit_uniformity_metric(self):
224
+ data = np.zeros(100, dtype=list(zip(["observationStartMJD"], [float])))
225
+ # Uniformly distribute time _differences_ between 0 and 100
226
+ dtimes = np.arange(100)
227
+ data["observationStartMJD"] = dtimes.cumsum()
228
+ # Set up "rapid revisit" metric to look for visits between 5 and 25
229
+ metric = metrics.RapidRevisitUniformityMetric(d_tmin=5, d_tmax=55, min_nvisits=50)
230
+ result = metric.run(data)
231
+ # This should be uniform.
232
+ self.assertLess(result, 0.1)
233
+ self.assertGreaterEqual(result, 0)
234
+ # Set up non-uniform distribution of time differences
235
+ dtimes = np.zeros(100) + 5
236
+ data["observationStartMJD"] = dtimes.cumsum()
237
+ result = metric.run(data)
238
+ self.assertGreaterEqual(result, 0.5)
239
+ dtimes = np.zeros(100) + 15
240
+ data["observationStartMJD"] = dtimes.cumsum()
241
+ result = metric.run(data)
242
+ self.assertGreaterEqual(result, 0.5)
243
+ """
244
+ # Let's see how much dmax/result can vary
245
+ resmin = 1
246
+ resmax = 0
247
+ rng = np.random.RandomState(88123100)
248
+ for i in range(10000):
249
+ dtimes = rng.rand(100)
250
+ data['observationStartMJD'] = dtimes.cumsum()
251
+ metric = metrics.RapidRevisitUniformityMetric(d_tmin=0.1,
252
+ d_tmax=0.8, min_nvisits=50)
253
+ result = metric.run(data)
254
+ resmin = np.min([resmin, result])
255
+ resmax = np.max([resmax, result])
256
+ print("RapidRevisitUniformity .. range", resmin, resmax)
257
+ """
258
+
259
+ def test_rapid_revisit_metric(self):
260
+ data = np.zeros(100, dtype=list(zip(["observationStartMJD"], [float])))
261
+ dtimes = np.arange(100) / 24.0 / 60.0
262
+ data["observationStartMJD"] = dtimes.cumsum()
263
+ # Set metric parameters to the actual N1/N2 values for these dtimes.
264
+ metric = metrics.RapidRevisitMetric(
265
+ d_tmin=40.0 / 60.0 / 60.0 / 24.0,
266
+ d_tpairs=20.0 / 60.0 / 24.0,
267
+ d_tmax=30.0 / 60.0 / 24.0,
268
+ min_n1=19,
269
+ min_n2=29,
270
+ )
271
+ result = metric.run(data)
272
+ self.assertEqual(result, 1)
273
+ # Set metric parameters to > N1/N2 values, to see it return 0.
274
+ metric = metrics.RapidRevisitMetric(
275
+ d_tmin=40.0 / 60.0 / 60.0 / 24.0,
276
+ d_tpairs=20.0 / 60.0 / 24.0,
277
+ d_tmax=30.0 / 60.0 / 24.0,
278
+ min_n1=30,
279
+ min_n2=50,
280
+ )
281
+ result = metric.run(data)
282
+ self.assertEqual(result, 0)
283
+ # Test with single value data.
284
+ data = np.zeros(1, dtype=list(zip(["observationStartMJD"], [float])))
285
+ result = metric.run(data)
286
+ self.assertEqual(result, 0)
287
+
288
+ def test_n_revisits_metric(self):
289
+ data = np.zeros(100, dtype=list(zip(["observationStartMJD"], [float])))
290
+ dtimes = np.arange(100) / 24.0 / 60.0
291
+ data["observationStartMJD"] = dtimes.cumsum()
292
+ metric = metrics.NRevisitsMetric(d_t=50.0)
293
+ result = metric.run(data)
294
+ self.assertEqual(result, 50)
295
+ metric = metrics.NRevisitsMetric(d_t=50.0, normed=True)
296
+ result = metric.run(data)
297
+ self.assertEqual(result, 0.5)
298
+
299
+ def test_transient_metric(self):
300
+ names = ["observationStartMJD", "fiveSigmaDepth", "band"]
301
+ types = [float, float, "<U1"]
302
+
303
+ ndata = 100
304
+ data_slice = np.zeros(ndata, dtype=list(zip(names, types)))
305
+ data_slice["observationStartMJD"] = np.arange(ndata)
306
+ data_slice["fiveSigmaDepth"] = 25
307
+ data_slice["band"] = "g"
308
+
309
+ metric = metrics.TransientMetric(survey_duration=ndata / 365.25)
310
+
311
+ # Should detect everything
312
+ self.assertEqual(metric.run(data_slice), 1.0)
313
+
314
+ # Double to survey duration, should now only detect half
315
+ metric = metrics.TransientMetric(survey_duration=ndata / 365.25 * 2)
316
+ self.assertEqual(metric.run(data_slice), 0.5)
317
+
318
+ # Set half of the m5 of the observations very bright,
319
+ # so kill another half.
320
+ data_slice["fiveSigmaDepth"][0:50] = 20
321
+ self.assertEqual(metric.run(data_slice), 0.25)
322
+
323
+ data_slice["fiveSigmaDepth"] = 25
324
+ # Demand lots of early observations
325
+ metric = metrics.TransientMetric(peak_time=0.5, n_pre_peak=3, survey_duration=ndata / 365.25)
326
+ self.assertEqual(metric.run(data_slice), 0.0)
327
+
328
+ # Demand a reasonable number of early observations
329
+ metric = metrics.TransientMetric(peak_time=2, n_pre_peak=2, survey_duration=ndata / 365.25)
330
+ self.assertEqual(metric.run(data_slice), 1.0)
331
+
332
+ # Demand multiple filters
333
+ metric = metrics.TransientMetric(n_filters=2, survey_duration=ndata / 365.25)
334
+ self.assertEqual(metric.run(data_slice), 0.0)
335
+
336
+ data_slice["band"] = ["r", "g"] * 50
337
+ self.assertEqual(metric.run(data_slice), 1.0)
338
+
339
+ # Demad too many observation per light curve
340
+ metric = metrics.TransientMetric(n_per_lc=20, survey_duration=ndata / 365.25)
341
+ self.assertEqual(metric.run(data_slice), 0.0)
342
+
343
+ # Test both filter and number of LC samples
344
+ metric = metrics.TransientMetric(n_filters=2, n_per_lc=3, survey_duration=ndata / 365.25)
345
+ self.assertEqual(metric.run(data_slice), 1.0)
346
+
347
+ def test_season_length_metric(self):
348
+ times = np.arange(0, 3650, 10)
349
+ data = np.zeros(
350
+ len(times),
351
+ dtype=list(zip(["observationStartMJD", "visitExposureTime"], [float, float])),
352
+ )
353
+ data["observationStartMJD"] = times
354
+ data["visitExposureTime"] = 30.0
355
+ metric = metrics.SeasonLengthMetric(reduce_func=np.median)
356
+ slice_point = {"ra": 0}
357
+ result = metric.run(data, slice_point)
358
+ self.assertEqual(result, 350)
359
+ times = np.arange(0, 3650, 365)
360
+ data = np.zeros(
361
+ len(times) * 2,
362
+ dtype=list(zip(["observationStartMJD", "visitExposureTime"], [float, float])),
363
+ )
364
+ data["observationStartMJD"][0 : len(times)] = times
365
+ data["observationStartMJD"][len(times) :] = times + 10
366
+ data["observationStartMJD"] = np.sort(data["observationStartMJD"])
367
+ data["visitExposureTime"] = 30.0
368
+ metric = metrics.SeasonLengthMetric(reduce_func=np.median)
369
+ slice_point = {"ra": 0}
370
+ result = metric.run(data, slice_point)
371
+ self.assertEqual(result, 10)
372
+ times = np.arange(0, 3650 - 365, 365)
373
+ data = np.zeros(
374
+ len(times) * 2,
375
+ dtype=list(zip(["observationStartMJD", "visitExposureTime"], [float, float])),
376
+ )
377
+ data["observationStartMJD"][0 : len(times)] = times
378
+ data["observationStartMJD"][len(times) :] = times + 10
379
+ data["observationStartMJD"] = np.sort(data["observationStartMJD"])
380
+ data["visitExposureTime"] = 30.0
381
+ metric = metrics.SeasonLengthMetric(reduce_func=np.size)
382
+ slice_point = {"ra": 0}
383
+ result = metric.run(data, slice_point)
384
+ self.assertEqual(result, 9)
385
+
386
+
387
+ if __name__ == "__main__":
388
+ unittest.main()