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,130 @@
|
|
|
1
|
+
__all__ = ("HourglassMetric",)
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from astroplan import Observer
|
|
5
|
+
from astropy import units as u
|
|
6
|
+
from astropy.coordinates import AltAz, EarthLocation, get_body, get_sun
|
|
7
|
+
from astropy.time import Time
|
|
8
|
+
from rubin_scheduler.utils import Site
|
|
9
|
+
|
|
10
|
+
from .base_metric import BaseMetric
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def nearest_val(A, val):
|
|
14
|
+
return A[np.argmin(np.abs(np.array(A) - val))]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class HourglassMetric(BaseMetric):
|
|
18
|
+
"""Plot the filters used as a function of time.
|
|
19
|
+
Must be used with the Hourglass Slicer.
|
|
20
|
+
Will totally fail in the arctic circle.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
telescope="LSST",
|
|
26
|
+
mjd_col="observationStartMJD",
|
|
27
|
+
filter_col="band",
|
|
28
|
+
night_col="night",
|
|
29
|
+
delta_t=60.0,
|
|
30
|
+
**kwargs,
|
|
31
|
+
):
|
|
32
|
+
self.mjd_col = mjd_col
|
|
33
|
+
self.filter_col = filter_col
|
|
34
|
+
self.night_col = night_col
|
|
35
|
+
cols = [self.mjd_col, self.filter_col, self.night_col]
|
|
36
|
+
super(HourglassMetric, self).__init__(col=cols, metric_dtype="object", **kwargs)
|
|
37
|
+
self.telescope = Site(name=telescope)
|
|
38
|
+
self.delta_t = delta_t / 60.0 / 24.0
|
|
39
|
+
self.location = EarthLocation(
|
|
40
|
+
lat=self.telescope.latitude_rad * u.rad,
|
|
41
|
+
lon=self.telescope.longitude_rad * u.rad,
|
|
42
|
+
height=self.telescope.height * u.m,
|
|
43
|
+
)
|
|
44
|
+
self.observer = Observer(location=self.location)
|
|
45
|
+
|
|
46
|
+
def run(self, data_slice, slice_point=None):
|
|
47
|
+
data_slice.sort(order=self.mjd_col)
|
|
48
|
+
unights, uindx = np.unique(data_slice[self.night_col], return_index=True)
|
|
49
|
+
|
|
50
|
+
mjds = np.arange(np.min(data_slice[self.mjd_col]), np.max(data_slice[self.mjd_col]) + 1, 0.5)
|
|
51
|
+
|
|
52
|
+
# Define the breakpoints as where either the filter changes OR
|
|
53
|
+
# there's more than a 2 minute gap in observing
|
|
54
|
+
good = np.where(
|
|
55
|
+
(data_slice[self.filter_col] != np.roll(data_slice[self.filter_col], 1))
|
|
56
|
+
| (
|
|
57
|
+
np.abs(np.roll(data_slice[self.mjd_col], 1) - data_slice[self.mjd_col])
|
|
58
|
+
> 120.0 / 3600.0 / 24.0
|
|
59
|
+
)
|
|
60
|
+
)[0]
|
|
61
|
+
good = np.concatenate((good, [0], [len(data_slice[self.filter_col])]))
|
|
62
|
+
good = np.unique(good)
|
|
63
|
+
left = good[:-1]
|
|
64
|
+
right = good[1:] - 1
|
|
65
|
+
good = np.ravel(list(zip(left, right)))
|
|
66
|
+
|
|
67
|
+
names = ["mjd", "midnight", "filter"]
|
|
68
|
+
types = ["float", "float", (np.str_, 1)]
|
|
69
|
+
perfilter = np.zeros((good.size), dtype=list(zip(names, types)))
|
|
70
|
+
perfilter["mjd"] = data_slice[self.mjd_col][good]
|
|
71
|
+
perfilter["filter"] = data_slice[self.filter_col][good]
|
|
72
|
+
|
|
73
|
+
# brute force compute midnight times for all days between
|
|
74
|
+
# start and enc of data_slice
|
|
75
|
+
times = Time(mjds, format="mjd")
|
|
76
|
+
# let's just find the midnight before and after each of the
|
|
77
|
+
# pre_night MJD values
|
|
78
|
+
m_after = self.observer.midnight(times, "next")
|
|
79
|
+
m_before = self.observer.midnight(times, "previous")
|
|
80
|
+
try:
|
|
81
|
+
midnights = np.unique(np.concatenate([m_before.mjd, m_after.mjd]).filled(np.nan))
|
|
82
|
+
except AttributeError:
|
|
83
|
+
midnights = np.unique(np.concatenate([m_before.mjd, m_after.mjd]))
|
|
84
|
+
# calculating midnight can return nans? That seems bad.
|
|
85
|
+
midnights = midnights[np.isfinite(midnights)]
|
|
86
|
+
# chop off any repeats. Need to round because observe.midnight
|
|
87
|
+
# values are not repeatable
|
|
88
|
+
m10 = np.round(midnights * 10)
|
|
89
|
+
_temp, indx = np.unique(m10, return_index=True)
|
|
90
|
+
midnights = midnights[indx]
|
|
91
|
+
names = [
|
|
92
|
+
"mjd",
|
|
93
|
+
"midnight",
|
|
94
|
+
"moonPer",
|
|
95
|
+
"twi6_rise",
|
|
96
|
+
"twi6_set",
|
|
97
|
+
"twi12_rise",
|
|
98
|
+
"twi12_set",
|
|
99
|
+
"twi18_rise",
|
|
100
|
+
"twi18_set",
|
|
101
|
+
]
|
|
102
|
+
types = ["float"] * len(names)
|
|
103
|
+
pernight = np.zeros(len(midnights), dtype=list(zip(names, types)))
|
|
104
|
+
pernight["midnight"] = midnights
|
|
105
|
+
pernight["mjd"] = midnights
|
|
106
|
+
|
|
107
|
+
# now for each perfilter, find the closes midnight
|
|
108
|
+
indx = np.searchsorted(midnights, perfilter["mjd"])
|
|
109
|
+
d1 = np.abs(perfilter["mjd"] - midnights[indx - 1])
|
|
110
|
+
indx[np.where(indx >= midnights.size)] -= 1
|
|
111
|
+
d2 = np.abs(perfilter["mjd"] - midnights[indx])
|
|
112
|
+
|
|
113
|
+
perfilter["midnight"] = midnights[indx]
|
|
114
|
+
temp_indx = np.where(d1 < d2)
|
|
115
|
+
perfilter["midnight"][temp_indx] = midnights[indx - 1][temp_indx]
|
|
116
|
+
mtime = Time(pernight["midnight"], format="mjd")
|
|
117
|
+
|
|
118
|
+
pernight["twi12_rise"] = self.observer.twilight_morning_nautical(mtime, which="next").mjd
|
|
119
|
+
pernight["twi12_set"] = self.observer.twilight_evening_nautical(mtime, which="previous").mjd
|
|
120
|
+
|
|
121
|
+
pernight["twi18_rise"] = self.observer.twilight_morning_astronomical(mtime, which="next").mjd
|
|
122
|
+
pernight["twi18_set"] = self.observer.twilight_evening_astronomical(mtime, which="previous").mjd
|
|
123
|
+
|
|
124
|
+
aa = AltAz(location=self.location, obstime=mtime)
|
|
125
|
+
moon_coords = get_body("moon", mtime).transform_to(aa)
|
|
126
|
+
sun_coords = get_sun(mtime).transform_to(aa)
|
|
127
|
+
ang_dist = sun_coords.separation(moon_coords)
|
|
128
|
+
pernight["moonPer"] = ang_dist.deg / 180 * 100
|
|
129
|
+
|
|
130
|
+
return {"pernight": pernight, "perfilter": perfilter}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from rubin_scheduler.utils import SURVEY_START_MJD, Site, SysEngVals, calc_season
|
|
3
|
+
|
|
4
|
+
from .base_metric import BaseMetric
|
|
5
|
+
|
|
6
|
+
__all__ = ["TemplateTime"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TemplateTime(BaseMetric):
|
|
10
|
+
"""Find the time at which we expect to hit incremental template
|
|
11
|
+
availability.
|
|
12
|
+
|
|
13
|
+
Note that there are some complications to real template generation
|
|
14
|
+
that make this an approximation and not an exact answer -- one aspect is
|
|
15
|
+
that templates are generated in `patches` and not per pixel. However, it
|
|
16
|
+
may be possible to generate parts of these patches at about 5 arcsecond
|
|
17
|
+
scales, which implies running with a healpix slicer at nside=512 or 1024.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
n_images_in_template : `int`, opt
|
|
22
|
+
Number of qualified visits required for template generation.
|
|
23
|
+
Default 3.
|
|
24
|
+
seeing_threshold : `float`, opt
|
|
25
|
+
The threshold for counting "good seeing" images, in arcseconds.
|
|
26
|
+
This is at zenith, at 500 nm - it will be scaled to the slicer's
|
|
27
|
+
best possible value at the relevant declination and in the template's
|
|
28
|
+
bandpass.
|
|
29
|
+
seeing_percentile : `float`, opt
|
|
30
|
+
When evaluating the local seeing distribution, if there
|
|
31
|
+
`n_images_in_template` better than `seeing_percentile`, go ahead
|
|
32
|
+
and make the template. This allows template creation in locations
|
|
33
|
+
with poor seeing compared to
|
|
34
|
+
Maximum percentile seeing to allow in the qualified images (0 - 100).
|
|
35
|
+
The maximum of seeing_threshold (scaled) or the seeing at
|
|
36
|
+
seeing_percentil will be used as the cutoff for template creation.
|
|
37
|
+
m5_threshold : `float` or None, opt
|
|
38
|
+
The threshold for counting an image as "good m5". This is also
|
|
39
|
+
scaled to the expected best minimum airmass/seeing given the
|
|
40
|
+
slicepoints' declination.
|
|
41
|
+
m5_percentile : `float`, opt
|
|
42
|
+
Maximum percentile m5 to allow in the qualified images (0 - 100).
|
|
43
|
+
The minimum of m5_threshold (scaled) or m5 resulting from
|
|
44
|
+
m5_percentile will be used as the cutoff for template creation.
|
|
45
|
+
seeing_col : `str`, opt
|
|
46
|
+
Name of the seeing column to use.
|
|
47
|
+
m5_col : `str`, opt
|
|
48
|
+
Name of the five sigma depth columns.
|
|
49
|
+
night_col : `str`, opt
|
|
50
|
+
Name of the column describing the night of the visit.
|
|
51
|
+
mjd_col : `str`, opt
|
|
52
|
+
Name of column describing time of the visit
|
|
53
|
+
band_col : `str`, opt
|
|
54
|
+
Name of column describing band
|
|
55
|
+
mjd_start : `float`, opt
|
|
56
|
+
The starting time of the survey, to use to count "nights before
|
|
57
|
+
template creation", etc.
|
|
58
|
+
site_latiude_rad : `float`, opt
|
|
59
|
+
The latitude of the site, used to determine minimum best airmass.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
n_images_in_template=3,
|
|
65
|
+
seeing_threshold=0.8,
|
|
66
|
+
m5_threshold=None,
|
|
67
|
+
seeing_percentile=50,
|
|
68
|
+
m5_percentile=50,
|
|
69
|
+
seeing_col="seeingFwhmEff",
|
|
70
|
+
m5_col="fiveSigmaDepth",
|
|
71
|
+
night_col="night",
|
|
72
|
+
mjd_col="observationStartMJD",
|
|
73
|
+
band_col="band",
|
|
74
|
+
mjd_start=None,
|
|
75
|
+
filter_col=None,
|
|
76
|
+
site_latitude_rad=Site("LSST").latitude_rad,
|
|
77
|
+
**kwargs,
|
|
78
|
+
):
|
|
79
|
+
self.n_images_in_template = n_images_in_template
|
|
80
|
+
self.seeing_threshold = seeing_threshold
|
|
81
|
+
if m5_threshold is None:
|
|
82
|
+
# Update these - currently just m5 defaults for v1.9
|
|
83
|
+
m5_threshold = {"u": 23.7, "g": 24.9, "r": 24.5, "i": 24.1, "z": 23.5, "y": 22.5}
|
|
84
|
+
self.m5_threshold = m5_threshold
|
|
85
|
+
self.seeing_percentile = seeing_percentile
|
|
86
|
+
self.m5_percentile = m5_percentile
|
|
87
|
+
self.seeing_col = seeing_col
|
|
88
|
+
self.m5_col = m5_col
|
|
89
|
+
self.night_col = night_col
|
|
90
|
+
self.mjd_col = mjd_col
|
|
91
|
+
self.band_col = band_col
|
|
92
|
+
if filter_col is not None:
|
|
93
|
+
self.band_col = filter_col
|
|
94
|
+
if "metric_name" in kwargs:
|
|
95
|
+
self.metric_name = kwargs["metric_name"]
|
|
96
|
+
del kwargs["metric_name"]
|
|
97
|
+
else:
|
|
98
|
+
self.metric_name = "TemplateTime"
|
|
99
|
+
if mjd_start is None:
|
|
100
|
+
self.mjd_start = SURVEY_START_MJD
|
|
101
|
+
else:
|
|
102
|
+
self.mjd_start = mjd_start
|
|
103
|
+
|
|
104
|
+
self.site_latitude_rad = site_latitude_rad
|
|
105
|
+
|
|
106
|
+
sev = SysEngVals()
|
|
107
|
+
self.eff_wavelens = dict([(b, sev.eff_wavelengths[b]) for b in "ugrizy"])
|
|
108
|
+
self.extinction_coeffs = {
|
|
109
|
+
"u": -0.46,
|
|
110
|
+
"g": -0.21,
|
|
111
|
+
"r": -0.12,
|
|
112
|
+
"i": -0.07,
|
|
113
|
+
"z": -0.06,
|
|
114
|
+
"y": -0.10,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
super().__init__(
|
|
118
|
+
col=[self.seeing_col, self.m5_col, self.night_col, self.mjd_col, self.band_col],
|
|
119
|
+
metric_name=self.metric_name,
|
|
120
|
+
units="days",
|
|
121
|
+
**kwargs,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def run(self, data_slice, slice_point):
|
|
125
|
+
result = {}
|
|
126
|
+
|
|
127
|
+
# Bail if not enough visits at all
|
|
128
|
+
if len(data_slice) < self.n_images_in_template:
|
|
129
|
+
return self.badval
|
|
130
|
+
|
|
131
|
+
# Check that the visits are sorted in time
|
|
132
|
+
data_slice.sort(order=self.mjd_col)
|
|
133
|
+
|
|
134
|
+
min_z_possible = np.abs(slice_point["dec"] - self.site_latitude_rad)
|
|
135
|
+
min_airmass_possible = 1.0 / np.cos(min_z_possible)
|
|
136
|
+
best_seeing_possible = self.seeing_threshold * np.power(min_airmass_possible, 0.6)
|
|
137
|
+
current_band = np.unique(data_slice[self.band_col])[0]
|
|
138
|
+
best_seeing_possible = best_seeing_possible * np.power(500 / self.eff_wavelens[current_band], 0.3)
|
|
139
|
+
|
|
140
|
+
percentile_seeing = np.percentile(data_slice[self.seeing_col], self.seeing_percentile)
|
|
141
|
+
bench_seeing = np.max([best_seeing_possible, percentile_seeing])
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
m5_threshold = self.m5_threshold[current_band]
|
|
145
|
+
except TypeError:
|
|
146
|
+
m5_threshold = self.m5_threshold
|
|
147
|
+
|
|
148
|
+
best_m5 = (
|
|
149
|
+
m5_threshold
|
|
150
|
+
- self.extinction_coeffs[current_band] * (1 - min_airmass_possible)
|
|
151
|
+
+ 2.5 * np.log10(self.seeing_threshold / best_seeing_possible)
|
|
152
|
+
)
|
|
153
|
+
percentile_m5 = np.percentile(data_slice[self.m5_col], 100 - self.m5_percentile)
|
|
154
|
+
bench_m5 = np.min([best_m5, percentile_m5])
|
|
155
|
+
|
|
156
|
+
seeing_ok = np.where(data_slice[self.seeing_col] <= bench_seeing, True, False)
|
|
157
|
+
|
|
158
|
+
m5_ok = np.where(data_slice[self.m5_col] >= bench_m5, True, False)
|
|
159
|
+
|
|
160
|
+
ok_template_input = np.where(seeing_ok & m5_ok)[0]
|
|
161
|
+
if (
|
|
162
|
+
len(ok_template_input) < self.n_images_in_template
|
|
163
|
+
): # If seeing_ok and/or m5_ok are "false", returned as bad value
|
|
164
|
+
return self.badval
|
|
165
|
+
|
|
166
|
+
idx_template_created = ok_template_input[
|
|
167
|
+
self.n_images_in_template - 1
|
|
168
|
+
] # Last image needed for template
|
|
169
|
+
idx_template_inputs = ok_template_input[: self.n_images_in_template] # Images included in template
|
|
170
|
+
|
|
171
|
+
night_template_created = data_slice[self.night_col][idx_template_created]
|
|
172
|
+
|
|
173
|
+
frac_into_season_template_created = calc_season(
|
|
174
|
+
np.degrees(slice_point["ra"]),
|
|
175
|
+
data_slice[self.mjd_col][idx_template_created],
|
|
176
|
+
mjd_start=self.mjd_start,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
where_template = (
|
|
180
|
+
data_slice[self.night_col] > night_template_created
|
|
181
|
+
) # of later images where we have a template
|
|
182
|
+
n_images_with_template = np.sum(where_template)
|
|
183
|
+
|
|
184
|
+
template_m5 = 1.25 * np.log10(np.sum(10.0 ** (0.8 * data_slice[self.m5_col][idx_template_inputs])))
|
|
185
|
+
|
|
186
|
+
# derive variance-weighted PSF width
|
|
187
|
+
# 1. normalize the weights
|
|
188
|
+
template_f0 = np.sqrt(np.sum(25 * 10 ** (0.8 * data_slice[self.m5_col][idx_template_inputs])))
|
|
189
|
+
# 2. compute per-input noise
|
|
190
|
+
image_noise = template_f0 / 5 * 10 ** (-0.4 * data_slice[self.m5_col])
|
|
191
|
+
# 3. used variance-weighted sum of squares to derive template seeing
|
|
192
|
+
template_seeing = np.sqrt(
|
|
193
|
+
np.sum(
|
|
194
|
+
(data_slice[self.seeing_col][idx_template_inputs] / image_noise[idx_template_inputs]) ** 2.0
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
delta_m5 = -2.5 * np.log10(np.sqrt(1.0 + 10 ** (-0.8 * (template_m5 - data_slice[self.m5_col]))))
|
|
199
|
+
diff_m5s = data_slice[self.m5_col] + delta_m5
|
|
200
|
+
|
|
201
|
+
n_alerts_per_diffim = 1e4 * 10 ** (0.6 * (diff_m5s - 24.7))
|
|
202
|
+
|
|
203
|
+
result["bench_seeing"] = bench_seeing
|
|
204
|
+
result["bench_m5"] = bench_m5
|
|
205
|
+
result["night_template_created"] = night_template_created
|
|
206
|
+
result["frac_into_season_template_created"] = frac_into_season_template_created
|
|
207
|
+
result["n_images_until_template"] = idx_template_created + 1
|
|
208
|
+
result["n_images_with_template"] = n_images_with_template
|
|
209
|
+
result["template_m5"] = template_m5
|
|
210
|
+
result["template_seeing"] = template_seeing
|
|
211
|
+
result["total_alerts"] = np.sum(n_alerts_per_diffim[where_template])
|
|
212
|
+
result["template_input_m5s"] = data_slice[self.m5_col][idx_template_inputs]
|
|
213
|
+
result["template_input_seeing"] = data_slice[self.seeing_col][idx_template_inputs]
|
|
214
|
+
result["fraction_better_template_seeing"] = np.sum(
|
|
215
|
+
(data_slice[self.seeing_col][where_template] > template_seeing)
|
|
216
|
+
) / np.sum(where_template)
|
|
217
|
+
result["diffim_lc"] = {
|
|
218
|
+
"mjd": data_slice[self.mjd_col][where_template],
|
|
219
|
+
"night": data_slice[self.night_col][where_template],
|
|
220
|
+
"band": data_slice[self.band_col][where_template],
|
|
221
|
+
"diff_m5": diff_m5s[where_template],
|
|
222
|
+
"science_m5": data_slice[self.m5_col][where_template],
|
|
223
|
+
"template_m5": template_m5 * np.ones(np.sum(where_template)),
|
|
224
|
+
"science_seeing": data_slice[self.seeing_col][where_template],
|
|
225
|
+
"template_seeing": template_seeing * np.ones(np.sum(where_template)),
|
|
226
|
+
"n_alerts": n_alerts_per_diffim[where_template],
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return result
|
|
230
|
+
|
|
231
|
+
def reduce_night_template_created(self, metric_val): # returns night of template creation
|
|
232
|
+
return metric_val["night_template_created"]
|
|
233
|
+
|
|
234
|
+
def reduce_n_images_until_template(
|
|
235
|
+
self, metric_val
|
|
236
|
+
): # returns number of images needed to complete template
|
|
237
|
+
return metric_val["n_images_until_template"]
|
|
238
|
+
|
|
239
|
+
def reduce_n_images_with_template(self, metric_val): # returns number of images with a template
|
|
240
|
+
return metric_val["n_images_with_template"]
|
|
241
|
+
|
|
242
|
+
def reduce_template_m5(self, metric_val): # calculated coadded m5 of resulting template
|
|
243
|
+
return metric_val["template_m5"]
|
|
244
|
+
|
|
245
|
+
def reduce_template_seeing(self, metric_val): # calculated seeing of resulting template
|
|
246
|
+
return metric_val["template_seeing"]
|
|
247
|
+
|
|
248
|
+
def reduce_fraction_better_template_seeing(self, metric_val): # calculated seeing of resulting template
|
|
249
|
+
return metric_val["fraction_better_template_seeing"]
|
|
250
|
+
|
|
251
|
+
def reduce_total_alerts(self, metric_val):
|
|
252
|
+
return metric_val["total_alerts"]
|
|
253
|
+
|
|
254
|
+
def reduce_frac_into_season(self, metric_val):
|
|
255
|
+
return metric_val["frac_into_season_template_created"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
__all__ = ("KuiperMetric",)
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from .base_metric import BaseMetric
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class KuiperMetric(BaseMetric):
|
|
9
|
+
"""Find the Kuiper V statistic for a distribution, useful for angles.
|
|
10
|
+
|
|
11
|
+
Value of 0 means perfecty uniform, 1 means delta function
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def run(self, data_slice, slice_point=None):
|
|
15
|
+
""""""
|
|
16
|
+
# Assume input in degrees
|
|
17
|
+
values = np.sort(data_slice[self.colname] % 360)
|
|
18
|
+
|
|
19
|
+
dist_1 = (np.arange(values.size) + 1) / values.size
|
|
20
|
+
uniform = values / (360.0)
|
|
21
|
+
|
|
22
|
+
d_plus = np.max(uniform - dist_1)
|
|
23
|
+
d_minus = np.max(dist_1 - uniform)
|
|
24
|
+
result = d_plus + d_minus
|
|
25
|
+
|
|
26
|
+
return result
|