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,771 @@
1
+ __all__ = ("just_return", "SkyModel")
2
+
3
+ import warnings
4
+
5
+ import numpy as np
6
+ from astropy import units as u
7
+ from astropy.coordinates import AltAz, EarthLocation, SkyCoord, get_body, get_sun
8
+ from astropy.time import Time
9
+ from rubin_scheduler.utils import Site, _approx_alt_az2_ra_dec, _approx_ra_dec2_alt_az, haversine
10
+
11
+ from rubin_sim.phot_utils import Sed
12
+
13
+ from .interp_components import (
14
+ Airglow,
15
+ LowerAtm,
16
+ MergedSpec,
17
+ MoonInterp,
18
+ ScatteredStar,
19
+ TwilightInterp,
20
+ UpperAtm,
21
+ ZodiacalInterp,
22
+ )
23
+ from .utils import wrap_ra
24
+
25
+
26
+ def just_return(inval):
27
+ """
28
+ Really, just return the input.
29
+
30
+ Parameters
31
+ ----------
32
+ input : anything
33
+
34
+ Returns
35
+ -------
36
+ input : anything
37
+ Just return whatever you sent in.
38
+ """
39
+ return inval
40
+
41
+
42
+ def inrange(inval, minimum=-1.0, maximum=1.0):
43
+ """
44
+ Make sure values are within min/max
45
+ """
46
+ inval = np.array(inval)
47
+ below = np.where(inval < minimum)
48
+ inval[below] = minimum
49
+ above = np.where(inval > maximum)
50
+ inval[above] = maximum
51
+ return inval
52
+
53
+
54
+ def calc_az_rel_moon(azs, moon_az):
55
+ az_rel_moon = wrap_ra(azs - moon_az)
56
+ if isinstance(azs, np.ndarray):
57
+ over = np.where(az_rel_moon > np.pi)
58
+ az_rel_moon[over] = 2.0 * np.pi - az_rel_moon[over]
59
+ else:
60
+ if az_rel_moon > np.pi:
61
+ az_rel_moon = 2.0 * np.pi - az_rel_moon
62
+ return az_rel_moon
63
+
64
+
65
+ class SkyModel:
66
+ def __init__(
67
+ self,
68
+ observatory=None,
69
+ twilight=True,
70
+ zodiacal=True,
71
+ moon=True,
72
+ airglow=True,
73
+ lower_atm=False,
74
+ upper_atm=False,
75
+ scattered_star=False,
76
+ merged_spec=True,
77
+ mags=False,
78
+ precise_alt_az=False,
79
+ airmass_limit=3.0,
80
+ ):
81
+ """A model of the sky, including all of the required
82
+ template spectra or magnitudes needed to interpolate the
83
+ sky spectrum or magnitudes during twilight or night time
84
+ at any point on the sky.
85
+
86
+
87
+ Parameters
88
+ ----------
89
+ observatory : `rubin_scheduler.site_models.Site`, optional
90
+ Default of None loads the LSST site.
91
+ twilight : `bool`, optional
92
+ Include twilight component (True)
93
+ zodiacal : `bool`, optional
94
+ Include zodiacal light component (True)
95
+ moon : `bool`, optional
96
+ Include scattered moonlight component (True)
97
+ airglow : `bool`, optional
98
+ Include airglow component
99
+ lower_atm : `bool`, optional
100
+ Include lower atmosphere component.
101
+ This component is part of `merged_spec`.
102
+ upper_atm : `bool`, optional
103
+ Include upper atmosphere component.
104
+ This component is part of `merged_spec`.
105
+ scattered_star : `bool`, optional
106
+ Include scattered starlight component.
107
+ This component is part of `merged_spec`.
108
+ merged_spec : `bool`, optional
109
+ Compute the lower_atm, upper_atm, and scattered_star
110
+ simultaneously since they are all functions of only airmass.
111
+ mags : `bool`, optional
112
+ By default, the sky model computes a 17,001 element spectrum.
113
+ If `mags` is True,
114
+ the model will return the LSST ugrizy magnitudes (in that order).
115
+ precise_alt_az : `bool`, optional
116
+ If False, use the fast alt, az to ra, dec coordinate
117
+ transformations that do not take aberation, diffraction, etc
118
+ into account. Results in errors up to ~1.5 degrees,
119
+ but an order of magnitude faster than the precise coordinate
120
+ transformations available in rubin_scheduler.utils.
121
+ airmass_limit : `float`, optional
122
+ Most of the models are only accurate to airmass 3.0.
123
+ If set higher, airmass values higher than 3.0 are set to 3.0.
124
+ """
125
+
126
+ self.moon = moon
127
+ self.lower_atm = lower_atm
128
+ self.twilight = twilight
129
+ self.zodiacal = zodiacal
130
+ self.upper_atm = upper_atm
131
+ self.airglow = airglow
132
+ self.scattered_star = scattered_star
133
+ self.merged_spec = merged_spec
134
+ self.mags = mags
135
+ self.precise_alt_az = precise_alt_az
136
+
137
+ # set this as a way to track if coords have been set
138
+ self.azs = None
139
+
140
+ # Airmass limit.
141
+ self.airmass_limit = airmass_limit
142
+
143
+ if self.mags:
144
+ self.npix = 6
145
+ else:
146
+ self.npix = 11001
147
+
148
+ self.components = {
149
+ "moon": self.moon,
150
+ "lower_atm": self.lower_atm,
151
+ "twilight": self.twilight,
152
+ "upper_atm": self.upper_atm,
153
+ "airglow": self.airglow,
154
+ "zodiacal": self.zodiacal,
155
+ "scattered_star": self.scattered_star,
156
+ "merged_spec": self.merged_spec,
157
+ }
158
+
159
+ # Check that the merged component isn't being run with other components
160
+ merged_comps = [self.lower_atm, self.upper_atm, self.scattered_star]
161
+ for comp in merged_comps:
162
+ if comp & self.merged_spec:
163
+ warnings.warn("Adding component multiple times to the final output spectra.")
164
+
165
+ interpolators = {
166
+ "scattered_star": ScatteredStar,
167
+ "airglow": Airglow,
168
+ "lower_atm": LowerAtm,
169
+ "upper_atm": UpperAtm,
170
+ "merged_spec": MergedSpec,
171
+ "moon": MoonInterp,
172
+ "zodiacal": ZodiacalInterp,
173
+ "twilight": TwilightInterp,
174
+ }
175
+
176
+ # Load up the interpolation objects for each component
177
+ self.interp_objs = {}
178
+ for key in self.components:
179
+ if self.components[key]:
180
+ self.interp_objs[key] = interpolators[key](mags=self.mags)
181
+
182
+ if observatory is None:
183
+ self.telescope = Site("LSST")
184
+ else:
185
+ self.telescope = observatory
186
+ self.location = EarthLocation(
187
+ lat=self.telescope.latitude_rad * u.rad,
188
+ lon=self.telescope.longitude_rad * u.rad,
189
+ height=self.telescope.height * u.m,
190
+ )
191
+
192
+ # Note that observing conditions have not been set
193
+ self.params_set = False
194
+
195
+ def _init_points(self):
196
+ """
197
+ Set up an array for all the interpolation points
198
+ """
199
+
200
+ names = [
201
+ "airmass",
202
+ "nightTimes",
203
+ "alt",
204
+ "az",
205
+ "azRelMoon",
206
+ "moonSunSep",
207
+ "moonAltitude",
208
+ "altEclip",
209
+ "azEclipRelSun",
210
+ "sunAlt",
211
+ "azRelSun",
212
+ "solar_flux",
213
+ ]
214
+ types = [float] * len(names)
215
+ self.points = np.zeros(self.npts, list(zip(names, types)))
216
+
217
+ def set_ra_dec_mjd(
218
+ self,
219
+ lon,
220
+ lat,
221
+ mjd,
222
+ degrees=False,
223
+ az_alt=False,
224
+ solar_flux=130.0,
225
+ filter_names=["u", "g", "r", "i", "z", "y"],
226
+ ):
227
+ """
228
+ Set the sky parameters by computing the sky conditions on a
229
+ given MJD and sky location.
230
+
231
+
232
+ Parameters
233
+ ----------
234
+ lon : `float` or `np.ndarray`, (N,)
235
+ Longitude-like (RA or Azimuth).
236
+ Can be single number, list, or numpy array
237
+ lat: `float` or `np.ndarray`, (N,)
238
+ Latitude-like (Dec or Altitude)
239
+ mjd: `float`
240
+ Modified Julian Date for the calculation. Must be single number.
241
+ degrees: `bool`, optional
242
+ If True, lon/lat are in degrees. If False, lon/lat in radians.
243
+ az_alt: `bool`, optional
244
+ Assume lon, lat are RA, Dec unless az_alt=True
245
+ solar_flux: `float`
246
+ Solar flux in SFU Between 50 and 310. Default=130. 1 SFU=10^4 Jy.
247
+ filter_names: `list` [`str`]
248
+ List of filter for which to return magnitudes
249
+ (if initialized with mags=True).
250
+ """
251
+ self.filter_names = filter_names
252
+ if self.mags:
253
+ self.npix = len(self.filter_names)
254
+ # Wrap in array just in case single points were passed
255
+ if np.size(lon) == 1:
256
+ lon = np.array([lon]).ravel()
257
+ lat = np.array([lat]).ravel()
258
+ else:
259
+ lon = np.array(lon)
260
+ lat = np.array(lat)
261
+ if degrees:
262
+ self.ra = np.radians(lon)
263
+ self.dec = np.radians(lat)
264
+ else:
265
+ self.ra = lon
266
+ self.dec = lat
267
+ if np.size(mjd) > 1:
268
+ raise ValueError("mjd must be single value.")
269
+ self.mjd = mjd
270
+ if az_alt:
271
+ self.azs = self.ra.copy()
272
+ self.alts = self.dec.copy()
273
+ if self.precise_alt_az:
274
+ raise ValueError("Need to swap in astropy")
275
+ # self.ra, self.dec = _ra_dec_from_alt_az(
276
+ # self.alts,
277
+ # self.azs,
278
+ # ObservationMetaData(mjd=self.mjd, site=self.telescope),
279
+ # )
280
+ else:
281
+ self.ra, self.dec = _approx_alt_az2_ra_dec(
282
+ self.alts,
283
+ self.azs,
284
+ self.telescope.latitude_rad,
285
+ self.telescope.longitude_rad,
286
+ mjd,
287
+ )
288
+ else:
289
+ if self.precise_alt_az:
290
+ raise ValueError("Need to swap in astropy")
291
+ # self.alts, self.azs, pa = _alt_az_pa_from_ra_dec(
292
+ # self.ra,
293
+ # self.dec,
294
+ # ObservationMetaData(mjd=self.mjd, site=self.telescope),
295
+ # )
296
+ else:
297
+ self.alts, self.azs = _approx_ra_dec2_alt_az(
298
+ self.ra,
299
+ self.dec,
300
+ self.telescope.latitude_rad,
301
+ self.telescope.longitude_rad,
302
+ mjd,
303
+ )
304
+
305
+ self.npts = self.ra.size
306
+ self._init_points()
307
+
308
+ self.solar_flux = solar_flux
309
+ self.points["solar_flux"] = self.solar_flux
310
+
311
+ self._setup_point_grid()
312
+
313
+ self.params_set = True
314
+
315
+ # Interpolate the templates to the set Parameters
316
+ self.good_pix = np.where((self.airmass <= self.airmass_limit) & (self.airmass >= 1.0))[0]
317
+
318
+ if self.good_pix.size <= 0:
319
+ raise ValueError(
320
+ "No valid points. Airmass limit=%.1f, min airmass of requested points=%.1f"
321
+ % (self.airmass_limit, np.min(self.airmass))
322
+ )
323
+ else:
324
+ self._interp_sky()
325
+
326
+ def set_ra_dec_alt_az_mjd(
327
+ self,
328
+ ra,
329
+ dec,
330
+ alt,
331
+ az,
332
+ mjd,
333
+ degrees=False,
334
+ solar_flux=130.0,
335
+ filter_names=["u", "g", "r", "i", "z", "y"],
336
+ ):
337
+ """
338
+ Set the sky parameters by computing the sky conditions on a
339
+ given MJD and sky location.
340
+
341
+ Use if you already have alt az coordinates so you can skip the
342
+ coordinate conversion.
343
+ """
344
+ self.filter_names = filter_names
345
+ if self.mags:
346
+ self.npix = len(self.filter_names)
347
+ # Wrap in array just in case single points were passed
348
+ if not type(ra).__module__ == np.__name__:
349
+ if np.size(ra) == 1:
350
+ ra = np.array([ra]).ravel()
351
+ dec = np.array([dec]).ravel()
352
+ alt = np.array(alt).ravel()
353
+ az = np.array(az).ravel()
354
+ else:
355
+ ra = np.array(ra)
356
+ dec = np.array(dec)
357
+ alt = np.array(alt)
358
+ az = np.array(az)
359
+ if degrees:
360
+ self.ra = np.radians(ra)
361
+ self.dec = np.radians(dec)
362
+ self.alts = np.radians(alt)
363
+ self.azs = np.radians(az)
364
+ else:
365
+ self.ra = ra
366
+ self.dec = dec
367
+ self.azs = az
368
+ self.alts = alt
369
+ if np.size(mjd) > 1:
370
+ raise ValueError("mjd must be single value.")
371
+ self.mjd = mjd
372
+
373
+ self.npts = self.ra.size
374
+ self._init_points()
375
+
376
+ self.solar_flux = solar_flux
377
+ self.points["solar_flux"] = self.solar_flux
378
+
379
+ self._setup_point_grid()
380
+
381
+ self.params_set = True
382
+
383
+ # Interpolate the templates to the set Parameters
384
+ self.good_pix = np.where((self.airmass <= self.airmass_limit) & (self.airmass >= 1.0))[0]
385
+ if self.good_pix.size <= 0:
386
+ raise ValueError(
387
+ "No valid points. Airmass limit=%.1f, min airmass of requested points=%.1f"
388
+ % (self.airmass_limit, np.min(self.airmass))
389
+ )
390
+ else:
391
+ self._interp_sky()
392
+
393
+ def get_computed_vals(self):
394
+ """
395
+ Return the intermediate values that are caluculated by
396
+ set_ra_dec_mjd and used for interpolation.
397
+ All of these values are also accessible as class attributes, this is
398
+ a convenience method to grab them all at once and document the formats.
399
+
400
+ Returns
401
+ -------
402
+ out : `dict`
403
+ Dictionary of all the intermediate calculated values that may
404
+ be of use outside (the key:values in the output dict)
405
+ ra : `np.ndarray`, (N,)
406
+ RA of the interpolation points (radians)
407
+ dec : `np.ndarray`, (N,)
408
+ Dec of the interpolation points (radians)
409
+ alts : `np.ndarray`, (N,)
410
+ Altitude (radians)
411
+ azs : `np.ndarray`, (N,)
412
+ Azimuth of interpolation points (radians)
413
+ airmass : `np.ndarray`, (N,)
414
+ Airmass values for each point,
415
+ computed via 1./np.cos(np.pi/2.-self.alts).
416
+ solar_flux : `float`
417
+ The solar flux used (SFU).
418
+ sunAz : `float`
419
+ Azimuth of the sun (radians)
420
+ sunAlt : `float`
421
+ Altitude of the sun (radians)
422
+ sunRA : `float`
423
+ RA of the sun (radians)
424
+ sunDec : `float`
425
+ Dec of the sun (radians)
426
+ azRelSun : `np.ndarray`, (N,)
427
+ Azimuth of each point relative to the sun
428
+ (0=same direction as sun) (radians)
429
+ moonAz : `float`
430
+ Azimuth of the moon (radians)
431
+ moonAlt : `float`
432
+ Altitude of the moon (radians)
433
+ moonRA : `float`
434
+ RA of the moon (radians)
435
+ moonDec : `float`
436
+ Dec of the moon (radians). Note, if you want distances
437
+ moon_phase : `float`
438
+ Phase of the moon (0-100)
439
+ moonSunSep : `float`
440
+ Seperation of moon and sun (radians)
441
+ azRelMoon : `np.ndarray`, (N,)
442
+ Azimuth of each point relative to teh moon
443
+ eclipLon : `np.ndarray`, (N,)
444
+ Ecliptic longitude (radians) of each point
445
+ eclipLat : `np.ndarray`, (N,)
446
+ Ecliptic latitude (radians) of each point
447
+ sunEclipLon: `np.ndarray`, (N,)
448
+ Ecliptic longitude (radians) of each point with the sun at
449
+ longitude zero
450
+
451
+ Note that since the alt and az can be calculated using the fast
452
+ approximation, if one wants to compute the distance between the points
453
+ and the sun or moon, it is probably better to use the ra,dec positions
454
+ rather than the alt,az positions.
455
+ """
456
+
457
+ result = {}
458
+ attributes = [
459
+ "ra",
460
+ "dec",
461
+ "alts",
462
+ "azs",
463
+ "airmass",
464
+ "solar_flux",
465
+ "moon_phase",
466
+ "moon_az",
467
+ "moon_alt",
468
+ "sun_alt",
469
+ "sun_az",
470
+ "az_rel_sun",
471
+ "moon_sun_sep",
472
+ "az_rel_moon",
473
+ "eclip_lon",
474
+ "eclip_lat",
475
+ "moon_ra",
476
+ "moon_dec",
477
+ "sun_ra",
478
+ "sun_dec",
479
+ "sun_eclip_lon",
480
+ ]
481
+
482
+ for attribute in attributes:
483
+ if hasattr(self, attribute):
484
+ result[attribute] = getattr(self, attribute)
485
+ else:
486
+ result[attribute] = None
487
+
488
+ return result
489
+
490
+ def _setup_point_grid(self):
491
+ """
492
+ Setup the points for the interpolation functions.
493
+ """
494
+
495
+ time = Time(self.mjd, format="mjd")
496
+ aa = AltAz(location=self.location, obstime=time)
497
+
498
+ sun_coords = get_sun(time)
499
+ self.sun_ra = sun_coords.ra.rad
500
+ self.sun_dec = sun_coords.dec.rad
501
+
502
+ sun_coords = sun_coords.transform_to(aa)
503
+ self.sun_alt = sun_coords.alt.rad
504
+ self.sun_az = sun_coords.az.rad
505
+
506
+ # Compute airmass the same way as ESO model
507
+ self.airmass = 1.0 / np.cos(np.pi / 2.0 - self.alts)
508
+
509
+ self.points["airmass"] = self.airmass
510
+ self.points["nightTimes"] = 0
511
+ self.points["alt"] = self.alts
512
+ self.points["az"] = self.azs
513
+
514
+ if self.twilight:
515
+ self.points["sunAlt"] = self.sun_alt
516
+ self.az_rel_sun = wrap_ra(self.azs - self.sun_az)
517
+ self.points["azRelSun"] = self.az_rel_sun
518
+
519
+ if self.moon:
520
+ moon_coords = get_body("moon", time)
521
+ self.moon_ra = moon_coords.ra.rad
522
+ self.moon_dec = moon_coords.dec.rad
523
+
524
+ moon_coords = moon_coords.transform_to(aa)
525
+ self.moon_alt = moon_coords.alt.rad
526
+ self.moon_az = moon_coords.az.rad
527
+
528
+ moon_coords = get_body("moon", time)
529
+ sun_coords = get_sun(time)
530
+ sep = sun_coords.separation(moon_coords)
531
+
532
+ # looks like phase is 0-100
533
+ self.moon_phase = sep.deg * 100 / 180.0
534
+
535
+ # Calc azimuth relative to moon
536
+ self.az_rel_moon = calc_az_rel_moon(self.azs, self.moon_az)
537
+ self.moon_targ_sep = haversine(self.azs, self.alts, self.moon_az, self.moon_alt)
538
+ # Oof, looks like some things were stored as degrees.
539
+ self.points["moonAltitude"] += np.degrees(self.moon_alt)
540
+ self.points["azRelMoon"] += self.az_rel_moon
541
+ self.moon_sun_sep = sep.rad
542
+ self.points["moonSunSep"] += np.degrees(self.moon_sun_sep)
543
+
544
+ if self.zodiacal:
545
+ self.eclip_lon = np.zeros(self.npts)
546
+ self.eclip_lat = np.zeros(self.npts)
547
+
548
+ coord = SkyCoord(ra=self.ra * u.rad, dec=self.dec * u.rad)
549
+ coord_ecl = coord.geocentricmeanecliptic
550
+ self.eclip_lon = coord_ecl.lon.rad
551
+ self.eclip_lat = coord_ecl.lat.rad
552
+
553
+ # Subtract off the sun ecliptic longitude
554
+ sun_coords = get_sun(time)
555
+ sun_eclip = sun_coords.geocentricmeanecliptic
556
+ self.sun_eclip_lon = sun_eclip.lon.rad
557
+ self.points["altEclip"] += self.eclip_lat
558
+ self.points["azEclipRelSun"] += wrap_ra(self.eclip_lon - self.sun_eclip_lon)
559
+
560
+ self.mask = np.where((self.airmass > self.airmass_limit) | (self.airmass < 1.0))[0]
561
+ self.good_pix = np.where((self.airmass <= self.airmass_limit) & (self.airmass >= 1.0))[0]
562
+
563
+ def set_params(
564
+ self,
565
+ airmass=1.0,
566
+ azs=90.0,
567
+ alts=None,
568
+ moon_phase=31.67,
569
+ moon_alt=45.0,
570
+ moon_az=0.0,
571
+ sun_alt=-12.0,
572
+ sun_az=0.0,
573
+ sun_eclip_lon=0.0,
574
+ eclip_lon=135.0,
575
+ eclip_lat=90.0,
576
+ degrees=True,
577
+ solar_flux=130.0,
578
+ filter_names=["u", "g", "r", "i", "z", "y"],
579
+ ):
580
+ """
581
+ Set parameters manually.
582
+ Note, you can put in unphysical combinations of Parameters if you
583
+ want to (e.g., put a full moon at zenith at sunset).
584
+ If the alts kwarg is set it will override the airmass kwarg.
585
+ MoonPhase is percent of moon illuminated (0-100)
586
+ """
587
+
588
+ # Convert all values to radians for internal use.
589
+ self.filter_names = filter_names
590
+ if self.mags:
591
+ self.npix = len(self.filter_names)
592
+ if degrees:
593
+ convert_func = np.radians
594
+ else:
595
+ convert_func = just_return
596
+
597
+ self.solar_flux = solar_flux
598
+ self.sun_alt = convert_func(sun_alt)
599
+ self.moon_phase = moon_phase
600
+ self.moon_alt = convert_func(moon_alt)
601
+ self.moon_az = convert_func(moon_az)
602
+ self.eclip_lon = convert_func(eclip_lon)
603
+ self.eclip_lat = convert_func(eclip_lat)
604
+ self.sun_eclip_lon = convert_func(sun_eclip_lon)
605
+ self.azs = convert_func(azs)
606
+ if alts is not None:
607
+ self.airmass = 1.0 / np.cos(np.pi / 2.0 - convert_func(alts))
608
+ self.alts = convert_func(alts)
609
+ else:
610
+ self.airmass = airmass
611
+ self.alts = np.pi / 2.0 - np.arccos(1.0 / airmass)
612
+ self.moon_targ_sep = haversine(self.azs, self.alts, moon_az, self.moon_alt)
613
+ self.npts = np.size(self.airmass)
614
+ self._init_points()
615
+
616
+ self.points["airmass"] = self.airmass
617
+ self.points["nightTimes"] = 0
618
+ self.points["alt"] = self.alts
619
+ self.points["az"] = self.azs
620
+
621
+ self.az_rel_moon = calc_az_rel_moon(self.azs, self.moon_az)
622
+ self.points["moonAltitude"] += np.degrees(self.moon_alt)
623
+ self.points["azRelMoon"] = self.az_rel_moon
624
+ self.moon_sun_sep = self.moon_phase / 100.0 * np.pi
625
+ self.points["moonSunSep"] += self.moon_phase / 100.0 * 180.0
626
+
627
+ self.eclip_lon = convert_func(eclip_lon)
628
+ self.eclip_lat = convert_func(eclip_lat)
629
+
630
+ self.sun_eclip_lon = convert_func(sun_eclip_lon)
631
+ self.points["altEclip"] += self.eclip_lat
632
+ self.points["azEclipRelSun"] += wrap_ra(self.eclip_lon - self.sun_eclip_lon)
633
+
634
+ self.sun_az = convert_func(sun_az)
635
+ self.points["sunAlt"] = self.sun_alt
636
+ self.points["azRelSun"] = wrap_ra(self.azs - self.sun_az)
637
+ self.points["solar_flux"] = solar_flux
638
+
639
+ self.params_set = True
640
+
641
+ self.mask = np.where((self.airmass > self.airmass_limit) | (self.airmass < 1.0))[0]
642
+ self.good_pix = np.where((self.airmass <= self.airmass_limit) & (self.airmass >= 1.0))[0]
643
+ # Interpolate the templates to the set Parameters
644
+ if self.good_pix.size > 0:
645
+ self._interp_sky()
646
+ else:
647
+ warnings.warn("No points in interpolation range")
648
+
649
+ def _interp_sky(self):
650
+ """
651
+ Interpolate the template spectra to the set RA, Dec and MJD.
652
+
653
+ the results are stored as attributes of the class:
654
+ .wave = the wavelength in nm
655
+ .spec = array of spectra with units of ergs/s/cm^2/nm
656
+ """
657
+
658
+ if not self.params_set:
659
+ raise ValueError(
660
+ "No parameters have been set. Must run set_ra_dec_mjd or setParams before running interpSky."
661
+ )
662
+
663
+ # set up array to hold the resulting spectra for each ra, dec point.
664
+ self.spec = np.zeros((self.npts, self.npix), dtype=float)
665
+
666
+ # Rebuild the components dict so things can be turned on/off
667
+ self.components = {
668
+ "moon": self.moon,
669
+ "lower_atm": self.lower_atm,
670
+ "twilight": self.twilight,
671
+ "upper_atm": self.upper_atm,
672
+ "airglow": self.airglow,
673
+ "zodiacal": self.zodiacal,
674
+ "scattered_star": self.scattered_star,
675
+ "merged_spec": self.merged_spec,
676
+ }
677
+
678
+ # Loop over each component and add it to the result.
679
+ mask = np.ones(self.npts)
680
+ for key in self.components:
681
+ if self.components[key]:
682
+ result = self.interp_objs[key](self.points[self.good_pix], filter_names=self.filter_names)
683
+ # Make sure the component has something
684
+ if np.size(result["spec"]) == 0:
685
+ self.spec[self.mask, :] = np.nan
686
+ return
687
+ if np.max(result["spec"]) > 0:
688
+ mask[np.where(np.sum(result["spec"], axis=1) == 0)] = 0
689
+ self.spec[self.good_pix] += result["spec"]
690
+ if not hasattr(self, "wave"):
691
+ self.wave = result["wave"]
692
+ else:
693
+ if not np.allclose(result["wave"], self.wave, rtol=1e-4, atol=1e-4):
694
+ warnings.warn("Wavelength arrays of components do not match.")
695
+ if self.airmass_limit <= 2.5:
696
+ self.spec[np.where(mask == 0), :] = 0
697
+ self.spec[self.mask, :] = np.nan
698
+
699
+ def return_wave_spec(self):
700
+ """
701
+ Return the wavelength and spectra.
702
+ Wavelenth in nm
703
+ spectra is flambda in ergs/cm^2/s/nm
704
+ """
705
+ if self.azs is None:
706
+ raise ValueError(
707
+ "No coordinates set. Use set_ra_dec_mjd, setRaDecAltAzMjd, or "
708
+ "setParams methods before calling returnWaveSpec."
709
+ )
710
+ if self.mags:
711
+ raise ValueError("SkyModel set to interpolate magnitudes. Initialize object with mags=False")
712
+ # Mask out high airmass points
713
+ # self.spec[self.mask] *= 0
714
+ return self.wave.copy(), self.spec.copy()
715
+
716
+ def return_mags(self, bandpasses=None):
717
+ """Return the skybrightness in magnitudes.
718
+
719
+ Convert the computed spectra to a magnitude using the
720
+ supplied bandpass, or, if self.mags=True, return the mags in the
721
+ LSST filters.
722
+
723
+ Parameters
724
+ ----------
725
+ bandpasses : `dict` [`str`, `rubin_sim.phot_utils.Bandpass`], optional
726
+ Dictionary with bandpass name as keys and `Bandpass` objects
727
+ as values.
728
+
729
+ If mags=True when initialized, return mags returns a structured array
730
+ with dtype names u,g,r,i,z,y; the default LSST bandpasses are used.
731
+
732
+ Returns
733
+ -------
734
+ mags : `np.ndarray`, (N,)
735
+ Sky brightness in AB mags/sq arcsec
736
+ """
737
+ if self.azs is None:
738
+ raise ValueError(
739
+ "No coordinates set. Use set_ra_dec_mjd, setRaDecAltAzMjd, or "
740
+ "setParams methods before calling return_mags."
741
+ )
742
+
743
+ if self.mags:
744
+ if bandpasses:
745
+ warnings.warn("Ignoring set bandpasses and returning LSST ugrizy.")
746
+ mags = -2.5 * np.log10(self.spec) + np.log10(3631.0)
747
+ # Mask out high airmass
748
+ mags[self.mask] *= np.nan
749
+ mags = mags.swapaxes(0, 1)
750
+ mags_back = {}
751
+ for i, f in enumerate(self.filter_names):
752
+ mags_back[f] = mags[i]
753
+ else:
754
+ mags_back = {}
755
+ for key in bandpasses:
756
+ mags = np.zeros(self.npts, dtype=float) - 666
757
+ temp_sed = Sed()
758
+ is_through = np.where(bandpasses[key].sb > 0)
759
+ min_wave = bandpasses[key].wavelen[is_through].min()
760
+ max_wave = bandpasses[key].wavelen[is_through].max()
761
+ in_band = np.where((self.wave >= min_wave) & (self.wave <= max_wave))
762
+ for i, ra in enumerate(self.ra):
763
+ # Check that there is flux in the band,
764
+ # otherwise calc_mag fails
765
+ if np.max(self.spec[i, in_band]) > 0:
766
+ temp_sed.set_sed(self.wave, flambda=self.spec[i, :])
767
+ mags[i] = temp_sed.calc_mag(bandpasses[key])
768
+ # Mask out high airmass
769
+ mags[self.mask] *= np.nan
770
+ mags_back[key] = mags
771
+ return mags_back