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,245 @@
1
+ import unittest
2
+ import warnings
3
+
4
+ import numpy as np
5
+
6
+ from rubin_sim.maf.slicers import OneDSlicer, UniSlicer
7
+
8
+
9
+ def make_data_values(size=100, min_val=0.0, max_val=1.0, random=-1):
10
+ """Generate a simple array of numbers, evenly arranged between min/max,
11
+ but (optional) random order."""
12
+ datavalues = np.arange(0, size, dtype="float")
13
+ datavalues *= (float(max_val) - float(min_val)) / (datavalues.max() - datavalues.min())
14
+ datavalues += min_val
15
+ if random > 0:
16
+ rng = np.random.RandomState(random)
17
+ randorder = rng.rand(size)
18
+ randind = np.argsort(randorder)
19
+ datavalues = datavalues[randind]
20
+ datavalues = np.array(list(zip(datavalues)), dtype=[("testdata", "float")])
21
+ return datavalues
22
+
23
+
24
+ class TestOneDSlicerSetup(unittest.TestCase):
25
+ def setUp(self):
26
+ self.testslicer = OneDSlicer(slice_col_name="testdata")
27
+
28
+ def tearDown(self):
29
+ del self.testslicer
30
+ self.testslicer = None
31
+
32
+ def test_slicertype(self):
33
+ """Test instantiation of slicer sets slicer type as expected."""
34
+ self.assertEqual(self.testslicer.slicer_name, self.testslicer.__class__.__name__)
35
+ self.assertEqual(self.testslicer.slicer_name, "OneDSlicer")
36
+
37
+ def test_setup_slicer_bins(self):
38
+ """Test setting up slicer using defined bins."""
39
+ dvmin = 0
40
+ dvmax = 1
41
+ nvalues = 1000
42
+ bins = np.arange(dvmin, dvmax + 0.05, 0.1)
43
+ dv = make_data_values(nvalues, dvmin, dvmax, random=4)
44
+ # Used right bins?
45
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bins=bins)
46
+ self.testslicer.setup_slicer(dv)
47
+ np.testing.assert_equal(self.testslicer.bins, bins)
48
+ self.assertEqual(self.testslicer.nslice, len(bins) - 1)
49
+
50
+ def test_setup_slicer_nbins_zeros(self):
51
+ """Test what happens if give slicer test data that is all
52
+ single-value."""
53
+ dv = np.zeros(100, float)
54
+ dv = np.array(list(zip(dv)), dtype=[("testdata", "float")])
55
+ bin_size = 0.1
56
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bin_size=bin_size)
57
+ with warnings.catch_warnings(record=True) as w:
58
+ warnings.simplefilter("always")
59
+ self.testslicer.setup_slicer(dv)
60
+ self.assertIn("creasing bin_max", str(w[-1].message))
61
+ self.assertEqual(self.testslicer.nslice, 2)
62
+
63
+ def test_setup_slicer_limits(self):
64
+ """Test setting up slicer using bin_min/max."""
65
+ bin_min = 0
66
+ bin_max = 1
67
+ dvmin = -0.5
68
+ dvmax = 1.5
69
+ dv = make_data_values(1000, dvmin, dvmax, random=342)
70
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bin_min=bin_min, bin_max=bin_max)
71
+ self.testslicer.setup_slicer(dv)
72
+ self.assertAlmostEqual(self.testslicer.bins.min(), bin_min)
73
+ self.assertAlmostEqual(self.testslicer.bins.max(), bin_max)
74
+
75
+ def test_setup_slicer_binsize(self):
76
+ """Test setting up slicer using bin_size."""
77
+ dvmin = 0
78
+ dvmax = 1
79
+ dv = make_data_values(1000, dvmin, dvmax, random=8977)
80
+ # Test basic use.
81
+ bin_size = 0.5
82
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bin_size=bin_size)
83
+ self.testslicer.setup_slicer(dv)
84
+ self.assertEqual(self.testslicer.nslice, (dvmax - dvmin) / bin_size)
85
+
86
+ def test_setup_slicer_freedman(self):
87
+ """Test that setting up the slicer using bins=None works."""
88
+ dvmin = 0
89
+ dvmax = 1
90
+ dv = make_data_values(1000, dvmin, dvmax, random=2234)
91
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bins=None)
92
+ self.testslicer.setup_slicer(dv)
93
+ # How many bins do you expect from optimal bin_size?
94
+ from rubin_sim.maf.utils import optimal_bins
95
+
96
+ bins = optimal_bins(dv["testdata"])
97
+ np.testing.assert_equal(self.testslicer.nslice, bins)
98
+
99
+
100
+ class TestOneDSlicerIteration(unittest.TestCase):
101
+ def setUp(self):
102
+ self.testslicer = OneDSlicer(slice_col_name="testdata")
103
+ dvmin = 0
104
+ dvmax = 1
105
+ nvalues = 1000
106
+ self.bins = np.arange(dvmin, dvmax, 0.01)
107
+ dv = make_data_values(nvalues, dvmin, dvmax, random=5678)
108
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bins=self.bins)
109
+ self.testslicer.setup_slicer(dv)
110
+
111
+ def tearDown(self):
112
+ del self.testslicer
113
+ self.testslicer = None
114
+
115
+ def test_iteration(self):
116
+ """Test iteration."""
117
+ for i, s in enumerate(self.testslicer):
118
+ self.assertEqual(s["slice_point"]["sid"], i)
119
+ self.assertEqual(s["slice_point"]["bin_left"], self.bins[i])
120
+ self.assertEqual(s["slice_point"]["bin_right"], self.bins[i + 1])
121
+ # Iteration stops while i<= nslice ..
122
+ # nslice = len(bins)-1 (and bins[i+2] is out of range
123
+ # but bins[i+1] is last RH edge of bins
124
+ self.assertEqual(i, self.testslicer.nslice - 1)
125
+
126
+ def test_get_item(self):
127
+ """Test that can return an individual indexed values of the slicer."""
128
+ for i in [0, 10, 20]:
129
+ self.assertEqual(self.testslicer[i]["slice_point"]["sid"], i)
130
+ self.assertEqual(self.testslicer[i]["slice_point"]["bin_left"], self.bins[i])
131
+
132
+
133
+ class TestOneDSlicerEqual(unittest.TestCase):
134
+ def setUp(self):
135
+ self.testslicer = OneDSlicer(slice_col_name="testdata")
136
+
137
+ def tearDown(self):
138
+ del self.testslicer
139
+ self.testslicer = None
140
+
141
+ def test_equivalence(self):
142
+ """Test equals method."""
143
+ # Note that two OneD slicers will be considered equal if
144
+ # they are both the same kind of slicer AND have the same bins.
145
+ # Set up self..
146
+ dvmin = 0
147
+ dvmax = 1
148
+ nvalues = 1000
149
+ bins = np.arange(dvmin, dvmax, 0.01)
150
+ dv = make_data_values(nvalues, dvmin, dvmax, random=32499)
151
+ # Set up reference
152
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bins=bins)
153
+ self.testslicer.setup_slicer(dv)
154
+ # Set up another slicer to match
155
+ # (same bins, although not the same data).
156
+ dv2 = make_data_values(nvalues + 100, dvmin, dvmax, random=334)
157
+ testslicer2 = OneDSlicer(slice_col_name="testdata", bins=bins)
158
+ testslicer2.setup_slicer(dv2)
159
+ self.assertTrue(self.testslicer == testslicer2)
160
+ self.assertFalse(self.testslicer != testslicer2)
161
+ # Set up another slicer that should not match
162
+ # (different bins, based on data)
163
+ dv2 = make_data_values(nvalues, dvmin + 1, dvmax + 1, random=445)
164
+ testslicer2 = OneDSlicer(slice_col_name="testdata", bins=None)
165
+ testslicer2.setup_slicer(dv2)
166
+ self.assertTrue(self.testslicer != testslicer2)
167
+ self.assertFalse(self.testslicer == testslicer2)
168
+ # Set up a different kind of slicer that should not match.
169
+ dv2 = make_data_values(100, 0, 1, random=12)
170
+ testslicer2 = UniSlicer()
171
+ testslicer2.setup_slicer(dv2)
172
+ self.assertTrue(self.testslicer != testslicer2)
173
+ self.assertFalse(self.testslicer == testslicer2)
174
+ # Get another oneDslicer that is not set up, and check equivalence.
175
+ testslicer2 = OneDSlicer(slice_col_name="testdata")
176
+ self.assertTrue(self.testslicer != testslicer2)
177
+ self.assertFalse(self.testslicer == testslicer2)
178
+ testslicer2 = OneDSlicer(slice_col_name="testdata", bin_min=0, bin_max=1, bin_size=0.5)
179
+ testslicer3 = OneDSlicer(slice_col_name="testdata", bin_min=0, bin_max=1, bin_size=0.5)
180
+ self.assertTrue(testslicer2 == testslicer3)
181
+ self.assertFalse(testslicer2 != testslicer3)
182
+ testslicer3 = OneDSlicer(slice_col_name="testdata", bin_min=0, bin_max=1)
183
+ self.assertFalse(testslicer2 == testslicer3)
184
+ self.assertTrue(testslicer2 != testslicer3)
185
+ usebins = np.arange(0, 1, 0.1)
186
+ testslicer2 = OneDSlicer(slice_col_name="testdata", bins=usebins)
187
+ testslicer3 = OneDSlicer(slice_col_name="testdata", bins=usebins)
188
+ self.assertTrue(testslicer2 == testslicer3)
189
+ self.assertFalse(testslicer2 != testslicer3)
190
+ testslicer3 = OneDSlicer(slice_col_name="testdata", bins=usebins + 1)
191
+ self.assertFalse(testslicer2 == testslicer3)
192
+ self.assertTrue(testslicer2 != testslicer3)
193
+
194
+
195
+ class TestOneDSlicerSlicing(unittest.TestCase):
196
+ long_message = True
197
+
198
+ def setUp(self):
199
+ self.testslicer = OneDSlicer(slice_col_name="testdata")
200
+
201
+ def tearDown(self):
202
+ del self.testslicer
203
+ self.testslicer = None
204
+
205
+ def test_slicing(self):
206
+ """Test slicing."""
207
+ dvmin = 0
208
+ dvmax = 1
209
+ stepsize = 0.01
210
+ bins = np.arange(dvmin, dvmax + stepsize / 2, stepsize)
211
+ # Test that testbinner raises appropriate error before it's set up
212
+ # (first time)
213
+ self.assertRaises(NotImplementedError, self.testslicer._slice_sim_data, 0)
214
+ # test that we're not dumping extra visits into the 'last bin'
215
+ # (that it's closed both sides)
216
+ nvalues = 1000
217
+ dv = make_data_values(nvalues, 0, 2, random=560)
218
+ bins = np.arange(0, 1.05, 0.1)
219
+ self.testslicer = OneDSlicer(slice_col_name="testdata", bins=bins)
220
+ nbins = len(bins) - 1
221
+ self.testslicer.setup_slicer(dv)
222
+ for i, s in enumerate(self.testslicer):
223
+ self.assertEqual(len(s["idxs"]), nvalues / float(nbins) / 2.0)
224
+
225
+ def test_night_slicing(self):
226
+ """Test slicing with 'night' column"""
227
+ numval = 1000
228
+ vals = np.arange(0, numval, 1) / (numval / 50)
229
+ nights = np.floor(vals)
230
+ np.random.shuffle(nights)
231
+ # If you were doing by-hand comparison, this can be useful
232
+ # bins = np.arange(0, 50.5, 1)
233
+ # vals, bb = np.histogram(nights, bins=bins)
234
+ vals = make_data_values(len(nights), random=10)
235
+ vals = np.array(list(zip(nights, vals["testdata"])), dtype=[("night", "int"), ("testdata", "float")])
236
+ test_slicer = OneDSlicer(slice_col_name="night", bins=np.arange(0, 50.5, 1))
237
+ test_slicer.setup_slicer(vals)
238
+ for s in test_slicer:
239
+ self.assertTrue(vals[s["idxs"]]["night"].min() >= s["slice_point"]["bin_left"])
240
+ self.assertTrue(vals[s["idxs"]]["night"].max() < s["slice_point"]["bin_right"])
241
+ self.assertEqual(len(s["idxs"]), numval / 50)
242
+
243
+
244
+ if __name__ == "__main__":
245
+ unittest.main()
@@ -0,0 +1,80 @@
1
+ import os
2
+ import sqlite3
3
+ import unittest
4
+
5
+ import numpy as np
6
+ from rubin_scheduler.data import get_data_dir
7
+
8
+ import rubin_sim.maf.utils.opsim_utils as opsimUtils
9
+
10
+ TEST_DB = "example_v3.4_0yrs.db"
11
+
12
+
13
+ class TestOpsimUtils(unittest.TestCase):
14
+ def test_scale_benchmarks(self):
15
+ """Test scaling the design and stretch benchmarks for the
16
+ length of the run.
17
+ """
18
+ # First test that method returns expected dictionaries.
19
+ for i in ("design", "stretch"):
20
+ benchmark = opsimUtils.scale_benchmarks(10.0, i)
21
+ self.assertIsInstance(benchmark, dict)
22
+ expectedkeys = (
23
+ "Area",
24
+ "nvisitsTotal",
25
+ "nvisits",
26
+ "seeing",
27
+ "skybrightness",
28
+ "singleVisitDepth",
29
+ )
30
+ expectedfilters = ("u", "g", "r", "i", "z", "y")
31
+ for k in expectedkeys:
32
+ self.assertIn(k, benchmark)
33
+ expecteddictkeys = (
34
+ "nvisits",
35
+ "seeing",
36
+ "skybrightness",
37
+ "singleVisitDepth",
38
+ )
39
+ for k in expecteddictkeys:
40
+ for f in expectedfilters:
41
+ self.assertIn(f, benchmark[k])
42
+
43
+ def test_calc_coadded_depth(self):
44
+ """Test the expected coadded depth calculation."""
45
+ benchmark = opsimUtils.scale_benchmarks(10, "design")
46
+ coadd = opsimUtils.calc_coadded_depth(benchmark["nvisits"], benchmark["singleVisitDepth"])
47
+ for f in coadd:
48
+ self.assertLess(coadd[f], 1000)
49
+ singlevisits = {"u": 1, "g": 1, "r": 1, "i": 1, "z": 1, "y": 1}
50
+ coadd = opsimUtils.calc_coadded_depth(singlevisits, benchmark["singleVisitDepth"])
51
+ for f in coadd:
52
+ self.assertAlmostEqual(coadd[f], benchmark["singleVisitDepth"][f])
53
+
54
+ def test_get_sim_data(self):
55
+ """Test that we can get simulation data"""
56
+ database_file = os.path.join(get_data_dir(), "tests", TEST_DB)
57
+ dbcols = ["fieldRA", "fieldDec", "scheduler_note"]
58
+ sql = "night < 10"
59
+ full_sql = "SELECT fieldRA, fieldDec, scheduler_note FROM observations where night < 10;"
60
+ # Check that we get data the usual way
61
+ data = opsimUtils.get_sim_data(database_file, sql, dbcols)
62
+ assert np.size(data) > 0
63
+
64
+ # Check that we can pass a connection object
65
+ con = sqlite3.connect(database_file)
66
+ data = opsimUtils.get_sim_data(con, sql, dbcols)
67
+ con.close()
68
+ assert np.size(data) > 0
69
+
70
+ # Check that kwarg overrides sqlconstraint and dbcols
71
+ data = opsimUtils.get_sim_data(database_file, "blah blah", ["nocol"], full_sql_query=full_sql)
72
+ assert np.size(data) > 0
73
+
74
+ # Check that bad file raises an error
75
+ with self.assertRaises(FileNotFoundError):
76
+ opsimUtils.get_sim_data("not_a_file.db", sql, ["nocol"])
77
+
78
+
79
+ if __name__ == "__main__":
80
+ unittest.main()
@@ -0,0 +1,134 @@
1
+ # imports
2
+ import unittest
3
+
4
+ import numpy as np
5
+ from matplotlib.figure import Figure
6
+ from rubin_scheduler.scheduler.model_observatory import ModelObservatory
7
+
8
+ import rubin_sim.maf as maf
9
+
10
+
11
+ class TestPlotters(unittest.TestCase):
12
+ def setUp(self):
13
+ # Set a seed to make the tests reproducible
14
+ self.rng = np.random.default_rng(seed=1234)
15
+
16
+ def test_healpix_plotters(self):
17
+ # Set up a metric bundle to send to plotters
18
+ bundle1 = maf.create_empty_metric_bundle()
19
+ nside = 64
20
+ bundle1.slicer = maf.HealpixSlicer(nside=nside)
21
+ bundle1._setup_metric_values()
22
+ bundle1.metric_values += self.rng.uniform(size=len(bundle1.slicer))
23
+ # First test healpix sky map - just that it runs.
24
+ bundle1.set_plot_funcs([maf.HealpixSkyMap()])
25
+ figs = bundle1.plot()
26
+ self.assertTrue(isinstance(figs["SkyMap"], Figure))
27
+ # Test healpix histogram - just that it runs
28
+ bundle1.set_plot_funcs([maf.HealpixHistogram()])
29
+ figs = bundle1.plot()
30
+ self.assertTrue(isinstance(figs["Histogram"], Figure))
31
+ # Test power spectrum
32
+ bundle1.set_plot_funcs([maf.HealpixPowerSpectrum()])
33
+ figs = bundle1.plot()
34
+ self.assertTrue(isinstance(figs["PowerSpectrum"], Figure))
35
+
36
+ def test_base_skymap(self):
37
+ bundle1 = maf.create_empty_metric_bundle()
38
+ npoints = 1000
39
+ ra = self.rng.uniform(low=0, high=360, size=npoints)
40
+ dec = self.rng.uniform(low=-90, high=90, size=npoints)
41
+ bundle1.slicer = maf.UserPointsSlicer(ra, dec)
42
+ bundle1._setup_metric_values()
43
+ bundle1.metric_values += self.rng.uniform(size=len(bundle1.slicer))
44
+ # Test skymap
45
+ bundle1.set_plot_funcs([maf.BaseSkyMap()])
46
+ figs = bundle1.plot()
47
+ self.assertTrue(isinstance(figs["SkyMap"], Figure))
48
+ # Test healpix histogram - just that it runs
49
+ bundle1.set_plot_funcs([maf.BaseHistogram()])
50
+ figs = bundle1.plot()
51
+ self.assertTrue(isinstance(figs["Histogram"], Figure))
52
+
53
+ def test_oned_plotter(self):
54
+ bundle1 = maf.create_empty_metric_bundle()
55
+ npoints = 100
56
+ bins = np.arange(0, npoints, 1)
57
+ bundle1.slicer = maf.OneDSlicer(slice_col_name="test", bins=bins)
58
+ bundle1.slicer.slice_points = {"bins": bins}
59
+ bundle1.slicer.nslice = len(bins) - 1
60
+ bundle1.slicer.shape = len(bins) - 1
61
+ bundle1._setup_metric_values()
62
+ bundle1.metric_values += self.rng.uniform(size=len(bundle1.slicer))
63
+ # Test plotter
64
+ bundle1.set_plot_funcs([maf.OneDBinnedData()])
65
+ figs = bundle1.plot()
66
+ self.assertTrue(isinstance(figs["BinnedData"], Figure))
67
+
68
+ def test_hpxmap_plotter(self):
69
+ bundle = maf.create_empty_metric_bundle()
70
+ nside = 64
71
+ bundle.slicer = maf.HealpixSlicer(nside=nside)
72
+ bundle._setup_metric_values()
73
+ bundle.metric_values += self.rng.uniform(size=len(bundle.slicer))
74
+
75
+ plotter = maf.HpxmapPlotter()
76
+ bundle.set_plot_funcs([plotter])
77
+ _ = bundle.plot()
78
+
79
+ def test_visit_perimeter_plotter(self):
80
+ model_observatory = ModelObservatory(init_load_length=1)
81
+
82
+ num_points = 5
83
+ field_ra = np.arange(30, 30 + num_points, dtype=float)
84
+ field_dec = np.arange(-60, -60 + num_points, dtype=float)
85
+ rot_sky_pos = np.arange(num_points, dtype=float) % 360
86
+
87
+ names = ["fieldRA", "fieldDec", "rotSkyPos"]
88
+ dtypes = [float] * 3
89
+ data = np.empty(field_ra.size, dtype=list(zip(names, dtypes)))
90
+ data["fieldRA"] = field_ra
91
+ data["fieldDec"] = field_dec
92
+ data["rotSkyPos"] = rot_sky_pos
93
+
94
+ unmasked_data = np.empty(dtype=object, shape=(1,))
95
+ unmasked_data[0] = data
96
+ masked_data = np.ma.MaskedArray(data=unmasked_data, mask=False, fill_value=-666, dtype=object)
97
+
98
+ bundle = maf.create_empty_metric_bundle()
99
+ bundle.slicer = maf.UniSlicer()
100
+ bundle._setup_metric_values()
101
+ bundle.metric_values = masked_data
102
+
103
+ def compute_camera_perimeter(ra, decl, rotation):
104
+ # just a quadrangle for this unit test.
105
+ # the math isn't quite right for an actual square,
106
+ # but good enough for a unit test.
107
+ size = 1.0
108
+ ras = [
109
+ ra - 0.5 * size * np.cos(np.radians(decl)) * np.sin(np.radians(rotation)),
110
+ ra - 0.5 * size * np.cos(np.radians(decl)) * np.cos(np.radians(rotation)),
111
+ ra + 0.5 * size * np.cos(np.radians(decl)) * np.sin(np.radians(rotation)),
112
+ ra + 0.5 * size * np.cos(np.radians(decl)) * np.cos(np.radians(rotation)),
113
+ ]
114
+ decls = [
115
+ decl + 0.5 * size * np.cos(np.radians(rotation)),
116
+ decl - 0.5 * size * np.sin(np.radians(rotation)),
117
+ decl - 0.5 * size * np.cos(np.radians(rotation)),
118
+ decl + 0.5 * size * np.sin(np.radians(rotation)),
119
+ ]
120
+ return ras, decls
121
+
122
+ plot_dict = {
123
+ "camera_perimeter_func": compute_camera_perimeter,
124
+ "model_observatory": model_observatory,
125
+ "decorations": ["ecliptic", "galactic_plane", "sun", "moon", "horizon"],
126
+ }
127
+ plotter = maf.VisitPerimeterPlotter()
128
+ bundle.set_plot_funcs([plotter])
129
+ bundle.set_plot_dict(plot_dict)
130
+ _ = bundle.plot()
131
+
132
+
133
+ if __name__ == "__main__":
134
+ unittest.main()
@@ -0,0 +1,145 @@
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ import unittest
5
+ import warnings
6
+
7
+ import numpy as np
8
+
9
+ import rubin_sim.maf.db as db
10
+
11
+
12
+ class TestResultsDb(unittest.TestCase):
13
+ def setUp(self):
14
+ self.out_dir = "Out"
15
+ self.metric_name = "Count ExpMJD"
16
+ self.slicer_name = "OneDSlicer"
17
+ self.run_name = "fakeopsim"
18
+ self.sql_constraint = ""
19
+ self.info_label = "Dithered"
20
+ self.metric_data_file = "testmetricdatafile.npz"
21
+ self.plot_type = "BinnedData"
22
+ self.plot_name = "testmetricplot_BinnedData.png"
23
+ self.summary_stat_name1 = "Mean"
24
+ self.summary_stat_value1 = 20
25
+ self.summary_stat_name2 = "Median"
26
+ self.summary_stat_value2 = 18
27
+ self.summary_stat_name3 = "TableFrac"
28
+ self.summary_stat_value3 = np.empty(10, dtype=[("name", "|S12"), ("value", float)])
29
+ for i in range(10):
30
+ self.summary_stat_value3["name"] = "test%d" % (i)
31
+ self.summary_stat_value3["value"] = i
32
+ self.display_dict = {
33
+ "group": "seeing",
34
+ "subgroup": "all",
35
+ "order": 1,
36
+ "caption": "lalalalal",
37
+ }
38
+
39
+ def test_db_creation(self):
40
+ # Test default sqlite file created.
41
+ tempdir = tempfile.mkdtemp(prefix="resDb")
42
+ resultsdb = db.ResultsDb(out_dir=tempdir)
43
+ self.assertTrue(os.path.isfile(os.path.join(tempdir, "resultsDb_sqlite.db")))
44
+ resultsdb.close()
45
+ # Test that get appropriate exception if directory doesn't exist.
46
+ sqlitefilename = os.path.join(self.out_dir + "test", "testDb_sqlite.db")
47
+ self.assertRaises(ValueError, db.ResultsDb, database=sqlitefilename)
48
+ shutil.rmtree(tempdir)
49
+
50
+ def test_add_data(self):
51
+ tempdir = tempfile.mkdtemp(prefix="resDb")
52
+ results_db = db.ResultsDb(out_dir=tempdir)
53
+ # Add metric.
54
+ metric_id = results_db.update_metric(
55
+ self.metric_name,
56
+ self.slicer_name,
57
+ self.run_name,
58
+ self.sql_constraint,
59
+ self.info_label,
60
+ self.metric_data_file,
61
+ )
62
+ # Try to re-add metric
63
+ # (should get back same metric id as previous, with no add).
64
+ metric_id2 = results_db.update_metric(
65
+ self.metric_name,
66
+ self.slicer_name,
67
+ self.run_name,
68
+ self.sql_constraint,
69
+ self.info_label,
70
+ self.metric_data_file,
71
+ )
72
+ self.assertEqual(metric_id, metric_id2)
73
+ run1 = results_db.session.query(db.MetricRow).filter_by(metric_id=metric_id).all()
74
+ self.assertEqual(len(run1), 1)
75
+ # Add plot.
76
+ results_db.update_plot(metric_id, self.plot_type, self.plot_name)
77
+ # Add normal summary statistics.
78
+ results_db.update_summary_stat(metric_id, self.summary_stat_name1, self.summary_stat_value1)
79
+ results_db.update_summary_stat(metric_id, self.summary_stat_name2, self.summary_stat_value2)
80
+ # Add something like tableFrac summary statistic.
81
+ results_db.update_summary_stat(metric_id, self.summary_stat_name3, self.summary_stat_value3)
82
+ # Test get warning when try to add a non-conforming summary stat
83
+ # (not 'name' & 'value' cols).
84
+ teststat = np.empty(10, dtype=[("col", "|S12"), ("value", float)])
85
+ with warnings.catch_warnings(record=True) as w:
86
+ warnings.simplefilter("always")
87
+ results_db.update_summary_stat(metric_id, "testfail", teststat)
88
+ self.assertIn("not save", str(w[-1].message))
89
+ # Test we get warning when try to add a string (non-conforming)
90
+ # summary stat.
91
+ teststat = "teststring"
92
+ with warnings.catch_warnings(record=True) as w:
93
+ warnings.simplefilter("always")
94
+ results_db.update_summary_stat(metric_id, "testfail", teststat)
95
+ self.assertIn("not save", str(w[-1].message))
96
+ shutil.rmtree(tempdir)
97
+
98
+
99
+ class TestUseResultsDb(unittest.TestCase):
100
+ def setUp(self):
101
+ self.out_dir = "Out"
102
+ self.metric_name = "Count ExpMJD"
103
+ self.slicer_name = "OneDSlicer"
104
+ self.run_name = "fakeopsim"
105
+ self.constraint = ""
106
+ self.info_label = "Dithered"
107
+ self.metric_data_file = "testmetricdatafile.npz"
108
+ self.plot_type = "BinnedData"
109
+ self.plot_name = "testmetricplot_BinnedData.png"
110
+ self.summary_stat_name1 = "Mean"
111
+ self.summary_stat_value1 = 20
112
+ self.summary_stat_name2 = "Median"
113
+ self.summary_stat_value2 = 18
114
+ self.tempdir = tempfile.mkdtemp(prefix="resDb")
115
+ self.results_db = db.ResultsDb(self.tempdir)
116
+ self.metric_id = self.results_db.update_metric(
117
+ self.metric_name,
118
+ self.slicer_name,
119
+ self.run_name,
120
+ self.constraint,
121
+ self.info_label,
122
+ self.metric_data_file,
123
+ )
124
+ self.results_db.update_plot(self.metric_id, self.plot_type, self.plot_name)
125
+ self.results_db.update_summary_stat(self.metric_id, self.summary_stat_name1, self.summary_stat_value1)
126
+ self.results_db.update_summary_stat(self.metric_id, self.summary_stat_name2, self.summary_stat_value2)
127
+
128
+ def testget_ids(self):
129
+ mids = self.results_db.get_all_metric_ids()
130
+ self.assertEqual(mids[0], self.metric_id)
131
+ mid = self.results_db.get_metric_id(self.metric_name)
132
+ self.assertEqual(mid[0], self.metric_id)
133
+ mid = self.results_db.get_metric_id("notreal")
134
+ self.assertEqual(len(mid), 0)
135
+
136
+ def testshow_summary(self):
137
+ self.results_db.get_summary_stats()
138
+
139
+ def tearDown(self):
140
+ self.results_db.close()
141
+ shutil.rmtree(self.tempdir)
142
+
143
+
144
+ if __name__ == "__main__":
145
+ unittest.main()
@@ -0,0 +1,14 @@
1
+ import unittest
2
+
3
+ import numpy as np
4
+
5
+ import rubin_sim.maf.metrics as metrics
6
+
7
+
8
+ class TestSchedviewMetrics(unittest.TestCase):
9
+ def test_age_metric(self):
10
+ data = np.rec.fromrecords([(1, 60000)], names="id,observationStartMJD")
11
+
12
+ assert metrics.AgeMetric(60002).run(data) == 2
13
+ assert metrics.AgeMetric(60002.5).run(data) == 2.5
14
+ assert np.isnan(metrics.AgeMetric(70000.0).run(data))