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.
- batch/compile_prenight_metadata_cache.sh +34 -0
- batch/run_auxtel_prenight_sims.sh +163 -0
- batch/run_prenight_sims.sh +239 -0
- docs/.gitignore +3 -0
- docs/Makefile +32 -0
- docs/api.rst +25 -0
- docs/conf.py +8 -0
- docs/data-api.rst +12 -0
- docs/data-download.rst +70 -0
- docs/developer.rst +14 -0
- docs/documenteer.toml +11 -0
- docs/index.rst +22 -0
- docs/installation.rst +76 -0
- docs/introduction.rst +37 -0
- docs/maf-api-batches.rst +12 -0
- docs/maf-api-db.rst +12 -0
- docs/maf-api-maf-contrib.rst +12 -0
- docs/maf-api-maps.rst +12 -0
- docs/maf-api-metricbundles.rst +12 -0
- docs/maf-api-metrics.rst +12 -0
- docs/maf-api-plots.rst +12 -0
- docs/maf-api-run-comparison.rst +12 -0
- docs/maf-api-slicers.rst +12 -0
- docs/maf-api-stackers.rst +12 -0
- docs/maf-api-utils.rst +12 -0
- docs/maf-api.rst +22 -0
- docs/maf.rst +60 -0
- docs/metric_list.py +49 -0
- docs/moving-objects-api.rst +12 -0
- docs/moving-objects.rst +22 -0
- docs/phot-utils-api.rst +12 -0
- docs/phot-utils.rst +11 -0
- docs/prenight.rst +117 -0
- docs/protoarchive.rst +276 -0
- docs/satellite-constellations-api.rst +12 -0
- docs/satellite-constellations.rst +13 -0
- docs/selfcal-api.rst +12 -0
- docs/selfcal.rst +15 -0
- docs/sim-archive-api.rst +12 -0
- docs/skybrightness-api.rst +12 -0
- docs/skybrightness.rst +23 -0
- docs/user-guide.rst +28 -0
- docs/vseqarchive-architecture.rst +438 -0
- docs/vseqarchive-setup.rst +238 -0
- docs/vseqarchive.rst +225 -0
- rubin_sim/__init__.py +7 -0
- rubin_sim/data/__init__.py +1 -0
- rubin_sim/data/rs_download_data.py +155 -0
- rubin_sim/maf/__init__.py +34 -0
- rubin_sim/maf/batches/__init__.py +18 -0
- rubin_sim/maf/batches/altaz_batch.py +161 -0
- rubin_sim/maf/batches/col_map_dict.py +274 -0
- rubin_sim/maf/batches/common.py +388 -0
- rubin_sim/maf/batches/ddf_batch.py +728 -0
- rubin_sim/maf/batches/filterchange_batch.py +182 -0
- rubin_sim/maf/batches/glance_batch.py +591 -0
- rubin_sim/maf/batches/hourglass_batch.py +79 -0
- rubin_sim/maf/batches/info_batch.py +114 -0
- rubin_sim/maf/batches/metadata_batch.py +558 -0
- rubin_sim/maf/batches/moving_objects_batch.py +1587 -0
- rubin_sim/maf/batches/openshutter_batch.py +100 -0
- rubin_sim/maf/batches/radar_limited.py +1100 -0
- rubin_sim/maf/batches/science_radar_batch.py +1910 -0
- rubin_sim/maf/batches/skycoverage.py +155 -0
- rubin_sim/maf/batches/slew_batch.py +146 -0
- rubin_sim/maf/batches/srd_batch.py +637 -0
- rubin_sim/maf/batches/time_batch.py +757 -0
- rubin_sim/maf/batches/time_sci_batch.py +105 -0
- rubin_sim/maf/batches/visitdepth_batch.py +485 -0
- rubin_sim/maf/db/__init__.py +2 -0
- rubin_sim/maf/db/add_run.py +34 -0
- rubin_sim/maf/db/results_db.py +1074 -0
- rubin_sim/maf/db/tracking_db.py +332 -0
- rubin_sim/maf/ddf_dir.py +53 -0
- rubin_sim/maf/generate_ss.py +218 -0
- rubin_sim/maf/glance_dir.py +58 -0
- rubin_sim/maf/maf_contrib/__init__.py +25 -0
- rubin_sim/maf/maf_contrib/calculate_lsst_field_visibility_astropy.py +170 -0
- rubin_sim/maf/maf_contrib/depth_limited_num_gal_metric.py +109 -0
- rubin_sim/maf/maf_contrib/example_new_metrics.py +40 -0
- rubin_sim/maf/maf_contrib/filter_pair_t_gaps_metric.py +208 -0
- rubin_sim/maf/maf_contrib/grb_transient_metric.py +249 -0
- rubin_sim/maf/maf_contrib/gw170817_det_metric.py +72 -0
- rubin_sim/maf/maf_contrib/intervals_between_obs_metric.py +68 -0
- rubin_sim/maf/maf_contrib/kne_metrics.py +473 -0
- rubin_sim/maf/maf_contrib/lss_metrics.py +45 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/__init__.py +3 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/constants_for_pipeline.py +73 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_metric_extended.py +205 -0
- rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_with_pixel_calibration.py +171 -0
- rubin_sim/maf/maf_contrib/lv_dwarfs/__init__.py +1 -0
- rubin_sim/maf/maf_contrib/lv_dwarfs/lv_dwarfs_metrics.py +388 -0
- rubin_sim/maf/maf_contrib/microlensing_metric.py +593 -0
- rubin_sim/maf/maf_contrib/num_obs_in_survey_time_overlap_metric.py +43 -0
- rubin_sim/maf/maf_contrib/periodic_metric.py +51 -0
- rubin_sim/maf/maf_contrib/periodic_star_metric.py +186 -0
- rubin_sim/maf/maf_contrib/periodic_star_modulation_metric.py +236 -0
- rubin_sim/maf/maf_contrib/presto_color_kne_pop_metric.py +441 -0
- rubin_sim/maf/maf_contrib/selfcal_uniformity_metric.py +171 -0
- rubin_sim/maf/maf_contrib/star_count_mass_metric.py +64 -0
- rubin_sim/maf/maf_contrib/star_count_metric.py +56 -0
- rubin_sim/maf/maf_contrib/star_counts/__init__.py +8 -0
- rubin_sim/maf/maf_contrib/star_counts/abs_mag.py +324 -0
- rubin_sim/maf/maf_contrib/star_counts/coords.py +99 -0
- rubin_sim/maf/maf_contrib/star_counts/readme.txt +1 -0
- rubin_sim/maf/maf_contrib/star_counts/spec_type.py +91 -0
- rubin_sim/maf/maf_contrib/star_counts/starcount.py +30 -0
- rubin_sim/maf/maf_contrib/star_counts/starcount_bymass.py +93 -0
- rubin_sim/maf/maf_contrib/star_counts/stellardensity.py +59 -0
- rubin_sim/maf/maf_contrib/static_probes_fom_summary_metric.py +386 -0
- rubin_sim/maf/maf_contrib/tdes_pop_metric.py +362 -0
- rubin_sim/maf/maf_contrib/transient_ascii_sed_metric.py +652 -0
- rubin_sim/maf/maf_contrib/triplet_metric.py +156 -0
- rubin_sim/maf/maf_contrib/var_depth_metric.py +157 -0
- rubin_sim/maf/maf_contrib/xrb_metrics.py +523 -0
- rubin_sim/maf/maf_contrib/young_stellar_objects_metric.py +200 -0
- rubin_sim/maf/maf_night_report.py +200 -0
- rubin_sim/maf/make_fbs_tracking_db.py +90 -0
- rubin_sim/maf/maps/__init__.py +8 -0
- rubin_sim/maf/maps/base_map.py +72 -0
- rubin_sim/maf/maps/create_gaia_density_map.py +158 -0
- rubin_sim/maf/maps/dust_map.py +66 -0
- rubin_sim/maf/maps/dust_map_3d.py +190 -0
- rubin_sim/maf/maps/ebv_3d_hp.py +170 -0
- rubin_sim/maf/maps/ebv_hp.py +64 -0
- rubin_sim/maf/maps/gal_coords_map.py +22 -0
- rubin_sim/maf/maps/galactic_plane_priority_maps.py +210 -0
- rubin_sim/maf/maps/stellar_density_map.py +73 -0
- rubin_sim/maf/maps/trilegal_map.py +82 -0
- rubin_sim/maf/metadata_dir.py +90 -0
- rubin_sim/maf/metric_bundles/__init__.py +3 -0
- rubin_sim/maf/metric_bundles/metric_bundle.py +816 -0
- rubin_sim/maf/metric_bundles/metric_bundle_group.py +834 -0
- rubin_sim/maf/metric_bundles/mo_metric_bundle.py +646 -0
- rubin_sim/maf/metrics/__init__.py +52 -0
- rubin_sim/maf/metrics/agn_time_lag_metric.py +118 -0
- rubin_sim/maf/metrics/agnstructure.py +141 -0
- rubin_sim/maf/metrics/area_summary_metrics.py +120 -0
- rubin_sim/maf/metrics/base_metric.py +215 -0
- rubin_sim/maf/metrics/brown_dwarf_metric.py +162 -0
- rubin_sim/maf/metrics/cadence_metrics.py +400 -0
- rubin_sim/maf/metrics/calibration_metrics.py +618 -0
- rubin_sim/maf/metrics/chip_vendor_metric.py +43 -0
- rubin_sim/maf/metrics/color_slope_metrics.py +189 -0
- rubin_sim/maf/metrics/cosmology_summary_metrics.py +1212 -0
- rubin_sim/maf/metrics/coverage_metric.py +48 -0
- rubin_sim/maf/metrics/crowding_metric.py +255 -0
- rubin_sim/maf/metrics/cumulative_metric.py +46 -0
- rubin_sim/maf/metrics/dcr_metric.py +93 -0
- rubin_sim/maf/metrics/exgal_m5.py +57 -0
- rubin_sim/maf/metrics/fft_metric.py +27 -0
- rubin_sim/maf/metrics/galactic_plane_metrics.py +375 -0
- rubin_sim/maf/metrics/galplane_time_sampling_metrics.py +236 -0
- rubin_sim/maf/metrics/hourglass_metric.py +130 -0
- rubin_sim/maf/metrics/incremental_template_metric.py +255 -0
- rubin_sim/maf/metrics/kuiper_metrics.py +26 -0
- rubin_sim/maf/metrics/mo_metrics.py +1496 -0
- rubin_sim/maf/metrics/mo_summary_metrics.py +464 -0
- rubin_sim/maf/metrics/night_pointing_metric.py +70 -0
- rubin_sim/maf/metrics/optimal_m5_metric.py +94 -0
- rubin_sim/maf/metrics/pair_metric.py +69 -0
- rubin_sim/maf/metrics/periodic_detect_metric.py +133 -0
- rubin_sim/maf/metrics/phase_gap_metric.py +172 -0
- rubin_sim/maf/metrics/qso_number_counts_metric.py +138 -0
- rubin_sim/maf/metrics/scaling_metrics.py +148 -0
- rubin_sim/maf/metrics/schedview_metrics.py +39 -0
- rubin_sim/maf/metrics/season_metrics.py +344 -0
- rubin_sim/maf/metrics/simple_metrics.py +546 -0
- rubin_sim/maf/metrics/sky_sat_metric.py +18 -0
- rubin_sim/maf/metrics/sn_cadence_metric.py +104 -0
- rubin_sim/maf/metrics/sn_n_sn_metric.py +1364 -0
- rubin_sim/maf/metrics/sn_sl_metric.py +216 -0
- rubin_sim/maf/metrics/sn_snr_metric.py +715 -0
- rubin_sim/maf/metrics/snr_weight.py +24 -0
- rubin_sim/maf/metrics/star_density.py +77 -0
- rubin_sim/maf/metrics/string_count_metric.py +95 -0
- rubin_sim/maf/metrics/summary_metrics.py +201 -0
- rubin_sim/maf/metrics/surfb_metric.py +175 -0
- rubin_sim/maf/metrics/technical_metrics.py +271 -0
- rubin_sim/maf/metrics/tgaps.py +412 -0
- rubin_sim/maf/metrics/tomography_models.py +2034 -0
- rubin_sim/maf/metrics/transient_metrics.py +268 -0
- rubin_sim/maf/metrics/uniformity_metrics.py +418 -0
- rubin_sim/maf/metrics/use_metrics.py +55 -0
- rubin_sim/maf/metrics/vector_metrics.py +190 -0
- rubin_sim/maf/metrics/visit_groups_metric.py +341 -0
- rubin_sim/maf/metrics/weak_lensing_systematics_metric.py +210 -0
- rubin_sim/maf/plots/__init__.py +14 -0
- rubin_sim/maf/plots/hg_plotters.py +1117 -0
- rubin_sim/maf/plots/hourglass_plotters.py +120 -0
- rubin_sim/maf/plots/mo_plotters.py +358 -0
- rubin_sim/maf/plots/nd_plotters.py +220 -0
- rubin_sim/maf/plots/neo_distance_plotter.py +140 -0
- rubin_sim/maf/plots/night_pointing_plotter.py +96 -0
- rubin_sim/maf/plots/oned_plotters.py +114 -0
- rubin_sim/maf/plots/perceptual_rainbow.py +30 -0
- rubin_sim/maf/plots/plot_handler.py +766 -0
- rubin_sim/maf/plots/skyproj_plotters.py +540 -0
- rubin_sim/maf/plots/spatial_plotters.py +1029 -0
- rubin_sim/maf/plots/special_plotters.py +256 -0
- rubin_sim/maf/plots/two_d_plotters.py +177 -0
- rubin_sim/maf/plots/xyplotter.py +37 -0
- rubin_sim/maf/run_comparison/__init__.py +5 -0
- rubin_sim/maf/run_comparison/archive.py +584 -0
- rubin_sim/maf/run_comparison/gather_summaries.py +125 -0
- rubin_sim/maf/run_comparison/microlensing_compare.py +514 -0
- rubin_sim/maf/run_comparison/radar_plot.py +202 -0
- rubin_sim/maf/run_comparison/summary_plots.py +710 -0
- rubin_sim/maf/run_moving_calc.py +239 -0
- rubin_sim/maf/run_moving_fractions.py +128 -0
- rubin_sim/maf/run_moving_join.py +103 -0
- rubin_sim/maf/run_selfcal_metric.py +92 -0
- rubin_sim/maf/scimaf_dir.py +87 -0
- rubin_sim/maf/show_maf.py +227 -0
- rubin_sim/maf/slicers/__init__.py +13 -0
- rubin_sim/maf/slicers/base_slicer.py +513 -0
- rubin_sim/maf/slicers/base_spatial_slicer.py +202 -0
- rubin_sim/maf/slicers/healpix_sdss_slicer.py +118 -0
- rubin_sim/maf/slicers/healpix_slicer.py +189 -0
- rubin_sim/maf/slicers/healpix_subset_slicer.py +293 -0
- rubin_sim/maf/slicers/hourglass_slicer.py +37 -0
- rubin_sim/maf/slicers/mo_slicer.py +171 -0
- rubin_sim/maf/slicers/movie_slicer.py +288 -0
- rubin_sim/maf/slicers/nd_slicer.py +147 -0
- rubin_sim/maf/slicers/one_d_slicer.py +210 -0
- rubin_sim/maf/slicers/time_interval_slicers.py +283 -0
- rubin_sim/maf/slicers/uni_slicer.py +57 -0
- rubin_sim/maf/slicers/user_points_slicer.py +141 -0
- rubin_sim/maf/stackers/__init__.py +13 -0
- rubin_sim/maf/stackers/base_stacker.py +221 -0
- rubin_sim/maf/stackers/coord_stackers.py +224 -0
- rubin_sim/maf/stackers/date_stackers.py +192 -0
- rubin_sim/maf/stackers/general_stackers.py +683 -0
- rubin_sim/maf/stackers/get_col_info.py +104 -0
- rubin_sim/maf/stackers/label_stackers.py +114 -0
- rubin_sim/maf/stackers/m5_optimal_stacker.py +126 -0
- rubin_sim/maf/stackers/mo_phase.py +265 -0
- rubin_sim/maf/stackers/mo_stackers.py +486 -0
- rubin_sim/maf/stackers/n_follow_stacker.py +187 -0
- rubin_sim/maf/stackers/neo_dist_stacker.py +126 -0
- rubin_sim/maf/stackers/sdss_stackers.py +30 -0
- rubin_sim/maf/stackers/sn_stacker.py +152 -0
- rubin_sim/maf/stackers/teff_stacker.py +154 -0
- rubin_sim/maf/utils/__init__.py +6 -0
- rubin_sim/maf/utils/astrometry_utils.py +93 -0
- rubin_sim/maf/utils/generate_fov_map.py +58 -0
- rubin_sim/maf/utils/get_date_version.py +28 -0
- rubin_sim/maf/utils/maf_utils.py +212 -0
- rubin_sim/maf/utils/opsim_utils.py +259 -0
- rubin_sim/maf/utils/output_utils.py +34 -0
- rubin_sim/maf/utils/sn_n_sn_utils.py +894 -0
- rubin_sim/maf/utils/sn_utils.py +369 -0
- rubin_sim/maf/utils/stellar_mags.py +197 -0
- rubin_sim/maf/web/__init__.py +2 -0
- rubin_sim/maf/web/favicon.ico +0 -0
- rubin_sim/maf/web/maf_run_results.py +645 -0
- rubin_sim/maf/web/maf_tracking.py +139 -0
- rubin_sim/maf/web/sorttable.js +496 -0
- rubin_sim/maf/web/templates/allmetricresults.html +72 -0
- rubin_sim/maf/web/templates/configs.html +28 -0
- rubin_sim/maf/web/templates/macros.html +243 -0
- rubin_sim/maf/web/templates/master.html +294 -0
- rubin_sim/maf/web/templates/metricselect.html +91 -0
- rubin_sim/maf/web/templates/multicolor.html +147 -0
- rubin_sim/maf/web/templates/results.html +82 -0
- rubin_sim/maf/web/templates/runselect.html +58 -0
- rubin_sim/maf/web/templates/stats.html +50 -0
- rubin_sim/moving_objects/__init__.py +8 -0
- rubin_sim/moving_objects/base_obs.py +468 -0
- rubin_sim/moving_objects/cheby_fits.py +689 -0
- rubin_sim/moving_objects/cheby_values.py +231 -0
- rubin_sim/moving_objects/chebyshev_utils.py +365 -0
- rubin_sim/moving_objects/direct_obs.py +376 -0
- rubin_sim/moving_objects/make_lsst_obs.py +282 -0
- rubin_sim/moving_objects/ooephemerides.py +643 -0
- rubin_sim/moving_objects/orbits.py +507 -0
- rubin_sim/moving_objects/pre_generate.py +37 -0
- rubin_sim/moving_objects/utils.py +61 -0
- rubin_sim/phot_utils/__init__.py +7 -0
- rubin_sim/phot_utils/bandpass.py +425 -0
- rubin_sim/phot_utils/photometric_parameters.py +449 -0
- rubin_sim/phot_utils/physical_parameters.py +50 -0
- rubin_sim/phot_utils/predicted_zeropoints.py +245 -0
- rubin_sim/phot_utils/sed.py +1773 -0
- rubin_sim/phot_utils/sed_utils.py +52 -0
- rubin_sim/phot_utils/signaltonoise.py +695 -0
- rubin_sim/phot_utils/spectral_resampling.py +161 -0
- rubin_sim/satellite_constellations/__init__.py +3 -0
- rubin_sim/satellite_constellations/basis_function.py +40 -0
- rubin_sim/satellite_constellations/model_observatory.py +157 -0
- rubin_sim/satellite_constellations/sat_utils.py +488 -0
- rubin_sim/selfcal/__init__.py +4 -0
- rubin_sim/selfcal/generate_catalog.py +188 -0
- rubin_sim/selfcal/offsets.py +119 -0
- rubin_sim/selfcal/solver.py +143 -0
- rubin_sim/selfcal/star_tools.py +42 -0
- rubin_sim/sim_archive/__init__.py +14 -0
- rubin_sim/sim_archive/conda_packages.py +65 -0
- rubin_sim/sim_archive/future_vsarch.py +480 -0
- rubin_sim/sim_archive/make_snapshot.py +255 -0
- rubin_sim/sim_archive/prenight.py +216 -0
- rubin_sim/sim_archive/prenightindex.py +229 -0
- rubin_sim/sim_archive/prototype.py +1029 -0
- rubin_sim/sim_archive/sim_archive.py +680 -0
- rubin_sim/sim_archive/tempdb.py +56 -0
- rubin_sim/sim_archive/util.py +146 -0
- rubin_sim/sim_archive/vseqarchive.py +965 -0
- rubin_sim/sim_archive/vseqmetadata.py +1721 -0
- rubin_sim/skybrightness/__init__.py +5 -0
- rubin_sim/skybrightness/allsky_db.py +93 -0
- rubin_sim/skybrightness/data/ESO_Spectra/eso_tools.py +505 -0
- rubin_sim/skybrightness/data/solarSpec/package.py +22 -0
- rubin_sim/skybrightness/generate_hdf5.py +243 -0
- rubin_sim/skybrightness/interp_components.py +798 -0
- rubin_sim/skybrightness/sky_model.py +771 -0
- rubin_sim/skybrightness/twilight_func.py +83 -0
- rubin_sim/skybrightness/utils.py +91 -0
- rubin_sim-2.6.1.dev2.dist-info/METADATA +95 -0
- rubin_sim-2.6.1.dev2.dist-info/RECORD +387 -0
- rubin_sim-2.6.1.dev2.dist-info/WHEEL +5 -0
- rubin_sim-2.6.1.dev2.dist-info/entry_points.txt +24 -0
- rubin_sim-2.6.1.dev2.dist-info/licenses/LICENSE +674 -0
- rubin_sim-2.6.1.dev2.dist-info/top_level.txt +5 -0
- sql/make_vseqmeta.sql +251 -0
- tests/data/test_data.py +26 -0
- tests/data/test_ddf_grid.py +17 -0
- tests/maf/test_3x2fom.py +68 -0
- tests/maf/test_archive.py +162 -0
- tests/maf/test_basemetrics.py +99 -0
- tests/maf/test_batchcommon.py +36 -0
- tests/maf/test_batches.py +159 -0
- tests/maf/test_cadencemetrics.py +388 -0
- tests/maf/test_calibrationmetrics.py +242 -0
- tests/maf/test_color_slopes.py +71 -0
- tests/maf/test_cosmology_summaries.py +20 -0
- tests/maf/test_gathersummaries.py +48 -0
- tests/maf/test_healpixslicer.py +439 -0
- tests/maf/test_healpixsubsetslicer.py +273 -0
- tests/maf/test_hgplotters.py +145 -0
- tests/maf/test_hourglassmetric.py +33 -0
- tests/maf/test_io.py +187 -0
- tests/maf/test_json.py +169 -0
- tests/maf/test_maps.py +199 -0
- tests/maf/test_metricbundle.py +69 -0
- tests/maf/test_mometrics.py +422 -0
- tests/maf/test_movieslicer.py +216 -0
- tests/maf/test_ndslicer.py +240 -0
- tests/maf/test_neodistanceplotter.py +41 -0
- tests/maf/test_onedslicer.py +245 -0
- tests/maf/test_opsimutils.py +80 -0
- tests/maf/test_plotters.py +134 -0
- tests/maf/test_resultsdb.py +145 -0
- tests/maf/test_schedviewmetrics.py +14 -0
- tests/maf/test_simplemetrics.py +200 -0
- tests/maf/test_snmetrics.py +335 -0
- tests/maf/test_snmetrics_nsn.py +123 -0
- tests/maf/test_stackers.py +423 -0
- tests/maf/test_stellarmags.py +50 -0
- tests/maf/test_stringcount.py +26 -0
- tests/maf/test_summary_plots.py +197 -0
- tests/maf/test_summarymetrics.py +82 -0
- tests/maf/test_technicalmetrics.py +267 -0
- tests/maf/test_templatemetrics.py +86 -0
- tests/maf/test_timeintervalslicers.py +97 -0
- tests/maf/test_trackingdb.py +88 -0
- tests/maf/test_unislicer.py +116 -0
- tests/maf/test_vectormetrics.py +225 -0
- tests/maf/test_visitgroupsmetric.py +181 -0
- tests/moving_objects/test_camera.py +39 -0
- tests/moving_objects/test_chebyfits.py +188 -0
- tests/moving_objects/test_chebyshevutils.py +76 -0
- tests/moving_objects/test_chebyvalues.py +245 -0
- tests/moving_objects/test_ephemerides.py +219 -0
- tests/moving_objects/test_orbits.py +170 -0
- tests/moving_objects/test_sed_data.py +61 -0
- tests/phot_utils/test_approximatebandpasses.py +91 -0
- tests/phot_utils/test_photometricparameters.py +268 -0
- tests/phot_utils/test_photometry.py +61 -0
- tests/phot_utils/test_predicted_zeropoints.py +53 -0
- tests/phot_utils/test_read_bandpasses.py +29 -0
- tests/phot_utils/test_sed.py +368 -0
- tests/phot_utils/test_snr.py +370 -0
- tests/satellite_constellations/test_satellites.py +36 -0
- tests/sim_archive/test_make_snapshot.py +24 -0
- tests/sim_archive/test_prototype_sim_archive.py +204 -0
- tests/sim_archive/test_vseqarchive.py +947 -0
- 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
|