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,584 @@
|
|
|
1
|
+
"""Tools for use of project-generated opsim simulations and analysis."""
|
|
2
|
+
|
|
3
|
+
__all__ = (
|
|
4
|
+
"get_metric_subsets",
|
|
5
|
+
"create_metric_subset",
|
|
6
|
+
"write_metric_subsets",
|
|
7
|
+
"get_metric_summaries",
|
|
8
|
+
"get_runs",
|
|
9
|
+
"get_family_runs",
|
|
10
|
+
"download_runs",
|
|
11
|
+
"get_family_descriptions",
|
|
12
|
+
"describe_families",
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import copy
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import urllib
|
|
20
|
+
import warnings
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
import pandas as pd
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import IPython
|
|
27
|
+
except ModuleNotFoundError:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
from rubin_sim.data import get_data_dir
|
|
31
|
+
|
|
32
|
+
from .summary_plots import plot_run_metric
|
|
33
|
+
|
|
34
|
+
FAMILY_SOURCE = os.environ.get(
|
|
35
|
+
"RUBIN_SIM_FAMILY_SOURCE",
|
|
36
|
+
"https://raw.githubusercontent.com/lsst-pst/survey_strategy/main/fbs_2.0/runs_v2.2.json",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
SUMMARY_SOURCE = os.environ.get(
|
|
40
|
+
"RUBIN_SIM_SUMMARY_SOURCE",
|
|
41
|
+
"https://s3df.slac.stanford.edu/data/rubin/sim-data/sims_featureScheduler_runs3.4/maf/summary.h5",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if os.uname().nodename.endswith(".datalab.noao.edu"):
|
|
45
|
+
DEFAULT_OPSIM_DB_DIR = "/sims_maf"
|
|
46
|
+
else:
|
|
47
|
+
DEFAULT_OPSIM_DB_DIR = os.getcwd()
|
|
48
|
+
OPSIM_DB_DIR = os.environ.get("OPSIM_DB_DIR", DEFAULT_OPSIM_DB_DIR)
|
|
49
|
+
|
|
50
|
+
BY_RUN_COLS = ["run", "brief", "filepath", "url"]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_metric_subsets(metric_subset_source=None):
|
|
54
|
+
"""Get metadata on named subsets of related metrics.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
metric_subset_source : `str` or None
|
|
59
|
+
File name or URL for the json file from which to load the data.
|
|
60
|
+
If it is set to `None`, the data is loaded from `metric_subsets.json`
|
|
61
|
+
in the $rubin_sim_data.maf directory.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
metric_subsets : `pandas.DataFrame`
|
|
66
|
+
``metric_subset``
|
|
67
|
+
The 1st level of the index is the name of a subset of metrics
|
|
68
|
+
(`str`).
|
|
69
|
+
``metric``
|
|
70
|
+
The 2nd level of the index is the full name of the metric
|
|
71
|
+
(`str`).
|
|
72
|
+
``metric``
|
|
73
|
+
The full name of the metric (`str`).
|
|
74
|
+
``short_name``
|
|
75
|
+
An abbreviated name for the metric (`str`)..
|
|
76
|
+
``style``
|
|
77
|
+
The ``matplotlib`` linestyle suggested for plots of the
|
|
78
|
+
metric (`str`).
|
|
79
|
+
``invert``
|
|
80
|
+
When normalizing, invert the metric value first? (`bool`)
|
|
81
|
+
``mag``
|
|
82
|
+
Is the value an (astronomical) magnitude? (`bool`)
|
|
83
|
+
"""
|
|
84
|
+
if metric_subset_source is None:
|
|
85
|
+
metric_subset_source = os.path.join(get_data_dir(), "maf", "metric_subsets.json")
|
|
86
|
+
if isinstance(metric_subset_source, pd.DataFrame):
|
|
87
|
+
metric_subsets = metric_subset_source
|
|
88
|
+
else:
|
|
89
|
+
metric_subsets = (
|
|
90
|
+
pd.read_json(metric_subset_source)
|
|
91
|
+
.set_index("metric subset")
|
|
92
|
+
.set_index("metric", append=True, drop=False)
|
|
93
|
+
)
|
|
94
|
+
return metric_subsets
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def create_metric_subset(
|
|
98
|
+
metric_subset_name,
|
|
99
|
+
metrics,
|
|
100
|
+
short_name=None,
|
|
101
|
+
style="-",
|
|
102
|
+
invert=False,
|
|
103
|
+
mag=False,
|
|
104
|
+
):
|
|
105
|
+
"""Create a DataFrame that defines a metric subset.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
metric_subset_name : `str`
|
|
110
|
+
The name of the new metric subset.
|
|
111
|
+
metrics : `list` [`str`]
|
|
112
|
+
A list of metric names in the subset.
|
|
113
|
+
short_name : `list` [`str`], optional
|
|
114
|
+
A list of shorter metric names, by default None
|
|
115
|
+
style : `list` [`str`], optional
|
|
116
|
+
The matplotlib line style symbol for lines representing the metric,
|
|
117
|
+
by default "-"
|
|
118
|
+
invert : `list` [`bool`], optional
|
|
119
|
+
Are smaller values of the metric better, such as for errors?,
|
|
120
|
+
by default False
|
|
121
|
+
mag : `list` [`bool`], optional
|
|
122
|
+
Is the metric an astronomical magnitude?, by default False
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
metric_subset : `pandas.DataFrame`
|
|
127
|
+
A table of metrics and normalization and plotting flags defining the
|
|
128
|
+
content of a metric subset.
|
|
129
|
+
"""
|
|
130
|
+
if short_name is None:
|
|
131
|
+
short_name = metrics
|
|
132
|
+
|
|
133
|
+
metric_subset = (
|
|
134
|
+
pd.DataFrame(
|
|
135
|
+
{
|
|
136
|
+
"metric subset": metric_subset_name,
|
|
137
|
+
"metric": metrics,
|
|
138
|
+
"short_name": short_name,
|
|
139
|
+
"style": style,
|
|
140
|
+
"invert": invert,
|
|
141
|
+
"mag": mag,
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
.set_index("metric subset")
|
|
145
|
+
.set_index("metric", append=True, drop=False)
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
return metric_subset
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def write_metric_subsets(metric_subset_file, metric_subsets):
|
|
152
|
+
"""Write an updated metric_subset dataframe to disk.
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
metric_subset_file : `str`
|
|
157
|
+
Output file name.
|
|
158
|
+
metric_subsets : `pandas.DataFrame`
|
|
159
|
+
Metric_subset dataframe, as defined in get_metric_subsets
|
|
160
|
+
"""
|
|
161
|
+
tmp = metric_subsets.reset_index("metric subset")
|
|
162
|
+
tmp.to_json(metric_subset_file, orient="records", indent=2)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def get_metric_summaries(
|
|
166
|
+
run_families=tuple(),
|
|
167
|
+
metric_subsets=tuple(),
|
|
168
|
+
runs=tuple(),
|
|
169
|
+
metrics=tuple(),
|
|
170
|
+
summary_source=None,
|
|
171
|
+
runs_source=None,
|
|
172
|
+
metric_subset_source=None,
|
|
173
|
+
run_order="family",
|
|
174
|
+
metric_order="summary",
|
|
175
|
+
):
|
|
176
|
+
"""Get summary metric values for a set of runs and metrics.
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
run_families : iterable [`str`]
|
|
181
|
+
Families of runs to include in the summary.
|
|
182
|
+
metric_subsets : iterable [`str`]
|
|
183
|
+
subsets of metrics to include in the summary.
|
|
184
|
+
runs : iterable [`str`]
|
|
185
|
+
Runs to include in the summary (in addition to any that are part
|
|
186
|
+
of families included in ``run_families``).
|
|
187
|
+
metrics : iterable [`str`]
|
|
188
|
+
Metrics to include in the summary (in addition to any that are
|
|
189
|
+
part of subsets included in ``metric_subsets``).
|
|
190
|
+
summary_source : `str` or `pandas.DataFrame`
|
|
191
|
+
File name or URL for the file from which to load the data.
|
|
192
|
+
If the supplied value is a `pandas.DataFrame`, it the table
|
|
193
|
+
returned will be a subset of this supplied table.
|
|
194
|
+
run_source : `pandas.DataFrame` or `str`
|
|
195
|
+
Either a `pandas.DataFrame` of runs metadata (as returned by
|
|
196
|
+
`archive.get_runs`), or a file name or URL for the json file
|
|
197
|
+
from which to load the run metadata.
|
|
198
|
+
If it is set to `None`, the data is loaded from the URL specified
|
|
199
|
+
by the `archive.RUNS_SOURCE` constant.
|
|
200
|
+
metric_subset_source : `pandas.DataFrame` or `str`
|
|
201
|
+
Either a `pandas.DataFrame` of metric subset specifications
|
|
202
|
+
(as returned by `archive.get_metric_subsets`) or a
|
|
203
|
+
file name for the json file from which to load the data.
|
|
204
|
+
run_order : `str`
|
|
205
|
+
Sort runs according to family definition ("family") or summary file
|
|
206
|
+
("summary") order.
|
|
207
|
+
metric_order : `str`
|
|
208
|
+
Sort metrics according to subset definition ("subset") or summary file
|
|
209
|
+
("summary") order.
|
|
210
|
+
|
|
211
|
+
Returns
|
|
212
|
+
-------
|
|
213
|
+
summaries : `pandas.DataFrame`
|
|
214
|
+
Metric summary values are returned in a `pandas.DataFrame`, with
|
|
215
|
+
each column providing the metrics for one run, and each row the
|
|
216
|
+
values for one metric. The metric names constitute the index, and
|
|
217
|
+
the column names are the canonical run names.
|
|
218
|
+
|
|
219
|
+
Note
|
|
220
|
+
----
|
|
221
|
+
The entire summary statistic values for all of the runs and metrics can
|
|
222
|
+
be downloaded from the default sources first, by simply calling
|
|
223
|
+
|
|
224
|
+
.. code-block:: python
|
|
225
|
+
|
|
226
|
+
summary = get_metric_summaries()
|
|
227
|
+
|
|
228
|
+
Then, you can use `get_metric_summaries` to get a subset without
|
|
229
|
+
redownloading the whole set by passing `summary_source=summary`. If you are
|
|
230
|
+
selecting multiple subsets of the summary, this avoids needing
|
|
231
|
+
to download the summary data multiple times.
|
|
232
|
+
"""
|
|
233
|
+
summary_source = SUMMARY_SOURCE if summary_source is None else summary_source
|
|
234
|
+
|
|
235
|
+
runs = list(runs)
|
|
236
|
+
metrics = list(metrics)
|
|
237
|
+
|
|
238
|
+
if isinstance(run_families, str):
|
|
239
|
+
run_families = [run_families]
|
|
240
|
+
|
|
241
|
+
if isinstance(metric_subsets, str):
|
|
242
|
+
metric_subsets = [metric_subsets]
|
|
243
|
+
|
|
244
|
+
if isinstance(summary_source, pd.DataFrame):
|
|
245
|
+
all_summaries = summary_source
|
|
246
|
+
else:
|
|
247
|
+
try:
|
|
248
|
+
all_summaries = pd.read_csv(summary_source, index_col=0, low_memory=False)
|
|
249
|
+
except UnicodeDecodeError:
|
|
250
|
+
# then this was probably the h5 file instead
|
|
251
|
+
all_summaries = pd.read_hdf(summary_source)
|
|
252
|
+
all_summaries.index.name = "OpsimRun"
|
|
253
|
+
|
|
254
|
+
if len(run_families) > 0:
|
|
255
|
+
families = get_family_runs(runs_source)
|
|
256
|
+
for run_family in run_families:
|
|
257
|
+
runs.extend(pd.Series(families.loc[run_family, "run"]).tolist())
|
|
258
|
+
|
|
259
|
+
if len(metric_subsets) > 0:
|
|
260
|
+
metric_subset_df = get_metric_subsets(metric_subset_source)
|
|
261
|
+
for metric_subset in metric_subsets:
|
|
262
|
+
metrics.extend(list(metric_subset_df.loc[metric_subset, "metric"]))
|
|
263
|
+
|
|
264
|
+
if len(runs) == 0:
|
|
265
|
+
runs = slice(None)
|
|
266
|
+
else:
|
|
267
|
+
if run_order == "summary":
|
|
268
|
+
runs = [r for r in all_summaries.index if r in runs]
|
|
269
|
+
|
|
270
|
+
if len(metrics) == 0:
|
|
271
|
+
metrics = slice(None)
|
|
272
|
+
else:
|
|
273
|
+
requested_metrics = copy.copy(metrics)
|
|
274
|
+
for metric in requested_metrics:
|
|
275
|
+
if metric not in all_summaries.columns:
|
|
276
|
+
warnings.warn(f'Metric "{metric}" not in summary, skipping')
|
|
277
|
+
metrics.remove(metric)
|
|
278
|
+
|
|
279
|
+
if metric_order == "summary":
|
|
280
|
+
metrics = [m for m in all_summaries.columns if m in metrics]
|
|
281
|
+
|
|
282
|
+
summaries = all_summaries.loc[runs, metrics]
|
|
283
|
+
summaries.columns.name = "metric"
|
|
284
|
+
summaries.index.name = "run"
|
|
285
|
+
return summaries
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def get_family_runs(run_source=None):
|
|
289
|
+
"""Load a data frame that supplies run names for each run family
|
|
290
|
+
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
run_source : `None` or `str`
|
|
294
|
+
File name or URL for the json file from which to load the metadata.
|
|
295
|
+
If it is set to `None`, the data is loaded from the URL specified
|
|
296
|
+
by the `archive.RUNS_SOURCE` constant.
|
|
297
|
+
|
|
298
|
+
Returns
|
|
299
|
+
-------
|
|
300
|
+
families : `pandas.DataFrame`
|
|
301
|
+
``families``
|
|
302
|
+
The index is the run family. (`str`)
|
|
303
|
+
``run``
|
|
304
|
+
the project-standard name for the run (`str`)
|
|
305
|
+
``OpsimGroup``
|
|
306
|
+
The name for the group to which the runs belong (`str`)
|
|
307
|
+
``OpsimComment``
|
|
308
|
+
Short description of the run (`str`)
|
|
309
|
+
``OpsimVersion``
|
|
310
|
+
Opsim version name (`str`)
|
|
311
|
+
``OpsimDate``
|
|
312
|
+
Date for the version of opsim (TODO: ?)
|
|
313
|
+
``brief``
|
|
314
|
+
A list of descriptions for the run. Runs may have a
|
|
315
|
+
different description for each family it belongs to, so it
|
|
316
|
+
a list of the same length as the families column (`list`
|
|
317
|
+
[`str`])
|
|
318
|
+
``url``
|
|
319
|
+
The URL from which the opsim output database for this run can be
|
|
320
|
+
downloaded.
|
|
321
|
+
|
|
322
|
+
Notes
|
|
323
|
+
-----
|
|
324
|
+
Because runs can be members of multiple families, more than one row may
|
|
325
|
+
provide metadata on the same run.
|
|
326
|
+
|
|
327
|
+
The same content (in a different form) can be obtained using
|
|
328
|
+
``get_runs``. ``get_runs`` is more convenient when indexing by
|
|
329
|
+
run; ``get_family_runs`` when indexing by family.
|
|
330
|
+
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
run_source = FAMILY_SOURCE if run_source is None else run_source
|
|
334
|
+
if isinstance(run_source, pd.DataFrame):
|
|
335
|
+
runs = run_source
|
|
336
|
+
else:
|
|
337
|
+
families = pd.read_json(run_source, orient="index")
|
|
338
|
+
families.index.name = "family"
|
|
339
|
+
runs = families.explode(BY_RUN_COLS)
|
|
340
|
+
|
|
341
|
+
return runs
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def get_runs(run_source=None):
|
|
345
|
+
"""Load metadata on opsim runs into a `pandas.DataFrame`.
|
|
346
|
+
|
|
347
|
+
Parameters
|
|
348
|
+
----------
|
|
349
|
+
run_source : `None` or `str`
|
|
350
|
+
File name or URL for the json file from which to load the metadata.
|
|
351
|
+
If it is set to `None`, the data is loaded from the URL specified
|
|
352
|
+
by the `archive.RUNS_SOURCE` constant.
|
|
353
|
+
|
|
354
|
+
Returns
|
|
355
|
+
-------
|
|
356
|
+
runs : `pandas.DataFrame`
|
|
357
|
+
``run``
|
|
358
|
+
The index of the DataFrame is the project-standard name for the run
|
|
359
|
+
(`str`)
|
|
360
|
+
``family``
|
|
361
|
+
A list of run families to which this run belongs (`list` [`str`])
|
|
362
|
+
``version``
|
|
363
|
+
The simulation version
|
|
364
|
+
``brief``
|
|
365
|
+
A list of descriptions for the run. Runs may have a
|
|
366
|
+
different description for each family it belongs to, so it
|
|
367
|
+
a list of the same length as the families column (`list`
|
|
368
|
+
[`str`])
|
|
369
|
+
``filepath``
|
|
370
|
+
The file path, relative to a base opsim output directory.
|
|
371
|
+
``url``
|
|
372
|
+
The URL from which the opsim output database for this run can be
|
|
373
|
+
downloaded.
|
|
374
|
+
|
|
375
|
+
Notes
|
|
376
|
+
-----
|
|
377
|
+
The same content (in a different form) can be obtained using
|
|
378
|
+
``get_family_runs``. ``get_runs`` is more convenient when indexing by
|
|
379
|
+
run; ``get_family_runs`` when indexing by family.
|
|
380
|
+
|
|
381
|
+
"""
|
|
382
|
+
|
|
383
|
+
family_runs = get_family_runs(run_source)
|
|
384
|
+
|
|
385
|
+
runs = (
|
|
386
|
+
family_runs.reset_index()
|
|
387
|
+
.groupby(BY_RUN_COLS)
|
|
388
|
+
.agg({c: list for c in family_runs.reset_index().columns if c not in BY_RUN_COLS})
|
|
389
|
+
.reset_index()
|
|
390
|
+
.set_index("run")
|
|
391
|
+
.loc[:, ["family", "version", "brief", "filepath", "url"]]
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
return runs
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def download_runs(runs, dest_dir=None, runs_source=None, clobber=False):
|
|
398
|
+
"""Download opsim visit databases for specified runs to a local directory.
|
|
399
|
+
|
|
400
|
+
Parameters
|
|
401
|
+
----------
|
|
402
|
+
runs : `pandas.DataFrame` or iterable [`str`]
|
|
403
|
+
If a `pandas.DataFrame` is provided, the `OpsimRun` column will be used
|
|
404
|
+
to get run names, and data will be read from the url specified in the
|
|
405
|
+
`url` column.
|
|
406
|
+
If a collection of `str` is provided, these will be interpreted as
|
|
407
|
+
run names supplied by data originating in the run metadata provided
|
|
408
|
+
by the ``runs_source`` parameter.
|
|
409
|
+
dest_dir : `str`
|
|
410
|
+
The local directory into which to write downloaded visit databases.
|
|
411
|
+
runs_source : `str`
|
|
412
|
+
File name or URL for the json file from which to load the metadata.
|
|
413
|
+
If it is set to `None`, the data is loaded from the URL specified
|
|
414
|
+
by the `archive.RUNS_SOURCE` constant. This parameter is ignored
|
|
415
|
+
if the ``runs`` parameter is set to a `pandas.DataFrame`.
|
|
416
|
+
clobber : `bool`
|
|
417
|
+
If ``False``, runs that would clobber an existing file will be skipped.
|
|
418
|
+
If ``True``, existing files will be overwritten.
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
Returns
|
|
422
|
+
-------
|
|
423
|
+
runs : `pandas.DataFrame`
|
|
424
|
+
Metadata on runs downloaded (in the same structure as the return of
|
|
425
|
+
``archive.get_runs``).
|
|
426
|
+
"""
|
|
427
|
+
|
|
428
|
+
if isinstance(runs, str):
|
|
429
|
+
runs = [runs]
|
|
430
|
+
|
|
431
|
+
if not isinstance(runs, pd.DataFrame):
|
|
432
|
+
all_runs = get_runs(runs_source)
|
|
433
|
+
runs = all_runs.loc[runs, :]
|
|
434
|
+
|
|
435
|
+
if dest_dir is None:
|
|
436
|
+
dest_dir = OPSIM_DB_DIR
|
|
437
|
+
|
|
438
|
+
if not os.path.exists(dest_dir):
|
|
439
|
+
raise FileNotFoundError(dest_dir)
|
|
440
|
+
|
|
441
|
+
dest_fnames = pd.Series(name="fname", index=pd.Index([], name="OpsimRun"), dtype=object)
|
|
442
|
+
|
|
443
|
+
for run_name, run in runs.iterrows():
|
|
444
|
+
dest_fnames[run_name] = os.path.join(dest_dir, run.filepath)
|
|
445
|
+
|
|
446
|
+
# Create the directory if it does not exist
|
|
447
|
+
os.makedirs(os.path.dirname(dest_fnames[run_name]), exist_ok=True)
|
|
448
|
+
|
|
449
|
+
if clobber or not os.path.exists(dest_fnames[run_name]):
|
|
450
|
+
urllib.request.urlretrieve(run.url, dest_fnames[run_name])
|
|
451
|
+
else:
|
|
452
|
+
warnings.warn(f"{dest_fnames[run_name]} already exists; not downloading")
|
|
453
|
+
|
|
454
|
+
return dest_fnames
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def get_family_descriptions(family_source=None):
|
|
458
|
+
"""Get description of families or funs.
|
|
459
|
+
|
|
460
|
+
Parameters
|
|
461
|
+
----------
|
|
462
|
+
family_source : `str
|
|
463
|
+
File name or URL for the json file from which to load the
|
|
464
|
+
family descriptinos. If it is set to `None`, the data is
|
|
465
|
+
loaded from the URL specified by the
|
|
466
|
+
`archive.FAMILY_SOURCE` constant.
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
Returns
|
|
470
|
+
-------
|
|
471
|
+
families : `pandas.DataFrame`
|
|
472
|
+
Family descriptions, with comments.
|
|
473
|
+
|
|
474
|
+
"""
|
|
475
|
+
family_source = FAMILY_SOURCE if family_source is None else family_source
|
|
476
|
+
if isinstance(family_source, pd.DataFrame):
|
|
477
|
+
families = family_source
|
|
478
|
+
else:
|
|
479
|
+
families = pd.read_json(family_source, orient="index")
|
|
480
|
+
families.index.name = "family"
|
|
481
|
+
by_family_cols = [c for c in families.columns if c not in BY_RUN_COLS]
|
|
482
|
+
families = families.loc[:, by_family_cols + BY_RUN_COLS]
|
|
483
|
+
return families
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def describe_families(
|
|
487
|
+
families,
|
|
488
|
+
summary=None,
|
|
489
|
+
table_metric_subset=None,
|
|
490
|
+
plot_metric_subset=None,
|
|
491
|
+
baseline_run=None,
|
|
492
|
+
round_table=2,
|
|
493
|
+
):
|
|
494
|
+
"""Display (in a jupyter on IPython notebook) family descirptions
|
|
495
|
+
|
|
496
|
+
Parameters
|
|
497
|
+
----------
|
|
498
|
+
families : `pandas.DataFrame`
|
|
499
|
+
Data family descriptions as returned by get_family_descriptions.
|
|
500
|
+
summary : `pandas.DataFrame`
|
|
501
|
+
Summary metrics for each run, as returned by get_metric_summaries.
|
|
502
|
+
table_metric_subset : `pandas.DataFrame`
|
|
503
|
+
Metadata on metrics to be included in the table, with columns and
|
|
504
|
+
index as returned by get_metric_subsets. None if no metrics should be
|
|
505
|
+
included in the table.
|
|
506
|
+
plot_metric_subset : `pandas.DataFrame`
|
|
507
|
+
Metadata on metrics to be included in the plot, with columns and
|
|
508
|
+
index as returned by get_metric_subsets. None if no plot should be
|
|
509
|
+
made.
|
|
510
|
+
baseline_run : `str`
|
|
511
|
+
The name of the run to use to normalize metrics in the plot.
|
|
512
|
+
None if normalization should be skipped.
|
|
513
|
+
round_table : `int`, opt
|
|
514
|
+
Decimal places to which to round the table_metrics. Default 2.
|
|
515
|
+
|
|
516
|
+
Returns
|
|
517
|
+
-------
|
|
518
|
+
fig : `matplotlib.figure.Figure`
|
|
519
|
+
The plot figure.
|
|
520
|
+
ax : `matplotilb.axes.Axes`
|
|
521
|
+
The plot axes.
|
|
522
|
+
"""
|
|
523
|
+
|
|
524
|
+
family_runs = families.explode(["run", "brief", "filepath"]).loc[:, ["run", "brief", "filepath"]]
|
|
525
|
+
|
|
526
|
+
# If there is just one run in the family, we might
|
|
527
|
+
# get a pd.Series back rather than a pd.DataFrame.
|
|
528
|
+
# Make sure we have a DataFrame
|
|
529
|
+
if isinstance(family_runs, pd.Series):
|
|
530
|
+
family_runs = pd.DataFrame([family_runs])
|
|
531
|
+
|
|
532
|
+
for family_name, family in families.iterrows():
|
|
533
|
+
# Use awkward appending of each line to string rather
|
|
534
|
+
# than a tripple quote to keep flake8 from complaining
|
|
535
|
+
# about blanks at the end of lines, which are
|
|
536
|
+
# meaningful in markdown (and desired here).
|
|
537
|
+
description = "---\n"
|
|
538
|
+
description += f"{family.description} \n"
|
|
539
|
+
description += f"**version**: {family.version} \n"
|
|
540
|
+
description += "**runs**: \n"
|
|
541
|
+
|
|
542
|
+
these_runs = family_runs.loc[[family_name], :]
|
|
543
|
+
if summary is not None:
|
|
544
|
+
if table_metric_subset is not None:
|
|
545
|
+
table_metric_summary = summary.loc[these_runs["run"], table_metric_subset["metric"]]
|
|
546
|
+
table_metric_summary.rename(table_metric_subset["short_name"], axis=1, inplace=True)
|
|
547
|
+
if round_table is not None:
|
|
548
|
+
table_metric_summary = table_metric_summary.round(round_table)
|
|
549
|
+
else:
|
|
550
|
+
table_metric_summary = summary.loc[these_runs["run"]]
|
|
551
|
+
|
|
552
|
+
these_runs = these_runs.join(table_metric_summary, on="run", how="left")
|
|
553
|
+
|
|
554
|
+
num_columns = len(these_runs.columns)
|
|
555
|
+
if num_columns > 5 and "filepath" in these_runs.columns:
|
|
556
|
+
these_runs = these_runs.drop(columns=["filepath"])
|
|
557
|
+
|
|
558
|
+
with pd.option_context("display.max_colwidth", 0):
|
|
559
|
+
if "IPython" in sys.modules:
|
|
560
|
+
IPython.display.display_markdown(description, raw=True)
|
|
561
|
+
IPython.display.display(
|
|
562
|
+
IPython.display.HTML(these_runs.set_index("run").to_html().replace("\\n", "<br>"))
|
|
563
|
+
)
|
|
564
|
+
else:
|
|
565
|
+
print(description)
|
|
566
|
+
print(these_runs.set_index("run"))
|
|
567
|
+
|
|
568
|
+
if plot_metric_subset is not None:
|
|
569
|
+
these_runs = family_runs["run"].values
|
|
570
|
+
if baseline_run is not None and baseline_run not in these_runs:
|
|
571
|
+
these_runs = np.concatenate([[baseline_run], these_runs])
|
|
572
|
+
these_metrics = [m for m in plot_metric_subset["metric"] if m in summary.columns]
|
|
573
|
+
fig, ax = plot_run_metric( # pylint: disable=invalid-name
|
|
574
|
+
summary.loc[these_runs, these_metrics],
|
|
575
|
+
metric_subset=plot_metric_subset,
|
|
576
|
+
metric_label_map=plot_metric_subset["short_name"],
|
|
577
|
+
baseline_run=baseline_run,
|
|
578
|
+
vertical_quantity="value",
|
|
579
|
+
horizontal_quantity="run",
|
|
580
|
+
)
|
|
581
|
+
else:
|
|
582
|
+
fig, ax = None, None # pylint: disable=invalid-name
|
|
583
|
+
|
|
584
|
+
return fig, ax
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
__all__ = ("combine_result_dbs", "gather_summaries")
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import glob
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
import sqlite3
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def combine_result_dbs(run_dirs, dbfilename="resultsDb_sqlite.db"):
|
|
15
|
+
"""Helper function for gather_summaries
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
run_dirs : `list` [`str`]
|
|
20
|
+
A list of directories to search for MAF result databases.
|
|
21
|
+
dbfilename : `str`
|
|
22
|
+
The database filename to look for (default: resultsDb_sqlite.db).
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# query to grab all the summary stats
|
|
26
|
+
sql_q = "SELECT summarystats.summary_value, "
|
|
27
|
+
sql_q += "metrics.metric_name, metrics.metric_info_label, "
|
|
28
|
+
sql_q += "metrics.slicer_name, summarystats.summary_name, metrics.run_name "
|
|
29
|
+
sql_q += "FROM summarystats INNER JOIN metrics ON metrics.metric_id=summarystats.metric_id"
|
|
30
|
+
|
|
31
|
+
all_summaries = []
|
|
32
|
+
for rdir in run_dirs:
|
|
33
|
+
fname = os.path.join(rdir, dbfilename)
|
|
34
|
+
if not os.path.isfile(fname):
|
|
35
|
+
logger.warning(f"No resultsDb database in {rdir}")
|
|
36
|
+
|
|
37
|
+
con = sqlite3.connect(fname)
|
|
38
|
+
temp_df = pd.read_sql(sql_q, con)
|
|
39
|
+
con.close()
|
|
40
|
+
|
|
41
|
+
# Make column names
|
|
42
|
+
def make_summary_name(x):
|
|
43
|
+
summary_name = " ".join(
|
|
44
|
+
[
|
|
45
|
+
x.summary_name.strip(),
|
|
46
|
+
x.metric_name.strip(),
|
|
47
|
+
x.metric_info_label.strip(),
|
|
48
|
+
x.slicer_name.strip(),
|
|
49
|
+
]
|
|
50
|
+
)
|
|
51
|
+
summary_name = summary_name.replace(" ", " ")
|
|
52
|
+
return summary_name
|
|
53
|
+
|
|
54
|
+
temp_df["summary_names"] = temp_df.apply(make_summary_name, axis=1)
|
|
55
|
+
all_summaries.append(temp_df[["summary_names", "summary_value", "run_name"]])
|
|
56
|
+
|
|
57
|
+
# Make one big dataframe
|
|
58
|
+
all_summaries = pd.concat(all_summaries)
|
|
59
|
+
# Group by run names and drop duplicates
|
|
60
|
+
g = all_summaries.groupby(["run_name", "summary_names"]).agg({"summary_value": "last"})
|
|
61
|
+
# Convert to one row with all summary stats per run
|
|
62
|
+
result_df = g.reset_index("summary_names").pivot(columns="summary_names")
|
|
63
|
+
# That ended up as a MultiIndex which we didn't need, so fix and rename
|
|
64
|
+
result_df.columns = result_df.columns.droplevel(0).rename("metric")
|
|
65
|
+
return result_df
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def gather_summaries():
|
|
69
|
+
"""Find resultsDbs in a series of directories and gather up their summary
|
|
70
|
+
stats into a single CSV or hdf5 file. Outputs one row per unique run name.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
parser = argparse.ArgumentParser(
|
|
74
|
+
description="Find resultsDbs in a series of directories and "
|
|
75
|
+
"gather up their summary stats into a single CSV or hdf5 file. "
|
|
76
|
+
"Intended to run on a set of metrics run on multiple "
|
|
77
|
+
"simulations, so that each results_db has similar summary"
|
|
78
|
+
"statistics."
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
"--base_dir",
|
|
82
|
+
type=str,
|
|
83
|
+
default=".",
|
|
84
|
+
help="Root directory from where to search for MAF (sub)directories.",
|
|
85
|
+
)
|
|
86
|
+
parser.add_argument(
|
|
87
|
+
"--outfile",
|
|
88
|
+
type=str,
|
|
89
|
+
default="summary",
|
|
90
|
+
help="Output file name. Default (summary)",
|
|
91
|
+
)
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--to_csv",
|
|
94
|
+
dest="to_csv",
|
|
95
|
+
action="store_true",
|
|
96
|
+
help="Create a .csv file, instead of the default hdf file.",
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument("--to_hdf", dest="to_hdf", action="store_true")
|
|
99
|
+
parser.add_argument(
|
|
100
|
+
"--dirs",
|
|
101
|
+
type=str,
|
|
102
|
+
default=None,
|
|
103
|
+
help="comma separated list of directories to use, default None",
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
args = parser.parse_args()
|
|
107
|
+
if args.dirs is None:
|
|
108
|
+
run_dirs = glob.glob(args.base_dir + "/*/")
|
|
109
|
+
else:
|
|
110
|
+
run_dirs = args.dirs.split(",")
|
|
111
|
+
|
|
112
|
+
# Create output file name if needed
|
|
113
|
+
if args.to_csv:
|
|
114
|
+
outfile = args.outfile + ".csv"
|
|
115
|
+
else:
|
|
116
|
+
outfile = args.outfile + ".h5"
|
|
117
|
+
|
|
118
|
+
result_df = combine_result_dbs(run_dirs)
|
|
119
|
+
|
|
120
|
+
# Save summary statistics
|
|
121
|
+
if args.to_csv:
|
|
122
|
+
result_df.to_csv(outfile)
|
|
123
|
+
else:
|
|
124
|
+
# Create a CSV file
|
|
125
|
+
result_df.to_hdf(outfile, key="stats")
|