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,219 @@
1
+ import os
2
+ import unittest
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+ from astropy.time import Time
7
+ from rubin_scheduler.data import get_data_dir
8
+
9
+ from rubin_sim.moving_objects import Orbits, PyOrbEphemerides
10
+
11
+
12
+ @unittest.skip("Temporary skip until ephemerides replaced")
13
+ class TestPyOrbEphemerides(unittest.TestCase):
14
+ def setUp(self):
15
+ self.testdir = os.path.join(get_data_dir(), "tests", "orbits_testdata")
16
+ self.orbits = Orbits()
17
+ self.orbits.read_orbits(os.path.join(self.testdir, "test_orbitsQ.des"))
18
+ self.orbits_kep = Orbits()
19
+ self.orbits_kep.read_orbits(os.path.join(self.testdir, "test_orbitsA.des"))
20
+ self.ephems = PyOrbEphemerides()
21
+ self.ephems.set_orbits(self.orbits)
22
+ self.len_ephems_basic = 11
23
+ self.len_ephems_full = 34
24
+
25
+ def tear_down(self):
26
+ del self.orbits
27
+ del self.orbits_kep
28
+ del self.ephems
29
+
30
+ def test_which_pyoorb(self):
31
+ import pyoorb
32
+
33
+ print(pyoorb.__file__)
34
+
35
+ def test_set_orbits(self):
36
+ # Test that we can set orbits.
37
+ self.ephems.set_orbits(self.orbits)
38
+ # Test that setting with an empty orbit object fails.
39
+ # (Avoids hard-to-interpret errors from pyoorb).
40
+ with self.assertRaises(ValueError):
41
+ empty_orb = Orbits()
42
+ empty = pd.DataFrame([], columns=self.orbits.data_cols["KEP"])
43
+ empty_orb.set_orbits(empty)
44
+ self.ephems.set_orbits(empty_orb)
45
+
46
+ def test_convert_to_oorb_array(self):
47
+ # Check that orbital elements are converted.
48
+ self.ephems._convert_to_oorb_elem(self.orbits.orbits, self.orbits.orb_format)
49
+ self.assertEqual(len(self.ephems.oorb_elem), len(self.orbits))
50
+ self.assertEqual(self.ephems.oorb_elem[0][7], 2)
51
+ self.assertEqual(self.ephems.oorb_elem[0][9], 3)
52
+ self.assertEqual(self.ephems.oorb_elem[0][1], self.orbits.orbits["q"][0])
53
+ # Test that we can convert KEP orbital elements too.
54
+ self.ephems._convert_to_oorb_elem(self.orbits_kep.orbits, self.orbits_kep.orb_format)
55
+ self.assertEqual(len(self.ephems.oorb_elem), len(self.orbits_kep))
56
+ self.assertEqual(self.ephems.oorb_elem[0][7], 3)
57
+ self.assertEqual(self.ephems.oorb_elem[0][1], self.orbits_kep.orbits["a"][0])
58
+
59
+ def test_convert_from_oorb_array(self):
60
+ # Check that we can convert orbital elements TO oorb format and back
61
+ # without losing info
62
+ # (except ObjId -- we will lose that unless we use updateOrbits.)
63
+ self.ephems._convert_to_oorb_elem(self.orbits.orbits, self.orbits.orb_format)
64
+ new_orbits = Orbits()
65
+ new_orbits.set_orbits(self.orbits.orbits)
66
+ new_orbits.update_orbits(self.ephems.convert_from_oorb_elem())
67
+ self.assertEqual(new_orbits, self.orbits)
68
+
69
+ def test_convert_times(self):
70
+ times = np.arange(49353, 49353 + 10, 0.5)
71
+ eph_times = self.ephems._convert_times(times, "UTC")
72
+ # Check that shape of eph_times is correct. (times x 2)
73
+ self.assertEqual(eph_times.shape[0], len(times))
74
+ self.assertEqual(eph_times.shape[1], 2)
75
+ # Check that 'timescale' for eph_times is correct.
76
+ self.assertEqual(eph_times[0][1], 1)
77
+ eph_times = self.ephems._convert_times(times, "TAI")
78
+ self.assertEqual(eph_times[0][1], 4)
79
+
80
+ def test_oorb_ephemeris(self):
81
+ self.ephems.set_orbits(self.orbits)
82
+ times = np.arange(49353, 49353 + 3, 0.25)
83
+ eph_times = self.ephems._convert_times(times)
84
+ # Basic ephemerides.
85
+ oorb_ephs = self.ephems._generate_oorb_ephs_basic(eph_times, obscode=807, eph_mode="N")
86
+ # Check that it returned the right sort of array.
87
+ self.assertEqual(
88
+ oorb_ephs.shape,
89
+ (len(self.ephems.oorb_elem), len(times), self.len_ephems_basic),
90
+ )
91
+ # Full ephemerides
92
+ oorb_ephs = self.ephems._generate_oorb_ephs_full(eph_times, obscode=807, eph_mode="N")
93
+ # Check that it returned the right sort of array.
94
+ self.assertEqual(
95
+ oorb_ephs.shape,
96
+ (len(self.ephems.oorb_elem), len(times), self.len_ephems_full),
97
+ )
98
+
99
+ def test_ephemeris(self):
100
+ # Calculate and convert ephemerides.
101
+ self.ephems.set_orbits(self.orbits)
102
+ times = np.arange(49353, 49353 + 2, 0.3)
103
+ eph_times = self.ephems._convert_times(times)
104
+ oorb_ephs = self.ephems._generate_oorb_ephs_basic(eph_times, obscode=807)
105
+ # Group by object, and check grouping.
106
+ ephs = self.ephems._convert_oorb_ephs_basic(oorb_ephs, by_object=True)
107
+ self.assertEqual(len(ephs), len(self.orbits))
108
+ # Group by time, and check grouping.
109
+ oorb_ephs = self.ephems._generate_oorb_ephs_basic(eph_times, obscode=807)
110
+ ephs = self.ephems._convert_oorb_ephs_basic(oorb_ephs, by_object=False)
111
+ self.assertEqual(len(ephs), len(times))
112
+ # And test all-wrapped-up method:
113
+ ephs_all = self.ephems.generate_ephemerides(
114
+ times,
115
+ obscode=807,
116
+ eph_mode="N",
117
+ eph_type="basic",
118
+ time_scale="UTC",
119
+ by_object=False,
120
+ )
121
+ # See https://rubinobs.atlassian.net/browse/SP-1633
122
+ # This needs to be fixed, but on a separate ticket
123
+ # for key in ephs_all.dtype.names:
124
+ # np.testing.assert_almost_equal(ephs_all[key], ephs[key])
125
+
126
+ # Reset ephems to use KEP Orbits, and calculate new ephemerides.
127
+ self.ephems.set_orbits(self.orbits_kep)
128
+ oorb_ephs = self.ephems._generate_oorb_ephs_basic(eph_times, obscode=807, eph_mode="N")
129
+ ephs_kep = self.ephems._convert_oorb_ephs_basic(oorb_ephs, by_object=True)
130
+ self.assertEqual(len(ephs_kep), len(self.orbits_kep))
131
+ oorb_ephs = self.ephems._generate_oorb_ephs_basic(eph_times, obscode=807, eph_mode="N")
132
+ ephs_kep = self.ephems._convert_oorb_ephs_basic(oorb_ephs, by_object=False)
133
+ self.assertEqual(len(ephs_kep), len(times))
134
+ # And test all-wrapped-up method:
135
+ ephs_all_kep = self.ephems.generate_ephemerides(
136
+ times,
137
+ obscode=807,
138
+ eph_mode="N",
139
+ eph_type="basic",
140
+ time_scale="UTC",
141
+ by_object=False,
142
+ )
143
+ # Also https://rubinobs.atlassian.net/browse/SP-1633
144
+ # for key in ephs_all_kep.dtype.names:
145
+ # np.testing.assert_almost_equal(ephs_all_kep[key], ephs_kep[key])
146
+
147
+ # Check that ephemerides calculated from the different (COM/KEP)
148
+ # orbits are almost equal
149
+ for column in ephs.dtype.names:
150
+ np.testing.assert_allclose(ephs[column], ephs_kep[column], rtol=1e-5, atol=1e-4)
151
+ # Check that the wrapped method using KEP elements and the wrapped
152
+ # method using COM elements match.
153
+ for column in ephs_all.dtype.names:
154
+ np.testing.assert_allclose(ephs_all_kep[column], ephs_all[column], rtol=1e-5, atol=1e-4)
155
+
156
+
157
+ @unittest.skip("Temporary skip until ephemerides replaced")
158
+ class TestJPLValues(unittest.TestCase):
159
+ """Test the oorb generated RA/Dec values against
160
+ JPL generated RA/Dec values."""
161
+
162
+ def setUp(self):
163
+ # Read orbits.
164
+ self.orbits = Orbits()
165
+ self.jpl_dir = os.path.join(get_data_dir(), "tests", "jpl_testdata")
166
+ self.orbits.read_orbits(os.path.join(self.jpl_dir, "S0_n747.des"), skiprows=1)
167
+ # Read JPL ephems.
168
+ self.jpl = pd.read_csv(os.path.join(self.jpl_dir, "807_n747.txt"), sep=r"\s+")
169
+ # Temp key fix
170
+ self.jpl["obj_id"] = self.jpl["objId"]
171
+ # Add times in TAI and UTC, because.
172
+ t = Time(self.jpl["epoch_mjd"], format="mjd", scale="utc")
173
+ self.jpl["mjdTAI"] = t.tai.mjd
174
+ self.jpl["mjdUTC"] = t.utc.mjd
175
+
176
+ def tear_down(self):
177
+ del self.orbits
178
+ del self.jpl
179
+
180
+ def test_ra_dec(self):
181
+ # We won't compare Vmag, because this also needs information
182
+ # on trailing losses.
183
+ times = self.jpl["mjdUTC"].unique()
184
+ delta_ra = np.zeros(len(times), float)
185
+ delta_dec = np.zeros(len(times), float)
186
+ for i, t in enumerate(times):
187
+ # Find the JPL obj_ids visible at this time.
188
+ j = self.jpl.query("mjdUTC == @t").sort_values("obj_id")
189
+ # Set the ephems, using the objects seen at this time.
190
+ suborbits = self.orbits.orbits.query("obj_id in @j.obj_id").sort_values("obj_id")
191
+ sub_orbits = Orbits()
192
+ sub_orbits.set_orbits(suborbits)
193
+ ephems = PyOrbEphemerides()
194
+ ephems.set_orbits(sub_orbits)
195
+ ephs = ephems.generate_ephemerides(
196
+ [t],
197
+ time_scale="UTC",
198
+ obscode=807,
199
+ eph_mode="N",
200
+ eph_type="Basic",
201
+ by_object=False,
202
+ )
203
+ delta_ra[i] = np.abs(ephs["ra"] - j["ra_deg"].values).max()
204
+ delta_dec[i] = np.abs(ephs["dec"] - j["dec_deg"].values).max()
205
+ # Convert to mas
206
+ delta_ra *= 3600.0 * 1000.0
207
+ delta_dec *= 3600.0 * 1000.0
208
+ # Much of the time we're closer than 1mas,
209
+ # but there are a few which hit higher values.
210
+ print("max JPL errors", np.max(delta_ra), np.max(delta_dec))
211
+ print("std JPL errors", np.std(delta_ra), np.std(delta_dec))
212
+ self.assertLess(np.max(delta_ra), 25)
213
+ self.assertLess(np.max(delta_dec), 25)
214
+ self.assertLess(np.std(delta_ra), 3)
215
+ self.assertLess(np.std(delta_dec), 3)
216
+
217
+
218
+ if __name__ == "__main__":
219
+ unittest.main()
@@ -0,0 +1,170 @@
1
+ import os
2
+ import unittest
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+ from pandas.testing import assert_frame_equal
7
+ from rubin_scheduler.data import get_data_dir
8
+
9
+ from rubin_sim.moving_objects import Orbits
10
+
11
+
12
+ class TestOrbits(unittest.TestCase):
13
+ def setUp(self):
14
+ self.testdir = os.path.join(get_data_dir(), "tests", "orbits_testdata")
15
+
16
+ def test_equal_not_equal(self):
17
+ orbits = Orbits()
18
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsQ.des"))
19
+ self.assertEqual(len(orbits), 4)
20
+ orbits2 = Orbits()
21
+ orbits2.read_orbits(os.path.join(self.testdir, "test_orbitsQ.des"))
22
+ self.assertEqual(orbits, orbits2)
23
+ orbits3 = Orbits()
24
+ orbits3.read_orbits(os.path.join(self.testdir, "test_orbitsA.des"))
25
+ self.assertNotEqual(orbits, orbits3)
26
+
27
+ def test_iteration_and_indexing(self):
28
+ orbits = Orbits()
29
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsNEO.s3m"))
30
+ orbits_single = orbits[0]
31
+ assert_frame_equal(orbits_single.orbits, orbits.orbits.query("index==0"))
32
+ orbits_single = orbits[3]
33
+ assert_frame_equal(orbits_single.orbits, orbits.orbits.query("index==3"))
34
+ # Test iteration through all orbits.
35
+ for orb, (i, orbi) in zip(orbits, orbits.orbits.iterrows()):
36
+ self.assertEqual(orb.orbits.obj_id.values[0], orbi.obj_id)
37
+ self.assertTrue(isinstance(orb, Orbits))
38
+ self.assertEqual(orb.orbits.index, i)
39
+ # Test iteration through a subset of orbits.
40
+ orbits_sub = Orbits()
41
+ orbits_sub.set_orbits(orbits.orbits.query("index > 4"))
42
+ for orb, (i, orbi) in zip(orbits_sub, orbits_sub.orbits.iterrows()):
43
+ self.assertEqual(orb.orbits.obj_id.values[0], orbi.obj_id)
44
+ self.assertTrue(isinstance(orb, Orbits))
45
+ self.assertEqual(orb.orbits.index, i)
46
+
47
+ def test_slicing(self):
48
+ """
49
+ Test that we can slice a collection of orbits
50
+ """
51
+ orbits = Orbits()
52
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsNEO.s3m"))
53
+ orbit_slice = orbits[2:6]
54
+ self.assertEqual(orbit_slice[0], orbits[2])
55
+ self.assertEqual(orbit_slice[1], orbits[3])
56
+ self.assertEqual(orbit_slice[2], orbits[4])
57
+ self.assertEqual(orbit_slice[3], orbits[5])
58
+ self.assertEqual(len(orbit_slice), 4)
59
+
60
+ orbit_slice = orbits[1:7:2]
61
+ self.assertEqual(orbit_slice[0], orbits[1])
62
+ self.assertEqual(orbit_slice[1], orbits[3])
63
+ self.assertEqual(orbit_slice[2], orbits[5])
64
+ self.assertEqual(len(orbit_slice), 3)
65
+
66
+ def test_offset_dataframe(self):
67
+ """
68
+ Test that we can slice and iterate through an orbits
69
+ dataframe that has already been sub-selected from another
70
+ dataframe.
71
+ """
72
+ orbits0 = Orbits()
73
+ orbits0.read_orbits(os.path.join(self.testdir, "test_orbitsNEO.s3m"))
74
+
75
+ orbits_sub = Orbits()
76
+ orbits_sub.set_orbits(orbits0.orbits.query("index>1"))
77
+
78
+ self.assertEqual(len(orbits_sub), 6)
79
+
80
+ orbit_slice = orbits_sub[2:6]
81
+ self.assertEqual(orbit_slice[0], orbits_sub[2])
82
+ self.assertEqual(orbit_slice[1], orbits_sub[3])
83
+ self.assertEqual(orbit_slice[2], orbits_sub[4])
84
+ self.assertEqual(orbit_slice[3], orbits_sub[5])
85
+ self.assertEqual(len(orbit_slice), 4)
86
+
87
+ orbit_slice = orbits_sub[1:5:2]
88
+ self.assertEqual(orbit_slice[0], orbits_sub[1])
89
+ self.assertEqual(orbit_slice[1], orbits_sub[3])
90
+ self.assertEqual(len(orbit_slice), 2)
91
+
92
+ for ii, oo in enumerate(orbits_sub):
93
+ self.assertEqual(oo, orbits0[ii + 2])
94
+
95
+ def test_read_orbits(self):
96
+ orbits = Orbits()
97
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsQ.des"))
98
+ self.assertEqual(len(orbits), 4)
99
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsA.des"))
100
+ self.assertEqual(len(orbits), 4)
101
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsCAR.des"))
102
+ self.assertEqual(len(orbits), 1)
103
+ with self.assertRaises(ValueError):
104
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsBadMix.des"))
105
+ with self.assertRaises(ValueError):
106
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsBad.des"))
107
+
108
+ def test_set_orbits(self):
109
+ orbits = Orbits()
110
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsQ.des"))
111
+ # Test that we can set the orbits using a dataframe.
112
+ suborbits = orbits.orbits.head(1)
113
+ new_orbits = Orbits()
114
+ new_orbits.set_orbits(suborbits)
115
+ self.assertEqual(len(new_orbits), 1)
116
+ self.assertEqual(new_orbits.orb_format, "COM")
117
+ assert_frame_equal(new_orbits.orbits, suborbits)
118
+ # Test that we can set the orbits using a Series.
119
+ for i, sso in suborbits.iterrows():
120
+ new_orbits = Orbits()
121
+ new_orbits.set_orbits(sso)
122
+ self.assertEqual(len(new_orbits), 1)
123
+ self.assertEqual(new_orbits.orb_format, "COM")
124
+ assert_frame_equal(new_orbits.orbits, suborbits)
125
+ # Test that we can set the orbits using a numpy array of many objects.
126
+ numpyorbits = orbits.orbits.to_records(index=False)
127
+ new_orbits = Orbits()
128
+ new_orbits.set_orbits(numpyorbits)
129
+ self.assertEqual(len(new_orbits), len(orbits))
130
+ self.assertEqual(new_orbits.orb_format, "COM")
131
+ assert_frame_equal(new_orbits.orbits, orbits.orbits)
132
+ # And test that this works for a single row of the numpy array.
133
+ onenumpyorbits = numpyorbits[0]
134
+ new_orbits = Orbits()
135
+ new_orbits.set_orbits(onenumpyorbits)
136
+ self.assertEqual(len(new_orbits), 1)
137
+ self.assertEqual(new_orbits.orb_format, "COM")
138
+ assert_frame_equal(new_orbits.orbits, suborbits)
139
+ # And test that it fails appropriately when columns are not correct.
140
+ neworbits = pd.DataFrame(orbits.orbits)
141
+ newcols = neworbits.columns.values.tolist()
142
+ newcols[0] = "ssmId"
143
+ newcols[3] = "ecc"
144
+ neworbits.columns = newcols
145
+ new_orbits = Orbits()
146
+ with self.assertRaises(ValueError):
147
+ new_orbits.set_orbits(neworbits)
148
+
149
+ def test_set_seds(self):
150
+ """
151
+ Test that the self-assignment of SEDs works as expected.
152
+ """
153
+ orbits = Orbits()
154
+ # Test with a range of a values.
155
+ a = np.arange(0, 5, 0.05)
156
+ orbs = pd.DataFrame(a, columns=["a"])
157
+ seds = orbits.assign_sed(orbs)
158
+ self.assertEqual(np.unique(seds[np.where(a < 2)]), "S.dat")
159
+ self.assertEqual(np.unique(seds[np.where(a > 4)]), "C.dat")
160
+ # Test when read a values.
161
+ orbits.read_orbits(os.path.join(self.testdir, "test_orbitsA.des"))
162
+ sedvals = orbits.assign_sed(orbits.orbits, random_seed=42)
163
+ orbits2 = Orbits()
164
+ orbits2.read_orbits(os.path.join(self.testdir, "test_orbitsQ.des"))
165
+ sedvals2 = orbits2.assign_sed(orbits2.orbits, random_seed=42)
166
+ np.testing.assert_array_equal(sedvals, sedvals2)
167
+
168
+
169
+ if __name__ == "__main__":
170
+ unittest.main()
@@ -0,0 +1,61 @@
1
+ import os
2
+ import unittest
3
+
4
+ from rubin_scheduler.data import get_data_dir
5
+
6
+ import rubin_sim.phot_utils as phot_utils
7
+
8
+
9
+ class SedDataUnitTest(unittest.TestCase):
10
+
11
+ def setUp(self) -> None:
12
+ # Read the lsst bandpasses
13
+ lsst = {}
14
+ lsst_filterlist = "ugrizy"
15
+ for b in lsst_filterlist:
16
+ lsst[b] = phot_utils.Bandpass()
17
+ lsst[b].read_throughput(os.path.join(get_data_dir(), "throughputs", "baseline", f"total_{b}.dat"))
18
+ self.lsst = lsst
19
+
20
+ def test_sun(self) -> None:
21
+ sun = phot_utils.Sed()
22
+ sun.read_sed_flambda(os.path.join(get_data_dir(), "movingObjects", "kurucz_sun.gz"))
23
+ expected_mags = {"u": -25.3, "g": -26.5, "r": -27.0, "i": -27.0, "z": -27.1, "y": -27.1}
24
+ for b in "ugrizy":
25
+ mag = sun.calc_mag(self.lsst[b])
26
+ self.assertTrue(abs(mag - expected_mags[b]) < 0.2)
27
+
28
+ def test_seds(self):
29
+ # We have some sample asteroid spectra in rubin_sim_data_dir -
30
+ # However, those are 'observed' spectra
31
+ # (already includes a sample solar spectra)
32
+ ast_templates = [
33
+ k.replace(".dat.gz", "")
34
+ for k in os.listdir(os.path.join(get_data_dir(), "movingObjects"))
35
+ if "kurucz" not in k and "harris" not in k
36
+ ]
37
+ # Read the sso seds from disk (using rubin_sim.photUtils.Sed)
38
+ sso = {}
39
+ for k in ast_templates:
40
+ sso[k] = phot_utils.Sed()
41
+ sso[k].read_sed_flambda(os.path.join(get_data_dir(), "movingObjects", f"{k}.dat.gz"))
42
+
43
+ # Calculate the colors for each type:
44
+ # referenc e bandpass first
45
+ refband_name = "r"
46
+ refband = self.lsst[refband_name]
47
+ # Calculate the reference bandpass magnitudes
48
+ refmags = {}
49
+ for k in sso:
50
+ refmags[k] = sso[k].calc_mag(refband)
51
+
52
+ # And now the colors
53
+ colors = {}
54
+ for k in sso:
55
+ colors[k] = {}
56
+ for f in "ugrizy":
57
+ colors[k][f"lsst_{f}"] = sso[k].calc_mag(self.lsst[f]) - refmags[k]
58
+
59
+
60
+ if __name__ == "__main__":
61
+ unittest.main()
@@ -0,0 +1,91 @@
1
+ """
2
+ Module to test that Approximate Bandpasses are in sync with the official LSST
3
+ Bandpasses from SYSENG
4
+
5
+ Note: While the LSST bandpasses list throughput values corresponding to
6
+ wavelengths in the range of 300.0-1150.0 nm, the `approximate_baseline`
7
+ directory of throughputs is created by a script manually. It is thus possible
8
+ for this directory to fall out of sync with the SYSENG values in `baseline`.
9
+ This module is intended to test whether this is happening.
10
+ """
11
+
12
+ import os
13
+ import unittest
14
+
15
+ import numpy as np
16
+ from rubin_scheduler.data import get_data_dir
17
+
18
+ from rubin_sim.phot_utils import Bandpass, PhotometricParameters
19
+
20
+
21
+ class ApproximateBandPassTest(unittest.TestCase):
22
+ """
23
+ Tests for the approximate Bandpasses in the throughputs directory
24
+ """
25
+
26
+ long_message = True
27
+
28
+ def setUp(self):
29
+ """Setup before tests."""
30
+ throughputs_dir = os.path.join(get_data_dir(), "throughputs")
31
+ self.approx_band_pass_dir = os.path.join(throughputs_dir, "approximate_baseline")
32
+ self.approx_band_pass_dict = {}
33
+ for kk in ["u", "g", "r", "i", "z", "y"]:
34
+ self.approx_band_pass_dict[kk] = Bandpass()
35
+ self.approx_band_pass_dict[kk].read_throughput(
36
+ os.path.join(self.approx_band_pass_dir, f"total_{kk}.dat")
37
+ )
38
+ self.ref_band_pass_dir = os.path.join(throughputs_dir, "baseline")
39
+ self.ref_band_pass_dict = {}
40
+ for kk in ["u", "g", "r", "i", "z", "y"]:
41
+ self.ref_band_pass_dict[kk] = Bandpass()
42
+ self.ref_band_pass_dict[kk].read_throughput(
43
+ os.path.join(self.ref_band_pass_dir, f"total_{kk}.dat")
44
+ )
45
+ self.error_msg = "The failure of this test indicates that the"
46
+ " approximate bandpasses in the lsst throughputs directory do not"
47
+ "sync up with the baseline bandpasses is throughputs. "
48
+ " This may require running the script :"
49
+ " throughputs.approximate_baseline/approximateBandpasses.py"
50
+
51
+ def test_band_pass_integrals(self):
52
+ """Test that the ratio of the quantity
53
+ int dlambda T(lambda) = band flux for a SED proportional to $lambda$
54
+ for the approximate bandpasses to the SYSENG band passes is 1.0 to an
55
+ absolute tolerance hard coded to be 1.0e-4
56
+
57
+ """
58
+ phot_params = PhotometricParameters()
59
+
60
+ for bn in "ugrizy":
61
+ ref_band_pass = self.ref_band_pass_dict[bn]
62
+ approx_band_pass = self.approx_band_pass_dict[bn]
63
+
64
+ zp_ref = ref_band_pass.calc_zp_t(phot_params)
65
+ zp_approx = approx_band_pass.calc_zp_t(phot_params)
66
+ self.assertAlmostEqual(zp_ref, zp_approx, delta=1.0e-4, msg=self.error_msg)
67
+
68
+ def test_bandpasses_indiv(self):
69
+ """
70
+ Test that individual transmission values at wavelengths kept in the
71
+ approximate bandpasses match the individual transmission values in
72
+ the reference bandpasses
73
+ """
74
+ for bn in "ugrizy":
75
+ approx_band_pass = self.approx_band_pass_dict[bn]
76
+ ref_band_pass = self.ref_band_pass_dict[bn]
77
+ refwavelen = ref_band_pass.wavelen
78
+ approxwavelen = approx_band_pass.wavelen
79
+ mask = np.zeros(len(refwavelen), dtype=bool)
80
+ for i, wave in enumerate(refwavelen):
81
+ if wave in approxwavelen:
82
+ mask[i] = True
83
+ # Assume that the wavelengths are in order
84
+ np.testing.assert_array_almost_equal(ref_band_pass.sb[mask], approx_band_pass.sb, decimal=3)
85
+
86
+ def tearDown(self):
87
+ pass
88
+
89
+
90
+ if __name__ == "__main__":
91
+ unittest.main()