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,271 @@
|
|
|
1
|
+
__all__ = (
|
|
2
|
+
"NChangesMetric",
|
|
3
|
+
"MinTimeBetweenStatesMetric",
|
|
4
|
+
"NStateChangesFasterThanMetric",
|
|
5
|
+
"MaxStateChangesWithinMetric",
|
|
6
|
+
"OpenShutterFractionMetric",
|
|
7
|
+
"BruteOSFMetric",
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
from .base_metric import BaseMetric
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NChangesMetric(BaseMetric):
|
|
16
|
+
"""Compute the number of times a column value changes.
|
|
17
|
+
(useful for filter changes in particular).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, col="band", order_by="observationStartMJD", **kwargs):
|
|
21
|
+
self.col = col
|
|
22
|
+
self.order_by = order_by
|
|
23
|
+
super(NChangesMetric, self).__init__(col=[col, order_by], units="#", **kwargs)
|
|
24
|
+
|
|
25
|
+
def run(self, data_slice, slice_point=None):
|
|
26
|
+
idxs = np.argsort(data_slice[self.order_by])
|
|
27
|
+
diff = data_slice[self.col][idxs][1:] != data_slice[self.col][idxs][:-1]
|
|
28
|
+
return np.size(np.where(diff)[0])
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MinTimeBetweenStatesMetric(BaseMetric):
|
|
32
|
+
"""Compute the minimum time between changes of state in a column value.
|
|
33
|
+
(useful for calculating fastest time between filter changes in particular).
|
|
34
|
+
Returns delta time in minutes!
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
change_col : `str`
|
|
39
|
+
Column that we are tracking changes in.
|
|
40
|
+
time_col : str
|
|
41
|
+
Column with the time of each visit
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
change_col="band",
|
|
47
|
+
time_col="observationStartMJD",
|
|
48
|
+
metric_name=None,
|
|
49
|
+
**kwargs,
|
|
50
|
+
):
|
|
51
|
+
self.change_col = change_col
|
|
52
|
+
self.time_col = time_col
|
|
53
|
+
if metric_name is None:
|
|
54
|
+
metric_name = "Minimum time between %s changes (minutes)" % (change_col)
|
|
55
|
+
super(MinTimeBetweenStatesMetric, self).__init__(
|
|
56
|
+
col=[change_col, time_col], metric_name=metric_name, units="", **kwargs
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def run(self, data_slice, slice_point=None):
|
|
60
|
+
# Sort on time, to be sure we've got changes in the right order.
|
|
61
|
+
idxs = np.argsort(data_slice[self.time_col])
|
|
62
|
+
changes = data_slice[self.change_col][idxs][1:] != data_slice[self.change_col][idxs][:-1]
|
|
63
|
+
condition = np.where(changes)[0]
|
|
64
|
+
changetimes = data_slice[self.time_col][idxs][1:][condition]
|
|
65
|
+
prevchangetime = np.concatenate(
|
|
66
|
+
(
|
|
67
|
+
np.array([data_slice[self.time_col][idxs][0]]),
|
|
68
|
+
data_slice[self.time_col][idxs][1:][condition][:-1],
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
dtimes = changetimes - prevchangetime
|
|
72
|
+
dtimes *= 24 * 60
|
|
73
|
+
if dtimes.size == 0:
|
|
74
|
+
return self.badval
|
|
75
|
+
return dtimes.min()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class NStateChangesFasterThanMetric(BaseMetric):
|
|
79
|
+
"""
|
|
80
|
+
Compute the number of changes of state that happen faster than 'cutoff'.
|
|
81
|
+
(useful for calculating time between filter changes in particular).
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
change_col : `str`
|
|
86
|
+
Column that we are tracking changes in.
|
|
87
|
+
time_col : str
|
|
88
|
+
Column with the time of each visit
|
|
89
|
+
cutoff : `float`
|
|
90
|
+
The cutoff value for the time between changes (in minutes).
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def __init__(
|
|
94
|
+
self,
|
|
95
|
+
change_col="band",
|
|
96
|
+
time_col="observationStartMJD",
|
|
97
|
+
metric_name=None,
|
|
98
|
+
cutoff=20,
|
|
99
|
+
**kwargs,
|
|
100
|
+
):
|
|
101
|
+
if metric_name is None:
|
|
102
|
+
metric_name = "Number of %s changes faster than <%.1f minutes" % (
|
|
103
|
+
change_col,
|
|
104
|
+
cutoff,
|
|
105
|
+
)
|
|
106
|
+
self.change_col = change_col
|
|
107
|
+
self.time_col = time_col
|
|
108
|
+
# Convert cutoff from minutes to days.
|
|
109
|
+
self.cutoff = cutoff / 24.0 / 60.0
|
|
110
|
+
super(NStateChangesFasterThanMetric, self).__init__(
|
|
111
|
+
col=[change_col, time_col], metric_name=metric_name, units="#", **kwargs
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def run(self, data_slice, slice_point=None):
|
|
115
|
+
# Sort on time, to be sure we've got changes in the right order.
|
|
116
|
+
idxs = np.argsort(data_slice[self.time_col])
|
|
117
|
+
changes = data_slice[self.change_col][idxs][1:] != data_slice[self.change_col][idxs][:-1]
|
|
118
|
+
condition = np.where(changes)[0]
|
|
119
|
+
changetimes = data_slice[self.time_col][idxs][1:][condition]
|
|
120
|
+
prevchangetime = np.concatenate(
|
|
121
|
+
(
|
|
122
|
+
np.array([data_slice[self.time_col][idxs][0]]),
|
|
123
|
+
data_slice[self.time_col][idxs][1:][condition][:-1],
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
dtimes = changetimes - prevchangetime
|
|
127
|
+
return np.where(dtimes < self.cutoff)[0].size
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class MaxStateChangesWithinMetric(BaseMetric):
|
|
131
|
+
"""Compute the maximum number of changes of state that occur
|
|
132
|
+
within a given timespan.
|
|
133
|
+
(useful for calculating time between filter changes in particular).
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
change_col : `str`
|
|
138
|
+
Column that we are tracking changes in.
|
|
139
|
+
time_col : str
|
|
140
|
+
Column with the time of each visit
|
|
141
|
+
timespan : `float`
|
|
142
|
+
The timespan to count the number of changes within (in minutes).
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(
|
|
146
|
+
self,
|
|
147
|
+
change_col="band",
|
|
148
|
+
time_col="observationStartMJD",
|
|
149
|
+
metric_name=None,
|
|
150
|
+
timespan=20,
|
|
151
|
+
**kwargs,
|
|
152
|
+
):
|
|
153
|
+
if metric_name is None:
|
|
154
|
+
metric_name = "Max number of %s changes within %.1f minutes" % (
|
|
155
|
+
change_col,
|
|
156
|
+
timespan,
|
|
157
|
+
)
|
|
158
|
+
self.change_col = change_col
|
|
159
|
+
self.time_col = time_col
|
|
160
|
+
self.timespan = timespan / 24.0 / 60.0 # Convert timespan from minutes to days.
|
|
161
|
+
super(MaxStateChangesWithinMetric, self).__init__(
|
|
162
|
+
col=[change_col, time_col], metric_name=metric_name, units="#", **kwargs
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def run(self, data_slice, slice_point=None):
|
|
166
|
+
# This operates slightly differently from the metrics above;
|
|
167
|
+
# those calculate only successive times between changes, but here
|
|
168
|
+
# we must calculate the actual times of each change.
|
|
169
|
+
# Check if there was only one observation (and return 0 if so).
|
|
170
|
+
if data_slice[self.change_col].size == 1:
|
|
171
|
+
return 0
|
|
172
|
+
# Sort on time, to be sure we've got changes in the right order.
|
|
173
|
+
idxs = np.argsort(data_slice[self.time_col])
|
|
174
|
+
changes = data_slice[self.change_col][idxs][:-1] != data_slice[self.change_col][idxs][1:]
|
|
175
|
+
condition = np.where(changes)[0]
|
|
176
|
+
changetimes = data_slice[self.time_col][idxs][1:][condition]
|
|
177
|
+
# If there are 0 filter changes ...
|
|
178
|
+
if changetimes.size == 0:
|
|
179
|
+
return 0
|
|
180
|
+
# Otherwise ..
|
|
181
|
+
ct_plus = changetimes + self.timespan
|
|
182
|
+
indx2 = np.searchsorted(changetimes, ct_plus, side="right")
|
|
183
|
+
indx1 = np.arange(changetimes.size)
|
|
184
|
+
nchanges = indx2 - indx1
|
|
185
|
+
return nchanges.max()
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class OpenShutterFractionMetric(BaseMetric):
|
|
189
|
+
"""Compute the fraction of time the shutter is open
|
|
190
|
+
compared to the total time spent observing.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def __init__(
|
|
194
|
+
self,
|
|
195
|
+
metric_name="OpenShutterFraction",
|
|
196
|
+
slew_time_col="slewTime",
|
|
197
|
+
exp_time_col="visitExposureTime",
|
|
198
|
+
visit_time_col="visitTime",
|
|
199
|
+
**kwargs,
|
|
200
|
+
):
|
|
201
|
+
self.exp_time_col = exp_time_col
|
|
202
|
+
self.visit_time_col = visit_time_col
|
|
203
|
+
self.slew_time_col = slew_time_col
|
|
204
|
+
super(OpenShutterFractionMetric, self).__init__(
|
|
205
|
+
col=[self.exp_time_col, self.visit_time_col, self.slew_time_col],
|
|
206
|
+
metric_name=metric_name,
|
|
207
|
+
units="OpenShutter/TotalTime",
|
|
208
|
+
**kwargs,
|
|
209
|
+
)
|
|
210
|
+
self.comment = "Open shutter time (%s total) divided by total visit time " "(%s) + slewtime (%s)." % (
|
|
211
|
+
self.exp_time_col,
|
|
212
|
+
self.visit_time_col,
|
|
213
|
+
self.slew_time_col,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def run(self, data_slice, slice_point=None):
|
|
217
|
+
result = np.sum(data_slice[self.exp_time_col]) / np.sum(
|
|
218
|
+
data_slice[self.slew_time_col] + data_slice[self.visit_time_col]
|
|
219
|
+
)
|
|
220
|
+
return result
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class BruteOSFMetric(BaseMetric):
|
|
224
|
+
"""Assume I can't trust the slewtime or visittime colums.
|
|
225
|
+
This computes the fraction of time the shutter is open,
|
|
226
|
+
with no penalty for the first exposure after a long gap
|
|
227
|
+
(e.g., 1st exposure of the night).
|
|
228
|
+
Presumably, the telescope will need to focus, so there's not much a
|
|
229
|
+
scheduler could do to optimize keeping the shutter open after a closure.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
maxgap : `float`
|
|
234
|
+
The maximum gap between observations, in minutes.
|
|
235
|
+
Assume anything longer the dome has closed.
|
|
236
|
+
fudge : `float`
|
|
237
|
+
Fudge factor if a constant has to be added to the exposure time values.
|
|
238
|
+
This time (in seconds) is added to the exposure time.
|
|
239
|
+
exp_time_col : `str`
|
|
240
|
+
The name of the exposure time column. Assumed to be in seconds.
|
|
241
|
+
mjd_col : `str`
|
|
242
|
+
The name of the start of the exposures. Assumed to be in units of days.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
def __init__(
|
|
246
|
+
self,
|
|
247
|
+
metric_name="BruteOSFMetric",
|
|
248
|
+
exp_time_col="visitExposureTime",
|
|
249
|
+
mjd_col="observationStartMJD",
|
|
250
|
+
maxgap=10.0,
|
|
251
|
+
fudge=0.0,
|
|
252
|
+
**kwargs,
|
|
253
|
+
):
|
|
254
|
+
self.exp_time_col = exp_time_col
|
|
255
|
+
self.maxgap = maxgap / 60.0 / 24.0 # convert from min to days
|
|
256
|
+
self.mjd_col = mjd_col
|
|
257
|
+
self.fudge = fudge
|
|
258
|
+
super(BruteOSFMetric, self).__init__(
|
|
259
|
+
col=[self.exp_time_col, mjd_col],
|
|
260
|
+
metric_name=metric_name,
|
|
261
|
+
units="OpenShutter/TotalTime",
|
|
262
|
+
**kwargs,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
def run(self, data_slice, slice_point=None):
|
|
266
|
+
times = np.sort(data_slice[self.mjd_col])
|
|
267
|
+
diff = np.diff(times)
|
|
268
|
+
good = np.where(diff < self.maxgap)
|
|
269
|
+
open_time = np.sum(diff[good]) * 24.0 * 3600.0
|
|
270
|
+
result = np.sum(data_slice[self.exp_time_col] + self.fudge) / float(open_time)
|
|
271
|
+
return result
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
__all__ = (
|
|
2
|
+
"GapsMetric",
|
|
3
|
+
"TgapsMetric",
|
|
4
|
+
"TgapsPercentMetric",
|
|
5
|
+
"NightgapsMetric",
|
|
6
|
+
"NVisitsPerNightMetric",
|
|
7
|
+
"CoaddM5PerNightMetric",
|
|
8
|
+
"MaxGapMetric",
|
|
9
|
+
"NightTimespanMetric",
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from scipy.stats import binned_statistic
|
|
14
|
+
|
|
15
|
+
from ..utils import coadd_m5
|
|
16
|
+
from .base_metric import BaseMetric
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class GapsMetric(BaseMetric):
|
|
20
|
+
"""Compute the number of times a gaps of a specified timescale
|
|
21
|
+
(+/- 1/2 timescale) is sampled.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
times_col : `str`, optional
|
|
26
|
+
The column name for the exposure times. Values assumed to be in days.
|
|
27
|
+
Default is 'observationStartMJD'.
|
|
28
|
+
time_scale : `float`, optional
|
|
29
|
+
Time scale to see how well it is sampled (hours).
|
|
30
|
+
For example, the default of 2 hours means
|
|
31
|
+
observations spaced anywhere between 1 and 3 hours apart
|
|
32
|
+
will count as a sample. Default 2 hours.
|
|
33
|
+
units : `str`, optional
|
|
34
|
+
Default units to use for plots, etc. Default is "N" (for number).
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
times_col="observationStartMJD",
|
|
40
|
+
time_scale=2.0,
|
|
41
|
+
units="N",
|
|
42
|
+
**kwargs,
|
|
43
|
+
):
|
|
44
|
+
self.times_col = times_col
|
|
45
|
+
# Convert to days and divide by two so we bin at the Nyquist frequency
|
|
46
|
+
self.bin_size = (time_scale / 24.0) / 2.0
|
|
47
|
+
super().__init__(col=[self.times_col], metric_dtype="float", units=units, **kwargs)
|
|
48
|
+
|
|
49
|
+
def run(self, data_slice, slice_point=None):
|
|
50
|
+
if data_slice.size < 2:
|
|
51
|
+
return self.badval
|
|
52
|
+
times = np.sort(data_slice[self.times_col])
|
|
53
|
+
bins = np.arange(times.min() - self.bin_size, times.max() + self.bin_size, self.bin_size)
|
|
54
|
+
vals, _be = np.histogram(times, bins)
|
|
55
|
+
# Bins are at 1/2 desired timescale, so compare bin 0 to bin 2 to see
|
|
56
|
+
# if the timescale has been sampled.
|
|
57
|
+
mult = vals[2:] * vals[0:-2]
|
|
58
|
+
result = np.size(np.where(mult > 0)[0])
|
|
59
|
+
|
|
60
|
+
return result
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class TgapsMetric(BaseMetric):
|
|
64
|
+
"""Histogram the times of the gaps between observations.
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
Measure the gaps between observations. By default, only gaps
|
|
68
|
+
between neighboring visits are computed. If all_gaps is set to true,
|
|
69
|
+
all gaps are computed (i.e., if there are observations at 10, 20, 30
|
|
70
|
+
and 40 the default will return a histogram of [10,10,10] while
|
|
71
|
+
all_gaps returns a histogram of [10,10,10,20,20,30])
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
times_col : `str`, optional
|
|
76
|
+
The column name for the exposure times. Values assumed to be in days.
|
|
77
|
+
Default observationStartMJD.
|
|
78
|
+
all_gaps : `bool`, optional
|
|
79
|
+
Histogram the gaps between all observations (True) or just successive
|
|
80
|
+
observations (False)?
|
|
81
|
+
Default is False.
|
|
82
|
+
If all gaps are used, this metric can become significantly slower.
|
|
83
|
+
bins : `np.ndarray`, optional
|
|
84
|
+
The bins to use for the histogram of time gaps
|
|
85
|
+
(in days, or same units as times_col).
|
|
86
|
+
Default values are bins from 0 to 2 hours, in 5 minute intervals.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
histogram : `np.ndarray`
|
|
91
|
+
Returns a histogram of the tgaps at each slice point;
|
|
92
|
+
these histograms can be combined and plotted using the
|
|
93
|
+
'SummaryHistogram plotter'.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def __init__(
|
|
97
|
+
self,
|
|
98
|
+
times_col="observationStartMJD",
|
|
99
|
+
all_gaps=False,
|
|
100
|
+
bins=np.arange(0, 120.0, 5.0) / 60.0 / 24.0,
|
|
101
|
+
units="days",
|
|
102
|
+
**kwargs,
|
|
103
|
+
):
|
|
104
|
+
# Pass the same bins to the plotter.
|
|
105
|
+
self.bins = bins
|
|
106
|
+
self.times_col = times_col
|
|
107
|
+
super().__init__(col=[self.times_col], metric_dtype="object", units=units, **kwargs)
|
|
108
|
+
self.all_gaps = all_gaps
|
|
109
|
+
|
|
110
|
+
def run(self, data_slice, slice_point=None):
|
|
111
|
+
if data_slice.size < 2:
|
|
112
|
+
return self.badval
|
|
113
|
+
times = np.sort(data_slice[self.times_col])
|
|
114
|
+
if self.all_gaps:
|
|
115
|
+
all_diffs = []
|
|
116
|
+
for i in np.arange(1, times.size, 1):
|
|
117
|
+
all_diffs.append((times - np.roll(times, i))[i:])
|
|
118
|
+
dts = np.concatenate(all_diffs)
|
|
119
|
+
else:
|
|
120
|
+
dts = np.diff(times)
|
|
121
|
+
result, bins = np.histogram(dts, self.bins)
|
|
122
|
+
return result
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TgapsPercentMetric(BaseMetric):
|
|
126
|
+
"""Compute the fraction of the time gaps between observations that occur
|
|
127
|
+
in a given time range.
|
|
128
|
+
|
|
129
|
+
Measure the gaps between observations. By default, only gaps
|
|
130
|
+
between neighboring visits are computed. If all_gaps is set to true,
|
|
131
|
+
all gaps are computed (i.e., if there are observations at 10, 20, 30 and
|
|
132
|
+
40 the default will compute the percent of gaps between
|
|
133
|
+
specified endpoints.
|
|
134
|
+
|
|
135
|
+
This is different from the TgapsMetric in that this only looks at
|
|
136
|
+
what percent of intervals fall into the specified range, rather than
|
|
137
|
+
histogramming the entire set of tgaps.
|
|
138
|
+
|
|
139
|
+
This metric has drawbacks in that the result is tied to the overall
|
|
140
|
+
number of tgaps (i.e. a result of 100 could still be worse than
|
|
141
|
+
a different simulation with a result of 50, in terms of how often a
|
|
142
|
+
particular Tgap is sampled).
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
times_col : `str`, opt
|
|
147
|
+
The column name for the exposure times. Values assumed to be in days.
|
|
148
|
+
Default observationStartMJD.
|
|
149
|
+
all_gaps : `bool`, opt
|
|
150
|
+
Histogram the gaps between all observations (True) or
|
|
151
|
+
just successive observations (False)?
|
|
152
|
+
Default is False. If all gaps are used, this metric
|
|
153
|
+
can become significantly slower.
|
|
154
|
+
min_time : `float`, opt
|
|
155
|
+
Minimum time of gaps to include (days). Default 2/24 (2 hours).
|
|
156
|
+
max_time : `float`, opt
|
|
157
|
+
Max time of gaps to include (days). Default 14/24 (14 hours).
|
|
158
|
+
|
|
159
|
+
Returns
|
|
160
|
+
-------
|
|
161
|
+
percent : `float`
|
|
162
|
+
Returns a float percent of the CDF between cdfMinTime and cdfMaxTime -
|
|
163
|
+
(# of tgaps within min_time/max_time / # of all tgaps).
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
def __init__(
|
|
167
|
+
self,
|
|
168
|
+
times_col="observationStartMJD",
|
|
169
|
+
all_gaps=False,
|
|
170
|
+
min_time=2.0 / 24,
|
|
171
|
+
max_time=14.0 / 24,
|
|
172
|
+
units="percent",
|
|
173
|
+
**kwargs,
|
|
174
|
+
):
|
|
175
|
+
self.times_col = times_col
|
|
176
|
+
assert min_time <= max_time
|
|
177
|
+
self.min_time = min_time
|
|
178
|
+
self.max_time = max_time
|
|
179
|
+
super().__init__(col=[self.times_col], metric_dtype="float", units=units, **kwargs)
|
|
180
|
+
self.all_gaps = all_gaps
|
|
181
|
+
|
|
182
|
+
def run(self, data_slice, slice_point=None):
|
|
183
|
+
if data_slice.size < 2:
|
|
184
|
+
return self.badval
|
|
185
|
+
times = np.sort(data_slice[self.times_col])
|
|
186
|
+
if self.all_gaps:
|
|
187
|
+
all_diffs = []
|
|
188
|
+
for i in np.arange(1, times.size, 1):
|
|
189
|
+
all_diffs.append((times - np.roll(times, i))[i:])
|
|
190
|
+
dts = np.concatenate(all_diffs)
|
|
191
|
+
else:
|
|
192
|
+
dts = np.diff(times)
|
|
193
|
+
n_in_window = np.sum((dts >= self.min_time) & (dts <= self.max_time))
|
|
194
|
+
return n_in_window / len(dts) * 100.0
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class NightgapsMetric(BaseMetric):
|
|
198
|
+
"""Histogram the number of nights between observations.
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
Measure the gaps between observations. By default, only gaps
|
|
202
|
+
between neighboring visits are computed. If all_gaps is set to true,
|
|
203
|
+
all gaps are computed (i.e., if there are observations at 10, 20, 30 and
|
|
204
|
+
40 the default will
|
|
205
|
+
histogram [10,10,10] while all_gaps histograms [10,10,10,20,20,30])
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
night_col : `str`, optional
|
|
210
|
+
The column name for the night of each observation.
|
|
211
|
+
Default 'night'.
|
|
212
|
+
all_gaps : `bool`, optional
|
|
213
|
+
Histogram the gaps between all observations (True) or just successive
|
|
214
|
+
observations (False)?
|
|
215
|
+
Default is False. If all gaps are used, this metric can become
|
|
216
|
+
significantly slower.
|
|
217
|
+
bins : `np.ndarray`, optional
|
|
218
|
+
The bins to use for the histogram of time gaps (in days, or same
|
|
219
|
+
units as timesCol).
|
|
220
|
+
Default values are bins from 0 to 10 days, in 1 day intervals.
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
histogram : `np.ndarray`
|
|
225
|
+
Returns a histogram of the deltaT between nights at each slice point;
|
|
226
|
+
these histograms can be combined and plotted using the
|
|
227
|
+
'SummaryHistogram plotter'.
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
def __init__(
|
|
231
|
+
self,
|
|
232
|
+
night_col="night",
|
|
233
|
+
all_gaps=False,
|
|
234
|
+
bins=np.arange(0, 10, 1),
|
|
235
|
+
units="nights",
|
|
236
|
+
**kwargs,
|
|
237
|
+
):
|
|
238
|
+
# Pass the same bins to the plotter.
|
|
239
|
+
self.bins = bins
|
|
240
|
+
self.night_col = night_col
|
|
241
|
+
super().__init__(col=[self.night_col], metric_dtype="object", units=units, **kwargs)
|
|
242
|
+
self.all_gaps = all_gaps
|
|
243
|
+
|
|
244
|
+
def run(self, data_slice, slice_point=None):
|
|
245
|
+
if data_slice.size < 2:
|
|
246
|
+
return self.badval
|
|
247
|
+
nights = np.sort(np.unique(data_slice[self.night_col]))
|
|
248
|
+
if self.all_gaps:
|
|
249
|
+
all_diffs = []
|
|
250
|
+
for i in np.arange(1, nights.size, 1):
|
|
251
|
+
all_diffs.append((nights - np.roll(nights, i))[i:])
|
|
252
|
+
dnights = np.concatenate(all_diffs)
|
|
253
|
+
else:
|
|
254
|
+
dnights = np.diff(nights)
|
|
255
|
+
result, bins = np.histogram(dnights, self.bins)
|
|
256
|
+
return result
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class NVisitsPerNightMetric(BaseMetric):
|
|
260
|
+
"""Histogram the number of visits in each night.
|
|
261
|
+
|
|
262
|
+
Splits the visits by night, then histograms how many visits occur
|
|
263
|
+
in each night.
|
|
264
|
+
|
|
265
|
+
Parameters
|
|
266
|
+
----------
|
|
267
|
+
night_col : `str`, optional
|
|
268
|
+
The column name for the night of each observation.
|
|
269
|
+
Default 'night'.
|
|
270
|
+
bins : `np.ndarray`, optional
|
|
271
|
+
The bins to use for the histogram of time gaps (in days, or same
|
|
272
|
+
units as timesCol).
|
|
273
|
+
Default values are bins from 0 to 5 visits, in steps of 1.
|
|
274
|
+
|
|
275
|
+
Returns
|
|
276
|
+
-------
|
|
277
|
+
histogram : `np.ndarray`
|
|
278
|
+
Returns a histogram of the number of visits per night at each
|
|
279
|
+
slice point; these histograms can be combined and plotted using the
|
|
280
|
+
'SummaryHistogram plotter'.
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
def __init__(self, night_col="night", bins=np.arange(0, 10, 1), units="#", **kwargs):
|
|
284
|
+
# Pass the same bins to the plotter.
|
|
285
|
+
self.bins = bins
|
|
286
|
+
self.night_col = night_col
|
|
287
|
+
super().__init__(col=[self.night_col], metric_dtype="object", units=units, **kwargs)
|
|
288
|
+
|
|
289
|
+
def run(self, data_slice, slice_point=None):
|
|
290
|
+
n, counts = np.unique(data_slice[self.night_col], return_counts=True)
|
|
291
|
+
result, bins = np.histogram(counts, self.bins)
|
|
292
|
+
return result
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class CoaddM5PerNightMetric(BaseMetric):
|
|
296
|
+
"""Histogram the coadded depth of visits in each night.
|
|
297
|
+
|
|
298
|
+
Splits the visits by night, then histograms the coadded depth.
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
night_col : `str`, optional
|
|
303
|
+
The column name for the night of each observation.
|
|
304
|
+
Default 'night'.
|
|
305
|
+
m5_col : `str`, optional
|
|
306
|
+
The column name for the five sigma depth of each observation.
|
|
307
|
+
bins : `np.ndarray`, (N,) optional
|
|
308
|
+
The bins to use for the histogram of magnitude values.
|
|
309
|
+
|
|
310
|
+
Returns
|
|
311
|
+
-------
|
|
312
|
+
histogram : `np.ndarray`
|
|
313
|
+
Returns a histogram of the coadded depth per night at each slice point;
|
|
314
|
+
these histograms can be combined and plotted using the
|
|
315
|
+
'SummaryHistogram plotter'.
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
def __init__(
|
|
319
|
+
self, night_col="night", m5_col="fiveSigmaDepth", bins=np.arange(20, 25, 0.05), units="mag", **kwargs
|
|
320
|
+
):
|
|
321
|
+
# Pass the same bins to the plotter.
|
|
322
|
+
self.night_col = night_col
|
|
323
|
+
self.m5_col = m5_col
|
|
324
|
+
self.bins = bins
|
|
325
|
+
super().__init__(col=[self.night_col, self.m5_col], metric_dtype="object", units=units, **kwargs)
|
|
326
|
+
|
|
327
|
+
def run(self, data_slice, slice_point=None):
|
|
328
|
+
m5_per_night, be, bn = binned_statistic(
|
|
329
|
+
data_slice[self.night_col],
|
|
330
|
+
data_slice[self.m5_col],
|
|
331
|
+
statistic=coadd_m5,
|
|
332
|
+
bins=np.arange(0, 3653, 1),
|
|
333
|
+
)
|
|
334
|
+
# Drop the nights with no observations (-inf)
|
|
335
|
+
m5_per_night = m5_per_night[np.where(m5_per_night > 0)]
|
|
336
|
+
result, bins = np.histogram(m5_per_night, self.bins)
|
|
337
|
+
return result
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class MaxGapMetric(BaseMetric):
|
|
341
|
+
"""Find the maximum gap (in days) in between successive observations.
|
|
342
|
+
|
|
343
|
+
Useful for making sure there is an image within the last year that
|
|
344
|
+
would make a good template image.
|
|
345
|
+
|
|
346
|
+
Parameters
|
|
347
|
+
----------
|
|
348
|
+
mjd_col : `str`, opt
|
|
349
|
+
The column name of the night of each observation.
|
|
350
|
+
|
|
351
|
+
Returns
|
|
352
|
+
-------
|
|
353
|
+
maxGap : `float`
|
|
354
|
+
The maximum gap (in days) between visits.
|
|
355
|
+
"""
|
|
356
|
+
|
|
357
|
+
def __init__(self, mjd_col="observationStartMJD", **kwargs):
|
|
358
|
+
self.mjd_col = mjd_col
|
|
359
|
+
units = "Days"
|
|
360
|
+
super(MaxGapMetric, self).__init__(col=[self.mjd_col], units=units, **kwargs)
|
|
361
|
+
|
|
362
|
+
def run(self, data_slice, slice_point=None):
|
|
363
|
+
gaps = np.diff(np.sort(data_slice[self.mjd_col]))
|
|
364
|
+
if np.size(gaps) > 0:
|
|
365
|
+
result = np.max(gaps)
|
|
366
|
+
else:
|
|
367
|
+
result = self.badval
|
|
368
|
+
return result
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class NightTimespanMetric(BaseMetric):
|
|
372
|
+
"""Calculate the maximum time span covered in each night,
|
|
373
|
+
report the `percentile` value of all timespans.
|
|
374
|
+
|
|
375
|
+
Parameters
|
|
376
|
+
----------
|
|
377
|
+
percentile : `float`, opt
|
|
378
|
+
Percentile value to report. Default 75th percentile.
|
|
379
|
+
night_col : `str`, opt
|
|
380
|
+
Name of the night column. Default 'night'.
|
|
381
|
+
mjd_col : `str`, opt
|
|
382
|
+
Name of the MJD visit column. Default 'observationStartMJD'.
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
def __init__(self, percentile=75, night_col="night", mjd_col="observationStartMJD", **kwargs):
|
|
386
|
+
self.percentile = percentile
|
|
387
|
+
self.night_col = night_col
|
|
388
|
+
self.mjd_col = mjd_col
|
|
389
|
+
if "metric_name" in kwargs:
|
|
390
|
+
metric_name = kwargs["metric_name"]
|
|
391
|
+
del kwargs["metric_name"]
|
|
392
|
+
else:
|
|
393
|
+
metric_name = f"{percentile}th Percentile Intranight Timespan"
|
|
394
|
+
super().__init__(
|
|
395
|
+
col=[self.night_col, self.mjd_col],
|
|
396
|
+
units="minutes",
|
|
397
|
+
metric_name=metric_name,
|
|
398
|
+
**kwargs,
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
def run(self, data_slice, slice_point=None):
|
|
402
|
+
data = np.sort(data_slice, order=self.mjd_col)
|
|
403
|
+
unights, counts = np.unique(data[self.night_col], return_counts=True)
|
|
404
|
+
unights = unights[np.where(counts > 1)]
|
|
405
|
+
if len(unights) == 0:
|
|
406
|
+
result = self.badval
|
|
407
|
+
else:
|
|
408
|
+
nstart = np.searchsorted(data[self.night_col], unights, side="left")
|
|
409
|
+
nend = np.searchsorted(data[self.night_col], unights, side="right") - 1
|
|
410
|
+
tspans = (data[self.mjd_col][nend] - data[self.mjd_col][nstart]) * 24.0 * 60.0
|
|
411
|
+
result = np.percentile(tspans, self.percentile)
|
|
412
|
+
return result
|