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,593 @@
|
|
|
1
|
+
__all__ = (
|
|
2
|
+
"generate_microlensing_slicer",
|
|
3
|
+
"MicrolensingMetric",
|
|
4
|
+
"microlensing_amplification",
|
|
5
|
+
"microlensing_amplification_fsfb",
|
|
6
|
+
"info_peak_before_t0",
|
|
7
|
+
"fisher_matrix",
|
|
8
|
+
"coefficients_pspl",
|
|
9
|
+
"coefficients_fsfb",
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from copy import deepcopy
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from astropy import units as u
|
|
17
|
+
from astropy.coordinates import SkyCoord
|
|
18
|
+
from rubin_scheduler.data import get_data_dir
|
|
19
|
+
from rubin_scheduler.utils import hpid2_ra_dec
|
|
20
|
+
|
|
21
|
+
import rubin_sim.maf.metrics as metrics
|
|
22
|
+
import rubin_sim.maf.slicers as slicers
|
|
23
|
+
from rubin_sim.maf.utils import m52snr
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Via Natasha Abrams nsabrams@college.harvard.edu
|
|
27
|
+
def microlensing_amplification(t, impact_parameter=1, crossing_time=1825.0, peak_time=100, blending_factor=1):
|
|
28
|
+
"""The microlensing amplification
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
t : `float`
|
|
33
|
+
The time of observation (days)
|
|
34
|
+
impact_parameter : `float`
|
|
35
|
+
The impact paramter (0 means big amplification)
|
|
36
|
+
crossing_time : `float`
|
|
37
|
+
Einstein crossing time (days)
|
|
38
|
+
peak_time : `float`
|
|
39
|
+
The peak time (days)
|
|
40
|
+
blending_factor: `float`
|
|
41
|
+
The blending factor where 1 is unblended
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
lightcurve_u = np.sqrt(impact_parameter**2 + ((t - peak_time) ** 2 / crossing_time**2))
|
|
45
|
+
amplified_mag = (lightcurve_u**2 + 2) / (
|
|
46
|
+
lightcurve_u * np.sqrt(lightcurve_u**2 + 4)
|
|
47
|
+
) * blending_factor + (1 - blending_factor)
|
|
48
|
+
|
|
49
|
+
return amplified_mag
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def microlensing_amplification_fsfb(t, impact_parameter=1, crossing_time=1825.0, peak_time=100, fs=20, fb=20):
|
|
53
|
+
"""The microlensing amplification in terms of source flux and blend flux
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
t : `float`
|
|
58
|
+
The time of observation (days)
|
|
59
|
+
impact_parameter : `float`
|
|
60
|
+
The impact paramter (0 means big amplification)
|
|
61
|
+
crossing_time : `float`
|
|
62
|
+
Einstein crossing time (days)
|
|
63
|
+
peak_time : `float`
|
|
64
|
+
The peak time (days)
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
lightcurve_u = np.sqrt(impact_parameter**2 + ((t - peak_time) ** 2 / crossing_time**2))
|
|
68
|
+
amplified_mag = (lightcurve_u**2 + 2) / (lightcurve_u * np.sqrt(lightcurve_u**2 + 4)) * fs + fb
|
|
69
|
+
|
|
70
|
+
return amplified_mag
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def info_peak_before_t0(impact_parameter=1, crossing_time=100.0):
|
|
74
|
+
"""Time of Maximum Information before peak
|
|
75
|
+
|
|
76
|
+
The point of maximum information before peak indicates when in a
|
|
77
|
+
lightcurve with constant snr the contribution to the
|
|
78
|
+
characterization of the event timescale tE is at maximum. After that
|
|
79
|
+
point in timem the timescale characterization is decisively improved.
|
|
80
|
+
via Markus Hundertmark markus.hundertmark@uni-heidelberg.de
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
impact_parameter : `float`
|
|
85
|
+
The impact paramter (0 means big amplification)
|
|
86
|
+
crossing_time : `float`
|
|
87
|
+
Einstein crossing time (days)
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
optimal_time = (
|
|
91
|
+
crossing_time
|
|
92
|
+
* np.sqrt(
|
|
93
|
+
-(impact_parameter**2) + np.sqrt(9 * impact_parameter**4 + 36 * impact_parameter**2 + 4) - 2
|
|
94
|
+
)
|
|
95
|
+
/ 2
|
|
96
|
+
)
|
|
97
|
+
return np.array(optimal_time)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def coefficients_pspl(t, t0, te, u0, fs, fb):
|
|
101
|
+
"""Coefficients for calculating the first derivatives wrt t0,te,u0
|
|
102
|
+
in the Fisher matrix in an effective way, optimized with sympy and cse
|
|
103
|
+
via Markus Hundertmark markus.hundertmark@uni-heidelberg.de
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
t : `float`
|
|
108
|
+
The time of observation (days usually as JD or HJD)
|
|
109
|
+
u0 : `float`
|
|
110
|
+
The impact parameter (0 means high magnification)
|
|
111
|
+
te : `float`
|
|
112
|
+
Einstein crossing time (days)
|
|
113
|
+
t0 : `float`
|
|
114
|
+
Time of peak (days usually as JD or HJD)
|
|
115
|
+
fs : `float`
|
|
116
|
+
Source flux (counts/s but here fs = 10.**(-0.4*mag_source)
|
|
117
|
+
in the respective passband)
|
|
118
|
+
fb : `float`
|
|
119
|
+
Blend flux (counts/s but here fs = 10.**(-0.4*mag_blend)
|
|
120
|
+
in the respective passband)
|
|
121
|
+
"""
|
|
122
|
+
x0 = te ** (-2)
|
|
123
|
+
x1 = (t - t0) ** 2
|
|
124
|
+
x2 = u0**2 + x0 * x1
|
|
125
|
+
x3 = 1 / np.sqrt(x2)
|
|
126
|
+
x4 = 2 * x3
|
|
127
|
+
x5 = x2 + 4
|
|
128
|
+
x6 = fs / np.sqrt(x5)
|
|
129
|
+
x7 = x1 / te**3
|
|
130
|
+
x8 = x6 * x7
|
|
131
|
+
x9 = x2 + 2
|
|
132
|
+
x10 = x9 / x2 ** (3 / 2)
|
|
133
|
+
x11 = fs * x3 * x9 / x5 ** (3 / 2)
|
|
134
|
+
x12 = u0 * x6
|
|
135
|
+
x13 = x0 * (-2 * t + 2 * t0)
|
|
136
|
+
x14 = x13 * x6
|
|
137
|
+
|
|
138
|
+
c0 = x10 * x8 + x11 * x7 - x4 * x8
|
|
139
|
+
c1 = -u0 * x11 - x10 * x12 + x12 * x4
|
|
140
|
+
c2 = -1 / 2 * x10 * x14 - 1 / 2 * x11 * x13 + x14 * x3
|
|
141
|
+
|
|
142
|
+
return [c2, c1, c0]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def coefficients_fsfb(t, t0, te, u0, fs, fb):
|
|
146
|
+
"""Coefficients for calculating the first derivatives wrt fs,fb
|
|
147
|
+
in the Fisher (information) matrix in an effective way, optimized
|
|
148
|
+
with sympy and cse this function needs to be evaluated for each
|
|
149
|
+
passband respectively.
|
|
150
|
+
via Markus Hundertmark markus.hundertmark@uni-heidelberg.de
|
|
151
|
+
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
t : `float`
|
|
155
|
+
The time of observation (days usually as JD or HJD)
|
|
156
|
+
u0 : `float`
|
|
157
|
+
The impact parameter (0 means high magnification)
|
|
158
|
+
te : `float`
|
|
159
|
+
Einstein crossing time (days)
|
|
160
|
+
t0 : `float`
|
|
161
|
+
Time of peak (days usually as JD or HJD)
|
|
162
|
+
fs : `float`
|
|
163
|
+
Source flux (counts/s but here fs = 10.**(-0.4*mag_source)
|
|
164
|
+
in the respective passband)
|
|
165
|
+
fb : `float`
|
|
166
|
+
Blend flux (counts/s but here fs = 10.**(-0.4*mag_blend)
|
|
167
|
+
in the respective passband)
|
|
168
|
+
"""
|
|
169
|
+
x0 = u0**2 + (t - t0) ** 2 / te**2
|
|
170
|
+
c0 = (x0 + 2) / (np.sqrt(x0) * np.sqrt(x0 + 4))
|
|
171
|
+
c1 = 1
|
|
172
|
+
return [c1, c0]
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def fisher_matrix(t, t0, te, u0, fs, fb, snr, filters="ugriz", filter_name="i"):
|
|
176
|
+
"""The Fisher (information) matrix relying on first derivatives
|
|
177
|
+
wrt t0,te,u0,fs,fb, relying on with cse optimized coefficents.
|
|
178
|
+
This implementation for the non-linear magnification is subject to the
|
|
179
|
+
respective underlying assumptions, i.e. relatively small uncertainties.
|
|
180
|
+
NB the Fisher matrix is using first derivatives, alternatively one
|
|
181
|
+
could consider second derivatives the resulting covariance matrix as
|
|
182
|
+
inverse of the Fisher matrix is a Cramer Rao lower bound of the
|
|
183
|
+
respective uncertainty.
|
|
184
|
+
The function returns the full information matrix for all t.
|
|
185
|
+
|
|
186
|
+
via Markus Hundertmark markus.hundertmark@uni-heidelberg.de
|
|
187
|
+
|
|
188
|
+
Parameters
|
|
189
|
+
----------
|
|
190
|
+
t : `float`
|
|
191
|
+
The time of observation (days usually as JD or HJD)
|
|
192
|
+
u0 : `float`
|
|
193
|
+
The impact parameter (0 means high magnification)
|
|
194
|
+
te : `float`
|
|
195
|
+
Einstein crossing time (days)
|
|
196
|
+
t0 : `float`
|
|
197
|
+
Time of peak (days usually as JD or HJD)
|
|
198
|
+
fs : `float`
|
|
199
|
+
Source flux (counts/s but here fs = 10.**(-0.4*mag_source)
|
|
200
|
+
in the respective passband)
|
|
201
|
+
fb : `float`
|
|
202
|
+
Blend flux (counts/s but here fs = 10.**(-0.4*mag_blend)
|
|
203
|
+
in the respective passband)
|
|
204
|
+
snr : `float`
|
|
205
|
+
Signal to noise ratio in order to infer the flux uncertainty
|
|
206
|
+
"""
|
|
207
|
+
# indices are 0:te, 1:u0, 2:t0
|
|
208
|
+
# 3:fs_i, 4:fb_i, 5:fs_i+1, 6: fb_i+1, etc. for ugrizy
|
|
209
|
+
filters = filters
|
|
210
|
+
npars = 2 * len(filters) + 3
|
|
211
|
+
fis_mat = np.zeros((npars, npars))
|
|
212
|
+
filter_index = np.where(filters == filter_name)[0]
|
|
213
|
+
# initialize result matrix
|
|
214
|
+
for i in range(len(t)):
|
|
215
|
+
t_value = t[i]
|
|
216
|
+
# err = flux_err[i]
|
|
217
|
+
matrix = np.zeros((npars, npars))
|
|
218
|
+
derivatives = coefficients_pspl(t_value, t0, te, u0, fs, fb)
|
|
219
|
+
fsfb_derivatives = 2 * len(filters) * [0]
|
|
220
|
+
fbdiff, fsdiff = coefficients_fsfb(t_value, t0, te, u0, fs, fb)
|
|
221
|
+
np.array(fsfb_derivatives)[filter_index * 2] = fsdiff
|
|
222
|
+
np.array(fsfb_derivatives)[filter_index * 2 + 1] = fbdiff
|
|
223
|
+
derivatives = derivatives + fsfb_derivatives
|
|
224
|
+
for idx in range(npars):
|
|
225
|
+
for jdx in range(idx, npars):
|
|
226
|
+
matrix[idx, jdx] = derivatives[idx] * derivatives[jdx]
|
|
227
|
+
# restore symmetrical entries
|
|
228
|
+
matrix = matrix + matrix.T - np.diag(np.diag(matrix))
|
|
229
|
+
|
|
230
|
+
# microlenisng_amplification function to replace
|
|
231
|
+
usqr = (t_value - t0) ** 2 / te**2 + u0**2
|
|
232
|
+
mu = (usqr + 2.0) / (usqr * (usqr + 4)) ** 0.5
|
|
233
|
+
# may need to check shape of snr and t
|
|
234
|
+
flux_err = (fs * mu + fb) / snr[i]
|
|
235
|
+
|
|
236
|
+
matrix = matrix / (flux_err**2)
|
|
237
|
+
fis_mat = fis_mat + matrix
|
|
238
|
+
return fis_mat
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class MicrolensingMetric(metrics.BaseMetric):
|
|
242
|
+
"""
|
|
243
|
+
Quantifies detectability of Microlensing events.
|
|
244
|
+
Can also return the number of datapoints within two crossing times
|
|
245
|
+
of the peak of event.
|
|
246
|
+
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
metric_calc : `str`
|
|
250
|
+
Type of metric.
|
|
251
|
+
If metric_calc == 'detect', returns the number of microlensing events
|
|
252
|
+
detected within certain parameters.
|
|
253
|
+
If metric_calc == 'Npts', returns the number of points
|
|
254
|
+
within two crossing times of the peak of the vent.
|
|
255
|
+
pts_needed : `int`
|
|
256
|
+
Number of an object's lightcurve points required to be above the
|
|
257
|
+
5-sigma limiting depth before it is considered detected.
|
|
258
|
+
time_before_peak: `int` or `str`
|
|
259
|
+
Number of days before lightcurve peak to qualify event as triggered.
|
|
260
|
+
If time_before_peak == 'optimal', the number of days before the
|
|
261
|
+
lightcurve peak is the time of maximal information.
|
|
262
|
+
detect: `bool`
|
|
263
|
+
By default we trigger which only looks at points before the peak
|
|
264
|
+
of the lightcurve. When detect = True, observations on either side
|
|
265
|
+
of the lightcurve are considered.
|
|
266
|
+
|
|
267
|
+
Notes
|
|
268
|
+
-----
|
|
269
|
+
Expects slice_point to have keys of:
|
|
270
|
+
peak_time : float (days)
|
|
271
|
+
crossing_time : float (days)
|
|
272
|
+
impact_parameter : float (positive)
|
|
273
|
+
blending_factors (optional): float (between 0 and 1)
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
def __init__(
|
|
277
|
+
self,
|
|
278
|
+
metric_name="MicrolensingMetric",
|
|
279
|
+
metric_calc="detect",
|
|
280
|
+
mjd_col="observationStartMJD",
|
|
281
|
+
m5_col="fiveSigmaDepth",
|
|
282
|
+
filter_col="band",
|
|
283
|
+
night_col="night",
|
|
284
|
+
pts_needed=2,
|
|
285
|
+
mag_dict=None,
|
|
286
|
+
detect_sigma=3.0,
|
|
287
|
+
time_before_peak=0,
|
|
288
|
+
detect=False,
|
|
289
|
+
**kwargs,
|
|
290
|
+
):
|
|
291
|
+
self.metric_calc = metric_calc
|
|
292
|
+
if metric_calc == "detect":
|
|
293
|
+
self.units = "Detected, 0 or 1"
|
|
294
|
+
elif metric_calc == "Npts":
|
|
295
|
+
self.units = "Npts within 2tE"
|
|
296
|
+
elif metric_calc == "Fisher":
|
|
297
|
+
self.units = "Characterized, 0 or 1"
|
|
298
|
+
else:
|
|
299
|
+
raise Exception('metric_calc must be "detect", "Npts" or "Fisher".')
|
|
300
|
+
if mag_dict is None:
|
|
301
|
+
# Mean mag of stars in each filter from TRIstarDensity map
|
|
302
|
+
mag_dict = {
|
|
303
|
+
"u": 25.2,
|
|
304
|
+
"g": 25.0,
|
|
305
|
+
"r": 24.5,
|
|
306
|
+
"i": 23.4,
|
|
307
|
+
"z": 22.8,
|
|
308
|
+
"y": 22.5,
|
|
309
|
+
}
|
|
310
|
+
self.mjd_col = mjd_col
|
|
311
|
+
self.m5_col = m5_col
|
|
312
|
+
self.filter_col = filter_col
|
|
313
|
+
self.night_col = night_col
|
|
314
|
+
self.pts_needed = pts_needed
|
|
315
|
+
self.detect_sigma = detect_sigma
|
|
316
|
+
self.time_before_peak = time_before_peak
|
|
317
|
+
self.detect = detect
|
|
318
|
+
self.mags = mag_dict
|
|
319
|
+
|
|
320
|
+
cols = [self.mjd_col, self.m5_col, self.filter_col, self.night_col]
|
|
321
|
+
super(MicrolensingMetric, self).__init__(
|
|
322
|
+
col=cols, units=self.units, metric_name=metric_name + "_" + self.metric_calc, **kwargs
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
def run(self, data_slice, slice_point=None):
|
|
326
|
+
if self.detect is True and self.time_before_peak > 0:
|
|
327
|
+
raise Exception("When detect = True, time_before_peak must be zero")
|
|
328
|
+
|
|
329
|
+
# Generate the lightcurve for this object
|
|
330
|
+
# make t a kind of simple way
|
|
331
|
+
t = data_slice[self.mjd_col] - np.min(data_slice[self.night_col])
|
|
332
|
+
t = t - t.min()
|
|
333
|
+
|
|
334
|
+
#
|
|
335
|
+
# Try for if a blending factor slice was added
|
|
336
|
+
if "apparent_m_no_blend_u" in slice_point:
|
|
337
|
+
amplitudes = np.zeros(len(t))
|
|
338
|
+
individual_mags = True
|
|
339
|
+
else:
|
|
340
|
+
if "blending_factor" in slice_point:
|
|
341
|
+
amplitudes = microlensing_amplification(
|
|
342
|
+
t,
|
|
343
|
+
impact_parameter=slice_point["impact_parameter"],
|
|
344
|
+
crossing_time=slice_point["crossing_time"],
|
|
345
|
+
peak_time=slice_point["peak_time"],
|
|
346
|
+
blending_factor=slice_point["blending_factor"],
|
|
347
|
+
)
|
|
348
|
+
individual_mags = False
|
|
349
|
+
else:
|
|
350
|
+
amplitudes = microlensing_amplification(
|
|
351
|
+
t,
|
|
352
|
+
impact_parameter=slice_point["impact_parameter"],
|
|
353
|
+
crossing_time=slice_point["crossing_time"],
|
|
354
|
+
peak_time=slice_point["peak_time"],
|
|
355
|
+
)
|
|
356
|
+
individual_mags = False
|
|
357
|
+
|
|
358
|
+
filters = np.unique(data_slice[self.filter_col])
|
|
359
|
+
amplified_mags = amplitudes * 0
|
|
360
|
+
|
|
361
|
+
npars = 2 * len(filters) + 3
|
|
362
|
+
fis_mat = np.zeros((npars, npars))
|
|
363
|
+
fis_mat_wzeros = deepcopy(fis_mat)
|
|
364
|
+
|
|
365
|
+
for filtername in filters:
|
|
366
|
+
infilt = np.where(data_slice[self.filter_col] == filtername)[0]
|
|
367
|
+
|
|
368
|
+
if individual_mags is True:
|
|
369
|
+
fs = slice_point["apparent_m_no_blend_{}".format(filtername)]
|
|
370
|
+
fb = slice_point["apparent_m_{}".format(filtername)] - fs
|
|
371
|
+
amplitudes = microlensing_amplification_fsfb(
|
|
372
|
+
t,
|
|
373
|
+
impact_parameter=slice_point["impact_parameter"],
|
|
374
|
+
crossing_time=slice_point["crossing_time"],
|
|
375
|
+
peak_time=slice_point["peak_time"],
|
|
376
|
+
fs=fs,
|
|
377
|
+
fb=fb,
|
|
378
|
+
)
|
|
379
|
+
self.mags[filtername] = slice_point["apparent_m_{}".format(filtername)]
|
|
380
|
+
amplified_mags[infilt] = self.mags[filtername] - 2.5 * np.log10(amplitudes[infilt])
|
|
381
|
+
|
|
382
|
+
else:
|
|
383
|
+
amplified_mags[infilt] = self.mags[filtername] - 2.5 * np.log10(amplitudes[infilt])
|
|
384
|
+
|
|
385
|
+
# The SNR of each point in the light curve
|
|
386
|
+
snr = m52snr(amplified_mags, data_slice[self.m5_col])
|
|
387
|
+
# The magnitude uncertainties that go with amplified mags
|
|
388
|
+
mag_uncert = 2.5 * np.log10(1 + 1.0 / snr)
|
|
389
|
+
|
|
390
|
+
n_pre = []
|
|
391
|
+
n_post = []
|
|
392
|
+
for filtername in filters:
|
|
393
|
+
if self.metric_calc == "detect":
|
|
394
|
+
if self.time_before_peak == "optimal":
|
|
395
|
+
time_before_peak_optimal = info_peak_before_t0(
|
|
396
|
+
slice_point["impact_parameter"], slice_point["crossing_time"]
|
|
397
|
+
)
|
|
398
|
+
# observations pre-peak and in the given filter
|
|
399
|
+
infilt = np.where(
|
|
400
|
+
(data_slice[self.filter_col] == filtername)
|
|
401
|
+
& (t < (slice_point["peak_time"] - time_before_peak_optimal))
|
|
402
|
+
)[0]
|
|
403
|
+
|
|
404
|
+
else:
|
|
405
|
+
# observations pre-peak and in the given filter
|
|
406
|
+
infilt = np.where(
|
|
407
|
+
(data_slice[self.filter_col] == filtername)
|
|
408
|
+
& (t < (slice_point["peak_time"] - self.time_before_peak))
|
|
409
|
+
)[0]
|
|
410
|
+
|
|
411
|
+
# observations post-peak and in the given filter
|
|
412
|
+
outfilt = np.where(
|
|
413
|
+
(data_slice[self.filter_col] == filtername) & (t > slice_point["peak_time"])
|
|
414
|
+
)[0]
|
|
415
|
+
# Broadcast to calc the mag_i - mag_j
|
|
416
|
+
diffs = amplified_mags[infilt] - amplified_mags[infilt][:, np.newaxis]
|
|
417
|
+
diffs_uncert = np.sqrt(mag_uncert[infilt] ** 2 + mag_uncert[infilt][:, np.newaxis] ** 2)
|
|
418
|
+
diffs_post = amplified_mags[outfilt] - amplified_mags[outfilt][:, np.newaxis]
|
|
419
|
+
diffs_post_uncert = np.sqrt(
|
|
420
|
+
mag_uncert[outfilt] ** 2 + mag_uncert[outfilt][:, np.newaxis] ** 2
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
# Calculating this as a catalog-level detection. In theory,
|
|
424
|
+
# we could have a high SNR template image, so there would be
|
|
425
|
+
# little to no additional uncertianty from the subtraction.
|
|
426
|
+
|
|
427
|
+
sigma_above = np.abs(diffs) / diffs_uncert
|
|
428
|
+
sigma_above_post = np.abs(diffs_post) / diffs_post_uncert
|
|
429
|
+
# divide by 2 because array has i,j and j,i
|
|
430
|
+
n_above = np.size(np.where(sigma_above > self.detect_sigma)[0]) / 2
|
|
431
|
+
n_pre.append(n_above)
|
|
432
|
+
n_above_post = np.size(np.where(sigma_above_post > self.detect_sigma)[0]) / 2
|
|
433
|
+
n_post.append(n_above_post)
|
|
434
|
+
|
|
435
|
+
elif self.metric_calc == "Npts":
|
|
436
|
+
# observations pre-peak and in the given filter within 2tE
|
|
437
|
+
infilt = np.where(
|
|
438
|
+
(data_slice[self.filter_col] == filtername)
|
|
439
|
+
& (t < (slice_point["peak_time"]))
|
|
440
|
+
& (t > (slice_point["peak_time"] - slice_point["crossing_time"]))
|
|
441
|
+
& (snr > self.detect_sigma)
|
|
442
|
+
)[0]
|
|
443
|
+
# observations post-peak and in the given filter within 2tE
|
|
444
|
+
outfilt = np.where(
|
|
445
|
+
(data_slice[self.filter_col] == filtername)
|
|
446
|
+
& (t > (slice_point["peak_time"]))
|
|
447
|
+
& (t < (slice_point["peak_time"] + slice_point["crossing_time"]))
|
|
448
|
+
& (snr > self.detect_sigma)
|
|
449
|
+
)[0]
|
|
450
|
+
n_pre.append(len(infilt))
|
|
451
|
+
n_post.append(len(outfilt))
|
|
452
|
+
|
|
453
|
+
elif self.metric_calc == "Fisher":
|
|
454
|
+
if individual_mags is True:
|
|
455
|
+
fs = slice_point["apparent_m_no_blend_{}".format(filtername)]
|
|
456
|
+
fb = slice_point["apparent_m_{}".format(filtername)] - fs
|
|
457
|
+
else:
|
|
458
|
+
fs = self.mags[filtername]
|
|
459
|
+
# assuming that in populated areas of the galaxy
|
|
460
|
+
# the blend fraction is 0.5
|
|
461
|
+
fb = fs
|
|
462
|
+
|
|
463
|
+
fis_mat = fis_mat_wzeros + fisher_matrix(
|
|
464
|
+
t[infilt],
|
|
465
|
+
t0=slice_point["peak_time"],
|
|
466
|
+
te=slice_point["crossing_time"],
|
|
467
|
+
u0=slice_point["impact_parameter"],
|
|
468
|
+
fs=fs,
|
|
469
|
+
fb=fb,
|
|
470
|
+
snr=snr[infilt],
|
|
471
|
+
filters=filters,
|
|
472
|
+
filter_name=filtername,
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
# We remove entries if there's no data in a filter
|
|
476
|
+
# which would keep it from being inverted
|
|
477
|
+
# detectable information in dimensions:
|
|
478
|
+
fis_mat_wzeros = deepcopy(fis_mat)
|
|
479
|
+
mask_idx = np.where(np.diag(fis_mat) == 0)
|
|
480
|
+
fis_mat = np.delete(fis_mat, mask_idx[0], 0)
|
|
481
|
+
fis_mat = np.delete(fis_mat, mask_idx[0], 1)
|
|
482
|
+
try:
|
|
483
|
+
cov = np.linalg.inv(fis_mat)
|
|
484
|
+
sigmat_e_t_e = cov[0, 0] ** 0.5 / slice_point["crossing_time"]
|
|
485
|
+
# sigmau0_u0 = cov[1, 1] ** 0.5
|
|
486
|
+
# / slice_point["impact_parameter"]
|
|
487
|
+
# corr_btwn_t_eu0 = cov[0, 1] /
|
|
488
|
+
# (slice_point["crossing_time"]
|
|
489
|
+
# * slice_point["impact_parameter"])
|
|
490
|
+
except np.linalg.LinAlgError:
|
|
491
|
+
sigmat_e_t_e = np.inf
|
|
492
|
+
# sigmau0_u0 = np.inf
|
|
493
|
+
# corr_btwn_t_eu0 = np.inf
|
|
494
|
+
|
|
495
|
+
npts = np.sum(n_pre)
|
|
496
|
+
npts_post = np.sum(n_post)
|
|
497
|
+
if self.metric_calc == "detect":
|
|
498
|
+
if self.detect is True:
|
|
499
|
+
if npts >= self.pts_needed and npts_post >= self.pts_needed:
|
|
500
|
+
return 1
|
|
501
|
+
else:
|
|
502
|
+
return 0
|
|
503
|
+
else:
|
|
504
|
+
if npts >= self.pts_needed:
|
|
505
|
+
return 1
|
|
506
|
+
else:
|
|
507
|
+
return 0
|
|
508
|
+
elif self.metric_calc == "Npts":
|
|
509
|
+
return npts + npts_post
|
|
510
|
+
elif self.metric_calc == "Fisher":
|
|
511
|
+
# cutoff of sigmat_e_t_e < 0.1 for
|
|
512
|
+
# values determined by the 3sigma of
|
|
513
|
+
# pubished planet candidates
|
|
514
|
+
return sigmat_e_t_e
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def generate_microlensing_slicer(
|
|
518
|
+
min_crossing_time=1,
|
|
519
|
+
max_crossing_time=10,
|
|
520
|
+
t_start=1,
|
|
521
|
+
t_end=3652,
|
|
522
|
+
n_events=10000,
|
|
523
|
+
seed=42,
|
|
524
|
+
nside=128,
|
|
525
|
+
filtername="r",
|
|
526
|
+
):
|
|
527
|
+
"""Generate a UserPointSlicer with a population of microlensing events.
|
|
528
|
+
To be used with MicrolensingMetric
|
|
529
|
+
|
|
530
|
+
Parameters
|
|
531
|
+
----------
|
|
532
|
+
min_crossing_time : `float`
|
|
533
|
+
The minimum crossing time for the events generated (days)
|
|
534
|
+
max_crossing_time : `float`
|
|
535
|
+
The max crossing time for the events generated (days)
|
|
536
|
+
t_start : `float`
|
|
537
|
+
The night to start generating peaks (days)
|
|
538
|
+
t_end : `float`
|
|
539
|
+
The night to end generating peaks (days)
|
|
540
|
+
n_events : `int`
|
|
541
|
+
Number of microlensing events to generate
|
|
542
|
+
seed : `float`
|
|
543
|
+
Random number seed
|
|
544
|
+
nside : `int`
|
|
545
|
+
HEALpix nside, used to pick which stellar density map to load
|
|
546
|
+
filtername : `str`
|
|
547
|
+
The filter to use for the stellar density map
|
|
548
|
+
|
|
549
|
+
Returns
|
|
550
|
+
-------
|
|
551
|
+
slicer : `maf.UserPointsSlicer`
|
|
552
|
+
A slicer populated by microlensing events
|
|
553
|
+
(each slice_point is a different event)
|
|
554
|
+
"""
|
|
555
|
+
# Seed the random number generator and generate random parameters
|
|
556
|
+
rng = np.random.default_rng(seed)
|
|
557
|
+
crossing_times = rng.uniform(low=min_crossing_time, high=max_crossing_time, size=n_events)
|
|
558
|
+
peak_times = rng.uniform(low=t_start, high=t_end, size=n_events)
|
|
559
|
+
impact_paramters = rng.uniform(low=0, high=1, size=n_events)
|
|
560
|
+
|
|
561
|
+
map_dir = os.path.join(get_data_dir(), "maps", "TriMaps")
|
|
562
|
+
data = np.load(os.path.join(map_dir, "TRIstarDensity_%s_nside_%i.npz" % (filtername, nside)))
|
|
563
|
+
star_density = data["starDensity"].copy()
|
|
564
|
+
# magnitude bins
|
|
565
|
+
bins = data["bins"].copy()
|
|
566
|
+
data.close()
|
|
567
|
+
|
|
568
|
+
star_mag = 22
|
|
569
|
+
bin_indx = np.where(bins[1:] >= star_mag)[0].min()
|
|
570
|
+
density_used = star_density[:, bin_indx].ravel()
|
|
571
|
+
order = np.argsort(density_used)
|
|
572
|
+
# I think the model might have a few outliers at the extreme,
|
|
573
|
+
# let's truncate it a bit
|
|
574
|
+
density_used[order[-10:]] = density_used[order[-11]]
|
|
575
|
+
|
|
576
|
+
# now, let's draw N from that distribution squared
|
|
577
|
+
dist = density_used[order] ** 2
|
|
578
|
+
cumm_dist = np.cumsum(dist)
|
|
579
|
+
cumm_dist = cumm_dist / np.max(cumm_dist)
|
|
580
|
+
uniform_draw = rng.uniform(size=n_events)
|
|
581
|
+
indexes = np.floor(np.interp(uniform_draw, cumm_dist, np.arange(cumm_dist.size)))
|
|
582
|
+
hp_ids = order[indexes.astype(int)]
|
|
583
|
+
gal_l, gal_b = hpid2_ra_dec(nside, hp_ids, nest=True)
|
|
584
|
+
c = SkyCoord(l=gal_l * u.deg, b=gal_b * u.deg, frame="galactic").transform_to("icrs")
|
|
585
|
+
ra, dec = c.ra.deg, c.dec.deg
|
|
586
|
+
# Set up the slicer to evaluate the catalog we just made
|
|
587
|
+
slicer = slicers.UserPointsSlicer(ra, dec, lat_lon_deg=True, badval=0)
|
|
588
|
+
# Add any additional information about each object to the slicer
|
|
589
|
+
slicer.slice_points["peak_time"] = peak_times
|
|
590
|
+
slicer.slice_points["crossing_time"] = crossing_times
|
|
591
|
+
slicer.slice_points["impact_parameter"] = impact_paramters
|
|
592
|
+
|
|
593
|
+
return slicer
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Example for numObsInSurveyTimeOverlap
|
|
2
|
+
# Somayeh Khakpash - Lehigh University
|
|
3
|
+
# Last edited : 10/21/2020
|
|
4
|
+
# Calculates number of observations during simultaneous windows of another
|
|
5
|
+
# survey.
|
|
6
|
+
# SurveyObsWin is the list of the survey observing window/inter-seasonal
|
|
7
|
+
# gap intervals. It should be in the format:
|
|
8
|
+
# SurveyObsWin = [ [YYYY-MM-DD, YYYY-MM-DD] ,
|
|
9
|
+
# [YYYY-MM-DD, YYYY-MM-DD] , ... , [YYYY-MM-DD, YYYY-MM-DD] ]
|
|
10
|
+
|
|
11
|
+
__all__ = ("NumObsInSurveyTimeOverlapMetric",)
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
from astropy.time import Time
|
|
15
|
+
|
|
16
|
+
from rubin_sim.maf.metrics import BaseMetric
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class NumObsInSurveyTimeOverlapMetric(BaseMetric):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
survey_obs_win,
|
|
23
|
+
time_col="observationStartMJD",
|
|
24
|
+
metric_name="NumObsInSurveyTimeOverlapMetric",
|
|
25
|
+
**kwargs,
|
|
26
|
+
):
|
|
27
|
+
self.time_col = time_col
|
|
28
|
+
self.metric_name = metric_name
|
|
29
|
+
self.survey_obs_win = survey_obs_win
|
|
30
|
+
super(NumObsInSurveyTimeOverlapMetric, self).__init__(col=time_col, metric_name=metric_name, **kwargs)
|
|
31
|
+
|
|
32
|
+
def run(self, data_slice, slice_point=None):
|
|
33
|
+
n__obs = 0
|
|
34
|
+
for interval in self.survey_obs_win:
|
|
35
|
+
start_interval = Time(interval[0] + " 00:00:00")
|
|
36
|
+
end_interval = Time(interval[1] + " 00:00:00")
|
|
37
|
+
index = np.where(
|
|
38
|
+
(data_slice[self.time_col] > start_interval.mjd)
|
|
39
|
+
& (data_slice[self.time_col] < end_interval.mjd)
|
|
40
|
+
)[0]
|
|
41
|
+
n__obs = n__obs + np.size(index)
|
|
42
|
+
|
|
43
|
+
return n__obs
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Example for PeriodicMetric
|
|
2
|
+
# Mike Lund - Vanderbilt University
|
|
3
|
+
# mike.lund@gmail.com
|
|
4
|
+
# Last edited 3/10/2015
|
|
5
|
+
# Motivation: The detection of periodic signals can be examined by
|
|
6
|
+
# using canonical signals and attempted to recover these.
|
|
7
|
+
# However, a more general approach would be to examine the strength in
|
|
8
|
+
# signal that is lost as a result of poor phase coverage.
|
|
9
|
+
# This metric calculates the spectral window function for a set of
|
|
10
|
+
# scheduled observations. The largest peak at a nonzero frequency is
|
|
11
|
+
# used as a proxy to quantify how much power is
|
|
12
|
+
# lost to other frequencies. Full phase coverage will result in a value of 1.
|
|
13
|
+
# We refer to this as the Periodic Purity Function.
|
|
14
|
+
|
|
15
|
+
__all__ = ("PeriodicMetric",)
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
from rubin_sim.maf.metrics import BaseMetric
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PeriodicMetric(BaseMetric):
|
|
23
|
+
"""From a set of observation times, uses code provided by Robert Siverd
|
|
24
|
+
(LCOGT) to calculate the spectral window function.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, time_col="expMJD", **kwargs):
|
|
28
|
+
self.time_col = time_col
|
|
29
|
+
super(PeriodicMetric, self).__init__(col=[self.time_col], **kwargs)
|
|
30
|
+
|
|
31
|
+
def run(self, data_slice, slice_point=None):
|
|
32
|
+
frq_pts = 30000.0
|
|
33
|
+
max_frq = 25.0
|
|
34
|
+
times = data_slice[self.time_col]
|
|
35
|
+
times = times - times[0] # change times to smaller numbers
|
|
36
|
+
use_jd = np.array(times)
|
|
37
|
+
window_frq = np.arange(frq_pts) * max_frq / frq_pts
|
|
38
|
+
window_val = np.zeros_like(window_frq, dtype="float")
|
|
39
|
+
for x, frq in enumerate(window_frq):
|
|
40
|
+
window_val[x] = np.sum(np.cos(-2.0 * np.pi * frq * use_jd))
|
|
41
|
+
window_val /= np.float(use_jd.size)
|
|
42
|
+
secondpeak = np.sort(window_val)[-2]
|
|
43
|
+
totalsum = (np.sum(window_val) - np.sort(window_val)[-1]) / (frq_pts - 1)
|
|
44
|
+
data = np.asarray([secondpeak, totalsum])
|
|
45
|
+
return data
|
|
46
|
+
|
|
47
|
+
def reduce_peak(self, data):
|
|
48
|
+
return 1.0 - data[0]
|
|
49
|
+
|
|
50
|
+
def reduce_sum(self, data):
|
|
51
|
+
return data[1]
|