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.
Files changed (387) hide show
  1. batch/compile_prenight_metadata_cache.sh +34 -0
  2. batch/run_auxtel_prenight_sims.sh +163 -0
  3. batch/run_prenight_sims.sh +239 -0
  4. docs/.gitignore +3 -0
  5. docs/Makefile +32 -0
  6. docs/api.rst +25 -0
  7. docs/conf.py +8 -0
  8. docs/data-api.rst +12 -0
  9. docs/data-download.rst +70 -0
  10. docs/developer.rst +14 -0
  11. docs/documenteer.toml +11 -0
  12. docs/index.rst +22 -0
  13. docs/installation.rst +76 -0
  14. docs/introduction.rst +37 -0
  15. docs/maf-api-batches.rst +12 -0
  16. docs/maf-api-db.rst +12 -0
  17. docs/maf-api-maf-contrib.rst +12 -0
  18. docs/maf-api-maps.rst +12 -0
  19. docs/maf-api-metricbundles.rst +12 -0
  20. docs/maf-api-metrics.rst +12 -0
  21. docs/maf-api-plots.rst +12 -0
  22. docs/maf-api-run-comparison.rst +12 -0
  23. docs/maf-api-slicers.rst +12 -0
  24. docs/maf-api-stackers.rst +12 -0
  25. docs/maf-api-utils.rst +12 -0
  26. docs/maf-api.rst +22 -0
  27. docs/maf.rst +60 -0
  28. docs/metric_list.py +49 -0
  29. docs/moving-objects-api.rst +12 -0
  30. docs/moving-objects.rst +22 -0
  31. docs/phot-utils-api.rst +12 -0
  32. docs/phot-utils.rst +11 -0
  33. docs/prenight.rst +117 -0
  34. docs/protoarchive.rst +276 -0
  35. docs/satellite-constellations-api.rst +12 -0
  36. docs/satellite-constellations.rst +13 -0
  37. docs/selfcal-api.rst +12 -0
  38. docs/selfcal.rst +15 -0
  39. docs/sim-archive-api.rst +12 -0
  40. docs/skybrightness-api.rst +12 -0
  41. docs/skybrightness.rst +23 -0
  42. docs/user-guide.rst +28 -0
  43. docs/vseqarchive-architecture.rst +438 -0
  44. docs/vseqarchive-setup.rst +238 -0
  45. docs/vseqarchive.rst +225 -0
  46. rubin_sim/__init__.py +7 -0
  47. rubin_sim/data/__init__.py +1 -0
  48. rubin_sim/data/rs_download_data.py +155 -0
  49. rubin_sim/maf/__init__.py +34 -0
  50. rubin_sim/maf/batches/__init__.py +18 -0
  51. rubin_sim/maf/batches/altaz_batch.py +161 -0
  52. rubin_sim/maf/batches/col_map_dict.py +274 -0
  53. rubin_sim/maf/batches/common.py +388 -0
  54. rubin_sim/maf/batches/ddf_batch.py +728 -0
  55. rubin_sim/maf/batches/filterchange_batch.py +182 -0
  56. rubin_sim/maf/batches/glance_batch.py +591 -0
  57. rubin_sim/maf/batches/hourglass_batch.py +79 -0
  58. rubin_sim/maf/batches/info_batch.py +114 -0
  59. rubin_sim/maf/batches/metadata_batch.py +558 -0
  60. rubin_sim/maf/batches/moving_objects_batch.py +1587 -0
  61. rubin_sim/maf/batches/openshutter_batch.py +100 -0
  62. rubin_sim/maf/batches/radar_limited.py +1100 -0
  63. rubin_sim/maf/batches/science_radar_batch.py +1910 -0
  64. rubin_sim/maf/batches/skycoverage.py +155 -0
  65. rubin_sim/maf/batches/slew_batch.py +146 -0
  66. rubin_sim/maf/batches/srd_batch.py +637 -0
  67. rubin_sim/maf/batches/time_batch.py +757 -0
  68. rubin_sim/maf/batches/time_sci_batch.py +105 -0
  69. rubin_sim/maf/batches/visitdepth_batch.py +485 -0
  70. rubin_sim/maf/db/__init__.py +2 -0
  71. rubin_sim/maf/db/add_run.py +34 -0
  72. rubin_sim/maf/db/results_db.py +1074 -0
  73. rubin_sim/maf/db/tracking_db.py +332 -0
  74. rubin_sim/maf/ddf_dir.py +53 -0
  75. rubin_sim/maf/generate_ss.py +218 -0
  76. rubin_sim/maf/glance_dir.py +58 -0
  77. rubin_sim/maf/maf_contrib/__init__.py +25 -0
  78. rubin_sim/maf/maf_contrib/calculate_lsst_field_visibility_astropy.py +170 -0
  79. rubin_sim/maf/maf_contrib/depth_limited_num_gal_metric.py +109 -0
  80. rubin_sim/maf/maf_contrib/example_new_metrics.py +40 -0
  81. rubin_sim/maf/maf_contrib/filter_pair_t_gaps_metric.py +208 -0
  82. rubin_sim/maf/maf_contrib/grb_transient_metric.py +249 -0
  83. rubin_sim/maf/maf_contrib/gw170817_det_metric.py +72 -0
  84. rubin_sim/maf/maf_contrib/intervals_between_obs_metric.py +68 -0
  85. rubin_sim/maf/maf_contrib/kne_metrics.py +473 -0
  86. rubin_sim/maf/maf_contrib/lss_metrics.py +45 -0
  87. rubin_sim/maf/maf_contrib/lss_obs_strategy/__init__.py +3 -0
  88. rubin_sim/maf/maf_contrib/lss_obs_strategy/constants_for_pipeline.py +73 -0
  89. rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_metric_extended.py +205 -0
  90. rubin_sim/maf/maf_contrib/lss_obs_strategy/galaxy_counts_with_pixel_calibration.py +171 -0
  91. rubin_sim/maf/maf_contrib/lv_dwarfs/__init__.py +1 -0
  92. rubin_sim/maf/maf_contrib/lv_dwarfs/lv_dwarfs_metrics.py +388 -0
  93. rubin_sim/maf/maf_contrib/microlensing_metric.py +593 -0
  94. rubin_sim/maf/maf_contrib/num_obs_in_survey_time_overlap_metric.py +43 -0
  95. rubin_sim/maf/maf_contrib/periodic_metric.py +51 -0
  96. rubin_sim/maf/maf_contrib/periodic_star_metric.py +186 -0
  97. rubin_sim/maf/maf_contrib/periodic_star_modulation_metric.py +236 -0
  98. rubin_sim/maf/maf_contrib/presto_color_kne_pop_metric.py +441 -0
  99. rubin_sim/maf/maf_contrib/selfcal_uniformity_metric.py +171 -0
  100. rubin_sim/maf/maf_contrib/star_count_mass_metric.py +64 -0
  101. rubin_sim/maf/maf_contrib/star_count_metric.py +56 -0
  102. rubin_sim/maf/maf_contrib/star_counts/__init__.py +8 -0
  103. rubin_sim/maf/maf_contrib/star_counts/abs_mag.py +324 -0
  104. rubin_sim/maf/maf_contrib/star_counts/coords.py +99 -0
  105. rubin_sim/maf/maf_contrib/star_counts/readme.txt +1 -0
  106. rubin_sim/maf/maf_contrib/star_counts/spec_type.py +91 -0
  107. rubin_sim/maf/maf_contrib/star_counts/starcount.py +30 -0
  108. rubin_sim/maf/maf_contrib/star_counts/starcount_bymass.py +93 -0
  109. rubin_sim/maf/maf_contrib/star_counts/stellardensity.py +59 -0
  110. rubin_sim/maf/maf_contrib/static_probes_fom_summary_metric.py +386 -0
  111. rubin_sim/maf/maf_contrib/tdes_pop_metric.py +362 -0
  112. rubin_sim/maf/maf_contrib/transient_ascii_sed_metric.py +652 -0
  113. rubin_sim/maf/maf_contrib/triplet_metric.py +156 -0
  114. rubin_sim/maf/maf_contrib/var_depth_metric.py +157 -0
  115. rubin_sim/maf/maf_contrib/xrb_metrics.py +523 -0
  116. rubin_sim/maf/maf_contrib/young_stellar_objects_metric.py +200 -0
  117. rubin_sim/maf/maf_night_report.py +200 -0
  118. rubin_sim/maf/make_fbs_tracking_db.py +90 -0
  119. rubin_sim/maf/maps/__init__.py +8 -0
  120. rubin_sim/maf/maps/base_map.py +72 -0
  121. rubin_sim/maf/maps/create_gaia_density_map.py +158 -0
  122. rubin_sim/maf/maps/dust_map.py +66 -0
  123. rubin_sim/maf/maps/dust_map_3d.py +190 -0
  124. rubin_sim/maf/maps/ebv_3d_hp.py +170 -0
  125. rubin_sim/maf/maps/ebv_hp.py +64 -0
  126. rubin_sim/maf/maps/gal_coords_map.py +22 -0
  127. rubin_sim/maf/maps/galactic_plane_priority_maps.py +210 -0
  128. rubin_sim/maf/maps/stellar_density_map.py +73 -0
  129. rubin_sim/maf/maps/trilegal_map.py +82 -0
  130. rubin_sim/maf/metadata_dir.py +90 -0
  131. rubin_sim/maf/metric_bundles/__init__.py +3 -0
  132. rubin_sim/maf/metric_bundles/metric_bundle.py +816 -0
  133. rubin_sim/maf/metric_bundles/metric_bundle_group.py +834 -0
  134. rubin_sim/maf/metric_bundles/mo_metric_bundle.py +646 -0
  135. rubin_sim/maf/metrics/__init__.py +52 -0
  136. rubin_sim/maf/metrics/agn_time_lag_metric.py +118 -0
  137. rubin_sim/maf/metrics/agnstructure.py +141 -0
  138. rubin_sim/maf/metrics/area_summary_metrics.py +120 -0
  139. rubin_sim/maf/metrics/base_metric.py +215 -0
  140. rubin_sim/maf/metrics/brown_dwarf_metric.py +162 -0
  141. rubin_sim/maf/metrics/cadence_metrics.py +400 -0
  142. rubin_sim/maf/metrics/calibration_metrics.py +618 -0
  143. rubin_sim/maf/metrics/chip_vendor_metric.py +43 -0
  144. rubin_sim/maf/metrics/color_slope_metrics.py +189 -0
  145. rubin_sim/maf/metrics/cosmology_summary_metrics.py +1212 -0
  146. rubin_sim/maf/metrics/coverage_metric.py +48 -0
  147. rubin_sim/maf/metrics/crowding_metric.py +255 -0
  148. rubin_sim/maf/metrics/cumulative_metric.py +46 -0
  149. rubin_sim/maf/metrics/dcr_metric.py +93 -0
  150. rubin_sim/maf/metrics/exgal_m5.py +57 -0
  151. rubin_sim/maf/metrics/fft_metric.py +27 -0
  152. rubin_sim/maf/metrics/galactic_plane_metrics.py +375 -0
  153. rubin_sim/maf/metrics/galplane_time_sampling_metrics.py +236 -0
  154. rubin_sim/maf/metrics/hourglass_metric.py +130 -0
  155. rubin_sim/maf/metrics/incremental_template_metric.py +255 -0
  156. rubin_sim/maf/metrics/kuiper_metrics.py +26 -0
  157. rubin_sim/maf/metrics/mo_metrics.py +1496 -0
  158. rubin_sim/maf/metrics/mo_summary_metrics.py +464 -0
  159. rubin_sim/maf/metrics/night_pointing_metric.py +70 -0
  160. rubin_sim/maf/metrics/optimal_m5_metric.py +94 -0
  161. rubin_sim/maf/metrics/pair_metric.py +69 -0
  162. rubin_sim/maf/metrics/periodic_detect_metric.py +133 -0
  163. rubin_sim/maf/metrics/phase_gap_metric.py +172 -0
  164. rubin_sim/maf/metrics/qso_number_counts_metric.py +138 -0
  165. rubin_sim/maf/metrics/scaling_metrics.py +148 -0
  166. rubin_sim/maf/metrics/schedview_metrics.py +39 -0
  167. rubin_sim/maf/metrics/season_metrics.py +344 -0
  168. rubin_sim/maf/metrics/simple_metrics.py +546 -0
  169. rubin_sim/maf/metrics/sky_sat_metric.py +18 -0
  170. rubin_sim/maf/metrics/sn_cadence_metric.py +104 -0
  171. rubin_sim/maf/metrics/sn_n_sn_metric.py +1364 -0
  172. rubin_sim/maf/metrics/sn_sl_metric.py +216 -0
  173. rubin_sim/maf/metrics/sn_snr_metric.py +715 -0
  174. rubin_sim/maf/metrics/snr_weight.py +24 -0
  175. rubin_sim/maf/metrics/star_density.py +77 -0
  176. rubin_sim/maf/metrics/string_count_metric.py +95 -0
  177. rubin_sim/maf/metrics/summary_metrics.py +201 -0
  178. rubin_sim/maf/metrics/surfb_metric.py +175 -0
  179. rubin_sim/maf/metrics/technical_metrics.py +271 -0
  180. rubin_sim/maf/metrics/tgaps.py +412 -0
  181. rubin_sim/maf/metrics/tomography_models.py +2034 -0
  182. rubin_sim/maf/metrics/transient_metrics.py +268 -0
  183. rubin_sim/maf/metrics/uniformity_metrics.py +418 -0
  184. rubin_sim/maf/metrics/use_metrics.py +55 -0
  185. rubin_sim/maf/metrics/vector_metrics.py +190 -0
  186. rubin_sim/maf/metrics/visit_groups_metric.py +341 -0
  187. rubin_sim/maf/metrics/weak_lensing_systematics_metric.py +210 -0
  188. rubin_sim/maf/plots/__init__.py +14 -0
  189. rubin_sim/maf/plots/hg_plotters.py +1117 -0
  190. rubin_sim/maf/plots/hourglass_plotters.py +120 -0
  191. rubin_sim/maf/plots/mo_plotters.py +358 -0
  192. rubin_sim/maf/plots/nd_plotters.py +220 -0
  193. rubin_sim/maf/plots/neo_distance_plotter.py +140 -0
  194. rubin_sim/maf/plots/night_pointing_plotter.py +96 -0
  195. rubin_sim/maf/plots/oned_plotters.py +114 -0
  196. rubin_sim/maf/plots/perceptual_rainbow.py +30 -0
  197. rubin_sim/maf/plots/plot_handler.py +766 -0
  198. rubin_sim/maf/plots/skyproj_plotters.py +540 -0
  199. rubin_sim/maf/plots/spatial_plotters.py +1029 -0
  200. rubin_sim/maf/plots/special_plotters.py +256 -0
  201. rubin_sim/maf/plots/two_d_plotters.py +177 -0
  202. rubin_sim/maf/plots/xyplotter.py +37 -0
  203. rubin_sim/maf/run_comparison/__init__.py +5 -0
  204. rubin_sim/maf/run_comparison/archive.py +584 -0
  205. rubin_sim/maf/run_comparison/gather_summaries.py +125 -0
  206. rubin_sim/maf/run_comparison/microlensing_compare.py +514 -0
  207. rubin_sim/maf/run_comparison/radar_plot.py +202 -0
  208. rubin_sim/maf/run_comparison/summary_plots.py +710 -0
  209. rubin_sim/maf/run_moving_calc.py +239 -0
  210. rubin_sim/maf/run_moving_fractions.py +128 -0
  211. rubin_sim/maf/run_moving_join.py +103 -0
  212. rubin_sim/maf/run_selfcal_metric.py +92 -0
  213. rubin_sim/maf/scimaf_dir.py +87 -0
  214. rubin_sim/maf/show_maf.py +227 -0
  215. rubin_sim/maf/slicers/__init__.py +13 -0
  216. rubin_sim/maf/slicers/base_slicer.py +513 -0
  217. rubin_sim/maf/slicers/base_spatial_slicer.py +202 -0
  218. rubin_sim/maf/slicers/healpix_sdss_slicer.py +118 -0
  219. rubin_sim/maf/slicers/healpix_slicer.py +189 -0
  220. rubin_sim/maf/slicers/healpix_subset_slicer.py +293 -0
  221. rubin_sim/maf/slicers/hourglass_slicer.py +37 -0
  222. rubin_sim/maf/slicers/mo_slicer.py +171 -0
  223. rubin_sim/maf/slicers/movie_slicer.py +288 -0
  224. rubin_sim/maf/slicers/nd_slicer.py +147 -0
  225. rubin_sim/maf/slicers/one_d_slicer.py +210 -0
  226. rubin_sim/maf/slicers/time_interval_slicers.py +283 -0
  227. rubin_sim/maf/slicers/uni_slicer.py +57 -0
  228. rubin_sim/maf/slicers/user_points_slicer.py +141 -0
  229. rubin_sim/maf/stackers/__init__.py +13 -0
  230. rubin_sim/maf/stackers/base_stacker.py +221 -0
  231. rubin_sim/maf/stackers/coord_stackers.py +224 -0
  232. rubin_sim/maf/stackers/date_stackers.py +192 -0
  233. rubin_sim/maf/stackers/general_stackers.py +683 -0
  234. rubin_sim/maf/stackers/get_col_info.py +104 -0
  235. rubin_sim/maf/stackers/label_stackers.py +114 -0
  236. rubin_sim/maf/stackers/m5_optimal_stacker.py +126 -0
  237. rubin_sim/maf/stackers/mo_phase.py +265 -0
  238. rubin_sim/maf/stackers/mo_stackers.py +486 -0
  239. rubin_sim/maf/stackers/n_follow_stacker.py +187 -0
  240. rubin_sim/maf/stackers/neo_dist_stacker.py +126 -0
  241. rubin_sim/maf/stackers/sdss_stackers.py +30 -0
  242. rubin_sim/maf/stackers/sn_stacker.py +152 -0
  243. rubin_sim/maf/stackers/teff_stacker.py +154 -0
  244. rubin_sim/maf/utils/__init__.py +6 -0
  245. rubin_sim/maf/utils/astrometry_utils.py +93 -0
  246. rubin_sim/maf/utils/generate_fov_map.py +58 -0
  247. rubin_sim/maf/utils/get_date_version.py +28 -0
  248. rubin_sim/maf/utils/maf_utils.py +212 -0
  249. rubin_sim/maf/utils/opsim_utils.py +259 -0
  250. rubin_sim/maf/utils/output_utils.py +34 -0
  251. rubin_sim/maf/utils/sn_n_sn_utils.py +894 -0
  252. rubin_sim/maf/utils/sn_utils.py +369 -0
  253. rubin_sim/maf/utils/stellar_mags.py +197 -0
  254. rubin_sim/maf/web/__init__.py +2 -0
  255. rubin_sim/maf/web/favicon.ico +0 -0
  256. rubin_sim/maf/web/maf_run_results.py +645 -0
  257. rubin_sim/maf/web/maf_tracking.py +139 -0
  258. rubin_sim/maf/web/sorttable.js +496 -0
  259. rubin_sim/maf/web/templates/allmetricresults.html +72 -0
  260. rubin_sim/maf/web/templates/configs.html +28 -0
  261. rubin_sim/maf/web/templates/macros.html +243 -0
  262. rubin_sim/maf/web/templates/master.html +294 -0
  263. rubin_sim/maf/web/templates/metricselect.html +91 -0
  264. rubin_sim/maf/web/templates/multicolor.html +147 -0
  265. rubin_sim/maf/web/templates/results.html +82 -0
  266. rubin_sim/maf/web/templates/runselect.html +58 -0
  267. rubin_sim/maf/web/templates/stats.html +50 -0
  268. rubin_sim/moving_objects/__init__.py +8 -0
  269. rubin_sim/moving_objects/base_obs.py +468 -0
  270. rubin_sim/moving_objects/cheby_fits.py +689 -0
  271. rubin_sim/moving_objects/cheby_values.py +231 -0
  272. rubin_sim/moving_objects/chebyshev_utils.py +365 -0
  273. rubin_sim/moving_objects/direct_obs.py +376 -0
  274. rubin_sim/moving_objects/make_lsst_obs.py +282 -0
  275. rubin_sim/moving_objects/ooephemerides.py +643 -0
  276. rubin_sim/moving_objects/orbits.py +507 -0
  277. rubin_sim/moving_objects/pre_generate.py +37 -0
  278. rubin_sim/moving_objects/utils.py +61 -0
  279. rubin_sim/phot_utils/__init__.py +7 -0
  280. rubin_sim/phot_utils/bandpass.py +425 -0
  281. rubin_sim/phot_utils/photometric_parameters.py +449 -0
  282. rubin_sim/phot_utils/physical_parameters.py +50 -0
  283. rubin_sim/phot_utils/predicted_zeropoints.py +245 -0
  284. rubin_sim/phot_utils/sed.py +1773 -0
  285. rubin_sim/phot_utils/sed_utils.py +52 -0
  286. rubin_sim/phot_utils/signaltonoise.py +695 -0
  287. rubin_sim/phot_utils/spectral_resampling.py +161 -0
  288. rubin_sim/satellite_constellations/__init__.py +3 -0
  289. rubin_sim/satellite_constellations/basis_function.py +40 -0
  290. rubin_sim/satellite_constellations/model_observatory.py +157 -0
  291. rubin_sim/satellite_constellations/sat_utils.py +488 -0
  292. rubin_sim/selfcal/__init__.py +4 -0
  293. rubin_sim/selfcal/generate_catalog.py +188 -0
  294. rubin_sim/selfcal/offsets.py +119 -0
  295. rubin_sim/selfcal/solver.py +143 -0
  296. rubin_sim/selfcal/star_tools.py +42 -0
  297. rubin_sim/sim_archive/__init__.py +14 -0
  298. rubin_sim/sim_archive/conda_packages.py +65 -0
  299. rubin_sim/sim_archive/future_vsarch.py +480 -0
  300. rubin_sim/sim_archive/make_snapshot.py +255 -0
  301. rubin_sim/sim_archive/prenight.py +216 -0
  302. rubin_sim/sim_archive/prenightindex.py +229 -0
  303. rubin_sim/sim_archive/prototype.py +1029 -0
  304. rubin_sim/sim_archive/sim_archive.py +680 -0
  305. rubin_sim/sim_archive/tempdb.py +56 -0
  306. rubin_sim/sim_archive/util.py +146 -0
  307. rubin_sim/sim_archive/vseqarchive.py +965 -0
  308. rubin_sim/sim_archive/vseqmetadata.py +1721 -0
  309. rubin_sim/skybrightness/__init__.py +5 -0
  310. rubin_sim/skybrightness/allsky_db.py +93 -0
  311. rubin_sim/skybrightness/data/ESO_Spectra/eso_tools.py +505 -0
  312. rubin_sim/skybrightness/data/solarSpec/package.py +22 -0
  313. rubin_sim/skybrightness/generate_hdf5.py +243 -0
  314. rubin_sim/skybrightness/interp_components.py +798 -0
  315. rubin_sim/skybrightness/sky_model.py +771 -0
  316. rubin_sim/skybrightness/twilight_func.py +83 -0
  317. rubin_sim/skybrightness/utils.py +91 -0
  318. rubin_sim-2.6.1.dev2.dist-info/METADATA +95 -0
  319. rubin_sim-2.6.1.dev2.dist-info/RECORD +387 -0
  320. rubin_sim-2.6.1.dev2.dist-info/WHEEL +5 -0
  321. rubin_sim-2.6.1.dev2.dist-info/entry_points.txt +24 -0
  322. rubin_sim-2.6.1.dev2.dist-info/licenses/LICENSE +674 -0
  323. rubin_sim-2.6.1.dev2.dist-info/top_level.txt +5 -0
  324. sql/make_vseqmeta.sql +251 -0
  325. tests/data/test_data.py +26 -0
  326. tests/data/test_ddf_grid.py +17 -0
  327. tests/maf/test_3x2fom.py +68 -0
  328. tests/maf/test_archive.py +162 -0
  329. tests/maf/test_basemetrics.py +99 -0
  330. tests/maf/test_batchcommon.py +36 -0
  331. tests/maf/test_batches.py +159 -0
  332. tests/maf/test_cadencemetrics.py +388 -0
  333. tests/maf/test_calibrationmetrics.py +242 -0
  334. tests/maf/test_color_slopes.py +71 -0
  335. tests/maf/test_cosmology_summaries.py +20 -0
  336. tests/maf/test_gathersummaries.py +48 -0
  337. tests/maf/test_healpixslicer.py +439 -0
  338. tests/maf/test_healpixsubsetslicer.py +273 -0
  339. tests/maf/test_hgplotters.py +145 -0
  340. tests/maf/test_hourglassmetric.py +33 -0
  341. tests/maf/test_io.py +187 -0
  342. tests/maf/test_json.py +169 -0
  343. tests/maf/test_maps.py +199 -0
  344. tests/maf/test_metricbundle.py +69 -0
  345. tests/maf/test_mometrics.py +422 -0
  346. tests/maf/test_movieslicer.py +216 -0
  347. tests/maf/test_ndslicer.py +240 -0
  348. tests/maf/test_neodistanceplotter.py +41 -0
  349. tests/maf/test_onedslicer.py +245 -0
  350. tests/maf/test_opsimutils.py +80 -0
  351. tests/maf/test_plotters.py +134 -0
  352. tests/maf/test_resultsdb.py +145 -0
  353. tests/maf/test_schedviewmetrics.py +14 -0
  354. tests/maf/test_simplemetrics.py +200 -0
  355. tests/maf/test_snmetrics.py +335 -0
  356. tests/maf/test_snmetrics_nsn.py +123 -0
  357. tests/maf/test_stackers.py +423 -0
  358. tests/maf/test_stellarmags.py +50 -0
  359. tests/maf/test_stringcount.py +26 -0
  360. tests/maf/test_summary_plots.py +197 -0
  361. tests/maf/test_summarymetrics.py +82 -0
  362. tests/maf/test_technicalmetrics.py +267 -0
  363. tests/maf/test_templatemetrics.py +86 -0
  364. tests/maf/test_timeintervalslicers.py +97 -0
  365. tests/maf/test_trackingdb.py +88 -0
  366. tests/maf/test_unislicer.py +116 -0
  367. tests/maf/test_vectormetrics.py +225 -0
  368. tests/maf/test_visitgroupsmetric.py +181 -0
  369. tests/moving_objects/test_camera.py +39 -0
  370. tests/moving_objects/test_chebyfits.py +188 -0
  371. tests/moving_objects/test_chebyshevutils.py +76 -0
  372. tests/moving_objects/test_chebyvalues.py +245 -0
  373. tests/moving_objects/test_ephemerides.py +219 -0
  374. tests/moving_objects/test_orbits.py +170 -0
  375. tests/moving_objects/test_sed_data.py +61 -0
  376. tests/phot_utils/test_approximatebandpasses.py +91 -0
  377. tests/phot_utils/test_photometricparameters.py +268 -0
  378. tests/phot_utils/test_photometry.py +61 -0
  379. tests/phot_utils/test_predicted_zeropoints.py +53 -0
  380. tests/phot_utils/test_read_bandpasses.py +29 -0
  381. tests/phot_utils/test_sed.py +368 -0
  382. tests/phot_utils/test_snr.py +370 -0
  383. tests/satellite_constellations/test_satellites.py +36 -0
  384. tests/sim_archive/test_make_snapshot.py +24 -0
  385. tests/sim_archive/test_prototype_sim_archive.py +204 -0
  386. tests/sim_archive/test_vseqarchive.py +947 -0
  387. tests/skybrightness/test_skymodel.py +359 -0
@@ -0,0 +1,231 @@
1
+ __all__ = ("ChebyValues",)
2
+
3
+ import os
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+ from .chebyshev_utils import chebeval
9
+
10
+
11
+ class ChebyValues:
12
+ """Calculates positions, velocities, deltas, vmags and elongations,
13
+ given a series of coefficients generated by ChebyFits.
14
+ """
15
+
16
+ def __init__(self):
17
+ self.coeffs = {}
18
+ self.coeff_keys = [
19
+ "obj_id",
20
+ "t_start",
21
+ "t_end",
22
+ "ra",
23
+ "dec",
24
+ "geo_dist",
25
+ "vmag",
26
+ "elongation",
27
+ ]
28
+ self.ephemeris_keys = [
29
+ "ra",
30
+ "dradt",
31
+ "dec",
32
+ "ddecdt",
33
+ "geo_dist",
34
+ "vmag",
35
+ "elongation",
36
+ ]
37
+
38
+ def set_coefficients(self, cheby_fits):
39
+ """Set coefficients using a ChebyFits object.
40
+ (which contains a dictionary of obj_id, t_start, t_end, ra,
41
+ dec, delta, vmag, and elongation lists).
42
+
43
+ Parameters
44
+ ----------
45
+ cheby_fits : `rubin_sim.movingObjects.chebyFits`
46
+ ChebyFits object, with attribute 'coeffs' -
47
+ a dictionary of lists of coefficients.
48
+ """
49
+ self.coeffs = cheby_fits.coeffs
50
+ # Convert list of coefficients into numpy arrays.
51
+ for k in self.coeffs:
52
+ self.coeffs[k] = np.array(self.coeffs[k])
53
+ # Check that expected values were received.
54
+ missing_keys = set(self.coeff_keys) - set(self.coeffs)
55
+ if len(missing_keys) > 0:
56
+ raise ValueError("Expected to find key(s) %s in coefficients." % " ".join(list[missing_keys]))
57
+ self.coeffs["meanRA"] = self.coeffs["ra"].swapaxes(0, 1)[0]
58
+ self.coeffs["meanDec"] = self.coeffs["dec"].swapaxes(0, 1)[0]
59
+
60
+ def read_coefficients(self, cheby_fits_file):
61
+ """Read coefficients from output file written by ChebyFits.
62
+
63
+ Parameters
64
+ ----------
65
+ cheby_fits_file : `str`
66
+ The filename of the coefficients file.
67
+ """
68
+ if not os.path.isfile(cheby_fits_file):
69
+ raise IOError("Could not find cheby_fits_file at %s" % (cheby_fits_file))
70
+ # Read the coefficients file.
71
+ coeffs = pd.read_table(cheby_fits_file, sep=r"\s+")
72
+ # The header line provides information on the number of
73
+ # coefficients for each parameter.
74
+ datacols = coeffs.columns.values
75
+ cols = {}
76
+ coeff_cols = ["ra", "dec", "geo_dist", "vmag", "elongation"]
77
+ for k in coeff_cols:
78
+ cols[k] = [x for x in datacols if x.startswith(k)]
79
+ # Translate dataframe to dictionary of numpy arrays
80
+ # while consolidating RA/Dec/Delta/Vmag/Elongation coeffs.
81
+ self.coeffs["obj_id"] = coeffs.obj_id.values
82
+ self.coeffs["t_start"] = coeffs.t_start.values
83
+ self.coeffs["t_end"] = coeffs.t_end.values
84
+ for k in coeff_cols:
85
+ self.coeffs[k] = np.empty([len(cols[k]), len(coeffs)], float)
86
+ for i in range(len(cols[k])):
87
+ self.coeffs[k][i] = coeffs["%s_%d" % (k, i)].values
88
+ # Add the mean RA and Dec columns
89
+ # (before swapping the coefficients axes).
90
+ self.coeffs["meanRA"] = self.coeffs["ra"][0]
91
+ self.coeffs["meanDec"] = self.coeffs["dec"][0]
92
+ # Swap the coefficient axes so that they are [segment, coeff].
93
+ for k in coeff_cols:
94
+ self.coeffs[k] = self.coeffs[k].swapaxes(0, 1)
95
+
96
+ def _eval_segment(self, segment_idx, times, subset_segments=None, mask=True):
97
+ """Evaluate the ra/dec/delta/vmag/elongation values for a
98
+ given segment at a series of times.
99
+
100
+ Parameters
101
+ ----------
102
+ segment_idx : `int`
103
+ The index in (each of) self.coeffs for the segment.
104
+ e.g. the first segment, for each object.
105
+ times : `np.ndarray`
106
+ The times at which to evaluate the segment.
107
+ subset_segments : `np.ndarray`, optional
108
+ Optionally specify a subset of the total segment indexes.
109
+ This lets you pick out particular obj_ids.
110
+ mask : `bool`, optional
111
+ If True, returns NaNs for values outside the range of times
112
+ in the segment.
113
+ If False, extrapolates segment for times outside the
114
+ segment time range.
115
+
116
+ Returns
117
+ -------
118
+ ephemeris : `dict`
119
+ Dictionary of RA, Dec, delta, vmag, and elongation values for
120
+ the segment indicated, at the time indicated.
121
+ """
122
+ if subset_segments is None:
123
+ subset_segments = np.ones(len(self.coeffs["obj_id"]), dtype=bool)
124
+ t_start = self.coeffs["t_start"][subset_segments][segment_idx]
125
+ t_end = self.coeffs["t_end"][subset_segments][segment_idx]
126
+ t_scaled = times - t_start
127
+ t_interval = np.array([t_start, t_end]) - t_start
128
+ # Evaluate RA/Dec/Delta/Vmag/elongation.
129
+ ephemeris = {}
130
+ ephemeris["ra"], ephemeris["dradt"] = chebeval(
131
+ t_scaled,
132
+ self.coeffs["ra"][subset_segments][segment_idx],
133
+ interval=t_interval,
134
+ do_velocity=True,
135
+ mask=mask,
136
+ )
137
+ ephemeris["dec"], ephemeris["ddecdt"] = chebeval(
138
+ t_scaled,
139
+ self.coeffs["dec"][subset_segments][segment_idx],
140
+ interval=t_interval,
141
+ do_velocity=True,
142
+ mask=mask,
143
+ )
144
+ ephemeris["dradt"] = ephemeris["dradt"] * np.cos(np.radians(ephemeris["dec"]))
145
+ for k in ("geo_dist", "vmag", "elongation"):
146
+ ephemeris[k], _ = chebeval(
147
+ t_scaled,
148
+ self.coeffs[k][subset_segments][segment_idx],
149
+ interval=t_interval,
150
+ do_velocity=False,
151
+ mask=mask,
152
+ )
153
+ return ephemeris
154
+
155
+ def get_ephemerides(self, times, obj_ids=None, extrapolate=False):
156
+ """Find the ephemeris information for 'obj_ids' at 'time'.
157
+
158
+ Implicit in how this is currently written is that the segments
159
+ are all expected to cover the same start/end time range across
160
+ all objects.
161
+ They do not have to have the same segment length for all objects.
162
+
163
+ Parameters
164
+ ----------
165
+ times : `float` or `np.ndarray`
166
+ The time to calculate ephemeris positions.
167
+ obj_ids : `np.ndarray`, opt
168
+ The object ids for which to generate ephemerides.
169
+ If None, then just uses all objects.
170
+ extrapolate : `bool`, opt
171
+ If True, extrapolate beyond ends of segments if time
172
+ outside of segment range.
173
+ If False, return ValueError if time is beyond range of segments.
174
+
175
+ Returns
176
+ -------
177
+ ephemerides : `np.ndarray`
178
+ The ephemeris positions for all objects.
179
+ Note that these may not be sorted in the same order as obj_ids.
180
+ """
181
+ if isinstance(times, float) or isinstance(times, int):
182
+ times = np.array([times], float)
183
+ ntimes = len(times)
184
+ ephemerides = {}
185
+ # Find subset of segments which match obj_id, if specified.
186
+ if obj_ids is None:
187
+ obj_match = np.ones(len(self.coeffs["obj_id"]), dtype=bool)
188
+ ephemerides["obj_id"] = np.unique(self.coeffs["obj_id"])
189
+ else:
190
+ if isinstance(obj_ids, str) or isinstance(obj_ids, int):
191
+ obj_ids = np.array([obj_ids])
192
+ obj_match = np.isin(self.coeffs["obj_id"], obj_ids)
193
+ ephemerides["obj_id"] = obj_ids
194
+ # Now find ephemeris values.
195
+ ephemerides["time"] = np.zeros((len(ephemerides["obj_id"]), ntimes), float) + times
196
+ for k in self.ephemeris_keys:
197
+ ephemerides[k] = np.zeros((len(ephemerides["obj_id"]), ntimes), float)
198
+ for it, t in enumerate(times):
199
+ # Find subset of segments which contain the appropriate time.
200
+ # Look for simplest subset first.
201
+ segments = np.where(
202
+ (self.coeffs["t_start"][obj_match] <= t) & (self.coeffs["t_end"][obj_match] > t)
203
+ )[0]
204
+ if len(segments) == 0:
205
+ seg_start = self.coeffs["t_start"][obj_match].min()
206
+ seg_end = self.coeffs["t_end"][obj_match].max()
207
+ if seg_start > t or seg_end < t:
208
+ if not extrapolate:
209
+ for k in self.ephemeris_keys:
210
+ ephemerides[k][:, it] = np.nan
211
+ else:
212
+ # Find the segments to use to extrapolate the times.
213
+ if seg_start > t:
214
+ segments = np.where(self.coeffs["t_start"][obj_match] == seg_start)[0]
215
+ if seg_end < t:
216
+ segments = np.where(self.coeffs["t_end"][obj_match] == seg_end)[0]
217
+ elif seg_end == t:
218
+ # Not extrapolating, but outside the
219
+ # simple match case above.
220
+ segments = np.where(self.coeffs["t_end"][obj_match] == seg_end)[0]
221
+ for i, segmentIdx in enumerate(segments):
222
+ ephemeris = self._eval_segment(segmentIdx, t, obj_match, mask=False)
223
+ for k in self.ephemeris_keys:
224
+ ephemerides[k][i][it] = ephemeris[k]
225
+ ephemerides["obj_id"][i] = self.coeffs["obj_id"][obj_match][segmentIdx]
226
+ if obj_ids is not None:
227
+ if set(ephemerides["obj_id"]) != set(obj_ids):
228
+ raise ValueError(
229
+ "Did not find expected match between obj_ids provided and ephemeride obj_ids."
230
+ )
231
+ return ephemerides
@@ -0,0 +1,365 @@
1
+ """Utilities to estimate and evaluate Chebyshev coefficients of a function.
2
+
3
+ Implementation of Newhall, X. X. 1989, Celestial Mechanics, 45, p. 305-310
4
+ """
5
+
6
+ __all__ = ("chebeval", "chebfit", "make_cheb_matrix", "make_cheb_matrix_only_x")
7
+
8
+ import numpy as np
9
+
10
+ # Evaluation routine.
11
+
12
+
13
+ def chebeval(x, p, interval=(-1.0, 1.0), do_velocity=True, mask=False):
14
+ """Evaluate a Chebyshev series and first derivative at points x.
15
+
16
+ If p is of length n + 1, this function returns:
17
+ y_hat(x) = p_0 * T_0(x*) + p_1 * T_1(x*) + ... + p_n * T_n(x*)
18
+ where T_n(x*) are the orthogonal Chebyshev polynomials of the
19
+ first kind, defined on the interval [-1, 1] and p_n are the
20
+ coefficients. The scaled variable x* is defined on the [-1, 1]
21
+ interval such that (x*) = (2*x - a - b)/(b - a), and x is defined
22
+ on the [a, b] interval.
23
+
24
+ Parameters
25
+ ----------
26
+ x : `scalar` or `np.ndarray`
27
+ Points at which to evaluate the polynomial.
28
+ p : `np.ndarray`
29
+ Chebyshev polynomial coefficients, as returned by chebfit.
30
+ interval : 2-element list/tuple
31
+ Bounds the x-interval on which the Chebyshev coefficients were fit.
32
+ do_velocity : `bool`
33
+ If True, compute the first derivative at points x.
34
+ mask : `bool`
35
+ If True, return Nans when the x goes beyond 'interval'.
36
+ If False, extrapolate fit beyond 'interval' limits.
37
+
38
+ Returns
39
+ -------
40
+ y, v : `float` or `np.ndarray`, `float` or `np.ndarray` (or None)
41
+ Y (position) and velocity values (if computed)
42
+ """
43
+ if len(interval) != 2:
44
+ raise RuntimeError("interval must have length 2")
45
+
46
+ interval_begin = float(interval[0])
47
+ interval_end = float(interval[-1])
48
+ t = 2.0 * np.array(x, dtype=np.float64) - interval_begin - interval_end
49
+ t /= interval_end - interval_begin
50
+
51
+ y = 0.0
52
+ v = 0.0
53
+ y0 = np.ones_like(t)
54
+ y1 = t
55
+ v0 = np.zeros_like(t)
56
+ v1 = np.ones_like(t)
57
+ v2 = 4.0 * t
58
+ t = 2.0 * t
59
+ N = len(p)
60
+
61
+ if do_velocity:
62
+ for i in np.arange(0, N, 2):
63
+ if i == N - 1:
64
+ y1 = 0.0
65
+ v1 = 0.0
66
+ j = min(i + 1, N - 1)
67
+
68
+ y += p[i] * y0 + p[j] * y1
69
+ v += p[i] * v0 + p[j] * v1
70
+
71
+ y2 = t * y1 - y0
72
+ y3 = t * y2 - y1
73
+ v2 = t * v1 - v0 + 2 * y1
74
+ v3 = t * v2 - v1 + 2 * y2
75
+
76
+ y0 = y2
77
+ y1 = y3
78
+ v0 = v2
79
+ v1 = v3
80
+
81
+ if mask:
82
+ mask = np.where((x < interval_begin) | (x > interval_end), True, False)
83
+ y = np.where(mask, np.nan, y)
84
+ v = np.where(mask, np.nan, v)
85
+ return y, 2 * v / (interval_end - interval_begin)
86
+ else:
87
+ for i in np.arange(0, N, 2):
88
+ if i == N - 1:
89
+ y1 = 0.0
90
+ j = min((i + 1), (N - 1))
91
+ y += p[i] * y0 + p[j] * y1
92
+ y0 = t * y1 - y0
93
+ y1 = t * y0 - y1
94
+ if mask:
95
+ mask = np.where((x < interval_begin) | (x > interval_end), True, False)
96
+ y = np.where(mask, np.nan, y)
97
+ return y, None
98
+
99
+
100
+ # Fitting routines.
101
+
102
+
103
+ def make_cheb_matrix(n_points, n_poly, weight=0.16):
104
+ """Compute C1^(-1)C2 using Newhall89 approach.
105
+
106
+ Utility function for fitting chebyshev polynomials to
107
+ x(t) and dx/dt(t) forcing equality at the end points.
108
+ This function computes the matrix (C1^(-1)C2).
109
+ Multiplying this matrix by the x and dx/dt values to be fit
110
+ produces the chebyshev coefficient.
111
+ This function need only be called once for a given polynomial degree and
112
+ number of points.
113
+
114
+ The matrices returned are of shape(n_points+1)x(n_poly).
115
+ The coefficients fitting the n_points+1 points, X, are found by:
116
+ A = xMultiplier * x + dxMultiplier * dxdt
117
+ if derivative information is known, or
118
+ A = xMultiplier * x
119
+ if no derivative information is known.
120
+ The xMultiplier matrices are different,
121
+ depending on whether derivative information is known.
122
+ Use function make_cheb_matrix_only_x if derviative is not known.
123
+ See Newhall, X. X. 1989, Celestial Mechanics, 45, p. 305-310 for details.
124
+
125
+ Parameters
126
+ ----------
127
+ n_points : `int`
128
+ Number of point to be fits. Must be greater than 2.
129
+ n_poly : `int`
130
+ Number of polynomial terms. Polynomial degree + 1
131
+ weight : `float`, optional
132
+ Weight to allow control of relative effectos of position and velocity
133
+ values. Newhall80 found best results are obtained with
134
+ velocity weighted at 0.4 relative to position,
135
+ giving W the form (1.0, 0.16, 1.0, 0.16,...)
136
+
137
+ Returns
138
+ -------
139
+ c1c2: `np.ndarray`
140
+ xMultiplier, C1^(-1)C2 even rows of shape (n_points+1)x(n_poly) to
141
+ be multiplied by x values.
142
+ c1c2: `np.ndarray`
143
+ dxMultiplier, C1^(-1)C2 odd rows of shape (n_points+1)x(n_poly) to
144
+ be multiplied by dx/dy values
145
+ """
146
+ tmat = np.zeros([n_points, n_poly])
147
+ tdot = np.zeros([n_points, n_poly])
148
+
149
+ cj = np.zeros([n_poly])
150
+ xj = np.linspace(1, -1, n_points)
151
+
152
+ for i in np.arange(0, n_poly):
153
+ cj[:] = 0
154
+ cj[i] = 1
155
+ y, v = chebeval(xj, cj)
156
+ tmat[:, i] = y
157
+ tdot[:, i] = v
158
+
159
+ # make matrix T*W
160
+ tw = np.zeros([n_poly, n_points, 2])
161
+ tw[:, :, 0] = tmat.transpose()
162
+ tw[:, :, 1] = tdot.transpose() * weight
163
+
164
+ # make matrix T*WT
165
+ twt = np.dot(tw[:, :, 0], tmat) + np.dot(tw[:, :, 1], tdot)
166
+ tw = tw.reshape(n_poly, 2 * n_points)
167
+
168
+ # insert matrix T*W in matrix C2
169
+ c2 = np.zeros([n_poly + 4, 2 * n_points])
170
+ c2[0:n_poly] = tw
171
+ c2[n_poly, 0] = 1
172
+ c2[n_poly + 1, 1] = 1
173
+ c2[n_poly + 2, -2] = 1
174
+ c2[n_poly + 3, -1] = 1
175
+
176
+ # insert matrix T*WT in matrix C1
177
+ c1 = np.zeros([n_poly + 4, n_poly + 4])
178
+ c1[0:n_poly, 0:n_poly] = twt
179
+ c1[n_poly + 0, 0:n_poly] = tmat[0]
180
+ c1[n_poly + 1, 0:n_poly] = tdot[0]
181
+ c1[n_poly + 2, 0:n_poly] = tmat[-1]
182
+ c1[n_poly + 3, 0:n_poly] = tdot[-1]
183
+
184
+ c1[0:n_poly, n_poly:] = c1[n_poly:, 0:n_poly].transpose()
185
+
186
+ c1inv = np.linalg.inv(c1)
187
+ c1c2 = np.dot(c1inv, c2)
188
+ c1c2 = c1c2.reshape(n_poly + 4, n_points, 2)
189
+ c1c2 = c1c2[:, ::-1, :]
190
+ c1c2 = c1c2.reshape(n_poly + 4, 2 * n_points)
191
+
192
+ # separate even rows for x, and odd rows for dx/dt
193
+ return c1c2[0:n_poly, 0::2], c1c2[0:n_poly, 1::2]
194
+
195
+
196
+ def make_cheb_matrix_only_x(n_points, n_poly):
197
+ """Compute C1^(-1)C2 using Newhall89 approach without dx/dt
198
+
199
+ Compute xMultiplier using only the equality constraint of the x-values
200
+ at the endpoints.
201
+ To be used when first derivatives are not available.
202
+ If chebyshev approximations are strung together piecewise only the x-values
203
+ and not the first derivatives will be continuous at the boundaries.
204
+ Multiplying this matrix by the x-values to be fit produces the chebyshev
205
+ coefficients. This function need only be called once for a given
206
+ polynomial degree and
207
+ number of points.
208
+ See Newhall, X. X. 1989, Celestial Mechanics, 45, p. 305-310.
209
+
210
+ Parameters
211
+ ----------
212
+ n_points : `int`
213
+ Number of point to be fits. Must be greater than 2.
214
+ n_poly : `int`
215
+ Number of polynomial terms. Polynomial degree + 1
216
+
217
+ Returns
218
+ -------
219
+ c1c2: `np.ndarray`
220
+ xMultiplier, Even rows of C1^(-1)C2 w/ shape (n_points+1)x(n_poly)
221
+ to be multiplied by x values
222
+ """
223
+
224
+ tmat = np.zeros([n_points, n_poly])
225
+ cj = np.zeros([n_poly])
226
+ xj = np.linspace(1, -1, n_points)
227
+ for i in range(0, n_poly):
228
+ cj[:] = 0
229
+ cj[i] = 1
230
+ tmat[:, i], v = chebeval(xj, cj)
231
+
232
+ # Augment matrix T to get matrix C2
233
+ c2 = np.zeros([n_poly + 2, n_points])
234
+ c2[0:n_poly] = tmat.transpose()
235
+ c2[n_poly, 0] = 1
236
+ c2[n_poly + 1, n_points - 1] = 1
237
+
238
+ # Augment matrix T*WT to get the matrix C1
239
+ c1 = np.zeros([n_poly + 2, n_poly + 2])
240
+ c1[0:n_poly, 0:n_poly] = np.dot(tmat.transpose(), tmat)
241
+ c1[n_poly + 0, 0:n_poly] = tmat[0]
242
+ c1[n_poly + 1, 0:n_poly] = tmat[-1]
243
+ c1[0:n_poly, n_poly:] = c1[n_poly:, 0:n_poly].transpose()
244
+
245
+ c1inv = np.linalg.inv(c1)
246
+ # C1^(-1) C2
247
+ c1c2 = np.dot(c1inv, c2)
248
+
249
+ c1c2 = c1c2.reshape(n_poly + 2, n_points)
250
+ c1c2 = c1c2[:, ::-1]
251
+ return c1c2[0:n_poly]
252
+
253
+
254
+ def chebfit(t, x, dxdt=None, x_multiplier=None, dx_multiplier=None, n_poly=7):
255
+ """Fit Chebyshev polynomial constrained at endpoints using
256
+ Newhall89 approach.
257
+
258
+ Return Chebyshev coefficients and statistics from fit
259
+ to array of positions (x) and optional velocities (dx/dt).
260
+ If both the function and its derivative are specified, then the value and
261
+ derivative of the interpolating polynomial at the
262
+ endpoints will be exactly equal to the input endpoint values.
263
+ Many approximations may be piecewise strung together and the function value
264
+ and its first derivative will be continuous across boundaries.
265
+ If derivatives are not provided, only the function value will be
266
+ continuous across boundaries.
267
+
268
+ If x_multiplier and dx_multiplier are not provided or
269
+ are an inappropriate shape for t and x, they will be recomputed.
270
+ See Newhall, X. X. 1989, Celestial Mechanics, 45, p. 305-310
271
+ for details.
272
+
273
+ Parameters
274
+ ----------
275
+ t : `np.ndarray`
276
+ Array of regularly sampled independent variable (e.g. time)
277
+ x : `np.ndarray`
278
+ Array of regularly sampled dependent variable (e.g. declination)
279
+ dxdt : `np.ndarray', optional
280
+ Optionally, array of first derivatives of x with respect to t,
281
+ at the same grid points. (e.g. sky velocity ddecl/dt)
282
+ x_multiplier : `np.ndarray`, optional
283
+ Optional 2D Matrix with rows of C1^(-1)C2 corresponding to x.
284
+ Use make_cheb_matrix to compute
285
+ dx_multiplier : `np.ndarray`, optional
286
+ Optional 2D Matrix with rows of C1^(-1)C2 corresponding to dx/dt.
287
+ Use make_cheb_matrix to compute
288
+ n_poly : `int`, optional
289
+ Number of polynomial terms. Degree + 1. Must be >=2 and <=2*n_points,
290
+ when derivative information is specified, or <=n_points, when no
291
+ derivative information is specified. Default = 7.
292
+
293
+ Returns
294
+ -------
295
+ a_n : `np.ndarray`
296
+ Array of chebyshev coefficients with length=n_poly.
297
+ residuals : `np.ndarray`
298
+ Array of residuals of the tabulated function x minus the
299
+ approximated function.
300
+ rms : `float`
301
+ The rms of the residuals in the fit.
302
+ maxresid : `float`
303
+ The maximum of the residals to the fit.
304
+ """
305
+ n_points = len(t)
306
+ if len(x) != n_points:
307
+ raise ValueError("length of x (%s) != length of t (%s)" % (len(x), n_points))
308
+ if dxdt is None:
309
+ if n_poly > n_points:
310
+ raise RuntimeError(
311
+ "Without velocity constraints, n_poly (%d) must be less than %s" % (n_poly, n_points)
312
+ )
313
+ if n_poly < 2:
314
+ raise RuntimeError("Without velocity constraints, n_poly (%d) must be greater than 2" % n_poly)
315
+ else:
316
+ if n_poly > 2 * n_points:
317
+ raise RuntimeError(
318
+ "n_poly (%d) must be less than %s (%d)" % (n_poly, "2 * n_points", 2 * (n_points))
319
+ )
320
+ if n_poly < 4:
321
+ raise RuntimeError("n_poly (%d) must be greater than 4" % n_poly)
322
+
323
+ # Recompute C1invX2 if x_multiplier and dx_multiplier are None or
324
+ # they are not appropriate for sizes of input positions and velocities.
325
+
326
+ if x_multiplier is None:
327
+ redo_x = True
328
+ else:
329
+ redo_x = (x_multiplier.shape[1] != n_points) | (x_multiplier.shape[0] != n_poly)
330
+
331
+ if dx_multiplier is None:
332
+ redo_v = True
333
+ else:
334
+ redo_v = (dx_multiplier.shape[1] != n_points) | (dx_multiplier.shape[0] != n_poly)
335
+
336
+ if (dxdt is None) & redo_x:
337
+ x_multiplier = make_cheb_matrix_only_x(n_points, n_poly)
338
+
339
+ if (dxdt is not None) & (redo_v | redo_x):
340
+ x_multiplier, dx_multiplier = make_cheb_matrix(n_points, n_poly)
341
+
342
+ if x.size != n_points:
343
+ raise RuntimeError("Not enough elements in X")
344
+
345
+ t_interval = np.array([t[0], t[-1]]) - t[0]
346
+ t_scaled = t - t[0]
347
+
348
+ # Compute the X portion of the coefficients
349
+ a_n = np.dot(x_multiplier, x)
350
+
351
+ # Compute statistics
352
+ # for x and dxdt if it is available
353
+ if dxdt is not None:
354
+ a_n = a_n + np.dot(dx_multiplier, dxdt * (t_interval[1] - t_interval[0]) / 2.0)
355
+ x_approx, dx_approx = chebeval(t_scaled, a_n, interval=t_interval)
356
+ else:
357
+ # Statistics for x only
358
+ x_approx, _ = chebeval(t_scaled, a_n, interval=t_interval, do_velocity=False)
359
+
360
+ residuals = x - x_approx
361
+ se = np.sum(residuals**2)
362
+ rms = np.sqrt(se / (n_points - 1))
363
+ maxresid = np.max(np.abs(residuals))
364
+
365
+ return a_n, residuals, rms, maxresid