From 86d591a853e2af6de1caf5c4253d707d08ae00bc Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 21 Jan 2024 18:59:06 +0000 Subject: [PATCH] Update documentation --- CNAME | 1 + ...gdp.cast_float64_variables_to_float32.html | 587 +++++++ .../clouddrift.adapters.gdp.cut_str.html | 585 +++++++ .../clouddrift.adapters.gdp.decode_date.html | 587 +++++++ ...ouddrift.adapters.gdp.drogue_presence.html | 585 +++++++ .../clouddrift.adapters.gdp.fetch_netcdf.html | 578 +++++++ .../clouddrift.adapters.gdp.fill_values.html | 579 +++++++ ...uddrift.adapters.gdp.get_gdp_metadata.html | 576 +++++++ _autosummary/clouddrift.adapters.gdp.html | 824 ++++++++++ ...clouddrift.adapters.gdp.order_by_date.html | 585 +++++++ ...ift.adapters.gdp.parse_directory_file.html | 583 +++++++ .../clouddrift.adapters.gdp.rowsize.html | 568 +++++++ .../clouddrift.adapters.gdp.str_to_float.html | 586 +++++++ .../clouddrift.adapters.gdp1h.download.html | 590 +++++++ _autosummary/clouddrift.adapters.gdp1h.html | 702 ++++++++ .../clouddrift.adapters.gdp1h.preprocess.html | 586 +++++++ ...uddrift.adapters.gdp1h.to_raggedarray.html | 631 ++++++++ .../clouddrift.adapters.gdp6h.download.html | 590 +++++++ _autosummary/clouddrift.adapters.gdp6h.html | 693 ++++++++ .../clouddrift.adapters.gdp6h.preprocess.html | 586 +++++++ ...uddrift.adapters.gdp6h.to_raggedarray.html | 622 ++++++++ ...louddrift.adapters.glad.get_dataframe.html | 569 +++++++ _autosummary/clouddrift.adapters.glad.html | 606 +++++++ .../clouddrift.adapters.glad.to_xarray.html | 569 +++++++ ...ddrift.adapters.mosaic.get_dataframes.html | 570 +++++++ ...uddrift.adapters.mosaic.get_file_urls.html | 569 +++++++ ...apters.mosaic.get_repository_metadata.html | 570 +++++++ _autosummary/clouddrift.adapters.mosaic.html | 632 ++++++++ .../clouddrift.adapters.mosaic.to_xarray.html | 569 +++++++ ...t.adapters.subsurface_floats.download.html | 568 +++++++ ...clouddrift.adapters.subsurface_floats.html | 585 +++++++ ....adapters.subsurface_floats.to_xarray.html | 568 +++++++ _autosummary/clouddrift.datasets.andro.html | 633 ++++++++ _autosummary/clouddrift.datasets.gdp1h.html | 635 ++++++++ _autosummary/clouddrift.datasets.gdp6h.html | 639 ++++++++ _autosummary/clouddrift.datasets.glad.html | 621 ++++++++ _autosummary/clouddrift.datasets.html | 1160 ++++++++++++++ _autosummary/clouddrift.datasets.mosaic.html | 628 ++++++++ .../clouddrift.datasets.spotters.html | 620 +++++++ ...clouddrift.datasets.subsurface_floats.html | 645 ++++++++ _autosummary/clouddrift.datasets.yomaha.html | 633 ++++++++ _autosummary/clouddrift.kinematics.html | 1103 +++++++++++++ ...cs.inertial_oscillation_from_position.html | 642 ++++++++ .../clouddrift.kinematics.kinetic_energy.html | 604 +++++++ ...ift.kinematics.position_from_velocity.html | 709 +++++++++ ...s.residual_position_from_displacement.html | 604 +++++++ _autosummary/clouddrift.kinematics.spin.html | 659 ++++++++ ...ift.kinematics.velocity_from_position.html | 666 ++++++++ .../clouddrift.pairs.chance_pair.html | 651 ++++++++ ...ddrift.pairs.chance_pairs_from_ragged.html | 652 ++++++++ _autosummary/clouddrift.pairs.html | 944 +++++++++++ ...drift.pairs.pair_bounding_box_overlap.html | 608 +++++++ .../clouddrift.pairs.pair_space_distance.html | 608 +++++++ .../clouddrift.pairs.pair_time_distance.html | 598 +++++++ .../clouddrift.pairs.pair_time_overlap.html | 608 +++++++ _autosummary/clouddrift.plotting.html | 686 ++++++++ .../clouddrift.plotting.plot_ragged.html | 677 ++++++++ .../clouddrift.ragged.apply_ragged.html | 649 ++++++++ _autosummary/clouddrift.ragged.chunk.html | 654 ++++++++ _autosummary/clouddrift.ragged.html | 1183 ++++++++++++++ _autosummary/clouddrift.ragged.prune.html | 607 +++++++ .../clouddrift.ragged.ragged_to_regular.html | 615 +++++++ .../clouddrift.ragged.regular_to_ragged.html | 604 +++++++ .../clouddrift.ragged.rowsize_to_index.html | 593 +++++++ _autosummary/clouddrift.ragged.segment.html | 634 ++++++++ _autosummary/clouddrift.ragged.subset.html | 668 ++++++++ _autosummary/clouddrift.ragged.unpack.html | 614 +++++++ .../clouddrift.raggedarray.RaggedArray.html | 919 +++++++++++ _autosummary/clouddrift.raggedarray.html | 551 +++++++ .../clouddrift.signal.analytic_signal.html | 644 ++++++++ ...clouddrift.signal.cartesian_to_rotary.html | 626 ++++++++ .../clouddrift.signal.ellipse_parameters.html | 614 +++++++ _autosummary/clouddrift.signal.html | 899 +++++++++++ ...drift.signal.modulated_ellipse_signal.html | 618 +++++++ ...clouddrift.signal.rotary_to_cartesian.html | 620 +++++++ _autosummary/clouddrift.sphere.bearing.html | 607 +++++++ ...uddrift.sphere.cartesian_to_spherical.html | 621 ++++++++ ...rift.sphere.cartesian_to_tangentplane.html | 620 +++++++ .../clouddrift.sphere.coriolis_frequency.html | 589 +++++++ ...clouddrift.sphere.cumulative_distance.html | 597 +++++++ _autosummary/clouddrift.sphere.distance.html | 612 +++++++ _autosummary/clouddrift.sphere.html | 1317 +++++++++++++++ .../clouddrift.sphere.plane_to_sphere.html | 622 ++++++++ ...re.position_from_distance_and_bearing.html | 611 +++++++ .../clouddrift.sphere.recast_lon.html | 616 +++++++ .../clouddrift.sphere.recast_lon180.html | 599 +++++++ .../clouddrift.sphere.recast_lon360.html | 599 +++++++ .../clouddrift.sphere.sphere_to_plane.html | 623 ++++++++ ...uddrift.sphere.spherical_to_cartesian.html | 629 ++++++++ ...rift.sphere.tangentplane_to_cartesian.html | 617 +++++++ _autosummary/clouddrift.wavelet.html | 1088 +++++++++++++ .../clouddrift.wavelet.morse_amplitude.html | 605 +++++++ .../clouddrift.wavelet.morse_freq.html | 629 ++++++++ ...louddrift.wavelet.morse_logspace_freq.html | 631 ++++++++ .../clouddrift.wavelet.morse_properties.html | 600 +++++++ .../clouddrift.wavelet.morse_wavelet.html | 631 ++++++++ ...drift.wavelet.morse_wavelet_transform.html | 690 ++++++++ .../clouddrift.wavelet.wavelet_transform.html | 621 ++++++++ _images/ragged_array.png | Bin 0 -> 305240 bytes _modules/clouddrift/adapters/gdp.html | 820 ++++++++++ _modules/clouddrift/adapters/gdp1h.html | 1091 +++++++++++++ _modules/clouddrift/adapters/gdp6h.html | 978 ++++++++++++ _modules/clouddrift/adapters/glad.html | 591 +++++++ _modules/clouddrift/adapters/mosaic.html | 633 ++++++++ .../adapters/subsurface_floats.html | 674 ++++++++ _modules/clouddrift/datasets.html | 1102 +++++++++++++ _modules/clouddrift/kinematics.html | 1418 +++++++++++++++++ _modules/clouddrift/pairs.html | 1007 ++++++++++++ _modules/clouddrift/plotting.html | 693 ++++++++ _modules/clouddrift/ragged.html | 1341 ++++++++++++++++ _modules/clouddrift/raggedarray.html | 999 ++++++++++++ _modules/clouddrift/signal.html | 951 +++++++++++ _modules/clouddrift/sphere.html | 1320 +++++++++++++++ _modules/clouddrift/wavelet.html | 1322 +++++++++++++++ _modules/index.html | 486 ++++++ ....gdp.cast_float64_variables_to_float32.rst | 6 + .../clouddrift.adapters.gdp.cut_str.rst | 6 + .../clouddrift.adapters.gdp.decode_date.rst | 6 + ...louddrift.adapters.gdp.drogue_presence.rst | 6 + .../clouddrift.adapters.gdp.fetch_netcdf.rst | 6 + .../clouddrift.adapters.gdp.fill_values.rst | 6 + ...ouddrift.adapters.gdp.get_gdp_metadata.rst | 6 + .../clouddrift.adapters.gdp.order_by_date.rst | 6 + ...rift.adapters.gdp.parse_directory_file.rst | 6 + .../clouddrift.adapters.gdp.rowsize.rst | 6 + .../_autosummary/clouddrift.adapters.gdp.rst | 41 + .../clouddrift.adapters.gdp.str_to_float.rst | 6 + .../clouddrift.adapters.gdp1h.download.rst | 6 + .../clouddrift.adapters.gdp1h.preprocess.rst | 6 + .../clouddrift.adapters.gdp1h.rst | 33 + ...ouddrift.adapters.gdp1h.to_raggedarray.rst | 6 + .../clouddrift.adapters.gdp6h.download.rst | 6 + .../clouddrift.adapters.gdp6h.preprocess.rst | 6 + .../clouddrift.adapters.gdp6h.rst | 33 + ...ouddrift.adapters.gdp6h.to_raggedarray.rst | 6 + ...clouddrift.adapters.glad.get_dataframe.rst | 6 + .../_autosummary/clouddrift.adapters.glad.rst | 32 + .../clouddrift.adapters.glad.to_xarray.rst | 6 + ...uddrift.adapters.mosaic.get_dataframes.rst | 6 + ...ouddrift.adapters.mosaic.get_file_urls.rst | 6 + ...dapters.mosaic.get_repository_metadata.rst | 6 + .../clouddrift.adapters.mosaic.rst | 34 + .../clouddrift.adapters.mosaic.to_xarray.rst | 6 + ...ft.adapters.subsurface_floats.download.rst | 6 + .../clouddrift.adapters.subsurface_floats.rst | 32 + ...t.adapters.subsurface_floats.to_xarray.rst | 6 + .../clouddrift.datasets.andro.rst | 6 + .../clouddrift.datasets.gdp1h.rst | 6 + .../clouddrift.datasets.gdp6h.rst | 6 + .../_autosummary/clouddrift.datasets.glad.rst | 6 + .../clouddrift.datasets.mosaic.rst | 6 + _sources/_autosummary/clouddrift.datasets.rst | 38 + .../clouddrift.datasets.spotters.rst | 6 + .../clouddrift.datasets.subsurface_floats.rst | 6 + .../clouddrift.datasets.yomaha.rst | 6 + ...ics.inertial_oscillation_from_position.rst | 6 + .../clouddrift.kinematics.kinetic_energy.rst | 6 + ...rift.kinematics.position_from_velocity.rst | 6 + ...cs.residual_position_from_displacement.rst | 6 + .../_autosummary/clouddrift.kinematics.rst | 36 + .../clouddrift.kinematics.spin.rst | 6 + ...rift.kinematics.velocity_from_position.rst | 6 + .../clouddrift.pairs.chance_pair.rst | 6 + ...uddrift.pairs.chance_pairs_from_ragged.rst | 6 + ...ddrift.pairs.pair_bounding_box_overlap.rst | 6 + .../clouddrift.pairs.pair_space_distance.rst | 6 + .../clouddrift.pairs.pair_time_distance.rst | 6 + .../clouddrift.pairs.pair_time_overlap.rst | 6 + _sources/_autosummary/clouddrift.pairs.rst | 36 + .../clouddrift.plotting.plot_ragged.rst | 6 + _sources/_autosummary/clouddrift.plotting.rst | 31 + .../clouddrift.ragged.apply_ragged.rst | 6 + .../_autosummary/clouddrift.ragged.chunk.rst | 6 + .../_autosummary/clouddrift.ragged.prune.rst | 6 + .../clouddrift.ragged.ragged_to_regular.rst | 6 + .../clouddrift.ragged.regular_to_ragged.rst | 6 + .../clouddrift.ragged.rowsize_to_index.rst | 6 + _sources/_autosummary/clouddrift.ragged.rst | 39 + .../clouddrift.ragged.segment.rst | 6 + .../_autosummary/clouddrift.ragged.subset.rst | 6 + .../_autosummary/clouddrift.ragged.unpack.rst | 6 + .../clouddrift.raggedarray.RaggedArray.rst | 38 + .../_autosummary/clouddrift.raggedarray.rst | 32 + .../clouddrift.signal.analytic_signal.rst | 6 + .../clouddrift.signal.cartesian_to_rotary.rst | 6 + .../clouddrift.signal.ellipse_parameters.rst | 6 + ...ddrift.signal.modulated_ellipse_signal.rst | 6 + .../clouddrift.signal.rotary_to_cartesian.rst | 6 + _sources/_autosummary/clouddrift.signal.rst | 35 + .../clouddrift.sphere.bearing.rst | 6 + ...ouddrift.sphere.cartesian_to_spherical.rst | 6 + ...drift.sphere.cartesian_to_tangentplane.rst | 6 + .../clouddrift.sphere.coriolis_frequency.rst | 6 + .../clouddrift.sphere.cumulative_distance.rst | 6 + .../clouddrift.sphere.distance.rst | 6 + .../clouddrift.sphere.plane_to_sphere.rst | 6 + ...ere.position_from_distance_and_bearing.rst | 6 + .../clouddrift.sphere.recast_lon.rst | 6 + .../clouddrift.sphere.recast_lon180.rst | 6 + .../clouddrift.sphere.recast_lon360.rst | 6 + _sources/_autosummary/clouddrift.sphere.rst | 44 + .../clouddrift.sphere.sphere_to_plane.rst | 6 + ...ouddrift.sphere.spherical_to_cartesian.rst | 6 + ...drift.sphere.tangentplane_to_cartesian.rst | 6 + .../clouddrift.wavelet.morse_amplitude.rst | 6 + .../clouddrift.wavelet.morse_freq.rst | 6 + ...clouddrift.wavelet.morse_logspace_freq.rst | 6 + .../clouddrift.wavelet.morse_properties.rst | 6 + .../clouddrift.wavelet.morse_wavelet.rst | 6 + ...ddrift.wavelet.morse_wavelet_transform.rst | 6 + _sources/_autosummary/clouddrift.wavelet.rst | 37 + .../clouddrift.wavelet.wavelet_transform.rst | 6 + _sources/api.rst | 27 + _sources/contributing.rst | 37 + _sources/datasets.rst | 78 + _sources/index.rst | 62 + _sources/install.rst | 78 + _sources/usage.rst | 265 +++ _static/basic.css | 327 +++- _static/check-solid.svg | 4 + _static/clipboard.min.js | 7 + _static/copy-button.svg | 5 + _static/copybutton.css | 94 ++ _static/copybutton.js | 248 +++ _static/copybutton_funcs.js | 73 + _static/doctools.js | 377 ++--- _static/documentation_options.js | 12 +- _static/favicon.ico | Bin 0 -> 15406 bytes _static/graphviz.css | 19 + _static/images/logo_binder.svg | 19 + _static/images/logo_colab.png | Bin 0 -> 7601 bytes _static/images/logo_deepnote.svg | 1 + _static/images/logo_jupyterhub.svg | 1 + _static/language_data.js | 106 +- _static/locales/ar/LC_MESSAGES/booktheme.mo | Bin 0 -> 1541 bytes _static/locales/ar/LC_MESSAGES/booktheme.po | 75 + _static/locales/bg/LC_MESSAGES/booktheme.mo | Bin 0 -> 1708 bytes _static/locales/bg/LC_MESSAGES/booktheme.po | 75 + _static/locales/bn/LC_MESSAGES/booktheme.mo | Bin 0 -> 1646 bytes _static/locales/bn/LC_MESSAGES/booktheme.po | 63 + _static/locales/ca/LC_MESSAGES/booktheme.mo | Bin 0 -> 1246 bytes _static/locales/ca/LC_MESSAGES/booktheme.po | 66 + _static/locales/cs/LC_MESSAGES/booktheme.mo | Bin 0 -> 1405 bytes _static/locales/cs/LC_MESSAGES/booktheme.po | 75 + _static/locales/da/LC_MESSAGES/booktheme.mo | Bin 0 -> 1304 bytes _static/locales/da/LC_MESSAGES/booktheme.po | 75 + _static/locales/de/LC_MESSAGES/booktheme.mo | Bin 0 -> 1388 bytes _static/locales/de/LC_MESSAGES/booktheme.po | 75 + _static/locales/el/LC_MESSAGES/booktheme.mo | Bin 0 -> 1722 bytes _static/locales/el/LC_MESSAGES/booktheme.po | 75 + _static/locales/eo/LC_MESSAGES/booktheme.mo | Bin 0 -> 1337 bytes _static/locales/eo/LC_MESSAGES/booktheme.po | 75 + _static/locales/es/LC_MESSAGES/booktheme.mo | Bin 0 -> 1396 bytes _static/locales/es/LC_MESSAGES/booktheme.po | 75 + _static/locales/et/LC_MESSAGES/booktheme.mo | Bin 0 -> 1341 bytes _static/locales/et/LC_MESSAGES/booktheme.po | 75 + _static/locales/fi/LC_MESSAGES/booktheme.mo | Bin 0 -> 1368 bytes _static/locales/fi/LC_MESSAGES/booktheme.po | 75 + _static/locales/fr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1412 bytes _static/locales/fr/LC_MESSAGES/booktheme.po | 75 + _static/locales/hr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1402 bytes _static/locales/hr/LC_MESSAGES/booktheme.po | 75 + _static/locales/id/LC_MESSAGES/booktheme.mo | Bin 0 -> 1323 bytes _static/locales/id/LC_MESSAGES/booktheme.po | 75 + _static/locales/it/LC_MESSAGES/booktheme.mo | Bin 0 -> 1403 bytes _static/locales/it/LC_MESSAGES/booktheme.po | 75 + _static/locales/iw/LC_MESSAGES/booktheme.mo | Bin 0 -> 1445 bytes _static/locales/iw/LC_MESSAGES/booktheme.po | 75 + _static/locales/ja/LC_MESSAGES/booktheme.mo | Bin 0 -> 1471 bytes _static/locales/ja/LC_MESSAGES/booktheme.po | 75 + _static/locales/ko/LC_MESSAGES/booktheme.mo | Bin 0 -> 1375 bytes _static/locales/ko/LC_MESSAGES/booktheme.po | 75 + _static/locales/lt/LC_MESSAGES/booktheme.mo | Bin 0 -> 1413 bytes _static/locales/lt/LC_MESSAGES/booktheme.po | 75 + _static/locales/lv/LC_MESSAGES/booktheme.mo | Bin 0 -> 1404 bytes _static/locales/lv/LC_MESSAGES/booktheme.po | 75 + _static/locales/ml/LC_MESSAGES/booktheme.mo | Bin 0 -> 1883 bytes _static/locales/ml/LC_MESSAGES/booktheme.po | 66 + _static/locales/mr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1674 bytes _static/locales/mr/LC_MESSAGES/booktheme.po | 66 + _static/locales/ms/LC_MESSAGES/booktheme.mo | Bin 0 -> 1213 bytes _static/locales/ms/LC_MESSAGES/booktheme.po | 66 + _static/locales/nl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1356 bytes _static/locales/nl/LC_MESSAGES/booktheme.po | 75 + _static/locales/no/LC_MESSAGES/booktheme.mo | Bin 0 -> 1317 bytes _static/locales/no/LC_MESSAGES/booktheme.po | 75 + _static/locales/pl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1371 bytes _static/locales/pl/LC_MESSAGES/booktheme.po | 75 + _static/locales/pt/LC_MESSAGES/booktheme.mo | Bin 0 -> 1364 bytes _static/locales/pt/LC_MESSAGES/booktheme.po | 75 + _static/locales/ro/LC_MESSAGES/booktheme.mo | Bin 0 -> 1390 bytes _static/locales/ro/LC_MESSAGES/booktheme.po | 75 + _static/locales/ru/LC_MESSAGES/booktheme.mo | Bin 0 -> 1722 bytes _static/locales/ru/LC_MESSAGES/booktheme.po | 75 + _static/locales/sk/LC_MESSAGES/booktheme.mo | Bin 0 -> 1393 bytes _static/locales/sk/LC_MESSAGES/booktheme.po | 75 + _static/locales/sl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1374 bytes _static/locales/sl/LC_MESSAGES/booktheme.po | 75 + _static/locales/sr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1679 bytes _static/locales/sr/LC_MESSAGES/booktheme.po | 75 + _static/locales/sv/LC_MESSAGES/booktheme.mo | Bin 0 -> 1365 bytes _static/locales/sv/LC_MESSAGES/booktheme.po | 75 + _static/locales/ta/LC_MESSAGES/booktheme.mo | Bin 0 -> 1928 bytes _static/locales/ta/LC_MESSAGES/booktheme.po | 66 + _static/locales/te/LC_MESSAGES/booktheme.mo | Bin 0 -> 1806 bytes _static/locales/te/LC_MESSAGES/booktheme.po | 66 + _static/locales/tg/LC_MESSAGES/booktheme.mo | Bin 0 -> 1628 bytes _static/locales/tg/LC_MESSAGES/booktheme.po | 75 + _static/locales/th/LC_MESSAGES/booktheme.mo | Bin 0 -> 1766 bytes _static/locales/th/LC_MESSAGES/booktheme.po | 75 + _static/locales/tl/LC_MESSAGES/booktheme.mo | Bin 0 -> 1273 bytes _static/locales/tl/LC_MESSAGES/booktheme.po | 66 + _static/locales/tr/LC_MESSAGES/booktheme.mo | Bin 0 -> 1373 bytes _static/locales/tr/LC_MESSAGES/booktheme.po | 75 + _static/locales/uk/LC_MESSAGES/booktheme.mo | Bin 0 -> 1681 bytes _static/locales/uk/LC_MESSAGES/booktheme.po | 75 + _static/locales/ur/LC_MESSAGES/booktheme.mo | Bin 0 -> 1462 bytes _static/locales/ur/LC_MESSAGES/booktheme.po | 66 + _static/locales/vi/LC_MESSAGES/booktheme.mo | Bin 0 -> 1431 bytes _static/locales/vi/LC_MESSAGES/booktheme.po | 75 + .../locales/zh_CN/LC_MESSAGES/booktheme.mo | Bin 0 -> 1310 bytes .../locales/zh_CN/LC_MESSAGES/booktheme.po | 75 + .../locales/zh_TW/LC_MESSAGES/booktheme.mo | Bin 0 -> 1341 bytes .../locales/zh_TW/LC_MESSAGES/booktheme.po | 75 + _static/logo.png | Bin 0 -> 605248 bytes _static/pygments.css | 229 ++- _static/sbt-webpack-macros.html | 11 + _static/scripts/bootstrap.js | 3 + _static/scripts/bootstrap.js.LICENSE.txt | 5 + _static/scripts/bootstrap.js.map | 1 + _static/scripts/pydata-sphinx-theme.js | 2 + _static/scripts/pydata-sphinx-theme.js.map | 1 + _static/scripts/sphinx-book-theme.js | 2 + _static/scripts/sphinx-book-theme.js.map | 1 + _static/searchtools.js | 818 +++++----- _static/sphinx_highlight.js | 154 ++ _static/styles/bootstrap.css | 6 + _static/styles/bootstrap.css.map | 1 + _static/styles/pydata-sphinx-theme.css | 2 + _static/styles/pydata-sphinx-theme.css.map | 1 + _static/styles/sphinx-book-theme.css | 8 + _static/styles/theme.css | 2 + _static/vendor/fontawesome/6.5.1/LICENSE.txt | 165 ++ .../vendor/fontawesome/6.5.1/css/all.min.css | 5 + .../vendor/fontawesome/6.5.1/js/all.min.js | 2 + .../6.5.1/js/all.min.js.LICENSE.txt | 5 + .../6.5.1/webfonts/fa-brands-400.ttf | Bin 0 -> 207972 bytes .../6.5.1/webfonts/fa-brands-400.woff2 | Bin 0 -> 117372 bytes .../6.5.1/webfonts/fa-regular-400.ttf | Bin 0 -> 68004 bytes .../6.5.1/webfonts/fa-regular-400.woff2 | Bin 0 -> 25452 bytes .../6.5.1/webfonts/fa-solid-900.ttf | Bin 0 -> 419720 bytes .../6.5.1/webfonts/fa-solid-900.woff2 | Bin 0 -> 156496 bytes .../6.5.1/webfonts/fa-v4compatibility.ttf | Bin 0 -> 10832 bytes .../6.5.1/webfonts/fa-v4compatibility.woff2 | Bin 0 -> 4792 bytes _static/webpack-macros.html | 31 + api.html | 590 +++++++ contributing.html | 591 +++++++ datasets.html | 611 +++++++ genindex.html | 996 +++++++++++- index.html | 615 ++++++- install.html | 632 ++++++++ objects.inv | Bin 273 -> 2758 bytes py-modindex.html | 566 +++++++ search.html | 513 +++++- searchindex.js | 2 +- usage.html | 821 ++++++++++ 366 files changed, 91417 insertions(+), 1107 deletions(-) create mode 100644 CNAME create mode 100644 _autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.html create mode 100644 _autosummary/clouddrift.adapters.gdp.cut_str.html create mode 100644 _autosummary/clouddrift.adapters.gdp.decode_date.html create mode 100644 _autosummary/clouddrift.adapters.gdp.drogue_presence.html create mode 100644 _autosummary/clouddrift.adapters.gdp.fetch_netcdf.html create mode 100644 _autosummary/clouddrift.adapters.gdp.fill_values.html create mode 100644 _autosummary/clouddrift.adapters.gdp.get_gdp_metadata.html create mode 100644 _autosummary/clouddrift.adapters.gdp.html create mode 100644 _autosummary/clouddrift.adapters.gdp.order_by_date.html create mode 100644 _autosummary/clouddrift.adapters.gdp.parse_directory_file.html create mode 100644 _autosummary/clouddrift.adapters.gdp.rowsize.html create mode 100644 _autosummary/clouddrift.adapters.gdp.str_to_float.html create mode 100644 _autosummary/clouddrift.adapters.gdp1h.download.html create mode 100644 _autosummary/clouddrift.adapters.gdp1h.html create mode 100644 _autosummary/clouddrift.adapters.gdp1h.preprocess.html create mode 100644 _autosummary/clouddrift.adapters.gdp1h.to_raggedarray.html create mode 100644 _autosummary/clouddrift.adapters.gdp6h.download.html create mode 100644 _autosummary/clouddrift.adapters.gdp6h.html create mode 100644 _autosummary/clouddrift.adapters.gdp6h.preprocess.html create mode 100644 _autosummary/clouddrift.adapters.gdp6h.to_raggedarray.html create mode 100644 _autosummary/clouddrift.adapters.glad.get_dataframe.html create mode 100644 _autosummary/clouddrift.adapters.glad.html create mode 100644 _autosummary/clouddrift.adapters.glad.to_xarray.html create mode 100644 _autosummary/clouddrift.adapters.mosaic.get_dataframes.html create mode 100644 _autosummary/clouddrift.adapters.mosaic.get_file_urls.html create mode 100644 _autosummary/clouddrift.adapters.mosaic.get_repository_metadata.html create mode 100644 _autosummary/clouddrift.adapters.mosaic.html create mode 100644 _autosummary/clouddrift.adapters.mosaic.to_xarray.html create mode 100644 _autosummary/clouddrift.adapters.subsurface_floats.download.html create mode 100644 _autosummary/clouddrift.adapters.subsurface_floats.html create mode 100644 _autosummary/clouddrift.adapters.subsurface_floats.to_xarray.html create mode 100644 _autosummary/clouddrift.datasets.andro.html create mode 100644 _autosummary/clouddrift.datasets.gdp1h.html create mode 100644 _autosummary/clouddrift.datasets.gdp6h.html create mode 100644 _autosummary/clouddrift.datasets.glad.html create mode 100644 _autosummary/clouddrift.datasets.html create mode 100644 _autosummary/clouddrift.datasets.mosaic.html create mode 100644 _autosummary/clouddrift.datasets.spotters.html create mode 100644 _autosummary/clouddrift.datasets.subsurface_floats.html create mode 100644 _autosummary/clouddrift.datasets.yomaha.html create mode 100644 _autosummary/clouddrift.kinematics.html create mode 100644 _autosummary/clouddrift.kinematics.inertial_oscillation_from_position.html create mode 100644 _autosummary/clouddrift.kinematics.kinetic_energy.html create mode 100644 _autosummary/clouddrift.kinematics.position_from_velocity.html create mode 100644 _autosummary/clouddrift.kinematics.residual_position_from_displacement.html create mode 100644 _autosummary/clouddrift.kinematics.spin.html create mode 100644 _autosummary/clouddrift.kinematics.velocity_from_position.html create mode 100644 _autosummary/clouddrift.pairs.chance_pair.html create mode 100644 _autosummary/clouddrift.pairs.chance_pairs_from_ragged.html create mode 100644 _autosummary/clouddrift.pairs.html create mode 100644 _autosummary/clouddrift.pairs.pair_bounding_box_overlap.html create mode 100644 _autosummary/clouddrift.pairs.pair_space_distance.html create mode 100644 _autosummary/clouddrift.pairs.pair_time_distance.html create mode 100644 _autosummary/clouddrift.pairs.pair_time_overlap.html create mode 100644 _autosummary/clouddrift.plotting.html create mode 100644 _autosummary/clouddrift.plotting.plot_ragged.html create mode 100644 _autosummary/clouddrift.ragged.apply_ragged.html create mode 100644 _autosummary/clouddrift.ragged.chunk.html create mode 100644 _autosummary/clouddrift.ragged.html create mode 100644 _autosummary/clouddrift.ragged.prune.html create mode 100644 _autosummary/clouddrift.ragged.ragged_to_regular.html create mode 100644 _autosummary/clouddrift.ragged.regular_to_ragged.html create mode 100644 _autosummary/clouddrift.ragged.rowsize_to_index.html create mode 100644 _autosummary/clouddrift.ragged.segment.html create mode 100644 _autosummary/clouddrift.ragged.subset.html create mode 100644 _autosummary/clouddrift.ragged.unpack.html create mode 100644 _autosummary/clouddrift.raggedarray.RaggedArray.html create mode 100644 _autosummary/clouddrift.raggedarray.html create mode 100644 _autosummary/clouddrift.signal.analytic_signal.html create mode 100644 _autosummary/clouddrift.signal.cartesian_to_rotary.html create mode 100644 _autosummary/clouddrift.signal.ellipse_parameters.html create mode 100644 _autosummary/clouddrift.signal.html create mode 100644 _autosummary/clouddrift.signal.modulated_ellipse_signal.html create mode 100644 _autosummary/clouddrift.signal.rotary_to_cartesian.html create mode 100644 _autosummary/clouddrift.sphere.bearing.html create mode 100644 _autosummary/clouddrift.sphere.cartesian_to_spherical.html create mode 100644 _autosummary/clouddrift.sphere.cartesian_to_tangentplane.html create mode 100644 _autosummary/clouddrift.sphere.coriolis_frequency.html create mode 100644 _autosummary/clouddrift.sphere.cumulative_distance.html create mode 100644 _autosummary/clouddrift.sphere.distance.html create mode 100644 _autosummary/clouddrift.sphere.html create mode 100644 _autosummary/clouddrift.sphere.plane_to_sphere.html create mode 100644 _autosummary/clouddrift.sphere.position_from_distance_and_bearing.html create mode 100644 _autosummary/clouddrift.sphere.recast_lon.html create mode 100644 _autosummary/clouddrift.sphere.recast_lon180.html create mode 100644 _autosummary/clouddrift.sphere.recast_lon360.html create mode 100644 _autosummary/clouddrift.sphere.sphere_to_plane.html create mode 100644 _autosummary/clouddrift.sphere.spherical_to_cartesian.html create mode 100644 _autosummary/clouddrift.sphere.tangentplane_to_cartesian.html create mode 100644 _autosummary/clouddrift.wavelet.html create mode 100644 _autosummary/clouddrift.wavelet.morse_amplitude.html create mode 100644 _autosummary/clouddrift.wavelet.morse_freq.html create mode 100644 _autosummary/clouddrift.wavelet.morse_logspace_freq.html create mode 100644 _autosummary/clouddrift.wavelet.morse_properties.html create mode 100644 _autosummary/clouddrift.wavelet.morse_wavelet.html create mode 100644 _autosummary/clouddrift.wavelet.morse_wavelet_transform.html create mode 100644 _autosummary/clouddrift.wavelet.wavelet_transform.html create mode 100644 _images/ragged_array.png create mode 100644 _modules/clouddrift/adapters/gdp.html create mode 100644 _modules/clouddrift/adapters/gdp1h.html create mode 100644 _modules/clouddrift/adapters/gdp6h.html create mode 100644 _modules/clouddrift/adapters/glad.html create mode 100644 _modules/clouddrift/adapters/mosaic.html create mode 100644 _modules/clouddrift/adapters/subsurface_floats.html create mode 100644 _modules/clouddrift/datasets.html create mode 100644 _modules/clouddrift/kinematics.html create mode 100644 _modules/clouddrift/pairs.html create mode 100644 _modules/clouddrift/plotting.html create mode 100644 _modules/clouddrift/ragged.html create mode 100644 _modules/clouddrift/raggedarray.html create mode 100644 _modules/clouddrift/signal.html create mode 100644 _modules/clouddrift/sphere.html create mode 100644 _modules/clouddrift/wavelet.html create mode 100644 _modules/index.html create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.cut_str.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.decode_date.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.drogue_presence.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.fill_values.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.order_by_date.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.parse_directory_file.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.rowsize.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp.str_to_float.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp1h.download.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp1h.preprocess.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp1h.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp6h.download.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp6h.preprocess.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp6h.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.glad.get_dataframe.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.glad.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.glad.to_xarray.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.mosaic.get_dataframes.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.mosaic.get_file_urls.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.mosaic.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.mosaic.to_xarray.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.subsurface_floats.download.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.subsurface_floats.rst create mode 100644 _sources/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.andro.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.gdp1h.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.gdp6h.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.glad.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.mosaic.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.spotters.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.subsurface_floats.rst create mode 100644 _sources/_autosummary/clouddrift.datasets.yomaha.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.kinetic_energy.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.position_from_velocity.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.residual_position_from_displacement.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.spin.rst create mode 100644 _sources/_autosummary/clouddrift.kinematics.velocity_from_position.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.chance_pair.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.pair_space_distance.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.pair_time_distance.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.pair_time_overlap.rst create mode 100644 _sources/_autosummary/clouddrift.pairs.rst create mode 100644 _sources/_autosummary/clouddrift.plotting.plot_ragged.rst create mode 100644 _sources/_autosummary/clouddrift.plotting.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.apply_ragged.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.chunk.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.prune.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.ragged_to_regular.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.regular_to_ragged.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.rowsize_to_index.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.segment.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.subset.rst create mode 100644 _sources/_autosummary/clouddrift.ragged.unpack.rst create mode 100644 _sources/_autosummary/clouddrift.raggedarray.RaggedArray.rst create mode 100644 _sources/_autosummary/clouddrift.raggedarray.rst create mode 100644 _sources/_autosummary/clouddrift.signal.analytic_signal.rst create mode 100644 _sources/_autosummary/clouddrift.signal.cartesian_to_rotary.rst create mode 100644 _sources/_autosummary/clouddrift.signal.ellipse_parameters.rst create mode 100644 _sources/_autosummary/clouddrift.signal.modulated_ellipse_signal.rst create mode 100644 _sources/_autosummary/clouddrift.signal.rotary_to_cartesian.rst create mode 100644 _sources/_autosummary/clouddrift.signal.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.bearing.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.cartesian_to_spherical.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.coriolis_frequency.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.cumulative_distance.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.distance.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.plane_to_sphere.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.recast_lon.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.recast_lon180.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.recast_lon360.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.sphere_to_plane.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.spherical_to_cartesian.rst create mode 100644 _sources/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.morse_amplitude.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.morse_freq.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.morse_logspace_freq.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.morse_properties.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.morse_wavelet.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.morse_wavelet_transform.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.rst create mode 100644 _sources/_autosummary/clouddrift.wavelet.wavelet_transform.rst create mode 100644 _sources/api.rst create mode 100644 _sources/contributing.rst create mode 100644 _sources/datasets.rst create mode 100644 _sources/index.rst create mode 100644 _sources/install.rst create mode 100644 _sources/usage.rst create mode 100644 _static/check-solid.svg create mode 100644 _static/clipboard.min.js create mode 100644 _static/copy-button.svg create mode 100644 _static/copybutton.css create mode 100644 _static/copybutton.js create mode 100644 _static/copybutton_funcs.js create mode 100644 _static/favicon.ico create mode 100644 _static/graphviz.css create mode 100644 _static/images/logo_binder.svg create mode 100644 _static/images/logo_colab.png create mode 100644 _static/images/logo_deepnote.svg create mode 100644 _static/images/logo_jupyterhub.svg create mode 100644 _static/locales/ar/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ar/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/bg/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/bg/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/bn/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/bn/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ca/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ca/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/cs/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/cs/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/da/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/da/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/de/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/de/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/el/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/el/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/eo/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/eo/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/es/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/es/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/et/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/et/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/fi/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/fi/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/fr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/fr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/hr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/hr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/id/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/id/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/it/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/it/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/iw/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/iw/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ja/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ja/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ko/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ko/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/lt/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/lt/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/lv/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/lv/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ml/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ml/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/mr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/mr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ms/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ms/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/nl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/nl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/no/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/no/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/pl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/pl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/pt/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/pt/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ro/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ro/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ru/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ru/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sk/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sk/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/sv/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/sv/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ta/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ta/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/te/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/te/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/tg/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/tg/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/th/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/th/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/tl/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/tl/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/tr/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/tr/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/uk/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/uk/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/ur/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/ur/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/vi/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/vi/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/zh_CN/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/zh_CN/LC_MESSAGES/booktheme.po create mode 100644 _static/locales/zh_TW/LC_MESSAGES/booktheme.mo create mode 100644 _static/locales/zh_TW/LC_MESSAGES/booktheme.po create mode 100644 _static/logo.png create mode 100644 _static/sbt-webpack-macros.html create mode 100644 _static/scripts/bootstrap.js create mode 100644 _static/scripts/bootstrap.js.LICENSE.txt create mode 100644 _static/scripts/bootstrap.js.map create mode 100644 _static/scripts/pydata-sphinx-theme.js create mode 100644 _static/scripts/pydata-sphinx-theme.js.map create mode 100644 _static/scripts/sphinx-book-theme.js create mode 100644 _static/scripts/sphinx-book-theme.js.map create mode 100644 _static/sphinx_highlight.js create mode 100644 _static/styles/bootstrap.css create mode 100644 _static/styles/bootstrap.css.map create mode 100644 _static/styles/pydata-sphinx-theme.css create mode 100644 _static/styles/pydata-sphinx-theme.css.map create mode 100644 _static/styles/sphinx-book-theme.css create mode 100644 _static/styles/theme.css create mode 100644 _static/vendor/fontawesome/6.5.1/LICENSE.txt create mode 100644 _static/vendor/fontawesome/6.5.1/css/all.min.css create mode 100644 _static/vendor/fontawesome/6.5.1/js/all.min.js create mode 100644 _static/vendor/fontawesome/6.5.1/js/all.min.js.LICENSE.txt create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-brands-400.ttf create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-brands-400.woff2 create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-regular-400.ttf create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-regular-400.woff2 create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-solid-900.ttf create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-solid-900.woff2 create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-v4compatibility.ttf create mode 100644 _static/vendor/fontawesome/6.5.1/webfonts/fa-v4compatibility.woff2 create mode 100644 _static/webpack-macros.html create mode 100644 api.html create mode 100644 contributing.html create mode 100644 datasets.html create mode 100644 install.html create mode 100644 py-modindex.html create mode 100644 usage.html diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..aff0750e --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +clouddrift.org diff --git a/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.html b/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.html new file mode 100644 index 00000000..b6c774c5 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.html @@ -0,0 +1,587 @@ + + + + + + + + + + + clouddrift.adapters.gdp.cast_float64_variables_to_float32 — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.cast_float64_variables_to_float32

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.cast_float64_variables_to_float32#

+
+
+clouddrift.adapters.gdp.cast_float64_variables_to_float32(ds: Dataset, variables_to_skip: list[str] = ['time', 'lat', 'lon']) Dataset[source]#
+

Cast all float64 variables except variables_to_skip to float32. +Extra precision from float64 is not needed and takes up memory and disk +space.

+
+

Parameters#

+
+
dsxr.Dataset

Dataset to modify

+
+
variables_to_skiplist[str]

List of variables to skip; default is [“time”, “lat”, “lon”].

+
+
+
+
+

Returns#

+
+
dsxr.Dataset

Modified dataset

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.cut_str.html b/_autosummary/clouddrift.adapters.gdp.cut_str.html new file mode 100644 index 00000000..3d7e8c16 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.cut_str.html @@ -0,0 +1,585 @@ + + + + + + + + + + + clouddrift.adapters.gdp.cut_str — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.cut_str

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.cut_str#

+
+
+clouddrift.adapters.gdp.cut_str(value: str, max_length: int) chararray[source]#
+

Cut a string to a specific length and return it as a numpy chararray.

+
+

Parameters#

+
+
valuestr

String to cut

+
+
max_lengthint

Length of the output

+
+
+
+
+

Returns#

+
+
outnp.chararray

String with max_length characters

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.decode_date.html b/_autosummary/clouddrift.adapters.gdp.decode_date.html new file mode 100644 index 00000000..e245a3ff --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.decode_date.html @@ -0,0 +1,587 @@ + + + + + + + + + + + clouddrift.adapters.gdp.decode_date — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.decode_date

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.decode_date#

+
+
+clouddrift.adapters.gdp.decode_date(t)[source]#
+

The date format is specified as ‘seconds since 1970-01-01 00:00:00’ but +the missing values are stored as -1e+34 which is not supported by the +default parsing mechanism in xarray.

+

This function returns replaced the missing value by NaN and returns a +datetime instance.

+
+

Parameters#

+
+
tarray

Array of time values

+
+
+
+
+

Returns#

+
+
outdatetime

Datetime instance with the missing value replaced by NaN

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.drogue_presence.html b/_autosummary/clouddrift.adapters.gdp.drogue_presence.html new file mode 100644 index 00000000..6401babf --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.drogue_presence.html @@ -0,0 +1,585 @@ + + + + + + + + + + + clouddrift.adapters.gdp.drogue_presence — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.drogue_presence

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.drogue_presence#

+
+
+clouddrift.adapters.gdp.drogue_presence(lost_time, time) bool[source]#
+

Create drogue status from the drogue lost time and the trajectory time.

+
+

Parameters#

+
+
lost_time

Timestamp of the drogue loss (or NaT)

+
+
time

Observation time

+
+
+
+
+

Returns#

+
+
outbool

True if drogues and False otherwise

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.html b/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.html new file mode 100644 index 00000000..346ca435 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.html @@ -0,0 +1,578 @@ + + + + + + + + + + + clouddrift.adapters.gdp.fetch_netcdf — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.fetch_netcdf

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.fetch_netcdf#

+
+
+clouddrift.adapters.gdp.fetch_netcdf(url: str, file: str)[source]#
+

Download and save the file from the given url, if not already downloaded.

+
+

Parameters#

+
+
urlstr

URL from which to download the file.

+
+
filestr

Name of the file to save.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.fill_values.html b/_autosummary/clouddrift.adapters.gdp.fill_values.html new file mode 100644 index 00000000..1562f0f3 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.fill_values.html @@ -0,0 +1,579 @@ + + + + + + + + + + + clouddrift.adapters.gdp.fill_values — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.fill_values

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.fill_values#

+
+
+clouddrift.adapters.gdp.fill_values(var, default=nan)[source]#
+

Change fill values (-1e+34, inf, -inf) in var array to the value +specified by default.

+
+

Parameters#

+
+
vararray

Array to fill

+
+
defaultfloat

Default value to use for fill values

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.html b/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.html new file mode 100644 index 00000000..4a14fa6d --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.html @@ -0,0 +1,576 @@ + + + + + + + + + + + clouddrift.adapters.gdp.get_gdp_metadata — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.get_gdp_metadata

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.get_gdp_metadata#

+
+
+clouddrift.adapters.gdp.get_gdp_metadata() DataFrame[source]#
+

Download and parse GDP metadata and return it as a Pandas DataFrame.

+
+

Returns#

+
+
dfpd.DataFrame

Sorted list of drifters as a pandas DataFrame.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.html b/_autosummary/clouddrift.adapters.gdp.html new file mode 100644 index 00000000..76ee6593 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.html @@ -0,0 +1,824 @@ + + + + + + + + + + + clouddrift.adapters.gdp — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.adapters.gdp#

+

This module provides functions and metadata to convert the Global Drifter +Program (GDP) data to a clouddrift.RaggedArray instance. The functions +defined in this module are common to both hourly (clouddrift.adapters.gdp1h) +and six-hourly (clouddrift.adapters.gdp6h) GDP modules.

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cast_float64_variables_to_float32(ds[, ...])

Cast all float64 variables except variables_to_skip to float32.

cut_str(value, max_length)

Cut a string to a specific length and return it as a numpy chararray.

decode_date(t)

The date format is specified as 'seconds since 1970-01-01 00:00:00' but the missing values are stored as -1e+34 which is not supported by the default parsing mechanism in xarray.

drogue_presence(lost_time, time)

Create drogue status from the drogue lost time and the trajectory time.

fetch_netcdf(url, file)

Download and save the file from the given url, if not already downloaded.

fill_values(var[, default])

Change fill values (-1e+34, inf, -inf) in var array to the value specified by default.

get_gdp_metadata()

Download and parse GDP metadata and return it as a Pandas DataFrame.

order_by_date(df, idx)

From the previously sorted DataFrame of directory files, return the unique set of drifter IDs sorted by their start date (the date of the first quality-controlled data point).

parse_directory_file(filename)

Read a GDP directory file that contains metadata of drifter releases.

rowsize(index, **kwargs)

str_to_float(value[, default])

Convert a string to float, while returning the value of default if the string is not convertible to a float, or if it's a NaN.

+
+
+clouddrift.adapters.gdp.cast_float64_variables_to_float32(ds: Dataset, variables_to_skip: list[str] = ['time', 'lat', 'lon']) Dataset[source]#
+

Cast all float64 variables except variables_to_skip to float32. +Extra precision from float64 is not needed and takes up memory and disk +space.

+
+

Parameters#

+
+
dsxr.Dataset

Dataset to modify

+
+
variables_to_skiplist[str]

List of variables to skip; default is [“time”, “lat”, “lon”].

+
+
+
+
+

Returns#

+
+
dsxr.Dataset

Modified dataset

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.cut_str(value: str, max_length: int) chararray[source]#
+

Cut a string to a specific length and return it as a numpy chararray.

+
+

Parameters#

+
+
valuestr

String to cut

+
+
max_lengthint

Length of the output

+
+
+
+
+

Returns#

+
+
outnp.chararray

String with max_length characters

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.decode_date(t)[source]#
+

The date format is specified as ‘seconds since 1970-01-01 00:00:00’ but +the missing values are stored as -1e+34 which is not supported by the +default parsing mechanism in xarray.

+

This function returns replaced the missing value by NaN and returns a +datetime instance.

+
+

Parameters#

+
+
tarray

Array of time values

+
+
+
+
+

Returns#

+
+
outdatetime

Datetime instance with the missing value replaced by NaN

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.drogue_presence(lost_time, time) bool[source]#
+

Create drogue status from the drogue lost time and the trajectory time.

+
+

Parameters#

+
+
lost_time

Timestamp of the drogue loss (or NaT)

+
+
time

Observation time

+
+
+
+
+

Returns#

+
+
outbool

True if drogues and False otherwise

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.fetch_netcdf(url: str, file: str)[source]#
+

Download and save the file from the given url, if not already downloaded.

+
+

Parameters#

+
+
urlstr

URL from which to download the file.

+
+
filestr

Name of the file to save.

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.fill_values(var, default=nan)[source]#
+

Change fill values (-1e+34, inf, -inf) in var array to the value +specified by default.

+
+

Parameters#

+
+
vararray

Array to fill

+
+
defaultfloat

Default value to use for fill values

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.get_gdp_metadata() DataFrame[source]#
+

Download and parse GDP metadata and return it as a Pandas DataFrame.

+
+

Returns#

+
+
dfpd.DataFrame

Sorted list of drifters as a pandas DataFrame.

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.order_by_date(df: DataFrame, idx: list[int]) ndarray[int][source]#
+

From the previously sorted DataFrame of directory files, return the +unique set of drifter IDs sorted by their start date (the date of the first +quality-controlled data point).

+
+

Parameters#

+
+
idxlist

List of drifters to include in the ragged array

+
+
+
+
+

Returns#

+
+
idxlist

Unique set of drifter IDs sorted by their start date.

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.parse_directory_file(filename: str) DataFrame[source]#
+

Read a GDP directory file that contains metadata of drifter releases.

+
+

Parameters#

+
+
filenamestr

Name of the directory file to parse.

+
+
+
+
+

Returns#

+
+
dfpd.DataFrame

List of drifters from a single directory file as a pandas DataFrame.

+
+
+
+
+ +
+
+clouddrift.adapters.gdp.str_to_float(value: str, default: float = nan) float[source]#
+

Convert a string to float, while returning the value of default if the +string is not convertible to a float, or if it’s a NaN.

+
+

Parameters#

+
+
valuestr

String to convert to float

+
+
defaultfloat

Default value to return if the string is not convertible to float

+
+
+
+
+

Returns#

+
+
outfloat

Float value of the string, or default if the string is not convertible to float.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.order_by_date.html b/_autosummary/clouddrift.adapters.gdp.order_by_date.html new file mode 100644 index 00000000..70888286 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.order_by_date.html @@ -0,0 +1,585 @@ + + + + + + + + + + + clouddrift.adapters.gdp.order_by_date — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.order_by_date

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.order_by_date#

+
+
+clouddrift.adapters.gdp.order_by_date(df: DataFrame, idx: list[int]) ndarray[int][source]#
+

From the previously sorted DataFrame of directory files, return the +unique set of drifter IDs sorted by their start date (the date of the first +quality-controlled data point).

+
+

Parameters#

+
+
idxlist

List of drifters to include in the ragged array

+
+
+
+
+

Returns#

+
+
idxlist

Unique set of drifter IDs sorted by their start date.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.parse_directory_file.html b/_autosummary/clouddrift.adapters.gdp.parse_directory_file.html new file mode 100644 index 00000000..96e7a2c1 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.parse_directory_file.html @@ -0,0 +1,583 @@ + + + + + + + + + + + clouddrift.adapters.gdp.parse_directory_file — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.parse_directory_file

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.parse_directory_file#

+
+
+clouddrift.adapters.gdp.parse_directory_file(filename: str) DataFrame[source]#
+

Read a GDP directory file that contains metadata of drifter releases.

+
+

Parameters#

+
+
filenamestr

Name of the directory file to parse.

+
+
+
+
+

Returns#

+
+
dfpd.DataFrame

List of drifters from a single directory file as a pandas DataFrame.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.rowsize.html b/_autosummary/clouddrift.adapters.gdp.rowsize.html new file mode 100644 index 00000000..41914913 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.rowsize.html @@ -0,0 +1,568 @@ + + + + + + + + + + + clouddrift.adapters.gdp.rowsize — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.rowsize

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.rowsize#

+
+
+clouddrift.adapters.gdp.rowsize(index: int, **kwargs) int[source]#
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp.str_to_float.html b/_autosummary/clouddrift.adapters.gdp.str_to_float.html new file mode 100644 index 00000000..74fd4cf4 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp.str_to_float.html @@ -0,0 +1,586 @@ + + + + + + + + + + + clouddrift.adapters.gdp.str_to_float — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp.str_to_float

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp.str_to_float#

+
+
+clouddrift.adapters.gdp.str_to_float(value: str, default: float = nan) float[source]#
+

Convert a string to float, while returning the value of default if the +string is not convertible to a float, or if it’s a NaN.

+
+

Parameters#

+
+
valuestr

String to convert to float

+
+
defaultfloat

Default value to return if the string is not convertible to float

+
+
+
+
+

Returns#

+
+
outfloat

Float value of the string, or default if the string is not convertible to float.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp1h.download.html b/_autosummary/clouddrift.adapters.gdp1h.download.html new file mode 100644 index 00000000..8173f0fa --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp1h.download.html @@ -0,0 +1,590 @@ + + + + + + + + + + + clouddrift.adapters.gdp1h.download — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp1h.download

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp1h.download#

+
+
+clouddrift.adapters.gdp1h.download(drifter_ids: list = None, n_random_id: int = None, url: str = 'https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/hourly_product/v2.01/', tmp_path: str = None)[source]#
+

Download individual NetCDF files from the AOML server.

+
+

Parameters#

+
+
drifter_idslist

List of drifter to retrieve (Default: all)

+
+
n_random_idint

Randomly select n_random_id drifter IDs to download (Default: None)

+
+
urlstr

URL from which to download the data (Default: GDP_DATA_URL). Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL.

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp on Linux)

+
+
+
+
+

Returns#

+
+
outlist

List of retrieved drifters

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp1h.html b/_autosummary/clouddrift.adapters.gdp1h.html new file mode 100644 index 00000000..d4a57604 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp1h.html @@ -0,0 +1,702 @@ + + + + + + + + + + + clouddrift.adapters.gdp1h — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp1h

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp1h#

+

This module provides functions and metadata that can be used to convert the +hourly Global Drifter Program (GDP) data to a clouddrift.RaggedArray +instance.

+

Functions

+ + + + + + + + + + + + +

download([drifter_ids, n_random_id, url, ...])

Download individual NetCDF files from the AOML server.

preprocess(index, **kwargs)

Extract and preprocess the Lagrangian data and attributes.

to_raggedarray([drifter_ids, n_random_id, ...])

Download and process individual GDP hourly files and return a RaggedArray instance with the data.

+
+
+clouddrift.adapters.gdp1h.download(drifter_ids: list = None, n_random_id: int = None, url: str = 'https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/hourly_product/v2.01/', tmp_path: str = None)[source]#
+

Download individual NetCDF files from the AOML server.

+
+

Parameters#

+
+
drifter_idslist

List of drifter to retrieve (Default: all)

+
+
n_random_idint

Randomly select n_random_id drifter IDs to download (Default: None)

+
+
urlstr

URL from which to download the data (Default: GDP_DATA_URL). Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL.

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp on Linux)

+
+
+
+
+

Returns#

+
+
outlist

List of retrieved drifters

+
+
+
+
+ +
+
+clouddrift.adapters.gdp1h.preprocess(index: int, **kwargs) Dataset[source]#
+

Extract and preprocess the Lagrangian data and attributes.

+

This function takes an identification number that can be used to create a +file or url pattern or select data from a Dataframe. It then preprocesses +the data and returns a clean Xarray Dataset.

+
+

Parameters#

+
+
indexint

Drifter’s identification number

+
+
+
+
+

Returns#

+
+
dsxr.Dataset

Xarray Dataset containing the data and attributes

+
+
+
+
+ +
+
+clouddrift.adapters.gdp1h.to_raggedarray(drifter_ids: list[int] | None = None, n_random_id: int | None = None, url: str | None = 'https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/hourly_product/v2.01/', tmp_path: str | None = None) RaggedArray[source]#
+

Download and process individual GDP hourly files and return a RaggedArray +instance with the data.

+
+

Parameters#

+
+
drifter_idslist[int], optional

List of drifters to retrieve (Default: all)

+
+
n_random_idlist[int], optional

Randomly select n_random_id drifter NetCDF files

+
+
urlstr, optional

URL from which to download the data (Default: GDP_DATA_URL). +Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL.

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp on Linux)

+
+
+
+
+

Returns#

+
+
outRaggedArray

A RaggedArray instance of the requested dataset

+
+
+
+
+

Examples#

+

Invoke to_raggedarray without any arguments to download all drifter data +from the 2.01 GDP feed:

+
>>> from clouddrift.adapters.gdp1h import to_raggedarray
+>>> ra = to_raggedarray()
+
+
+

To download a random sample of 100 drifters, for example for development +or testing, use the n_random_id argument:

+
>>> ra = to_raggedarray(n_random_id=100)
+
+
+

To download a specific list of drifters, use the drifter_ids argument:

+
>>> ra = to_raggedarray(drifter_ids=[44136, 54680, 83463])
+
+
+

To download the experimental 2.01 GDP feed, use the url argument to +specify the experimental feed URL:

+
>>> from clouddrift.adapters.gdp1h import GDP_DATA_URL_EXPERIMENTAL, to_raggedarray
+>>> ra = to_raggedarray(url=GDP_DATA_URL_EXPERIMENTAL)
+
+
+

Finally, to_raggedarray returns a RaggedArray instance which provides +a convenience method to emit a xarray.Dataset instance:

+
>>> ds = ra.to_xarray()
+
+
+

To write the ragged array dataset to a NetCDF file on disk, do

+
>>> ds.to_netcdf("gdp1h.nc", format="NETCDF4")
+
+
+

Alternatively, to write the ragged array to a Parquet file, first create +it as an Awkward Array:

+
>>> arr = ra.to_awkward()
+>>> arr.to_parquet("gdp1h.parquet")
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp1h.preprocess.html b/_autosummary/clouddrift.adapters.gdp1h.preprocess.html new file mode 100644 index 00000000..24f1243d --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp1h.preprocess.html @@ -0,0 +1,586 @@ + + + + + + + + + + + clouddrift.adapters.gdp1h.preprocess — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp1h.preprocess

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp1h.preprocess#

+
+
+clouddrift.adapters.gdp1h.preprocess(index: int, **kwargs) Dataset[source]#
+

Extract and preprocess the Lagrangian data and attributes.

+

This function takes an identification number that can be used to create a +file or url pattern or select data from a Dataframe. It then preprocesses +the data and returns a clean Xarray Dataset.

+
+

Parameters#

+
+
indexint

Drifter’s identification number

+
+
+
+
+

Returns#

+
+
dsxr.Dataset

Xarray Dataset containing the data and attributes

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.html b/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.html new file mode 100644 index 00000000..bb3ad5dd --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.html @@ -0,0 +1,631 @@ + + + + + + + + + + + clouddrift.adapters.gdp1h.to_raggedarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp1h.to_raggedarray

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp1h.to_raggedarray#

+
+
+clouddrift.adapters.gdp1h.to_raggedarray(drifter_ids: list[int] | None = None, n_random_id: int | None = None, url: str | None = 'https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/hourly_product/v2.01/', tmp_path: str | None = None) RaggedArray[source]#
+

Download and process individual GDP hourly files and return a RaggedArray +instance with the data.

+
+

Parameters#

+
+
drifter_idslist[int], optional

List of drifters to retrieve (Default: all)

+
+
n_random_idlist[int], optional

Randomly select n_random_id drifter NetCDF files

+
+
urlstr, optional

URL from which to download the data (Default: GDP_DATA_URL). +Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL.

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp on Linux)

+
+
+
+
+

Returns#

+
+
outRaggedArray

A RaggedArray instance of the requested dataset

+
+
+
+
+

Examples#

+

Invoke to_raggedarray without any arguments to download all drifter data +from the 2.01 GDP feed:

+
>>> from clouddrift.adapters.gdp1h import to_raggedarray
+>>> ra = to_raggedarray()
+
+
+

To download a random sample of 100 drifters, for example for development +or testing, use the n_random_id argument:

+
>>> ra = to_raggedarray(n_random_id=100)
+
+
+

To download a specific list of drifters, use the drifter_ids argument:

+
>>> ra = to_raggedarray(drifter_ids=[44136, 54680, 83463])
+
+
+

To download the experimental 2.01 GDP feed, use the url argument to +specify the experimental feed URL:

+
>>> from clouddrift.adapters.gdp1h import GDP_DATA_URL_EXPERIMENTAL, to_raggedarray
+>>> ra = to_raggedarray(url=GDP_DATA_URL_EXPERIMENTAL)
+
+
+

Finally, to_raggedarray returns a RaggedArray instance which provides +a convenience method to emit a xarray.Dataset instance:

+
>>> ds = ra.to_xarray()
+
+
+

To write the ragged array dataset to a NetCDF file on disk, do

+
>>> ds.to_netcdf("gdp1h.nc", format="NETCDF4")
+
+
+

Alternatively, to write the ragged array to a Parquet file, first create +it as an Awkward Array:

+
>>> arr = ra.to_awkward()
+>>> arr.to_parquet("gdp1h.parquet")
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp6h.download.html b/_autosummary/clouddrift.adapters.gdp6h.download.html new file mode 100644 index 00000000..d3eec6c2 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp6h.download.html @@ -0,0 +1,590 @@ + + + + + + + + + + + clouddrift.adapters.gdp6h.download — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp6h.download

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp6h.download#

+
+
+clouddrift.adapters.gdp6h.download(drifter_ids: list = None, n_random_id: int = None, url: str = 'https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/6h/', tmp_path: str = '/tmp/clouddrift/gdp6h')[source]#
+

Download individual NetCDF files from the AOML server.

+
+

Parameters#

+
+
drifter_idslist

List of drifter to retrieve (Default: all)

+
+
n_random_idint

Randomly select n_random_id drifter IDs to download (Default: None)

+
+
urlstr

URL from which to download the data (Default: GDP_DATA_URL). Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL.

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp6h on Linux)

+
+
+
+
+

Returns#

+
+
outlist

List of retrieved drifters

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp6h.html b/_autosummary/clouddrift.adapters.gdp6h.html new file mode 100644 index 00000000..d32789b4 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp6h.html @@ -0,0 +1,693 @@ + + + + + + + + + + + clouddrift.adapters.gdp6h — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp6h

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp6h#

+

This module provides functions and metadata that can be used to convert the +6-hourly Global Drifter Program (GDP) data to a clouddrift.RaggedArray +instance.

+

Functions

+ + + + + + + + + + + + +

download([drifter_ids, n_random_id, url, ...])

Download individual NetCDF files from the AOML server.

preprocess(index, **kwargs)

Extract and preprocess the Lagrangian data and attributes.

to_raggedarray([drifter_ids, n_random_id, ...])

Download and process individual GDP 6-hourly files and return a RaggedArray instance with the data.

+
+
+clouddrift.adapters.gdp6h.download(drifter_ids: list = None, n_random_id: int = None, url: str = 'https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/6h/', tmp_path: str = '/tmp/clouddrift/gdp6h')[source]#
+

Download individual NetCDF files from the AOML server.

+
+

Parameters#

+
+
drifter_idslist

List of drifter to retrieve (Default: all)

+
+
n_random_idint

Randomly select n_random_id drifter IDs to download (Default: None)

+
+
urlstr

URL from which to download the data (Default: GDP_DATA_URL). Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL.

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp6h on Linux)

+
+
+
+
+

Returns#

+
+
outlist

List of retrieved drifters

+
+
+
+
+ +
+
+clouddrift.adapters.gdp6h.preprocess(index: int, **kwargs) Dataset[source]#
+

Extract and preprocess the Lagrangian data and attributes.

+

This function takes an identification number that can be used to create a +file or url pattern or select data from a Dataframe. It then preprocesses +the data and returns a clean Xarray Dataset.

+
+

Parameters#

+
+
indexint

Drifter’s identification number

+
+
+
+
+

Returns#

+
+
dsxr.Dataset

Xarray Dataset containing the data and attributes

+
+
+
+
+ +
+
+clouddrift.adapters.gdp6h.to_raggedarray(drifter_ids: list[int] | None = None, n_random_id: int | None = None, tmp_path: str | None = '/tmp/clouddrift/gdp6h') RaggedArray[source]#
+

Download and process individual GDP 6-hourly files and return a +RaggedArray instance with the data.

+
+

Parameters#

+
+
drifter_idslist[int], optional

List of drifters to retrieve (Default: all)

+
+
n_random_idlist[int], optional

Randomly select n_random_id drifter NetCDF files

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp6h on Linux)

+
+
+
+
+

Returns#

+
+
outRaggedArray

A RaggedArray instance of the requested dataset

+
+
+
+
+

Examples#

+

Invoke to_raggedarray without any arguments to download all drifter data +from the 6-hourly GDP feed:

+
>>> from clouddrift.adapters.gdp6h import to_raggedarray
+>>> ra = to_raggedarray()
+
+
+

To download a random sample of 100 drifters, for example for development +or testing, use the n_random_id argument:

+
>>> ra = to_raggedarray(n_random_id=100)
+
+
+

To download a specific list of drifters, use the drifter_ids argument:

+
>>> ra = to_raggedarray(drifter_ids=[54375, 114956, 126934])
+
+
+

Finally, to_raggedarray returns a RaggedArray instance which provides +a convenience method to emit a xarray.Dataset instance:

+
>>> ds = ra.to_xarray()
+
+
+

To write the ragged array dataset to a NetCDF file on disk, do

+
>>> ds.to_netcdf("gdp6h.nc", format="NETCDF4")
+
+
+

Alternatively, to write the ragged array to a Parquet file, first create +it as an Awkward Array:

+
>>> arr = ra.to_awkward()
+>>> arr.to_parquet("gdp6h.parquet")
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp6h.preprocess.html b/_autosummary/clouddrift.adapters.gdp6h.preprocess.html new file mode 100644 index 00000000..d02ec5a0 --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp6h.preprocess.html @@ -0,0 +1,586 @@ + + + + + + + + + + + clouddrift.adapters.gdp6h.preprocess — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp6h.preprocess

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp6h.preprocess#

+
+
+clouddrift.adapters.gdp6h.preprocess(index: int, **kwargs) Dataset[source]#
+

Extract and preprocess the Lagrangian data and attributes.

+

This function takes an identification number that can be used to create a +file or url pattern or select data from a Dataframe. It then preprocesses +the data and returns a clean Xarray Dataset.

+
+

Parameters#

+
+
indexint

Drifter’s identification number

+
+
+
+
+

Returns#

+
+
dsxr.Dataset

Xarray Dataset containing the data and attributes

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.html b/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.html new file mode 100644 index 00000000..fb3d3b2f --- /dev/null +++ b/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.html @@ -0,0 +1,622 @@ + + + + + + + + + + + clouddrift.adapters.gdp6h.to_raggedarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.gdp6h.to_raggedarray

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.gdp6h.to_raggedarray#

+
+
+clouddrift.adapters.gdp6h.to_raggedarray(drifter_ids: list[int] | None = None, n_random_id: int | None = None, tmp_path: str | None = '/tmp/clouddrift/gdp6h') RaggedArray[source]#
+

Download and process individual GDP 6-hourly files and return a +RaggedArray instance with the data.

+
+

Parameters#

+
+
drifter_idslist[int], optional

List of drifters to retrieve (Default: all)

+
+
n_random_idlist[int], optional

Randomly select n_random_id drifter NetCDF files

+
+
tmp_pathstr, optional

Path to the directory where the individual NetCDF files are stored +(default varies depending on operating system; /tmp/clouddrift/gdp6h on Linux)

+
+
+
+
+

Returns#

+
+
outRaggedArray

A RaggedArray instance of the requested dataset

+
+
+
+
+

Examples#

+

Invoke to_raggedarray without any arguments to download all drifter data +from the 6-hourly GDP feed:

+
>>> from clouddrift.adapters.gdp6h import to_raggedarray
+>>> ra = to_raggedarray()
+
+
+

To download a random sample of 100 drifters, for example for development +or testing, use the n_random_id argument:

+
>>> ra = to_raggedarray(n_random_id=100)
+
+
+

To download a specific list of drifters, use the drifter_ids argument:

+
>>> ra = to_raggedarray(drifter_ids=[54375, 114956, 126934])
+
+
+

Finally, to_raggedarray returns a RaggedArray instance which provides +a convenience method to emit a xarray.Dataset instance:

+
>>> ds = ra.to_xarray()
+
+
+

To write the ragged array dataset to a NetCDF file on disk, do

+
>>> ds.to_netcdf("gdp6h.nc", format="NETCDF4")
+
+
+

Alternatively, to write the ragged array to a Parquet file, first create +it as an Awkward Array:

+
>>> arr = ra.to_awkward()
+>>> arr.to_parquet("gdp6h.parquet")
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.glad.get_dataframe.html b/_autosummary/clouddrift.adapters.glad.get_dataframe.html new file mode 100644 index 00000000..d7439d31 --- /dev/null +++ b/_autosummary/clouddrift.adapters.glad.get_dataframe.html @@ -0,0 +1,569 @@ + + + + + + + + + + + clouddrift.adapters.glad.get_dataframe — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.glad.get_dataframe

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.glad.get_dataframe#

+
+
+clouddrift.adapters.glad.get_dataframe() DataFrame[source]#
+

Get the GLAD dataset as a pandas DataFrame.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.glad.html b/_autosummary/clouddrift.adapters.glad.html new file mode 100644 index 00000000..6895d6c0 --- /dev/null +++ b/_autosummary/clouddrift.adapters.glad.html @@ -0,0 +1,606 @@ + + + + + + + + + + + clouddrift.adapters.glad — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.glad

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.glad#

+

This module defines functions used to adapt the Grand LAgrangian Deployment +(GLAD) dataset as a ragged-array Xarray Dataset.

+

The dataset and its description are hosted at https://doi.org/10.7266/N7VD6WC8.

+
+

Example#

+
>>> from clouddrift.adapters import glad
+>>> ds = glad.to_xarray()
+
+
+
+
+

Reference#

+

Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012. Distributed by: Gulf of Mexico Research Initiative Information and Data Cooperative (GRIIDC), Harte Research Institute, Texas A&M University–Corpus Christi. doi:10.7266/N7VD6WC8

+
+

Functions

+ + + + + + + + + +

get_dataframe()

Get the GLAD dataset as a pandas DataFrame.

to_xarray()

Return the GLAD data as a ragged-array Xarray Dataset.

+
+
+clouddrift.adapters.glad.get_dataframe() DataFrame[source]#
+

Get the GLAD dataset as a pandas DataFrame.

+
+ +
+
+clouddrift.adapters.glad.to_xarray() Dataset[source]#
+

Return the GLAD data as a ragged-array Xarray Dataset.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.glad.to_xarray.html b/_autosummary/clouddrift.adapters.glad.to_xarray.html new file mode 100644 index 00000000..4b991930 --- /dev/null +++ b/_autosummary/clouddrift.adapters.glad.to_xarray.html @@ -0,0 +1,569 @@ + + + + + + + + + + + clouddrift.adapters.glad.to_xarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.glad.to_xarray

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.glad.to_xarray#

+
+
+clouddrift.adapters.glad.to_xarray() Dataset[source]#
+

Return the GLAD data as a ragged-array Xarray Dataset.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.mosaic.get_dataframes.html b/_autosummary/clouddrift.adapters.mosaic.get_dataframes.html new file mode 100644 index 00000000..7d6b0538 --- /dev/null +++ b/_autosummary/clouddrift.adapters.mosaic.get_dataframes.html @@ -0,0 +1,570 @@ + + + + + + + + + + + clouddrift.adapters.mosaic.get_dataframes — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.mosaic.get_dataframes

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.mosaic.get_dataframes#

+
+
+clouddrift.adapters.mosaic.get_dataframes() tuple[DataFrame, DataFrame][source]#
+

Get the MOSAiC data (obs dimension in the target Dataset) and metadata +(traj dimension in the target dataset ) as pandas DataFrames.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.mosaic.get_file_urls.html b/_autosummary/clouddrift.adapters.mosaic.get_file_urls.html new file mode 100644 index 00000000..d767094c --- /dev/null +++ b/_autosummary/clouddrift.adapters.mosaic.get_file_urls.html @@ -0,0 +1,569 @@ + + + + + + + + + + + clouddrift.adapters.mosaic.get_file_urls — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.mosaic.get_file_urls

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.mosaic.get_file_urls#

+
+
+clouddrift.adapters.mosaic.get_file_urls(xml: str) list[str][source]#
+

Pass the MOSAiC XML string and return the list of filenames and URLs.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.html b/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.html new file mode 100644 index 00000000..386b8118 --- /dev/null +++ b/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.html @@ -0,0 +1,570 @@ + + + + + + + + + + + clouddrift.adapters.mosaic.get_repository_metadata — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.mosaic.get_repository_metadata

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.mosaic.get_repository_metadata#

+
+
+clouddrift.adapters.mosaic.get_repository_metadata() str[source]#
+

Get the MOSAiC repository metadata as an XML string. +Pass this string to other get_* functions to extract the data you need.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.mosaic.html b/_autosummary/clouddrift.adapters.mosaic.html new file mode 100644 index 00000000..509d910a --- /dev/null +++ b/_autosummary/clouddrift.adapters.mosaic.html @@ -0,0 +1,632 @@ + + + + + + + + + + + clouddrift.adapters.mosaic — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.mosaic

+ +
+ +
+
+ + + + +
+ +
+

clouddrift.adapters.mosaic#

+

This module defines functions used to adapt the MOSAiC sea-ice drift dataset as +a ragged-array dataset.

+

The dataset is hosted at https://doi.org/10.18739/A2KP7TS83.

+

Reference: Angela Bliss, Jennifer Hutchings, Philip Anderson, Philipp Anhaus, +Hans Jakob Belter, Jørgen Berge, Vladimir Bessonov, Bin Cheng, Sylvia Cole, +Dave Costa, Finlo Cottier, Christopher J Cox, Pedro R De La Torre, Dmitry V Divine, +Gilbert Emzivat, Ying-Chih Fang, Steven Fons, Michael Gallagher, Maxime Geoffrey, +Mats A Granskog, … Guangyu Zuo. (2022). Sea ice drift tracks from the Distributed +Network of autonomous buoys deployed during the Multidisciplinary drifting Observatory +for the Study of Arctic Climate (MOSAiC) expedition 2019 - 2021. Arctic Data Center. +doi:10.18739/A2KP7TS83.

+
+

Example#

+
>>> from clouddrift.adapters import mosaic
+>>> ds = mosaic.to_xarray()
+
+
+
+

Functions

+ + + + + + + + + + + + + + + +

get_dataframes()

Get the MOSAiC data (obs dimension in the target Dataset) and metadata (traj dimension in the target dataset ) as pandas DataFrames.

get_file_urls(xml)

Pass the MOSAiC XML string and return the list of filenames and URLs.

get_repository_metadata()

Get the MOSAiC repository metadata as an XML string.

to_xarray()

Return the MOSAiC data as an ragged-array Xarray Dataset.

+
+
+clouddrift.adapters.mosaic.get_dataframes() tuple[DataFrame, DataFrame][source]#
+

Get the MOSAiC data (obs dimension in the target Dataset) and metadata +(traj dimension in the target dataset ) as pandas DataFrames.

+
+ +
+
+clouddrift.adapters.mosaic.get_file_urls(xml: str) list[str][source]#
+

Pass the MOSAiC XML string and return the list of filenames and URLs.

+
+ +
+
+clouddrift.adapters.mosaic.get_repository_metadata() str[source]#
+

Get the MOSAiC repository metadata as an XML string. +Pass this string to other get_* functions to extract the data you need.

+
+ +
+
+clouddrift.adapters.mosaic.to_xarray()[source]#
+

Return the MOSAiC data as an ragged-array Xarray Dataset.

+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.mosaic.to_xarray.html b/_autosummary/clouddrift.adapters.mosaic.to_xarray.html new file mode 100644 index 00000000..8b987951 --- /dev/null +++ b/_autosummary/clouddrift.adapters.mosaic.to_xarray.html @@ -0,0 +1,569 @@ + + + + + + + + + + + clouddrift.adapters.mosaic.to_xarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.mosaic.to_xarray

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.mosaic.to_xarray#

+
+
+clouddrift.adapters.mosaic.to_xarray()[source]#
+

Return the MOSAiC data as an ragged-array Xarray Dataset.

+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.subsurface_floats.download.html b/_autosummary/clouddrift.adapters.subsurface_floats.download.html new file mode 100644 index 00000000..ab31261f --- /dev/null +++ b/_autosummary/clouddrift.adapters.subsurface_floats.download.html @@ -0,0 +1,568 @@ + + + + + + + + + + + clouddrift.adapters.subsurface_floats.download — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.subsurface_floats.download

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.subsurface_floats.download#

+
+
+clouddrift.adapters.subsurface_floats.download(file: str)[source]#
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.subsurface_floats.html b/_autosummary/clouddrift.adapters.subsurface_floats.html new file mode 100644 index 00000000..c93626f0 --- /dev/null +++ b/_autosummary/clouddrift.adapters.subsurface_floats.html @@ -0,0 +1,585 @@ + + + + + + + + + + + clouddrift.adapters.subsurface_floats — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.subsurface_floats

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.subsurface_floats#

+

This module defines functions to adapt as a ragged-array dataset a collection of data +from 2193 trajectories of SOFAR, APEX, and RAFOS subsurface floats from 52 experiments +across the world between 1989 and 2015.

+

The dataset is hosted at https://www.aoml.noaa.gov/phod/float_traj/index.php

+
+

Example#

+
>>> from clouddrift.adapters import subsurface_floats
+>>> ds = subsurface_floats.to_xarray()
+
+
+
+

Functions

+ + + + + + + + + +

download(file)

to_xarray([tmp_path])

+
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.html b/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.html new file mode 100644 index 00000000..3b381687 --- /dev/null +++ b/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.html @@ -0,0 +1,568 @@ + + + + + + + + + + + clouddrift.adapters.subsurface_floats.to_xarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.adapters.subsurface_floats.to_xarray

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.adapters.subsurface_floats.to_xarray#

+
+
+clouddrift.adapters.subsurface_floats.to_xarray(tmp_path: str = None)[source]#
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.andro.html b/_autosummary/clouddrift.datasets.andro.html new file mode 100644 index 00000000..ab2eeee3 --- /dev/null +++ b/_autosummary/clouddrift.datasets.andro.html @@ -0,0 +1,633 @@ + + + + + + + + + + + clouddrift.datasets.andro — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.andro

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.andro#

+
+
+clouddrift.datasets.andro(decode_times: bool = True) Dataset[source]#
+

Returns the ANDRO as a ragged array Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access. The upstream +data is available at https://www.seanoe.org/data/00360/47077/.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

ANDRO dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import andro
+>>> ds = andro()
+>>> ds
+<xarray.Dataset>
+Dimensions:     (obs: 1360753, traj: 9996)
+Coordinates:
+    time_d      (obs) datetime64[ns] ...
+    time_s      (obs) datetime64[ns] ...
+    time_lp     (obs) datetime64[ns] ...
+    time_lc     (obs) datetime64[ns] ...
+    id          (traj) int64 ...
+Dimensions without coordinates: obs, traj
+Data variables: (12/33)
+    lon_d       (obs) float64 ...
+    lat_d       (obs) float64 ...
+    pres_d      (obs) float32 ...
+    temp_d      (obs) float32 ...
+    sal_d       (obs) float32 ...
+    ve_d        (obs) float32 ...
+    ...          ...
+    lon_lc      (obs) float64 ...
+    lat_lc      (obs) float64 ...
+    surf_fix    (obs) int64 ...
+    cycle       (obs) int64 ...
+    profile_id  (obs) float32 ...
+    rowsize     (traj) int64 ...
+Attributes:
+    title:           ANDRO: An Argo-based deep displacement dataset
+    history:         2022-03-04
+    date_created:    2023-12-08T00:52:00.937120
+    publisher_name:  SEANOE (SEA scieNtific Open data Edition)
+    publisher_url:   https://www.seanoe.org/data/00360/47077/
+    license:         freely available
+
+
+
+
+

Reference#

+

Ollitrault Michel, Rannou Philippe, Brion Emilie, Cabanes Cecile, Piron Anne, Reverdin Gilles, +Kolodziejczyk Nicolas (2022). ANDRO: An Argo-based deep displacement dataset. +SEANOE. https://doi.org/10.17882/47077

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.gdp1h.html b/_autosummary/clouddrift.datasets.gdp1h.html new file mode 100644 index 00000000..40209117 --- /dev/null +++ b/_autosummary/clouddrift.datasets.gdp1h.html @@ -0,0 +1,635 @@ + + + + + + + + + + + clouddrift.datasets.gdp1h — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.gdp1h

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.gdp1h#

+
+
+clouddrift.datasets.gdp1h(decode_times: bool = True) Dataset[source]#
+

Returns the latest version of the NOAA Global Drifter Program (GDP) hourly +dataset as a ragged array Xarray dataset.

+

The data is accessed from zarr archive hosted on a public AWS S3 bucket accessible at +https://registry.opendata.aws/noaa-oar-hourly-gdp/. Original data source from NOAA NCEI +is https://doi.org/10.25921/x46c-3620).

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

Hourly GDP dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import gdp1h
+>>> ds = gdp1h()
+>>> ds
+<xarray.Dataset>
+Dimensions:                (traj: 19396, obs: 197214787)
+Coordinates:
+    id                     (traj) int64 ...
+    time                   (obs) datetime64[ns] ...
+Dimensions without coordinates: traj, obs
+Data variables: (12/60)
+    BuoyTypeManufacturer   (traj) |S20 ...
+    BuoyTypeSensorArray    (traj) |S20 ...
+    CurrentProgram         (traj) float32 ...
+    DeployingCountry       (traj) |S20 ...
+    DeployingShip          (traj) |S20 ...
+    DeploymentComments     (traj) |S20 ...
+    ...                     ...
+    start_lat              (traj) float32 ...
+    start_lon              (traj) float32 ...
+    typebuoy               (traj) |S10 ...
+    typedeath              (traj) int8 ...
+    ve                     (obs) float32 ...
+    vn                     (obs) float32 ...
+Attributes: (12/16)
+    Conventions:       CF-1.6
+    acknowledgement:   Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurio...
+    contributor_name:  NOAA Global Drifter Program
+    contributor_role:  Data Acquisition Center
+    date_created:      2023-09-08T17:05:12.130123
+    doi:               10.25921/x46c-3620
+    ...                ...
+    processing_level:  Level 2 QC by GDP drifter DAC
+    publisher_email:   aoml.dftr@noaa.gov
+    publisher_name:    GDP Drifter DAC
+    publisher_url:     https://www.aoml.noaa.gov/phod/gdp
+    summary:           Global Drifter Program hourly data
+    title:             Global Drifter Program hourly drifting buoy collection
+
+
+
+
+

See Also#

+

gdp6h()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.gdp6h.html b/_autosummary/clouddrift.datasets.gdp6h.html new file mode 100644 index 00000000..33de4bb0 --- /dev/null +++ b/_autosummary/clouddrift.datasets.gdp6h.html @@ -0,0 +1,639 @@ + + + + + + + + + + + clouddrift.datasets.gdp6h — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.gdp6h

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.gdp6h#

+
+
+clouddrift.datasets.gdp6h(decode_times: bool = True) Dataset[source]#
+

Returns the NOAA Global Drifter Program (GDP) 6-hourly dataset as a ragged array +Xarray dataset.

+

The data is accessed from a public HTTPS server at NOAA’s Atlantic +Oceanographic and Meteorological Laboratory (AOML) accessible at +https://www.aoml.noaa.gov/phod/gdp/index.php. It should be noted that the data loading +method is platform dependent. Linux and Darwin (macOS) machines lazy load the datasets leveraging the +byte-range feature of the netCDF-c library (dataset loading engine used by xarray). +Windows machines download the entire dataset into a memory buffer which is then passed +to xarray.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

6-hourly GDP dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import gdp6h
+>>> ds = gdp6h()
+>>> ds
+<xarray.Dataset>
+Dimensions:                (traj: 27647, obs: 46535470)
+Coordinates:
+    ids                    (obs) int64 7702204 7702204 ... 300234061198840
+    time                   (obs) float64 2.879e+08 2.879e+08 ... 1.697e+09
+Dimensions without coordinates: traj, obs
+Data variables: (12/50)
+    ID                     (traj) int64 7702204 7702201 ... 300234061198840
+    rowsize                (traj) int32 92 1747 1943 1385 1819 ... 54 53 51 28
+    WMO                    (traj) int32 0 0 0 0 ... 6203890 6203888 4101885
+    expno                  (traj) int32 40 40 40 40 ... 31412 21421 21421 31412
+    deploy_date            (traj) float32 2.878e+08 2.878e+08 ... 1.696e+09 nan
+    deploy_lat             (traj) float32 -7.798 -4.9 -3.18 ... 9.9 11.9 nan
+    ...                     ...
+    vn                     (obs) float32 nan 0.1056 0.04974 ... 0.7384 nan
+    temp                   (obs) float32 28.35 28.3 nan ... 29.08 28.97 28.92
+    err_lat                (obs) float32 0.009737 0.007097 ... 0.001659 0.001687
+    err_lon                (obs) float32 0.00614 0.004583 ... 0.002471 0.002545
+    err_temp               (obs) float32 0.08666 0.08757 ... 0.03665 0.03665
+    drogue_status          (obs) bool False False False False ... True True True
+Attributes: (12/18)
+    title:                Global Drifter Program drifting buoy collection
+    history:              version September 2023. Metadata from dirall.dat an...
+    Conventions:          CF-1.6
+    time_coverage_start:  1979-02-15:00:00:00Z
+    time_coverage_end:    2023-10-18:18:00:00Z
+    date_created:         2023-12-22T17:50:22.242943
+    ...                   ...
+    contributor_name:     NOAA Global Drifter Program
+    contributor_role:     Data Acquisition Center
+    institution:          NOAA Atlantic Oceanographic and Meteorological Labo...
+    acknowledgement:      Lumpkin, Rick; Centurioni, Luca (2019). NOAA Global...
+    summary:              Global Drifter Program six-hourly data
+    doi:                  10.25921/7ntx-z961
+
+
+
+
+

See Also#

+

gdp1h()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.glad.html b/_autosummary/clouddrift.datasets.glad.html new file mode 100644 index 00000000..a806b836 --- /dev/null +++ b/_autosummary/clouddrift.datasets.glad.html @@ -0,0 +1,621 @@ + + + + + + + + + + + clouddrift.datasets.glad — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.glad

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.glad#

+
+
+clouddrift.datasets.glad(decode_times: bool = True) Dataset[source]#
+

Returns the Grand LAgrangian Deployment (GLAD) dataset as a ragged array +Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access.

+

The upstream data is available at https://doi.org/10.7266/N7VD6WC8.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

GLAD dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import glad
+>>> ds = glad()
+>>> ds
+<xarray.Dataset>
+Dimensions:         (obs: 1602883, traj: 297)
+Coordinates:
+  time            (obs) datetime64[ns] ...
+  id              (traj) object ...
+Data variables:
+  latitude        (obs) float32 ...
+  longitude       (obs) float32 ...
+  position_error  (obs) float32 ...
+  u               (obs) float32 ...
+  v               (obs) float32 ...
+  velocity_error  (obs) float32 ...
+  rowsize         (traj) int64 ...
+Attributes:
+  title:        GLAD experiment CODE-style drifter trajectories (low-pass f...
+  institution:  Consortium for Advanced Research on Transport of Hydrocarbo...
+  source:       CODE-style drifters
+  history:      Downloaded from https://data.gulfresearchinitiative.org/dat...
+  references:   Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter t...
+
+
+
+
+

Reference#

+

Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012. Distributed by: Gulf of Mexico Research Initiative Information and Data Cooperative (GRIIDC), Harte Research Institute, Texas A&M University–Corpus Christi. doi:10.7266/N7VD6WC8

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.html b/_autosummary/clouddrift.datasets.html new file mode 100644 index 00000000..5e1b263a --- /dev/null +++ b/_autosummary/clouddrift.datasets.html @@ -0,0 +1,1160 @@ + + + + + + + + + + + clouddrift.datasets — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets

+ +
+ +
+
+ + + + +
+ +
+

clouddrift.datasets#

+

This module provides functions to easily access ragged array datasets. If the datasets are +not accessed via cloud storage platforms or are not found on the local filesystem, +they will be downloaded from their upstream repositories and stored for later access +(~/.clouddrift for UNIX-based systems).

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

andro([decode_times])

Returns the ANDRO as a ragged array Xarray dataset.

gdp1h([decode_times])

Returns the latest version of the NOAA Global Drifter Program (GDP) hourly dataset as a ragged array Xarray dataset.

gdp6h([decode_times])

Returns the NOAA Global Drifter Program (GDP) 6-hourly dataset as a ragged array Xarray dataset.

glad([decode_times])

Returns the Grand LAgrangian Deployment (GLAD) dataset as a ragged array Xarray dataset.

mosaic([decode_times])

Returns the MOSAiC sea-ice drift dataset as a ragged array Xarray dataset.

spotters([decode_times])

Returns the Sofar Ocean Spotter drifters ragged array dataset as an Xarray dataset.

subsurface_floats([decode_times])

Returns the subsurface floats dataset as a ragged array Xarray dataset.

yomaha([decode_times])

Returns the YoMaHa dataset as a ragged array Xarray dataset.

+
+
+clouddrift.datasets.andro(decode_times: bool = True) Dataset[source]#
+

Returns the ANDRO as a ragged array Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access. The upstream +data is available at https://www.seanoe.org/data/00360/47077/.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

ANDRO dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import andro
+>>> ds = andro()
+>>> ds
+<xarray.Dataset>
+Dimensions:     (obs: 1360753, traj: 9996)
+Coordinates:
+    time_d      (obs) datetime64[ns] ...
+    time_s      (obs) datetime64[ns] ...
+    time_lp     (obs) datetime64[ns] ...
+    time_lc     (obs) datetime64[ns] ...
+    id          (traj) int64 ...
+Dimensions without coordinates: obs, traj
+Data variables: (12/33)
+    lon_d       (obs) float64 ...
+    lat_d       (obs) float64 ...
+    pres_d      (obs) float32 ...
+    temp_d      (obs) float32 ...
+    sal_d       (obs) float32 ...
+    ve_d        (obs) float32 ...
+    ...          ...
+    lon_lc      (obs) float64 ...
+    lat_lc      (obs) float64 ...
+    surf_fix    (obs) int64 ...
+    cycle       (obs) int64 ...
+    profile_id  (obs) float32 ...
+    rowsize     (traj) int64 ...
+Attributes:
+    title:           ANDRO: An Argo-based deep displacement dataset
+    history:         2022-03-04
+    date_created:    2023-12-08T00:52:00.937120
+    publisher_name:  SEANOE (SEA scieNtific Open data Edition)
+    publisher_url:   https://www.seanoe.org/data/00360/47077/
+    license:         freely available
+
+
+
+
+

Reference#

+

Ollitrault Michel, Rannou Philippe, Brion Emilie, Cabanes Cecile, Piron Anne, Reverdin Gilles, +Kolodziejczyk Nicolas (2022). ANDRO: An Argo-based deep displacement dataset. +SEANOE. https://doi.org/10.17882/47077

+
+
+ +
+
+clouddrift.datasets.gdp1h(decode_times: bool = True) Dataset[source]#
+

Returns the latest version of the NOAA Global Drifter Program (GDP) hourly +dataset as a ragged array Xarray dataset.

+

The data is accessed from zarr archive hosted on a public AWS S3 bucket accessible at +https://registry.opendata.aws/noaa-oar-hourly-gdp/. Original data source from NOAA NCEI +is https://doi.org/10.25921/x46c-3620).

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

Hourly GDP dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import gdp1h
+>>> ds = gdp1h()
+>>> ds
+<xarray.Dataset>
+Dimensions:                (traj: 19396, obs: 197214787)
+Coordinates:
+    id                     (traj) int64 ...
+    time                   (obs) datetime64[ns] ...
+Dimensions without coordinates: traj, obs
+Data variables: (12/60)
+    BuoyTypeManufacturer   (traj) |S20 ...
+    BuoyTypeSensorArray    (traj) |S20 ...
+    CurrentProgram         (traj) float32 ...
+    DeployingCountry       (traj) |S20 ...
+    DeployingShip          (traj) |S20 ...
+    DeploymentComments     (traj) |S20 ...
+    ...                     ...
+    start_lat              (traj) float32 ...
+    start_lon              (traj) float32 ...
+    typebuoy               (traj) |S10 ...
+    typedeath              (traj) int8 ...
+    ve                     (obs) float32 ...
+    vn                     (obs) float32 ...
+Attributes: (12/16)
+    Conventions:       CF-1.6
+    acknowledgement:   Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurio...
+    contributor_name:  NOAA Global Drifter Program
+    contributor_role:  Data Acquisition Center
+    date_created:      2023-09-08T17:05:12.130123
+    doi:               10.25921/x46c-3620
+    ...                ...
+    processing_level:  Level 2 QC by GDP drifter DAC
+    publisher_email:   aoml.dftr@noaa.gov
+    publisher_name:    GDP Drifter DAC
+    publisher_url:     https://www.aoml.noaa.gov/phod/gdp
+    summary:           Global Drifter Program hourly data
+    title:             Global Drifter Program hourly drifting buoy collection
+
+
+
+
+

See Also#

+

gdp6h()

+
+
+ +
+
+clouddrift.datasets.gdp6h(decode_times: bool = True) Dataset[source]#
+

Returns the NOAA Global Drifter Program (GDP) 6-hourly dataset as a ragged array +Xarray dataset.

+

The data is accessed from a public HTTPS server at NOAA’s Atlantic +Oceanographic and Meteorological Laboratory (AOML) accessible at +https://www.aoml.noaa.gov/phod/gdp/index.php. It should be noted that the data loading +method is platform dependent. Linux and Darwin (macOS) machines lazy load the datasets leveraging the +byte-range feature of the netCDF-c library (dataset loading engine used by xarray). +Windows machines download the entire dataset into a memory buffer which is then passed +to xarray.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

6-hourly GDP dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import gdp6h
+>>> ds = gdp6h()
+>>> ds
+<xarray.Dataset>
+Dimensions:                (traj: 27647, obs: 46535470)
+Coordinates:
+    ids                    (obs) int64 7702204 7702204 ... 300234061198840
+    time                   (obs) float64 2.879e+08 2.879e+08 ... 1.697e+09
+Dimensions without coordinates: traj, obs
+Data variables: (12/50)
+    ID                     (traj) int64 7702204 7702201 ... 300234061198840
+    rowsize                (traj) int32 92 1747 1943 1385 1819 ... 54 53 51 28
+    WMO                    (traj) int32 0 0 0 0 ... 6203890 6203888 4101885
+    expno                  (traj) int32 40 40 40 40 ... 31412 21421 21421 31412
+    deploy_date            (traj) float32 2.878e+08 2.878e+08 ... 1.696e+09 nan
+    deploy_lat             (traj) float32 -7.798 -4.9 -3.18 ... 9.9 11.9 nan
+    ...                     ...
+    vn                     (obs) float32 nan 0.1056 0.04974 ... 0.7384 nan
+    temp                   (obs) float32 28.35 28.3 nan ... 29.08 28.97 28.92
+    err_lat                (obs) float32 0.009737 0.007097 ... 0.001659 0.001687
+    err_lon                (obs) float32 0.00614 0.004583 ... 0.002471 0.002545
+    err_temp               (obs) float32 0.08666 0.08757 ... 0.03665 0.03665
+    drogue_status          (obs) bool False False False False ... True True True
+Attributes: (12/18)
+    title:                Global Drifter Program drifting buoy collection
+    history:              version September 2023. Metadata from dirall.dat an...
+    Conventions:          CF-1.6
+    time_coverage_start:  1979-02-15:00:00:00Z
+    time_coverage_end:    2023-10-18:18:00:00Z
+    date_created:         2023-12-22T17:50:22.242943
+    ...                   ...
+    contributor_name:     NOAA Global Drifter Program
+    contributor_role:     Data Acquisition Center
+    institution:          NOAA Atlantic Oceanographic and Meteorological Labo...
+    acknowledgement:      Lumpkin, Rick; Centurioni, Luca (2019). NOAA Global...
+    summary:              Global Drifter Program six-hourly data
+    doi:                  10.25921/7ntx-z961
+
+
+
+
+

See Also#

+

gdp1h()

+
+
+ +
+
+clouddrift.datasets.glad(decode_times: bool = True) Dataset[source]#
+

Returns the Grand LAgrangian Deployment (GLAD) dataset as a ragged array +Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access.

+

The upstream data is available at https://doi.org/10.7266/N7VD6WC8.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

GLAD dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import glad
+>>> ds = glad()
+>>> ds
+<xarray.Dataset>
+Dimensions:         (obs: 1602883, traj: 297)
+Coordinates:
+  time            (obs) datetime64[ns] ...
+  id              (traj) object ...
+Data variables:
+  latitude        (obs) float32 ...
+  longitude       (obs) float32 ...
+  position_error  (obs) float32 ...
+  u               (obs) float32 ...
+  v               (obs) float32 ...
+  velocity_error  (obs) float32 ...
+  rowsize         (traj) int64 ...
+Attributes:
+  title:        GLAD experiment CODE-style drifter trajectories (low-pass f...
+  institution:  Consortium for Advanced Research on Transport of Hydrocarbo...
+  source:       CODE-style drifters
+  history:      Downloaded from https://data.gulfresearchinitiative.org/dat...
+  references:   Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter t...
+
+
+
+
+

Reference#

+

Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012. Distributed by: Gulf of Mexico Research Initiative Information and Data Cooperative (GRIIDC), Harte Research Institute, Texas A&M University–Corpus Christi. doi:10.7266/N7VD6WC8

+
+
+ +
+
+clouddrift.datasets.mosaic(decode_times: bool = True) Dataset[source]#
+

Returns the MOSAiC sea-ice drift dataset as a ragged array Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access.

+

The upstream data is available at https://arcticdata.io/catalog/view/doi:10.18739/A2KP7TS83.

+
+

Reference#

+

Angela Bliss, Jennifer Hutchings, Philip Anderson, Philipp Anhaus, +Hans Jakob Belter, Jørgen Berge, Vladimir Bessonov, Bin Cheng, Sylvia Cole, +Dave Costa, Finlo Cottier, Christopher J Cox, Pedro R De La Torre, Dmitry V Divine, +Gilbert Emzivat, Ying-Chih Fang, Steven Fons, Michael Gallagher, Maxime Geoffrey, +Mats A Granskog, … Guangyu Zuo. (2022). Sea ice drift tracks from the Distributed +Network of autonomous buoys deployed during the Multidisciplinary drifting Observatory +for the Study of Arctic Climate (MOSAiC) expedition 2019 - 2021. Arctic Data Center. +doi:10.18739/A2KP7TS83.

+
+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

MOSAiC sea-ice drift dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import mosaic
+>>> ds = mosaic()
+>>> ds
+<xarray.Dataset>
+Dimensions:                     (obs: 1926226, traj: 216)
+Coordinates:
+    time                        (obs) datetime64[ns] ...
+    id                          (traj) object ...
+Dimensions without coordinates: obs, traj
+Data variables: (12/19)
+    latitude                    (obs) float64 ...
+    longitude                   (obs) float64 ...
+    Deployment Leg              (traj) int64 ...
+    DN Station ID               (traj) object ...
+    IMEI                        (traj) object ...
+    Deployment Date             (traj) datetime64[ns] ...
+    ...                          ...
+    Buoy Type                   (traj) object ...
+    Manufacturer                (traj) object ...
+    Model                       (traj) object ...
+    PI                          (traj) object ...
+    Data Authors                (traj) object ...
+    rowsize                     (traj) int64 ...
+
+
+
+
+ +
+
+clouddrift.datasets.spotters(decode_times: bool = True) Dataset[source]#
+

Returns the Sofar Ocean Spotter drifters ragged array dataset as an Xarray dataset.

+

The data is accessed from a zarr archive hosted on a public AWS S3 bucket accessible +at https://sofar-spotter-archive.s3.amazonaws.com/spotter_data_bulk_zarr.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

Sofar ocean floats dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import spotters
+>>> ds = spotters()
+>>> ds
+<xarray.Dataset>
+Dimensions:                (index: 6390651, trajectory: 871)
+Coordinates:
+    time                   (index) datetime64[ns] ...
+  * trajectory             (trajectory) object 'SPOT-010001' ... 'SPOT-1975'
+Dimensions without coordinates: index
+Data variables:
+    latitude               (index) float64 ...
+    longitude              (index) float64 ...
+    meanDirection          (index) float64 ...
+    meanDirectionalSpread  (index) float64 ...
+    meanPeriod             (index) float64 ...
+    peakDirection          (index) float64 ...
+    peakDirectionalSpread  (index) float64 ...
+    peakPeriod             (index) float64 ...
+    rowsize                (trajectory) int64 ...
+    significantWaveHeight  (index) float64 ...
+Attributes:
+    author:         Isabel A. Houghton
+    creation_date:  2023-10-18 00:43:55.333537
+    email:          isabel.houghton@sofarocean.com
+    institution:    Sofar Ocean
+    references:     https://content.sofarocean.com/hubfs/Spotter%20product%20...
+    source:         Spotter wave buoy
+    title:          Sofar Spotter Data Archive - Bulk Wave Parameters
+
+
+
+
+ +
+
+clouddrift.datasets.subsurface_floats(decode_times: bool = True) Dataset[source]#
+

Returns the subsurface floats dataset as a ragged array Xarray dataset.

+

The data is accessed from a public HTTPS server at NOAA’s Atlantic +Oceanographic and Meteorological Laboratory (AOML) accessible at +https://www.aoml.noaa.gov/phod/gdp/index.php.

+

The upstream data is available at +https://www.aoml.noaa.gov/phod/float_traj/files/allFloats_12122017.mat.

+

This dataset of subsurface float observations was compiled by the WOCE Subsurface +Float Data Assembly Center (WFDAC) in Woods Hole maintained by Andree Ramsey and +Heather Furey and copied to NOAA/AOML in October 2014 (version 1) and in December +2017 (version 2). Subsequent updates will be included as additional appropriate +float data, quality controlled by the appropriate principal investigators, is +submitted for inclusion.

+

Note that these observations are collected by ALACE/RAFOS/Eurofloat-style +acoustically-tracked, neutrally-buoyant subsurface floats which collect data while +drifting beneath the ocean surface. These data are the result of the effort and +resources of many individuals and institutions. You are encouraged to acknowledge +the work of the data originators and Data Centers in publications arising from use +of these data.

+

The float data were originally divided by project at the WFDAC. Here they have been +compiled in a single Matlab data set. See here for more information on the variables +contained in these files.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

Subsurface floats dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import subsurface_floats
+>>> ds = subsurface_floats()
+>>> ds
+<xarray.Dataset>
+Dimensions:   (traj: 2193, obs: 1402840)
+Coordinates:
+    id        (traj) uint16 ...
+    time      (obs) datetime64[ns] ...
+Dimensions without coordinates: traj, obs
+Data variables: (12/13)
+    expList   (traj) object ...
+    expName   (traj) object ...
+    expOrg    (traj) object ...
+    expPI     (traj) object ...
+    indexExp  (traj) uint8 ...
+    fltType   (traj) object ...
+    ...        ...
+    lon       (obs) float64 ...
+    lat       (obs) float64 ...
+    pres      (obs) float64 ...
+    temp      (obs) float64 ...
+    ve        (obs) float64 ...
+    vn        (obs) float64 ...
+Attributes:
+    title:            Subsurface float trajectories dataset
+    history:          December 2017 (version 2)
+    date_created:     2023-11-14T22:30:38.831656
+    publisher_name:   WOCE Subsurface Float Data Assembly Center and NOAA AOML
+    publisher_url:    https://www.aoml.noaa.gov/phod/float_traj/data.php
+    license:          freely available
+    acknowledgement:  Maintained by Andree Ramsey and Heather Furey from the ...
+
+
+
+
+

References#

+

WOCE Subsurface Float Data Assembly Center (WFDAC) https://www.aoml.noaa.gov/phod/float_traj/index.php

+
+
+ +
+
+clouddrift.datasets.yomaha(decode_times: bool = True) Dataset[source]#
+

Returns the YoMaHa dataset as a ragged array Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access. The upstream +data is available at http://apdrc.soest.hawaii.edu/projects/yomaha/.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

YoMaHa’07 dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import yomaha
+>>> ds = yomaha()
+>>> ds
+<xarray.Dataset>
+Dimensions:     (obs: 1926743, traj: 12196)
+Coordinates:
+    time_d      (obs) datetime64[ns] ...
+    time_s      (obs) datetime64[ns] ...
+    time_lp     (obs) datetime64[ns] ...
+    time_lc     (obs) datetime64[ns] ...
+    id          (traj) int64 ...
+Dimensions without coordinates: obs, traj
+Data variables: (12/27)
+    lon_d       (obs) float64 ...
+    lat_d       (obs) float64 ...
+    pres_d      (obs) float32 ...
+    ve_d        (obs) float32 ...
+    vn_d        (obs) float32 ...
+    err_ve_d    (obs) float32 ...
+    ...          ...
+    cycle       (obs) int64 ...
+    time_inv    (obs) int64 ...
+    rowsize     (traj) int64 ...
+    wmo_id      (traj) int64 ...
+    dac_id      (traj) int64 ...
+    float_type  (traj) int64 ...
+Attributes:
+    title:           YoMaHa'07: Velocity data assessed from trajectories of A...
+    history:         Dataset updated on Tue Jun 28 03:14:34 HST 2022
+    date_created:    2023-12-08T00:52:08.478075
+    publisher_name:  Asia-Pacific Data Research Center
+    publisher_url:   http://apdrc.soest.hawaii.edu/index.php
+    license:         Creative Commons Attribution 4.0 International License..
+
+
+
+
+

Reference#

+

Lebedev, K. V., Yoshinari, H., Maximenko, N. A., & Hacker, P. W. (2007). Velocity data +assessed from trajectories of Argo floats at parking level and at the sea +surface. IPRC Technical Note, 4(2), 1-16.

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.mosaic.html b/_autosummary/clouddrift.datasets.mosaic.html new file mode 100644 index 00000000..b6fa52f3 --- /dev/null +++ b/_autosummary/clouddrift.datasets.mosaic.html @@ -0,0 +1,628 @@ + + + + + + + + + + + clouddrift.datasets.mosaic — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.mosaic

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.mosaic#

+
+
+clouddrift.datasets.mosaic(decode_times: bool = True) Dataset[source]#
+

Returns the MOSAiC sea-ice drift dataset as a ragged array Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access.

+

The upstream data is available at https://arcticdata.io/catalog/view/doi:10.18739/A2KP7TS83.

+
+

Reference#

+

Angela Bliss, Jennifer Hutchings, Philip Anderson, Philipp Anhaus, +Hans Jakob Belter, Jørgen Berge, Vladimir Bessonov, Bin Cheng, Sylvia Cole, +Dave Costa, Finlo Cottier, Christopher J Cox, Pedro R De La Torre, Dmitry V Divine, +Gilbert Emzivat, Ying-Chih Fang, Steven Fons, Michael Gallagher, Maxime Geoffrey, +Mats A Granskog, … Guangyu Zuo. (2022). Sea ice drift tracks from the Distributed +Network of autonomous buoys deployed during the Multidisciplinary drifting Observatory +for the Study of Arctic Climate (MOSAiC) expedition 2019 - 2021. Arctic Data Center. +doi:10.18739/A2KP7TS83.

+
+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

MOSAiC sea-ice drift dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import mosaic
+>>> ds = mosaic()
+>>> ds
+<xarray.Dataset>
+Dimensions:                     (obs: 1926226, traj: 216)
+Coordinates:
+    time                        (obs) datetime64[ns] ...
+    id                          (traj) object ...
+Dimensions without coordinates: obs, traj
+Data variables: (12/19)
+    latitude                    (obs) float64 ...
+    longitude                   (obs) float64 ...
+    Deployment Leg              (traj) int64 ...
+    DN Station ID               (traj) object ...
+    IMEI                        (traj) object ...
+    Deployment Date             (traj) datetime64[ns] ...
+    ...                          ...
+    Buoy Type                   (traj) object ...
+    Manufacturer                (traj) object ...
+    Model                       (traj) object ...
+    PI                          (traj) object ...
+    Data Authors                (traj) object ...
+    rowsize                     (traj) int64 ...
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.spotters.html b/_autosummary/clouddrift.datasets.spotters.html new file mode 100644 index 00000000..31c41a70 --- /dev/null +++ b/_autosummary/clouddrift.datasets.spotters.html @@ -0,0 +1,620 @@ + + + + + + + + + + + clouddrift.datasets.spotters — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.spotters

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.spotters#

+
+
+clouddrift.datasets.spotters(decode_times: bool = True) Dataset[source]#
+

Returns the Sofar Ocean Spotter drifters ragged array dataset as an Xarray dataset.

+

The data is accessed from a zarr archive hosted on a public AWS S3 bucket accessible +at https://sofar-spotter-archive.s3.amazonaws.com/spotter_data_bulk_zarr.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

Sofar ocean floats dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import spotters
+>>> ds = spotters()
+>>> ds
+<xarray.Dataset>
+Dimensions:                (index: 6390651, trajectory: 871)
+Coordinates:
+    time                   (index) datetime64[ns] ...
+  * trajectory             (trajectory) object 'SPOT-010001' ... 'SPOT-1975'
+Dimensions without coordinates: index
+Data variables:
+    latitude               (index) float64 ...
+    longitude              (index) float64 ...
+    meanDirection          (index) float64 ...
+    meanDirectionalSpread  (index) float64 ...
+    meanPeriod             (index) float64 ...
+    peakDirection          (index) float64 ...
+    peakDirectionalSpread  (index) float64 ...
+    peakPeriod             (index) float64 ...
+    rowsize                (trajectory) int64 ...
+    significantWaveHeight  (index) float64 ...
+Attributes:
+    author:         Isabel A. Houghton
+    creation_date:  2023-10-18 00:43:55.333537
+    email:          isabel.houghton@sofarocean.com
+    institution:    Sofar Ocean
+    references:     https://content.sofarocean.com/hubfs/Spotter%20product%20...
+    source:         Spotter wave buoy
+    title:          Sofar Spotter Data Archive - Bulk Wave Parameters
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.subsurface_floats.html b/_autosummary/clouddrift.datasets.subsurface_floats.html new file mode 100644 index 00000000..7f7c60bd --- /dev/null +++ b/_autosummary/clouddrift.datasets.subsurface_floats.html @@ -0,0 +1,645 @@ + + + + + + + + + + + clouddrift.datasets.subsurface_floats — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.subsurface_floats

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.subsurface_floats#

+
+
+clouddrift.datasets.subsurface_floats(decode_times: bool = True) Dataset[source]#
+

Returns the subsurface floats dataset as a ragged array Xarray dataset.

+

The data is accessed from a public HTTPS server at NOAA’s Atlantic +Oceanographic and Meteorological Laboratory (AOML) accessible at +https://www.aoml.noaa.gov/phod/gdp/index.php.

+

The upstream data is available at +https://www.aoml.noaa.gov/phod/float_traj/files/allFloats_12122017.mat.

+

This dataset of subsurface float observations was compiled by the WOCE Subsurface +Float Data Assembly Center (WFDAC) in Woods Hole maintained by Andree Ramsey and +Heather Furey and copied to NOAA/AOML in October 2014 (version 1) and in December +2017 (version 2). Subsequent updates will be included as additional appropriate +float data, quality controlled by the appropriate principal investigators, is +submitted for inclusion.

+

Note that these observations are collected by ALACE/RAFOS/Eurofloat-style +acoustically-tracked, neutrally-buoyant subsurface floats which collect data while +drifting beneath the ocean surface. These data are the result of the effort and +resources of many individuals and institutions. You are encouraged to acknowledge +the work of the data originators and Data Centers in publications arising from use +of these data.

+

The float data were originally divided by project at the WFDAC. Here they have been +compiled in a single Matlab data set. See here for more information on the variables +contained in these files.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

Subsurface floats dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import subsurface_floats
+>>> ds = subsurface_floats()
+>>> ds
+<xarray.Dataset>
+Dimensions:   (traj: 2193, obs: 1402840)
+Coordinates:
+    id        (traj) uint16 ...
+    time      (obs) datetime64[ns] ...
+Dimensions without coordinates: traj, obs
+Data variables: (12/13)
+    expList   (traj) object ...
+    expName   (traj) object ...
+    expOrg    (traj) object ...
+    expPI     (traj) object ...
+    indexExp  (traj) uint8 ...
+    fltType   (traj) object ...
+    ...        ...
+    lon       (obs) float64 ...
+    lat       (obs) float64 ...
+    pres      (obs) float64 ...
+    temp      (obs) float64 ...
+    ve        (obs) float64 ...
+    vn        (obs) float64 ...
+Attributes:
+    title:            Subsurface float trajectories dataset
+    history:          December 2017 (version 2)
+    date_created:     2023-11-14T22:30:38.831656
+    publisher_name:   WOCE Subsurface Float Data Assembly Center and NOAA AOML
+    publisher_url:    https://www.aoml.noaa.gov/phod/float_traj/data.php
+    license:          freely available
+    acknowledgement:  Maintained by Andree Ramsey and Heather Furey from the ...
+
+
+
+
+

References#

+

WOCE Subsurface Float Data Assembly Center (WFDAC) https://www.aoml.noaa.gov/phod/float_traj/index.php

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.datasets.yomaha.html b/_autosummary/clouddrift.datasets.yomaha.html new file mode 100644 index 00000000..4bdda2e2 --- /dev/null +++ b/_autosummary/clouddrift.datasets.yomaha.html @@ -0,0 +1,633 @@ + + + + + + + + + + + clouddrift.datasets.yomaha — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.datasets.yomaha

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.datasets.yomaha#

+
+
+clouddrift.datasets.yomaha(decode_times: bool = True) Dataset[source]#
+

Returns the YoMaHa dataset as a ragged array Xarray dataset.

+

The function will first look for the ragged-array dataset on the local +filesystem. If it is not found, the dataset will be downloaded using the +corresponding adapter function and stored for later access. The upstream +data is available at http://apdrc.soest.hawaii.edu/projects/yomaha/.

+
+

Parameters#

+
+
decode_timesbool, optional

If True, decode the time coordinate into a datetime object. If False, the time +coordinate will be an int64 or float64 array of increments since the origin +time indicated in the units attribute. Default is True.

+
+
+
+
+

Returns#

+
+
xarray.Dataset

YoMaHa’07 dataset as a ragged array

+
+
+
+
+

Examples#

+
>>> from clouddrift.datasets import yomaha
+>>> ds = yomaha()
+>>> ds
+<xarray.Dataset>
+Dimensions:     (obs: 1926743, traj: 12196)
+Coordinates:
+    time_d      (obs) datetime64[ns] ...
+    time_s      (obs) datetime64[ns] ...
+    time_lp     (obs) datetime64[ns] ...
+    time_lc     (obs) datetime64[ns] ...
+    id          (traj) int64 ...
+Dimensions without coordinates: obs, traj
+Data variables: (12/27)
+    lon_d       (obs) float64 ...
+    lat_d       (obs) float64 ...
+    pres_d      (obs) float32 ...
+    ve_d        (obs) float32 ...
+    vn_d        (obs) float32 ...
+    err_ve_d    (obs) float32 ...
+    ...          ...
+    cycle       (obs) int64 ...
+    time_inv    (obs) int64 ...
+    rowsize     (traj) int64 ...
+    wmo_id      (traj) int64 ...
+    dac_id      (traj) int64 ...
+    float_type  (traj) int64 ...
+Attributes:
+    title:           YoMaHa'07: Velocity data assessed from trajectories of A...
+    history:         Dataset updated on Tue Jun 28 03:14:34 HST 2022
+    date_created:    2023-12-08T00:52:08.478075
+    publisher_name:  Asia-Pacific Data Research Center
+    publisher_url:   http://apdrc.soest.hawaii.edu/index.php
+    license:         Creative Commons Attribution 4.0 International License..
+
+
+
+
+

Reference#

+

Lebedev, K. V., Yoshinari, H., Maximenko, N. A., & Hacker, P. W. (2007). Velocity data +assessed from trajectories of Argo floats at parking level and at the sea +surface. IPRC Technical Note, 4(2), 1-16.

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.html b/_autosummary/clouddrift.kinematics.html new file mode 100644 index 00000000..3e229fb3 --- /dev/null +++ b/_autosummary/clouddrift.kinematics.html @@ -0,0 +1,1103 @@ + + + + + + + + + + + clouddrift.kinematics — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.kinematics#

+

Functions for kinematic computations.

+

Functions

+ + + + + + + + + + + + + + + + + + + + + +

inertial_oscillation_from_position(...[, ...])

Extract inertial oscillations from consecutive geographical positions.

kinetic_energy(u[, v])

Compute kinetic energy from zonal and meridional velocities.

position_from_velocity(u, v, time, x_origin, ...)

Compute positions from arrays of velocities and time and a pair of origin coordinates.

residual_position_from_displacement(...)

Return residual longitudes and latitudes along a trajectory on the spherical Earth after correcting for zonal and meridional displacements x and y in meters.

spin(u, v, time[, difference_scheme, time_axis])

Compute spin continuously from velocities and times.

velocity_from_position(x, y, time[, ...])

Compute velocity from arrays of positions and time.

+
+
+clouddrift.kinematics.inertial_oscillation_from_position(longitude: ndarray, latitude: ndarray, relative_bandwidth: float | None = None, wavelet_duration: float | None = None, time_step: float | None = 3600.0, relative_vorticity: float | ndarray | None = 0.0) ndarray[source]#
+

Extract inertial oscillations from consecutive geographical positions.

+

This function acts by performing a time-frequency analysis of horizontal displacements +with analytic Morse wavelets. It extracts the portion of the wavelet transform signal +that follows the inertial frequency (opposite of Coriolis frequency) as a function of time, +potentially shifted in frequency by a measure of relative vorticity. The result is a pair +of zonal and meridional relative displacements in meters.

+

This function is equivalent to a bandpass filtering of the horizontal displacements. The characteristics +of the filter are defined by the relative bandwidth of the wavelet transform or by the duration of the wavelet, +see the parameters below.

+
+

Parameters#

+
+
longitudearray-like

Longitude sequence. Unidimensional array input.

+
+
latitudearray-like

Latitude sequence. Unidimensional array input.

+
+
relative_bandwidthfloat, optional

Bandwidth of the frequency-domain equivalent filter for the extraction of the inertial +oscillations; a number less or equal to one which is a fraction of the inertial frequency. +A value of 0.1 leads to a bandpass filter equivalent of +/- 10 percent of the inertial frequency.

+
+
wavelet_durationfloat, optional

Duration of the wavelet, or inverse of the relative bandwidth, which can be passed instead of the +relative bandwidth.

+
+
time_stepfloat, optional

The constant time interval between data points in seconds. Default is 3600.

+
+
relative_vorticity: Optional, float or array-like

Relative vorticity adding to the local Coriolis frequency. If “f” is the Coriolis +frequency then “f” + relative_vorticity will be the effective Coriolis frequency as defined by Kunze (1985). +Positive values correspond to cyclonic vorticity, irrespectively of the latitudes of the data +points.

+
+
+
+
+

Returns#

+
+
xhatarray-like

Zonal relative displacement in meters from inertial oscillations.

+
+
yhatarray-like

Meridional relative displacement in meters from inertial oscillations.

+
+
+
+
+

Examples#

+

To extract displacements from inertial oscillations from sequences of longitude +and latitude values, equivalent to bandpass around 20 percent of the local inertial frequency:

+
>>> xhat, yhat = inertial_oscillation_from_position(longitude, latitude, relative_bandwidth=0.2)
+
+
+

The same result can be obtained by specifying the wavelet duration instead of the relative bandwidth:

+
>>> xhat, yhat = inertial_oscillation_from_position(longitude, latitude, wavelet_duration=5)
+
+
+

Next, the residual positions from the inertial displacements can be obtained with another function:

+
>>> residual_longitudes, residual_latitudes = residual_position_from_displacement(longitude, latitude, xhat, yhat)
+
+
+
+
+

Raises#

+
+
ValueError

If longitude and latitude arrays do not have the same shape. +If relative_vorticity is an array and does not have the same shape as longitude and latitude. +If time_step is not a float. +If both relative_bandwidth and wavelet_duration are specified. +If neither relative_bandwidth nor wavelet_duration are specified. +If the absolute value of relative_bandwidth is not in the range (0,1]. +If the wavelet duration is not greater than or equal to 1.

+
+
+
+
+

See Also#

+

residual_position_from_displacement(), wavelet_transform, morse_wavelet

+
+
+ +
+
+clouddrift.kinematics.kinetic_energy(u: float | list | ndarray | DataArray | Series, v: float | list | ndarray | DataArray | Series | None = None) float | ndarray | DataArray[source]#
+

Compute kinetic energy from zonal and meridional velocities.

+
+

Parameters#

+
+
ufloat or array-like

Zonal velocity.

+
+
vfloat or array-like, optional.

Meridional velocity. If not provided, the flow is assumed one-dimensional +in time and defined by u.

+
+
+
+
+

Returns#

+
+
kefloat or array-like

Kinetic energy.

+
+
+
+
+

Examples#

+
>>> import numpy as np
+>>> from clouddrift.kinematics import kinetic_energy
+>>> u = np.array([1., 2., 3., 4.])
+>>> v = np.array([1., 1., 1., 1.])
+>>> kinetic_energy(u, v)
+array([1. , 2.5, 5. , 8.5])
+
+
+
>>> u = np.reshape(np.tile([1., 2., 3., 4.], 2), (2, 4))
+>>> v = np.reshape(np.tile([1., 1., 1., 1.], 2), (2, 4))
+>>> kinetic_energy(u, v)
+array([[1. , 2.5, 5. , 8.5],
+       [1. , 2.5, 5. , 8.5]])
+
+
+
+
+ +
+
+clouddrift.kinematics.position_from_velocity(u: ndarray, v: ndarray, time: ndarray, x_origin: float, y_origin: float, coord_system: str | None = 'spherical', integration_scheme: str | None = 'forward', time_axis: int | None = -1) Tuple[ndarray, ndarray][source]#
+

Compute positions from arrays of velocities and time and a pair of origin +coordinates.

+

The units of the result are degrees if coord_system == "spherical" (default). +If coord_system == "cartesian", the units of the result are equal to the +units of the input velocities multiplied by the units of the input time. +For example, if the input velocities are in meters per second and the input +time is in seconds, the units of the result will be meters.

+

Integration scheme can take one of three values:

+
+
    +
  1. +
    “forward” (default): integration from x[i] to x[i+1] is performed

    using the velocity at x[i].

    +
    +
    +
  2. +
  3. +
    “backward”: integration from x[i] to x[i+1] is performed using the

    velocity at x[i+1].

    +
    +
    +
  4. +
  5. +
    “centered”: integration from x[i] to x[i+1] is performed using the

    arithmetic average of the velocities at x[i] and x[i+1]. Note that +this method introduces some error due to the averaging.

    +
    +
    +
  6. +
+
+

u, v, and time can be multi-dimensional arrays. If the time axis, along +which the finite differencing is performed, is not the last one (i.e. +x.shape[-1]), use the time_axis optional argument to specify along which +axis should the differencing be done. x, y, and time must have +the same shape.

+

This function will not do any special handling of longitude ranges. If the +integrated trajectory crosses the antimeridian (dateline) in either direction, the +longitude values will not be adjusted to stay in any specific range such +as [-180, 180] or [0, 360]. If you need your longitudes to be in a specific +range, recast the resulting longitude from this function using the function +clouddrift.sphere.recast_lon().

+
+

Parameters#

+
+
unp.ndarray

An array of eastward velocities.

+
+
vnp.ndarray

An array of northward velocities.

+
+
timenp.ndarray

An array of time values.

+
+
x_originfloat

Origin x-coordinate or origin longitude.

+
+
y_originfloat

Origin y-coordinate or origin latitude.

+
+
coord_systemstr, optional

The coordinate system of the input. Can be “spherical” or “cartesian”. +Default is “spherical”.

+
+
integration_schemestr, optional

The difference scheme to use for computing the position. Can be +“forward” or “backward”. Default is “forward”.

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
xnp.ndarray

An array of zonal displacements or longitudes.

+
+
ynp.ndarray

An array of meridional displacements or latitudes.

+
+
+
+
+

Examples#

+

Simple integration on a plane, using the forward scheme by default:

+
>>> import numpy as np
+>>> from clouddrift.analysis import position_from_velocity
+>>> u = np.array([1., 2., 3., 4.])
+>>> v = np.array([1., 1., 1., 1.])
+>>> time = np.array([0., 1., 2., 3.])
+>>> x, y = position_from_velocity(u, v, time, 0, 0, coord_system="cartesian")
+>>> x
+array([0., 1., 3., 6.])
+>>> y
+array([0., 1., 2., 3.])
+
+
+

As above, but using centered scheme:

+
>>> x, y = position_from_velocity(u, v, time, 0, 0, coord_system="cartesian", integration_scheme="centered")
+>>> x
+array([0., 1.5, 4., 7.5])
+>>> y
+array([0., 1., 2., 3.])
+
+
+

Simple integration on a sphere (default):

+
>>> u = np.array([1., 2., 3., 4.])
+>>> v = np.array([1., 1., 1., 1.])
+>>> time = np.array([0., 1., 2., 3.]) * 1e5
+>>> x, y = position_from_velocity(u, v, time, 0, 0)
+>>> x
+array([0.        , 0.89839411, 2.69584476, 5.39367518])
+>>> y
+array([0.        , 0.89828369, 1.79601515, 2.69201609])
+
+
+

Integrating across the antimeridian (dateline) by default does not +recast the resulting longitude:

+
>>> u = np.array([1., 1.])
+>>> v = np.array([0., 0.])
+>>> time = np.array([0, 1e5])
+>>> x, y = position_from_velocity(u, v, time, 179.5, 0)
+>>> x
+array([179.5      , 180.3983205])
+>>> y
+array([0., 0.])
+
+
+

Use the clouddrift.sphere.recast_lon function to recast the longitudes +to the desired range:

+
>>> from clouddrift.sphere import recast_lon
+>>> recast_lon(x, -180)
+array([ 179.5      , -179.6016795])
+
+
+
+
+

Raises#

+
+
ValueError

If u and v do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]). +If lengths of x, y, and time along time_axis are not equal. +If the input coordinate system is not “spherical” or “cartesian”. +If the input integration scheme is not “forward”, “backward”, or “centered”

+
+
+
+
+

See Also#

+

velocity_from_position()

+
+
+ +
+
+clouddrift.kinematics.residual_position_from_displacement(longitude: float | ndarray | DataArray, latitude: float | ndarray | DataArray, x: float | ndarray, y: float | ndarray) Tuple[float] | Tuple[ndarray][source]#
+

Return residual longitudes and latitudes along a trajectory on the spherical Earth +after correcting for zonal and meridional displacements x and y in meters.

+

This is applicable as an example when one seeks to correct a trajectory for +horizontal oscillations due to inertial motions, tides, etc.

+
+

Parameters#

+
+
longitudefloat or array-like

Longitude in degrees.

+
+
latitudefloat or array-like

Latitude in degrees.

+
+
xfloat or np.ndarray

Zonal displacement in meters.

+
+
yfloat or np.ndarray

Meridional displacement in meters.

+
+
+
+
+

Returns#

+
+
residual_longitudefloat or np.ndarray

Residual longitude after correcting for zonal displacement, in degrees.

+
+
residual_latitudefloat or np.ndarray

Residual latitude after correcting for meridional displacement, in degrees.

+
+
+
+
+

Examples#

+

Obtain the new geographical position for a displacement of 1/360-th of the +circumference of the Earth from original position (longitude,latitude) = (1,0):

+
>>> from clouddrift.sphere import EARTH_RADIUS_METERS
+>>> residual_position_from_displacement(1,0,2 * np.pi * EARTH_RADIUS_METERS / 360,0)
+(0.0, 0.0)
+
+
+
+
+ +
+
+clouddrift.kinematics.spin(u: ndarray, v: ndarray, time: ndarray, difference_scheme: str | None = 'forward', time_axis: int | None = -1) float | ndarray[source]#
+

Compute spin continuously from velocities and times.

+

Spin is traditionally (Sawford, 1999; Veneziani et al., 2005) defined as +(<u’dv’ - v’du’>) / (2 dt EKE) where u’ and v’ are eddy-perturbations of the +velocity field, EKE is eddy kinetic energy, dt is the time step, and du’ and +dv’ are velocity component increments during dt, and < > denotes ensemble +average.

+

To allow computing spin based on full velocity fields, this function does +not do any demeaning of the velocity fields. If you need the spin based on +velocity anomalies, ensure to demean the velocity fields before passing +them to this function. This function also returns instantaneous spin values, +so the rank of the result is not reduced relative to the input.

+

u, v, and time can be multi-dimensional arrays. If the time +axis, along which the finite differencing is performed, is not the last one +(i.e. u.shape[-1]), use the time_axis optional argument to specify along +which the spin should be calculated. u, v, and time must either have the +same shape, or time must be a 1-d array with the same length as +u.shape[time_axis].

+

Difference scheme can be one of three values:

+
+
    +
  1. “forward” (default): finite difference is evaluated as dx[i] = dx[i+1] - dx[i];

  2. +
  3. “backward”: finite difference is evaluated as dx[i] = dx[i] - dx[i-1];

  4. +
  5. “centered”: finite difference is evaluated as dx[i] = (dx[i+1] - dx[i-1]) / 2.

  6. +
+
+

Forward and backward schemes are effectively the same except that the +position at which the velocity is evaluated is shifted one element down in +the backward scheme relative to the forward scheme. In the case of a +forward or backward difference scheme, the last or first element of the +velocity, respectively, is extrapolated from its neighboring point. In the +case of a centered difference scheme, the start and end boundary points are +evaluated using the forward and backward difference scheme, respectively.

+
+

Parameters#

+
+
unp.ndarray

Zonal velocity

+
+
vnp.ndarray

Meridional velocity

+
+
timearray-like

Time

+
+
difference_schemestr, optional

Difference scheme to use; possible values are “forward”, “backward”, and “centered”.

+
+
time_axisint, optional

Axis along which the time varies (default is -1)

+
+
+
+
+

Returns#

+
+
sfloat or np.ndarray

Spin

+
+
+
+
+

Raises#

+
+
ValueError

If u and v do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]). +If lengths of u, v, and time along time_axis are not equal. +If difference_scheme is not “forward”, “backward”, or “centered”.

+
+
+
+
+

Examples#

+
>>> from clouddrift.kinematics import spin
+>>> import numpy as np
+>>> u = np.array([1., 2., -1., 4.])
+>>> v = np.array([1., 3., -2., 1.])
+>>> time = np.array([0., 1., 2., 3.])
+>>> spin(u, v, time)
+array([ 0.5       , -0.07692308,  1.4       ,  0.41176471])
+
+
+

Use difference_scheme to specify an alternative finite difference +scheme for the velocity differences:

+
>>> spin(u, v, time, difference_scheme="centered")
+array([0.5       , 0.        , 0.6       , 0.41176471])
+>>> spin(u, v, time, difference_scheme="backward")
+array([ 0.5       ,  0.07692308, -0.2       ,  0.41176471])
+
+
+
+
+

References#

+ +
+
+ +
+
+clouddrift.kinematics.velocity_from_position(x: ndarray, y: ndarray, time: ndarray, coord_system: str | None = 'spherical', difference_scheme: str | None = 'forward', time_axis: int | None = -1) Tuple[DataArray, DataArray][source]#
+

Compute velocity from arrays of positions and time.

+

x and y can be provided as longitude and latitude in degrees if +coord_system == “spherical” (default), or as easting and northing if +coord_system == “cartesian”.

+

The units of the result are meters per unit of time if +coord_system == “spherical”. For example, if the time is provided in the +units of seconds, the resulting velocity is in the units of meters per +second. Otherwise, if coord_system == “cartesian”, the units of the +resulting velocity correspond to the units of the input. For example, +if zonal and meridional displacements are in the units of kilometers and +time is in the units of hours, the resulting velocity is in the units of +kilometers per hour.

+

x, y, and time can be multi-dimensional arrays. If the time axis, along +which the finite differencing is performed, is not the last one (i.e. +x.shape[-1]), use the time_axis optional argument to specify along which +axis should the differencing be done. x, y, and time must have the same +shape.

+

Difference scheme can take one of three values:

+
    +
  1. “forward” (default): finite difference is evaluated as dx[i] = dx[i+1] - dx[i];

  2. +
  3. “backward”: finite difference is evaluated as dx[i] = dx[i] - dx[i-1];

  4. +
  5. “centered”: finite difference is evaluated as dx[i] = (dx[i+1] - dx[i-1]) / 2.

  6. +
+

Forward and backward schemes are effectively the same except that the +position at which the velocity is evaluated is shifted one element down in +the backward scheme relative to the forward scheme. In the case of a +forward or backward difference scheme, the last or first element of the +velocity, respectively, is extrapolated from its neighboring point. In the +case of a centered difference scheme, the start and end boundary points are +evaluated using the forward and backward difference scheme, respectively.

+
+

Parameters#

+
+
xarray_like

An N-d array of x-positions (longitude in degrees or zonal displacement in any unit)

+
+
yarray_like

An N-d array of y-positions (latitude in degrees or meridional displacement in any unit)

+
+
timearray_like

An N-d array of times as floating point values (in any unit)

+
+
coord_systemstr, optional

Coordinate system that x and y arrays are in; possible values are “spherical” (default) or “cartesian”.

+
+
difference_schemestr, optional

Difference scheme to use; possible values are “forward”, “backward”, and “centered”.

+
+
time_axisint, optional

Axis along which to differentiate (default is -1)

+
+
+
+
+

Returns#

+
+
unp.ndarray

Zonal velocity

+
+
vnp.ndarray

Meridional velocity

+
+
+
+
+

Raises#

+
+
ValueError

If x and y do not have the same shape. +If time_axis is outside of the valid range. +If lengths of x, y, and time along time_axis are not equal. +If coord_system is not “spherical” or “cartesian”. +If difference_scheme is not “forward”, “backward”, or “centered”.

+
+
+
+
+

Examples#

+

Simple integration on a sphere, using the forward scheme by default:

+
>>> import numpy as np
+>>> from clouddrift.kinematics import velocity_from_position
+>>> lon = np.array([0., 1., 3., 6.])
+>>> lat = np.array([0., 1., 2., 3.])
+>>> time = np.array([0., 1., 2., 3.]) * 1e5
+>>> u, v = velocity_from_position(lon, lat, time)
+>>> u
+array([1.11307541, 2.22513331, 3.33515501, 3.33515501])
+>>> v
+array([1.11324496, 1.11409224, 1.1167442 , 1.1167442 ])
+
+
+

Integration on a Cartesian plane, using the forward scheme by default:

+
>>> x = np.array([0., 1., 3., 6.])
+>>> y = np.array([0., 1., 2., 3.])
+>>> time = np.array([0., 1., 2., 3.])
+>>> u, v = velocity_from_position(x, y, time, coord_system="cartesian")
+>>> u
+array([1., 2., 3., 3.])
+>>> v
+array([1., 1., 1., 1.])
+
+
+
+
+

See Also#

+

position_from_velocity()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.html b/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.html new file mode 100644 index 00000000..bc2919cc --- /dev/null +++ b/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.html @@ -0,0 +1,642 @@ + + + + + + + + + + + clouddrift.kinematics.inertial_oscillation_from_position — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.kinematics.inertial_oscillation_from_position

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.kinematics.inertial_oscillation_from_position#

+
+
+clouddrift.kinematics.inertial_oscillation_from_position(longitude: ndarray, latitude: ndarray, relative_bandwidth: float | None = None, wavelet_duration: float | None = None, time_step: float | None = 3600.0, relative_vorticity: float | ndarray | None = 0.0) ndarray[source]#
+

Extract inertial oscillations from consecutive geographical positions.

+

This function acts by performing a time-frequency analysis of horizontal displacements +with analytic Morse wavelets. It extracts the portion of the wavelet transform signal +that follows the inertial frequency (opposite of Coriolis frequency) as a function of time, +potentially shifted in frequency by a measure of relative vorticity. The result is a pair +of zonal and meridional relative displacements in meters.

+

This function is equivalent to a bandpass filtering of the horizontal displacements. The characteristics +of the filter are defined by the relative bandwidth of the wavelet transform or by the duration of the wavelet, +see the parameters below.

+
+

Parameters#

+
+
longitudearray-like

Longitude sequence. Unidimensional array input.

+
+
latitudearray-like

Latitude sequence. Unidimensional array input.

+
+
relative_bandwidthfloat, optional

Bandwidth of the frequency-domain equivalent filter for the extraction of the inertial +oscillations; a number less or equal to one which is a fraction of the inertial frequency. +A value of 0.1 leads to a bandpass filter equivalent of +/- 10 percent of the inertial frequency.

+
+
wavelet_durationfloat, optional

Duration of the wavelet, or inverse of the relative bandwidth, which can be passed instead of the +relative bandwidth.

+
+
time_stepfloat, optional

The constant time interval between data points in seconds. Default is 3600.

+
+
relative_vorticity: Optional, float or array-like

Relative vorticity adding to the local Coriolis frequency. If “f” is the Coriolis +frequency then “f” + relative_vorticity will be the effective Coriolis frequency as defined by Kunze (1985). +Positive values correspond to cyclonic vorticity, irrespectively of the latitudes of the data +points.

+
+
+
+
+

Returns#

+
+
xhatarray-like

Zonal relative displacement in meters from inertial oscillations.

+
+
yhatarray-like

Meridional relative displacement in meters from inertial oscillations.

+
+
+
+
+

Examples#

+

To extract displacements from inertial oscillations from sequences of longitude +and latitude values, equivalent to bandpass around 20 percent of the local inertial frequency:

+
>>> xhat, yhat = inertial_oscillation_from_position(longitude, latitude, relative_bandwidth=0.2)
+
+
+

The same result can be obtained by specifying the wavelet duration instead of the relative bandwidth:

+
>>> xhat, yhat = inertial_oscillation_from_position(longitude, latitude, wavelet_duration=5)
+
+
+

Next, the residual positions from the inertial displacements can be obtained with another function:

+
>>> residual_longitudes, residual_latitudes = residual_position_from_displacement(longitude, latitude, xhat, yhat)
+
+
+
+
+

Raises#

+
+
ValueError

If longitude and latitude arrays do not have the same shape. +If relative_vorticity is an array and does not have the same shape as longitude and latitude. +If time_step is not a float. +If both relative_bandwidth and wavelet_duration are specified. +If neither relative_bandwidth nor wavelet_duration are specified. +If the absolute value of relative_bandwidth is not in the range (0,1]. +If the wavelet duration is not greater than or equal to 1.

+
+
+
+
+

See Also#

+

residual_position_from_displacement(), wavelet_transform, morse_wavelet

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.kinetic_energy.html b/_autosummary/clouddrift.kinematics.kinetic_energy.html new file mode 100644 index 00000000..9e49e0f5 --- /dev/null +++ b/_autosummary/clouddrift.kinematics.kinetic_energy.html @@ -0,0 +1,604 @@ + + + + + + + + + + + clouddrift.kinematics.kinetic_energy — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.kinematics.kinetic_energy

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.kinematics.kinetic_energy#

+
+
+clouddrift.kinematics.kinetic_energy(u: float | list | ndarray | DataArray | Series, v: float | list | ndarray | DataArray | Series | None = None) float | ndarray | DataArray[source]#
+

Compute kinetic energy from zonal and meridional velocities.

+
+

Parameters#

+
+
ufloat or array-like

Zonal velocity.

+
+
vfloat or array-like, optional.

Meridional velocity. If not provided, the flow is assumed one-dimensional +in time and defined by u.

+
+
+
+
+

Returns#

+
+
kefloat or array-like

Kinetic energy.

+
+
+
+
+

Examples#

+
>>> import numpy as np
+>>> from clouddrift.kinematics import kinetic_energy
+>>> u = np.array([1., 2., 3., 4.])
+>>> v = np.array([1., 1., 1., 1.])
+>>> kinetic_energy(u, v)
+array([1. , 2.5, 5. , 8.5])
+
+
+
>>> u = np.reshape(np.tile([1., 2., 3., 4.], 2), (2, 4))
+>>> v = np.reshape(np.tile([1., 1., 1., 1.], 2), (2, 4))
+>>> kinetic_energy(u, v)
+array([[1. , 2.5, 5. , 8.5],
+       [1. , 2.5, 5. , 8.5]])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.position_from_velocity.html b/_autosummary/clouddrift.kinematics.position_from_velocity.html new file mode 100644 index 00000000..0827f015 --- /dev/null +++ b/_autosummary/clouddrift.kinematics.position_from_velocity.html @@ -0,0 +1,709 @@ + + + + + + + + + + + clouddrift.kinematics.position_from_velocity — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.kinematics.position_from_velocity

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.kinematics.position_from_velocity#

+
+
+clouddrift.kinematics.position_from_velocity(u: ndarray, v: ndarray, time: ndarray, x_origin: float, y_origin: float, coord_system: str | None = 'spherical', integration_scheme: str | None = 'forward', time_axis: int | None = -1) Tuple[ndarray, ndarray][source]#
+

Compute positions from arrays of velocities and time and a pair of origin +coordinates.

+

The units of the result are degrees if coord_system == "spherical" (default). +If coord_system == "cartesian", the units of the result are equal to the +units of the input velocities multiplied by the units of the input time. +For example, if the input velocities are in meters per second and the input +time is in seconds, the units of the result will be meters.

+

Integration scheme can take one of three values:

+
+
    +
  1. +
    “forward” (default): integration from x[i] to x[i+1] is performed

    using the velocity at x[i].

    +
    +
    +
  2. +
  3. +
    “backward”: integration from x[i] to x[i+1] is performed using the

    velocity at x[i+1].

    +
    +
    +
  4. +
  5. +
    “centered”: integration from x[i] to x[i+1] is performed using the

    arithmetic average of the velocities at x[i] and x[i+1]. Note that +this method introduces some error due to the averaging.

    +
    +
    +
  6. +
+
+

u, v, and time can be multi-dimensional arrays. If the time axis, along +which the finite differencing is performed, is not the last one (i.e. +x.shape[-1]), use the time_axis optional argument to specify along which +axis should the differencing be done. x, y, and time must have +the same shape.

+

This function will not do any special handling of longitude ranges. If the +integrated trajectory crosses the antimeridian (dateline) in either direction, the +longitude values will not be adjusted to stay in any specific range such +as [-180, 180] or [0, 360]. If you need your longitudes to be in a specific +range, recast the resulting longitude from this function using the function +clouddrift.sphere.recast_lon().

+
+

Parameters#

+
+
unp.ndarray

An array of eastward velocities.

+
+
vnp.ndarray

An array of northward velocities.

+
+
timenp.ndarray

An array of time values.

+
+
x_originfloat

Origin x-coordinate or origin longitude.

+
+
y_originfloat

Origin y-coordinate or origin latitude.

+
+
coord_systemstr, optional

The coordinate system of the input. Can be “spherical” or “cartesian”. +Default is “spherical”.

+
+
integration_schemestr, optional

The difference scheme to use for computing the position. Can be +“forward” or “backward”. Default is “forward”.

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
xnp.ndarray

An array of zonal displacements or longitudes.

+
+
ynp.ndarray

An array of meridional displacements or latitudes.

+
+
+
+
+

Examples#

+

Simple integration on a plane, using the forward scheme by default:

+
>>> import numpy as np
+>>> from clouddrift.analysis import position_from_velocity
+>>> u = np.array([1., 2., 3., 4.])
+>>> v = np.array([1., 1., 1., 1.])
+>>> time = np.array([0., 1., 2., 3.])
+>>> x, y = position_from_velocity(u, v, time, 0, 0, coord_system="cartesian")
+>>> x
+array([0., 1., 3., 6.])
+>>> y
+array([0., 1., 2., 3.])
+
+
+

As above, but using centered scheme:

+
>>> x, y = position_from_velocity(u, v, time, 0, 0, coord_system="cartesian", integration_scheme="centered")
+>>> x
+array([0., 1.5, 4., 7.5])
+>>> y
+array([0., 1., 2., 3.])
+
+
+

Simple integration on a sphere (default):

+
>>> u = np.array([1., 2., 3., 4.])
+>>> v = np.array([1., 1., 1., 1.])
+>>> time = np.array([0., 1., 2., 3.]) * 1e5
+>>> x, y = position_from_velocity(u, v, time, 0, 0)
+>>> x
+array([0.        , 0.89839411, 2.69584476, 5.39367518])
+>>> y
+array([0.        , 0.89828369, 1.79601515, 2.69201609])
+
+
+

Integrating across the antimeridian (dateline) by default does not +recast the resulting longitude:

+
>>> u = np.array([1., 1.])
+>>> v = np.array([0., 0.])
+>>> time = np.array([0, 1e5])
+>>> x, y = position_from_velocity(u, v, time, 179.5, 0)
+>>> x
+array([179.5      , 180.3983205])
+>>> y
+array([0., 0.])
+
+
+

Use the clouddrift.sphere.recast_lon function to recast the longitudes +to the desired range:

+
>>> from clouddrift.sphere import recast_lon
+>>> recast_lon(x, -180)
+array([ 179.5      , -179.6016795])
+
+
+
+
+

Raises#

+
+
ValueError

If u and v do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]). +If lengths of x, y, and time along time_axis are not equal. +If the input coordinate system is not “spherical” or “cartesian”. +If the input integration scheme is not “forward”, “backward”, or “centered”

+
+
+
+
+

See Also#

+

velocity_from_position()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.residual_position_from_displacement.html b/_autosummary/clouddrift.kinematics.residual_position_from_displacement.html new file mode 100644 index 00000000..4a2f95bc --- /dev/null +++ b/_autosummary/clouddrift.kinematics.residual_position_from_displacement.html @@ -0,0 +1,604 @@ + + + + + + + + + + + clouddrift.kinematics.residual_position_from_displacement — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.kinematics.residual_position_from_displacement

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.kinematics.residual_position_from_displacement#

+
+
+clouddrift.kinematics.residual_position_from_displacement(longitude: float | ndarray | DataArray, latitude: float | ndarray | DataArray, x: float | ndarray, y: float | ndarray) Tuple[float] | Tuple[ndarray][source]#
+

Return residual longitudes and latitudes along a trajectory on the spherical Earth +after correcting for zonal and meridional displacements x and y in meters.

+

This is applicable as an example when one seeks to correct a trajectory for +horizontal oscillations due to inertial motions, tides, etc.

+
+

Parameters#

+
+
longitudefloat or array-like

Longitude in degrees.

+
+
latitudefloat or array-like

Latitude in degrees.

+
+
xfloat or np.ndarray

Zonal displacement in meters.

+
+
yfloat or np.ndarray

Meridional displacement in meters.

+
+
+
+
+

Returns#

+
+
residual_longitudefloat or np.ndarray

Residual longitude after correcting for zonal displacement, in degrees.

+
+
residual_latitudefloat or np.ndarray

Residual latitude after correcting for meridional displacement, in degrees.

+
+
+
+
+

Examples#

+

Obtain the new geographical position for a displacement of 1/360-th of the +circumference of the Earth from original position (longitude,latitude) = (1,0):

+
>>> from clouddrift.sphere import EARTH_RADIUS_METERS
+>>> residual_position_from_displacement(1,0,2 * np.pi * EARTH_RADIUS_METERS / 360,0)
+(0.0, 0.0)
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.spin.html b/_autosummary/clouddrift.kinematics.spin.html new file mode 100644 index 00000000..9ba7bfdf --- /dev/null +++ b/_autosummary/clouddrift.kinematics.spin.html @@ -0,0 +1,659 @@ + + + + + + + + + + + clouddrift.kinematics.spin — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.kinematics.spin

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.kinematics.spin#

+
+
+clouddrift.kinematics.spin(u: ndarray, v: ndarray, time: ndarray, difference_scheme: str | None = 'forward', time_axis: int | None = -1) float | ndarray[source]#
+

Compute spin continuously from velocities and times.

+

Spin is traditionally (Sawford, 1999; Veneziani et al., 2005) defined as +(<u’dv’ - v’du’>) / (2 dt EKE) where u’ and v’ are eddy-perturbations of the +velocity field, EKE is eddy kinetic energy, dt is the time step, and du’ and +dv’ are velocity component increments during dt, and < > denotes ensemble +average.

+

To allow computing spin based on full velocity fields, this function does +not do any demeaning of the velocity fields. If you need the spin based on +velocity anomalies, ensure to demean the velocity fields before passing +them to this function. This function also returns instantaneous spin values, +so the rank of the result is not reduced relative to the input.

+

u, v, and time can be multi-dimensional arrays. If the time +axis, along which the finite differencing is performed, is not the last one +(i.e. u.shape[-1]), use the time_axis optional argument to specify along +which the spin should be calculated. u, v, and time must either have the +same shape, or time must be a 1-d array with the same length as +u.shape[time_axis].

+

Difference scheme can be one of three values:

+
+
    +
  1. “forward” (default): finite difference is evaluated as dx[i] = dx[i+1] - dx[i];

  2. +
  3. “backward”: finite difference is evaluated as dx[i] = dx[i] - dx[i-1];

  4. +
  5. “centered”: finite difference is evaluated as dx[i] = (dx[i+1] - dx[i-1]) / 2.

  6. +
+
+

Forward and backward schemes are effectively the same except that the +position at which the velocity is evaluated is shifted one element down in +the backward scheme relative to the forward scheme. In the case of a +forward or backward difference scheme, the last or first element of the +velocity, respectively, is extrapolated from its neighboring point. In the +case of a centered difference scheme, the start and end boundary points are +evaluated using the forward and backward difference scheme, respectively.

+
+

Parameters#

+
+
unp.ndarray

Zonal velocity

+
+
vnp.ndarray

Meridional velocity

+
+
timearray-like

Time

+
+
difference_schemestr, optional

Difference scheme to use; possible values are “forward”, “backward”, and “centered”.

+
+
time_axisint, optional

Axis along which the time varies (default is -1)

+
+
+
+
+

Returns#

+
+
sfloat or np.ndarray

Spin

+
+
+
+
+

Raises#

+
+
ValueError

If u and v do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]). +If lengths of u, v, and time along time_axis are not equal. +If difference_scheme is not “forward”, “backward”, or “centered”.

+
+
+
+
+

Examples#

+
>>> from clouddrift.kinematics import spin
+>>> import numpy as np
+>>> u = np.array([1., 2., -1., 4.])
+>>> v = np.array([1., 3., -2., 1.])
+>>> time = np.array([0., 1., 2., 3.])
+>>> spin(u, v, time)
+array([ 0.5       , -0.07692308,  1.4       ,  0.41176471])
+
+
+

Use difference_scheme to specify an alternative finite difference +scheme for the velocity differences:

+
>>> spin(u, v, time, difference_scheme="centered")
+array([0.5       , 0.        , 0.6       , 0.41176471])
+>>> spin(u, v, time, difference_scheme="backward")
+array([ 0.5       ,  0.07692308, -0.2       ,  0.41176471])
+
+
+
+
+

References#

+ +
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.kinematics.velocity_from_position.html b/_autosummary/clouddrift.kinematics.velocity_from_position.html new file mode 100644 index 00000000..c51e4192 --- /dev/null +++ b/_autosummary/clouddrift.kinematics.velocity_from_position.html @@ -0,0 +1,666 @@ + + + + + + + + + + + clouddrift.kinematics.velocity_from_position — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.kinematics.velocity_from_position

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.kinematics.velocity_from_position#

+
+
+clouddrift.kinematics.velocity_from_position(x: ndarray, y: ndarray, time: ndarray, coord_system: str | None = 'spherical', difference_scheme: str | None = 'forward', time_axis: int | None = -1) Tuple[DataArray, DataArray][source]#
+

Compute velocity from arrays of positions and time.

+

x and y can be provided as longitude and latitude in degrees if +coord_system == “spherical” (default), or as easting and northing if +coord_system == “cartesian”.

+

The units of the result are meters per unit of time if +coord_system == “spherical”. For example, if the time is provided in the +units of seconds, the resulting velocity is in the units of meters per +second. Otherwise, if coord_system == “cartesian”, the units of the +resulting velocity correspond to the units of the input. For example, +if zonal and meridional displacements are in the units of kilometers and +time is in the units of hours, the resulting velocity is in the units of +kilometers per hour.

+

x, y, and time can be multi-dimensional arrays. If the time axis, along +which the finite differencing is performed, is not the last one (i.e. +x.shape[-1]), use the time_axis optional argument to specify along which +axis should the differencing be done. x, y, and time must have the same +shape.

+

Difference scheme can take one of three values:

+
    +
  1. “forward” (default): finite difference is evaluated as dx[i] = dx[i+1] - dx[i];

  2. +
  3. “backward”: finite difference is evaluated as dx[i] = dx[i] - dx[i-1];

  4. +
  5. “centered”: finite difference is evaluated as dx[i] = (dx[i+1] - dx[i-1]) / 2.

  6. +
+

Forward and backward schemes are effectively the same except that the +position at which the velocity is evaluated is shifted one element down in +the backward scheme relative to the forward scheme. In the case of a +forward or backward difference scheme, the last or first element of the +velocity, respectively, is extrapolated from its neighboring point. In the +case of a centered difference scheme, the start and end boundary points are +evaluated using the forward and backward difference scheme, respectively.

+
+

Parameters#

+
+
xarray_like

An N-d array of x-positions (longitude in degrees or zonal displacement in any unit)

+
+
yarray_like

An N-d array of y-positions (latitude in degrees or meridional displacement in any unit)

+
+
timearray_like

An N-d array of times as floating point values (in any unit)

+
+
coord_systemstr, optional

Coordinate system that x and y arrays are in; possible values are “spherical” (default) or “cartesian”.

+
+
difference_schemestr, optional

Difference scheme to use; possible values are “forward”, “backward”, and “centered”.

+
+
time_axisint, optional

Axis along which to differentiate (default is -1)

+
+
+
+
+

Returns#

+
+
unp.ndarray

Zonal velocity

+
+
vnp.ndarray

Meridional velocity

+
+
+
+
+

Raises#

+
+
ValueError

If x and y do not have the same shape. +If time_axis is outside of the valid range. +If lengths of x, y, and time along time_axis are not equal. +If coord_system is not “spherical” or “cartesian”. +If difference_scheme is not “forward”, “backward”, or “centered”.

+
+
+
+
+

Examples#

+

Simple integration on a sphere, using the forward scheme by default:

+
>>> import numpy as np
+>>> from clouddrift.kinematics import velocity_from_position
+>>> lon = np.array([0., 1., 3., 6.])
+>>> lat = np.array([0., 1., 2., 3.])
+>>> time = np.array([0., 1., 2., 3.]) * 1e5
+>>> u, v = velocity_from_position(lon, lat, time)
+>>> u
+array([1.11307541, 2.22513331, 3.33515501, 3.33515501])
+>>> v
+array([1.11324496, 1.11409224, 1.1167442 , 1.1167442 ])
+
+
+

Integration on a Cartesian plane, using the forward scheme by default:

+
>>> x = np.array([0., 1., 3., 6.])
+>>> y = np.array([0., 1., 2., 3.])
+>>> time = np.array([0., 1., 2., 3.])
+>>> u, v = velocity_from_position(x, y, time, coord_system="cartesian")
+>>> u
+array([1., 2., 3., 3.])
+>>> v
+array([1., 1., 1., 1.])
+
+
+
+
+

See Also#

+

position_from_velocity()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.chance_pair.html b/_autosummary/clouddrift.pairs.chance_pair.html new file mode 100644 index 00000000..c54828ec --- /dev/null +++ b/_autosummary/clouddrift.pairs.chance_pair.html @@ -0,0 +1,651 @@ + + + + + + + + + + + clouddrift.pairs.chance_pair — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.pairs.chance_pair

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.pairs.chance_pair#

+
+
+clouddrift.pairs.chance_pair(lon1: list[float] | ndarray[float] | Series | DataArray, lat1: list[float] | ndarray[float] | Series | DataArray, lon2: list[float] | ndarray[float] | Series | DataArray, lat2: list[float] | ndarray[float] | Series | DataArray, time1: list[float] | ndarray[float] | Series | DataArray | None = None, time2: list[float] | ndarray[float] | Series | DataArray | None = None, space_distance: float | None = 0, time_distance: float | None = 0)[source]#
+

Given two sets of longitudes, latitudes, and times arrays, return in pairs +the indices of collocated data points that are within prescribed distances +in space and time. Also known as chance pairs.

+
+

Parameters#

+
+
lon1array_like

First array of longitudes in degrees.

+
+
lat1array_like

First array of latitudes in degrees.

+
+
lon2array_like

Second array of longitudes in degrees.

+
+
lat2array_like

Second array of latitudes in degrees.

+
+
time1array_like, optional

First array of times.

+
+
time2array_like, optional

Second array of times.

+
+
space_distancefloat, optional

Maximum allowable space distance in meters for a pair to qualify as chance pair. +If the separation is within this distance, the pair is considered to be +a chance pair. Default is 0, or no distance, i.e. the positions must be +exactly the same.

+
+
time_distancefloat, optional

Maximum allowable time distance for a pair to qualify as chance pair. +If a separation is within this distance, and a space distance +condition is satisfied, the pair is considered a chance pair. Default is +0, or no distance, i.e. the times must be exactly the same.

+
+
+
+
+

Returns#

+
+
indices1np.ndarray[int]

Indices within the first set of arrays that lead to chance pair.

+
+
indices2np.ndarray[int]

Indices within the second set of arrays that lead to chance pair.

+
+
+
+
+

Examples#

+

In the following example, we load the GLAD dataset, extract the first +two trajectories, and find between these the array indices that satisfy +the chance pair criteria of 6 km separation distance and no time separation:

+
>>> from clouddrift.datasets import glad
+>>> from clouddrift.pairs import chance_pair
+>>> from clouddrift.ragged import unpack
+>>> ds = glad()
+>>> lon1 = unpack(ds["longitude"], ds["rowsize"], rows=0).pop()
+>>> lat1 = unpack(ds["latitude"], ds["rowsize"], rows=0).pop()
+>>> time1 = unpack(ds["time"], ds["rowsize"], rows=0).pop()
+>>> lon2 = unpack(ds["longitude"], ds["rowsize"], rows=1).pop()
+>>> lat2 = unpack(ds["latitude"], ds["rowsize"], rows=1).pop()
+>>> time2 = unpack(ds["time"], ds["rowsize"], rows=1).pop()
+>>> i1, i2 = chance_pair(lon1, lat1, lon2, lat2, time1, time2, 6000, np.timedelta64(0))
+>>> i1, i2
+(array([177, 180, 183, 186, 189, 192]), array([166, 169, 172, 175, 178, 181]))
+
+
+

Check to ensure our collocation in space worked by calculating the distance +between the identified pairs:

+
>>> sphere.distance(lon1[i1], lat1[i1], lon2[i2], lat2[i2])
+array([5967.4844, 5403.253 , 5116.9136, 5185.715 , 5467.8555, 5958.4917],
+      dtype=float32)
+
+
+

Check the collocation in time:

+
>>> time1[i1] - time2[i2]
+<xarray.DataArray 'time' (obs: 6)>
+array([0, 0, 0, 0, 0, 0], dtype='timedelta64[ns]')
+Coordinates:
+    time     (obs) datetime64[ns] 2012-07-21T21:30:00.524160 ... 2012-07-22T0...
+Dimensions without coordinates: obs
+
+
+
+
+

Raises#

+
+
ValueError

If time1 and time2 are not both provided or both omitted.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.html b/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.html new file mode 100644 index 00000000..64f57cb0 --- /dev/null +++ b/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.html @@ -0,0 +1,652 @@ + + + + + + + + + + + clouddrift.pairs.chance_pairs_from_ragged — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.pairs.chance_pairs_from_ragged

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.pairs.chance_pairs_from_ragged#

+
+
+clouddrift.pairs.chance_pairs_from_ragged(lon: list[float] | ndarray[float] | Series | DataArray, lat: list[float] | ndarray[float] | Series | DataArray, rowsize: list[float] | ndarray[float] | Series | DataArray, space_distance: float | None = 0, time: list[float] | ndarray[float] | Series | DataArray | None = None, time_distance: float | None = 0) List[Tuple[Tuple[int, int], Tuple[ndarray, ndarray]]][source]#
+

Return all chance pairs of contiguous trajectories in a ragged array, +and their collocated points in space and (optionally) time, given input +ragged arrays of longitude, latitude, and (optionally) time, and chance +pair criteria as maximum allowable distances in space and time.

+

If time and time_distance are omitted, the search will be done +only on the spatial criteria, and the result will not include the time +arrays.

+

If time and time_distance are provided, the search will be done +on both the spatial and temporal criteria, and the result will include the +time arrays.

+
+

Parameters#

+
+
lonarray_like

Array of longitudes in degrees.

+
+
latarray_like

Array of latitudes in degrees.

+
+
rowsizearray_like

Array of rowsizes.

+
+
space_distancefloat, optional

Maximum space distance in meters for the pair to qualify as chance pair. +If the separation is within this distance, the pair is considered to be +a chance pair. Default is 0, or no distance, i.e. the positions must be +exactly the same.

+
+
timearray_like, optional

Array of times.

+
+
time_distancefloat, optional

Maximum time distance allowed for the pair to qualify as chance pair. +If the separation is within this distance, and the space distance +condition is satisfied, the pair is considered a chance pair. Default is +0, or no distance, i.e. the times must be exactly the same.

+
+
+
+
+

Returns#

+
+
pairsList[Tuple[Tuple[int, int], Tuple[np.ndarray, np.ndarray]]]

List of tuples, each tuple containing a Tuple of integer indices that +corresponds to the trajectory rows in the ragged array, indicating the +pair of trajectories that satisfy the chance pair criteria, and a Tuple +of arrays containing the indices of the collocated points for each +trajectory in the chance pair.

+
+
+
+
+

Examples#

+

In the following example, we load GLAD dataset as a ragged array dataset, +subset the result to retain the first five trajectories, and finally find +all trajectories that satisfy the chance pair criteria of 12 km separation +distance and no time separation, as well as the indices of the collocated +points for each pair.

+
>>> from clouddrift.datasets import glad
+>>> from clouddrift.pairs import chance_pairs_from_ragged
+>>> from clouddrift.ragged import subset
+>>> ds = subset(glad(), {"id": ["CARTHE_001", "CARTHE_002", "CARTHE_003", "CARTHE_004", "CARTHE_005"]}, id_var_name="id")
+>>> pairs = chance_pairs_from_ragged(
+    ds["longitude"].values,
+    ds["latitude"].values,
+    ds["rowsize"].values,
+    space_distance=12000,
+    time=ds["time"].values,
+    time_distance=np.timedelta64(0)
+)
+[((0, 1),
+  (array([153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189,
+          192, 195, 198, 201, 204, 207, 210, 213, 216]),
+   array([142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178,
+          181, 184, 187, 190, 193, 196, 199, 202, 205]))),
+ ((3, 4),
+  (array([141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177,
+          180, 183]),
+   array([136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172,
+          175, 178])))]
+
+
+

The result above shows that 2 chance pairs were found.

+
+
+

Raises#

+
+
ValueError

If rowsize has fewer than two elements.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.html b/_autosummary/clouddrift.pairs.html new file mode 100644 index 00000000..280dfb72 --- /dev/null +++ b/_autosummary/clouddrift.pairs.html @@ -0,0 +1,944 @@ + + + + + + + + + + + clouddrift.pairs — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.pairs#

+

Functions to analyze pairs of contiguous data segments.

+

Functions

+ + + + + + + + + + + + + + + + + + + + + +

chance_pair(lon1, lat1, lon2, lat2[, time1, ...])

Given two sets of longitudes, latitudes, and times arrays, return in pairs the indices of collocated data points that are within prescribed distances in space and time.

chance_pairs_from_ragged(lon, lat, rowsize)

Return all chance pairs of contiguous trajectories in a ragged array, and their collocated points in space and (optionally) time, given input ragged arrays of longitude, latitude, and (optionally) time, and chance pair criteria as maximum allowable distances in space and time.

pair_bounding_box_overlap(lon1, lat1, lon2, lat2)

Given two arrays of longitudes and latitudes, return boolean masks for their overlapping bounding boxes.

pair_space_distance(lon1, lat1, lon2, lat2)

Given two arrays of longitudes and latitudes, return the distance on a sphere between all pairs of points.

pair_time_distance(time1, time2)

Given two arrays of times (or any other monotonically increasing quantity), return the temporal distance between all pairs of times.

pair_time_overlap(time1, time2[, distance])

Given two arrays of times (or any other monotonically increasing quantity), return indices where the times are within a prescribed distance.

+
+
+clouddrift.pairs.chance_pair(lon1: list[float] | ndarray[float] | Series | DataArray, lat1: list[float] | ndarray[float] | Series | DataArray, lon2: list[float] | ndarray[float] | Series | DataArray, lat2: list[float] | ndarray[float] | Series | DataArray, time1: list[float] | ndarray[float] | Series | DataArray | None = None, time2: list[float] | ndarray[float] | Series | DataArray | None = None, space_distance: float | None = 0, time_distance: float | None = 0)[source]#
+

Given two sets of longitudes, latitudes, and times arrays, return in pairs +the indices of collocated data points that are within prescribed distances +in space and time. Also known as chance pairs.

+
+

Parameters#

+
+
lon1array_like

First array of longitudes in degrees.

+
+
lat1array_like

First array of latitudes in degrees.

+
+
lon2array_like

Second array of longitudes in degrees.

+
+
lat2array_like

Second array of latitudes in degrees.

+
+
time1array_like, optional

First array of times.

+
+
time2array_like, optional

Second array of times.

+
+
space_distancefloat, optional

Maximum allowable space distance in meters for a pair to qualify as chance pair. +If the separation is within this distance, the pair is considered to be +a chance pair. Default is 0, or no distance, i.e. the positions must be +exactly the same.

+
+
time_distancefloat, optional

Maximum allowable time distance for a pair to qualify as chance pair. +If a separation is within this distance, and a space distance +condition is satisfied, the pair is considered a chance pair. Default is +0, or no distance, i.e. the times must be exactly the same.

+
+
+
+
+

Returns#

+
+
indices1np.ndarray[int]

Indices within the first set of arrays that lead to chance pair.

+
+
indices2np.ndarray[int]

Indices within the second set of arrays that lead to chance pair.

+
+
+
+
+

Examples#

+

In the following example, we load the GLAD dataset, extract the first +two trajectories, and find between these the array indices that satisfy +the chance pair criteria of 6 km separation distance and no time separation:

+
>>> from clouddrift.datasets import glad
+>>> from clouddrift.pairs import chance_pair
+>>> from clouddrift.ragged import unpack
+>>> ds = glad()
+>>> lon1 = unpack(ds["longitude"], ds["rowsize"], rows=0).pop()
+>>> lat1 = unpack(ds["latitude"], ds["rowsize"], rows=0).pop()
+>>> time1 = unpack(ds["time"], ds["rowsize"], rows=0).pop()
+>>> lon2 = unpack(ds["longitude"], ds["rowsize"], rows=1).pop()
+>>> lat2 = unpack(ds["latitude"], ds["rowsize"], rows=1).pop()
+>>> time2 = unpack(ds["time"], ds["rowsize"], rows=1).pop()
+>>> i1, i2 = chance_pair(lon1, lat1, lon2, lat2, time1, time2, 6000, np.timedelta64(0))
+>>> i1, i2
+(array([177, 180, 183, 186, 189, 192]), array([166, 169, 172, 175, 178, 181]))
+
+
+

Check to ensure our collocation in space worked by calculating the distance +between the identified pairs:

+
>>> sphere.distance(lon1[i1], lat1[i1], lon2[i2], lat2[i2])
+array([5967.4844, 5403.253 , 5116.9136, 5185.715 , 5467.8555, 5958.4917],
+      dtype=float32)
+
+
+

Check the collocation in time:

+
>>> time1[i1] - time2[i2]
+<xarray.DataArray 'time' (obs: 6)>
+array([0, 0, 0, 0, 0, 0], dtype='timedelta64[ns]')
+Coordinates:
+    time     (obs) datetime64[ns] 2012-07-21T21:30:00.524160 ... 2012-07-22T0...
+Dimensions without coordinates: obs
+
+
+
+
+

Raises#

+
+
ValueError

If time1 and time2 are not both provided or both omitted.

+
+
+
+
+ +
+
+clouddrift.pairs.chance_pairs_from_ragged(lon: list[float] | ndarray[float] | Series | DataArray, lat: list[float] | ndarray[float] | Series | DataArray, rowsize: list[float] | ndarray[float] | Series | DataArray, space_distance: float | None = 0, time: list[float] | ndarray[float] | Series | DataArray | None = None, time_distance: float | None = 0) List[Tuple[Tuple[int, int], Tuple[ndarray, ndarray]]][source]#
+

Return all chance pairs of contiguous trajectories in a ragged array, +and their collocated points in space and (optionally) time, given input +ragged arrays of longitude, latitude, and (optionally) time, and chance +pair criteria as maximum allowable distances in space and time.

+

If time and time_distance are omitted, the search will be done +only on the spatial criteria, and the result will not include the time +arrays.

+

If time and time_distance are provided, the search will be done +on both the spatial and temporal criteria, and the result will include the +time arrays.

+
+

Parameters#

+
+
lonarray_like

Array of longitudes in degrees.

+
+
latarray_like

Array of latitudes in degrees.

+
+
rowsizearray_like

Array of rowsizes.

+
+
space_distancefloat, optional

Maximum space distance in meters for the pair to qualify as chance pair. +If the separation is within this distance, the pair is considered to be +a chance pair. Default is 0, or no distance, i.e. the positions must be +exactly the same.

+
+
timearray_like, optional

Array of times.

+
+
time_distancefloat, optional

Maximum time distance allowed for the pair to qualify as chance pair. +If the separation is within this distance, and the space distance +condition is satisfied, the pair is considered a chance pair. Default is +0, or no distance, i.e. the times must be exactly the same.

+
+
+
+
+

Returns#

+
+
pairsList[Tuple[Tuple[int, int], Tuple[np.ndarray, np.ndarray]]]

List of tuples, each tuple containing a Tuple of integer indices that +corresponds to the trajectory rows in the ragged array, indicating the +pair of trajectories that satisfy the chance pair criteria, and a Tuple +of arrays containing the indices of the collocated points for each +trajectory in the chance pair.

+
+
+
+
+

Examples#

+

In the following example, we load GLAD dataset as a ragged array dataset, +subset the result to retain the first five trajectories, and finally find +all trajectories that satisfy the chance pair criteria of 12 km separation +distance and no time separation, as well as the indices of the collocated +points for each pair.

+
>>> from clouddrift.datasets import glad
+>>> from clouddrift.pairs import chance_pairs_from_ragged
+>>> from clouddrift.ragged import subset
+>>> ds = subset(glad(), {"id": ["CARTHE_001", "CARTHE_002", "CARTHE_003", "CARTHE_004", "CARTHE_005"]}, id_var_name="id")
+>>> pairs = chance_pairs_from_ragged(
+    ds["longitude"].values,
+    ds["latitude"].values,
+    ds["rowsize"].values,
+    space_distance=12000,
+    time=ds["time"].values,
+    time_distance=np.timedelta64(0)
+)
+[((0, 1),
+  (array([153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189,
+          192, 195, 198, 201, 204, 207, 210, 213, 216]),
+   array([142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178,
+          181, 184, 187, 190, 193, 196, 199, 202, 205]))),
+ ((3, 4),
+  (array([141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177,
+          180, 183]),
+   array([136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172,
+          175, 178])))]
+
+
+

The result above shows that 2 chance pairs were found.

+
+
+

Raises#

+
+
ValueError

If rowsize has fewer than two elements.

+
+
+
+
+ +
+
+clouddrift.pairs.pair_bounding_box_overlap(lon1: list[float] | ndarray[float] | Series | DataArray, lat1: list[float] | ndarray[float] | Series | DataArray, lon2: list[float] | ndarray[float] | Series | DataArray, lat2: list[float] | ndarray[float] | Series | DataArray, distance: float | None = 0) Tuple[ndarray[bool], ndarray[bool]][source]#
+

Given two arrays of longitudes and latitudes, return boolean masks for +their overlapping bounding boxes.

+
+

Parameters#

+
+
lon1array_like

First array of longitudes in degrees.

+
+
lat1array_like

First array of latitudes in degrees.

+
+
lon2array_like

Second array of longitudes in degrees.

+
+
lat2array_like

Second array of latitudes in degrees.

+
+
distancefloat, optional

Distance in degrees for the overlap. If the overlap is within this +distance, the bounding boxes are considered to overlap. Default is 0.

+
+
+
+
+

Returns#

+
+
overlap1np.ndarray[int]

Indices lon1 and lat1 where their bounding box overlaps with +that of lon2 and lat2.

+
+
overlap2np.ndarray[int]

Indices lon2 and lat2 where their bounding box overlaps with +that of lon1 and lat1.

+
+
+
+
+

Examples#

+
>>> lon1 = [0, 0, 1, 1]
+>>> lat1 = [0, 0, 1, 1]
+>>> lon2 = [1, 1, 2, 2]
+>>> lat2 = [1, 1, 2, 2]
+>>> pair_bounding_box_overlap(lon1, lat1, lon2, lat2, 0.5)
+(array([2, 3]), array([0, 1]))
+
+
+
+
+ +
+
+clouddrift.pairs.pair_space_distance(lon1: list[float] | ndarray[float] | Series | DataArray, lat1: list[float] | ndarray[float] | Series | DataArray, lon2: list[float] | ndarray[float] | Series | DataArray, lat2: list[float] | ndarray[float] | Series | DataArray) ndarray[float][source]#
+

Given two arrays of longitudes and latitudes, return the distance +on a sphere between all pairs of points.

+
+

Parameters#

+
+
lon1array_like

First array of longitudes in degrees.

+
+
lat1array_like

First array of latitudes in degrees.

+
+
lon2array_like

Second array of longitudes in degrees.

+
+
lat2array_like

Second array of latitudes in degrees.

+
+
+
+
+

Returns#

+
+
distancenp.ndarray[float]

Array of distances between all pairs of points.

+
+
+
+
+

Examples#

+
>>> lon1 = [0, 0, 1, 1]
+>>> lat1 = [0, 0, 1, 1]
+>>> lon2 = [1, 1, 2, 2]
+>>> lat2 = [1, 1, 2, 2]
+>>> pair_space_distance(lon1, lat1, lon2, lat2)
+array([[157424.62387233, 157424.62387233,      0.        ,
+         0.        ],
+   [157424.62387233, 157424.62387233,      0.        ,
+         0.        ],
+   [314825.26360286, 314825.26360286, 157400.64794884,
+    157400.64794884],
+   [314825.26360286, 314825.26360286, 157400.64794884,
+    157400.64794884]])
+
+
+
+
+ +
+
+clouddrift.pairs.pair_time_distance(time1: list[float] | ndarray[float] | Series | DataArray, time2: list[float] | ndarray[float] | Series | DataArray) ndarray[float][source]#
+

Given two arrays of times (or any other monotonically increasing +quantity), return the temporal distance between all pairs of times.

+
+

Parameters#

+
+
time1array_like

First array of times.

+
+
time2array_like

Second array of times.

+
+
+
+
+

Returns#

+
+
distancenp.ndarray[float]

Array of distances between all pairs of times.

+
+
+
+
+

Examples#

+
>>> time1 = np.arange(4)
+>>> time2 = np.arange(2, 6)
+>>> pair_time_distance(time1, time2)
+array([[2, 1, 0, 1],
+       [3, 2, 1, 0],
+       [4, 3, 2, 1],
+       [5, 4, 3, 2]])
+
+
+
+
+ +
+
+clouddrift.pairs.pair_time_overlap(time1: list[float] | ndarray[float] | Series | DataArray, time2: list[float] | ndarray[float] | Series | DataArray, distance: float | None = 0) Tuple[ndarray[int], ndarray[int]][source]#
+

Given two arrays of times (or any other monotonically increasing +quantity), return indices where the times are within a prescribed distance.

+

Although higher-level array containers like xarray and pandas are supported +for input arrays, this function is an order of magnitude faster when passing +in numpy arrays.

+
+

Parameters#

+
+
time1array_like

First array of times.

+
+
time2array_like

Second array of times.

+
+
distancefloat

Maximum distance within which the values of time1 and time2 are +considered to overlap. Default is 0, or, the values must be exactly the +same.

+
+
+
+
+

Returns#

+
+
overlap1np.ndarray[int]

Indices of time1 where its time overlaps with time2.

+
+
overlap2np.ndarray[int]

Indices of time2 where its time overlaps with time1.

+
+
+
+
+

Examples#

+
>>> time1 = np.arange(4)
+>>> time2 = np.arange(2, 6)
+>>> pair_time_overlap(time1, time2)
+(array([2, 3]), array([0, 1]))
+
+
+
>>> pair_time_overlap(time1, time2, 1)
+(array([1, 2, 3]), array([0, 1, 2]))
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.html b/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.html new file mode 100644 index 00000000..192da657 --- /dev/null +++ b/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.html @@ -0,0 +1,608 @@ + + + + + + + + + + + clouddrift.pairs.pair_bounding_box_overlap — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.pairs.pair_bounding_box_overlap

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.pairs.pair_bounding_box_overlap#

+
+
+clouddrift.pairs.pair_bounding_box_overlap(lon1: list[float] | ndarray[float] | Series | DataArray, lat1: list[float] | ndarray[float] | Series | DataArray, lon2: list[float] | ndarray[float] | Series | DataArray, lat2: list[float] | ndarray[float] | Series | DataArray, distance: float | None = 0) Tuple[ndarray[bool], ndarray[bool]][source]#
+

Given two arrays of longitudes and latitudes, return boolean masks for +their overlapping bounding boxes.

+
+

Parameters#

+
+
lon1array_like

First array of longitudes in degrees.

+
+
lat1array_like

First array of latitudes in degrees.

+
+
lon2array_like

Second array of longitudes in degrees.

+
+
lat2array_like

Second array of latitudes in degrees.

+
+
distancefloat, optional

Distance in degrees for the overlap. If the overlap is within this +distance, the bounding boxes are considered to overlap. Default is 0.

+
+
+
+
+

Returns#

+
+
overlap1np.ndarray[int]

Indices lon1 and lat1 where their bounding box overlaps with +that of lon2 and lat2.

+
+
overlap2np.ndarray[int]

Indices lon2 and lat2 where their bounding box overlaps with +that of lon1 and lat1.

+
+
+
+
+

Examples#

+
>>> lon1 = [0, 0, 1, 1]
+>>> lat1 = [0, 0, 1, 1]
+>>> lon2 = [1, 1, 2, 2]
+>>> lat2 = [1, 1, 2, 2]
+>>> pair_bounding_box_overlap(lon1, lat1, lon2, lat2, 0.5)
+(array([2, 3]), array([0, 1]))
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.pair_space_distance.html b/_autosummary/clouddrift.pairs.pair_space_distance.html new file mode 100644 index 00000000..bda9acff --- /dev/null +++ b/_autosummary/clouddrift.pairs.pair_space_distance.html @@ -0,0 +1,608 @@ + + + + + + + + + + + clouddrift.pairs.pair_space_distance — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.pairs.pair_space_distance

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.pairs.pair_space_distance#

+
+
+clouddrift.pairs.pair_space_distance(lon1: list[float] | ndarray[float] | Series | DataArray, lat1: list[float] | ndarray[float] | Series | DataArray, lon2: list[float] | ndarray[float] | Series | DataArray, lat2: list[float] | ndarray[float] | Series | DataArray) ndarray[float][source]#
+

Given two arrays of longitudes and latitudes, return the distance +on a sphere between all pairs of points.

+
+

Parameters#

+
+
lon1array_like

First array of longitudes in degrees.

+
+
lat1array_like

First array of latitudes in degrees.

+
+
lon2array_like

Second array of longitudes in degrees.

+
+
lat2array_like

Second array of latitudes in degrees.

+
+
+
+
+

Returns#

+
+
distancenp.ndarray[float]

Array of distances between all pairs of points.

+
+
+
+
+

Examples#

+
>>> lon1 = [0, 0, 1, 1]
+>>> lat1 = [0, 0, 1, 1]
+>>> lon2 = [1, 1, 2, 2]
+>>> lat2 = [1, 1, 2, 2]
+>>> pair_space_distance(lon1, lat1, lon2, lat2)
+array([[157424.62387233, 157424.62387233,      0.        ,
+         0.        ],
+   [157424.62387233, 157424.62387233,      0.        ,
+         0.        ],
+   [314825.26360286, 314825.26360286, 157400.64794884,
+    157400.64794884],
+   [314825.26360286, 314825.26360286, 157400.64794884,
+    157400.64794884]])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.pair_time_distance.html b/_autosummary/clouddrift.pairs.pair_time_distance.html new file mode 100644 index 00000000..fd1e487c --- /dev/null +++ b/_autosummary/clouddrift.pairs.pair_time_distance.html @@ -0,0 +1,598 @@ + + + + + + + + + + + clouddrift.pairs.pair_time_distance — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.pairs.pair_time_distance

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.pairs.pair_time_distance#

+
+
+clouddrift.pairs.pair_time_distance(time1: list[float] | ndarray[float] | Series | DataArray, time2: list[float] | ndarray[float] | Series | DataArray) ndarray[float][source]#
+

Given two arrays of times (or any other monotonically increasing +quantity), return the temporal distance between all pairs of times.

+
+

Parameters#

+
+
time1array_like

First array of times.

+
+
time2array_like

Second array of times.

+
+
+
+
+

Returns#

+
+
distancenp.ndarray[float]

Array of distances between all pairs of times.

+
+
+
+
+

Examples#

+
>>> time1 = np.arange(4)
+>>> time2 = np.arange(2, 6)
+>>> pair_time_distance(time1, time2)
+array([[2, 1, 0, 1],
+       [3, 2, 1, 0],
+       [4, 3, 2, 1],
+       [5, 4, 3, 2]])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.pairs.pair_time_overlap.html b/_autosummary/clouddrift.pairs.pair_time_overlap.html new file mode 100644 index 00000000..feefe680 --- /dev/null +++ b/_autosummary/clouddrift.pairs.pair_time_overlap.html @@ -0,0 +1,608 @@ + + + + + + + + + + + clouddrift.pairs.pair_time_overlap — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.pairs.pair_time_overlap

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.pairs.pair_time_overlap#

+
+
+clouddrift.pairs.pair_time_overlap(time1: list[float] | ndarray[float] | Series | DataArray, time2: list[float] | ndarray[float] | Series | DataArray, distance: float | None = 0) Tuple[ndarray[int], ndarray[int]][source]#
+

Given two arrays of times (or any other monotonically increasing +quantity), return indices where the times are within a prescribed distance.

+

Although higher-level array containers like xarray and pandas are supported +for input arrays, this function is an order of magnitude faster when passing +in numpy arrays.

+
+

Parameters#

+
+
time1array_like

First array of times.

+
+
time2array_like

Second array of times.

+
+
distancefloat

Maximum distance within which the values of time1 and time2 are +considered to overlap. Default is 0, or, the values must be exactly the +same.

+
+
+
+
+

Returns#

+
+
overlap1np.ndarray[int]

Indices of time1 where its time overlaps with time2.

+
+
overlap2np.ndarray[int]

Indices of time2 where its time overlaps with time1.

+
+
+
+
+

Examples#

+
>>> time1 = np.arange(4)
+>>> time2 = np.arange(2, 6)
+>>> pair_time_overlap(time1, time2)
+(array([2, 3]), array([0, 1]))
+
+
+
>>> pair_time_overlap(time1, time2, 1)
+(array([1, 2, 3]), array([0, 1, 2]))
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.plotting.html b/_autosummary/clouddrift.plotting.html new file mode 100644 index 00000000..183b3ebb --- /dev/null +++ b/_autosummary/clouddrift.plotting.html @@ -0,0 +1,686 @@ + + + + + + + + + + + clouddrift.plotting — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.plotting

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.plotting#

+

This module provides a function to easily and efficiently plot trajectories stored in a ragged array.

+

Functions

+ + + + + + +

plot_ragged(ax, longitude, latitude, ...[, ...])

Plot trajectories from a ragged array dataset on a Matplotlib Axes or a Cartopy GeoAxes object ax.

+
+
+clouddrift.plotting.plot_ragged(ax, longitude: list | ndarray | Series | DataArray, latitude: list | ndarray | Series | DataArray, rowsize: list | ndarray | Series | DataArray, *args, colors: list | ndarray | Series | DataArray | None = None, tolerance: float | int | None = 180, **kwargs)[source]#
+

Plot trajectories from a ragged array dataset on a Matplotlib Axes +or a Cartopy GeoAxes object ax.

+

This function wraps Matplotlib’s plot function (plt.plot) and +LineCollection (matplotlib.collections) to efficiently plot +trajectories from a ragged array dataset.

+
+

Parameters#

+
+
ax: matplotlib.axes.Axes or cartopy.mpl.geoaxes.GeoAxes

Axis to plot on.

+
+
longitudearray-like

Longitude sequence. Unidimensional array input.

+
+
latitudearray-like

Latitude sequence. Unidimensional array input.

+
+
rowsizelist

List of integers specifying the number of data points in each row.

+
+
*argstuple

Additional arguments to pass to ax.plot.

+
+
colorsarray-like

Colors to use for plotting. If colors is the same shape as longitude and latitude, +the trajectories are splitted into segments and each segment is colored according +to the corresponding color value. If colors is the same shape as rowsize, the +trajectories are uniformly colored according to the corresponding color value.

+
+
tolerancefloat

Longitude tolerance gap between data points (in degrees) for segmenting trajectories. +For periodic domains, the tolerance parameter should be set to the maximum allowed gap +between data points. Defaults to 180.

+
+
**kwargsdict

Additional keyword arguments to pass to ax.plot.

+
+
+
+
+

Returns#

+
+
list of matplotlib.lines.Line2D or matplotlib.collections.LineCollection

The plotted lines or line collection. Can be used to set a colorbar +after plotting or extract information from the lines.

+
+
+
+
+

Examples#

+

Plot the first 100 trajectories from the gdp1h dataset, assigning +a different color to each trajectory:

+
>>> from clouddrift import datasets
+>>> import matplotlib.pyplot as plt
+>>> ds = datasets.gdp1h()
+>>> ds = subset(ds, {"ID": ds.ID[:100].values}).load()
+>>> fig = plt.figure()
+>>> ax = fig.add_subplot(1, 1, 1)
+
+
+
>>> plot_ragged(
+>>>     ax,
+>>>     ds.lon,
+>>>     ds.lat,
+>>>     ds.rowsize,
+>>>     colors=np.arange(len(ds.rowsize))
+>>> )
+
+
+

To plot the same trajectories, but assigning a different color to each +observation and specifying a colormap:

+
>>> fig = plt.figure()
+>>> ax = fig.add_subplot(1, 1, 1)
+>>> time = [v.astype(np.int64) / 86400 / 1e9 for v in ds.time.values]
+>>> lc = plot_ragged(
+>>>     ax,
+>>>     ds.lon,
+>>>     ds.lat,
+>>>     ds.rowsize,
+>>>     colors=np.floor(time),
+>>>     cmap="inferno"
+>>> )
+>>> fig.colorbar(lc[0])
+>>> ax.set_xlim([-180, 180])
+>>> ax.set_ylim([-90, 90])
+
+
+

Finally, to plot the same trajectories, but using a cartopy +projection:

+
>>> import cartopy.crs as ccrs
+>>> fig = plt.figure()
+>>> ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mollweide())
+>>> time = [v.astype(np.int64) / 86400 / 1e9 for v in ds.time.values]
+>>> lc = plot_ragged(
+>>>     ax,
+>>>     ds.lon,
+>>>     ds.lat,
+>>>     ds.rowsize,
+>>>     colors=np.arange(len(ds.rowsize)),
+>>>     transform=ccrs.PlateCarree(),
+>>>     cmap=cmocean.cm.ice,
+>>> )
+
+
+
+
+

Raises#

+
+
ValueError

If longitude and latitude arrays do not have the same shape. +If colors do not have the same shape as longitude and latitude arrays or rowsize. +If ax is not a matplotlib Axes or GeoAxes object. +If ax is a GeoAxes object and the transform keyword argument is not provided.

+
+
ImportError

If matplotlib is not installed. +If the axis is a GeoAxes object and cartopy is not installed.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.plotting.plot_ragged.html b/_autosummary/clouddrift.plotting.plot_ragged.html new file mode 100644 index 00000000..06c69db2 --- /dev/null +++ b/_autosummary/clouddrift.plotting.plot_ragged.html @@ -0,0 +1,677 @@ + + + + + + + + + + + clouddrift.plotting.plot_ragged — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.plotting.plot_ragged

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.plotting.plot_ragged#

+
+
+clouddrift.plotting.plot_ragged(ax, longitude: list | ndarray | Series | DataArray, latitude: list | ndarray | Series | DataArray, rowsize: list | ndarray | Series | DataArray, *args, colors: list | ndarray | Series | DataArray | None = None, tolerance: float | int | None = 180, **kwargs)[source]#
+

Plot trajectories from a ragged array dataset on a Matplotlib Axes +or a Cartopy GeoAxes object ax.

+

This function wraps Matplotlib’s plot function (plt.plot) and +LineCollection (matplotlib.collections) to efficiently plot +trajectories from a ragged array dataset.

+
+

Parameters#

+
+
ax: matplotlib.axes.Axes or cartopy.mpl.geoaxes.GeoAxes

Axis to plot on.

+
+
longitudearray-like

Longitude sequence. Unidimensional array input.

+
+
latitudearray-like

Latitude sequence. Unidimensional array input.

+
+
rowsizelist

List of integers specifying the number of data points in each row.

+
+
*argstuple

Additional arguments to pass to ax.plot.

+
+
colorsarray-like

Colors to use for plotting. If colors is the same shape as longitude and latitude, +the trajectories are splitted into segments and each segment is colored according +to the corresponding color value. If colors is the same shape as rowsize, the +trajectories are uniformly colored according to the corresponding color value.

+
+
tolerancefloat

Longitude tolerance gap between data points (in degrees) for segmenting trajectories. +For periodic domains, the tolerance parameter should be set to the maximum allowed gap +between data points. Defaults to 180.

+
+
**kwargsdict

Additional keyword arguments to pass to ax.plot.

+
+
+
+
+

Returns#

+
+
list of matplotlib.lines.Line2D or matplotlib.collections.LineCollection

The plotted lines or line collection. Can be used to set a colorbar +after plotting or extract information from the lines.

+
+
+
+
+

Examples#

+

Plot the first 100 trajectories from the gdp1h dataset, assigning +a different color to each trajectory:

+
>>> from clouddrift import datasets
+>>> import matplotlib.pyplot as plt
+>>> ds = datasets.gdp1h()
+>>> ds = subset(ds, {"ID": ds.ID[:100].values}).load()
+>>> fig = plt.figure()
+>>> ax = fig.add_subplot(1, 1, 1)
+
+
+
>>> plot_ragged(
+>>>     ax,
+>>>     ds.lon,
+>>>     ds.lat,
+>>>     ds.rowsize,
+>>>     colors=np.arange(len(ds.rowsize))
+>>> )
+
+
+

To plot the same trajectories, but assigning a different color to each +observation and specifying a colormap:

+
>>> fig = plt.figure()
+>>> ax = fig.add_subplot(1, 1, 1)
+>>> time = [v.astype(np.int64) / 86400 / 1e9 for v in ds.time.values]
+>>> lc = plot_ragged(
+>>>     ax,
+>>>     ds.lon,
+>>>     ds.lat,
+>>>     ds.rowsize,
+>>>     colors=np.floor(time),
+>>>     cmap="inferno"
+>>> )
+>>> fig.colorbar(lc[0])
+>>> ax.set_xlim([-180, 180])
+>>> ax.set_ylim([-90, 90])
+
+
+

Finally, to plot the same trajectories, but using a cartopy +projection:

+
>>> import cartopy.crs as ccrs
+>>> fig = plt.figure()
+>>> ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mollweide())
+>>> time = [v.astype(np.int64) / 86400 / 1e9 for v in ds.time.values]
+>>> lc = plot_ragged(
+>>>     ax,
+>>>     ds.lon,
+>>>     ds.lat,
+>>>     ds.rowsize,
+>>>     colors=np.arange(len(ds.rowsize)),
+>>>     transform=ccrs.PlateCarree(),
+>>>     cmap=cmocean.cm.ice,
+>>> )
+
+
+
+
+

Raises#

+
+
ValueError

If longitude and latitude arrays do not have the same shape. +If colors do not have the same shape as longitude and latitude arrays or rowsize. +If ax is not a matplotlib Axes or GeoAxes object. +If ax is a GeoAxes object and the transform keyword argument is not provided.

+
+
ImportError

If matplotlib is not installed. +If the axis is a GeoAxes object and cartopy is not installed.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.apply_ragged.html b/_autosummary/clouddrift.ragged.apply_ragged.html new file mode 100644 index 00000000..dcf33b78 --- /dev/null +++ b/_autosummary/clouddrift.ragged.apply_ragged.html @@ -0,0 +1,649 @@ + + + + + + + + + + + clouddrift.ragged.apply_ragged — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.apply_ragged

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.apply_ragged#

+
+
+clouddrift.ragged.apply_ragged(func: callable, arrays: list[~numpy.ndarray | ~xarray.core.dataarray.DataArray] | ~numpy.ndarray | ~xarray.core.dataarray.DataArray, rowsize: list[int] | ~numpy.ndarray[int] | ~xarray.core.dataarray.DataArray, *args: tuple, rows: int | ~typing.Iterable[int] = None, axis: int = 0, executor: ~concurrent.futures._base.Executor = <concurrent.futures.thread.ThreadPoolExecutor object>, **kwargs: dict) tuple[ndarray] | ndarray[source]#
+

Apply a function to a ragged array.

+

The function func will be applied to each contiguous row of arrays as +indicated by row sizes rowsize. The output of func will be +concatenated into a single ragged array.

+

You can pass arrays as NumPy arrays or xarray DataArrays, however, +the result will always be a NumPy array. Passing rows as an integer or +a sequence of integers will make apply_ragged process and return only +those specific rows, and otherwise, all rows in the input ragged array will +be processed. Further, you can use the axis parameter to specify the +ragged axis of the input array(s) (default is 0).

+

By default this function uses concurrent.futures.ThreadPoolExecutor to +run func in multiple threads. The number of threads can be controlled by +passing the max_workers argument to the executor instance passed to +apply_ragged. Alternatively, you can pass the concurrent.futures.ProcessPoolExecutor +instance to use processes instead. Passing alternative (3rd party library) +concurrent executors may work if they follow the same executor interface as +that of concurrent.futures, however this has not been tested yet.

+
+

Parameters#

+
+
funccallable

Function to apply to each row of each ragged array in arrays.

+
+
arrayslist[np.ndarray] or np.ndarray or xr.DataArray

An array or a list of arrays to apply func to.

+
+
rowsizelist[int] or np.ndarray[int] or xr.DataArray[int]

List of integers specifying the number of data points in each row.

+
+
*argstuple

Additional arguments to pass to func.

+
+
rowsint or Iterable[int], optional

The row(s) of the ragged array to apply func to. If rows is +None (default), then func will be applied to all rows.

+
+
axisint, optional

The ragged axis of the input arrays. Default is 0.

+
+
executorconcurrent.futures.Executor, optional

Executor to use for concurrent execution. Default is ThreadPoolExecutor +with the default number of max_workers. +Another supported option is ProcessPoolExecutor.

+
+
**kwargsdict

Additional keyword arguments to pass to func.

+
+
+
+
+

Returns#

+
+
outtuple[np.ndarray] or np.ndarray

Output array(s) from func.

+
+
+
+
+

Examples#

+

Using velocity_from_position with apply_ragged, calculate the velocities of +multiple particles, the coordinates of which are found in the ragged arrays x, y, and t +that share row sizes 2, 3, and 4:

+
>>> rowsize = [2, 3, 4]
+>>> x = np.array([1, 2, 10, 12, 14, 30, 33, 36, 39])
+>>> y = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
+>>> t = np.array([1, 2, 1, 2, 3, 1, 2, 3, 4])
+>>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, coord_system="cartesian")
+array([1., 1., 2., 2., 2., 3., 3., 3., 3.]),
+array([1., 1., 1., 1., 1., 1., 1., 1., 1.]))
+
+
+

To apply func to only a subset of rows, use the rows argument:

+
>>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, rows=0, coord_system="cartesian")
+array([1., 1.]),
+array([1., 1.]))
+>>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, rows=[0, 1], coord_system="cartesian")
+array([1., 1., 2., 2., 2.]),
+array([1., 1., 1., 1., 1.]))
+
+
+
+
+

Raises#

+
+
ValueError

If the sum of rowsize does not equal the length of arrays.

+
+
IndexError

If empty arrays.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.chunk.html b/_autosummary/clouddrift.ragged.chunk.html new file mode 100644 index 00000000..5f60f84e --- /dev/null +++ b/_autosummary/clouddrift.ragged.chunk.html @@ -0,0 +1,654 @@ + + + + + + + + + + + clouddrift.ragged.chunk — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.chunk

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.chunk#

+
+
+clouddrift.ragged.chunk(x: list | ndarray | DataArray | Series, length: int, overlap: int = 0, align: str = 'start') ndarray[source]#
+

Divide an array x into equal chunks of length length. The result +is a 2-dimensional NumPy array of shape (num_chunks, length). The resulting +number of chunks is determined based on the length of x, length, +and overlap.

+

chunk can be combined with apply_ragged() to chunk a ragged array.

+
+

Parameters#

+
+
xlist or array-like

Array to divide into chunks.

+
+
lengthint

The length of each chunk.

+
+
overlapint, optional

The number of overlapping array elements across chunks. The default is 0. +Must be smaller than length. For example, if length is 4 and +overlap is 2, the chunks of [0, 1, 2, 3, 4, 5] will be +np.array([[0, 1, 2, 3], [2, 3, 4, 5]]). Negative overlap can be used +to offset chunks by some number of elements. For example, if length +is 2 and overlap is -1, the chunks of [0, 1, 2, 3, 4, 5] will +be np.array([[0, 1], [3, 4]]).

+
+
alignstr, optional [“start”, “middle”, “end”]

If the remainder of the length of x divided by the chunk length is a number +N different from zero, this parameter controls which part of the array will be kept +into the chunks. If align="start", the elements at the beginning of the array +will be part of the chunks and N points are discarded at the end. If align=”middle”, +floor(N/2) and ceil(N/2) elements will be discarded from the beginning and the end +of the array, respectively. If align="end", the elements at the end of the array +will be kept, and the N first elements are discarded. The default is “start”.

+
+
+
+
+

Returns#

+
+
np.ndarray

2-dimensional array of shape (num_chunks, length).

+
+
+
+
+

Examples#

+

Chunk a simple list; this discards the end elements that exceed the last chunk:

+
>>> chunk([1, 2, 3, 4, 5], 2)
+array([[1, 2],
+       [3, 4]])
+
+
+

To discard the starting elements of the array instead, use align="end":

+
>>> chunk([1, 2, 3, 4, 5], 2, align="end")
+array([[2, 3],
+       [4, 5]])
+
+
+

To center the chunks by discarding both ends of the array, use align="middle":

+
>>> chunk([1, 2, 3, 4, 5, 6, 7, 8], 3, align="middle")
+array([[2, 3, 4],
+       [5, 6, 7]])
+
+
+

Specify overlap to get overlapping chunks:

+
>>> chunk([1, 2, 3, 4, 5], 2, overlap=1)
+array([[1, 2],
+       [2, 3],
+       [3, 4],
+       [4, 5]])
+
+
+

Use apply_ragged to chunk a ragged array by providing the row sizes; +notice that you must pass the array to chunk as an array-like, not a list:

+
>>> x = np.array([1, 2, 3, 4, 5])
+>>> rowsize = [2, 1, 2]
+>>> apply_ragged(chunk, x, rowsize, 2)
+array([[1, 2],
+       [4, 5]])
+
+
+
+
+

Raises#

+
+
ValueError

If length < 0.

+
+
ValueError

If align not in ["start", "middle", "end"].

+
+
ZeroDivisionError

if length == 0.

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.html b/_autosummary/clouddrift.ragged.html new file mode 100644 index 00000000..1becab27 --- /dev/null +++ b/_autosummary/clouddrift.ragged.html @@ -0,0 +1,1183 @@ + + + + + + + + + + + clouddrift.ragged — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged

+ +
+ +
+
+ + + + +
+ +
+

clouddrift.ragged#

+

Transformational and inquiry functions for ragged arrays.

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

apply_ragged(func, arrays, rowsize, *args[, ...])

Apply a function to a ragged array.

chunk(x, length[, overlap, align])

Divide an array x into equal chunks of length length.

prune(ragged, rowsize, min_rowsize)

Within a ragged array, removes arrays less than a specified row size.

ragged_to_regular(ragged, rowsize[, fill_value])

Convert a ragged array to a two-dimensional array such that each contiguous segment of a ragged array is a row in the two-dimensional array.

regular_to_ragged(array[, fill_value])

Convert a two-dimensional array to a ragged array.

rowsize_to_index(rowsize)

Convert a list of row sizes to a list of indices.

segment(x, tolerance[, rowsize])

Divide an array into segments based on a tolerance value.

subset(ds, criteria[, id_var_name, ...])

Subset a ragged array dataset as a function of one or more criteria.

unpack(ragged_array, rowsize[, rows, axis])

Unpack a ragged array into a list of regular arrays.

+
+
+clouddrift.ragged.apply_ragged(func: callable, arrays: list[~numpy.ndarray | ~xarray.core.dataarray.DataArray] | ~numpy.ndarray | ~xarray.core.dataarray.DataArray, rowsize: list[int] | ~numpy.ndarray[int] | ~xarray.core.dataarray.DataArray, *args: tuple, rows: int | ~typing.Iterable[int] = None, axis: int = 0, executor: ~concurrent.futures._base.Executor = <concurrent.futures.thread.ThreadPoolExecutor object>, **kwargs: dict) tuple[ndarray] | ndarray[source]#
+

Apply a function to a ragged array.

+

The function func will be applied to each contiguous row of arrays as +indicated by row sizes rowsize. The output of func will be +concatenated into a single ragged array.

+

You can pass arrays as NumPy arrays or xarray DataArrays, however, +the result will always be a NumPy array. Passing rows as an integer or +a sequence of integers will make apply_ragged process and return only +those specific rows, and otherwise, all rows in the input ragged array will +be processed. Further, you can use the axis parameter to specify the +ragged axis of the input array(s) (default is 0).

+

By default this function uses concurrent.futures.ThreadPoolExecutor to +run func in multiple threads. The number of threads can be controlled by +passing the max_workers argument to the executor instance passed to +apply_ragged. Alternatively, you can pass the concurrent.futures.ProcessPoolExecutor +instance to use processes instead. Passing alternative (3rd party library) +concurrent executors may work if they follow the same executor interface as +that of concurrent.futures, however this has not been tested yet.

+
+

Parameters#

+
+
funccallable

Function to apply to each row of each ragged array in arrays.

+
+
arrayslist[np.ndarray] or np.ndarray or xr.DataArray

An array or a list of arrays to apply func to.

+
+
rowsizelist[int] or np.ndarray[int] or xr.DataArray[int]

List of integers specifying the number of data points in each row.

+
+
*argstuple

Additional arguments to pass to func.

+
+
rowsint or Iterable[int], optional

The row(s) of the ragged array to apply func to. If rows is +None (default), then func will be applied to all rows.

+
+
axisint, optional

The ragged axis of the input arrays. Default is 0.

+
+
executorconcurrent.futures.Executor, optional

Executor to use for concurrent execution. Default is ThreadPoolExecutor +with the default number of max_workers. +Another supported option is ProcessPoolExecutor.

+
+
**kwargsdict

Additional keyword arguments to pass to func.

+
+
+
+
+

Returns#

+
+
outtuple[np.ndarray] or np.ndarray

Output array(s) from func.

+
+
+
+
+

Examples#

+

Using velocity_from_position with apply_ragged, calculate the velocities of +multiple particles, the coordinates of which are found in the ragged arrays x, y, and t +that share row sizes 2, 3, and 4:

+
>>> rowsize = [2, 3, 4]
+>>> x = np.array([1, 2, 10, 12, 14, 30, 33, 36, 39])
+>>> y = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
+>>> t = np.array([1, 2, 1, 2, 3, 1, 2, 3, 4])
+>>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, coord_system="cartesian")
+array([1., 1., 2., 2., 2., 3., 3., 3., 3.]),
+array([1., 1., 1., 1., 1., 1., 1., 1., 1.]))
+
+
+

To apply func to only a subset of rows, use the rows argument:

+
>>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, rows=0, coord_system="cartesian")
+array([1., 1.]),
+array([1., 1.]))
+>>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, rows=[0, 1], coord_system="cartesian")
+array([1., 1., 2., 2., 2.]),
+array([1., 1., 1., 1., 1.]))
+
+
+
+
+

Raises#

+
+
ValueError

If the sum of rowsize does not equal the length of arrays.

+
+
IndexError

If empty arrays.

+
+
+
+
+ +
+
+clouddrift.ragged.chunk(x: list | ndarray | DataArray | Series, length: int, overlap: int = 0, align: str = 'start') ndarray[source]#
+

Divide an array x into equal chunks of length length. The result +is a 2-dimensional NumPy array of shape (num_chunks, length). The resulting +number of chunks is determined based on the length of x, length, +and overlap.

+

chunk can be combined with apply_ragged() to chunk a ragged array.

+
+

Parameters#

+
+
xlist or array-like

Array to divide into chunks.

+
+
lengthint

The length of each chunk.

+
+
overlapint, optional

The number of overlapping array elements across chunks. The default is 0. +Must be smaller than length. For example, if length is 4 and +overlap is 2, the chunks of [0, 1, 2, 3, 4, 5] will be +np.array([[0, 1, 2, 3], [2, 3, 4, 5]]). Negative overlap can be used +to offset chunks by some number of elements. For example, if length +is 2 and overlap is -1, the chunks of [0, 1, 2, 3, 4, 5] will +be np.array([[0, 1], [3, 4]]).

+
+
alignstr, optional [“start”, “middle”, “end”]

If the remainder of the length of x divided by the chunk length is a number +N different from zero, this parameter controls which part of the array will be kept +into the chunks. If align="start", the elements at the beginning of the array +will be part of the chunks and N points are discarded at the end. If align=”middle”, +floor(N/2) and ceil(N/2) elements will be discarded from the beginning and the end +of the array, respectively. If align="end", the elements at the end of the array +will be kept, and the N first elements are discarded. The default is “start”.

+
+
+
+
+

Returns#

+
+
np.ndarray

2-dimensional array of shape (num_chunks, length).

+
+
+
+
+

Examples#

+

Chunk a simple list; this discards the end elements that exceed the last chunk:

+
>>> chunk([1, 2, 3, 4, 5], 2)
+array([[1, 2],
+       [3, 4]])
+
+
+

To discard the starting elements of the array instead, use align="end":

+
>>> chunk([1, 2, 3, 4, 5], 2, align="end")
+array([[2, 3],
+       [4, 5]])
+
+
+

To center the chunks by discarding both ends of the array, use align="middle":

+
>>> chunk([1, 2, 3, 4, 5, 6, 7, 8], 3, align="middle")
+array([[2, 3, 4],
+       [5, 6, 7]])
+
+
+

Specify overlap to get overlapping chunks:

+
>>> chunk([1, 2, 3, 4, 5], 2, overlap=1)
+array([[1, 2],
+       [2, 3],
+       [3, 4],
+       [4, 5]])
+
+
+

Use apply_ragged to chunk a ragged array by providing the row sizes; +notice that you must pass the array to chunk as an array-like, not a list:

+
>>> x = np.array([1, 2, 3, 4, 5])
+>>> rowsize = [2, 1, 2]
+>>> apply_ragged(chunk, x, rowsize, 2)
+array([[1, 2],
+       [4, 5]])
+
+
+
+
+

Raises#

+
+
ValueError

If length < 0.

+
+
ValueError

If align not in ["start", "middle", "end"].

+
+
ZeroDivisionError

if length == 0.

+
+
+
+
+ +
+
+clouddrift.ragged.prune(ragged: list | ndarray | Series | DataArray, rowsize: list | ndarray | Series | DataArray, min_rowsize: float) Tuple[ndarray, ndarray][source]#
+

Within a ragged array, removes arrays less than a specified row size.

+
+

Parameters#

+
+
raggednp.ndarray or pd.Series or xr.DataArray

A ragged array.

+
+
rowsizelist or np.ndarray[int] or pd.Series or xr.DataArray[int]

The size of each row in the input ragged array.

+
+
min_rowsize :

The minimum row size that will be kept.

+
+
+
+
+

Returns#

+
+
tuple[np.ndarray, np.ndarray]

A tuple of ragged array and size of each row.

+
+
+
+
+

Examples#

+
>>> prune(np.array([1, 2, 3, 0, -1, -2]), np.array([3, 1, 2]),2)
+(array([1, 2, 3, -1, -2]), array([3, 2]))
+
+
+
+
+

Raises#

+
+
ValueError

If the sum of rowsize does not equal the length of arrays.

+
+
IndexError

If empty ragged.

+
+
+
+
+

See Also#

+

segment(), chunk

+
+
+ +
+
+clouddrift.ragged.ragged_to_regular(ragged: ndarray | Series | DataArray, rowsize: list | ndarray | Series | DataArray, fill_value: float = nan) ndarray[source]#
+

Convert a ragged array to a two-dimensional array such that each contiguous segment +of a ragged array is a row in the two-dimensional array. Each row of the two-dimensional +array is padded with NaNs as needed. The length of the first dimension of the output +array is the length of rowsize. The length of the second dimension is the maximum +element of rowsize.

+

Note: Although this function accepts parameters of type xarray.DataArray, +passing NumPy arrays is recommended for performance reasons.

+
+

Parameters#

+
+
raggednp.ndarray or pd.Series or xr.DataArray

A ragged array.

+
+
rowsizelist or np.ndarray[int] or pd.Series or xr.DataArray[int]

The size of each row in the ragged array.

+
+
fill_valuefloat, optional

Fill value to use for the trailing elements of each row of the resulting +regular array.

+
+
+
+
+

Returns#

+
+
np.ndarray

A two-dimensional array.

+
+
+
+
+

Examples#

+

By default, the fill value used is NaN:

+
>>> ragged_to_regular(np.array([1, 2, 3, 4, 5]), np.array([2, 1, 2]))
+array([[ 1.,  2.],
+       [ 3., nan],
+       [ 4.,  5.]])
+
+
+

You can specify an alternative fill value:

+
>>> ragged_to_regular(np.array([1, 2, 3, 4, 5]), np.array([2, 1, 2]), fill_value=999)
+array([[ 1.,    2.],
+       [ 3., -999.],
+       [ 4.,    5.]])
+
+
+
+
+

See Also#

+

regular_to_ragged()

+
+
+ +
+
+clouddrift.ragged.regular_to_ragged(array: ndarray, fill_value: float = nan) tuple[ndarray, ndarray][source]#
+

Convert a two-dimensional array to a ragged array. Fill values in the input array are +excluded from the output ragged array.

+
+

Parameters#

+
+
arraynp.ndarray

A two-dimensional array.

+
+
fill_valuefloat, optional

Fill value used to determine the bounds of contiguous segments.

+
+
+
+
+

Returns#

+
+
tuple[np.ndarray, np.ndarray]

A tuple of the ragged array and the size of each row.

+
+
+
+
+

Examples#

+

By default, NaN values found in the input regular array are excluded from +the output ragged array:

+
>>> regular_to_ragged(np.array([[1, 2], [3, np.nan], [4, 5]]))
+(array([1., 2., 3., 4., 5.]), array([2, 1, 2]))
+
+
+

Alternatively, a different fill value can be specified:

+
>>> regular_to_ragged(np.array([[1, 2], [3, -999], [4, 5]]), fill_value=-999)
+(array([1., 2., 3., 4., 5.]), array([2, 1, 2]))
+
+
+
+
+

See Also#

+

ragged_to_regular()

+
+
+ +
+
+clouddrift.ragged.rowsize_to_index(rowsize: list | ndarray | DataArray) ndarray[source]#
+

Convert a list of row sizes to a list of indices.

+

This function is typically used to obtain the indices of data rows organized +in a ragged array.

+
+

Parameters#

+
+
rowsizelist or np.ndarray or xr.DataArray

A list of row sizes.

+
+
+
+
+

Returns#

+
+
np.ndarray

A list of indices.

+
+
+
+
+

Examples#

+

To obtain the indices within a ragged array of three consecutive rows of sizes 100, 202, and 53:

+
>>> rowsize_to_index([100, 202, 53])
+array([0, 100, 302, 355])
+
+
+
+
+ +
+
+clouddrift.ragged.segment(x: ndarray, tolerance: float | timedelta64 | timedelta | Timedelta, rowsize: ndarray[int] = None) ndarray[int][source]#
+

Divide an array into segments based on a tolerance value.

+
+

Parameters#

+
+
xlist, np.ndarray, or xr.DataArray

An array to divide into segment.

+
+
tolerancefloat, np.timedelta64, timedelta, pd.Timedelta

The maximum signed difference between consecutive points in a segment. +The array x will be segmented wherever differences exceed the tolerance.

+
+
rowsizenp.ndarray[int], optional

The size of rows if x is originally a ragged array. If present, x will be +divided both by gaps that exceed the tolerance, and by the original rows +of the ragged array.

+
+
+
+
+

Returns#

+
+
np.ndarray[int]

An array of row sizes that divides the input array into segments.

+
+
+
+
+

Examples#

+

The simplest use of segment is to provide a tolerance value that is +used to divide an array into segments:

+
>>> x = [0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4]
+>>> segment(x, 0.5)
+array([1, 3, 2, 4, 1])
+
+
+

If the array is already previously segmented (e.g. multiple rows in +a ragged array), then the rowsize argument can be used to preserve +the original segments:

+
>>> x = [0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4]
+>>> rowsize = [3, 2, 6]
+>>> segment(x, 0.5, rowsize)
+array([1, 2, 1, 1, 1, 4, 1])
+
+
+

The tolerance can also be negative. In this case, the input array is +segmented where the negative difference exceeds the negative +value of the tolerance, i.e. where x[n+1] - x[n] < -tolerance:

+
>>> x = [0, 1, 2, 0, 1, 2]
+>>> segment(x, -0.5)
+array([3, 3])
+
+
+

To segment an array for both positive and negative gaps, invoke the function +twice, once for a positive tolerance and once for a negative tolerance. +The result of the first invocation can be passed as the rowsize argument +to the first segment invocation:

+
>>> x = [1, 1, 2, 2, 1, 1, 2, 2]
+>>> segment(x, 0.5, rowsize=segment(x, -0.5))
+array([2, 2, 2, 2])
+
+
+

If the input array contains time objects, the tolerance must be a time interval:

+
>>> x = np.array([np.datetime64("2023-01-01"), np.datetime64("2023-01-02"),
+                  np.datetime64("2023-01-03"), np.datetime64("2023-02-01"),
+                  np.datetime64("2023-02-02")])
+>>> segment(x, np.timedelta64(1, "D"))
+np.array([3, 2])
+
+
+
+
+ +
+
+clouddrift.ragged.subset(ds: Dataset, criteria: dict, id_var_name: str = 'id', rowsize_var_name: str = 'rowsize', traj_dim_name: str = 'traj', obs_dim_name: str = 'obs', full_trajectories=False) Dataset[source]#
+

Subset a ragged array dataset as a function of one or more criteria. +The criteria are passed with a dictionary, where a dictionary key +is a variable to subset and the associated dictionary value is either a range +(valuemin, valuemax), a list [value1, value2, valueN], a single value, or a +masking function applied to every row of the ragged array using apply_ragged.

+

This function needs to know the names of the dimensions of the ragged array dataset +(traj_dim_name and obs_dim_name), and the name of the rowsize variable (rowsize_var_name). +Default values are provided for these arguments (see below), but they can be changed if needed.

+
+

Parameters#

+
+
dsxr.Dataset

Dataset stored as ragged arrays

+
+
criteriadict

dictionary containing the variables (as keys) and the ranges/values/functions (as values) to subset

+
+
id_var_namestr, optional

Name of the variable containing the ID of the trajectories (default is “id”)

+
+
rowsize_var_namestr, optional

Name of the variable containing the number of observations per trajectory (default is “rowsize”)

+
+
traj_dim_namestr, optional

Name of the trajectory dimension (default is “traj”)

+
+
obs_dim_namestr, optional

Name of the observation dimension (default is “obs”)

+
+
full_trajectoriesbool, optional

If True, it returns the complete trajectories (rows) where at least one observation +matches the criteria, rather than just the segments where the criteria are satisfied. +Default is False.

+
+
+
+
+

Returns#

+
+
xr.Dataset

subset Dataset matching the criterion(a)

+
+
+
+
+

Examples#

+

Criteria are combined on any data or metadata variables part of the Dataset. +The following examples are based on NOAA GDP datasets which can be accessed with the +clouddrift.datasets module.

+

Retrieve a region, like the Gulf of Mexico, using ranges of latitude and longitude:

+
>>> subset(ds, {"lat": (21, 31), "lon": (-98, -78)})
+
+
+

The parameter full_trajectories can be used to retrieve trajectories passing through a region, for example all trajectories passing through the Gulf of Mexico:

+
>>> subset(ds, {"lat": (21, 31), "lon": (-98, -78)}, full_trajectories=True)
+
+
+

Retrieve drogued trajectory segments:

+
>>> subset(ds, {"drogue_status": True})
+
+
+

Retrieve trajectory segments with temperature higher than 25°C (303.15K):

+
>>> subset(ds, {"sst": (303.15, np.inf)})
+
+
+

You can use the same approach to return only the trajectories that are +shorter than some number of observations (similar to prune() but for +the entire dataset):

+
>>> subset(ds, {"rowsize": (0, 1000)})
+
+
+

Retrieve specific drifters from their IDs:

+
>>> subset(ds, {"id": [2578, 2582, 2583]})
+
+
+

Sometimes, you may want to retrieve specific rows of a ragged array. +You can do that by filtering along the trajectory dimension directly, since +this one corresponds to row numbers:

+
>>> rows = [5, 6, 7]
+>>> subset(ds, {"traj": rows})
+
+
+

Retrieve a specific time period:

+
>>> subset(ds, {"time": (np.datetime64("2000-01-01"), np.datetime64("2020-01-31"))})
+
+
+

Note that to subset time variable, the range has to be defined as a function +type of the variable. By default, xarray uses np.datetime64 to +represent datetime data. If the datetime data is a datetime.datetime, or +pd.Timestamp, the range would have to be defined accordingly.

+

Those criteria can also be combined:

+
>>> subset(ds, {"lat": (21, 31), "lon": (-98, -78), "drogue_status": True, "sst": (303.15, np.inf), "time": (np.datetime64("2000-01-01"), np.datetime64("2020-01-31"))})
+
+
+

You can also use a function to filter the data. For example, retrieve every other observation +of each trajectory (row):

+
>>> func = (lambda arr: ((arr - arr[0]) % 2) == 0)
+>>> subset(ds, {"time": func})
+
+
+
+
+

Raises#

+
+
ValueError

If one of the variable in a criterion is not found in the Dataset

+
+
+
+
+ +
+
+clouddrift.ragged.unpack(ragged_array: ndarray, rowsize: ndarray[int], rows: int | Iterable[int] = None, axis: int = 0) list[ndarray][source]#
+

Unpack a ragged array into a list of regular arrays.

+

Unpacking a np.ndarray ragged array is about 2 orders of magnitude +faster than unpacking an xr.DataArray ragged array, so unless you need a +DataArray as the result, we recommend passing np.ndarray as input.

+
+

Parameters#

+
+
ragged_arrayarray-like

A ragged_array to unpack

+
+
rowsizearray-like

An array of integers whose values is the size of each row in the ragged +array

+
+
rowsint or Iterable[int], optional

A row or list of rows to unpack. Default is None, which unpacks all rows.

+
+
axisint, optional

The axis along which to unpack the ragged array. Default is 0.

+
+
+
+
+

Returns#

+
+
list

A list of array-likes with sizes that correspond to the values in +rowsize, and types that correspond to the type of ragged_array

+
+
+
+
+

Examples#

+

Unpacking longitude arrays from a ragged Xarray Dataset:

+
lon = unpack(ds.lon, ds["rowsize"]) # return a list[xr.DataArray] (slower)
+lon = unpack(ds.lon.values, ds["rowsize"]) # return a list[np.ndarray] (faster)
+first_lon = unpack(ds.lon.values, ds["rowsize"], rows=0) # return only the first row
+first_two_lons = unpack(ds.lon.values, ds["rowsize"], rows=[0, 1]) # return first two rows
+
+
+

Looping over trajectories in a ragged Xarray Dataset to compute velocities +for each:

+
for lon, lat, time in list(zip(
+    unpack(ds.lon.values, ds["rowsize"]),
+    unpack(ds.lat.values, ds["rowsize"]),
+    unpack(ds.time.values, ds["rowsize"])
+)):
+    u, v = velocity_from_position(lon, lat, time)
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.prune.html b/_autosummary/clouddrift.ragged.prune.html new file mode 100644 index 00000000..f590d5a0 --- /dev/null +++ b/_autosummary/clouddrift.ragged.prune.html @@ -0,0 +1,607 @@ + + + + + + + + + + + clouddrift.ragged.prune — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.prune

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.prune#

+
+
+clouddrift.ragged.prune(ragged: list | ndarray | Series | DataArray, rowsize: list | ndarray | Series | DataArray, min_rowsize: float) Tuple[ndarray, ndarray][source]#
+

Within a ragged array, removes arrays less than a specified row size.

+
+

Parameters#

+
+
raggednp.ndarray or pd.Series or xr.DataArray

A ragged array.

+
+
rowsizelist or np.ndarray[int] or pd.Series or xr.DataArray[int]

The size of each row in the input ragged array.

+
+
min_rowsize :

The minimum row size that will be kept.

+
+
+
+
+

Returns#

+
+
tuple[np.ndarray, np.ndarray]

A tuple of ragged array and size of each row.

+
+
+
+
+

Examples#

+
>>> prune(np.array([1, 2, 3, 0, -1, -2]), np.array([3, 1, 2]),2)
+(array([1, 2, 3, -1, -2]), array([3, 2]))
+
+
+
+
+

Raises#

+
+
ValueError

If the sum of rowsize does not equal the length of arrays.

+
+
IndexError

If empty ragged.

+
+
+
+
+

See Also#

+

segment(), chunk

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.ragged_to_regular.html b/_autosummary/clouddrift.ragged.ragged_to_regular.html new file mode 100644 index 00000000..ec60b6a2 --- /dev/null +++ b/_autosummary/clouddrift.ragged.ragged_to_regular.html @@ -0,0 +1,615 @@ + + + + + + + + + + + clouddrift.ragged.ragged_to_regular — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.ragged_to_regular

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.ragged_to_regular#

+
+
+clouddrift.ragged.ragged_to_regular(ragged: ndarray | Series | DataArray, rowsize: list | ndarray | Series | DataArray, fill_value: float = nan) ndarray[source]#
+

Convert a ragged array to a two-dimensional array such that each contiguous segment +of a ragged array is a row in the two-dimensional array. Each row of the two-dimensional +array is padded with NaNs as needed. The length of the first dimension of the output +array is the length of rowsize. The length of the second dimension is the maximum +element of rowsize.

+

Note: Although this function accepts parameters of type xarray.DataArray, +passing NumPy arrays is recommended for performance reasons.

+
+

Parameters#

+
+
raggednp.ndarray or pd.Series or xr.DataArray

A ragged array.

+
+
rowsizelist or np.ndarray[int] or pd.Series or xr.DataArray[int]

The size of each row in the ragged array.

+
+
fill_valuefloat, optional

Fill value to use for the trailing elements of each row of the resulting +regular array.

+
+
+
+
+

Returns#

+
+
np.ndarray

A two-dimensional array.

+
+
+
+
+

Examples#

+

By default, the fill value used is NaN:

+
>>> ragged_to_regular(np.array([1, 2, 3, 4, 5]), np.array([2, 1, 2]))
+array([[ 1.,  2.],
+       [ 3., nan],
+       [ 4.,  5.]])
+
+
+

You can specify an alternative fill value:

+
>>> ragged_to_regular(np.array([1, 2, 3, 4, 5]), np.array([2, 1, 2]), fill_value=999)
+array([[ 1.,    2.],
+       [ 3., -999.],
+       [ 4.,    5.]])
+
+
+
+
+

See Also#

+

regular_to_ragged()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.regular_to_ragged.html b/_autosummary/clouddrift.ragged.regular_to_ragged.html new file mode 100644 index 00000000..6908c27b --- /dev/null +++ b/_autosummary/clouddrift.ragged.regular_to_ragged.html @@ -0,0 +1,604 @@ + + + + + + + + + + + clouddrift.ragged.regular_to_ragged — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.regular_to_ragged

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.regular_to_ragged#

+
+
+clouddrift.ragged.regular_to_ragged(array: ndarray, fill_value: float = nan) tuple[ndarray, ndarray][source]#
+

Convert a two-dimensional array to a ragged array. Fill values in the input array are +excluded from the output ragged array.

+
+

Parameters#

+
+
arraynp.ndarray

A two-dimensional array.

+
+
fill_valuefloat, optional

Fill value used to determine the bounds of contiguous segments.

+
+
+
+
+

Returns#

+
+
tuple[np.ndarray, np.ndarray]

A tuple of the ragged array and the size of each row.

+
+
+
+
+

Examples#

+

By default, NaN values found in the input regular array are excluded from +the output ragged array:

+
>>> regular_to_ragged(np.array([[1, 2], [3, np.nan], [4, 5]]))
+(array([1., 2., 3., 4., 5.]), array([2, 1, 2]))
+
+
+

Alternatively, a different fill value can be specified:

+
>>> regular_to_ragged(np.array([[1, 2], [3, -999], [4, 5]]), fill_value=-999)
+(array([1., 2., 3., 4., 5.]), array([2, 1, 2]))
+
+
+
+
+

See Also#

+

ragged_to_regular()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.rowsize_to_index.html b/_autosummary/clouddrift.ragged.rowsize_to_index.html new file mode 100644 index 00000000..bf59d439 --- /dev/null +++ b/_autosummary/clouddrift.ragged.rowsize_to_index.html @@ -0,0 +1,593 @@ + + + + + + + + + + + clouddrift.ragged.rowsize_to_index — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.rowsize_to_index

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.rowsize_to_index#

+
+
+clouddrift.ragged.rowsize_to_index(rowsize: list | ndarray | DataArray) ndarray[source]#
+

Convert a list of row sizes to a list of indices.

+

This function is typically used to obtain the indices of data rows organized +in a ragged array.

+
+

Parameters#

+
+
rowsizelist or np.ndarray or xr.DataArray

A list of row sizes.

+
+
+
+
+

Returns#

+
+
np.ndarray

A list of indices.

+
+
+
+
+

Examples#

+

To obtain the indices within a ragged array of three consecutive rows of sizes 100, 202, and 53:

+
>>> rowsize_to_index([100, 202, 53])
+array([0, 100, 302, 355])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.segment.html b/_autosummary/clouddrift.ragged.segment.html new file mode 100644 index 00000000..96b89842 --- /dev/null +++ b/_autosummary/clouddrift.ragged.segment.html @@ -0,0 +1,634 @@ + + + + + + + + + + + clouddrift.ragged.segment — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.segment

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.segment#

+
+
+clouddrift.ragged.segment(x: ndarray, tolerance: float | timedelta64 | timedelta | Timedelta, rowsize: ndarray[int] = None) ndarray[int][source]#
+

Divide an array into segments based on a tolerance value.

+
+

Parameters#

+
+
xlist, np.ndarray, or xr.DataArray

An array to divide into segment.

+
+
tolerancefloat, np.timedelta64, timedelta, pd.Timedelta

The maximum signed difference between consecutive points in a segment. +The array x will be segmented wherever differences exceed the tolerance.

+
+
rowsizenp.ndarray[int], optional

The size of rows if x is originally a ragged array. If present, x will be +divided both by gaps that exceed the tolerance, and by the original rows +of the ragged array.

+
+
+
+
+

Returns#

+
+
np.ndarray[int]

An array of row sizes that divides the input array into segments.

+
+
+
+
+

Examples#

+

The simplest use of segment is to provide a tolerance value that is +used to divide an array into segments:

+
>>> x = [0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4]
+>>> segment(x, 0.5)
+array([1, 3, 2, 4, 1])
+
+
+

If the array is already previously segmented (e.g. multiple rows in +a ragged array), then the rowsize argument can be used to preserve +the original segments:

+
>>> x = [0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4]
+>>> rowsize = [3, 2, 6]
+>>> segment(x, 0.5, rowsize)
+array([1, 2, 1, 1, 1, 4, 1])
+
+
+

The tolerance can also be negative. In this case, the input array is +segmented where the negative difference exceeds the negative +value of the tolerance, i.e. where x[n+1] - x[n] < -tolerance:

+
>>> x = [0, 1, 2, 0, 1, 2]
+>>> segment(x, -0.5)
+array([3, 3])
+
+
+

To segment an array for both positive and negative gaps, invoke the function +twice, once for a positive tolerance and once for a negative tolerance. +The result of the first invocation can be passed as the rowsize argument +to the first segment invocation:

+
>>> x = [1, 1, 2, 2, 1, 1, 2, 2]
+>>> segment(x, 0.5, rowsize=segment(x, -0.5))
+array([2, 2, 2, 2])
+
+
+

If the input array contains time objects, the tolerance must be a time interval:

+
>>> x = np.array([np.datetime64("2023-01-01"), np.datetime64("2023-01-02"),
+                  np.datetime64("2023-01-03"), np.datetime64("2023-02-01"),
+                  np.datetime64("2023-02-02")])
+>>> segment(x, np.timedelta64(1, "D"))
+np.array([3, 2])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.subset.html b/_autosummary/clouddrift.ragged.subset.html new file mode 100644 index 00000000..963b9d79 --- /dev/null +++ b/_autosummary/clouddrift.ragged.subset.html @@ -0,0 +1,668 @@ + + + + + + + + + + + clouddrift.ragged.subset — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.subset

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.subset#

+
+
+clouddrift.ragged.subset(ds: Dataset, criteria: dict, id_var_name: str = 'id', rowsize_var_name: str = 'rowsize', traj_dim_name: str = 'traj', obs_dim_name: str = 'obs', full_trajectories=False) Dataset[source]#
+

Subset a ragged array dataset as a function of one or more criteria. +The criteria are passed with a dictionary, where a dictionary key +is a variable to subset and the associated dictionary value is either a range +(valuemin, valuemax), a list [value1, value2, valueN], a single value, or a +masking function applied to every row of the ragged array using apply_ragged.

+

This function needs to know the names of the dimensions of the ragged array dataset +(traj_dim_name and obs_dim_name), and the name of the rowsize variable (rowsize_var_name). +Default values are provided for these arguments (see below), but they can be changed if needed.

+
+

Parameters#

+
+
dsxr.Dataset

Dataset stored as ragged arrays

+
+
criteriadict

dictionary containing the variables (as keys) and the ranges/values/functions (as values) to subset

+
+
id_var_namestr, optional

Name of the variable containing the ID of the trajectories (default is “id”)

+
+
rowsize_var_namestr, optional

Name of the variable containing the number of observations per trajectory (default is “rowsize”)

+
+
traj_dim_namestr, optional

Name of the trajectory dimension (default is “traj”)

+
+
obs_dim_namestr, optional

Name of the observation dimension (default is “obs”)

+
+
full_trajectoriesbool, optional

If True, it returns the complete trajectories (rows) where at least one observation +matches the criteria, rather than just the segments where the criteria are satisfied. +Default is False.

+
+
+
+
+

Returns#

+
+
xr.Dataset

subset Dataset matching the criterion(a)

+
+
+
+
+

Examples#

+

Criteria are combined on any data or metadata variables part of the Dataset. +The following examples are based on NOAA GDP datasets which can be accessed with the +clouddrift.datasets module.

+

Retrieve a region, like the Gulf of Mexico, using ranges of latitude and longitude:

+
>>> subset(ds, {"lat": (21, 31), "lon": (-98, -78)})
+
+
+

The parameter full_trajectories can be used to retrieve trajectories passing through a region, for example all trajectories passing through the Gulf of Mexico:

+
>>> subset(ds, {"lat": (21, 31), "lon": (-98, -78)}, full_trajectories=True)
+
+
+

Retrieve drogued trajectory segments:

+
>>> subset(ds, {"drogue_status": True})
+
+
+

Retrieve trajectory segments with temperature higher than 25°C (303.15K):

+
>>> subset(ds, {"sst": (303.15, np.inf)})
+
+
+

You can use the same approach to return only the trajectories that are +shorter than some number of observations (similar to prune() but for +the entire dataset):

+
>>> subset(ds, {"rowsize": (0, 1000)})
+
+
+

Retrieve specific drifters from their IDs:

+
>>> subset(ds, {"id": [2578, 2582, 2583]})
+
+
+

Sometimes, you may want to retrieve specific rows of a ragged array. +You can do that by filtering along the trajectory dimension directly, since +this one corresponds to row numbers:

+
>>> rows = [5, 6, 7]
+>>> subset(ds, {"traj": rows})
+
+
+

Retrieve a specific time period:

+
>>> subset(ds, {"time": (np.datetime64("2000-01-01"), np.datetime64("2020-01-31"))})
+
+
+

Note that to subset time variable, the range has to be defined as a function +type of the variable. By default, xarray uses np.datetime64 to +represent datetime data. If the datetime data is a datetime.datetime, or +pd.Timestamp, the range would have to be defined accordingly.

+

Those criteria can also be combined:

+
>>> subset(ds, {"lat": (21, 31), "lon": (-98, -78), "drogue_status": True, "sst": (303.15, np.inf), "time": (np.datetime64("2000-01-01"), np.datetime64("2020-01-31"))})
+
+
+

You can also use a function to filter the data. For example, retrieve every other observation +of each trajectory (row):

+
>>> func = (lambda arr: ((arr - arr[0]) % 2) == 0)
+>>> subset(ds, {"time": func})
+
+
+
+
+

Raises#

+
+
ValueError

If one of the variable in a criterion is not found in the Dataset

+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.ragged.unpack.html b/_autosummary/clouddrift.ragged.unpack.html new file mode 100644 index 00000000..043fc6c9 --- /dev/null +++ b/_autosummary/clouddrift.ragged.unpack.html @@ -0,0 +1,614 @@ + + + + + + + + + + + clouddrift.ragged.unpack — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.ragged.unpack

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.ragged.unpack#

+
+
+clouddrift.ragged.unpack(ragged_array: ndarray, rowsize: ndarray[int], rows: int | Iterable[int] = None, axis: int = 0) list[ndarray][source]#
+

Unpack a ragged array into a list of regular arrays.

+

Unpacking a np.ndarray ragged array is about 2 orders of magnitude +faster than unpacking an xr.DataArray ragged array, so unless you need a +DataArray as the result, we recommend passing np.ndarray as input.

+
+

Parameters#

+
+
ragged_arrayarray-like

A ragged_array to unpack

+
+
rowsizearray-like

An array of integers whose values is the size of each row in the ragged +array

+
+
rowsint or Iterable[int], optional

A row or list of rows to unpack. Default is None, which unpacks all rows.

+
+
axisint, optional

The axis along which to unpack the ragged array. Default is 0.

+
+
+
+
+

Returns#

+
+
list

A list of array-likes with sizes that correspond to the values in +rowsize, and types that correspond to the type of ragged_array

+
+
+
+
+

Examples#

+

Unpacking longitude arrays from a ragged Xarray Dataset:

+
lon = unpack(ds.lon, ds["rowsize"]) # return a list[xr.DataArray] (slower)
+lon = unpack(ds.lon.values, ds["rowsize"]) # return a list[np.ndarray] (faster)
+first_lon = unpack(ds.lon.values, ds["rowsize"], rows=0) # return only the first row
+first_two_lons = unpack(ds.lon.values, ds["rowsize"], rows=[0, 1]) # return first two rows
+
+
+

Looping over trajectories in a ragged Xarray Dataset to compute velocities +for each:

+
for lon, lat, time in list(zip(
+    unpack(ds.lon.values, ds["rowsize"]),
+    unpack(ds.lat.values, ds["rowsize"]),
+    unpack(ds.time.values, ds["rowsize"])
+)):
+    u, v = velocity_from_position(lon, lat, time)
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.raggedarray.RaggedArray.html b/_autosummary/clouddrift.raggedarray.RaggedArray.html new file mode 100644 index 00000000..a439e103 --- /dev/null +++ b/_autosummary/clouddrift.raggedarray.RaggedArray.html @@ -0,0 +1,919 @@ + + + + + + + + + + + clouddrift.raggedarray.RaggedArray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.raggedarray.RaggedArray#

+
+
+class clouddrift.raggedarray.RaggedArray(coords: dict, metadata: dict, data: dict, attrs_global: dict | None = {}, attrs_variables: dict | None = {})[source]#
+

Bases: object

+
+
+__init__(coords: dict, metadata: dict, data: dict, attrs_global: dict | None = {}, attrs_variables: dict | None = {})[source]#
+
+ +

Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

__init__(coords, metadata, data[, ...])

allocate(preprocess_func, indices, rowsize, ...)

Iterate through the files and fill for the ragged array associated with coordinates, and selected metadata and data variables.

attributes(ds, name_coords, name_meta, name_data)

Return global attributes and the attributes of all variables (name_coords, name_meta, and name_data) from an Xarray Dataset.

from_awkward(array[, name_coords])

Load a RaggedArray instance from an Awkward Array.

from_files(indices, preprocess_func, name_coords)

Generate a ragged array archive from a list of trajectory files

from_netcdf(filename)

Read a ragged arrays archive from a NetCDF file.

from_parquet(filename[, name_coords])

Read a ragged array from a parquet file.

from_xarray(ds[, dim_traj, dim_obs])

Populate a RaggedArray instance from an xarray Dataset instance.

number_of_observations(rowsize_func, ...)

Iterate through the files and evaluate the number of observations.

to_awkward()

Convert ragged array object to an Awkward Array.

to_netcdf(filename)

Export ragged array object to a NetCDF file.

to_parquet(filename)

Export ragged array object to a parquet file.

to_xarray([cast_to_float32])

Convert ragged array object to a xarray Dataset.

validate_attributes()

Validate that each variable has an assigned attribute tag.

+
+
+static allocate(preprocess_func: Callable[[int], Dataset], indices: list, rowsize: list, name_coords: list, name_meta: list, name_data: list, **kwargs) Tuple[dict, dict, dict][source]#
+

Iterate through the files and fill for the ragged array associated +with coordinates, and selected metadata and data variables.

+
+

Parameters#

+
+
preprocess_funcCallable[[int], xr.Dataset]

Returns a processed xarray Dataset from an identification number.

+
+
indiceslist

List of indices separating trajectory in the ragged arrays.

+
+
rowsizelist

List of the number of observations per trajectory.

+
+
name_coordslist

Name of the coordinate variables to include in the archive.

+
+
name_metalist, optional

Name of metadata variables to include in the archive (Defaults to []).

+
+
name_datalist, optional

Name of the data variables to include in the archive (Defaults to []).

+
+
+
+
+

Returns#

+
+
Tuple[dict, dict, dict]

Dictionaries containing numerical data and attributes of coordinates, metadata and data variables.

+
+
+
+
+ +
+
+static attributes(ds: Dataset, name_coords: list, name_meta: list, name_data: list) Tuple[dict, dict][source]#
+

Return global attributes and the attributes of all variables +(name_coords, name_meta, and name_data) from an Xarray Dataset.

+
+

Parameters#

+
+
dsxr.Dataset

_description_

+
+
name_coordslist

Name of the coordinate variables to include in the archive

+
+
name_metalist, optional

Name of metadata variables to include in the archive (default is [])

+
+
name_datalist, optional

Name of the data variables to include in the archive (default is [])

+
+
+
+
+

Returns#

+
+
Tuple[dict, dict]

The global and variables attributes

+
+
+
+
+ +
+
+classmethod from_awkward(array: Array, name_coords: list | None = ['time', 'lon', 'lat', 'ids'])[source]#
+

Load a RaggedArray instance from an Awkward Array.

+
+

Parameters#

+
+
arrayak.Array

Awkward Array instance to load the data from

+
+
name_coordslist, optional

Names of the coordinate variables in the ragged arrays

+
+
+
+
+

Returns#

+
+
RaggedArray

A RaggedArray instance

+
+
+
+
+ +
+
+classmethod from_files(indices: list, preprocess_func: Callable[[int], Dataset], name_coords: list, name_meta: list | None = [], name_data: list | None = [], rowsize_func: Callable[[int], int] | None = None, **kwargs)[source]#
+

Generate a ragged array archive from a list of trajectory files

+
+

Parameters#

+
+
indiceslist

Identification numbers list to iterate

+
+
preprocess_funcCallable[[int], xr.Dataset]

Returns a processed xarray Dataset from an identification number

+
+
name_coordslist

Name of the coordinate variables to include in the archive

+
+
name_metalist, optional

Name of metadata variables to include in the archive (Defaults to [])

+
+
name_datalist, optional

Name of the data variables to include in the archive (Defaults to [])

+
+
rowsize_funcOptional[Callable[[int], int]], optional

Returns the number of observations from an identification number (to speed up processing) (Defaults to None)

+
+
+
+
+

Returns#

+
+
RaggedArray

A RaggedArray instance

+
+
+
+
+ +
+
+classmethod from_netcdf(filename: str)[source]#
+

Read a ragged arrays archive from a NetCDF file.

+

This is a thin wrapper around from_xarray().

+
+

Parameters#

+
+
filenamestr

File name of the NetCDF archive to read.

+
+
+
+
+

Returns#

+
+
RaggedArray

A ragged array instance

+
+
+
+
+ +
+
+classmethod from_parquet(filename: str, name_coords: list | None = ['time', 'lon', 'lat', 'ids'])[source]#
+

Read a ragged array from a parquet file.

+
+

Parameters#

+
+
filenamestr

File name of the parquet archive to read.

+
+
name_coordslist, optional

Names of the coordinate variables in the ragged arrays

+
+
+
+
+

Returns#

+
+
RaggedArray

A ragged array instance

+
+
+
+
+ +
+
+classmethod from_xarray(ds: Dataset, dim_traj: str = 'traj', dim_obs: str = 'obs')[source]#
+

Populate a RaggedArray instance from an xarray Dataset instance.

+
+

Parameters#

+
+
dsxr.Dataset

Xarray Dataset from which to load the RaggedArray

+
+
dim_trajstr, optional

Name of the trajectories dimension in the xarray Dataset

+
+
dim_obsstr, optional

Name of the observations dimension in the xarray Dataset

+
+
+
+
+

Returns#

+
+
RaggedArray

A RaggedArray instance

+
+
+
+
+ +
+
+static number_of_observations(rowsize_func: Callable[[int], int], indices: list, **kwargs) array[source]#
+

Iterate through the files and evaluate the number of observations.

+
+

Parameters#

+
+
rowsize_funcCallable[[int], int]]

Function that returns the number observations of a trajectory from +its identification number

+
+
indiceslist

Identification numbers list to iterate

+
+
+
+
+

Returns#

+
+
np.ndarray

Number of observations of each trajectory

+
+
+
+
+ +
+
+to_awkward()[source]#
+

Convert ragged array object to an Awkward Array.

+
+

Returns#

+
+
ak.Array

Awkward Array containing the ragged array and its attributes

+
+
+
+
+ +
+
+to_netcdf(filename: str)[source]#
+

Export ragged array object to a NetCDF file.

+
+

Parameters#

+
+
filenamestr

Name of the NetCDF file to create.

+
+
+
+
+ +
+
+to_parquet(filename: str)[source]#
+

Export ragged array object to a parquet file.

+
+

Parameters#

+
+
filenamestr

Name of the parquet file to create.

+
+
+
+
+ +
+
+to_xarray(cast_to_float32: bool = True)[source]#
+

Convert ragged array object to a xarray Dataset.

+
+

Parameters#

+
+
cast_to_float32bool, optional

Cast all float64 variables to float32 (default is True). This option aims at +minimizing the size of the xarray dataset.

+
+
+
+
+

Returns#

+
+
xr.Dataset

Xarray Dataset containing the ragged arrays and their attributes

+
+
+
+
+ +
+
+validate_attributes()[source]#
+

Validate that each variable has an assigned attribute tag.

+
+ +
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.raggedarray.html b/_autosummary/clouddrift.raggedarray.html new file mode 100644 index 00000000..6cdb1cfb --- /dev/null +++ b/_autosummary/clouddrift.raggedarray.html @@ -0,0 +1,551 @@ + + + + + + + + + + + clouddrift.raggedarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.raggedarray

+ +
+
+ +
+
+
+ + + + +
+ +
+

clouddrift.raggedarray#

+

This module defines the RaggedArray class, which is the intermediate data +structure used by CloudDrift to process custom Lagrangian datasets to Xarray +Datasets and Awkward Arrays.

+

Classes

+ + + + + + +

RaggedArray(coords, metadata, data[, ...])

+
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.signal.analytic_signal.html b/_autosummary/clouddrift.signal.analytic_signal.html new file mode 100644 index 00000000..1e18b149 --- /dev/null +++ b/_autosummary/clouddrift.signal.analytic_signal.html @@ -0,0 +1,644 @@ + + + + + + + + + + + clouddrift.signal.analytic_signal — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.signal.analytic_signal

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.signal.analytic_signal#

+
+
+clouddrift.signal.analytic_signal(x: ndarray | DataArray, boundary: str | None = 'mirror', time_axis: int | None = -1) ndarray | Tuple[ndarray, ndarray][source]#
+

Return the analytic signal from a real-valued signal or the analytic and +conjugate analytic signals from a complex-valued signal.

+

If the input is a real-valued signal, the analytic signal is calculated as +the inverse Fourier transform of the positive-frequency part of the Fourier +transform. If the input is a complex-valued signal, the conjugate analytic signal +is additionally calculated as the inverse Fourier transform of the positive-frequency +part of the Fourier transform of the complex conjugate of the input signal.

+

For a complex-valued signal, the mean is evenly divided between the analytic and +conjugate analytic signal.

+

The calculation is performed along the last axis of the input array by default. +Alternatively, the user can specify the time axis of the input. The user can also +specify the boundary conditions to be applied to the input array (default is “mirror”).

+
+

Parameters#

+
+
xarray_like

Real- or complex-valued signal.

+
+
boundarystr, optional

The boundary condition to be imposed at the edges of the time series. +Allowed values are “mirror”, “zeros”, and “periodic”. +Default is “mirror”.

+
+
time_axisint, optional

Axis on which the time is defined (default is -1).

+
+
+
+
+

Returns#

+
+
xanp.ndarray

Analytic signal. It is a tuple if the input is a complex-valed signal +with the first element being the analytic signal and the second element +being the conjugate analytic signal.

+
+
+
+
+

Examples#

+

To obtain the analytic signal of a real-valued signal:

+
>>> x = np.random.rand(99)
+>>> xa = analytic_signal(x)
+
+
+

To obtain the analytic and conjugate analytic signals of a complex-valued signal:

+
>>> w = np.random.rand(99)+1j*np.random.rand(99)
+>>> wp, wn = analytic_signal(w)
+
+
+

To specify that a periodic boundary condition should be used:

+
>>> x = np.random.rand(99)
+>>> xa = analytic_signal(x, boundary="periodic")
+
+
+

To specify that the time axis is along the first axis and apply +zero boundary conditions:

+
>>> x = np.random.rand(100, 99)
+>>> xa = analytic_signal(x, time_axis=0, boundary="zeros")
+
+
+
+
+

Raises#

+
+
ValueError

If the time axis is outside of the valid range ([-1, N-1]). +If boundary not in ["mirror", "zeros", "periodic"].

+
+
+
+
+

References#

+

[1] Gabor D. 1946 Theory of communication. Proc. IEE 93, 429–457. (10.1049/ji-1.1947.0015).

+

[2] Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729).

+
+
+

See Also#

+

rotary_to_cartesian(), cartesian_to_rotary()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.signal.cartesian_to_rotary.html b/_autosummary/clouddrift.signal.cartesian_to_rotary.html new file mode 100644 index 00000000..231940f1 --- /dev/null +++ b/_autosummary/clouddrift.signal.cartesian_to_rotary.html @@ -0,0 +1,626 @@ + + + + + + + + + + + clouddrift.signal.cartesian_to_rotary — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.signal.cartesian_to_rotary

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.signal.cartesian_to_rotary#

+
+
+clouddrift.signal.cartesian_to_rotary(ua: ndarray | DataArray, va: ndarray | DataArray, time_axis: int | None = -1) Tuple[ndarray, ndarray][source]#
+

Return rotary signals (wp,wn) from analytic Cartesian signals (ua,va).

+

If ua is the analytic signal from real-valued signal u, and va the analytic signal +from real-valued signal v, then the positive (counterclockwise) and negative (clockwise) +signals are defined by wp = 0.5*(up+1j*vp), wp = 0.5*(up-1j*vp).

+

This function is the inverse of rotary_to_cartesian().

+
+

Parameters#

+
+
uaarray_like

Complex-valued analytic signal for first Cartesian component (zonal, east-west)

+
+
vaarray_like

Complex-valued analytic signal for second Cartesian component (meridional, north-south)

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
wpnp.ndarray

Complex-valued positive (counterclockwise) rotary signal.

+
+
wnnp.ndarray

Complex-valued negative (clockwise) rotary signal.

+
+
+
+
+

Examples#

+

To obtain the rotary signals from a pair of real-valued signal:

+
>>> u = np.random.rand(99)
+>>> v = np.random.rand(99)
+>>> wp, wn = cartesian_to_rotary(analytic_signal(u), analytic_signal(v))
+
+
+

To specify that the time axis is along the first axis:

+
>>> u = np.random.rand(100, 99)
+>>> v = np.random.rand(100, 99)
+>>> wp, wn = cartesian_to_rotary(analytic_signal(u), analytic_signal(v), time_axis=0)
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]).

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729)

+
+
+

See Also#

+

analytic_signal(), rotary_to_cartesian()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.signal.ellipse_parameters.html b/_autosummary/clouddrift.signal.ellipse_parameters.html new file mode 100644 index 00000000..648191ce --- /dev/null +++ b/_autosummary/clouddrift.signal.ellipse_parameters.html @@ -0,0 +1,614 @@ + + + + + + + + + + + clouddrift.signal.ellipse_parameters — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.signal.ellipse_parameters

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.signal.ellipse_parameters#

+
+
+clouddrift.signal.ellipse_parameters(xa: ndarray | DataArray, ya: ndarray | DataArray) Tuple[ndarray, ndarray, ndarray, ndarray][source]#
+

Return the instantaneous parameters of a modulated elliptical signal from its analytic Cartesian signals.

+
+

Parameters#

+
+
xaarray_like

Complex-valued analytic signal for first Cartesian component (zonal, east-west).

+
+
yaarray_like

Complex-valued analytic signal for second Cartesian component (meridional, north-south).

+
+
+
+
+

Returns#

+
+
kappanp.ndarray

Ellipse root-mean-square amplitude.

+
+
lambdanp.ndarray

Ellipse linearity between -1 and 1, or departure from circular motion (lambda=0).

+
+
thetanp.ndarray

Ellipse orientation in radian.

+
+
phinp.ndarray

Ellipse phase in radian.

+
+
+
+
+

Examples#

+

To obtain the ellipse parameters from a pair of real-valued signals (x, y):

+
>>> kappa, lambda, theta, phi = ellipse_parameters(analytic_signal(x), analytic_signal(y))
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape.

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729).

+
+
+

See Also#

+

modulated_ellipse_signal(), analytic_signal(), rotary_to_cartesian(), cartesian_to_rotary()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.signal.html b/_autosummary/clouddrift.signal.html new file mode 100644 index 00000000..2effca1a --- /dev/null +++ b/_autosummary/clouddrift.signal.html @@ -0,0 +1,899 @@ + + + + + + + + + + + clouddrift.signal — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.signal#

+

This module provides signal processing functions.

+

Functions

+ + + + + + + + + + + + + + + + + + +

analytic_signal(x[, boundary, time_axis])

Return the analytic signal from a real-valued signal or the analytic and conjugate analytic signals from a complex-valued signal.

cartesian_to_rotary(ua, va[, time_axis])

Return rotary signals (wp,wn) from analytic Cartesian signals (ua,va).

ellipse_parameters(xa, ya)

Return the instantaneous parameters of a modulated elliptical signal from its analytic Cartesian signals.

modulated_ellipse_signal(kappa, lambda_, ...)

Return the analytic Cartesian signals (xa, ya) from the instantaneous parameters of a modulated elliptical signal.

rotary_to_cartesian(wp, wn[, time_axis])

Return Cartesian analytic signals (ua, va) from rotary signals (wp, wn) as ua = wp + wn and va = -1j * (wp - wn).

+
+
+clouddrift.signal.analytic_signal(x: ndarray | DataArray, boundary: str | None = 'mirror', time_axis: int | None = -1) ndarray | Tuple[ndarray, ndarray][source]#
+

Return the analytic signal from a real-valued signal or the analytic and +conjugate analytic signals from a complex-valued signal.

+

If the input is a real-valued signal, the analytic signal is calculated as +the inverse Fourier transform of the positive-frequency part of the Fourier +transform. If the input is a complex-valued signal, the conjugate analytic signal +is additionally calculated as the inverse Fourier transform of the positive-frequency +part of the Fourier transform of the complex conjugate of the input signal.

+

For a complex-valued signal, the mean is evenly divided between the analytic and +conjugate analytic signal.

+

The calculation is performed along the last axis of the input array by default. +Alternatively, the user can specify the time axis of the input. The user can also +specify the boundary conditions to be applied to the input array (default is “mirror”).

+
+

Parameters#

+
+
xarray_like

Real- or complex-valued signal.

+
+
boundarystr, optional

The boundary condition to be imposed at the edges of the time series. +Allowed values are “mirror”, “zeros”, and “periodic”. +Default is “mirror”.

+
+
time_axisint, optional

Axis on which the time is defined (default is -1).

+
+
+
+
+

Returns#

+
+
xanp.ndarray

Analytic signal. It is a tuple if the input is a complex-valed signal +with the first element being the analytic signal and the second element +being the conjugate analytic signal.

+
+
+
+
+

Examples#

+

To obtain the analytic signal of a real-valued signal:

+
>>> x = np.random.rand(99)
+>>> xa = analytic_signal(x)
+
+
+

To obtain the analytic and conjugate analytic signals of a complex-valued signal:

+
>>> w = np.random.rand(99)+1j*np.random.rand(99)
+>>> wp, wn = analytic_signal(w)
+
+
+

To specify that a periodic boundary condition should be used:

+
>>> x = np.random.rand(99)
+>>> xa = analytic_signal(x, boundary="periodic")
+
+
+

To specify that the time axis is along the first axis and apply +zero boundary conditions:

+
>>> x = np.random.rand(100, 99)
+>>> xa = analytic_signal(x, time_axis=0, boundary="zeros")
+
+
+
+
+

Raises#

+
+
ValueError

If the time axis is outside of the valid range ([-1, N-1]). +If boundary not in ["mirror", "zeros", "periodic"].

+
+
+
+
+

References#

+

[1] Gabor D. 1946 Theory of communication. Proc. IEE 93, 429–457. (10.1049/ji-1.1947.0015).

+

[2] Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729).

+
+
+

See Also#

+

rotary_to_cartesian(), cartesian_to_rotary()

+
+
+ +
+
+clouddrift.signal.cartesian_to_rotary(ua: ndarray | DataArray, va: ndarray | DataArray, time_axis: int | None = -1) Tuple[ndarray, ndarray][source]#
+

Return rotary signals (wp,wn) from analytic Cartesian signals (ua,va).

+

If ua is the analytic signal from real-valued signal u, and va the analytic signal +from real-valued signal v, then the positive (counterclockwise) and negative (clockwise) +signals are defined by wp = 0.5*(up+1j*vp), wp = 0.5*(up-1j*vp).

+

This function is the inverse of rotary_to_cartesian().

+
+

Parameters#

+
+
uaarray_like

Complex-valued analytic signal for first Cartesian component (zonal, east-west)

+
+
vaarray_like

Complex-valued analytic signal for second Cartesian component (meridional, north-south)

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
wpnp.ndarray

Complex-valued positive (counterclockwise) rotary signal.

+
+
wnnp.ndarray

Complex-valued negative (clockwise) rotary signal.

+
+
+
+
+

Examples#

+

To obtain the rotary signals from a pair of real-valued signal:

+
>>> u = np.random.rand(99)
+>>> v = np.random.rand(99)
+>>> wp, wn = cartesian_to_rotary(analytic_signal(u), analytic_signal(v))
+
+
+

To specify that the time axis is along the first axis:

+
>>> u = np.random.rand(100, 99)
+>>> v = np.random.rand(100, 99)
+>>> wp, wn = cartesian_to_rotary(analytic_signal(u), analytic_signal(v), time_axis=0)
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]).

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729)

+
+
+

See Also#

+

analytic_signal(), rotary_to_cartesian()

+
+
+ +
+
+clouddrift.signal.ellipse_parameters(xa: ndarray | DataArray, ya: ndarray | DataArray) Tuple[ndarray, ndarray, ndarray, ndarray][source]#
+

Return the instantaneous parameters of a modulated elliptical signal from its analytic Cartesian signals.

+
+

Parameters#

+
+
xaarray_like

Complex-valued analytic signal for first Cartesian component (zonal, east-west).

+
+
yaarray_like

Complex-valued analytic signal for second Cartesian component (meridional, north-south).

+
+
+
+
+

Returns#

+
+
kappanp.ndarray

Ellipse root-mean-square amplitude.

+
+
lambdanp.ndarray

Ellipse linearity between -1 and 1, or departure from circular motion (lambda=0).

+
+
thetanp.ndarray

Ellipse orientation in radian.

+
+
phinp.ndarray

Ellipse phase in radian.

+
+
+
+
+

Examples#

+

To obtain the ellipse parameters from a pair of real-valued signals (x, y):

+
>>> kappa, lambda, theta, phi = ellipse_parameters(analytic_signal(x), analytic_signal(y))
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape.

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729).

+
+
+

See Also#

+

modulated_ellipse_signal(), analytic_signal(), rotary_to_cartesian(), cartesian_to_rotary()

+
+
+ +
+
+clouddrift.signal.modulated_ellipse_signal(kappa: ndarray | DataArray, lambda_: ndarray | DataArray, theta: ndarray | DataArray, phi: ndarray | DataArray) Tuple[ndarray, ndarray][source]#
+

Return the analytic Cartesian signals (xa, ya) from the instantaneous parameters of a modulated elliptical signal.

+

This function is the inverse of ellipse_parameters().

+
+

Parameters#

+
+
kappaarray_like

Ellipse root-mean-square amplitude.

+
+
lambdaarray_like

Ellipse linearity between -1 and 1, or departure from circular motion (lambda=0).

+
+
thetaarray_like

Ellipse orientation in radian.

+
+
phiarray_like

Ellipse phase in radian.

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
xanp.ndarray

Complex-valued analytic signal for first Cartesian component (zonal, east-west).

+
+
yanp.ndarray

Complex-valued analytic signal for second Cartesian component (meridional, north-south).

+
+
+
+
+

Examples#

+

To obtain the analytic signals from the instantaneous parameters of a modulated elliptical signal:

+
>>> xa, ya = modulated_ellipse_signal(kappa, lambda, theta, phi)
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape.

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729).

+
+
+

See Also#

+

ellipse_parameters(), analytic_signal(), rotary_to_cartesian(), cartesian_to_rotary()

+
+
+ +
+
+clouddrift.signal.rotary_to_cartesian(wp: ndarray | DataArray, wn: ndarray | DataArray, time_axis: int | None = -1) Tuple[ndarray, ndarray][source]#
+

Return Cartesian analytic signals (ua, va) from rotary signals (wp, wn) +as ua = wp + wn and va = -1j * (wp - wn).

+

This function is the inverse of cartesian_to_rotary().

+
+

Parameters#

+
+
wparray_like

Complex-valued positive (counterclockwise) rotary signal.

+
+
wnarray_like

Complex-valued negative (clockwise) rotary signal.

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
uaarray_like

Complex-valued analytic signal, first Cartesian component (zonal, east-west)

+
+
vaarray_like

Complex-valued analytic signal, second Cartesian component (meridional, north-south)

+
+
+
+
+

Examples#

+

To obtain the Cartesian analytic signals from a pair of rotary signals (wp,wn):

+
>>> ua, va = rotary_to_cartesian(wp, wn)
+
+
+

To specify that the time axis is along the first axis:

+
>>> ua, va = rotary_to_cartesian(wp, wn, time_axis=0)
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]).

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729)

+
+
+

See Also#

+

analytic_signal(), cartesian_to_rotary()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.signal.modulated_ellipse_signal.html b/_autosummary/clouddrift.signal.modulated_ellipse_signal.html new file mode 100644 index 00000000..340acd18 --- /dev/null +++ b/_autosummary/clouddrift.signal.modulated_ellipse_signal.html @@ -0,0 +1,618 @@ + + + + + + + + + + + clouddrift.signal.modulated_ellipse_signal — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.signal.modulated_ellipse_signal

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.signal.modulated_ellipse_signal#

+
+
+clouddrift.signal.modulated_ellipse_signal(kappa: ndarray | DataArray, lambda_: ndarray | DataArray, theta: ndarray | DataArray, phi: ndarray | DataArray) Tuple[ndarray, ndarray][source]#
+

Return the analytic Cartesian signals (xa, ya) from the instantaneous parameters of a modulated elliptical signal.

+

This function is the inverse of ellipse_parameters().

+
+

Parameters#

+
+
kappaarray_like

Ellipse root-mean-square amplitude.

+
+
lambdaarray_like

Ellipse linearity between -1 and 1, or departure from circular motion (lambda=0).

+
+
thetaarray_like

Ellipse orientation in radian.

+
+
phiarray_like

Ellipse phase in radian.

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
xanp.ndarray

Complex-valued analytic signal for first Cartesian component (zonal, east-west).

+
+
yanp.ndarray

Complex-valued analytic signal for second Cartesian component (meridional, north-south).

+
+
+
+
+

Examples#

+

To obtain the analytic signals from the instantaneous parameters of a modulated elliptical signal:

+
>>> xa, ya = modulated_ellipse_signal(kappa, lambda, theta, phi)
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape.

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729).

+
+
+

See Also#

+

ellipse_parameters(), analytic_signal(), rotary_to_cartesian(), cartesian_to_rotary()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.signal.rotary_to_cartesian.html b/_autosummary/clouddrift.signal.rotary_to_cartesian.html new file mode 100644 index 00000000..72358107 --- /dev/null +++ b/_autosummary/clouddrift.signal.rotary_to_cartesian.html @@ -0,0 +1,620 @@ + + + + + + + + + + + clouddrift.signal.rotary_to_cartesian — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.signal.rotary_to_cartesian

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.signal.rotary_to_cartesian#

+
+
+clouddrift.signal.rotary_to_cartesian(wp: ndarray | DataArray, wn: ndarray | DataArray, time_axis: int | None = -1) Tuple[ndarray, ndarray][source]#
+

Return Cartesian analytic signals (ua, va) from rotary signals (wp, wn) +as ua = wp + wn and va = -1j * (wp - wn).

+

This function is the inverse of cartesian_to_rotary().

+
+

Parameters#

+
+
wparray_like

Complex-valued positive (counterclockwise) rotary signal.

+
+
wnarray_like

Complex-valued negative (clockwise) rotary signal.

+
+
time_axisint, optional

The axis of the time array. Default is -1, which corresponds to the +last axis.

+
+
+
+
+

Returns#

+
+
uaarray_like

Complex-valued analytic signal, first Cartesian component (zonal, east-west)

+
+
vaarray_like

Complex-valued analytic signal, second Cartesian component (meridional, north-south)

+
+
+
+
+

Examples#

+

To obtain the Cartesian analytic signals from a pair of rotary signals (wp,wn):

+
>>> ua, va = rotary_to_cartesian(wp, wn)
+
+
+

To specify that the time axis is along the first axis:

+
>>> ua, va = rotary_to_cartesian(wp, wn, time_axis=0)
+
+
+
+
+

Raises#

+
+
ValueError

If the input arrays do not have the same shape. +If the time axis is outside of the valid range ([-1, N-1]).

+
+
+
+
+

References#

+

Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. +IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729)

+
+
+

See Also#

+

analytic_signal(), cartesian_to_rotary()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.bearing.html b/_autosummary/clouddrift.sphere.bearing.html new file mode 100644 index 00000000..58c45b74 --- /dev/null +++ b/_autosummary/clouddrift.sphere.bearing.html @@ -0,0 +1,607 @@ + + + + + + + + + + + clouddrift.sphere.bearing — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.bearing

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.bearing#

+
+
+clouddrift.sphere.bearing(lon1: float | list | ndarray | DataArray, lat1: float | list | ndarray | DataArray, lon2: float | list | ndarray | DataArray, lat2: float | list | ndarray | DataArray) float | ndarray[source]#
+

Return elementwise initial (forward) bearing in radians from arrays of +latitude and longitude in degrees, based on the spherical law of cosines.

+

The formula is:

+

θ = atan2(cos φ1 ⋅ sin φ2 - sin φ1 ⋅ cos φ2 ⋅ cos Δλ, sin Δλ ⋅ cos φ2)

+

where (φ, λ) is (lat, lon) and θ is bearing, all in radians. +Bearing is defined as zero toward East and positive counterclockwise.

+
+

Parameters#

+
+
lon1float or array-like

Longitudes of the first set of points, in degrees

+
+
lat1float or array-like

Latitudes of the first set of points, in degrees

+
+
lon2float or array-like

Longitudes of the second set of points, in degrees

+
+
lat2float or array-like

Latitudes of the second set of points, in degrees

+
+
+
+
+

Returns#

+
+
thetafloat or np.ndarray

Bearing angles in radians

+
+
+
+
+

Examples#

+

Calculate the bearing of one degree longitude on the equator:

+
>>> bearing(0, 0, 1, 0)
+0.0
+
+
+

Calculate the bearing of 10 degrees longitude at 45-degrees North latitude:

+
>>> bearing(0, 45, 10, 45)
+0.06178508761798218
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.cartesian_to_spherical.html b/_autosummary/clouddrift.sphere.cartesian_to_spherical.html new file mode 100644 index 00000000..66591215 --- /dev/null +++ b/_autosummary/clouddrift.sphere.cartesian_to_spherical.html @@ -0,0 +1,621 @@ + + + + + + + + + + + clouddrift.sphere.cartesian_to_spherical — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.cartesian_to_spherical

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.cartesian_to_spherical#

+
+
+clouddrift.sphere.cartesian_to_spherical(x: float | ndarray | DataArray, y: float | ndarray | DataArray, z: float | ndarray | DataArray) Tuple[ndarray, ndarray][source]#
+

Converts Cartesian three-dimensional coordinates to latitude and longitude on a +spherical body.

+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of the sphere. It is oriented with the +Z-axis passing through the poles and the X-axis passing through +the point lon = 0, lat = 0. This function is inverted by spherical_to_cartesian.

+
+

Parameters#

+
+
xfloat or array-like

x-coordinates in 3D.

+
+
yfloat or array-like

y-coordinates in 3D.

+
+
zfloat or array-like

z-coordinates in 3D.

+
+
+
+
+

Returns#

+
+
lonfloat or array-like

An N-d array of longitudes in degrees in range [-180, 180].

+
+
latfloat or array-like

An N-d array of latitudes in degrees.

+
+
+
+
+

Examples#

+
>>> x = EARTH_RADIUS_METERS * np.cos(np.deg2rad(45))
+>>> y = EARTH_RADIUS_METERS * np.cos(np.deg2rad(45))
+>>> z = 0 * x
+>>> cartesian_to_spherical(x, y, z)
+(44.99999999999985, 0.0)
+
+
+

cartesian_to_spherical is inverted by spherical_to_cartesian:

+
>>> x, y, z = spherical_to_cartesian(np.array([45]),np.array(0))
+>>> cartesian_to_spherical(x, y, z)
+(array([45.]), array([0.]))
+
+
+
+
+

Raises#

+
+
AttributeError

If x, y, and z are not NumPy arrays.

+
+
+
+
+

See Also#

+

spherical_to_cartesian()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.html b/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.html new file mode 100644 index 00000000..ee45c8a2 --- /dev/null +++ b/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.html @@ -0,0 +1,620 @@ + + + + + + + + + + + clouddrift.sphere.cartesian_to_tangentplane — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.cartesian_to_tangentplane

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.cartesian_to_tangentplane#

+
+
+clouddrift.sphere.cartesian_to_tangentplane(u: float | ndarray, v: float | ndarray, w: float | ndarray, longitude: float | ndarray, latitude: float | ndarray) Tuple[float] | Tuple[ndarray][source]#
+

Project a three-dimensional Cartesian vector on a plane tangent to +a spherical Earth.

+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of a sphere. It is oriented with the +Z-axis passing through the north pole at lat = 90, the X-axis passing through +the point lon = 0, lat = 0, and the Y-axis passing through the point lon = 90, +lat = 0.

+
+

Parameters#

+
+
+
ufloat or np.ndarray

First component of Cartesian vector.

+
+
vfloat or np.ndarray

Second component of Cartesian vector.

+
+
wfloat or np.ndarray

Third component of Cartesian vector.

+
+
longitudefloat or np.ndarray

Longitude in degrees of tangent point of plane.

+
+
latitudefloat or np.ndarray

Latitude in degrees of tangent point of plane.

+
+
+
+
+
+

Returns#

+
+
+
up: float or np.ndarray

First component of projected vector on tangent plane (positive eastward).

+
+
vp: float or np.ndarray

Second component of projected vector on tangent plane (positive northward).

+
+
+
+
+
+

Raises#

+
+
Warning

Raised if the input latitude is not in the expected range [-90, 90].

+
+
+
+
+

Examples#

+
>>> u, v = cartesian_to_tangentplane(1, 1, 1, 45, 90)
+
+
+
+
+

See Also#

+

tangentplane_to_cartesian()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.coriolis_frequency.html b/_autosummary/clouddrift.sphere.coriolis_frequency.html new file mode 100644 index 00000000..819fb76f --- /dev/null +++ b/_autosummary/clouddrift.sphere.coriolis_frequency.html @@ -0,0 +1,589 @@ + + + + + + + + + + + clouddrift.sphere.coriolis_frequency — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.coriolis_frequency

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.coriolis_frequency#

+
+
+clouddrift.sphere.coriolis_frequency(latitude: float | ndarray) float | ndarray[source]#
+

Return the Coriolis frequency or commonly known f parameter in geophysical fluid dynamics.

+
+

Parameters#

+
+
latitudefloat or np.ndarray

Latitude in degrees.

+
+
+
+
+

Returns#

+
+
ffloat or np.ndarray

Signed Coriolis frequency in radian per seconds.

+
+
+
+
+

Examples#

+
>>> f = coriolis_frequency(np.array([0, 45, 90]))
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.cumulative_distance.html b/_autosummary/clouddrift.sphere.cumulative_distance.html new file mode 100644 index 00000000..7ce7051d --- /dev/null +++ b/_autosummary/clouddrift.sphere.cumulative_distance.html @@ -0,0 +1,597 @@ + + + + + + + + + + + clouddrift.sphere.cumulative_distance — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.cumulative_distance

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.cumulative_distance#

+
+
+clouddrift.sphere.cumulative_distance(longitude: list | ndarray | DataArray, latitude: list | ndarray | DataArray) ndarray[source]#
+

Return the cumulative great circle distance in meters along a sequence of geographical locations.

+
+

Parameters#

+
+
latitudearray-like

Latitude sequence, in degrees.

+
+
longitudearray-like

Longitude sequence, in degrees.

+
+
+
+
+

Returns#

+
+
outnp.ndarray

Cumulative distance.

+
+
+
+
+

See Also#

+

distance()

+
+
+

Examples#

+

Calculate the cumulative distance in meters along a path of three points:

+
>>> cumulative_distance(np.array([0, 1, 2]), np.array([0, 1, 2]))
+array([     0.        , 157424.62387233, 314825.27182116])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.distance.html b/_autosummary/clouddrift.sphere.distance.html new file mode 100644 index 00000000..1d65aea8 --- /dev/null +++ b/_autosummary/clouddrift.sphere.distance.html @@ -0,0 +1,612 @@ + + + + + + + + + + + clouddrift.sphere.distance — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.distance

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.distance#

+
+
+clouddrift.sphere.distance(lon1: float | list | ndarray | DataArray, lat1: float | list | ndarray | DataArray, lon2: float | list | ndarray | DataArray, lat2: float | list | ndarray | DataArray) float | ndarray[source]#
+

Return elementwise great circle distance in meters between one or more +points from arrays of their latitudes and longitudes, using the Haversine +formula.

+

d = 2⋅r⋅asin √[sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)]

+

where (φ, λ) is (lat, lon) in radians and r is the radius of the sphere in +meters.

+
+

Parameters#

+
+
lon1np.ndarray

Longitudes of the first set of points, in degrees

+
+
lat1np.ndarray

Latitudes of the first set of points, in degrees

+
+
lon2np.ndarray

Longitudes of the second set of points, in degrees

+
+
lat2np.ndarray

Latitudes of the second set of points, in degrees

+
+
+
+
+

Returns#

+
+
outnp.ndarray

Great circle distance

+
+
+
+
+

Examples#

+

Calculate the distance of one degree longitude on the equator:

+
>>> distance(0, 0, 0, 1)
+111318.84502145034
+
+
+

Calculate the distance of one degree longitude at 45-degrees North latitude:

+
>>> distance(0, 45, 1, 45)
+78713.81064540472
+
+
+

You can also pass array-like inputs to calculate an array of distances:

+
>>> distance([0, 0], [0, 45], [0, 1], [1, 45])
+array([111318.84502145,  78713.8106454 ])
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.html b/_autosummary/clouddrift.sphere.html new file mode 100644 index 00000000..6d409300 --- /dev/null +++ b/_autosummary/clouddrift.sphere.html @@ -0,0 +1,1317 @@ + + + + + + + + + + + clouddrift.sphere — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.sphere#

+

This module provides functions for spherical geometry calculations.

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

bearing(lon1, lat1, lon2, lat2)

Return elementwise initial (forward) bearing in radians from arrays of latitude and longitude in degrees, based on the spherical law of cosines.

cartesian_to_spherical(x, y, z)

Converts Cartesian three-dimensional coordinates to latitude and longitude on a spherical body.

cartesian_to_tangentplane(u, v, w, ...)

Project a three-dimensional Cartesian vector on a plane tangent to a spherical Earth.

coriolis_frequency(latitude)

Return the Coriolis frequency or commonly known f parameter in geophysical fluid dynamics.

cumulative_distance(longitude, latitude)

Return the cumulative great circle distance in meters along a sequence of geographical locations.

distance(lon1, lat1, lon2, lat2)

Return elementwise great circle distance in meters between one or more points from arrays of their latitudes and longitudes, using the Haversine formula.

plane_to_sphere(x, y[, lon_origin, lat_origin])

Convert Cartesian coordinates on a plane to spherical coordinates.

position_from_distance_and_bearing(lon, lat, ...)

Return elementwise new position in degrees from arrays of latitude and longitude in degrees, distance in meters, and bearing in radians, based on the spherical law of cosines.

recast_lon(lon[, lon0])

Recast (convert) longitude values to a selected range of 360 degrees starting from lon0.

recast_lon180(lon)

Recast (convert) longitude values to the range [-180, 180[.

recast_lon360(lon)

Recast (convert) longitude values to the range [0, 360[.

sphere_to_plane(lon, lat[, lon_origin, ...])

Convert spherical coordinates to a tangent (Cartesian) plane.

spherical_to_cartesian(lon, lat[, radius])

Converts latitude and longitude on a spherical body to

tangentplane_to_cartesian(up, vp, longitude, ...)

Return the three-dimensional Cartesian components of a vector contained in a plane tangent to a spherical Earth.

+
+
+clouddrift.sphere.bearing(lon1: float | list | ndarray | DataArray, lat1: float | list | ndarray | DataArray, lon2: float | list | ndarray | DataArray, lat2: float | list | ndarray | DataArray) float | ndarray[source]#
+

Return elementwise initial (forward) bearing in radians from arrays of +latitude and longitude in degrees, based on the spherical law of cosines.

+

The formula is:

+

θ = atan2(cos φ1 ⋅ sin φ2 - sin φ1 ⋅ cos φ2 ⋅ cos Δλ, sin Δλ ⋅ cos φ2)

+

where (φ, λ) is (lat, lon) and θ is bearing, all in radians. +Bearing is defined as zero toward East and positive counterclockwise.

+
+

Parameters#

+
+
lon1float or array-like

Longitudes of the first set of points, in degrees

+
+
lat1float or array-like

Latitudes of the first set of points, in degrees

+
+
lon2float or array-like

Longitudes of the second set of points, in degrees

+
+
lat2float or array-like

Latitudes of the second set of points, in degrees

+
+
+
+
+

Returns#

+
+
thetafloat or np.ndarray

Bearing angles in radians

+
+
+
+
+

Examples#

+

Calculate the bearing of one degree longitude on the equator:

+
>>> bearing(0, 0, 1, 0)
+0.0
+
+
+

Calculate the bearing of 10 degrees longitude at 45-degrees North latitude:

+
>>> bearing(0, 45, 10, 45)
+0.06178508761798218
+
+
+
+
+ +
+
+clouddrift.sphere.cartesian_to_spherical(x: float | ndarray | DataArray, y: float | ndarray | DataArray, z: float | ndarray | DataArray) Tuple[ndarray, ndarray][source]#
+

Converts Cartesian three-dimensional coordinates to latitude and longitude on a +spherical body.

+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of the sphere. It is oriented with the +Z-axis passing through the poles and the X-axis passing through +the point lon = 0, lat = 0. This function is inverted by spherical_to_cartesian.

+
+

Parameters#

+
+
xfloat or array-like

x-coordinates in 3D.

+
+
yfloat or array-like

y-coordinates in 3D.

+
+
zfloat or array-like

z-coordinates in 3D.

+
+
+
+
+

Returns#

+
+
lonfloat or array-like

An N-d array of longitudes in degrees in range [-180, 180].

+
+
latfloat or array-like

An N-d array of latitudes in degrees.

+
+
+
+
+

Examples#

+
>>> x = EARTH_RADIUS_METERS * np.cos(np.deg2rad(45))
+>>> y = EARTH_RADIUS_METERS * np.cos(np.deg2rad(45))
+>>> z = 0 * x
+>>> cartesian_to_spherical(x, y, z)
+(44.99999999999985, 0.0)
+
+
+

cartesian_to_spherical is inverted by spherical_to_cartesian:

+
>>> x, y, z = spherical_to_cartesian(np.array([45]),np.array(0))
+>>> cartesian_to_spherical(x, y, z)
+(array([45.]), array([0.]))
+
+
+
+
+

Raises#

+
+
AttributeError

If x, y, and z are not NumPy arrays.

+
+
+
+
+

See Also#

+

spherical_to_cartesian()

+
+
+ +
+
+clouddrift.sphere.cartesian_to_tangentplane(u: float | ndarray, v: float | ndarray, w: float | ndarray, longitude: float | ndarray, latitude: float | ndarray) Tuple[float] | Tuple[ndarray][source]#
+

Project a three-dimensional Cartesian vector on a plane tangent to +a spherical Earth.

+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of a sphere. It is oriented with the +Z-axis passing through the north pole at lat = 90, the X-axis passing through +the point lon = 0, lat = 0, and the Y-axis passing through the point lon = 90, +lat = 0.

+
+

Parameters#

+
+
+
ufloat or np.ndarray

First component of Cartesian vector.

+
+
vfloat or np.ndarray

Second component of Cartesian vector.

+
+
wfloat or np.ndarray

Third component of Cartesian vector.

+
+
longitudefloat or np.ndarray

Longitude in degrees of tangent point of plane.

+
+
latitudefloat or np.ndarray

Latitude in degrees of tangent point of plane.

+
+
+
+
+
+

Returns#

+
+
+
up: float or np.ndarray

First component of projected vector on tangent plane (positive eastward).

+
+
vp: float or np.ndarray

Second component of projected vector on tangent plane (positive northward).

+
+
+
+
+
+

Raises#

+
+
Warning

Raised if the input latitude is not in the expected range [-90, 90].

+
+
+
+
+

Examples#

+
>>> u, v = cartesian_to_tangentplane(1, 1, 1, 45, 90)
+
+
+
+
+

See Also#

+

tangentplane_to_cartesian()

+
+
+ +
+
+clouddrift.sphere.coriolis_frequency(latitude: float | ndarray) float | ndarray[source]#
+

Return the Coriolis frequency or commonly known f parameter in geophysical fluid dynamics.

+
+

Parameters#

+
+
latitudefloat or np.ndarray

Latitude in degrees.

+
+
+
+
+

Returns#

+
+
ffloat or np.ndarray

Signed Coriolis frequency in radian per seconds.

+
+
+
+
+

Examples#

+
>>> f = coriolis_frequency(np.array([0, 45, 90]))
+
+
+
+
+ +
+
+clouddrift.sphere.cumulative_distance(longitude: list | ndarray | DataArray, latitude: list | ndarray | DataArray) ndarray[source]#
+

Return the cumulative great circle distance in meters along a sequence of geographical locations.

+
+

Parameters#

+
+
latitudearray-like

Latitude sequence, in degrees.

+
+
longitudearray-like

Longitude sequence, in degrees.

+
+
+
+
+

Returns#

+
+
outnp.ndarray

Cumulative distance.

+
+
+
+
+

See Also#

+

distance()

+
+
+

Examples#

+

Calculate the cumulative distance in meters along a path of three points:

+
>>> cumulative_distance(np.array([0, 1, 2]), np.array([0, 1, 2]))
+array([     0.        , 157424.62387233, 314825.27182116])
+
+
+
+
+ +
+
+clouddrift.sphere.distance(lon1: float | list | ndarray | DataArray, lat1: float | list | ndarray | DataArray, lon2: float | list | ndarray | DataArray, lat2: float | list | ndarray | DataArray) float | ndarray[source]#
+

Return elementwise great circle distance in meters between one or more +points from arrays of their latitudes and longitudes, using the Haversine +formula.

+

d = 2⋅r⋅asin √[sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)]

+

where (φ, λ) is (lat, lon) in radians and r is the radius of the sphere in +meters.

+
+

Parameters#

+
+
lon1np.ndarray

Longitudes of the first set of points, in degrees

+
+
lat1np.ndarray

Latitudes of the first set of points, in degrees

+
+
lon2np.ndarray

Longitudes of the second set of points, in degrees

+
+
lat2np.ndarray

Latitudes of the second set of points, in degrees

+
+
+
+
+

Returns#

+
+
outnp.ndarray

Great circle distance

+
+
+
+
+

Examples#

+

Calculate the distance of one degree longitude on the equator:

+
>>> distance(0, 0, 0, 1)
+111318.84502145034
+
+
+

Calculate the distance of one degree longitude at 45-degrees North latitude:

+
>>> distance(0, 45, 1, 45)
+78713.81064540472
+
+
+

You can also pass array-like inputs to calculate an array of distances:

+
>>> distance([0, 0], [0, 45], [0, 1], [1, 45])
+array([111318.84502145,  78713.8106454 ])
+
+
+
+
+ +
+
+clouddrift.sphere.plane_to_sphere(x: ndarray, y: ndarray, lon_origin: float = 0, lat_origin: float = 0) Tuple[ndarray, ndarray][source]#
+

Convert Cartesian coordinates on a plane to spherical coordinates.

+

The arrays of input zonal and meridional displacements x and y are +assumed to follow a contiguous trajectory. The spherical coordinate of each +successive point is determined by following a great circle path from the +previous point. The spherical coordinate of the first point is determined by +following a great circle path from the origin, by default (0, 0).

+

The output arrays have the same floating-point output type as the input.

+

If projecting multiple trajectories onto the same plane, use +apply_ragged() for highest accuracy.

+
+

Parameters#

+
+
xnp.ndarray

An N-d array of zonal displacements in meters

+
+
ynp.ndarray

An N-d array of meridional displacements in meters

+
+
lon_originfloat, optional

Origin longitude of the tangent plane in degrees, default 0

+
+
lat_originfloat, optional

Origin latitude of the tangent plane in degrees, default 0

+
+
+
+
+

Returns#

+
+
lonnp.ndarray

Longitude in degrees

+
+
latnp.ndarray

Latitude in degrees

+
+
+
+
+

Examples#

+
>>> plane_to_sphere(np.array([0., 0.]), np.array([0., 1000.]))
+(array([0.00000000e+00, 5.50062664e-19]), array([0.       , 0.0089832]))
+
+
+

You can also specify an origin longitude and latitude:

+
>>> plane_to_sphere(np.array([0., 0.]), np.array([0., 1000.]), lon_origin=1, lat_origin=0)
+(array([1., 1.]), array([0.       , 0.0089832]))
+
+
+
+
+

Raises#

+
+
AttributeError

If x and y are not NumPy arrays

+
+
+
+
+

See Also#

+

sphere_to_plane()

+
+
+ +
+
+clouddrift.sphere.position_from_distance_and_bearing(lon: float, lat: float, distance: float, bearing: float) Tuple[float, float][source]#
+

Return elementwise new position in degrees from arrays of latitude and +longitude in degrees, distance in meters, and bearing in radians, based on +the spherical law of cosines.

+

The formula is:

+

φ2 = asin( sin φ1 ⋅ cos δ + cos φ1 ⋅ sin δ ⋅ cos θ ) +λ2 = λ1 + atan2( sin θ ⋅ sin δ ⋅ cos φ1, cos δ − sin φ1 ⋅ sin φ2 )

+

where (φ, λ) is (lat, lon) and θ is bearing, all in radians. +Bearing is defined as zero toward East and positive counterclockwise.

+
+

Parameters#

+
+
lonfloat

Longitude of the first set of points, in degrees

+
+
latfloat

Latitude of the first set of points, in degrees

+
+
distancearray_like

Distance in meters

+
+
bearingarray_like

Bearing angles in radians

+
+
+
+
+

Returns#

+
+
lon2array_like

Latitudes of the second set of points, in degrees, in the range [-90, 90]

+
+
lat2array_like

Longitudes of the second set of points, in degrees, in the range [-180, 180]

+
+
+
+
+

Examples#

+

Calculate the position of one degree longitude distance on the equator:

+
>>> position_from_distance_and_bearing(0, 0, 111318.84502145034, 0)
+(1.0, 0.0)
+
+
+

Calculate the position of one degree latitude distance from 45 degrees North latitude:

+
>>> position_from_distance_and_bearing(0, 45, 111318.84502145034, np.pi / 2)
+(8.81429402840006e-17, 45.99999999999999)
+
+
+
+
+ +
+
+clouddrift.sphere.recast_lon(lon: ndarray, lon0: float | None = -180) ndarray[source]#
+

Recast (convert) longitude values to a selected range of 360 degrees +starting from lon0.

+
+

Parameters#

+
+
lonnp.ndarray or float

An N-d array of longitudes in degrees

+
+
lon0float, optional

Starting longitude of the recasted range (default -180).

+
+
+
+
+

Returns#

+
+
np.ndarray or float

Converted longitudes in the range [lon0, lon0+360[

+
+
+
+
+

Examples#

+

By default, recast_lon converts longitude values to the range +[-180, 180[:

+
>>> recast_lon(200)
+-160
+
+
+
>>> recast_lon(180)
+-180
+
+
+

The range of the output longitude is controlled by lon0. +For example, with lon0 = 0, the longitude values are converted to the +range [0, 360[.

+
>>> recast_lon(200, -180)
+-160
+
+
+

With lon0 = 20, longitude values are converted to range [20, 380], +which can be useful to avoid cutting the major ocean basins.

+
>>> recast_lon(10, 20)
+370
+
+
+
+
+

See Also#

+

recast_lon360(), recast_lon180()

+
+
+ +
+
+clouddrift.sphere.recast_lon180(lon: ndarray) ndarray[source]#
+

Recast (convert) longitude values to the range [-180, 180[. +This is a convenience wrapper around recast_lon() with lon0 = -180.

+
+

Parameters#

+
+
lonnp.ndarray

An N-d array of longitudes in degrees

+
+
+
+
+

Returns#

+
+
np.ndarray

Converted longitudes in the range [-180, 180[

+
+
+
+
+

Examples#

+
>>> recast_lon180(200)
+-160
+
+
+
>>> recast_lon180(-200)
+160
+
+
+
+
+

See Also#

+

recast_lon(), recast_lon360()

+
+
+ +
+
+clouddrift.sphere.recast_lon360(lon: ndarray) ndarray[source]#
+

Recast (convert) longitude values to the range [0, 360[. +This is a convenience wrapper around recast_lon() with lon0 = 0.

+
+

Parameters#

+
+
lonnp.ndarray

An N-d array of longitudes in degrees

+
+
+
+
+

Returns#

+
+
np.ndarray

Converted longitudes in the range [0, 360[

+
+
+
+
+

Examples#

+
>>> recast_lon360(200)
+200
+
+
+
>>> recast_lon360(-200)
+160
+
+
+
+
+

See Also#

+

recast_lon(), recast_lon180()

+
+
+ +
+
+clouddrift.sphere.sphere_to_plane(lon: ndarray, lat: ndarray, lon_origin: float = 0, lat_origin: float = 0) Tuple[ndarray, ndarray][source]#
+

Convert spherical coordinates to a tangent (Cartesian) plane.

+

The arrays of input longitudes and latitudes are assumed to be following +a contiguous trajectory. The Cartesian coordinate of each successive point +is determined by following a great circle path from the previous point. +The Cartesian coordinate of the first point is determined by following a +great circle path from the origin, by default (0, 0).

+

The output arrays have the same floating-point output type as the input.

+

If projecting multiple trajectories onto the same plane, use +apply_ragged() for highest accuracy.

+
+

Parameters#

+
+
lonnp.ndarray

An N-d array of longitudes in degrees

+
+
latnp.ndarray

An N-d array of latitudes in degrees

+
+
lon_originfloat, optional

Origin longitude of the tangent plane in degrees, default 0

+
+
lat_originfloat, optional

Origin latitude of the tangent plane in degrees, default 0

+
+
+
+
+

Returns#

+
+
xnp.ndarray

x-coordinates on the tangent plane

+
+
ynp.ndarray

y-coordinates on the tangent plane

+
+
+
+
+

Examples#

+
>>> sphere_to_plane(np.array([0., 1.]), np.array([0., 0.]))
+(array([     0.        , 111318.84502145]), array([0., 0.]))
+
+
+

You can also specify an origin longitude and latitude:

+
>>> sphere_to_plane(np.array([0., 1.]), np.array([0., 0.]), lon_origin=1, lat_origin=0)
+(array([-111318.84502145,       0.        ]),
+ array([1.36326267e-11, 1.36326267e-11]))
+
+
+
+
+

Raises#

+
+
AttributeError

If lon and lat are not NumPy arrays

+
+
+
+
+

See Also#

+

plane_to_sphere()

+
+
+ +
+
+clouddrift.sphere.spherical_to_cartesian(lon: float | list | ndarray | DataArray, lat: float | list | ndarray | DataArray, radius: float | None = 6378100.0) Tuple[ndarray, ndarray, ndarray][source]#
+
+
Converts latitude and longitude on a spherical body to

three-dimensional Cartesian coordinates.

+
+
+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of a sphere. It is oriented with the +Z-axis passing through the poles and the X-axis passing through +the point lon = 0, lat = 0. This function is inverted by +cartesian_to_spherical().

+
+

Parameters#

+
+
lonarray-like

An N-d array of longitudes in degrees.

+
+
latarray-like

An N-d array of latitudes in degrees.

+
+
radius: float, optional

The radius of the spherical body in meters. The default assumes the Earth with +EARTH_RADIUS_METERS = 6.3781e6.

+
+
+
+
+

Returns#

+
+
xfloat or array-like

x-coordinates in 3D in meters.

+
+
yfloat or array-like

y-coordinates in 3D in meters.

+
+
zfloat or array-like

z-coordinates in 3D in meters.

+
+
+
+
+

Examples#

+
>>> spherical_to_cartesian(np.array([0, 45]), np.array([0, 45]))
+(array([6378100., 3189050.]),
+array([      0., 3189050.]),
+array([      0.        , 4509997.76108592]))
+
+
+
>>> spherical_to_cartesian(np.array([0, 45, 90]), np.array([0, 90, 180]), radius=1)
+(array([ 1.00000000e+00,  4.32978028e-17, -6.12323400e-17]),
+array([ 0.00000000e+00,  4.32978028e-17, -1.00000000e+00]),
+array([0.0000000e+00, 1.0000000e+00, 1.2246468e-16]))
+
+
+
>>> x, y, z = spherical_to_cartesian(np.array([0, 5]), np.array([0, 5]))
+
+
+
+
+

Raises#

+
+
AttributeError

If lon and lat are not NumPy arrays.

+
+
+
+
+

See Also#

+

cartesian_to_spherical()

+
+
+ +
+
+clouddrift.sphere.tangentplane_to_cartesian(up: float | ndarray, vp: float | ndarray, longitude: float | ndarray, latitude: float | ndarray) Tuple[float] | Tuple[ndarray][source]#
+

Return the three-dimensional Cartesian components of a vector contained in +a plane tangent to a spherical Earth.

+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of a sphere. It is oriented with the +Z-axis passing through the north pole at lat = 90, the X-axis passing through +the point lon = 0, lat = 0, and the Y-axis passing through the point lon = 90, +lat = 0.

+
+

Parameters#

+
+
+
up: float or np.ndarray

First component of vector on tangent plane (positive eastward).

+
+
vp: float or np.ndarray

Second component of vector on tangent plane (positive northward).

+
+
longitudefloat or np.ndarray

Longitude in degrees of tangent point of plane.

+
+
latitudefloat or np.ndarray

Latitude in degrees of tangent point of plane.

+
+
+
+
+
+

Returns#

+
+
+
ufloat or np.ndarray

First component of Cartesian vector.

+
+
vfloat or np.ndarray

Second component of Cartesian vector.

+
+
wfloat or np.ndarray

Third component of Cartesian vector.

+
+
+
+
+
+

Examples#

+
>>> u, v, w = tangentplane_to_cartesian(1, 1, 45, 90)
+
+
+
+
+

Notes#

+

This function is inverted by cartesian_to_tangetplane().

+
+
+

See Also#

+

cartesian_to_tangentplane()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.plane_to_sphere.html b/_autosummary/clouddrift.sphere.plane_to_sphere.html new file mode 100644 index 00000000..3c4ec110 --- /dev/null +++ b/_autosummary/clouddrift.sphere.plane_to_sphere.html @@ -0,0 +1,622 @@ + + + + + + + + + + + clouddrift.sphere.plane_to_sphere — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.plane_to_sphere

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.plane_to_sphere#

+
+
+clouddrift.sphere.plane_to_sphere(x: ndarray, y: ndarray, lon_origin: float = 0, lat_origin: float = 0) Tuple[ndarray, ndarray][source]#
+

Convert Cartesian coordinates on a plane to spherical coordinates.

+

The arrays of input zonal and meridional displacements x and y are +assumed to follow a contiguous trajectory. The spherical coordinate of each +successive point is determined by following a great circle path from the +previous point. The spherical coordinate of the first point is determined by +following a great circle path from the origin, by default (0, 0).

+

The output arrays have the same floating-point output type as the input.

+

If projecting multiple trajectories onto the same plane, use +apply_ragged() for highest accuracy.

+
+

Parameters#

+
+
xnp.ndarray

An N-d array of zonal displacements in meters

+
+
ynp.ndarray

An N-d array of meridional displacements in meters

+
+
lon_originfloat, optional

Origin longitude of the tangent plane in degrees, default 0

+
+
lat_originfloat, optional

Origin latitude of the tangent plane in degrees, default 0

+
+
+
+
+

Returns#

+
+
lonnp.ndarray

Longitude in degrees

+
+
latnp.ndarray

Latitude in degrees

+
+
+
+
+

Examples#

+
>>> plane_to_sphere(np.array([0., 0.]), np.array([0., 1000.]))
+(array([0.00000000e+00, 5.50062664e-19]), array([0.       , 0.0089832]))
+
+
+

You can also specify an origin longitude and latitude:

+
>>> plane_to_sphere(np.array([0., 0.]), np.array([0., 1000.]), lon_origin=1, lat_origin=0)
+(array([1., 1.]), array([0.       , 0.0089832]))
+
+
+
+
+

Raises#

+
+
AttributeError

If x and y are not NumPy arrays

+
+
+
+
+

See Also#

+

sphere_to_plane()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.html b/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.html new file mode 100644 index 00000000..65a6c442 --- /dev/null +++ b/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.html @@ -0,0 +1,611 @@ + + + + + + + + + + + clouddrift.sphere.position_from_distance_and_bearing — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.position_from_distance_and_bearing

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.position_from_distance_and_bearing#

+
+
+clouddrift.sphere.position_from_distance_and_bearing(lon: float, lat: float, distance: float, bearing: float) Tuple[float, float][source]#
+

Return elementwise new position in degrees from arrays of latitude and +longitude in degrees, distance in meters, and bearing in radians, based on +the spherical law of cosines.

+

The formula is:

+

φ2 = asin( sin φ1 ⋅ cos δ + cos φ1 ⋅ sin δ ⋅ cos θ ) +λ2 = λ1 + atan2( sin θ ⋅ sin δ ⋅ cos φ1, cos δ − sin φ1 ⋅ sin φ2 )

+

where (φ, λ) is (lat, lon) and θ is bearing, all in radians. +Bearing is defined as zero toward East and positive counterclockwise.

+
+

Parameters#

+
+
lonfloat

Longitude of the first set of points, in degrees

+
+
latfloat

Latitude of the first set of points, in degrees

+
+
distancearray_like

Distance in meters

+
+
bearingarray_like

Bearing angles in radians

+
+
+
+
+

Returns#

+
+
lon2array_like

Latitudes of the second set of points, in degrees, in the range [-90, 90]

+
+
lat2array_like

Longitudes of the second set of points, in degrees, in the range [-180, 180]

+
+
+
+
+

Examples#

+

Calculate the position of one degree longitude distance on the equator:

+
>>> position_from_distance_and_bearing(0, 0, 111318.84502145034, 0)
+(1.0, 0.0)
+
+
+

Calculate the position of one degree latitude distance from 45 degrees North latitude:

+
>>> position_from_distance_and_bearing(0, 45, 111318.84502145034, np.pi / 2)
+(8.81429402840006e-17, 45.99999999999999)
+
+
+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.recast_lon.html b/_autosummary/clouddrift.sphere.recast_lon.html new file mode 100644 index 00000000..88a1a881 --- /dev/null +++ b/_autosummary/clouddrift.sphere.recast_lon.html @@ -0,0 +1,616 @@ + + + + + + + + + + + clouddrift.sphere.recast_lon — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.recast_lon

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.recast_lon#

+
+
+clouddrift.sphere.recast_lon(lon: ndarray, lon0: float | None = -180) ndarray[source]#
+

Recast (convert) longitude values to a selected range of 360 degrees +starting from lon0.

+
+

Parameters#

+
+
lonnp.ndarray or float

An N-d array of longitudes in degrees

+
+
lon0float, optional

Starting longitude of the recasted range (default -180).

+
+
+
+
+

Returns#

+
+
np.ndarray or float

Converted longitudes in the range [lon0, lon0+360[

+
+
+
+
+

Examples#

+

By default, recast_lon converts longitude values to the range +[-180, 180[:

+
>>> recast_lon(200)
+-160
+
+
+
>>> recast_lon(180)
+-180
+
+
+

The range of the output longitude is controlled by lon0. +For example, with lon0 = 0, the longitude values are converted to the +range [0, 360[.

+
>>> recast_lon(200, -180)
+-160
+
+
+

With lon0 = 20, longitude values are converted to range [20, 380], +which can be useful to avoid cutting the major ocean basins.

+
>>> recast_lon(10, 20)
+370
+
+
+
+
+

See Also#

+

recast_lon360(), recast_lon180()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.recast_lon180.html b/_autosummary/clouddrift.sphere.recast_lon180.html new file mode 100644 index 00000000..c1c1f347 --- /dev/null +++ b/_autosummary/clouddrift.sphere.recast_lon180.html @@ -0,0 +1,599 @@ + + + + + + + + + + + clouddrift.sphere.recast_lon180 — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.recast_lon180

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.recast_lon180#

+
+
+clouddrift.sphere.recast_lon180(lon: ndarray) ndarray[source]#
+

Recast (convert) longitude values to the range [-180, 180[. +This is a convenience wrapper around recast_lon() with lon0 = -180.

+
+

Parameters#

+
+
lonnp.ndarray

An N-d array of longitudes in degrees

+
+
+
+
+

Returns#

+
+
np.ndarray

Converted longitudes in the range [-180, 180[

+
+
+
+
+

Examples#

+
>>> recast_lon180(200)
+-160
+
+
+
>>> recast_lon180(-200)
+160
+
+
+
+
+

See Also#

+

recast_lon(), recast_lon360()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.recast_lon360.html b/_autosummary/clouddrift.sphere.recast_lon360.html new file mode 100644 index 00000000..2818e12e --- /dev/null +++ b/_autosummary/clouddrift.sphere.recast_lon360.html @@ -0,0 +1,599 @@ + + + + + + + + + + + clouddrift.sphere.recast_lon360 — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.recast_lon360

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.recast_lon360#

+
+
+clouddrift.sphere.recast_lon360(lon: ndarray) ndarray[source]#
+

Recast (convert) longitude values to the range [0, 360[. +This is a convenience wrapper around recast_lon() with lon0 = 0.

+
+

Parameters#

+
+
lonnp.ndarray

An N-d array of longitudes in degrees

+
+
+
+
+

Returns#

+
+
np.ndarray

Converted longitudes in the range [0, 360[

+
+
+
+
+

Examples#

+
>>> recast_lon360(200)
+200
+
+
+
>>> recast_lon360(-200)
+160
+
+
+
+
+

See Also#

+

recast_lon(), recast_lon180()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.sphere_to_plane.html b/_autosummary/clouddrift.sphere.sphere_to_plane.html new file mode 100644 index 00000000..64a26e0e --- /dev/null +++ b/_autosummary/clouddrift.sphere.sphere_to_plane.html @@ -0,0 +1,623 @@ + + + + + + + + + + + clouddrift.sphere.sphere_to_plane — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.sphere_to_plane

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.sphere_to_plane#

+
+
+clouddrift.sphere.sphere_to_plane(lon: ndarray, lat: ndarray, lon_origin: float = 0, lat_origin: float = 0) Tuple[ndarray, ndarray][source]#
+

Convert spherical coordinates to a tangent (Cartesian) plane.

+

The arrays of input longitudes and latitudes are assumed to be following +a contiguous trajectory. The Cartesian coordinate of each successive point +is determined by following a great circle path from the previous point. +The Cartesian coordinate of the first point is determined by following a +great circle path from the origin, by default (0, 0).

+

The output arrays have the same floating-point output type as the input.

+

If projecting multiple trajectories onto the same plane, use +apply_ragged() for highest accuracy.

+
+

Parameters#

+
+
lonnp.ndarray

An N-d array of longitudes in degrees

+
+
latnp.ndarray

An N-d array of latitudes in degrees

+
+
lon_originfloat, optional

Origin longitude of the tangent plane in degrees, default 0

+
+
lat_originfloat, optional

Origin latitude of the tangent plane in degrees, default 0

+
+
+
+
+

Returns#

+
+
xnp.ndarray

x-coordinates on the tangent plane

+
+
ynp.ndarray

y-coordinates on the tangent plane

+
+
+
+
+

Examples#

+
>>> sphere_to_plane(np.array([0., 1.]), np.array([0., 0.]))
+(array([     0.        , 111318.84502145]), array([0., 0.]))
+
+
+

You can also specify an origin longitude and latitude:

+
>>> sphere_to_plane(np.array([0., 1.]), np.array([0., 0.]), lon_origin=1, lat_origin=0)
+(array([-111318.84502145,       0.        ]),
+ array([1.36326267e-11, 1.36326267e-11]))
+
+
+
+
+

Raises#

+
+
AttributeError

If lon and lat are not NumPy arrays

+
+
+
+
+

See Also#

+

plane_to_sphere()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.spherical_to_cartesian.html b/_autosummary/clouddrift.sphere.spherical_to_cartesian.html new file mode 100644 index 00000000..41bddf1a --- /dev/null +++ b/_autosummary/clouddrift.sphere.spherical_to_cartesian.html @@ -0,0 +1,629 @@ + + + + + + + + + + + clouddrift.sphere.spherical_to_cartesian — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.spherical_to_cartesian

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.spherical_to_cartesian#

+
+
+clouddrift.sphere.spherical_to_cartesian(lon: float | list | ndarray | DataArray, lat: float | list | ndarray | DataArray, radius: float | None = 6378100.0) Tuple[ndarray, ndarray, ndarray][source]#
+
+
Converts latitude and longitude on a spherical body to

three-dimensional Cartesian coordinates.

+
+
+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of a sphere. It is oriented with the +Z-axis passing through the poles and the X-axis passing through +the point lon = 0, lat = 0. This function is inverted by +cartesian_to_spherical().

+
+

Parameters#

+
+
lonarray-like

An N-d array of longitudes in degrees.

+
+
latarray-like

An N-d array of latitudes in degrees.

+
+
radius: float, optional

The radius of the spherical body in meters. The default assumes the Earth with +EARTH_RADIUS_METERS = 6.3781e6.

+
+
+
+
+

Returns#

+
+
xfloat or array-like

x-coordinates in 3D in meters.

+
+
yfloat or array-like

y-coordinates in 3D in meters.

+
+
zfloat or array-like

z-coordinates in 3D in meters.

+
+
+
+
+

Examples#

+
>>> spherical_to_cartesian(np.array([0, 45]), np.array([0, 45]))
+(array([6378100., 3189050.]),
+array([      0., 3189050.]),
+array([      0.        , 4509997.76108592]))
+
+
+
>>> spherical_to_cartesian(np.array([0, 45, 90]), np.array([0, 90, 180]), radius=1)
+(array([ 1.00000000e+00,  4.32978028e-17, -6.12323400e-17]),
+array([ 0.00000000e+00,  4.32978028e-17, -1.00000000e+00]),
+array([0.0000000e+00, 1.0000000e+00, 1.2246468e-16]))
+
+
+
>>> x, y, z = spherical_to_cartesian(np.array([0, 5]), np.array([0, 5]))
+
+
+
+
+

Raises#

+
+
AttributeError

If lon and lat are not NumPy arrays.

+
+
+
+
+

See Also#

+

cartesian_to_spherical()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.html b/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.html new file mode 100644 index 00000000..c534e400 --- /dev/null +++ b/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.html @@ -0,0 +1,617 @@ + + + + + + + + + + + clouddrift.sphere.tangentplane_to_cartesian — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.sphere.tangentplane_to_cartesian

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.sphere.tangentplane_to_cartesian#

+
+
+clouddrift.sphere.tangentplane_to_cartesian(up: float | ndarray, vp: float | ndarray, longitude: float | ndarray, latitude: float | ndarray) Tuple[float] | Tuple[ndarray][source]#
+

Return the three-dimensional Cartesian components of a vector contained in +a plane tangent to a spherical Earth.

+

The Cartesian coordinate system is a right-handed system whose +origin lies at the center of a sphere. It is oriented with the +Z-axis passing through the north pole at lat = 90, the X-axis passing through +the point lon = 0, lat = 0, and the Y-axis passing through the point lon = 90, +lat = 0.

+
+

Parameters#

+
+
+
up: float or np.ndarray

First component of vector on tangent plane (positive eastward).

+
+
vp: float or np.ndarray

Second component of vector on tangent plane (positive northward).

+
+
longitudefloat or np.ndarray

Longitude in degrees of tangent point of plane.

+
+
latitudefloat or np.ndarray

Latitude in degrees of tangent point of plane.

+
+
+
+
+
+

Returns#

+
+
+
ufloat or np.ndarray

First component of Cartesian vector.

+
+
vfloat or np.ndarray

Second component of Cartesian vector.

+
+
wfloat or np.ndarray

Third component of Cartesian vector.

+
+
+
+
+
+

Examples#

+
>>> u, v, w = tangentplane_to_cartesian(1, 1, 45, 90)
+
+
+
+
+

Notes#

+

This function is inverted by cartesian_to_tangetplane().

+
+
+

See Also#

+

cartesian_to_tangentplane()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.html b/_autosummary/clouddrift.wavelet.html new file mode 100644 index 00000000..e05dc56e --- /dev/null +++ b/_autosummary/clouddrift.wavelet.html @@ -0,0 +1,1088 @@ + + + + + + + + + + + clouddrift.wavelet — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + + + + + + +
+ +
+

clouddrift.wavelet#

+

This module provides functions for computing wavelet transforms and time-frequency analyses, +notably using generalized Morse wavelets.

+

The Python code in this module was translated from the MATLAB implementation +by J. M. Lilly in the jWavelet module of jLab (http://jmlilly.net/code.html).

+

Lilly, J. M. (2021), jLab: A data analysis package for Matlab, v.1.7.1, +doi:10.5281/zenodo.4547006, http://www.jmlilly.net/software.

+

jLab is licensed under the Creative Commons Attribution-Noncommercial-ShareAlike +License (https://creativecommons.org/licenses/by-nc-sa/4.0/). The code that is +directly translated from jLab/jWavelet is licensed under the same license. +Any other code that is added to this module and that is specific to Python and +not the MATLAB implementation is licensed under CloudDrift’s MIT license.

+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + +

morse_amplitude(gamma, beta[, order, ...])

Calculate the amplitude coefficient of the generalized Morse wavelets.

morse_freq(gamma, beta)

Frequency measures for generalized Morse wavelets.

morse_logspace_freq(gamma, beta, length[, ...])

Compute logarithmically-spaced frequencies for generalized Morse wavelets with parameters gamma and beta.

morse_properties(gamma, beta)

Calculate the properties of the demodulated generalized Morse wavelets.

morse_wavelet(length, gamma, beta, ...[, ...])

Compute the generalized Morse wavelets of Olhede and Walden (2002), doi: 10.1109/TSP.2002.804066.

morse_wavelet_transform(x, gamma, beta, ...)

Apply a continuous wavelet transform to an input signal using the generalized Morse wavelets of Olhede and Walden (2002).

wavelet_transform(x, wavelet[, boundary, ...])

Apply a continuous wavelet transform to an input signal using an input wavelet function.

+
+
+clouddrift.wavelet.morse_amplitude(gamma: ndarray | float, beta: ndarray | float, order: int64 | None = 1, normalization: str | None = 'bandpass') float[source]#
+

Calculate the amplitude coefficient of the generalized Morse wavelets. +By default, the amplitude is calculated such that the maximum of the +frequency-domain wavelet is equal to 2, which is the bandpass normalization. +Optionally, specify normalization="energy" in order to return the coefficient +giving the wavelets unit energies. See Lilly and Olhede (2009), doi doi: 10.1109/TSP.2008.2007607.

+
+

Parameters#

+
+
gammanp.ndarray or float

Gamma parameter of the wavelets.

+
+
betanp.ndarray or float

Beta parameter of the wavelets.

+
+
orderint, optional

Order of wavelets, default is 1.

+
+
normalizationstr, optional

Normalization for the wavelets. By default it is assumed to be "bandpass" +which uses a bandpass normalization, meaning that the FFT of the wavelets +have peak value of 2 for all central frequencies radian_frequency. The other option is "energy" +which uses the unit energy normalization. In this last case the time-domain wavelet +energies np.sum(np.abs(wave)**2) are always unity.

+
+
+
+
+

Returns#

+
+
ampnp.ndarray or float

The amplitude coefficient of the wavelets.

+
+
+
+
+

Examples#

+

TODO

+
+
+

See Also#

+

morse_wavelet(), morse_freq(), morse_properties(), morse_logspace_freq().

+
+
+ +
+
+clouddrift.wavelet.morse_freq(gamma: ndarray | float, beta: ndarray | float) Tuple[ndarray] | Tuple[float][source]#
+

Frequency measures for generalized Morse wavelets. This functions calculates +three different measures fm, fe, and fi of the frequency of the lowest-order generalized Morse +wavelet specified by parameters gamma and beta.

+

Note that all frequency quantities here are in radian as in cos(f t) and not +cyclic as in np.cos(2 np.pi f t).

+

For beta=0, the corresponding wavelet becomes an analytic lowpass filter, and fm +is not defined in the usual way but as the point at which the filter has decayed +to one-half of its peak power.

+

For details see Lilly and Olhede (2009), doi: 10.1109/TSP.2008.2007607.

+
+

Parameters#

+
+
gammanp.ndarray or float

Gamma parameter of the wavelets.

+
+
betanp.ndarray or float

Beta parameter of the wavelets.

+
+
+
+
+

Returns#

+
+
fmnp.ndarray

The modal or peak frequency.

+
+
fenp.ndarray

The energy frequency.

+
+
finp.ndarray

The instantaneous frequency at the wavelets’ centers.

+
+
+
+
+

Examples#

+
>>> fm, fe, fi = morse_freq(3, 4)
+
+
+
>>> morse_freq(3, 4)
+(array(1.10064242), 1.1025129235952809, 1.1077321674324723)
+
+
+
>>> morse_freq(3, np.array([10, 20, 30]))
+(array([1.49380158, 1.88207206, 2.15443469]),
+array([1.49421505, 1.88220264, 2.15450116]),
+array([1.49543843, 1.88259299, 2.15470024]))
+
+
+
>>> morse_freq(np.array([3, 4, 5]), np.array([10, 20, 30]))
+(array([1.49380158, 1.49534878, 1.43096908]),
+array([1.49421505, 1.49080278, 1.4262489 ]),
+array([1.49543843, 1.48652036, 1.42163583]))
+
+
+
>>> morse_freq(np.array([3, 4, 5]), 10)
+(array([1.49380158, 1.25743343, 1.14869835]),
+array([1.49421505, 1.25000964, 1.13759731]),
+array([1.49543843, 1.24350315, 1.12739747]))
+
+
+
+
+

See Also#

+

morse_wavelet(), morse_amplitude()

+
+
+ +
+
+clouddrift.wavelet.morse_logspace_freq(gamma: float, beta: float, length: int, highset: Tuple[float] | None = (0.1, 3.141592653589793), lowset: Tuple[float] | None = (5, 0), density: int | None = 4) ndarray[source]#
+

Compute logarithmically-spaced frequencies for generalized Morse wavelets +with parameters gamma and beta. This is a useful function to obtain the frequencies +needed for time-frequency analyses using wavelets. If radian_frequencies is the +output, np.log(radian_frequencies) is uniformly spaced, following convention +for wavelet analysis. See Lilly (2017), doi: 10.1098/rspa.2016.0776.

+

Default settings to compute the frequencies can be changed by passing optional +arguments lowset, highset, and density. See below.

+
+

Parameters#

+
+
gammafloat

Gamma parameter of the Morse wavelets.

+
+
betafloat

Beta parameter of the Morse wavelets.

+
+
lengthint

Length of the Morse wavelets and input signals.

+
+
highsettuple of floats, optional.

Tuple of values (eta, high) used for high-frequency cutoff calculation. The highest +frequency is set to be the minimum of a specified value and a cutoff frequency +based on a Nyquist overlap condition: the highest frequency is the minimum of +the specified value high, and the largest frequency for which the wavelet will +satisfy the threshold level eta. Here eta be a number between zero and one +specifying the ratio of a frequency-domain wavelet at the Nyquist frequency +to its peak value. Default is (eta, high) = (0.1, np.pi).

+
+
lowsettuple of floats, optional.

Tupe of values (P, low) set used for low-frequency cutoff calculation based on an +endpoint overlap condition. The lowest frequency is set such that the lowest-frequency +wavelet will reach some number P, called the packing number, times its central window +width at the ends of the time series. A choice of P=1 corresponds to roughly 95% of +the time-domain wavelet energy being contained within the time series endpoints for +a wavelet at the center of the domain. The second value of the tuple is the absolute +lowest frequency. Default is (P, low) = (5, 0).

+
+
densityint, optional

This optional argument controls the number of points in the returned frequency +array. Higher values of density mean more overlap in the frequency +domain between transforms. When density=1, the peak of one wavelet is located at the +half-power points of the adjacent wavelet. The default density=4 means +that four other wavelets will occur between the peak of one wavelet and +its half-power point.

+
+
+
+
+

Returns#

+
+
radian_frequencynp.ndarray

Logarithmically-spaced frequencies in radians cycles per unit time, +sorted in descending order.

+
+
+
+
+

Examples#

+

Generate a frequency array for the generalized Morse wavelet +with parameters gamma=3 and beta=5 for a time series of length n=1024:

+
>>> radian_frequency = morse_logspace_freq(3, 5, 1024)
+>>> radian_frequency = morse_logspace_freq(3, 5, 1024, highset=(0.2, np.pi), lowset=(5, 0))
+>>> radian_frequency = morse_logspace_freq(3, 5, 1024, highset=(0.2, np.pi), lowset=(5, 0), density=10)
+
+
+
+
+

See Also#

+

morse_wavelet(), morse_freq(), morse_properties()

+
+
+ +
+
+clouddrift.wavelet.morse_properties(gamma: ndarray | float, beta: ndarray | float) Tuple[ndarray] | Tuple[float][source]#
+

Calculate the properties of the demodulated generalized Morse wavelets. +See Lilly and Olhede (2009), doi: 10.1109/TSP.2008.2007607.

+
+

Parameters#

+
+
gammanp.ndarray or float

Gamma parameter of the wavelets.

+
+
betanp.ndarray or float

Beta parameter of the wavelets.

+
+
+
+
+

Returns#

+
+
widthnp.ndarray or float

Dimensionless time-domain window width of the wavelets.

+
+
skewnp.ndarray or float

Imaginary part of normalized third moment of the time-domain demodulate, +or ‘demodulate skewness’.

+
+
kurtnp.ndarray or float

Normalized fourth moment of the time-domain demodulate, +or ‘demodulate kurtosis’.

+
+
+
+
+

Examples#

+

TODO

+
+
+

See Also#

+

morse_wavelet(), morse_freq(), morse_amplitude(), morse_logspace_freq().

+
+
+ +
+
+clouddrift.wavelet.morse_wavelet(length: int, gamma: float, beta: float, radian_frequency: ndarray, order: int | None = 1, normalization: str | None = 'bandpass') Tuple[ndarray, ndarray][source]#
+

Compute the generalized Morse wavelets of Olhede and Walden (2002), doi: 10.1109/TSP.2002.804066.

+
+

Parameters#

+
+
lengthint

Length of the wavelets.

+
+
gammafloat

Gamma parameter of the wavelets.

+
+
betafloat

Beta parameter of the wavelets.

+
+
radian_frequencynp.ndarray

The radian frequencies at which the Fourier transform of the wavelets +reach their maximum amplitudes. radian_frequency is between 0 and 2 * np.pi * 0.5, +the normalized Nyquist radian frequency.

+
+
orderint, optional

Order of wavelets, default is 1.

+
+
normalizationstr, optional

Normalization for the wavelet output. By default it is assumed to be "bandpass" +which uses a bandpass normalization, meaning that the FFT of the wavelets +have peak value of 2 for all central frequencies radian_frequency. The other option is +"energy"``which uses the unit energy normalization. In this last case, the time-domain wavelet +energies ``np.sum(np.abs(wave)**2) are always unity.

+
+
+
+
+

Returns#

+
+
waveletnp.ndarray

Time-domain wavelets with shape (order, radian_frequency, length).

+
+
wavelet_fft: np.ndarray

Frequency-domain wavelets with shape (order, radian_frequency, length).

+
+
+
+
+

Examples#

+

Compute a Morse wavelet with gamma parameter 3, beta parameter 4, at radian +frequency 0.2 cycles per unit time:

+
>>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]))
+>>> np.shape(wavelet)
+(1, 1, 1024)
+
+
+

Compute a suite of Morse wavelets with gamma parameter 3, beta parameter 4, up to order 3, +at radian frequencies 0.2 and 0.3 cycles per unit time:

+
>>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2, 2*np.pi*0.3]), order=3)
+>>> np.shape(wavelet)
+(3, 2, 1024)
+
+
+

Compute a Morse wavelet specifying an energy normalization : +>>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]), normalization=”energy”)

+
+
+

Raises#

+
+
ValueError

If normalization optional argument is not in [“bandpass”, “energy”]``.

+
+
+
+
+

See Also#

+

wavelet_transform(), morse_wavelet_transform(), morse_freq(), morse_logspace_freq(), morse_amplitude(), morse_properties()

+
+
+ +
+
+clouddrift.wavelet.morse_wavelet_transform(x: ndarray, gamma: float, beta: float, radian_frequency: ndarray, complex: bool | None = False, order: int | None = 1, normalization: str | None = 'bandpass', boundary: str | None = 'mirror', time_axis: int | None = -1) Tuple[ndarray] | ndarray[source]#
+

Apply a continuous wavelet transform to an input signal using the generalized Morse +wavelets of Olhede and Walden (2002). The wavelet transform is normalized differently +for complex-valued input than for real-valued input, and this in turns depends on whether the +optional argument normalization is set to "bandpass" or "energy" normalizations.

+
+

Parameters#

+
+
xnp.ndarray

Real- or complex-valued signals. The time axis is assumed to be the last. If not, specify optional +argument time_axis.

+
+
gammafloat

Gamma parameter of the Morse wavelets.

+
+
betafloat

Beta parameter of the Morse wavelets.

+
+
radian_frequencynp.ndarray

An array of radian frequencies at which the Fourier transform of the wavelets +reach their maximum amplitudes. radian_frequency is typically between 0 and 2 * np.pi * 0.5, +the normalized Nyquist radian frequency.

+
+
complexboolean, optional

Specify explicitely if the input signal x is a complex signal. Default is False which +means that the input is real but that is not explicitely tested by the function. +This choice affects the normalization of the outputs and their interpretation. +See examples below.

+
+
time_axisint, optional

Axis on which the time is defined for input x (default is last, or -1).

+
+
normalizationstr, optional

Normalization for the wavelet transforms. By default it is assumed to be +"bandpass" which uses a bandpass normalization, meaning that the FFT +of the wavelets have peak value of 2 for all central frequencies +radian_frequency. However, if the optional argument complex=True +is specified, the wavelets will be divided by 2 so that the total +variance of the input complex signal is equal to the sum of the +variances of the returned analytic (positive) and conjugate analytic +(negative) parts. See examples below. The other option is "energy" +which uses the unit energy normalization. In this last case, the +time-domain wavelet energies np.sum(np.abs(wave)**2) are always +unity.

+
+
boundarystr, optional

The boundary condition to be imposed at the edges of the input signal x. +Allowed values are "mirror", "zeros", and "periodic". Default is "mirror".

+
+
orderint, optional

Order of Morse wavelets, default is 1.

+
+
+
+
+

Returns#

+

If the input signal is real as specificied by complex=False:

+
+
wtxnp.ndarray

Time-domain wavelet transform of input x with shape ((x shape without time_axis), orders, frequencies, time_axis) +but with dimensions of length 1 removed (squeezed).

+
+
+

If the input signal is complex as specificied by complex=True, a tuple is returned:

+
+
wtx_pnp.array

Time-domain positive wavelet transform of input x with shape ((x shape without time_axis), frequencies, orders), +but with dimensions of length 1 removed (squeezed).

+
+
wtx_nnp.array

Time-domain negative wavelet transform of input x with shape ((x shape without time_axis), frequencies, orders), +but with dimensions of length 1 removed (squeezed).

+
+
+
+
+

Examples#

+

Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta parameter 4, +at radian frequency 0.2 cycles per unit time:

+
>>> x = np.random.random(1024)
+>>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]))
+
+
+

Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta parameter 4, +for a complex input signal at radian frequency 0.2 cycles per unit time. This case returns the +analytic and conjugate analytic components:

+
>>> z = np.random.random(1024) + 1j*np.random.random(1024)
+>>> wtz_p, wtz_n = morse_wavelet_transform(z, 3, 4, np.array([2*np.pi*0.2]), complex=True)
+
+
+

The same result as above can be otained by applying the Morse transform on the real and imaginary +component of z and recombining the results as follows for the “bandpass” normalization: +>>> wtz_real = morse_wavelet_transform(np.real(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_imag = morse_wavelet_transform(np.imag(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_p, wtz_n = (wtz_real + 1j*wtz_imag) / 2, (wtz_real - 1j*wtz_imag) / 2

+

For the “energy” normalization, the analytic and conjugate analytic components are obtained as follows +with this alternative method: +>>> wtz_real = morse_wavelet_transform(np.real(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_imag = morse_wavelet_transform(np.imag(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_p, wtz_n = (wtz_real + 1j*wtz_imag) / np.sqrt(2), (wtz_real - 1j*wtz_imag) / np.sqrt(2)

+

The input signal can have an arbitrary number of dimensions but its time_axis must be +specified if it is not the last:

+
>>> x = np.random.random((1024,10,15))
+>>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]), time_axis=0)
+
+
+

The default way to handle the boundary conditions is to mirror the ends points +but this can be changed by specifying the chosen boundary method:

+
>>> x = np.random.random((10,15,1024))
+>>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]), boundary="periodic")
+
+
+

This function can be used to conduct a time-frequency analysis of the input signal by specifying +a range of randian frequencies using the morse_logspace_freq function as an example:

+
>>> x = np.random.random(1024)
+>>> gamma = 3
+>>> beta = 4
+>>> radian_frequency = morse_logspace_freq(gamma, beta, np.shape(x)[0])
+>>> wtx = morse_wavelet_transform(x, gamma, beta, radian_frequency)
+
+
+
+
+

Raises#

+
+
ValueError

If the time axis is outside of the valid range ([-1, np.ndim(x)-1]). +If boundary optional argument is not in [“mirror”, “zeros”, “periodic”]``. +If normalization optional argument is not in [“bandpass”, “energy”]``.

+
+
+
+
+

See Also#

+

morse_wavelet(), wavelet_transform(), morse_logspace_freq()

+
+
+ +
+
+clouddrift.wavelet.wavelet_transform(x: ndarray, wavelet: ndarray, boundary: str | None = 'mirror', time_axis: int | None = -1, freq_axis: int | None = -2, order_axis: int | None = -3) ndarray[source]#
+

Apply a continuous wavelet transform to an input signal using an input wavelet +function. Such wavelet can be provided by the function morse_wavelet.

+
+

Parameters#

+
+
xnp.ndarray

Real- or complex-valued signals.

+
+
waveletnp.ndarray

A suite of time-domain wavelets, typically returned by the function morse_wavelet. +The length of the time axis of the wavelets must be the last one and matches the +length of the time axis of x. The other dimensions (axes) of the wavelets (such as orders and frequencies) are +typically organized as orders, frequencies, and time, unless specified by optional arguments freq_axis and order_axis. +The normalization of the wavelets is assumed to be “bandpass”, if not, use kwarg normalization=”energy”, see morse_wavelet.

+
+
boundarystr, optional

The boundary condition to be imposed at the edges of the input signal x. +Allowed values are "mirror", "zeros", and "periodic". Default is "mirror".

+
+
time_axisint, optional

Axis on which the time is defined for input x (default is last, or -1). Note that the time axis of the +wavelets must be last.

+
+
freq_axisint, optional

Axis of wavelet for the frequencies (default is second or 1)

+
+
order_axisint, optional

Axis of wavelet for the orders (default is first or 0)

+
+
+
+
+

Returns#

+
+
wtxnp.ndarray

Time-domain wavelet transform of x with shape ((x shape without time_axis), orders, frequencies, time_axis) +but with dimensions of length 1 removed (squeezed).

+
+
+
+
+

Examples#

+

Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta +parameter 4, at radian frequency 0.2 cycles per unit time:

+
>>> x = np.random.random(1024)
+>>> wavelet, _ = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]))
+>>> wtx = wavelet_transform(x, wavelet)
+
+
+

The input signal can have an arbitrary number of dimensions but its +time_axis must be specified if it is not the last:

+
>>> x = np.random.random((1024,10,15))
+>>> wavelet, _ = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]))
+>>> wtx = wavelet_transform(x, wavelet,time_axis=0)
+
+
+
+
+

Raises#

+
+
ValueError

If the time axis is outside of the valid range ([-1, N-1]). +If the shape of time axis is different for input signal and wavelet. +If boundary optional argument is not in [“mirror”, “zeros”, “periodic”]``.

+
+
+
+
+

See Also#

+

morse_wavelet(), morse_wavelet_transform(), morse_freq()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + + + + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.morse_amplitude.html b/_autosummary/clouddrift.wavelet.morse_amplitude.html new file mode 100644 index 00000000..1bd7f539 --- /dev/null +++ b/_autosummary/clouddrift.wavelet.morse_amplitude.html @@ -0,0 +1,605 @@ + + + + + + + + + + + clouddrift.wavelet.morse_amplitude — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.morse_amplitude

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.morse_amplitude#

+
+
+clouddrift.wavelet.morse_amplitude(gamma: ndarray | float, beta: ndarray | float, order: int64 | None = 1, normalization: str | None = 'bandpass') float[source]#
+

Calculate the amplitude coefficient of the generalized Morse wavelets. +By default, the amplitude is calculated such that the maximum of the +frequency-domain wavelet is equal to 2, which is the bandpass normalization. +Optionally, specify normalization="energy" in order to return the coefficient +giving the wavelets unit energies. See Lilly and Olhede (2009), doi doi: 10.1109/TSP.2008.2007607.

+
+

Parameters#

+
+
gammanp.ndarray or float

Gamma parameter of the wavelets.

+
+
betanp.ndarray or float

Beta parameter of the wavelets.

+
+
orderint, optional

Order of wavelets, default is 1.

+
+
normalizationstr, optional

Normalization for the wavelets. By default it is assumed to be "bandpass" +which uses a bandpass normalization, meaning that the FFT of the wavelets +have peak value of 2 for all central frequencies radian_frequency. The other option is "energy" +which uses the unit energy normalization. In this last case the time-domain wavelet +energies np.sum(np.abs(wave)**2) are always unity.

+
+
+
+
+

Returns#

+
+
ampnp.ndarray or float

The amplitude coefficient of the wavelets.

+
+
+
+
+

Examples#

+

TODO

+
+
+

See Also#

+

morse_wavelet(), morse_freq(), morse_properties(), morse_logspace_freq().

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.morse_freq.html b/_autosummary/clouddrift.wavelet.morse_freq.html new file mode 100644 index 00000000..6222d6d5 --- /dev/null +++ b/_autosummary/clouddrift.wavelet.morse_freq.html @@ -0,0 +1,629 @@ + + + + + + + + + + + clouddrift.wavelet.morse_freq — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.morse_freq

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.morse_freq#

+
+
+clouddrift.wavelet.morse_freq(gamma: ndarray | float, beta: ndarray | float) Tuple[ndarray] | Tuple[float][source]#
+

Frequency measures for generalized Morse wavelets. This functions calculates +three different measures fm, fe, and fi of the frequency of the lowest-order generalized Morse +wavelet specified by parameters gamma and beta.

+

Note that all frequency quantities here are in radian as in cos(f t) and not +cyclic as in np.cos(2 np.pi f t).

+

For beta=0, the corresponding wavelet becomes an analytic lowpass filter, and fm +is not defined in the usual way but as the point at which the filter has decayed +to one-half of its peak power.

+

For details see Lilly and Olhede (2009), doi: 10.1109/TSP.2008.2007607.

+
+

Parameters#

+
+
gammanp.ndarray or float

Gamma parameter of the wavelets.

+
+
betanp.ndarray or float

Beta parameter of the wavelets.

+
+
+
+
+

Returns#

+
+
fmnp.ndarray

The modal or peak frequency.

+
+
fenp.ndarray

The energy frequency.

+
+
finp.ndarray

The instantaneous frequency at the wavelets’ centers.

+
+
+
+
+

Examples#

+
>>> fm, fe, fi = morse_freq(3, 4)
+
+
+
>>> morse_freq(3, 4)
+(array(1.10064242), 1.1025129235952809, 1.1077321674324723)
+
+
+
>>> morse_freq(3, np.array([10, 20, 30]))
+(array([1.49380158, 1.88207206, 2.15443469]),
+array([1.49421505, 1.88220264, 2.15450116]),
+array([1.49543843, 1.88259299, 2.15470024]))
+
+
+
>>> morse_freq(np.array([3, 4, 5]), np.array([10, 20, 30]))
+(array([1.49380158, 1.49534878, 1.43096908]),
+array([1.49421505, 1.49080278, 1.4262489 ]),
+array([1.49543843, 1.48652036, 1.42163583]))
+
+
+
>>> morse_freq(np.array([3, 4, 5]), 10)
+(array([1.49380158, 1.25743343, 1.14869835]),
+array([1.49421505, 1.25000964, 1.13759731]),
+array([1.49543843, 1.24350315, 1.12739747]))
+
+
+
+
+

See Also#

+

morse_wavelet(), morse_amplitude()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.morse_logspace_freq.html b/_autosummary/clouddrift.wavelet.morse_logspace_freq.html new file mode 100644 index 00000000..5cfcceb5 --- /dev/null +++ b/_autosummary/clouddrift.wavelet.morse_logspace_freq.html @@ -0,0 +1,631 @@ + + + + + + + + + + + clouddrift.wavelet.morse_logspace_freq — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.morse_logspace_freq

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.morse_logspace_freq#

+
+
+clouddrift.wavelet.morse_logspace_freq(gamma: float, beta: float, length: int, highset: Tuple[float] | None = (0.1, 3.141592653589793), lowset: Tuple[float] | None = (5, 0), density: int | None = 4) ndarray[source]#
+

Compute logarithmically-spaced frequencies for generalized Morse wavelets +with parameters gamma and beta. This is a useful function to obtain the frequencies +needed for time-frequency analyses using wavelets. If radian_frequencies is the +output, np.log(radian_frequencies) is uniformly spaced, following convention +for wavelet analysis. See Lilly (2017), doi: 10.1098/rspa.2016.0776.

+

Default settings to compute the frequencies can be changed by passing optional +arguments lowset, highset, and density. See below.

+
+

Parameters#

+
+
gammafloat

Gamma parameter of the Morse wavelets.

+
+
betafloat

Beta parameter of the Morse wavelets.

+
+
lengthint

Length of the Morse wavelets and input signals.

+
+
highsettuple of floats, optional.

Tuple of values (eta, high) used for high-frequency cutoff calculation. The highest +frequency is set to be the minimum of a specified value and a cutoff frequency +based on a Nyquist overlap condition: the highest frequency is the minimum of +the specified value high, and the largest frequency for which the wavelet will +satisfy the threshold level eta. Here eta be a number between zero and one +specifying the ratio of a frequency-domain wavelet at the Nyquist frequency +to its peak value. Default is (eta, high) = (0.1, np.pi).

+
+
lowsettuple of floats, optional.

Tupe of values (P, low) set used for low-frequency cutoff calculation based on an +endpoint overlap condition. The lowest frequency is set such that the lowest-frequency +wavelet will reach some number P, called the packing number, times its central window +width at the ends of the time series. A choice of P=1 corresponds to roughly 95% of +the time-domain wavelet energy being contained within the time series endpoints for +a wavelet at the center of the domain. The second value of the tuple is the absolute +lowest frequency. Default is (P, low) = (5, 0).

+
+
densityint, optional

This optional argument controls the number of points in the returned frequency +array. Higher values of density mean more overlap in the frequency +domain between transforms. When density=1, the peak of one wavelet is located at the +half-power points of the adjacent wavelet. The default density=4 means +that four other wavelets will occur between the peak of one wavelet and +its half-power point.

+
+
+
+
+

Returns#

+
+
radian_frequencynp.ndarray

Logarithmically-spaced frequencies in radians cycles per unit time, +sorted in descending order.

+
+
+
+
+

Examples#

+

Generate a frequency array for the generalized Morse wavelet +with parameters gamma=3 and beta=5 for a time series of length n=1024:

+
>>> radian_frequency = morse_logspace_freq(3, 5, 1024)
+>>> radian_frequency = morse_logspace_freq(3, 5, 1024, highset=(0.2, np.pi), lowset=(5, 0))
+>>> radian_frequency = morse_logspace_freq(3, 5, 1024, highset=(0.2, np.pi), lowset=(5, 0), density=10)
+
+
+
+
+

See Also#

+

morse_wavelet(), morse_freq(), morse_properties()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.morse_properties.html b/_autosummary/clouddrift.wavelet.morse_properties.html new file mode 100644 index 00000000..4cfb1ade --- /dev/null +++ b/_autosummary/clouddrift.wavelet.morse_properties.html @@ -0,0 +1,600 @@ + + + + + + + + + + + clouddrift.wavelet.morse_properties — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.morse_properties

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.morse_properties#

+
+
+clouddrift.wavelet.morse_properties(gamma: ndarray | float, beta: ndarray | float) Tuple[ndarray] | Tuple[float][source]#
+

Calculate the properties of the demodulated generalized Morse wavelets. +See Lilly and Olhede (2009), doi: 10.1109/TSP.2008.2007607.

+
+

Parameters#

+
+
gammanp.ndarray or float

Gamma parameter of the wavelets.

+
+
betanp.ndarray or float

Beta parameter of the wavelets.

+
+
+
+
+

Returns#

+
+
widthnp.ndarray or float

Dimensionless time-domain window width of the wavelets.

+
+
skewnp.ndarray or float

Imaginary part of normalized third moment of the time-domain demodulate, +or ‘demodulate skewness’.

+
+
kurtnp.ndarray or float

Normalized fourth moment of the time-domain demodulate, +or ‘demodulate kurtosis’.

+
+
+
+
+

Examples#

+

TODO

+
+
+

See Also#

+

morse_wavelet(), morse_freq(), morse_amplitude(), morse_logspace_freq().

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.morse_wavelet.html b/_autosummary/clouddrift.wavelet.morse_wavelet.html new file mode 100644 index 00000000..a8a34964 --- /dev/null +++ b/_autosummary/clouddrift.wavelet.morse_wavelet.html @@ -0,0 +1,631 @@ + + + + + + + + + + + clouddrift.wavelet.morse_wavelet — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.morse_wavelet

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.morse_wavelet#

+
+
+clouddrift.wavelet.morse_wavelet(length: int, gamma: float, beta: float, radian_frequency: ndarray, order: int | None = 1, normalization: str | None = 'bandpass') Tuple[ndarray, ndarray][source]#
+

Compute the generalized Morse wavelets of Olhede and Walden (2002), doi: 10.1109/TSP.2002.804066.

+
+

Parameters#

+
+
lengthint

Length of the wavelets.

+
+
gammafloat

Gamma parameter of the wavelets.

+
+
betafloat

Beta parameter of the wavelets.

+
+
radian_frequencynp.ndarray

The radian frequencies at which the Fourier transform of the wavelets +reach their maximum amplitudes. radian_frequency is between 0 and 2 * np.pi * 0.5, +the normalized Nyquist radian frequency.

+
+
orderint, optional

Order of wavelets, default is 1.

+
+
normalizationstr, optional

Normalization for the wavelet output. By default it is assumed to be "bandpass" +which uses a bandpass normalization, meaning that the FFT of the wavelets +have peak value of 2 for all central frequencies radian_frequency. The other option is +"energy"``which uses the unit energy normalization. In this last case, the time-domain wavelet +energies ``np.sum(np.abs(wave)**2) are always unity.

+
+
+
+
+

Returns#

+
+
waveletnp.ndarray

Time-domain wavelets with shape (order, radian_frequency, length).

+
+
wavelet_fft: np.ndarray

Frequency-domain wavelets with shape (order, radian_frequency, length).

+
+
+
+
+

Examples#

+

Compute a Morse wavelet with gamma parameter 3, beta parameter 4, at radian +frequency 0.2 cycles per unit time:

+
>>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]))
+>>> np.shape(wavelet)
+(1, 1, 1024)
+
+
+

Compute a suite of Morse wavelets with gamma parameter 3, beta parameter 4, up to order 3, +at radian frequencies 0.2 and 0.3 cycles per unit time:

+
>>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2, 2*np.pi*0.3]), order=3)
+>>> np.shape(wavelet)
+(3, 2, 1024)
+
+
+

Compute a Morse wavelet specifying an energy normalization : +>>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]), normalization=”energy”)

+
+
+

Raises#

+
+
ValueError

If normalization optional argument is not in [“bandpass”, “energy”]``.

+
+
+
+
+

See Also#

+

wavelet_transform(), morse_wavelet_transform(), morse_freq(), morse_logspace_freq(), morse_amplitude(), morse_properties()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.morse_wavelet_transform.html b/_autosummary/clouddrift.wavelet.morse_wavelet_transform.html new file mode 100644 index 00000000..a57d9657 --- /dev/null +++ b/_autosummary/clouddrift.wavelet.morse_wavelet_transform.html @@ -0,0 +1,690 @@ + + + + + + + + + + + clouddrift.wavelet.morse_wavelet_transform — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.morse_wavelet_transform

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.morse_wavelet_transform#

+
+
+clouddrift.wavelet.morse_wavelet_transform(x: ndarray, gamma: float, beta: float, radian_frequency: ndarray, complex: bool | None = False, order: int | None = 1, normalization: str | None = 'bandpass', boundary: str | None = 'mirror', time_axis: int | None = -1) Tuple[ndarray] | ndarray[source]#
+

Apply a continuous wavelet transform to an input signal using the generalized Morse +wavelets of Olhede and Walden (2002). The wavelet transform is normalized differently +for complex-valued input than for real-valued input, and this in turns depends on whether the +optional argument normalization is set to "bandpass" or "energy" normalizations.

+
+

Parameters#

+
+
xnp.ndarray

Real- or complex-valued signals. The time axis is assumed to be the last. If not, specify optional +argument time_axis.

+
+
gammafloat

Gamma parameter of the Morse wavelets.

+
+
betafloat

Beta parameter of the Morse wavelets.

+
+
radian_frequencynp.ndarray

An array of radian frequencies at which the Fourier transform of the wavelets +reach their maximum amplitudes. radian_frequency is typically between 0 and 2 * np.pi * 0.5, +the normalized Nyquist radian frequency.

+
+
complexboolean, optional

Specify explicitely if the input signal x is a complex signal. Default is False which +means that the input is real but that is not explicitely tested by the function. +This choice affects the normalization of the outputs and their interpretation. +See examples below.

+
+
time_axisint, optional

Axis on which the time is defined for input x (default is last, or -1).

+
+
normalizationstr, optional

Normalization for the wavelet transforms. By default it is assumed to be +"bandpass" which uses a bandpass normalization, meaning that the FFT +of the wavelets have peak value of 2 for all central frequencies +radian_frequency. However, if the optional argument complex=True +is specified, the wavelets will be divided by 2 so that the total +variance of the input complex signal is equal to the sum of the +variances of the returned analytic (positive) and conjugate analytic +(negative) parts. See examples below. The other option is "energy" +which uses the unit energy normalization. In this last case, the +time-domain wavelet energies np.sum(np.abs(wave)**2) are always +unity.

+
+
boundarystr, optional

The boundary condition to be imposed at the edges of the input signal x. +Allowed values are "mirror", "zeros", and "periodic". Default is "mirror".

+
+
orderint, optional

Order of Morse wavelets, default is 1.

+
+
+
+
+

Returns#

+

If the input signal is real as specificied by complex=False:

+
+
wtxnp.ndarray

Time-domain wavelet transform of input x with shape ((x shape without time_axis), orders, frequencies, time_axis) +but with dimensions of length 1 removed (squeezed).

+
+
+

If the input signal is complex as specificied by complex=True, a tuple is returned:

+
+
wtx_pnp.array

Time-domain positive wavelet transform of input x with shape ((x shape without time_axis), frequencies, orders), +but with dimensions of length 1 removed (squeezed).

+
+
wtx_nnp.array

Time-domain negative wavelet transform of input x with shape ((x shape without time_axis), frequencies, orders), +but with dimensions of length 1 removed (squeezed).

+
+
+
+
+

Examples#

+

Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta parameter 4, +at radian frequency 0.2 cycles per unit time:

+
>>> x = np.random.random(1024)
+>>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]))
+
+
+

Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta parameter 4, +for a complex input signal at radian frequency 0.2 cycles per unit time. This case returns the +analytic and conjugate analytic components:

+
>>> z = np.random.random(1024) + 1j*np.random.random(1024)
+>>> wtz_p, wtz_n = morse_wavelet_transform(z, 3, 4, np.array([2*np.pi*0.2]), complex=True)
+
+
+

The same result as above can be otained by applying the Morse transform on the real and imaginary +component of z and recombining the results as follows for the “bandpass” normalization: +>>> wtz_real = morse_wavelet_transform(np.real(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_imag = morse_wavelet_transform(np.imag(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_p, wtz_n = (wtz_real + 1j*wtz_imag) / 2, (wtz_real - 1j*wtz_imag) / 2

+

For the “energy” normalization, the analytic and conjugate analytic components are obtained as follows +with this alternative method: +>>> wtz_real = morse_wavelet_transform(np.real(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_imag = morse_wavelet_transform(np.imag(z)), 3, 4, np.array([2*np.pi*0.2])) +>>> wtz_p, wtz_n = (wtz_real + 1j*wtz_imag) / np.sqrt(2), (wtz_real - 1j*wtz_imag) / np.sqrt(2)

+

The input signal can have an arbitrary number of dimensions but its time_axis must be +specified if it is not the last:

+
>>> x = np.random.random((1024,10,15))
+>>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]), time_axis=0)
+
+
+

The default way to handle the boundary conditions is to mirror the ends points +but this can be changed by specifying the chosen boundary method:

+
>>> x = np.random.random((10,15,1024))
+>>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]), boundary="periodic")
+
+
+

This function can be used to conduct a time-frequency analysis of the input signal by specifying +a range of randian frequencies using the morse_logspace_freq function as an example:

+
>>> x = np.random.random(1024)
+>>> gamma = 3
+>>> beta = 4
+>>> radian_frequency = morse_logspace_freq(gamma, beta, np.shape(x)[0])
+>>> wtx = morse_wavelet_transform(x, gamma, beta, radian_frequency)
+
+
+
+
+

Raises#

+
+
ValueError

If the time axis is outside of the valid range ([-1, np.ndim(x)-1]). +If boundary optional argument is not in [“mirror”, “zeros”, “periodic”]``. +If normalization optional argument is not in [“bandpass”, “energy”]``.

+
+
+
+
+

See Also#

+

morse_wavelet(), wavelet_transform(), morse_logspace_freq()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autosummary/clouddrift.wavelet.wavelet_transform.html b/_autosummary/clouddrift.wavelet.wavelet_transform.html new file mode 100644 index 00000000..d213c52d --- /dev/null +++ b/_autosummary/clouddrift.wavelet.wavelet_transform.html @@ -0,0 +1,621 @@ + + + + + + + + + + + clouddrift.wavelet.wavelet_transform — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

clouddrift.wavelet.wavelet_transform

+ +
+
+ +
+

Contents

+
+ +
+
+
+ + + + +
+ +
+

clouddrift.wavelet.wavelet_transform#

+
+
+clouddrift.wavelet.wavelet_transform(x: ndarray, wavelet: ndarray, boundary: str | None = 'mirror', time_axis: int | None = -1, freq_axis: int | None = -2, order_axis: int | None = -3) ndarray[source]#
+

Apply a continuous wavelet transform to an input signal using an input wavelet +function. Such wavelet can be provided by the function morse_wavelet.

+
+

Parameters#

+
+
xnp.ndarray

Real- or complex-valued signals.

+
+
waveletnp.ndarray

A suite of time-domain wavelets, typically returned by the function morse_wavelet. +The length of the time axis of the wavelets must be the last one and matches the +length of the time axis of x. The other dimensions (axes) of the wavelets (such as orders and frequencies) are +typically organized as orders, frequencies, and time, unless specified by optional arguments freq_axis and order_axis. +The normalization of the wavelets is assumed to be “bandpass”, if not, use kwarg normalization=”energy”, see morse_wavelet.

+
+
boundarystr, optional

The boundary condition to be imposed at the edges of the input signal x. +Allowed values are "mirror", "zeros", and "periodic". Default is "mirror".

+
+
time_axisint, optional

Axis on which the time is defined for input x (default is last, or -1). Note that the time axis of the +wavelets must be last.

+
+
freq_axisint, optional

Axis of wavelet for the frequencies (default is second or 1)

+
+
order_axisint, optional

Axis of wavelet for the orders (default is first or 0)

+
+
+
+
+

Returns#

+
+
wtxnp.ndarray

Time-domain wavelet transform of x with shape ((x shape without time_axis), orders, frequencies, time_axis) +but with dimensions of length 1 removed (squeezed).

+
+
+
+
+

Examples#

+

Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta +parameter 4, at radian frequency 0.2 cycles per unit time:

+
>>> x = np.random.random(1024)
+>>> wavelet, _ = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]))
+>>> wtx = wavelet_transform(x, wavelet)
+
+
+

The input signal can have an arbitrary number of dimensions but its +time_axis must be specified if it is not the last:

+
>>> x = np.random.random((1024,10,15))
+>>> wavelet, _ = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]))
+>>> wtx = wavelet_transform(x, wavelet,time_axis=0)
+
+
+
+
+

Raises#

+
+
ValueError

If the time axis is outside of the valid range ([-1, N-1]). +If the shape of time axis is different for input signal and wavelet. +If boundary optional argument is not in [“mirror”, “zeros”, “periodic”]``.

+
+
+
+
+

See Also#

+

morse_wavelet(), morse_wavelet_transform(), morse_freq()

+
+
+ +
+ + +
+ + + + + + + + +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_images/ragged_array.png b/_images/ragged_array.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e42bb3ece40e29c29940ddec486cd7d44017ad GIT binary patch literal 305240 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≷lg}JOQM--M+eOc9~;M< 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 + + + + + + + + clouddrift.adapters.gdp — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.adapters.gdp

+"""
+This module provides functions and metadata to convert the Global Drifter
+Program (GDP) data to a ``clouddrift.RaggedArray`` instance. The functions
+defined in this module are common to both hourly (``clouddrift.adapters.gdp1h``)
+and six-hourly (``clouddrift.adapters.gdp6h``) GDP modules.
+"""
+
+from clouddrift.adapters.utils import download_with_progress
+import numpy as np
+import os
+import pandas as pd
+import xarray as xr
+
+GDP_COORDS = [
+    "ids",
+    "time",
+]
+
+GDP_METADATA = [
+    "ID",
+    "rowsize",
+    "WMO",
+    "expno",
+    "deploy_date",
+    "deploy_lat",
+    "deploy_lon",
+    "start_date",
+    "start_lat",
+    "start_lon",
+    "end_date",
+    "end_lat",
+    "end_lon",
+    "drogue_lost_date",
+    "typedeath",
+    "typebuoy",
+    "location_type",
+    "DeployingShip",
+    "DeploymentStatus",
+    "BuoyTypeManufacturer",
+    "BuoyTypeSensorArray",
+    "CurrentProgram",
+    "PurchaserFunding",
+    "SensorUpgrade",
+    "Transmissions",
+    "DeployingCountry",
+    "DeploymentComments",
+    "ManufactureYear",
+    "ManufactureMonth",
+    "ManufactureSensorType",
+    "ManufactureVoltage",
+    "FloatDiameter",
+    "SubsfcFloatPresence",
+    "DrogueType",
+    "DrogueLength",
+    "DrogueBallast",
+    "DragAreaAboveDrogue",
+    "DragAreaOfDrogue",
+    "DragAreaRatio",
+    "DrogueCenterDepth",
+    "DrogueDetectSensor",
+]
+
+
+
+[docs] +def cast_float64_variables_to_float32( + ds: xr.Dataset, variables_to_skip: list[str] = ["time", "lat", "lon"] +) -> xr.Dataset: + """Cast all float64 variables except ``variables_to_skip`` to float32. + Extra precision from float64 is not needed and takes up memory and disk + space. + + Parameters + ---------- + ds : xr.Dataset + Dataset to modify + variables_to_skip : list[str] + List of variables to skip; default is ["time", "lat", "lon"]. + + Returns + ------- + ds : xr.Dataset + Modified dataset + """ + for var in ds.variables: + if var in variables_to_skip: + continue + if ds[var].dtype == "float64": + ds[var] = ds[var].astype("float32") + return ds
+ + + +
+[docs] +def parse_directory_file(filename: str) -> pd.DataFrame: + """Read a GDP directory file that contains metadata of drifter releases. + + Parameters + ---------- + filename : str + Name of the directory file to parse. + + Returns + ------- + df : pd.DataFrame + List of drifters from a single directory file as a pandas DataFrame. + """ + GDP_DIRECTORY_FILE_URL = "https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/" + df = pd.read_csv( + os.path.join(GDP_DIRECTORY_FILE_URL, filename), delimiter="\s+", header=None + ) + + # Combine the date and time columns to easily parse dates below. + df[4] += " " + df[5] + df[8] += " " + df[9] + df[12] += " " + df[13] + df = df.drop(columns=[5, 9, 13]) + df.columns = [ + "ID", + "WMO_number", + "program_number", + "buoys_type", + "Start_date", + "Start_lat", + "Start_lon", + "End_date", + "End_lat", + "End_lon", + "Drogue_off_date", + "death_code", + ] + for t in ["Start_date", "End_date", "Drogue_off_date"]: + df[t] = pd.to_datetime(df[t], format="%Y/%m/%d %H:%M", errors="coerce") + + return df
+ + + +
+[docs] +def get_gdp_metadata() -> pd.DataFrame: + """Download and parse GDP metadata and return it as a Pandas DataFrame. + + Returns + ------- + df : pd.DataFrame + Sorted list of drifters as a pandas DataFrame. + """ + directory_file_pattern = "dirfl_{low}_{high}.dat" + + dfs = [] + start = 1 + while True: + name = directory_file_pattern.format(low=start, high=start + 4999) + try: + dfs.append(parse_directory_file(name)) + start += 5000 + except: + break + + name = directory_file_pattern.format(low=start, high="current") + dfs.append(parse_directory_file(name)) + + df = pd.concat(dfs) + df.sort_values(["Start_date"], inplace=True, ignore_index=True) + return df
+ + + +
+[docs] +def order_by_date(df: pd.DataFrame, idx: list[int]) -> np.ndarray[int]: + """From the previously sorted DataFrame of directory files, return the + unique set of drifter IDs sorted by their start date (the date of the first + quality-controlled data point). + + Parameters + ---------- + idx : list + List of drifters to include in the ragged array + + Returns + ------- + idx : list + Unique set of drifter IDs sorted by their start date. + """ + return df.ID[np.where(np.in1d(df.ID, idx))[0]].values
+ + + +
+[docs] +def fetch_netcdf(url: str, file: str): + """Download and save the file from the given url, if not already downloaded. + + Parameters + ---------- + url : str + URL from which to download the file. + file : str + Name of the file to save. + """ + download_with_progress([(url, file)])
+ + + +
+[docs] +def decode_date(t): + """The date format is specified as 'seconds since 1970-01-01 00:00:00' but + the missing values are stored as -1e+34 which is not supported by the + default parsing mechanism in xarray. + + This function returns replaced the missing value by NaN and returns a + datetime instance. + + Parameters + ---------- + t : array + Array of time values + + Returns + ------- + out : datetime + Datetime instance with the missing value replaced by NaN + """ + nat_index = np.logical_or(np.isclose(t, -1e34), np.isnan(t)) + t[nat_index] = np.nan + return t
+ + + +
+[docs] +def fill_values(var, default=np.nan): + """Change fill values (-1e+34, inf, -inf) in var array to the value + specified by default. + + Parameters + ---------- + var : array + Array to fill + default : float + Default value to use for fill values + """ + missing_value = np.logical_or(np.isclose(var, -1e34), ~np.isfinite(var)) + if np.any(missing_value): + var[missing_value] = default + return var
+ + + +
+[docs] +def str_to_float(value: str, default: float = np.nan) -> float: + """Convert a string to float, while returning the value of default if the + string is not convertible to a float, or if it's a NaN. + + Parameters + ---------- + value : str + String to convert to float + default : float + Default value to return if the string is not convertible to float + + Returns + ------- + out : float + Float value of the string, or default if the string is not convertible to float. + """ + try: + fvalue = float(value) + if np.isnan(fvalue): + return default + else: + return fvalue + except ValueError: + return default
+ + + +
+[docs] +def cut_str(value: str, max_length: int) -> np.chararray: + """Cut a string to a specific length and return it as a numpy chararray. + + Parameters + ---------- + value : str + String to cut + max_length : int + Length of the output + + Returns + ------- + out : np.chararray + String with max_length characters + """ + charar = np.chararray(1, max_length) + charar[:max_length] = value + return charar
+ + + +
+[docs] +def drogue_presence(lost_time, time) -> bool: + """Create drogue status from the drogue lost time and the trajectory time. + + Parameters + ---------- + lost_time + Timestamp of the drogue loss (or NaT) + time + Observation time + + Returns + ------- + out : bool + True if drogues and False otherwise + """ + if pd.isnull(lost_time) or lost_time >= time[-1]: + return np.ones_like(time, dtype="bool") + else: + return time < lost_time
+ + + +
+[docs] +def rowsize(index: int, **kwargs) -> int: + try: + return xr.open_dataset( + os.path.join( + kwargs["tmp_path"], kwargs["filename_pattern"].format(id=index) + ), + decode_cf=False, + decode_times=False, + concat_characters=False, + decode_coords=False, + ).sizes["obs"] + except Exception as e: + print( + f"Error processing {os.path.join(kwargs['tmp_path'], kwargs['filename_pattern'].format(id=index))}" + ) + print(str(e)) + return 0
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/adapters/gdp1h.html b/_modules/clouddrift/adapters/gdp1h.html new file mode 100644 index 00000000..7109144b --- /dev/null +++ b/_modules/clouddrift/adapters/gdp1h.html @@ -0,0 +1,1091 @@ + + + + + + + + + + clouddrift.adapters.gdp1h — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.adapters.gdp1h

+"""
+This module provides functions and metadata that can be used to convert the
+hourly Global Drifter Program (GDP) data to a ``clouddrift.RaggedArray``
+instance.
+"""
+
+import clouddrift.adapters.gdp as gdp
+from clouddrift.raggedarray import RaggedArray
+from clouddrift.adapters.utils import download_with_progress
+from datetime import datetime, timedelta
+import numpy as np
+import urllib.request
+import re
+import tempfile
+from typing import Optional
+import os
+import warnings
+import xarray as xr
+
+GDP_VERSION = "2.01"
+
+GDP_DATA_URL = "https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/hourly_product/v2.01/"
+GDP_DATA_URL_EXPERIMENTAL = (
+    "https://www.aoml.noaa.gov/ftp/pub/phod/lumpkin/hourly/experimental/"
+)
+GDP_TMP_PATH = os.path.join(tempfile.gettempdir(), "clouddrift", "gdp")
+GDP_TMP_PATH_EXPERIMENTAL = os.path.join(tempfile.gettempdir(), "clouddrift", "gdp_exp")
+GDP_DATA = [
+    "lon",
+    "lat",
+    "ve",
+    "vn",
+    "err_lat",
+    "err_lon",
+    "err_ve",
+    "err_vn",
+    "gap",
+    "sst",
+    "sst1",
+    "sst2",
+    "err_sst",
+    "err_sst1",
+    "err_sst2",
+    "flg_sst",
+    "flg_sst1",
+    "flg_sst2",
+    "drogue_status",
+]
+
+
+
+[docs] +def download( + drifter_ids: list = None, + n_random_id: int = None, + url: str = GDP_DATA_URL, + tmp_path: str = None, +): + """Download individual NetCDF files from the AOML server. + + Parameters + ---------- + drifter_ids : list + List of drifter to retrieve (Default: all) + n_random_id : int + Randomly select n_random_id drifter IDs to download (Default: None) + url : str + URL from which to download the data (Default: GDP_DATA_URL). Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL. + tmp_path : str, optional + Path to the directory where the individual NetCDF files are stored + (default varies depending on operating system; /tmp/clouddrift/gdp on Linux) + + Returns + ------- + out : list + List of retrieved drifters + """ + + # adjust the tmp_path if using the experimental source + if tmp_path is None: + tmp_path = GDP_TMP_PATH if url == GDP_DATA_URL else GDP_TMP_PATH_EXPERIMENTAL + + print(f"Downloading GDP hourly data from {url} to {tmp_path}...") + + # Create a temporary directory if doesn't already exists. + os.makedirs(tmp_path, exist_ok=True) + + if url == GDP_DATA_URL: + pattern = "drifter_hourly_[0-9]*.nc" + filename_pattern = "drifter_hourly_{id}.nc" + elif url == GDP_DATA_URL_EXPERIMENTAL: + pattern = "drifter_hourly_[0-9]*.nc" + filename_pattern = "drifter_hourly_{id}.nc" + + # retrieve all drifter ID numbers + if drifter_ids is None: + urlpath = urllib.request.urlopen(url) + string = urlpath.read().decode("utf-8") + filelist = re.compile(pattern).findall(string) + drifter_ids = np.unique([int(f.split("_")[-1][:-3]) for f in filelist]) + + # retrieve only a subset of n_random_id trajectories + if n_random_id: + if n_random_id > len(drifter_ids): + warnings.warn( + f"Retrieving all listed trajectories because {n_random_id} is larger than the {len(drifter_ids)} listed trajectories." + ) + else: + rng = np.random.RandomState(42) + drifter_ids = sorted(rng.choice(drifter_ids, n_random_id, replace=False)) + + download_requests = [ + (os.path.join(url, file_name), os.path.join(tmp_path, file_name)) + for file_name in map(lambda d_id: filename_pattern.format(id=d_id), drifter_ids) + ] + download_with_progress(download_requests) + # Download the metadata so we can order the drifter IDs by end date. + gdp_metadata = gdp.get_gdp_metadata() + + return gdp.order_by_date(gdp_metadata, drifter_ids)
+ + + +
+[docs] +def preprocess(index: int, **kwargs) -> xr.Dataset: + """Extract and preprocess the Lagrangian data and attributes. + + This function takes an identification number that can be used to create a + file or url pattern or select data from a Dataframe. It then preprocesses + the data and returns a clean Xarray Dataset. + + Parameters + ---------- + index : int + Drifter's identification number + + Returns + ------- + ds : xr.Dataset + Xarray Dataset containing the data and attributes + """ + ds = xr.load_dataset( + os.path.join(kwargs["tmp_path"], kwargs["filename_pattern"].format(id=index)), + decode_times=False, + decode_coords=False, + ) + + # parse the date with custom function + ds["deploy_date"].data = gdp.decode_date(np.array([ds.deploy_date.data[0]])) + ds["end_date"].data = gdp.decode_date(np.array([ds.end_date.data[0]])) + ds["drogue_lost_date"].data = gdp.decode_date( + np.array([ds.drogue_lost_date.data[0]]) + ) + ds["time"].data = gdp.decode_date(np.array([ds.time.data[0]])) + + # convert fill values to nan + for var in [ + "err_lon", + "err_lat", + "err_ve", + "err_vn", + "sst", + "sst1", + "sst2", + "err_sst", + "err_sst1", + "err_sst2", + ]: + try: + ds[var].data = gdp.fill_values(ds[var].data) + except KeyError: + warnings.warn(f"Variable {var} not found; skipping.") + + # fix missing values stored as str + for var in [ + "longitude", + "latitude", + "err_lat", + "err_lon", + "ve", + "vn", + "err_ve", + "err_vn", + "sst", + "sst1", + "sst2", + ]: + try: + ds[var].encoding["missing value"] = -1e-34 + except KeyError: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + + # convert type of some variable + target_dtype = { + "ID": "int64", + "WMO": "int32", + "expno": "int32", + "typedeath": "int8", + "flg_sst": "int8", + "flg_sst1": "int8", + "flg_sst2": "int8", + } + + for var in target_dtype.keys(): + if var in ds.keys(): + ds[var].data = ds[var].data.astype(target_dtype[var]) + else: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + + # new variables + ds["ids"] = (["traj", "obs"], [np.repeat(ds.ID.values, ds.sizes["obs"])]) + ds["drogue_status"] = ( + ["traj", "obs"], + [gdp.drogue_presence(ds.drogue_lost_date.data, ds.time.data[0])], + ) + + # convert attributes to variable + ds["location_type"] = ( + ("traj"), + [False if ds.get("location_type") == "Argos" else True], + ) # 0 for Argos, 1 for GPS + ds["DeployingShip"] = (("traj"), gdp.cut_str(ds.DeployingShip, 20)) + ds["DeploymentStatus"] = (("traj"), gdp.cut_str(ds.DeploymentStatus, 20)) + ds["BuoyTypeManufacturer"] = (("traj"), gdp.cut_str(ds.BuoyTypeManufacturer, 20)) + ds["BuoyTypeSensorArray"] = (("traj"), gdp.cut_str(ds.BuoyTypeSensorArray, 20)) + ds["CurrentProgram"] = ( + ("traj"), + np.int32([gdp.str_to_float(ds.CurrentProgram, -1)]), + ) + ds["PurchaserFunding"] = (("traj"), gdp.cut_str(ds.PurchaserFunding, 20)) + ds["SensorUpgrade"] = (("traj"), gdp.cut_str(ds.SensorUpgrade, 20)) + ds["Transmissions"] = (("traj"), gdp.cut_str(ds.Transmissions, 20)) + ds["DeployingCountry"] = (("traj"), gdp.cut_str(ds.DeployingCountry, 20)) + ds["DeploymentComments"] = ( + ("traj"), + gdp.cut_str( + ds.DeploymentComments.encode("ascii", "ignore").decode("ascii"), 20 + ), + ) # remove non ascii char + ds["ManufactureYear"] = ( + ("traj"), + np.int16([gdp.str_to_float(ds.ManufactureYear, -1)]), + ) + ds["ManufactureMonth"] = ( + ("traj"), + np.int16([gdp.str_to_float(ds.ManufactureMonth, -1)]), + ) + ds["ManufactureSensorType"] = (("traj"), gdp.cut_str(ds.ManufactureSensorType, 20)) + ds["ManufactureVoltage"] = ( + ("traj"), + np.int16([gdp.str_to_float(ds.ManufactureVoltage[:-6], -1)]), + ) # e.g. 56 V + ds["FloatDiameter"] = ( + ("traj"), + [gdp.str_to_float(ds.FloatDiameter[:-3])], + ) # e.g. 35.5 cm + ds["SubsfcFloatPresence"] = ( + ("traj"), + np.array([gdp.str_to_float(ds.SubsfcFloatPresence)], dtype="bool"), + ) + ds["DrogueType"] = (("traj"), gdp.cut_str(ds.DrogueType, 7)) + ds["DrogueLength"] = ( + ("traj"), + [gdp.str_to_float(ds.DrogueLength[:-2])], + ) # e.g. 4.8 m + ds["DrogueBallast"] = ( + ("traj"), + [gdp.str_to_float(ds.DrogueBallast[:-3])], + ) # e.g. 1.4 kg + ds["DragAreaAboveDrogue"] = ( + ("traj"), + [gdp.str_to_float(ds.DragAreaAboveDrogue[:-4])], + ) # 10.66 m^2 + ds["DragAreaOfDrogue"] = ( + ("traj"), + [gdp.str_to_float(ds.DragAreaOfDrogue[:-4])], + ) # e.g. 416.6 m^2 + ds["DragAreaRatio"] = (("traj"), [gdp.str_to_float(ds.DragAreaRatio)]) # e.g. 39.08 + ds["DrogueCenterDepth"] = ( + ("traj"), + [gdp.str_to_float(ds.DrogueCenterDepth[:-2])], + ) # e.g. 20.0 m + ds["DrogueDetectSensor"] = (("traj"), gdp.cut_str(ds.DrogueDetectSensor, 20)) + + # vars attributes + vars_attrs = { + "ID": {"long_name": "Global Drifter Program Buoy ID", "units": "-"}, + "longitude": {"long_name": "Longitude", "units": "degrees_east"}, + "latitude": {"long_name": "Latitude", "units": "degrees_north"}, + "time": {"long_name": "Time", "units": "seconds since 1970-01-01 00:00:00"}, + "ids": { + "long_name": "Global Drifter Program Buoy ID repeated along observations", + "units": "-", + }, + "rowsize": { + "long_name": "Number of observations per trajectory", + "sample_dimension": "obs", + "units": "-", + }, + "location_type": { + "long_name": "Satellite-based location system", + "units": "-", + "comments": "0 (Argos), 1 (GPS)", + }, + "WMO": { + "long_name": "World Meteorological Organization buoy identification number", + "units": "-", + }, + "expno": {"long_name": "Experiment number", "units": "-"}, + "deploy_date": { + "long_name": "Deployment date and time", + "units": "seconds since 1970-01-01 00:00:00", + }, + "deploy_lon": {"long_name": "Deployment longitude", "units": "degrees_east"}, + "deploy_lat": {"long_name": "Deployment latitude", "units": "degrees_north"}, + "start_date": { + "long_name": "First good date and time derived by DAC quality control", + "units": "seconds since 1970-01-01 00:00:00", + }, + "start_lon": { + "long_name": "First good longitude derived by DAC quality control", + "units": "degrees_east", + }, + "start_lat": { + "long_name": "Last good latitude derived by DAC quality control", + "units": "degrees_north", + }, + "end_date": { + "long_name": "Last good date and time derived by DAC quality control", + "units": "seconds since 1970-01-01 00:00:00", + }, + "end_lon": { + "long_name": "Last good longitude derived by DAC quality control", + "units": "degrees_east", + }, + "end_lat": { + "long_name": "Last good latitude derived by DAC quality control", + "units": "degrees_north", + }, + "drogue_lost_date": { + "long_name": "Date and time of drogue loss", + "units": "seconds since 1970-01-01 00:00:00", + }, + "typedeath": { + "long_name": "Type of death", + "units": "-", + "comments": "0 (buoy still alive), 1 (buoy ran aground), 2 (picked up by vessel), 3 (stop transmitting), 4 (sporadic transmissions), 5 (bad batteries), 6 (inactive status)", + }, + "typebuoy": { + "long_name": "Buoy type (see https://www.aoml.noaa.gov/phod/dac/dirall.html)", + "units": "-", + }, + "DeployingShip": {"long_name": "Name of deployment ship", "units": "-"}, + "DeploymentStatus": {"long_name": "Deployment status", "units": "-"}, + "BuoyTypeManufacturer": {"long_name": "Buoy type manufacturer", "units": "-"}, + "BuoyTypeSensorArray": {"long_name": "Buoy type sensor array", "units": "-"}, + "CurrentProgram": { + "long_name": "Current Program", + "units": "-", + "_FillValue": "-1", + }, + "PurchaserFunding": {"long_name": "Purchaser funding", "units": "-"}, + "SensorUpgrade": {"long_name": "Sensor upgrade", "units": "-"}, + "Transmissions": {"long_name": "Transmissions", "units": "-"}, + "DeployingCountry": {"long_name": "Deploying country", "units": "-"}, + "DeploymentComments": {"long_name": "Deployment comments", "units": "-"}, + "ManufactureYear": { + "long_name": "Manufacture year", + "units": "-", + "_FillValue": "-1", + }, + "ManufactureMonth": { + "long_name": "Manufacture month", + "units": "-", + "_FillValue": "-1", + }, + "ManufactureSensorType": {"long_name": "Manufacture Sensor Type", "units": "-"}, + "ManufactureVoltage": { + "long_name": "Manufacture voltage", + "units": "V", + "_FillValue": "-1", + }, + "FloatDiameter": {"long_name": "Diameter of surface floater", "units": "cm"}, + "SubsfcFloatPresence": {"long_name": "Subsurface Float Presence", "units": "-"}, + "DrogueType": {"drogue_type": "Drogue Type", "units": "-"}, + "DrogueLength": {"long_name": "Length of drogue.", "units": "m"}, + "DrogueBallast": { + "long_name": "Weight of the drogue's ballast.", + "units": "kg", + }, + "DragAreaAboveDrogue": {"long_name": "Drag area above drogue.", "units": "m^2"}, + "DragAreaOfDrogue": {"long_name": "Drag area drogue.", "units": "m^2"}, + "DragAreaRatio": {"long_name": "Drag area ratio", "units": "m"}, + "DrogueCenterDepth": { + "long_name": "Average depth of the drogue.", + "units": "m", + }, + "DrogueDetectSensor": {"long_name": "Drogue detection sensor", "units": "-"}, + "ve": {"long_name": "Eastward velocity", "units": "m/s"}, + "vn": {"long_name": "Northward velocity", "units": "m/s"}, + "gap": { + "long_name": "Time interval between previous and next location", + "units": "s", + }, + "err_lat": { + "long_name": "95% confidence interval in latitude", + "units": "degrees_north", + }, + "err_lon": { + "long_name": "95% confidence interval in longitude", + "units": "degrees_east", + }, + "err_ve": { + "long_name": "95% confidence interval in eastward velocity", + "units": "m/s", + }, + "err_vn": { + "long_name": "95% confidence interval in northward velocity", + "units": "m/s", + }, + "drogue_status": { + "long_name": "Status indicating the presence of the drogue", + "units": "-", + "flag_values": "1,0", + "flag_meanings": "drogued, undrogued", + }, + "sst": { + "long_name": "Fitted sea water temperature", + "units": "Kelvin", + "comments": "Estimated near-surface sea water temperature from drifting buoy measurements. It is the sum of the fitted near-surface non-diurnal sea water temperature and fitted diurnal sea water temperature anomaly. Discrepancies may occur because of rounding.", + }, + "sst1": { + "long_name": "Fitted non-diurnal sea water temperature", + "units": "Kelvin", + "comments": "Estimated near-surface non-diurnal sea water temperature from drifting buoy measurements", + }, + "sst2": { + "long_name": "Fitted diurnal sea water temperature anomaly", + "units": "Kelvin", + "comments": "Estimated near-surface diurnal sea water temperature anomaly from drifting buoy measurements", + }, + "err_sst": { + "long_name": "Standard uncertainty of fitted sea water temperature", + "units": "Kelvin", + "comments": "Estimated one standard error of near-surface sea water temperature estimate from drifting buoy measurements", + }, + "err_sst1": { + "long_name": "Standard uncertainty of fitted non-diurnal sea water temperature", + "units": "Kelvin", + "comments": "Estimated one standard error of near-surface non-diurnal sea water temperature estimate from drifting buoy measurements", + }, + "err_sst2": { + "long_name": "Standard uncertainty of fitted diurnal sea water temperature anomaly", + "units": "Kelvin", + "comments": "Estimated one standard error of near-surface diurnal sea water temperature anomaly estimate from drifting buoy measurements", + }, + "flg_sst": { + "long_name": "Fitted sea water temperature quality flag", + "units": "-", + "flag_values": "0, 1, 2, 3, 4, 5", + "flag_meanings": "no-estimate, no-uncertainty-estimate, estimate-not-in-range-uncertainty-not-in-range, estimate-not-in-range-uncertainty-in-range estimate-in-range-uncertainty-not-in-range, estimate-in-range-uncertainty-in-range", + }, + "flg_sst1": { + "long_name": "Fitted non-diurnal sea water temperature quality flag", + "units": "-", + "flag_values": "0, 1, 2, 3, 4, 5", + "flag_meanings": "no-estimate, no-uncertainty-estimate, estimate-not-in-range-uncertainty-not-in-range, estimate-not-in-range-uncertainty-in-range estimate-in-range-uncertainty-not-in-range, estimate-in-range-uncertainty-in-range", + }, + "flg_sst2": { + "long_name": "Fitted diurnal sea water temperature anomaly quality flag", + "units": "-", + "flag_values": "0, 1, 2, 3, 4, 5", + "flag_meanings": "no-estimate, no-uncertainty-estimate, estimate-not-in-range-uncertainty-not-in-range, estimate-not-in-range-uncertainty-in-range estimate-in-range-uncertainty-not-in-range, estimate-in-range-uncertainty-in-range", + }, + } + + # global attributes + attrs = { + "title": "Global Drifter Program hourly drifting buoy collection", + "history": f"version {GDP_VERSION}. Metadata from dirall.dat and deplog.dat", + "Conventions": "CF-1.6", + "time_coverage_start": "", + "time_coverage_end": "", + "date_created": datetime.now().isoformat(), + "publisher_name": "GDP Drifter DAC", + "publisher_email": "aoml.dftr@noaa.gov", + "publisher_url": "https://www.aoml.noaa.gov/phod/gdp", + "license": "freely available", + "processing_level": "Level 2 QC by GDP drifter DAC", + "metadata_link": "https://www.aoml.noaa.gov/phod/dac/dirall.html", + "contributor_name": "NOAA Global Drifter Program", + "contributor_role": "Data Acquisition Center", + "institution": "NOAA Atlantic Oceanographic and Meteorological Laboratory", + "acknowledgement": "Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurioni, Luca; Pazos, Mayra (2022). Hourly location, current velocity, and temperature collected from Global Drifter Program drifters world-wide. [indicate subset used]. NOAA National Centers for Environmental Information. Dataset. https://doi.org/10.25921/x46c-3620. Accessed [date]. Elipot et al. (2022): A Dataset of Hourly Sea Surface Temperature From Drifting Buoys, Scientific Data, 9, 567, https://dx.doi.org/10.1038/s41597-022-01670-2. Elipot et al. (2016): A global surface drifter dataset at hourly resolution, J. Geophys. Res.-Oceans, 121, https://dx.doi.org/10.1002/2016JC011716.", + "summary": "Global Drifter Program hourly data", + "doi": "10.25921/x46c-3620", + } + + # set attributes + for var in vars_attrs.keys(): + if var in ds.keys(): + ds[var].attrs = vars_attrs[var] + else: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + ds.attrs = attrs + + # rename variables + ds = ds.rename_vars({"longitude": "lon", "latitude": "lat"}) + + # Cast float64 variables to float32 to reduce memory footprint. + ds = gdp.cast_float64_variables_to_float32(ds) + + return ds
+ + + +
+[docs] +def to_raggedarray( + drifter_ids: Optional[list[int]] = None, + n_random_id: Optional[int] = None, + url: Optional[str] = GDP_DATA_URL, + tmp_path: Optional[str] = None, +) -> RaggedArray: + """Download and process individual GDP hourly files and return a RaggedArray + instance with the data. + + Parameters + ---------- + drifter_ids : list[int], optional + List of drifters to retrieve (Default: all) + n_random_id : list[int], optional + Randomly select n_random_id drifter NetCDF files + url : str, optional + URL from which to download the data (Default: GDP_DATA_URL). + Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL. + tmp_path : str, optional + Path to the directory where the individual NetCDF files are stored + (default varies depending on operating system; /tmp/clouddrift/gdp on Linux) + + Returns + ------- + out : RaggedArray + A RaggedArray instance of the requested dataset + + Examples + -------- + + Invoke `to_raggedarray` without any arguments to download all drifter data + from the 2.01 GDP feed: + + >>> from clouddrift.adapters.gdp1h import to_raggedarray + >>> ra = to_raggedarray() + + To download a random sample of 100 drifters, for example for development + or testing, use the `n_random_id` argument: + + >>> ra = to_raggedarray(n_random_id=100) + + To download a specific list of drifters, use the `drifter_ids` argument: + + >>> ra = to_raggedarray(drifter_ids=[44136, 54680, 83463]) + + To download the experimental 2.01 GDP feed, use the `url` argument to + specify the experimental feed URL: + + >>> from clouddrift.adapters.gdp1h import GDP_DATA_URL_EXPERIMENTAL, to_raggedarray + >>> ra = to_raggedarray(url=GDP_DATA_URL_EXPERIMENTAL) + + Finally, `to_raggedarray` returns a `RaggedArray` instance which provides + a convenience method to emit a `xarray.Dataset` instance: + + >>> ds = ra.to_xarray() + + To write the ragged array dataset to a NetCDF file on disk, do + + >>> ds.to_netcdf("gdp1h.nc", format="NETCDF4") + + Alternatively, to write the ragged array to a Parquet file, first create + it as an Awkward Array: + + >>> arr = ra.to_awkward() + >>> arr.to_parquet("gdp1h.parquet") + """ + + # adjust the tmp_path if using the experimental source + if tmp_path is None: + tmp_path = GDP_TMP_PATH if url == GDP_DATA_URL else GDP_TMP_PATH_EXPERIMENTAL + + ids = download(drifter_ids, n_random_id, url, tmp_path) + + if url == GDP_DATA_URL: + filename_pattern = "drifter_hourly_{id}.nc" + elif url == GDP_DATA_URL_EXPERIMENTAL: + filename_pattern = "drifter_hourly_{id}.nc" + else: + raise ValueError(f"url must be {GDP_DATA_URL} or {GDP_DATA_URL_EXPERIMENTAL}.") + + ra = RaggedArray.from_files( + indices=ids, + preprocess_func=preprocess, + name_coords=gdp.GDP_COORDS, + name_meta=gdp.GDP_METADATA, + name_data=GDP_DATA, + rowsize_func=gdp.rowsize, + filename_pattern=filename_pattern, + tmp_path=tmp_path, + ) + + # set dynamic global attributes + ra.attrs_global[ + "time_coverage_start" + ] = f"{datetime(1970,1,1) + timedelta(seconds=int(np.min(ra.coords['time']))):%Y-%m-%d:%H:%M:%SZ}" + ra.attrs_global[ + "time_coverage_end" + ] = f"{datetime(1970,1,1) + timedelta(seconds=int(np.max(ra.coords['time']))):%Y-%m-%d:%H:%M:%SZ}" + + return ra
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/adapters/gdp6h.html b/_modules/clouddrift/adapters/gdp6h.html new file mode 100644 index 00000000..2b70dfc8 --- /dev/null +++ b/_modules/clouddrift/adapters/gdp6h.html @@ -0,0 +1,978 @@ + + + + + + + + + + clouddrift.adapters.gdp6h — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.adapters.gdp6h

+"""
+This module provides functions and metadata that can be used to convert the
+6-hourly Global Drifter Program (GDP) data to a ``clouddrift.RaggedArray``
+instance.
+"""
+
+import clouddrift.adapters.gdp as gdp
+from clouddrift.adapters.utils import download_with_progress
+from clouddrift.raggedarray import RaggedArray
+from datetime import datetime, timedelta
+import numpy as np
+import urllib.request
+import re
+import tempfile
+from typing import Optional
+import os
+import warnings
+import xarray as xr
+
+GDP_VERSION = "September 2023"
+
+GDP_DATA_URL = "https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/6h/"
+GDP_TMP_PATH = os.path.join(tempfile.gettempdir(), "clouddrift", "gdp6h")
+GDP_DATA = [
+    "lon",
+    "lat",
+    "ve",
+    "vn",
+    "temp",
+    "err_lat",
+    "err_lon",
+    "err_temp",
+    "drogue_status",
+]
+
+
+
+[docs] +def download( + drifter_ids: list = None, + n_random_id: int = None, + url: str = GDP_DATA_URL, + tmp_path: str = GDP_TMP_PATH, +): + """Download individual NetCDF files from the AOML server. + + Parameters + ---------- + drifter_ids : list + List of drifter to retrieve (Default: all) + n_random_id : int + Randomly select n_random_id drifter IDs to download (Default: None) + url : str + URL from which to download the data (Default: GDP_DATA_URL). Alternatively, it can be GDP_DATA_URL_EXPERIMENTAL. + tmp_path : str, optional + Path to the directory where the individual NetCDF files are stored + (default varies depending on operating system; /tmp/clouddrift/gdp6h on Linux) + + Returns + ------- + out : list + List of retrieved drifters + """ + + print(f"Downloading GDP 6-hourly data to {tmp_path}...") + + # Create a temporary directory if doesn't already exists. + os.makedirs(tmp_path, exist_ok=True) + + pattern = "drifter_6h_[0-9]*.nc" + directory_list = [ + "netcdf_1_5000", + "netcdf_5001_10000", + "netcdf_10001_15000", + "netcdf_15001_current", + ] + + # retrieve all drifter ID numbers + if drifter_ids is None: + urlpath = urllib.request.urlopen(url) + string = urlpath.read().decode("utf-8") + drifter_urls = [] + for dir in directory_list: + urlpath = urllib.request.urlopen(os.path.join(url, dir)) + string = urlpath.read().decode("utf-8") + filelist = list(set(re.compile(pattern).findall(string))) + drifter_urls += [os.path.join(url, dir, f) for f in filelist] + + # retrieve only a subset of n_random_id trajectories + if n_random_id: + if n_random_id > len(drifter_urls): + warnings.warn( + f"Retrieving all listed trajectories because {n_random_id} is larger than the {len(drifter_ids)} listed trajectories." + ) + else: + rng = np.random.RandomState(42) + drifter_urls = rng.choice(drifter_urls, n_random_id, replace=False) + + download_with_progress( + [(url, os.path.join(tmp_path, os.path.basename(url))) for url in drifter_urls] + ) + + # Download the metadata so we can order the drifter IDs by end date. + gdp_metadata = gdp.get_gdp_metadata() + drifter_ids = [ + int(os.path.basename(f).split("_")[2].split(".")[0]) for f in drifter_urls + ] + + return gdp.order_by_date(gdp_metadata, drifter_ids)
+ + + +
+[docs] +def preprocess(index: int, **kwargs) -> xr.Dataset: + """Extract and preprocess the Lagrangian data and attributes. + + This function takes an identification number that can be used to create a + file or url pattern or select data from a Dataframe. It then preprocesses + the data and returns a clean Xarray Dataset. + + Parameters + ---------- + index : int + Drifter's identification number + + Returns + ------- + ds : xr.Dataset + Xarray Dataset containing the data and attributes + """ + ds = xr.load_dataset( + os.path.join(kwargs["tmp_path"], kwargs["filename_pattern"].format(id=index)), + decode_times=False, + decode_coords=False, + ) + + # parse the date with custom function + ds["deploy_date"].data = gdp.decode_date(np.array([ds.deploy_date.data[0]])) + ds["end_date"].data = gdp.decode_date(np.array([ds.end_date.data[0]])) + ds["drogue_lost_date"].data = gdp.decode_date( + np.array([ds.drogue_lost_date.data[0]]) + ) + ds["time"].data = gdp.decode_date(np.array([ds.time.data[0]])) + + # convert fill values to nan + for var in [ + "err_lon", + "err_lat", + "temp", + "err_temp", + ]: + try: + ds[var].data = gdp.fill_values(ds[var].data) + except KeyError: + warnings.warn(f"Variable {var} not found; skipping.") + + # fix missing values stored as str + for var in [ + "longitude", + "latitude", + "err_lat", + "err_lon", + "ve", + "vn", + "temp", + "err_temp", + ]: + try: + ds[var].encoding["missing value"] = -1e-34 + except KeyError: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + + # convert type of some variable + target_dtype = { + "ID": "int64", + "WMO": "int32", + "expno": "int32", + "typedeath": "int8", + } + + for var in target_dtype.keys(): + if var in ds.keys(): + ds[var].data = ds[var].data.astype(target_dtype[var]) + else: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + + # new variables + ds["ids"] = (["traj", "obs"], [np.repeat(ds.ID.values, ds.sizes["obs"])]) + ds["drogue_status"] = ( + ["traj", "obs"], + [gdp.drogue_presence(ds.drogue_lost_date.data, ds.time.data[0])], + ) + + # convert attributes to variable + ds["location_type"] = ( + ("traj"), + [False if ds.get("location_type") == "Argos" else True], + ) # 0 for Argos, 1 for GPS + ds["DeployingShip"] = (("traj"), gdp.cut_str(ds.DeployingShip, 20)) + ds["DeploymentStatus"] = (("traj"), gdp.cut_str(ds.DeploymentStatus, 20)) + ds["BuoyTypeManufacturer"] = (("traj"), gdp.cut_str(ds.BuoyTypeManufacturer, 20)) + ds["BuoyTypeSensorArray"] = (("traj"), gdp.cut_str(ds.BuoyTypeSensorArray, 20)) + ds["CurrentProgram"] = ( + ("traj"), + np.int32([gdp.str_to_float(ds.CurrentProgram, -1)]), + ) + ds["PurchaserFunding"] = (("traj"), gdp.cut_str(ds.PurchaserFunding, 20)) + ds["SensorUpgrade"] = (("traj"), gdp.cut_str(ds.SensorUpgrade, 20)) + ds["Transmissions"] = (("traj"), gdp.cut_str(ds.Transmissions, 20)) + ds["DeployingCountry"] = (("traj"), gdp.cut_str(ds.DeployingCountry, 20)) + ds["DeploymentComments"] = ( + ("traj"), + gdp.cut_str( + ds.DeploymentComments.encode("ascii", "ignore").decode("ascii"), 20 + ), + ) # remove non ascii char + ds["ManufactureYear"] = ( + ("traj"), + np.int16([gdp.str_to_float(ds.ManufactureYear, -1)]), + ) + ds["ManufactureMonth"] = ( + ("traj"), + np.int16([gdp.str_to_float(ds.ManufactureMonth, -1)]), + ) + ds["ManufactureSensorType"] = (("traj"), gdp.cut_str(ds.ManufactureSensorType, 20)) + ds["ManufactureVoltage"] = ( + ("traj"), + np.int16([gdp.str_to_float(ds.ManufactureVoltage[:-6], -1)]), + ) # e.g. 56 V + ds["FloatDiameter"] = ( + ("traj"), + [gdp.str_to_float(ds.FloatDiameter[:-3])], + ) # e.g. 35.5 cm + ds["SubsfcFloatPresence"] = ( + ("traj"), + np.array([gdp.str_to_float(ds.SubsfcFloatPresence)], dtype="bool"), + ) + ds["DrogueType"] = (("traj"), gdp.cut_str(ds.DrogueType, 7)) + ds["DrogueLength"] = ( + ("traj"), + [gdp.str_to_float(ds.DrogueLength[:-2])], + ) # e.g. 4.8 m + ds["DrogueBallast"] = ( + ("traj"), + [gdp.str_to_float(ds.DrogueBallast[:-3])], + ) # e.g. 1.4 kg + ds["DragAreaAboveDrogue"] = ( + ("traj"), + [gdp.str_to_float(ds.DragAreaAboveDrogue[:-4])], + ) # 10.66 m^2 + ds["DragAreaOfDrogue"] = ( + ("traj"), + [gdp.str_to_float(ds.DragAreaOfDrogue[:-4])], + ) # e.g. 416.6 m^2 + ds["DragAreaRatio"] = (("traj"), [gdp.str_to_float(ds.DragAreaRatio)]) # e.g. 39.08 + ds["DrogueCenterDepth"] = ( + ("traj"), + [gdp.str_to_float(ds.DrogueCenterDepth[:-2])], + ) # e.g. 20.0 m + ds["DrogueDetectSensor"] = (("traj"), gdp.cut_str(ds.DrogueDetectSensor, 20)) + + # vars attributes + vars_attrs = { + "ID": {"long_name": "Global Drifter Program Buoy ID", "units": "-"}, + "longitude": {"long_name": "Longitude", "units": "degrees_east"}, + "latitude": {"long_name": "Latitude", "units": "degrees_north"}, + "time": {"long_name": "Time", "units": "seconds since 1970-01-01 00:00:00"}, + "ids": { + "long_name": "Global Drifter Program Buoy ID repeated along observations", + "units": "-", + }, + "rowsize": { + "long_name": "Number of observations per trajectory", + "sample_dimension": "obs", + "units": "-", + }, + "location_type": { + "long_name": "Satellite-based location system", + "units": "-", + "comments": "0 (Argos), 1 (GPS)", + }, + "WMO": { + "long_name": "World Meteorological Organization buoy identification number", + "units": "-", + }, + "expno": {"long_name": "Experiment number", "units": "-"}, + "deploy_date": { + "long_name": "Deployment date and time", + "units": "seconds since 1970-01-01 00:00:00", + }, + "deploy_lon": {"long_name": "Deployment longitude", "units": "degrees_east"}, + "deploy_lat": {"long_name": "Deployment latitude", "units": "degrees_north"}, + "end_date": { + "long_name": "End date and time", + "units": "seconds since 1970-01-01 00:00:00", + }, + "end_lon": {"long_name": "End latitude", "units": "degrees_north"}, + "end_lat": {"long_name": "End longitude", "units": "degrees_east"}, + "drogue_lost_date": { + "long_name": "Date and time of drogue loss", + "units": "seconds since 1970-01-01 00:00:00", + }, + "typedeath": { + "long_name": "Type of death", + "units": "-", + "comments": "0 (buoy still alive), 1 (buoy ran aground), 2 (picked up by vessel), 3 (stop transmitting), 4 (sporadic transmissions), 5 (bad batteries), 6 (inactive status)", + }, + "typebuoy": { + "long_name": "Buoy type (see https://www.aoml.noaa.gov/phod/dac/dirall.html)", + "units": "-", + }, + "DeployingShip": {"long_name": "Name of deployment ship", "units": "-"}, + "DeploymentStatus": {"long_name": "Deployment status", "units": "-"}, + "BuoyTypeManufacturer": {"long_name": "Buoy type manufacturer", "units": "-"}, + "BuoyTypeSensorArray": {"long_name": "Buoy type sensor array", "units": "-"}, + "CurrentProgram": { + "long_name": "Current Program", + "units": "-", + "_FillValue": "-1", + }, + "PurchaserFunding": {"long_name": "Purchaser funding", "units": "-"}, + "SensorUpgrade": {"long_name": "Sensor upgrade", "units": "-"}, + "Transmissions": {"long_name": "Transmissions", "units": "-"}, + "DeployingCountry": {"long_name": "Deploying country", "units": "-"}, + "DeploymentComments": {"long_name": "Deployment comments", "units": "-"}, + "ManufactureYear": { + "long_name": "Manufacture year", + "units": "-", + "_FillValue": "-1", + }, + "ManufactureMonth": { + "long_name": "Manufacture month", + "units": "-", + "_FillValue": "-1", + }, + "ManufactureSensorType": {"long_name": "Manufacture Sensor Type", "units": "-"}, + "ManufactureVoltage": { + "long_name": "Manufacture voltage", + "units": "V", + "_FillValue": "-1", + }, + "FloatDiameter": {"long_name": "Diameter of surface floater", "units": "cm"}, + "SubsfcFloatPresence": {"long_name": "Subsurface Float Presence", "units": "-"}, + "DrogueType": {"drogue_type": "Drogue Type", "units": "-"}, + "DrogueLength": {"long_name": "Length of drogue.", "units": "m"}, + "DrogueBallast": { + "long_name": "Weight of the drogue's ballast.", + "units": "kg", + }, + "DragAreaAboveDrogue": {"long_name": "Drag area above drogue.", "units": "m^2"}, + "DragAreaOfDrogue": {"long_name": "Drag area drogue.", "units": "m^2"}, + "DragAreaRatio": {"long_name": "Drag area ratio", "units": "m"}, + "DrogueCenterDepth": { + "long_name": "Average depth of the drogue.", + "units": "m", + }, + "DrogueDetectSensor": {"long_name": "Drogue detection sensor", "units": "-"}, + "ve": {"long_name": "Eastward velocity", "units": "m/s"}, + "vn": {"long_name": "Northward velocity", "units": "m/s"}, + "err_lat": { + "long_name": "95% confidence interval in latitude", + "units": "degrees_north", + }, + "err_lon": { + "long_name": "95% confidence interval in longitude", + "units": "degrees_east", + }, + "drogue_status": { + "long_name": "Status indicating the presence of the drogue", + "units": "-", + "flag_values": "1,0", + "flag_meanings": "drogued, undrogued", + }, + "temp": { + "long_name": "Fitted sea water temperature", + "units": "Kelvin", + "comments": "Estimated near-surface sea water temperature from drifting buoy measurements. It is the sum of the fitted near-surface non-diurnal sea water temperature and fitted diurnal sea water temperature anomaly. Discrepancies may occur because of rounding.", + }, + "err_temp": { + "long_name": "Standard uncertainty of fitted sea water temperature", + "units": "Kelvin", + "comments": "Estimated one standard error of near-surface sea water temperature estimate from drifting buoy measurements", + }, + } + + # global attributes + attrs = { + "title": "Global Drifter Program drifting buoy collection", + "history": f"version {GDP_VERSION}. Metadata from dirall.dat and deplog.dat", + "Conventions": "CF-1.6", + "time_coverage_start": "", + "time_coverage_end": "", + "date_created": datetime.now().isoformat(), + "publisher_name": "GDP Drifter DAC", + "publisher_email": "aoml.dftr@noaa.gov", + "publisher_url": "https://www.aoml.noaa.gov/phod/gdp", + "license": "freely available", + "processing_level": "Level 2 QC by GDP drifter DAC", + "metadata_link": "https://www.aoml.noaa.gov/phod/dac/dirall.html", + "contributor_name": "NOAA Global Drifter Program", + "contributor_role": "Data Acquisition Center", + "institution": "NOAA Atlantic Oceanographic and Meteorological Laboratory", + "acknowledgement": f"Lumpkin, Rick; Centurioni, Luca (2019). NOAA Global Drifter Program quality-controlled 6-hour interpolated data from ocean surface drifting buoys. [indicate subset used]. NOAA National Centers for Environmental Information. Dataset. https://doi.org/10.25921/7ntx-z961. Accessed {datetime.utcnow().strftime('%d %B %Y')}.", + "summary": "Global Drifter Program six-hourly data", + "doi": "10.25921/7ntx-z961", + } + + # set attributes + for var in vars_attrs.keys(): + if var in ds.keys(): + ds[var].attrs = vars_attrs[var] + else: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + ds.attrs = attrs + + # rename variables + ds = ds.rename_vars({"longitude": "lon", "latitude": "lat"}) + + # Cast float64 variables to float32 to reduce memory footprint. + ds = gdp.cast_float64_variables_to_float32(ds) + + return ds
+ + + +
+[docs] +def to_raggedarray( + drifter_ids: Optional[list[int]] = None, + n_random_id: Optional[int] = None, + tmp_path: Optional[str] = GDP_TMP_PATH, +) -> RaggedArray: + """Download and process individual GDP 6-hourly files and return a + RaggedArray instance with the data. + + Parameters + ---------- + drifter_ids : list[int], optional + List of drifters to retrieve (Default: all) + n_random_id : list[int], optional + Randomly select n_random_id drifter NetCDF files + tmp_path : str, optional + Path to the directory where the individual NetCDF files are stored + (default varies depending on operating system; /tmp/clouddrift/gdp6h on Linux) + + Returns + ------- + out : RaggedArray + A RaggedArray instance of the requested dataset + + Examples + -------- + + Invoke `to_raggedarray` without any arguments to download all drifter data + from the 6-hourly GDP feed: + + >>> from clouddrift.adapters.gdp6h import to_raggedarray + >>> ra = to_raggedarray() + + To download a random sample of 100 drifters, for example for development + or testing, use the `n_random_id` argument: + + >>> ra = to_raggedarray(n_random_id=100) + + To download a specific list of drifters, use the `drifter_ids` argument: + + >>> ra = to_raggedarray(drifter_ids=[54375, 114956, 126934]) + + Finally, `to_raggedarray` returns a `RaggedArray` instance which provides + a convenience method to emit a `xarray.Dataset` instance: + + >>> ds = ra.to_xarray() + + To write the ragged array dataset to a NetCDF file on disk, do + + >>> ds.to_netcdf("gdp6h.nc", format="NETCDF4") + + Alternatively, to write the ragged array to a Parquet file, first create + it as an Awkward Array: + + >>> arr = ra.to_awkward() + >>> arr.to_parquet("gdp6h.parquet") + """ + ids = download(drifter_ids, n_random_id, GDP_DATA_URL, tmp_path) + + ra = RaggedArray.from_files( + indices=ids, + preprocess_func=preprocess, + name_coords=gdp.GDP_COORDS, + name_meta=gdp.GDP_METADATA, + name_data=GDP_DATA, + rowsize_func=gdp.rowsize, + filename_pattern="drifter_6h_{id}.nc", + tmp_path=tmp_path, + ) + + # update dynamic global attributes + ra.attrs_global[ + "time_coverage_start" + ] = f"{datetime(1970,1,1) + timedelta(seconds=int(np.min(ra.coords['time']))):%Y-%m-%d:%H:%M:%SZ}" + ra.attrs_global[ + "time_coverage_end" + ] = f"{datetime(1970,1,1) + timedelta(seconds=int(np.max(ra.coords['time']))):%Y-%m-%d:%H:%M:%SZ}" + + return ra
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/adapters/glad.html b/_modules/clouddrift/adapters/glad.html new file mode 100644 index 00000000..432ee5df --- /dev/null +++ b/_modules/clouddrift/adapters/glad.html @@ -0,0 +1,591 @@ + + + + + + + + + + clouddrift.adapters.glad — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.adapters.glad

+"""
+This module defines functions used to adapt the Grand LAgrangian Deployment
+(GLAD) dataset as a ragged-array Xarray Dataset.
+
+The dataset and its description are hosted at https://doi.org/10.7266/N7VD6WC8.
+
+Example
+-------
+>>> from clouddrift.adapters import glad
+>>> ds = glad.to_xarray()
+
+Reference
+---------
+Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012. Distributed by: Gulf of Mexico Research Initiative Information and Data Cooperative (GRIIDC), Harte Research Institute, Texas A&M University–Corpus Christi. doi:10.7266/N7VD6WC8
+"""
+from clouddrift.adapters.utils import download_with_progress
+from io import BytesIO
+import numpy as np
+import pandas as pd
+import xarray as xr
+
+
+
+[docs] +def get_dataframe() -> pd.DataFrame: + """Get the GLAD dataset as a pandas DataFrame.""" + url = "https://data.gulfresearchinitiative.org/pelagos-symfony/api/file/download/169841" + # GRIIDC server doesn't provide Content-Length header, so we'll hardcode + # the expected data length here. + file_size = 155330876 + buf = BytesIO(b"") + download_with_progress([(url, buf)]) + buf.seek(0) + column_names = [ + "id", + "date", + "time", + "latitude", + "longitude", + "position_error", + "u", + "v", + "velocity_error", + ] + df = pd.read_csv(buf, delim_whitespace=True, skiprows=5, names=column_names) + df["obs"] = pd.to_datetime(df["date"] + " " + df["time"]) + df.drop(["date", "time"], axis=1, inplace=True) + return df
+ + + +
+[docs] +def to_xarray() -> xr.Dataset: + """Return the GLAD data as a ragged-array Xarray Dataset.""" + df = get_dataframe() + ds = df.to_xarray() + + traj, rowsize = np.unique(ds.id, return_counts=True) + + # Make the dataset compatible with clouddrift functions. + ds = ( + ds.swap_dims({"index": "obs"}) + .drop_vars(["id", "index"]) + .assign_coords(traj=traj) + .assign({"rowsize": ("traj", rowsize)}) + .rename_vars({"obs": "time", "traj": "id"}) + ) + + # Cast double floats to singles + for var in ds.variables: + if ds[var].dtype == "float64": + ds[var] = ds[var].astype("float32") + + # Set variable attributes + ds["longitude"].attrs = { + "long_name": "longitude", + "standard_name": "longitude", + "units": "degrees_east", + } + + ds["latitude"].attrs = { + "long_name": "latitude", + "standard_name": "latitude", + "units": "degrees_north", + } + + ds["position_error"].attrs = { + "long_name": "position_error", + "units": "m", + } + + ds["u"].attrs = { + "long_name": "eastward_sea_water_velocity", + "standard_name": "eastward_sea_water_velocity", + "units": "m s-1", + } + + ds["v"].attrs = { + "long_name": "northward_sea_water_velocity", + "standard_name": "northward_sea_water_velocity", + "units": "m s-1", + } + + ds["velocity_error"].attrs = { + "long_name": "velocity_error", + "units": "m s-1", + } + + # Set global attributes + ds.attrs = { + "title": "GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012", + "institution": "Consortium for Advanced Research on Transport of Hydrocarbon in the Environment (CARTHE)", + "source": "CODE-style drifters", + "history": "Downloaded from https://data.gulfresearchinitiative.org/data/R1.x134.073:0004 and post-processed into a ragged-array Xarray Dataset by CloudDrift", + "references": "Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012. Distributed by: Gulf of Mexico Research Initiative Information and Data Cooperative (GRIIDC), Harte Research Institute, Texas A&M University–Corpus Christi. doi:10.7266/N7VD6WC8", + } + + return ds
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/adapters/mosaic.html b/_modules/clouddrift/adapters/mosaic.html new file mode 100644 index 00000000..dedb5364 --- /dev/null +++ b/_modules/clouddrift/adapters/mosaic.html @@ -0,0 +1,633 @@ + + + + + + + + + + clouddrift.adapters.mosaic — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.adapters.mosaic

+"""
+This module defines functions used to adapt the MOSAiC sea-ice drift dataset as
+a ragged-array dataset.
+
+The dataset is hosted at https://doi.org/10.18739/A2KP7TS83.
+
+Reference: Angela Bliss, Jennifer Hutchings, Philip Anderson, Philipp Anhaus,
+Hans Jakob Belter, Jørgen Berge, Vladimir Bessonov, Bin Cheng, Sylvia Cole,
+Dave Costa, Finlo Cottier, Christopher J Cox, Pedro R De La Torre, Dmitry V Divine,
+Gilbert Emzivat, Ying-Chih Fang, Steven Fons, Michael Gallagher, Maxime Geoffrey,
+Mats A Granskog, ... Guangyu Zuo. (2022). Sea ice drift tracks from the Distributed
+Network of autonomous buoys deployed during the Multidisciplinary drifting Observatory
+for the Study of Arctic Climate (MOSAiC) expedition 2019 - 2021. Arctic Data Center.
+doi:10.18739/A2KP7TS83.
+
+Example
+-------
+>>> from clouddrift.adapters import mosaic
+>>> ds = mosaic.to_xarray()
+"""
+from datetime import datetime
+from io import BytesIO
+import numpy as np
+import pandas as pd
+import requests
+from tqdm import tqdm
+import xarray as xr
+import xml.etree.ElementTree as ET
+
+from clouddrift.adapters.utils import download_with_progress
+
+MOSAIC_VERSION = "2022"
+
+
+
+[docs] +def get_dataframes() -> tuple[pd.DataFrame, pd.DataFrame]: + """Get the MOSAiC data (obs dimension in the target Dataset) and metadata + (traj dimension in the target dataset ) as pandas DataFrames.""" + xml = get_repository_metadata() + filenames, urls = get_file_urls(xml) + exclude_patterns = ["site_buoy_summary", "buoy_list"] + data_filenames = [ + f for f in filenames if not any([s in f for s in exclude_patterns]) + ] + data_urls = [ + f + for n, f in enumerate(urls) + if not any([s in filenames[n] for s in exclude_patterns]) + ] + sensor_ids = [f.split("_")[-1].rstrip(".csv") for f in data_filenames] + sensor_list_url = urls[ + filenames.index([f for f in filenames if "buoy_list" in f].pop()) + ] + sensors = pd.read_csv(sensor_list_url) + + # Sort the urls by the order of sensor IDs in the sensor list + order_index = {id: n for n, id in enumerate(sensors["Sensor ID"])} + sorted_indices = sorted( + range(len(sensor_ids)), key=lambda k: order_index[sensor_ids[k]] + ) + sorted_data_urls = [data_urls[i] for i in sorted_indices] + buffers = [BytesIO(b"") * len(sorted_data_urls)] + + download_with_progress(zip(sorted_data_urls, buffers), desc="Downloading data") + dfs = [pd.read_csv(b) for b in buffers] + obs_df = pd.concat(dfs) + + # Use the index of the concatenated DataFrame to determine the count/rowsize + zero_indices = [n for n, val in enumerate(list(obs_df.index)) if val == 0] + sensors["rowsize"] = np.diff(zero_indices + [len(obs_df)]) + + # Make the time column the index of the DataFrame, which will make it a + # coordinate in the xarray Dataset. + obs_df.set_index("datetime", inplace=True) + sensors.set_index("Sensor ID", inplace=True) + + return obs_df, sensors
+ + + +
+[docs] +def get_file_urls(xml: str) -> list[str]: + """Pass the MOSAiC XML string and return the list of filenames and URLs.""" + filenames = [ + tag.text + for tag in ET.fromstring(xml).findall("./dataset/dataTable/physical/objectName") + ] + urls = [ + tag.text + for tag in ET.fromstring(xml).findall( + "./dataset/dataTable/physical/distribution/online/url" + ) + ] + return filenames, urls
+ + + +
+[docs] +def get_repository_metadata() -> str: + """Get the MOSAiC repository metadata as an XML string. + Pass this string to other get_* functions to extract the data you need. + """ + url = "https://arcticdata.io/metacat/d1/mn/v2/object/doi:10.18739/A2KP7TS83" + r = requests.get(url) + return r.content
+ + + +
+[docs] +def to_xarray(): + """Return the MOSAiC data as an ragged-array Xarray Dataset.""" + + # Download the data and metadata as pandas DataFrames. + obs_df, traj_df = get_dataframes() + + # Dates and datetimes are strings; convert them to datetime64 instances + # for compatibility with CloudDrift's analysis functions. + obs_df.index = pd.to_datetime(obs_df.index) + for col in [ + "Deployment Date", + "Deployment Datetime", + "First Data Datetime", + "Last Data Datetime", + ]: + traj_df[col] = pd.to_datetime(traj_df[col]) + + # Merge into an Xarray Dataset and rename the dimensions and variables to + # follow the CloudDrift convention. + ds = xr.merge([obs_df.to_xarray(), traj_df.to_xarray()]) + ds = ds.rename_dims({"datetime": "obs", "Sensor ID": "traj"}).rename_vars( + {"datetime": "time", "Sensor ID": "id"} + ) + + # Set variable attributes + ds["longitude"].attrs = { + "long_name": "longitude", + "standard_name": "longitude", + "units": "degrees_east", + } + + ds["latitude"].attrs = { + "long_name": "latitude", + "standard_name": "latitude", + "units": "degrees_north", + } + + # global attributes + ds.attrs = { + "title": "Multidisciplinary drifting Observatory for the Study of Arctic Climate (MOSAiC) expedition 2019 - 2021", + "history": f"Dataset updated in {MOSAIC_VERSION}", + "date_created": datetime.now().isoformat(), + "publisher_name": "NSF Arctic Data Center", + "publisher_url": "https://arcticdata.io/catalog/view/doi:10.18739/A2KP7TS83", + "license": "Creative Commons Attribution 4.0 International License (http://creativecommons.org/licenses/by/4.0/)", + } + + return ds
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/adapters/subsurface_floats.html b/_modules/clouddrift/adapters/subsurface_floats.html new file mode 100644 index 00000000..94d3bde4 --- /dev/null +++ b/_modules/clouddrift/adapters/subsurface_floats.html @@ -0,0 +1,674 @@ + + + + + + + + + + clouddrift.adapters.subsurface_floats — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.adapters.subsurface_floats

+"""
+This module defines functions to adapt as a ragged-array dataset a collection of data 
+from 2193 trajectories of SOFAR, APEX, and RAFOS subsurface floats from 52 experiments 
+across the world between 1989 and 2015.
+
+The dataset is hosted at https://www.aoml.noaa.gov/phod/float_traj/index.php
+
+Example
+-------
+>>> from clouddrift.adapters import subsurface_floats
+>>> ds = subsurface_floats.to_xarray()
+"""
+
+from datetime import datetime
+import numpy as np
+import os
+import pandas as pd
+import scipy.io
+import tempfile
+import xarray as xr
+import warnings
+
+from clouddrift.adapters.utils import download_with_progress
+
+SUBSURFACE_FLOATS_DATA_URL = (
+    "https://www.aoml.noaa.gov/phod/float_traj/files/allFloats_12122017.mat"
+)
+SUBSURFACE_FLOATS_VERSION = "December 2017 (version 2)"
+SUBSURFACE_FLOATS_TMP_PATH = os.path.join(
+    tempfile.gettempdir(), "clouddrift", "subsurface_floats"
+)
+
+
+
+[docs] +def download(file: str): + download_with_progress([(SUBSURFACE_FLOATS_DATA_URL, file)])
+ + + +
+[docs] +def to_xarray( + tmp_path: str = None, +): + if tmp_path is None: + tmp_path = SUBSURFACE_FLOATS_TMP_PATH + os.makedirs(tmp_path, exist_ok=True) + + local_file = f"{tmp_path}/{SUBSURFACE_FLOATS_DATA_URL.split('/')[-1]}" + download(local_file) + source_data = scipy.io.loadmat(local_file) + + # metadata + meta_variables = [ + "expList", + "expName", + "expOrg", + "expPI", + "fltType", + "indexExp", + "indexFlt", + ] + + metadata = {} + for var in meta_variables: + metadata[var] = np.array([v.flatten()[0] for v in source_data[var].flatten()]) + + # bring the expList to the "traj" dimension + _, float_per_exp = np.unique(metadata["indexExp"], return_counts=True) + metadata["expList"] = np.repeat(metadata["expList"], float_per_exp) + + # data + data_variables = ["dtnum", "lon", "lat", "p", "t", "u", "v"] + data = {} + for var in data_variables: + data[var] = np.concatenate([v.flatten() for v in source_data[var].flatten()]) + + # create rowsize variable + rowsize = np.array([len(v) for v in source_data["dtnum"].flatten()]) + assert np.sum(rowsize) == len(data["dtnum"]) + + # Unix epoch start (1970-01-01) + origin_datenum = 719529 + + ds = xr.Dataset( + { + "expList": (["traj"], metadata["expList"]), + "expName": (["traj"], metadata["expName"]), + "expOrg": (["traj"], metadata["expOrg"]), + "expPI": (["traj"], metadata["expPI"]), + "indexExp": (["traj"], metadata["indexExp"]), + "fltType": (["traj"], metadata["fltType"]), + "id": (["traj"], metadata["indexFlt"]), + "rowsize": (["traj"], rowsize), + "time": ( + ["obs"], + pd.to_datetime(data["dtnum"] - origin_datenum, unit="D"), + ), + "lon": (["obs"], data["lon"]), + "lat": (["obs"], data["lat"]), + "pres": (["obs"], data["p"]), + "temp": (["obs"], data["t"]), + "ve": (["obs"], data["u"]), + "vn": (["obs"], data["v"]), + } + ) + + # Cast double floats to singles + double_vars = ["lat", "lon"] + for var in [v for v in ds.variables if v not in double_vars]: + if ds[var].dtype == "float64": + ds[var] = ds[var].astype("float32") + + # define attributes + vars_attrs = { + "expList": { + "long_name": "Experiment list", + "units": "-", + }, + "expName": { + "long_name": "Experiment name", + "units": "-", + }, + "expOrg": { + "long_name": "Experiment organization", + "units": "-", + }, + "expPI": { + "long_name": "Experiment principal investigator", + "units": "-", + }, + "indexExp": { + "long_name": "Experiment index number", + "units": "-", + "comment": "The index matches the float with its experiment metadata", + }, + "fltType": { + "long_name": "Float type", + "units": "-", + }, + "id": {"long_name": "Float ID", "units": "-"}, + "lon": { + "long_name": "Longitude", + "standard_name": "longitude", + "units": "degrees_east", + }, + "lat": { + "long_name": "Latitude", + "standard_name": "latitude", + "units": "degrees_north", + }, + "rowsize": { + "long_name": "Number of observations per trajectory", + "sample_dimension": "obs", + "units": "-", + }, + "pres": { + "long_name": "Pressure", + "standard_name": "sea_water_pressure", + "units": "dbar", + }, + "temp": { + "long_name": "Temperature", + "standard_name": "sea_water_temperature", + "units": "degree_C", + }, + "ve": { + "long_name": "Eastward velocity", + "standard_name": "eastward_sea_water_velocity", + "units": "m s-1", + }, + "vn": { + "long_name": "Northward velocity", + "standard_name": "northward_sea_water_velocity", + "units": "m s-1", + }, + } + + # global attributes + attrs = { + "title": "Subsurface float trajectories dataset", + "history": SUBSURFACE_FLOATS_VERSION, + "date_created": datetime.now().isoformat(), + "publisher_name": "WOCE Subsurface Float Data Assembly Center and NOAA AOML", + "publisher_url": "https://www.aoml.noaa.gov/phod/float_traj/data.php", + "license": "freely available", + "acknowledgement": f"Maintained by Andree Ramsey and Heather Furey from the Woods Hole Oceanographic Institution", + } + + # set attributes + for var in vars_attrs.keys(): + if var in ds.keys(): + ds[var].attrs = vars_attrs[var] + else: + warnings.warn(f"Variable {var} not found in upstream data; skipping.") + ds.attrs = attrs + + # set coordinates + ds = ds.set_coords(["time", "id"]) + + return ds
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/datasets.html b/_modules/clouddrift/datasets.html new file mode 100644 index 00000000..fa584a16 --- /dev/null +++ b/_modules/clouddrift/datasets.html @@ -0,0 +1,1102 @@ + + + + + + + + + + clouddrift.datasets — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.datasets

+"""
+This module provides functions to easily access ragged array datasets. If the datasets are 
+not accessed via cloud storage platforms or are not found on the local filesystem,
+they will be downloaded from their upstream repositories and stored for later access 
+(~/.clouddrift for UNIX-based systems).
+"""
+from io import BufferedReader, BytesIO
+from clouddrift import adapters
+import os
+import platform
+import xarray as xr
+
+
+
+[docs] +def gdp1h(decode_times: bool = True) -> xr.Dataset: + """Returns the latest version of the NOAA Global Drifter Program (GDP) hourly + dataset as a ragged array Xarray dataset. + + The data is accessed from zarr archive hosted on a public AWS S3 bucket accessible at + https://registry.opendata.aws/noaa-oar-hourly-gdp/. Original data source from NOAA NCEI + is https://doi.org/10.25921/x46c-3620). + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + Hourly GDP dataset as a ragged array + + Examples + -------- + >>> from clouddrift.datasets import gdp1h + >>> ds = gdp1h() + >>> ds + <xarray.Dataset> + Dimensions: (traj: 19396, obs: 197214787) + Coordinates: + id (traj) int64 ... + time (obs) datetime64[ns] ... + Dimensions without coordinates: traj, obs + Data variables: (12/60) + BuoyTypeManufacturer (traj) |S20 ... + BuoyTypeSensorArray (traj) |S20 ... + CurrentProgram (traj) float32 ... + DeployingCountry (traj) |S20 ... + DeployingShip (traj) |S20 ... + DeploymentComments (traj) |S20 ... + ... ... + start_lat (traj) float32 ... + start_lon (traj) float32 ... + typebuoy (traj) |S10 ... + typedeath (traj) int8 ... + ve (obs) float32 ... + vn (obs) float32 ... + Attributes: (12/16) + Conventions: CF-1.6 + acknowledgement: Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurio... + contributor_name: NOAA Global Drifter Program + contributor_role: Data Acquisition Center + date_created: 2023-09-08T17:05:12.130123 + doi: 10.25921/x46c-3620 + ... ... + processing_level: Level 2 QC by GDP drifter DAC + publisher_email: aoml.dftr@noaa.gov + publisher_name: GDP Drifter DAC + publisher_url: https://www.aoml.noaa.gov/phod/gdp + summary: Global Drifter Program hourly data + title: Global Drifter Program hourly drifting buoy collection + + See Also + -------- + :func:`gdp6h` + """ + url = "https://noaa-oar-hourly-gdp-pds.s3.amazonaws.com/latest/gdp-v2.01.zarr" + ds = xr.open_dataset(url, engine="zarr", decode_times=decode_times) + ds = ds.rename_vars({"ID": "id"}).assign_coords({"id": ds.ID}).drop_vars(["ids"]) + return ds
+ + + +
+[docs] +def gdp6h(decode_times: bool = True) -> xr.Dataset: + """Returns the NOAA Global Drifter Program (GDP) 6-hourly dataset as a ragged array + Xarray dataset. + + The data is accessed from a public HTTPS server at NOAA's Atlantic + Oceanographic and Meteorological Laboratory (AOML) accessible at + https://www.aoml.noaa.gov/phod/gdp/index.php. It should be noted that the data loading + method is platform dependent. Linux and Darwin (macOS) machines lazy load the datasets leveraging the + byte-range feature of the netCDF-c library (dataset loading engine used by xarray). + Windows machines download the entire dataset into a memory buffer which is then passed + to xarray. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + 6-hourly GDP dataset as a ragged array + + Examples + -------- + >>> from clouddrift.datasets import gdp6h + >>> ds = gdp6h() + >>> ds + <xarray.Dataset> + Dimensions: (traj: 27647, obs: 46535470) + Coordinates: + ids (obs) int64 7702204 7702204 ... 300234061198840 + time (obs) float64 2.879e+08 2.879e+08 ... 1.697e+09 + Dimensions without coordinates: traj, obs + Data variables: (12/50) + ID (traj) int64 7702204 7702201 ... 300234061198840 + rowsize (traj) int32 92 1747 1943 1385 1819 ... 54 53 51 28 + WMO (traj) int32 0 0 0 0 ... 6203890 6203888 4101885 + expno (traj) int32 40 40 40 40 ... 31412 21421 21421 31412 + deploy_date (traj) float32 2.878e+08 2.878e+08 ... 1.696e+09 nan + deploy_lat (traj) float32 -7.798 -4.9 -3.18 ... 9.9 11.9 nan + ... ... + vn (obs) float32 nan 0.1056 0.04974 ... 0.7384 nan + temp (obs) float32 28.35 28.3 nan ... 29.08 28.97 28.92 + err_lat (obs) float32 0.009737 0.007097 ... 0.001659 0.001687 + err_lon (obs) float32 0.00614 0.004583 ... 0.002471 0.002545 + err_temp (obs) float32 0.08666 0.08757 ... 0.03665 0.03665 + drogue_status (obs) bool False False False False ... True True True + Attributes: (12/18) + title: Global Drifter Program drifting buoy collection + history: version September 2023. Metadata from dirall.dat an... + Conventions: CF-1.6 + time_coverage_start: 1979-02-15:00:00:00Z + time_coverage_end: 2023-10-18:18:00:00Z + date_created: 2023-12-22T17:50:22.242943 + ... ... + contributor_name: NOAA Global Drifter Program + contributor_role: Data Acquisition Center + institution: NOAA Atlantic Oceanographic and Meteorological Labo... + acknowledgement: Lumpkin, Rick; Centurioni, Luca (2019). NOAA Global... + summary: Global Drifter Program six-hourly data + doi: 10.25921/7ntx-z961 + + See Also + -------- + :func:`gdp1h` + """ + url = "https://www.aoml.noaa.gov/ftp/pub/phod/buoydata/gdp6h_ragged_may23.nc#mode=bytes" + + if platform.system() == "Windows": + buffer = BytesIO() + adapters.utils.download_with_progress([(f"{url}#mode=bytes", buffer)]) + reader = BufferedReader(buffer) + ds = xr.open_dataset(reader, decode_times=decode_times) + else: + ds = xr.open_dataset(f"{url}", decode_times=decode_times) + + ds = ds.rename_vars({"ID": "id"}).assign_coords({"id": ds.ID}).drop_vars(["ids"]) + return ds
+ + + +
+[docs] +def glad(decode_times: bool = True) -> xr.Dataset: + """Returns the Grand LAgrangian Deployment (GLAD) dataset as a ragged array + Xarray dataset. + + The function will first look for the ragged-array dataset on the local + filesystem. If it is not found, the dataset will be downloaded using the + corresponding adapter function and stored for later access. + + The upstream data is available at https://doi.org/10.7266/N7VD6WC8. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + GLAD dataset as a ragged array + + Examples + -------- + >>> from clouddrift.datasets import glad + >>> ds = glad() + >>> ds + <xarray.Dataset> + Dimensions: (obs: 1602883, traj: 297) + Coordinates: + time (obs) datetime64[ns] ... + id (traj) object ... + Data variables: + latitude (obs) float32 ... + longitude (obs) float32 ... + position_error (obs) float32 ... + u (obs) float32 ... + v (obs) float32 ... + velocity_error (obs) float32 ... + rowsize (traj) int64 ... + Attributes: + title: GLAD experiment CODE-style drifter trajectories (low-pass f... + institution: Consortium for Advanced Research on Transport of Hydrocarbo... + source: CODE-style drifters + history: Downloaded from https://data.gulfresearchinitiative.org/dat... + references: Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter t... + + Reference + --------- + Özgökmen, Tamay. 2013. GLAD experiment CODE-style drifter trajectories (low-pass filtered, 15 minute interval records), northern Gulf of Mexico near DeSoto Canyon, July-October 2012. Distributed by: Gulf of Mexico Research Initiative Information and Data Cooperative (GRIIDC), Harte Research Institute, Texas A&M University–Corpus Christi. doi:10.7266/N7VD6WC8 + """ + clouddrift_path = ( + os.path.expanduser("~/.clouddrift") + if not os.getenv("CLOUDDRIFT_PATH") + else os.getenv("CLOUDDRIFT_PATH") + ) + glad_path = f"{clouddrift_path}/data/glad.nc" + if not os.path.exists(glad_path): + print(f"{glad_path} not found; download from upstream repository.") + ds = adapters.glad.to_xarray() + os.makedirs(os.path.dirname(glad_path), exist_ok=True) + ds.to_netcdf(glad_path) + else: + ds = xr.open_dataset(glad_path, decode_times=decode_times) + return ds
+ + + +
+[docs] +def mosaic(decode_times: bool = True) -> xr.Dataset: + """Returns the MOSAiC sea-ice drift dataset as a ragged array Xarray dataset. + + The function will first look for the ragged-array dataset on the local + filesystem. If it is not found, the dataset will be downloaded using the + corresponding adapter function and stored for later access. + + The upstream data is available at https://arcticdata.io/catalog/view/doi:10.18739/A2KP7TS83. + + Reference + --------- + Angela Bliss, Jennifer Hutchings, Philip Anderson, Philipp Anhaus, + Hans Jakob Belter, Jørgen Berge, Vladimir Bessonov, Bin Cheng, Sylvia Cole, + Dave Costa, Finlo Cottier, Christopher J Cox, Pedro R De La Torre, Dmitry V Divine, + Gilbert Emzivat, Ying-Chih Fang, Steven Fons, Michael Gallagher, Maxime Geoffrey, + Mats A Granskog, ... Guangyu Zuo. (2022). Sea ice drift tracks from the Distributed + Network of autonomous buoys deployed during the Multidisciplinary drifting Observatory + for the Study of Arctic Climate (MOSAiC) expedition 2019 - 2021. Arctic Data Center. + doi:10.18739/A2KP7TS83. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + MOSAiC sea-ice drift dataset as a ragged array + + Examples + -------- + >>> from clouddrift.datasets import mosaic + >>> ds = mosaic() + >>> ds + <xarray.Dataset> + Dimensions: (obs: 1926226, traj: 216) + Coordinates: + time (obs) datetime64[ns] ... + id (traj) object ... + Dimensions without coordinates: obs, traj + Data variables: (12/19) + latitude (obs) float64 ... + longitude (obs) float64 ... + Deployment Leg (traj) int64 ... + DN Station ID (traj) object ... + IMEI (traj) object ... + Deployment Date (traj) datetime64[ns] ... + ... ... + Buoy Type (traj) object ... + Manufacturer (traj) object ... + Model (traj) object ... + PI (traj) object ... + Data Authors (traj) object ... + rowsize (traj) int64 ... + """ + clouddrift_path = ( + os.path.expanduser("~/.clouddrift") + if not os.getenv("CLOUDDRIFT_PATH") + else os.getenv("CLOUDDRIFT_PATH") + ) + mosaic_path = f"{clouddrift_path}/data/mosaic.nc" + if not os.path.exists(mosaic_path): + print(f"{mosaic_path} not found; download from upstream repository.") + ds = adapters.mosaic.to_xarray() + os.makedirs(os.path.dirname(mosaic_path), exist_ok=True) + ds.to_netcdf(mosaic_path) + else: + ds = xr.open_dataset(mosaic_path, decode_times=decode_times) + return ds
+ + + +
+[docs] +def spotters(decode_times: bool = True) -> xr.Dataset: + """Returns the Sofar Ocean Spotter drifters ragged array dataset as an Xarray dataset. + + The data is accessed from a zarr archive hosted on a public AWS S3 bucket accessible + at https://sofar-spotter-archive.s3.amazonaws.com/spotter_data_bulk_zarr. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + Sofar ocean floats dataset as a ragged array + + Examples + -------- + >>> from clouddrift.datasets import spotters + >>> ds = spotters() + >>> ds + <xarray.Dataset> + Dimensions: (index: 6390651, trajectory: 871) + Coordinates: + time (index) datetime64[ns] ... + * trajectory (trajectory) object 'SPOT-010001' ... 'SPOT-1975' + Dimensions without coordinates: index + Data variables: + latitude (index) float64 ... + longitude (index) float64 ... + meanDirection (index) float64 ... + meanDirectionalSpread (index) float64 ... + meanPeriod (index) float64 ... + peakDirection (index) float64 ... + peakDirectionalSpread (index) float64 ... + peakPeriod (index) float64 ... + rowsize (trajectory) int64 ... + significantWaveHeight (index) float64 ... + Attributes: + author: Isabel A. Houghton + creation_date: 2023-10-18 00:43:55.333537 + email: isabel.houghton@sofarocean.com + institution: Sofar Ocean + references: https://content.sofarocean.com/hubfs/Spotter%20product%20... + source: Spotter wave buoy + title: Sofar Spotter Data Archive - Bulk Wave Parameters + """ + url = "https://sofar-spotter-archive.s3.amazonaws.com/spotter_data_bulk_zarr" + return xr.open_dataset(url, engine="zarr", decode_times=decode_times)
+ + + +
+[docs] +def subsurface_floats(decode_times: bool = True) -> xr.Dataset: + """Returns the subsurface floats dataset as a ragged array Xarray dataset. + + The data is accessed from a public HTTPS server at NOAA's Atlantic + Oceanographic and Meteorological Laboratory (AOML) accessible at + https://www.aoml.noaa.gov/phod/gdp/index.php. + + The upstream data is available at + https://www.aoml.noaa.gov/phod/float_traj/files/allFloats_12122017.mat. + + This dataset of subsurface float observations was compiled by the WOCE Subsurface + Float Data Assembly Center (WFDAC) in Woods Hole maintained by Andree Ramsey and + Heather Furey and copied to NOAA/AOML in October 2014 (version 1) and in December + 2017 (version 2). Subsequent updates will be included as additional appropriate + float data, quality controlled by the appropriate principal investigators, is + submitted for inclusion. + + Note that these observations are collected by ALACE/RAFOS/Eurofloat-style + acoustically-tracked, neutrally-buoyant subsurface floats which collect data while + drifting beneath the ocean surface. These data are the result of the effort and + resources of many individuals and institutions. You are encouraged to acknowledge + the work of the data originators and Data Centers in publications arising from use + of these data. + + The float data were originally divided by project at the WFDAC. Here they have been + compiled in a single Matlab data set. See here for more information on the variables + contained in these files. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + Subsurface floats dataset as a ragged array + + Examples + -------- + >>> from clouddrift.datasets import subsurface_floats + >>> ds = subsurface_floats() + >>> ds + <xarray.Dataset> + Dimensions: (traj: 2193, obs: 1402840) + Coordinates: + id (traj) uint16 ... + time (obs) datetime64[ns] ... + Dimensions without coordinates: traj, obs + Data variables: (12/13) + expList (traj) object ... + expName (traj) object ... + expOrg (traj) object ... + expPI (traj) object ... + indexExp (traj) uint8 ... + fltType (traj) object ... + ... ... + lon (obs) float64 ... + lat (obs) float64 ... + pres (obs) float64 ... + temp (obs) float64 ... + ve (obs) float64 ... + vn (obs) float64 ... + Attributes: + title: Subsurface float trajectories dataset + history: December 2017 (version 2) + date_created: 2023-11-14T22:30:38.831656 + publisher_name: WOCE Subsurface Float Data Assembly Center and NOAA AOML + publisher_url: https://www.aoml.noaa.gov/phod/float_traj/data.php + license: freely available + acknowledgement: Maintained by Andree Ramsey and Heather Furey from the ... + + References + ---------- + WOCE Subsurface Float Data Assembly Center (WFDAC) https://www.aoml.noaa.gov/phod/float_traj/index.php + """ + + clouddrift_path = ( + os.path.expanduser("~/.clouddrift") + if not os.getenv("CLOUDDRIFT_PATH") + else os.getenv("CLOUDDRIFT_PATH") + ) + + local_file = f"{clouddrift_path}/data/subsurface_floats.nc" + if not os.path.exists(local_file): + print(f"{local_file} not found; download from upstream repository.") + ds = adapters.subsurface_floats.to_xarray() + else: + ds = xr.open_dataset(local_file, decode_times=decode_times) + return ds
+ + + +
+[docs] +def yomaha(decode_times: bool = True) -> xr.Dataset: + """Returns the YoMaHa dataset as a ragged array Xarray dataset. + + The function will first look for the ragged-array dataset on the local + filesystem. If it is not found, the dataset will be downloaded using the + corresponding adapter function and stored for later access. The upstream + data is available at http://apdrc.soest.hawaii.edu/projects/yomaha/. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + YoMaHa'07 dataset as a ragged array + + Examples + -------- + + >>> from clouddrift.datasets import yomaha + >>> ds = yomaha() + >>> ds + <xarray.Dataset> + Dimensions: (obs: 1926743, traj: 12196) + Coordinates: + time_d (obs) datetime64[ns] ... + time_s (obs) datetime64[ns] ... + time_lp (obs) datetime64[ns] ... + time_lc (obs) datetime64[ns] ... + id (traj) int64 ... + Dimensions without coordinates: obs, traj + Data variables: (12/27) + lon_d (obs) float64 ... + lat_d (obs) float64 ... + pres_d (obs) float32 ... + ve_d (obs) float32 ... + vn_d (obs) float32 ... + err_ve_d (obs) float32 ... + ... ... + cycle (obs) int64 ... + time_inv (obs) int64 ... + rowsize (traj) int64 ... + wmo_id (traj) int64 ... + dac_id (traj) int64 ... + float_type (traj) int64 ... + Attributes: + title: YoMaHa'07: Velocity data assessed from trajectories of A... + history: Dataset updated on Tue Jun 28 03:14:34 HST 2022 + date_created: 2023-12-08T00:52:08.478075 + publisher_name: Asia-Pacific Data Research Center + publisher_url: http://apdrc.soest.hawaii.edu/index.php + license: Creative Commons Attribution 4.0 International License.. + + Reference + --------- + Lebedev, K. V., Yoshinari, H., Maximenko, N. A., & Hacker, P. W. (2007). Velocity data + assessed from trajectories of Argo floats at parking level and at the sea + surface. IPRC Technical Note, 4(2), 1-16. + """ + clouddrift_path = ( + os.path.expanduser("~/.clouddrift") + if not os.getenv("CLOUDDRIFT_PATH") + else os.getenv("CLOUDDRIFT_PATH") + ) + local_file = f"{clouddrift_path}/data/yomaha.nc" + if not os.path.exists(local_file): + print(f"{local_file} not found; download from upstream repository.") + ds = adapters.yomaha.to_xarray() + os.makedirs(os.path.dirname(local_file), exist_ok=True) + ds.to_netcdf(local_file) + else: + ds = xr.open_dataset(local_file, decode_times=decode_times) + return ds
+ + + +
+[docs] +def andro(decode_times: bool = True) -> xr.Dataset: + """Returns the ANDRO as a ragged array Xarray dataset. + + The function will first look for the ragged-array dataset on the local + filesystem. If it is not found, the dataset will be downloaded using the + corresponding adapter function and stored for later access. The upstream + data is available at https://www.seanoe.org/data/00360/47077/. + + Parameters + ---------- + decode_times : bool, optional + If True, decode the time coordinate into a datetime object. If False, the time + coordinate will be an int64 or float64 array of increments since the origin + time indicated in the units attribute. Default is True. + + Returns + ------- + xarray.Dataset + ANDRO dataset as a ragged array + Examples + -------- + >>> from clouddrift.datasets import andro + >>> ds = andro() + >>> ds + <xarray.Dataset> + Dimensions: (obs: 1360753, traj: 9996) + Coordinates: + time_d (obs) datetime64[ns] ... + time_s (obs) datetime64[ns] ... + time_lp (obs) datetime64[ns] ... + time_lc (obs) datetime64[ns] ... + id (traj) int64 ... + Dimensions without coordinates: obs, traj + Data variables: (12/33) + lon_d (obs) float64 ... + lat_d (obs) float64 ... + pres_d (obs) float32 ... + temp_d (obs) float32 ... + sal_d (obs) float32 ... + ve_d (obs) float32 ... + ... ... + lon_lc (obs) float64 ... + lat_lc (obs) float64 ... + surf_fix (obs) int64 ... + cycle (obs) int64 ... + profile_id (obs) float32 ... + rowsize (traj) int64 ... + Attributes: + title: ANDRO: An Argo-based deep displacement dataset + history: 2022-03-04 + date_created: 2023-12-08T00:52:00.937120 + publisher_name: SEANOE (SEA scieNtific Open data Edition) + publisher_url: https://www.seanoe.org/data/00360/47077/ + license: freely available + + Reference + --------- + Ollitrault Michel, Rannou Philippe, Brion Emilie, Cabanes Cecile, Piron Anne, Reverdin Gilles, + Kolodziejczyk Nicolas (2022). ANDRO: An Argo-based deep displacement dataset. + SEANOE. https://doi.org/10.17882/47077 + """ + clouddrift_path = ( + os.path.expanduser("~/.clouddrift") + if not os.getenv("CLOUDDRIFT_PATH") + else os.getenv("CLOUDDRIFT_PATH") + ) + local_file = f"{clouddrift_path}/data/andro.nc" + if not os.path.exists(local_file): + print(f"{local_file} not found; download from upstream repository.") + ds = adapters.andro.to_xarray() + os.makedirs(os.path.dirname(local_file), exist_ok=True) + ds.to_netcdf(local_file) + else: + ds = xr.open_dataset(local_file, decode_times=decode_times) + return ds
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/kinematics.html b/_modules/clouddrift/kinematics.html new file mode 100644 index 00000000..1e82f785 --- /dev/null +++ b/_modules/clouddrift/kinematics.html @@ -0,0 +1,1418 @@ + + + + + + + + + + clouddrift.kinematics — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.kinematics

+"""
+Functions for kinematic computations.
+"""
+
+import numpy as np
+import pandas as pd
+from typing import Optional, Tuple, Union
+import xarray as xr
+from clouddrift.sphere import (
+    EARTH_RADIUS_METERS,
+    bearing,
+    cartesian_to_spherical,
+    cartesian_to_tangentplane,
+    coriolis_frequency,
+    distance,
+    position_from_distance_and_bearing,
+    recast_lon360,
+    spherical_to_cartesian,
+)
+from clouddrift.wavelet import morse_logspace_freq, morse_wavelet, wavelet_transform
+
+
+
+[docs] +def kinetic_energy( + u: Union[float, list, np.ndarray, xr.DataArray, pd.Series], + v: Optional[Union[float, list, np.ndarray, xr.DataArray, pd.Series]] = None, +) -> Union[float, np.ndarray, xr.DataArray]: + """Compute kinetic energy from zonal and meridional velocities. + + Parameters + ---------- + u : float or array-like + Zonal velocity. + v : float or array-like, optional. + Meridional velocity. If not provided, the flow is assumed one-dimensional + in time and defined by ``u``. + + Returns + ------- + ke : float or array-like + Kinetic energy. + + Examples + -------- + >>> import numpy as np + >>> from clouddrift.kinematics import kinetic_energy + >>> u = np.array([1., 2., 3., 4.]) + >>> v = np.array([1., 1., 1., 1.]) + >>> kinetic_energy(u, v) + array([1. , 2.5, 5. , 8.5]) + + >>> u = np.reshape(np.tile([1., 2., 3., 4.], 2), (2, 4)) + >>> v = np.reshape(np.tile([1., 1., 1., 1.], 2), (2, 4)) + >>> kinetic_energy(u, v) + array([[1. , 2.5, 5. , 8.5], + [1. , 2.5, 5. , 8.5]]) + """ + if v is None: + v = np.zeros_like(u) + ke = (u**2 + v**2) / 2 + return ke
+ + + +
+[docs] +def inertial_oscillation_from_position( + longitude: np.ndarray, + latitude: np.ndarray, + relative_bandwidth: Optional[float] = None, + wavelet_duration: Optional[float] = None, + time_step: Optional[float] = 3600.0, + relative_vorticity: Optional[Union[float, np.ndarray]] = 0.0, +) -> np.ndarray: + """Extract inertial oscillations from consecutive geographical positions. + + This function acts by performing a time-frequency analysis of horizontal displacements + with analytic Morse wavelets. It extracts the portion of the wavelet transform signal + that follows the inertial frequency (opposite of Coriolis frequency) as a function of time, + potentially shifted in frequency by a measure of relative vorticity. The result is a pair + of zonal and meridional relative displacements in meters. + + This function is equivalent to a bandpass filtering of the horizontal displacements. The characteristics + of the filter are defined by the relative bandwidth of the wavelet transform or by the duration of the wavelet, + see the parameters below. + + Parameters + ---------- + longitude : array-like + Longitude sequence. Unidimensional array input. + latitude : array-like + Latitude sequence. Unidimensional array input. + relative_bandwidth : float, optional + Bandwidth of the frequency-domain equivalent filter for the extraction of the inertial + oscillations; a number less or equal to one which is a fraction of the inertial frequency. + A value of 0.1 leads to a bandpass filter equivalent of +/- 10 percent of the inertial frequency. + wavelet_duration : float, optional + Duration of the wavelet, or inverse of the relative bandwidth, which can be passed instead of the + relative bandwidth. + time_step : float, optional + The constant time interval between data points in seconds. Default is 3600. + relative_vorticity: Optional, float or array-like + Relative vorticity adding to the local Coriolis frequency. If "f" is the Coriolis + frequency then "f" + `relative_vorticity` will be the effective Coriolis frequency as defined by Kunze (1985). + Positive values correspond to cyclonic vorticity, irrespectively of the latitudes of the data + points. + + Returns + ------- + xhat : array-like + Zonal relative displacement in meters from inertial oscillations. + yhat : array-like + Meridional relative displacement in meters from inertial oscillations. + + Examples + -------- + To extract displacements from inertial oscillations from sequences of longitude + and latitude values, equivalent to bandpass around 20 percent of the local inertial frequency: + + >>> xhat, yhat = inertial_oscillation_from_position(longitude, latitude, relative_bandwidth=0.2) + + The same result can be obtained by specifying the wavelet duration instead of the relative bandwidth: + + >>> xhat, yhat = inertial_oscillation_from_position(longitude, latitude, wavelet_duration=5) + + Next, the residual positions from the inertial displacements can be obtained with another function: + + >>> residual_longitudes, residual_latitudes = residual_position_from_displacement(longitude, latitude, xhat, yhat) + + Raises + ------ + ValueError + If longitude and latitude arrays do not have the same shape. + If relative_vorticity is an array and does not have the same shape as longitude and latitude. + If time_step is not a float. + If both relative_bandwidth and wavelet_duration are specified. + If neither relative_bandwidth nor wavelet_duration are specified. + If the absolute value of relative_bandwidth is not in the range (0,1]. + If the wavelet duration is not greater than or equal to 1. + + See Also + -------- + :func:`residual_position_from_displacement`, `wavelet_transform`, `morse_wavelet` + + """ + if longitude.shape != latitude.shape: + raise ValueError("longitude and latitude arrays must have the same shape.") + + if relative_bandwidth is not None and wavelet_duration is not None: + raise ValueError( + "Only one of 'relative_bandwidth' and 'wavelet_duration' can be specified" + ) + elif relative_bandwidth is None and wavelet_duration is None: + raise ValueError( + "One of 'relative_bandwidth' and 'wavelet_duration' must be specified" + ) + + # length of data sequence + data_length = longitude.shape[0] + + if isinstance(relative_vorticity, float): + relative_vorticity = np.full_like(longitude, relative_vorticity) + elif isinstance(relative_vorticity, np.ndarray): + if not relative_vorticity.shape == longitude.shape: + raise ValueError( + "relative_vorticity must be a float or the same shape as longitude and latitude." + ) + if relative_bandwidth is not None: + if not 0 < np.abs(relative_bandwidth) <= 1: + raise ValueError("relative_bandwidth must be in the (0, 1]) range") + + if wavelet_duration is not None: + if not wavelet_duration >= 1: + raise ValueError("wavelet_duration must be greater than or equal to 1") + + # wavelet parameters are gamma and beta + gamma = 3 # symmetric wavelet + density = 16 # results relative insensitive to this parameter + # calculate beta from wavelet duration or from relative bandwidth + if relative_bandwidth is not None: + wavelet_duration = 1 / np.abs(relative_bandwidth) # P parameter + beta = wavelet_duration**2 / gamma + + if isinstance(latitude, xr.DataArray): + latitude = latitude.to_numpy() + if isinstance(longitude, xr.DataArray): + longitude = longitude.to_numpy() + + # Instantaneous absolute frequency of oscillations along trajectory in radian per second + cor_freq = np.abs( + coriolis_frequency(latitude) + relative_vorticity * np.sign(latitude) + ) + cor_freq_max = np.max(cor_freq * 1.05) + cor_freq_min = np.max( + [np.min(cor_freq * 0.95), 2 * np.pi / (time_step * data_length)] + ) + + # logarithmically distributed frequencies for wavelet analysis + radian_frequency = morse_logspace_freq( + gamma, + beta, + data_length, + (0.05, cor_freq_max * time_step), + (5, cor_freq_min * time_step), + density, + ) # frequencies in radian per unit time + + # wavelet transform on a sphere + # unwrap longitude recasted in [0,360) + longitude_unwrapped = np.unwrap(recast_lon360(longitude), period=360) + + # convert lat/lon to Cartesian coordinates x, y , z + x, y, z = spherical_to_cartesian(longitude_unwrapped, latitude) + + # wavelet transform of x, y, z + wavelet, _ = morse_wavelet(data_length, gamma, beta, radian_frequency) + wx = wavelet_transform(x, wavelet, boundary="mirror") + wy = wavelet_transform(y, wavelet, boundary="mirror") + wz = wavelet_transform(z, wavelet, boundary="mirror") + + longitude_new, latitude_new = cartesian_to_spherical( + x - np.real(wx), y - np.real(wy), z - np.real(wz) + ) + + # convert transforms to horizontal displacements on tangent plane + wxh, wyh = cartesian_to_tangentplane(wx, wy, wz, longitude_new, latitude_new) + + # rotary wavelet transforms to select inertial component; need to divide by sqrt(2) + wp = (wxh + 1j * wyh) / np.sqrt(2) + wn = (wxh - 1j * wyh) / np.sqrt(2) + + # find the values of radian_frequency/dt that most closely match cor_freq + frequency_bins = [ + np.argmin(np.abs(cor_freq[i] - radian_frequency / time_step)) + for i in range(data_length) + ] + + # get the transform at the inertial and "anti-inertial" frequencies + # extract the values of wp and wn at the calculated index as a function of time + # positive is anticyclonic (inertial) in the southern hemisphere + # negative is anticyclonic (inertial) in the northern hemisphere + wp = wp[frequency_bins, np.arange(0, data_length)] + wn = wn[frequency_bins, np.arange(0, data_length)] + + # indices of northern latitude points + north = latitude >= 0 + + # initialize the zonal and meridional components of inertial displacements + wxhat = np.zeros_like(latitude, dtype=np.complex64) + wyhat = np.zeros_like(latitude, dtype=np.complex64) + # equations are x+ = 0.5*(z+ + z-) and y+ = -0.5*1j*(z+ - z-) + if any(north): + wxhat[north] = wn[north] / np.sqrt(2) + wyhat[north] = 1j * wn[north] / np.sqrt(2) + if any(~north): + wxhat[~north] = wp[~north] / np.sqrt(2) + wyhat[~north] = -1j * wp[~north] / np.sqrt(2) + + # inertial displacement in meters + xhat = np.real(wxhat) + yhat = np.real(wyhat) + + return xhat, yhat
+ + + +
+[docs] +def residual_position_from_displacement( + longitude: Union[float, np.ndarray, xr.DataArray], + latitude: Union[float, np.ndarray, xr.DataArray], + x: Union[float, np.ndarray], + y: Union[float, np.ndarray], +) -> Union[Tuple[float], Tuple[np.ndarray]]: + """ + Return residual longitudes and latitudes along a trajectory on the spherical Earth + after correcting for zonal and meridional displacements x and y in meters. + + This is applicable as an example when one seeks to correct a trajectory for + horizontal oscillations due to inertial motions, tides, etc. + + Parameters + ---------- + longitude : float or array-like + Longitude in degrees. + latitude : float or array-like + Latitude in degrees. + x : float or np.ndarray + Zonal displacement in meters. + y : float or np.ndarray + Meridional displacement in meters. + + Returns + ------- + residual_longitude : float or np.ndarray + Residual longitude after correcting for zonal displacement, in degrees. + residual_latitude : float or np.ndarray + Residual latitude after correcting for meridional displacement, in degrees. + + Examples + -------- + Obtain the new geographical position for a displacement of 1/360-th of the + circumference of the Earth from original position (longitude,latitude) = (1,0): + + >>> from clouddrift.sphere import EARTH_RADIUS_METERS + >>> residual_position_from_displacement(1,0,2 * np.pi * EARTH_RADIUS_METERS / 360,0) + (0.0, 0.0) + """ + # convert to numpy arrays to insure consistent outputs + if isinstance(longitude, xr.DataArray): + longitude = longitude.to_numpy() + if isinstance(latitude, xr.DataArray): + latitude = latitude.to_numpy() + + latitudehat = 180 / np.pi * y / EARTH_RADIUS_METERS + longitudehat = ( + 180 / np.pi * x / (EARTH_RADIUS_METERS * np.cos(np.radians(latitude))) + ) + + residual_latitude = latitude - latitudehat + residual_longitude = recast_lon360( + np.degrees(np.angle(np.exp(1j * np.radians(longitude - longitudehat)))) + ) + + return residual_longitude, residual_latitude
+ + + +
+[docs] +def position_from_velocity( + u: np.ndarray, + v: np.ndarray, + time: np.ndarray, + x_origin: float, + y_origin: float, + coord_system: Optional[str] = "spherical", + integration_scheme: Optional[str] = "forward", + time_axis: Optional[int] = -1, +) -> Tuple[np.ndarray, np.ndarray]: + """Compute positions from arrays of velocities and time and a pair of origin + coordinates. + + The units of the result are degrees if ``coord_system == "spherical"`` (default). + If ``coord_system == "cartesian"``, the units of the result are equal to the + units of the input velocities multiplied by the units of the input time. + For example, if the input velocities are in meters per second and the input + time is in seconds, the units of the result will be meters. + + Integration scheme can take one of three values: + + 1. "forward" (default): integration from x[i] to x[i+1] is performed + using the velocity at x[i]. + 2. "backward": integration from x[i] to x[i+1] is performed using the + velocity at x[i+1]. + 3. "centered": integration from x[i] to x[i+1] is performed using the + arithmetic average of the velocities at x[i] and x[i+1]. Note that + this method introduces some error due to the averaging. + + u, v, and time can be multi-dimensional arrays. If the time axis, along + which the finite differencing is performed, is not the last one (i.e. + x.shape[-1]), use the ``time_axis`` optional argument to specify along which + axis should the differencing be done. ``x``, ``y``, and ``time`` must have + the same shape. + + This function will not do any special handling of longitude ranges. If the + integrated trajectory crosses the antimeridian (dateline) in either direction, the + longitude values will not be adjusted to stay in any specific range such + as [-180, 180] or [0, 360]. If you need your longitudes to be in a specific + range, recast the resulting longitude from this function using the function + :func:`clouddrift.sphere.recast_lon`. + + Parameters + ---------- + u : np.ndarray + An array of eastward velocities. + v : np.ndarray + An array of northward velocities. + time : np.ndarray + An array of time values. + x_origin : float + Origin x-coordinate or origin longitude. + y_origin : float + Origin y-coordinate or origin latitude. + coord_system : str, optional + The coordinate system of the input. Can be "spherical" or "cartesian". + Default is "spherical". + integration_scheme : str, optional + The difference scheme to use for computing the position. Can be + "forward" or "backward". Default is "forward". + time_axis : int, optional + The axis of the time array. Default is -1, which corresponds to the + last axis. + + Returns + ------- + x : np.ndarray + An array of zonal displacements or longitudes. + y : np.ndarray + An array of meridional displacements or latitudes. + + Examples + -------- + + Simple integration on a plane, using the forward scheme by default: + + >>> import numpy as np + >>> from clouddrift.analysis import position_from_velocity + >>> u = np.array([1., 2., 3., 4.]) + >>> v = np.array([1., 1., 1., 1.]) + >>> time = np.array([0., 1., 2., 3.]) + >>> x, y = position_from_velocity(u, v, time, 0, 0, coord_system="cartesian") + >>> x + array([0., 1., 3., 6.]) + >>> y + array([0., 1., 2., 3.]) + + As above, but using centered scheme: + + >>> x, y = position_from_velocity(u, v, time, 0, 0, coord_system="cartesian", integration_scheme="centered") + >>> x + array([0., 1.5, 4., 7.5]) + >>> y + array([0., 1., 2., 3.]) + + Simple integration on a sphere (default): + + >>> u = np.array([1., 2., 3., 4.]) + >>> v = np.array([1., 1., 1., 1.]) + >>> time = np.array([0., 1., 2., 3.]) * 1e5 + >>> x, y = position_from_velocity(u, v, time, 0, 0) + >>> x + array([0. , 0.89839411, 2.69584476, 5.39367518]) + >>> y + array([0. , 0.89828369, 1.79601515, 2.69201609]) + + Integrating across the antimeridian (dateline) by default does not + recast the resulting longitude: + + >>> u = np.array([1., 1.]) + >>> v = np.array([0., 0.]) + >>> time = np.array([0, 1e5]) + >>> x, y = position_from_velocity(u, v, time, 179.5, 0) + >>> x + array([179.5 , 180.3983205]) + >>> y + array([0., 0.]) + + Use the ``clouddrift.sphere.recast_lon`` function to recast the longitudes + to the desired range: + + >>> from clouddrift.sphere import recast_lon + >>> recast_lon(x, -180) + array([ 179.5 , -179.6016795]) + + Raises + ------ + ValueError + If u and v do not have the same shape. + If the time axis is outside of the valid range ([-1, N-1]). + If lengths of x, y, and time along time_axis are not equal. + If the input coordinate system is not "spherical" or "cartesian". + If the input integration scheme is not "forward", "backward", or "centered" + + See Also + -------- + :func:`velocity_from_position` + """ + # Velocity arrays must have the same shape. + # Although the exception would be raised further down in the function, + # we do the check here for a clearer error message. + if not u.shape == v.shape: + raise ValueError("u and v must have the same shape.") + + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(u.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(x.shape) - 1}])." + ) + + # Input arrays must have the same length along the time axis. + if not u.shape[time_axis] == v.shape[time_axis] == time.shape[time_axis]: + raise ValueError( + f"u, v, and time must have the same length along the time axis " + f"({time_axis})." + ) + + # Swap axes so that we can differentiate along the last axis. + # This is a syntax convenience rather than memory access optimization: + # np.swapaxes returns a view of the array, not a copy, if the input is a + # NumPy array. Otherwise, it returns a copy. For readability, introduce new + # variable names so that we can more easily differentiate between the + # original arrays and those with swapped axes. + u_ = np.swapaxes(u, time_axis, -1) + v_ = np.swapaxes(v, time_axis, -1) + time_ = np.swapaxes(time, time_axis, -1) + + x = np.zeros(u_.shape, dtype=u.dtype) + y = np.zeros(v_.shape, dtype=v.dtype) + + dt = np.diff(time_) + + if integration_scheme.lower() == "forward": + x[..., 1:] = np.cumsum(u_[..., :-1] * dt, axis=-1) + y[..., 1:] = np.cumsum(v_[..., :-1] * dt, axis=-1) + elif integration_scheme.lower() == "backward": + x[..., 1:] = np.cumsum(u_[1:] * dt, axis=-1) + y[..., 1:] = np.cumsum(v_[1:] * dt, axis=-1) + elif integration_scheme.lower() == "centered": + x[..., 1:] = np.cumsum(0.5 * (u_[..., :-1] + u_[..., 1:]) * dt, axis=-1) + y[..., 1:] = np.cumsum(0.5 * (v_[..., :-1] + v_[..., 1:]) * dt, axis=-1) + else: + raise ValueError( + 'integration_scheme must be "forward", "backward", or "centered".' + ) + + if coord_system.lower() == "cartesian": + x += x_origin + y += y_origin + elif coord_system.lower() == "spherical": + dx = np.diff(x) + dy = np.diff(y) + distances = np.sqrt(dx**2 + dy**2) + bearings = np.arctan2(dy, dx) + x[..., 0], y[..., 0] = x_origin, y_origin + for n in range(distances.shape[-1]): + x[..., n + 1], y[..., n + 1] = position_from_distance_and_bearing( + x[..., n], y[..., n], distances[..., n], bearings[..., n] + ) + else: + raise ValueError('coord_system must be "spherical" or "cartesian".') + + return np.swapaxes(x, time_axis, -1), np.swapaxes(y, time_axis, -1)
+ + + +
+[docs] +def velocity_from_position( + x: np.ndarray, + y: np.ndarray, + time: np.ndarray, + coord_system: Optional[str] = "spherical", + difference_scheme: Optional[str] = "forward", + time_axis: Optional[int] = -1, +) -> Tuple[xr.DataArray, xr.DataArray]: + """Compute velocity from arrays of positions and time. + + x and y can be provided as longitude and latitude in degrees if + coord_system == "spherical" (default), or as easting and northing if + coord_system == "cartesian". + + The units of the result are meters per unit of time if + coord_system == "spherical". For example, if the time is provided in the + units of seconds, the resulting velocity is in the units of meters per + second. Otherwise, if coord_system == "cartesian", the units of the + resulting velocity correspond to the units of the input. For example, + if zonal and meridional displacements are in the units of kilometers and + time is in the units of hours, the resulting velocity is in the units of + kilometers per hour. + + x, y, and time can be multi-dimensional arrays. If the time axis, along + which the finite differencing is performed, is not the last one (i.e. + x.shape[-1]), use the time_axis optional argument to specify along which + axis should the differencing be done. x, y, and time must have the same + shape. + + Difference scheme can take one of three values: + + #. "forward" (default): finite difference is evaluated as ``dx[i] = dx[i+1] - dx[i]``; + #. "backward": finite difference is evaluated as ``dx[i] = dx[i] - dx[i-1]``; + #. "centered": finite difference is evaluated as ``dx[i] = (dx[i+1] - dx[i-1]) / 2``. + + Forward and backward schemes are effectively the same except that the + position at which the velocity is evaluated is shifted one element down in + the backward scheme relative to the forward scheme. In the case of a + forward or backward difference scheme, the last or first element of the + velocity, respectively, is extrapolated from its neighboring point. In the + case of a centered difference scheme, the start and end boundary points are + evaluated using the forward and backward difference scheme, respectively. + + Parameters + ---------- + x : array_like + An N-d array of x-positions (longitude in degrees or zonal displacement in any unit) + y : array_like + An N-d array of y-positions (latitude in degrees or meridional displacement in any unit) + time : array_like + An N-d array of times as floating point values (in any unit) + coord_system : str, optional + Coordinate system that x and y arrays are in; possible values are "spherical" (default) or "cartesian". + difference_scheme : str, optional + Difference scheme to use; possible values are "forward", "backward", and "centered". + time_axis : int, optional + Axis along which to differentiate (default is -1) + + Returns + ------- + u : np.ndarray + Zonal velocity + v : np.ndarray + Meridional velocity + + Raises + ------ + ValueError + If x and y do not have the same shape. + If time_axis is outside of the valid range. + If lengths of x, y, and time along time_axis are not equal. + If coord_system is not "spherical" or "cartesian". + If difference_scheme is not "forward", "backward", or "centered". + + Examples + -------- + Simple integration on a sphere, using the forward scheme by default: + + >>> import numpy as np + >>> from clouddrift.kinematics import velocity_from_position + >>> lon = np.array([0., 1., 3., 6.]) + >>> lat = np.array([0., 1., 2., 3.]) + >>> time = np.array([0., 1., 2., 3.]) * 1e5 + >>> u, v = velocity_from_position(lon, lat, time) + >>> u + array([1.11307541, 2.22513331, 3.33515501, 3.33515501]) + >>> v + array([1.11324496, 1.11409224, 1.1167442 , 1.1167442 ]) + + Integration on a Cartesian plane, using the forward scheme by default: + + >>> x = np.array([0., 1., 3., 6.]) + >>> y = np.array([0., 1., 2., 3.]) + >>> time = np.array([0., 1., 2., 3.]) + >>> u, v = velocity_from_position(x, y, time, coord_system="cartesian") + >>> u + array([1., 2., 3., 3.]) + >>> v + array([1., 1., 1., 1.]) + + See Also + -------- + :func:`position_from_velocity` + """ + + # Position arrays must have the same shape. + # Although the exception would be raised further down in the function, + # we do the check here for a clearer error message. + if not x.shape == y.shape: + raise ValueError("x and y arrays must have the same shape.") + + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(x.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(x.shape) - 1}])." + ) + + # Input arrays must have the same length along the time axis. + if not x.shape[time_axis] == y.shape[time_axis] == time.shape[time_axis]: + raise ValueError( + f"x, y, and time must have the same length along the time axis " + f"({time_axis})." + ) + + # Swap axes so that we can differentiate along the last axis. + # This is a syntax convenience rather than memory access optimization: + # np.swapaxes returns a view of the array, not a copy, if the input is a + # NumPy array. Otherwise, it returns a copy. For readability, introduce new + # variable names so that we can more easily differentiate between the + # original arrays and those with swapped axes. + x_ = np.swapaxes(x, time_axis, -1) + y_ = np.swapaxes(y, time_axis, -1) + time_ = np.swapaxes(time, time_axis, -1) + + dx = np.empty(x_.shape) + dy = np.empty(y_.shape) + dt = np.empty(time_.shape) + + # Compute dx, dy, and dt + if difference_scheme == "forward": + # All values except the ending boundary value are computed using the + # 1st order forward differencing. The ending boundary value is + # computed using the 1st order backward difference. + + # Time + dt[..., :-1] = np.diff(time_) + dt[..., -1] = dt[..., -2] + + # Space + if coord_system == "cartesian": + dx[..., :-1] = np.diff(x_) + dx[..., -1] = dx[..., -2] + dy[..., :-1] = np.diff(y_) + dy[..., -1] = dy[..., -2] + + elif coord_system == "spherical": + distances = distance(x_[..., :-1], y_[..., :-1], x_[..., 1:], y_[..., 1:]) + bearings = bearing(x_[..., :-1], y_[..., :-1], x_[..., 1:], y_[..., 1:]) + dx[..., :-1] = distances * np.cos(bearings) + dx[..., -1] = dx[..., -2] + dy[..., :-1] = distances * np.sin(bearings) + dy[..., -1] = dy[..., -2] + + else: + raise ValueError('coord_system must be "spherical" or "cartesian".') + + elif difference_scheme == "backward": + # All values except the starting boundary value are computed using the + # 1st order backward differencing. The starting boundary value is + # computed using the 1st order forward difference. + + # Time + dt[..., 1:] = np.diff(time_) + dt[..., 0] = dt[..., 1] + + # Space + if coord_system == "cartesian": + dx[..., 1:] = np.diff(x_) + dx[..., 0] = dx[..., 1] + dy[..., 1:] = np.diff(y_) + dy[..., 0] = dy[..., 1] + + elif coord_system == "spherical": + distances = distance(x_[..., :-1], y_[..., :-1], x_[..., 1:], y_[..., 1:]) + bearings = bearing(x_[..., :-1], y_[..., :-1], x_[..., 1:], y_[..., 1:]) + dx[..., 1:] = distances * np.cos(bearings) + dx[..., 0] = dx[..., 1] + dy[..., 1:] = distances * np.sin(bearings) + dy[..., 0] = dy[..., 1] + + else: + raise ValueError('coord_system must be "spherical" or "cartesian".') + + elif difference_scheme == "centered": + # Inner values are computed using the 2nd order centered differencing. + # The start and end boundary values are computed using the 1st order + # forward and backward differencing, respectively. + + # Time + dt[..., 1:-1] = (time_[..., 2:] - time_[..., :-2]) / 2 + dt[..., 0] = time_[..., 1] - time_[..., 0] + dt[..., -1] = time_[..., -1] - time_[..., -2] + + # Space + if coord_system == "cartesian": + dx[..., 1:-1] = (x_[..., 2:] - x_[..., :-2]) / 2 + dx[..., 0] = x_[..., 1] - x_[..., 0] + dx[..., -1] = x_[..., -1] - x_[..., -2] + dy[..., 1:-1] = (y_[..., 2:] - y_[..., :-2]) / 2 + dy[..., 0] = y_[..., 1] - y_[..., 0] + dy[..., -1] = y_[..., -1] - y_[..., -2] + + elif coord_system == "spherical": + # Inner values + y1 = (y_[..., :-2] + y_[..., 1:-1]) / 2 + x1 = (x_[..., :-2] + x_[..., 1:-1]) / 2 + y2 = (y_[..., 2:] + y_[..., 1:-1]) / 2 + x2 = (x_[..., 2:] + x_[..., 1:-1]) / 2 + distances = distance(x1, y1, x2, y2) + bearings = bearing(x1, y1, x2, y2) + dx[..., 1:-1] = distances * np.cos(bearings) + dy[..., 1:-1] = distances * np.sin(bearings) + + # Boundary values + distance1 = distance(x_[..., 0], y_[..., 0], x_[..., 1], y_[..., 1]) + bearing1 = bearing(x_[..., 0], y_[..., 0], x_[..., 1], y_[..., 1]) + dx[..., 0] = distance1 * np.cos(bearing1) + dy[..., 0] = distance1 * np.sin(bearing1) + distance2 = distance(x_[..., -2], y_[..., -2], x_[..., -1], y_[..., -1]) + bearing2 = bearing(x_[..., -2], y_[..., -2], x_[..., -1], y_[..., -1]) + dx[..., -1] = distance2 * np.cos(bearing2) + dy[..., -1] = distance2 * np.sin(bearing2) + + else: + raise ValueError('coord_system must be "spherical" or "cartesian".') + + else: + raise ValueError( + 'difference_scheme must be "forward", "backward", or "centered".' + ) + + # This should avoid an array copy when returning the result + dx /= dt + dy /= dt + + return np.swapaxes(dx, time_axis, -1), np.swapaxes(dy, time_axis, -1)
+ + + +
+[docs] +def spin( + u: np.ndarray, + v: np.ndarray, + time: np.ndarray, + difference_scheme: Optional[str] = "forward", + time_axis: Optional[int] = -1, +) -> Union[float, np.ndarray]: + """Compute spin continuously from velocities and times. + + Spin is traditionally (Sawford, 1999; Veneziani et al., 2005) defined as + (<u'dv' - v'du'>) / (2 dt EKE) where u' and v' are eddy-perturbations of the + velocity field, EKE is eddy kinetic energy, dt is the time step, and du' and + dv' are velocity component increments during dt, and < > denotes ensemble + average. + + To allow computing spin based on full velocity fields, this function does + not do any demeaning of the velocity fields. If you need the spin based on + velocity anomalies, ensure to demean the velocity fields before passing + them to this function. This function also returns instantaneous spin values, + so the rank of the result is not reduced relative to the input. + + ``u``, ``v``, and ``time`` can be multi-dimensional arrays. If the time + axis, along which the finite differencing is performed, is not the last one + (i.e. ``u.shape[-1]``), use the time_axis optional argument to specify along + which the spin should be calculated. u, v, and time must either have the + same shape, or time must be a 1-d array with the same length as + ``u.shape[time_axis]``. + + Difference scheme can be one of three values: + + 1. "forward" (default): finite difference is evaluated as ``dx[i] = dx[i+1] - dx[i]``; + 2. "backward": finite difference is evaluated as ``dx[i] = dx[i] - dx[i-1]``; + 3. "centered": finite difference is evaluated as ``dx[i] = (dx[i+1] - dx[i-1]) / 2``. + + Forward and backward schemes are effectively the same except that the + position at which the velocity is evaluated is shifted one element down in + the backward scheme relative to the forward scheme. In the case of a + forward or backward difference scheme, the last or first element of the + velocity, respectively, is extrapolated from its neighboring point. In the + case of a centered difference scheme, the start and end boundary points are + evaluated using the forward and backward difference scheme, respectively. + + Parameters + ---------- + u : np.ndarray + Zonal velocity + v : np.ndarray + Meridional velocity + time : array-like + Time + difference_scheme : str, optional + Difference scheme to use; possible values are "forward", "backward", and "centered". + time_axis : int, optional + Axis along which the time varies (default is -1) + + Returns + ------- + s : float or np.ndarray + Spin + + Raises + ------ + ValueError + If u and v do not have the same shape. + If the time axis is outside of the valid range ([-1, N-1]). + If lengths of u, v, and time along time_axis are not equal. + If difference_scheme is not "forward", "backward", or "centered". + + Examples + -------- + >>> from clouddrift.kinematics import spin + >>> import numpy as np + >>> u = np.array([1., 2., -1., 4.]) + >>> v = np.array([1., 3., -2., 1.]) + >>> time = np.array([0., 1., 2., 3.]) + >>> spin(u, v, time) + array([ 0.5 , -0.07692308, 1.4 , 0.41176471]) + + Use ``difference_scheme`` to specify an alternative finite difference + scheme for the velocity differences: + + >>> spin(u, v, time, difference_scheme="centered") + array([0.5 , 0. , 0.6 , 0.41176471]) + >>> spin(u, v, time, difference_scheme="backward") + array([ 0.5 , 0.07692308, -0.2 , 0.41176471]) + + References + ---------- + * Sawford, B.L., 1999. Rotation of trajectories in Lagrangian stochastic models of turbulent dispersion. Boundary-layer meteorology, 93, pp.411-424. https://doi.org/10.1023/A:1002114132715 + * Veneziani, M., Griffa, A., Garraffo, Z.D. and Chassignet, E.P., 2005. Lagrangian spin parameter and coherent structures from trajectories released in a high-resolution ocean model. Journal of Marine Research, 63(4), pp.753-788. https://elischolar.library.yale.edu/journal_of_marine_research/100/ + """ + if not u.shape == v.shape: + raise ValueError("u and v arrays must have the same shape.") + + if not time.shape == u.shape: + if not time.size == u.shape[time_axis]: + raise ValueError("time must have the same length as u along time_axis.") + + # axis must be in valid range + if time_axis < -1 or time_axis > len(u.shape) - 1: + raise ValueError( + f"axis ({time_axis}) is outside of the valid range ([-1," + f" {len(u.shape) - 1}])." + ) + + # Swap axes so that we can differentiate along the last axis. + # This is a syntax convenience rather than memory access optimization: + # np.swapaxes returns a view of the array, not a copy, if the input is a + # NumPy array. Otherwise, it returns a copy. + u = np.swapaxes(u, time_axis, -1) + v = np.swapaxes(v, time_axis, -1) + time = np.swapaxes(time, time_axis, -1) + + if not time.shape == u.shape: + # time is 1-d array; broadcast to u.shape. + time = np.broadcast_to(time, u.shape) + + du = np.empty(u.shape) + dv = np.empty(v.shape) + dt = np.empty(time.shape) + + if difference_scheme == "forward": + du[..., :-1] = np.diff(u) + du[..., -1] = du[..., -2] + dv[..., :-1] = np.diff(v) + dv[..., -1] = dv[..., -2] + dt[..., :-1] = np.diff(time) + dt[..., -1] = dt[..., -2] + elif difference_scheme == "backward": + du[..., 1:] = np.diff(u) + du[..., 0] = du[..., 1] + dv[..., 1:] = np.diff(v) + dv[..., 0] = dv[..., 1] + dt[..., 1:] = np.diff(time) + dt[..., 0] = dt[..., 1] + elif difference_scheme == "centered": + du[..., 1:-1] = (u[..., 2:] - u[..., :-2]) / 2 + du[..., 0] = u[..., 1] - u[..., 0] + du[..., -1] = u[..., -1] - u[..., -2] + dv[..., 1:-1] = (v[..., 2:] - v[..., :-2]) / 2 + dv[..., 0] = v[..., 1] - v[..., 0] + dv[..., -1] = v[..., -1] - v[..., -2] + dt[..., 1:-1] = (time[..., 2:] - time[..., :-2]) / 2 + dt[..., 0] = time[..., 1] - time[..., 0] + dt[..., -1] = time[..., -1] - time[..., -2] + else: + raise ValueError( + 'difference_scheme must be "forward", "backward", or "centered".' + ) + + # Compute spin + s = (u * dv - v * du) / (2 * dt * kinetic_energy(u, v)) + + return np.swapaxes(s, time_axis, -1)
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/pairs.html b/_modules/clouddrift/pairs.html new file mode 100644 index 00000000..7126019f --- /dev/null +++ b/_modules/clouddrift/pairs.html @@ -0,0 +1,1007 @@ + + + + + + + + + + clouddrift.pairs — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.pairs

+"""
+Functions to analyze pairs of contiguous data segments.
+"""
+from clouddrift import ragged, sphere
+from concurrent.futures import as_completed, ThreadPoolExecutor
+import itertools
+import numpy as np
+import pandas as pd
+import xarray as xr
+from typing import List, Optional, Tuple, Union
+
+array_like = Union[list[float], np.ndarray[float], pd.Series, xr.DataArray]
+
+
+
+[docs] +def chance_pair( + lon1: array_like, + lat1: array_like, + lon2: array_like, + lat2: array_like, + time1: Optional[array_like] = None, + time2: Optional[array_like] = None, + space_distance: Optional[float] = 0, + time_distance: Optional[float] = 0, +): + """Given two sets of longitudes, latitudes, and times arrays, return in pairs + the indices of collocated data points that are within prescribed distances + in space and time. Also known as chance pairs. + + Parameters + ---------- + lon1 : array_like + First array of longitudes in degrees. + lat1 : array_like + First array of latitudes in degrees. + lon2 : array_like + Second array of longitudes in degrees. + lat2 : array_like + Second array of latitudes in degrees. + time1 : array_like, optional + First array of times. + time2 : array_like, optional + Second array of times. + space_distance : float, optional + Maximum allowable space distance in meters for a pair to qualify as chance pair. + If the separation is within this distance, the pair is considered to be + a chance pair. Default is 0, or no distance, i.e. the positions must be + exactly the same. + time_distance : float, optional + Maximum allowable time distance for a pair to qualify as chance pair. + If a separation is within this distance, and a space distance + condition is satisfied, the pair is considered a chance pair. Default is + 0, or no distance, i.e. the times must be exactly the same. + + Returns + ------- + indices1 : np.ndarray[int] + Indices within the first set of arrays that lead to chance pair. + indices2 : np.ndarray[int] + Indices within the second set of arrays that lead to chance pair. + + Examples + -------- + In the following example, we load the GLAD dataset, extract the first + two trajectories, and find between these the array indices that satisfy + the chance pair criteria of 6 km separation distance and no time separation: + + >>> from clouddrift.datasets import glad + >>> from clouddrift.pairs import chance_pair + >>> from clouddrift.ragged import unpack + >>> ds = glad() + >>> lon1 = unpack(ds["longitude"], ds["rowsize"], rows=0).pop() + >>> lat1 = unpack(ds["latitude"], ds["rowsize"], rows=0).pop() + >>> time1 = unpack(ds["time"], ds["rowsize"], rows=0).pop() + >>> lon2 = unpack(ds["longitude"], ds["rowsize"], rows=1).pop() + >>> lat2 = unpack(ds["latitude"], ds["rowsize"], rows=1).pop() + >>> time2 = unpack(ds["time"], ds["rowsize"], rows=1).pop() + >>> i1, i2 = chance_pair(lon1, lat1, lon2, lat2, time1, time2, 6000, np.timedelta64(0)) + >>> i1, i2 + (array([177, 180, 183, 186, 189, 192]), array([166, 169, 172, 175, 178, 181])) + + Check to ensure our collocation in space worked by calculating the distance + between the identified pairs: + + >>> sphere.distance(lon1[i1], lat1[i1], lon2[i2], lat2[i2]) + array([5967.4844, 5403.253 , 5116.9136, 5185.715 , 5467.8555, 5958.4917], + dtype=float32) + + Check the collocation in time: + + >>> time1[i1] - time2[i2] + <xarray.DataArray 'time' (obs: 6)> + array([0, 0, 0, 0, 0, 0], dtype='timedelta64[ns]') + Coordinates: + time (obs) datetime64[ns] 2012-07-21T21:30:00.524160 ... 2012-07-22T0... + Dimensions without coordinates: obs + + Raises + ------ + ValueError + If ``time1`` and ``time2`` are not both provided or both omitted. + """ + if (time1 is None and time2 is not None) or (time1 is not None and time2 is None): + raise ValueError( + "Both time1 and time2 must be provided or both must be omitted." + ) + + time_present = time1 is not None and time2 is not None + + if time_present: + # If time is provided, subset the trajectories to the overlapping times. + overlap1, overlap2 = pair_time_overlap(time1, time2, time_distance) + else: + # Otherwise, initialize the overlap indices to the full length of the + # trajectories. + overlap1 = np.arange(lon1.size) + overlap2 = np.arange(lon2.size) + + # Provided space distance is in meters, but here we convert it to degrees + # for the bounding box overlap check. + space_distance_degrees = np.degrees(space_distance / sphere.EARTH_RADIUS_METERS) + + # Compute the indices for each trajectory where the two trajectories' + # bounding boxes overlap. + bbox_overlap1, bbox_overlap2 = pair_bounding_box_overlap( + lon1[overlap1], + lat1[overlap1], + lon2[overlap2], + lat2[overlap2], + space_distance_degrees, + ) + + # bbox_overlap1 and bbox_overlap2 subset the overlap1 and overlap2 indices. + overlap1 = overlap1[bbox_overlap1] + overlap2 = overlap2[bbox_overlap2] + + # If time is present, first search for collocation in time. + if time_present: + time_separation = pair_time_distance(time1[overlap1], time2[overlap2]) + time_match2, time_match1 = np.where(time_separation <= time_distance) + overlap1 = overlap1[time_match1] + overlap2 = overlap2[time_match2] + + # Now search for collocation in space. + space_separation = pair_space_distance( + lon1[overlap1], lat1[overlap1], lon2[overlap2], lat2[overlap2] + ) + space_overlap = space_separation <= space_distance + if time_present: + time_separation = pair_time_distance(time1[overlap1], time2[overlap2]) + time_overlap = time_separation <= time_distance + match2, match1 = np.where(space_overlap & time_overlap) + else: + match2, match1 = np.where(space_overlap) + + overlap1 = overlap1[match1] + overlap2 = overlap2[match2] + + return overlap1, overlap2
+ + + +
+[docs] +def chance_pairs_from_ragged( + lon: array_like, + lat: array_like, + rowsize: array_like, + space_distance: Optional[float] = 0, + time: Optional[array_like] = None, + time_distance: Optional[float] = 0, +) -> List[Tuple[Tuple[int, int], Tuple[np.ndarray, np.ndarray]]]: + """Return all chance pairs of contiguous trajectories in a ragged array, + and their collocated points in space and (optionally) time, given input + ragged arrays of longitude, latitude, and (optionally) time, and chance + pair criteria as maximum allowable distances in space and time. + + If ``time`` and ``time_distance`` are omitted, the search will be done + only on the spatial criteria, and the result will not include the time + arrays. + + If ``time`` and ``time_distance`` are provided, the search will be done + on both the spatial and temporal criteria, and the result will include the + time arrays. + + Parameters + ---------- + lon : array_like + Array of longitudes in degrees. + lat : array_like + Array of latitudes in degrees. + rowsize : array_like + Array of rowsizes. + space_distance : float, optional + Maximum space distance in meters for the pair to qualify as chance pair. + If the separation is within this distance, the pair is considered to be + a chance pair. Default is 0, or no distance, i.e. the positions must be + exactly the same. + time : array_like, optional + Array of times. + time_distance : float, optional + Maximum time distance allowed for the pair to qualify as chance pair. + If the separation is within this distance, and the space distance + condition is satisfied, the pair is considered a chance pair. Default is + 0, or no distance, i.e. the times must be exactly the same. + + Returns + ------- + pairs : List[Tuple[Tuple[int, int], Tuple[np.ndarray, np.ndarray]]] + List of tuples, each tuple containing a Tuple of integer indices that + corresponds to the trajectory rows in the ragged array, indicating the + pair of trajectories that satisfy the chance pair criteria, and a Tuple + of arrays containing the indices of the collocated points for each + trajectory in the chance pair. + + Examples + -------- + In the following example, we load GLAD dataset as a ragged array dataset, + subset the result to retain the first five trajectories, and finally find + all trajectories that satisfy the chance pair criteria of 12 km separation + distance and no time separation, as well as the indices of the collocated + points for each pair. + + >>> from clouddrift.datasets import glad + >>> from clouddrift.pairs import chance_pairs_from_ragged + >>> from clouddrift.ragged import subset + >>> ds = subset(glad(), {"id": ["CARTHE_001", "CARTHE_002", "CARTHE_003", "CARTHE_004", "CARTHE_005"]}, id_var_name="id") + >>> pairs = chance_pairs_from_ragged( + ds["longitude"].values, + ds["latitude"].values, + ds["rowsize"].values, + space_distance=12000, + time=ds["time"].values, + time_distance=np.timedelta64(0) + ) + [((0, 1), + (array([153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, + 192, 195, 198, 201, 204, 207, 210, 213, 216]), + array([142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, + 181, 184, 187, 190, 193, 196, 199, 202, 205]))), + ((3, 4), + (array([141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, + 180, 183]), + array([136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, + 175, 178])))] + + The result above shows that 2 chance pairs were found. + + Raises + ------ + ValueError + If ``rowsize`` has fewer than two elements. + """ + if len(rowsize) < 2: + raise ValueError("rowsize must have at least two elements.") + pairs = list(itertools.combinations(np.arange(rowsize.size), 2)) + i = ragged.rowsize_to_index(rowsize) + results = [] + with ThreadPoolExecutor() as executor: + if time is None: + futures = [ + executor.submit( + chance_pair, + lon[i[j] : i[j + 1]], + lat[i[j] : i[j + 1]], + lon[i[k] : i[k + 1]], + lat[i[k] : i[k + 1]], + space_distance=space_distance, + ) + for j, k in pairs + ] + else: + futures = [ + executor.submit( + chance_pair, + lon[i[j] : i[j + 1]], + lat[i[j] : i[j + 1]], + lon[i[k] : i[k + 1]], + lat[i[k] : i[k + 1]], + time[i[j] : i[j + 1]], + time[i[k] : i[k + 1]], + space_distance, + time_distance, + ) + for j, k in pairs + ] + for future in as_completed(futures): + res = future.result() + # chance_pair function returns empty arrays if no chance criteria + # are satisfied. We only want to keep pairs that satisfy the + # criteria. chance_pair returns a tuple of arrays that are always + # the same size, so we only need to check the length of the first + # array. + if res[0].size > 0: + results.append((pairs[futures.index(future)], res)) + return results
+ + + +
+[docs] +def pair_bounding_box_overlap( + lon1: array_like, + lat1: array_like, + lon2: array_like, + lat2: array_like, + distance: Optional[float] = 0, +) -> Tuple[np.ndarray[bool], np.ndarray[bool]]: + """Given two arrays of longitudes and latitudes, return boolean masks for + their overlapping bounding boxes. + + Parameters + ---------- + lon1 : array_like + First array of longitudes in degrees. + lat1 : array_like + First array of latitudes in degrees. + lon2 : array_like + Second array of longitudes in degrees. + lat2 : array_like + Second array of latitudes in degrees. + distance : float, optional + Distance in degrees for the overlap. If the overlap is within this + distance, the bounding boxes are considered to overlap. Default is 0. + + Returns + ------- + overlap1 : np.ndarray[int] + Indices ``lon1`` and ``lat1`` where their bounding box overlaps with + that of ``lon2`` and ``lat2``. + overlap2 : np.ndarray[int] + Indices ``lon2`` and ``lat2`` where their bounding box overlaps with + that of ``lon1`` and ``lat1``. + + Examples + -------- + >>> lon1 = [0, 0, 1, 1] + >>> lat1 = [0, 0, 1, 1] + >>> lon2 = [1, 1, 2, 2] + >>> lat2 = [1, 1, 2, 2] + >>> pair_bounding_box_overlap(lon1, lat1, lon2, lat2, 0.5) + (array([2, 3]), array([0, 1])) + """ + # First get the bounding box of each trajectory. + # We unwrap the longitudes before computing min/max because we want to + # consider trajectories that cross the dateline. + lon1_min, lon1_max = np.min(np.unwrap(lon1, period=360)), np.max( + np.unwrap(lon1, period=360) + ) + lat1_min, lat1_max = np.min(lat1), np.max(lat1) + lon2_min, lon2_max = np.min(np.unwrap(lon2, period=360)), np.max( + np.unwrap(lon2, period=360) + ) + lat2_min, lat2_max = np.min(lat2), np.max(lat2) + + bounding_boxes_overlap = ( + (lon1_min <= lon2_max + distance) + & (lon1_max >= lon2_min - distance) + & (lat1_min <= lat2_max + distance) + & (lat1_max >= lat2_min - distance) + ) + + # Now check if the trajectories overlap within the bounding box. + if bounding_boxes_overlap: + overlap_start = ( + max(lon1_min, lon2_min) - distance, # West + max(lat1_min, lat2_min) - distance, # South + ) + overlap_end = ( + min(lon1_max, lon2_max) + distance, # East + min(lat1_max, lat2_max) + distance, # North + ) + overlap1 = ( + (lon1 >= overlap_start[0]) + & (lon1 <= overlap_end[0]) + & (lat1 >= overlap_start[1]) + & (lat1 <= overlap_end[1]) + ) + overlap2 = ( + (lon2 >= overlap_start[0]) + & (lon2 <= overlap_end[0]) + & (lat2 >= overlap_start[1]) + & (lat2 <= overlap_end[1]) + ) + return np.where(overlap1)[0], np.where(overlap2)[0] + else: + return np.array([], dtype=int), np.array([], dtype=int)
+ + + +
+[docs] +def pair_space_distance( + lon1: array_like, + lat1: array_like, + lon2: array_like, + lat2: array_like, +) -> np.ndarray[float]: + """Given two arrays of longitudes and latitudes, return the distance + on a sphere between all pairs of points. + + Parameters + ---------- + lon1 : array_like + First array of longitudes in degrees. + lat1 : array_like + First array of latitudes in degrees. + lon2 : array_like + Second array of longitudes in degrees. + lat2 : array_like + Second array of latitudes in degrees. + + Returns + ------- + distance : np.ndarray[float] + Array of distances between all pairs of points. + + Examples + -------- + >>> lon1 = [0, 0, 1, 1] + >>> lat1 = [0, 0, 1, 1] + >>> lon2 = [1, 1, 2, 2] + >>> lat2 = [1, 1, 2, 2] + >>> pair_space_distance(lon1, lat1, lon2, lat2) + array([[157424.62387233, 157424.62387233, 0. , + 0. ], + [157424.62387233, 157424.62387233, 0. , + 0. ], + [314825.26360286, 314825.26360286, 157400.64794884, + 157400.64794884], + [314825.26360286, 314825.26360286, 157400.64794884, + 157400.64794884]]) + """ + # Create longitude and latitude matrices from arrays to compute distance + lon1_2d, lon2_2d = np.meshgrid(lon1, lon2, copy=False) + lat1_2d, lat2_2d = np.meshgrid(lat1, lat2, copy=False) + + # Compute distance between all pairs of points + distance = sphere.distance(lon1_2d, lat1_2d, lon2_2d, lat2_2d) + + return distance
+ + + +
+[docs] +def pair_time_distance( + time1: array_like, + time2: array_like, +) -> np.ndarray[float]: + """Given two arrays of times (or any other monotonically increasing + quantity), return the temporal distance between all pairs of times. + + Parameters + ---------- + time1 : array_like + First array of times. + time2 : array_like + Second array of times. + + Returns + ------- + distance : np.ndarray[float] + Array of distances between all pairs of times. + + Examples + -------- + >>> time1 = np.arange(4) + >>> time2 = np.arange(2, 6) + >>> pair_time_distance(time1, time2) + array([[2, 1, 0, 1], + [3, 2, 1, 0], + [4, 3, 2, 1], + [5, 4, 3, 2]]) + """ + # Create time matrices from arrays to compute distance + time1_2d, time2_2d = np.meshgrid(time1, time2, copy=False) + + # Compute distance between all pairs of times + distance = np.abs(time1_2d - time2_2d) + + return distance
+ + + +
+[docs] +def pair_time_overlap( + time1: array_like, + time2: array_like, + distance: Optional[float] = 0, +) -> Tuple[np.ndarray[int], np.ndarray[int]]: + """Given two arrays of times (or any other monotonically increasing + quantity), return indices where the times are within a prescribed distance. + + Although higher-level array containers like xarray and pandas are supported + for input arrays, this function is an order of magnitude faster when passing + in numpy arrays. + + Parameters + ---------- + time1 : array_like + First array of times. + time2 : array_like + Second array of times. + distance : float + Maximum distance within which the values of ``time1`` and ``time2`` are + considered to overlap. Default is 0, or, the values must be exactly the + same. + + Returns + ------- + overlap1 : np.ndarray[int] + Indices of ``time1`` where its time overlaps with ``time2``. + overlap2 : np.ndarray[int] + Indices of ``time2`` where its time overlaps with ``time1``. + + Examples + -------- + >>> time1 = np.arange(4) + >>> time2 = np.arange(2, 6) + >>> pair_time_overlap(time1, time2) + (array([2, 3]), array([0, 1])) + + >>> pair_time_overlap(time1, time2, 1) + (array([1, 2, 3]), array([0, 1, 2])) + """ + time1_min, time1_max = np.min(time1), np.max(time1) + time2_min, time2_max = np.min(time2), np.max(time2) + overlap_start = max(time1_min, time2_min) - distance + overlap_end = min(time1_max, time2_max) + distance + overlap1 = np.where((time1 >= overlap_start) & (time1 <= overlap_end))[0] + overlap2 = np.where((time2 >= overlap_start) & (time2 <= overlap_end))[0] + return overlap1, overlap2
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/plotting.html b/_modules/clouddrift/plotting.html new file mode 100644 index 00000000..b89314c8 --- /dev/null +++ b/_modules/clouddrift/plotting.html @@ -0,0 +1,693 @@ + + + + + + + + + + clouddrift.plotting — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.plotting

+"""
+This module provides a function to easily and efficiently plot trajectories stored in a ragged array.
+"""
+
+from clouddrift.ragged import segment, rowsize_to_index
+import numpy as np
+import pandas as pd
+from typing import Optional, Union
+import xarray as xr
+import pandas as pd
+from typing import Optional, Union
+from clouddrift.ragged import segment, rowsize_to_index
+
+
+
+[docs] +def plot_ragged( + ax, + longitude: Union[list, np.ndarray, pd.Series, xr.DataArray], + latitude: Union[list, np.ndarray, pd.Series, xr.DataArray], + rowsize: Union[list, np.ndarray, pd.Series, xr.DataArray], + *args, + colors: Optional[Union[list, np.ndarray, pd.Series, xr.DataArray]] = None, + tolerance: Optional[Union[float, int]] = 180, + **kwargs, +): + """Plot trajectories from a ragged array dataset on a Matplotlib Axes + or a Cartopy GeoAxes object ``ax``. + + This function wraps Matplotlib's ``plot`` function (``plt.plot``) and + ``LineCollection`` (``matplotlib.collections``) to efficiently plot + trajectories from a ragged array dataset. + + Parameters + ---------- + ax: matplotlib.axes.Axes or cartopy.mpl.geoaxes.GeoAxes + Axis to plot on. + longitude : array-like + Longitude sequence. Unidimensional array input. + latitude : array-like + Latitude sequence. Unidimensional array input. + rowsize : list + List of integers specifying the number of data points in each row. + *args : tuple + Additional arguments to pass to ``ax.plot``. + colors : array-like + Colors to use for plotting. If colors is the same shape as longitude and latitude, + the trajectories are splitted into segments and each segment is colored according + to the corresponding color value. If colors is the same shape as rowsize, the + trajectories are uniformly colored according to the corresponding color value. + tolerance : float + Longitude tolerance gap between data points (in degrees) for segmenting trajectories. + For periodic domains, the tolerance parameter should be set to the maximum allowed gap + between data points. Defaults to 180. + **kwargs : dict + Additional keyword arguments to pass to ``ax.plot``. + + Returns + ------- + list of matplotlib.lines.Line2D or matplotlib.collections.LineCollection + The plotted lines or line collection. Can be used to set a colorbar + after plotting or extract information from the lines. + + Examples + -------- + + Plot the first 100 trajectories from the gdp1h dataset, assigning + a different color to each trajectory: + + >>> from clouddrift import datasets + >>> import matplotlib.pyplot as plt + >>> ds = datasets.gdp1h() + >>> ds = subset(ds, {"ID": ds.ID[:100].values}).load() + >>> fig = plt.figure() + >>> ax = fig.add_subplot(1, 1, 1) + + >>> plot_ragged( + >>> ax, + >>> ds.lon, + >>> ds.lat, + >>> ds.rowsize, + >>> colors=np.arange(len(ds.rowsize)) + >>> ) + + To plot the same trajectories, but assigning a different color to each + observation and specifying a colormap: + + >>> fig = plt.figure() + >>> ax = fig.add_subplot(1, 1, 1) + >>> time = [v.astype(np.int64) / 86400 / 1e9 for v in ds.time.values] + >>> lc = plot_ragged( + >>> ax, + >>> ds.lon, + >>> ds.lat, + >>> ds.rowsize, + >>> colors=np.floor(time), + >>> cmap="inferno" + >>> ) + >>> fig.colorbar(lc[0]) + >>> ax.set_xlim([-180, 180]) + >>> ax.set_ylim([-90, 90]) + + Finally, to plot the same trajectories, but using a cartopy + projection: + + >>> import cartopy.crs as ccrs + >>> fig = plt.figure() + >>> ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mollweide()) + >>> time = [v.astype(np.int64) / 86400 / 1e9 for v in ds.time.values] + >>> lc = plot_ragged( + >>> ax, + >>> ds.lon, + >>> ds.lat, + >>> ds.rowsize, + >>> colors=np.arange(len(ds.rowsize)), + >>> transform=ccrs.PlateCarree(), + >>> cmap=cmocean.cm.ice, + >>> ) + + Raises + ------ + ValueError + If longitude and latitude arrays do not have the same shape. + If colors do not have the same shape as longitude and latitude arrays or rowsize. + If ax is not a matplotlib Axes or GeoAxes object. + If ax is a GeoAxes object and the transform keyword argument is not provided. + + ImportError + If matplotlib is not installed. + If the axis is a GeoAxes object and cartopy is not installed. + """ + + # optional dependency + try: + import matplotlib.pyplot as plt + import matplotlib.colors as mcolors + from matplotlib.collections import LineCollection + from matplotlib import cm + except ImportError: + raise ImportError("missing optional dependency 'matplotlib'") + + if hasattr(ax, "coastlines"): # check if GeoAxes without cartopy + try: + from cartopy.mpl.geoaxes import GeoAxes + + if isinstance(ax, GeoAxes) and not kwargs.get("transform"): + raise ValueError( + "For GeoAxes, the transform keyword argument must be provided." + ) + except ImportError: + raise ImportError("missing optional dependency 'cartopy'") + elif not isinstance(ax, plt.Axes): + raise ValueError("ax must be either: plt.Axes or GeoAxes.") + + if np.sum(rowsize) != len(longitude): + raise ValueError("The sum of rowsize must equal the length of lon and lat.") + + if len(longitude) != len(latitude): + raise ValueError("lon and lat must have the same length.") + + if colors is None: + colors = np.arange(len(rowsize)) + elif colors is not None and (len(colors) not in [len(longitude), len(rowsize)]): + raise ValueError("shape colors must match the shape of lon/lat or rowsize.") + + # define a colormap + cmap = kwargs.pop("cmap", cm.viridis) + + # define a normalization obtain uniform colors + # for the sequence of lines or LineCollection + norm = kwargs.pop( + "norm", mcolors.Normalize(vmin=np.nanmin(colors), vmax=np.nanmax(colors)) + ) + + mpl_plot = True if colors is None or len(colors) == len(rowsize) else False + traj_idx = rowsize_to_index(rowsize) + + lines = [] + for i in range(len(rowsize)): + lon_i, lat_i = ( + longitude[traj_idx[i] : traj_idx[i + 1]], + latitude[traj_idx[i] : traj_idx[i + 1]], + ) + + start = 0 + for length in segment(lon_i, tolerance, rowsize=segment(lon_i, -tolerance)): + end = start + length + + if mpl_plot: + line = ax.plot( + lon_i[start:end], + lat_i[start:end], + c=cmap(norm(colors[i])) if colors is not None else None, + *args, + **kwargs, + ) + else: + colors_i = colors[traj_idx[i] : traj_idx[i + 1]] + segments = np.column_stack( + [ + lon_i[start : end - 1], + lat_i[start : end - 1], + lon_i[start + 1 : end], + lat_i[start + 1 : end], + ] + ).reshape(-1, 2, 2) + line = LineCollection(segments, cmap=cmap, norm=norm, *args, **kwargs) + line.set_array( + # color of a segment is the average of its two data points + np.convolve(colors_i[start:end], [0.5, 0.5], mode="valid") + ) + ax.add_collection(line) + + start = end + lines.append(line) + + # set axis limits + ax.set_xlim([np.min(longitude), np.max(longitude)]) + ax.set_ylim([np.min(latitude), np.max(latitude)]) + + return lines
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/ragged.html b/_modules/clouddrift/ragged.html new file mode 100644 index 00000000..5c2f36f4 --- /dev/null +++ b/_modules/clouddrift/ragged.html @@ -0,0 +1,1341 @@ + + + + + + + + + + clouddrift.ragged — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.ragged

+"""
+Transformational and inquiry functions for ragged arrays.
+"""
+
+import numpy as np
+from typing import Tuple, Union, Iterable, Callable
+import xarray as xr
+import pandas as pd
+from concurrent import futures
+from datetime import timedelta
+import warnings
+
+
+
+[docs] +def apply_ragged( + func: callable, + arrays: Union[list[Union[np.ndarray, xr.DataArray]], np.ndarray, xr.DataArray], + rowsize: Union[list[int], np.ndarray[int], xr.DataArray], + *args: tuple, + rows: Union[int, Iterable[int]] = None, + axis: int = 0, + executor: futures.Executor = futures.ThreadPoolExecutor(max_workers=None), + **kwargs: dict, +) -> Union[tuple[np.ndarray], np.ndarray]: + """Apply a function to a ragged array. + + The function ``func`` will be applied to each contiguous row of ``arrays`` as + indicated by row sizes ``rowsize``. The output of ``func`` will be + concatenated into a single ragged array. + + You can pass ``arrays`` as NumPy arrays or xarray DataArrays, however, + the result will always be a NumPy array. Passing ``rows`` as an integer or + a sequence of integers will make ``apply_ragged`` process and return only + those specific rows, and otherwise, all rows in the input ragged array will + be processed. Further, you can use the ``axis`` parameter to specify the + ragged axis of the input array(s) (default is 0). + + By default this function uses ``concurrent.futures.ThreadPoolExecutor`` to + run ``func`` in multiple threads. The number of threads can be controlled by + passing the ``max_workers`` argument to the executor instance passed to + ``apply_ragged``. Alternatively, you can pass the ``concurrent.futures.ProcessPoolExecutor`` + instance to use processes instead. Passing alternative (3rd party library) + concurrent executors may work if they follow the same executor interface as + that of ``concurrent.futures``, however this has not been tested yet. + + Parameters + ---------- + func : callable + Function to apply to each row of each ragged array in ``arrays``. + arrays : list[np.ndarray] or np.ndarray or xr.DataArray + An array or a list of arrays to apply ``func`` to. + rowsize : list[int] or np.ndarray[int] or xr.DataArray[int] + List of integers specifying the number of data points in each row. + *args : tuple + Additional arguments to pass to ``func``. + rows : int or Iterable[int], optional + The row(s) of the ragged array to apply ``func`` to. If ``rows`` is + ``None`` (default), then ``func`` will be applied to all rows. + axis : int, optional + The ragged axis of the input arrays. Default is 0. + executor : concurrent.futures.Executor, optional + Executor to use for concurrent execution. Default is ``ThreadPoolExecutor`` + with the default number of ``max_workers``. + Another supported option is ``ProcessPoolExecutor``. + **kwargs : dict + Additional keyword arguments to pass to ``func``. + + Returns + ------- + out : tuple[np.ndarray] or np.ndarray + Output array(s) from ``func``. + + Examples + -------- + + Using ``velocity_from_position`` with ``apply_ragged``, calculate the velocities of + multiple particles, the coordinates of which are found in the ragged arrays x, y, and t + that share row sizes 2, 3, and 4: + + >>> rowsize = [2, 3, 4] + >>> x = np.array([1, 2, 10, 12, 14, 30, 33, 36, 39]) + >>> y = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]) + >>> t = np.array([1, 2, 1, 2, 3, 1, 2, 3, 4]) + >>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, coord_system="cartesian") + array([1., 1., 2., 2., 2., 3., 3., 3., 3.]), + array([1., 1., 1., 1., 1., 1., 1., 1., 1.])) + + To apply ``func`` to only a subset of rows, use the ``rows`` argument: + + >>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, rows=0, coord_system="cartesian") + array([1., 1.]), + array([1., 1.])) + >>> u1, v1 = apply_ragged(velocity_from_position, [x, y, t], rowsize, rows=[0, 1], coord_system="cartesian") + array([1., 1., 2., 2., 2.]), + array([1., 1., 1., 1., 1.])) + + Raises + ------ + ValueError + If the sum of ``rowsize`` does not equal the length of ``arrays``. + IndexError + If empty ``arrays``. + """ + # make sure the arrays is iterable + if type(arrays) not in [list, tuple]: + arrays = [arrays] + # validate rowsize + for arr in arrays: + if not np.sum(rowsize) == arr.shape[axis]: + raise ValueError("The sum of rowsize must equal the length of arr.") + + # split the array(s) into trajectories + arrays = [unpack(np.array(arr), rowsize, rows, axis) for arr in arrays] + iter = [[arrays[i][j] for i in range(len(arrays))] for j in range(len(arrays[0]))] + + # parallel execution + res = [executor.submit(func, *x, *args, **kwargs) for x in iter] + res = [r.result() for r in res] + + # Concatenate the outputs. + + # The following wraps items in a list if they are not already iterable. + res = [item if isinstance(item, Iterable) else [item] for item in res] + + # np.concatenate can concatenate along non-zero axis iff the length of + # arrays to be concatenated is > 1. If the length is 1, for example in the + # case of func that reduces over the non-ragged axis, we can only + # concatenate along axis 0. + if isinstance(res[0], tuple): # more than 1 parameter + outputs = [] + for i in range(len(res[0])): # iterate over each result variable + # If we have multiple outputs and func is a reduction function, + # we now here have a list of scalars. We need to wrap them in a + # list to concatenate them. + result = [r[i] if isinstance(r[i], Iterable) else [r[i]] for r in res] + if len(result[0]) > 1: + # Arrays to concatenate are longer than 1 element, so we can + # concatenate along the non-zero axis. + outputs.append(np.concatenate(result, axis=axis)) + else: + # Arrays to concatenate are 1 element long, so we can only + # concatenate along axis 0. + outputs.append(np.concatenate(result)) + return tuple(outputs) + else: + if len(res[0]) > 1: + # Arrays to concatenate are longer than 1 element, so we can + # concatenate along the non-zero axis. + return np.concatenate(res, axis=axis) + else: + # Arrays to concatenate are 1 element long, so we can only + # concatenate along axis 0. + return np.concatenate(res)
+ + + +
+[docs] +def chunk( + x: Union[list, np.ndarray, xr.DataArray, pd.Series], + length: int, + overlap: int = 0, + align: str = "start", +) -> np.ndarray: + """Divide an array ``x`` into equal chunks of length ``length``. The result + is a 2-dimensional NumPy array of shape ``(num_chunks, length)``. The resulting + number of chunks is determined based on the length of ``x``, ``length``, + and ``overlap``. + + ``chunk`` can be combined with :func:`apply_ragged` to chunk a ragged array. + + Parameters + ---------- + x : list or array-like + Array to divide into chunks. + length : int + The length of each chunk. + overlap : int, optional + The number of overlapping array elements across chunks. The default is 0. + Must be smaller than ``length``. For example, if ``length`` is 4 and + ``overlap`` is 2, the chunks of ``[0, 1, 2, 3, 4, 5]`` will be + ``np.array([[0, 1, 2, 3], [2, 3, 4, 5]])``. Negative overlap can be used + to offset chunks by some number of elements. For example, if ``length`` + is 2 and ``overlap`` is -1, the chunks of ``[0, 1, 2, 3, 4, 5]`` will + be ``np.array([[0, 1], [3, 4]])``. + align : str, optional ["start", "middle", "end"] + If the remainder of the length of ``x`` divided by the chunk ``length`` is a number + N different from zero, this parameter controls which part of the array will be kept + into the chunks. If ``align="start"``, the elements at the beginning of the array + will be part of the chunks and N points are discarded at the end. If `align="middle"`, + floor(N/2) and ceil(N/2) elements will be discarded from the beginning and the end + of the array, respectively. If ``align="end"``, the elements at the end of the array + will be kept, and the `N` first elements are discarded. The default is "start". + + Returns + ------- + np.ndarray + 2-dimensional array of shape ``(num_chunks, length)``. + + Examples + -------- + + Chunk a simple list; this discards the end elements that exceed the last chunk: + + >>> chunk([1, 2, 3, 4, 5], 2) + array([[1, 2], + [3, 4]]) + + To discard the starting elements of the array instead, use ``align="end"``: + + >>> chunk([1, 2, 3, 4, 5], 2, align="end") + array([[2, 3], + [4, 5]]) + + To center the chunks by discarding both ends of the array, use ``align="middle"``: + + >>> chunk([1, 2, 3, 4, 5, 6, 7, 8], 3, align="middle") + array([[2, 3, 4], + [5, 6, 7]]) + + Specify ``overlap`` to get overlapping chunks: + + >>> chunk([1, 2, 3, 4, 5], 2, overlap=1) + array([[1, 2], + [2, 3], + [3, 4], + [4, 5]]) + + Use ``apply_ragged`` to chunk a ragged array by providing the row sizes; + notice that you must pass the array to chunk as an array-like, not a list: + + >>> x = np.array([1, 2, 3, 4, 5]) + >>> rowsize = [2, 1, 2] + >>> apply_ragged(chunk, x, rowsize, 2) + array([[1, 2], + [4, 5]]) + + Raises + ------ + ValueError + If ``length < 0``. + ValueError + If ``align not in ["start", "middle", "end"]``. + ZeroDivisionError + if ``length == 0``. + """ + num_chunks = (len(x) - length) // (length - overlap) + 1 if len(x) >= length else 0 + remainder = len(x) - num_chunks * length + (num_chunks - 1) * overlap + res = np.empty((num_chunks, length), dtype=np.array(x).dtype) + + if align == "start": + start = 0 + elif align == "middle": + start = remainder // 2 + elif align == "end": + start = remainder + else: + raise ValueError("align must be one of 'start', 'middle', or 'end'.") + + for n in range(num_chunks): + end = start + length + res[n] = x[start:end] + start = end - overlap + + return res
+ + + +
+[docs] +def prune( + ragged: Union[list, np.ndarray, pd.Series, xr.DataArray], + rowsize: Union[list, np.ndarray, pd.Series, xr.DataArray], + min_rowsize: float, +) -> Tuple[np.ndarray, np.ndarray]: + """Within a ragged array, removes arrays less than a specified row size. + + Parameters + ---------- + ragged : np.ndarray or pd.Series or xr.DataArray + A ragged array. + rowsize : list or np.ndarray[int] or pd.Series or xr.DataArray[int] + The size of each row in the input ragged array. + min_rowsize : + The minimum row size that will be kept. + + Returns + ------- + tuple[np.ndarray, np.ndarray] + A tuple of ragged array and size of each row. + + Examples + -------- + >>> prune(np.array([1, 2, 3, 0, -1, -2]), np.array([3, 1, 2]),2) + (array([1, 2, 3, -1, -2]), array([3, 2])) + + Raises + ------ + ValueError + If the sum of ``rowsize`` does not equal the length of ``arrays``. + IndexError + If empty ``ragged``. + + See Also + -------- + :func:`segment`, `chunk` + """ + + ragged = apply_ragged( + lambda x, min_len: x if len(x) >= min_len else np.empty(0, dtype=x.dtype), + np.array(ragged), + rowsize, + min_len=min_rowsize, + ) + rowsize = apply_ragged( + lambda x, min_len: x if x >= min_len else np.empty(0, dtype=x.dtype), + np.array(rowsize), + np.ones_like(rowsize), + min_len=min_rowsize, + ) + + return ragged, rowsize
+ + + +
+[docs] +def ragged_to_regular( + ragged: Union[np.ndarray, pd.Series, xr.DataArray], + rowsize: Union[list, np.ndarray, pd.Series, xr.DataArray], + fill_value: float = np.nan, +) -> np.ndarray: + """Convert a ragged array to a two-dimensional array such that each contiguous segment + of a ragged array is a row in the two-dimensional array. Each row of the two-dimensional + array is padded with NaNs as needed. The length of the first dimension of the output + array is the length of ``rowsize``. The length of the second dimension is the maximum + element of ``rowsize``. + + Note: Although this function accepts parameters of type ``xarray.DataArray``, + passing NumPy arrays is recommended for performance reasons. + + Parameters + ---------- + ragged : np.ndarray or pd.Series or xr.DataArray + A ragged array. + rowsize : list or np.ndarray[int] or pd.Series or xr.DataArray[int] + The size of each row in the ragged array. + fill_value : float, optional + Fill value to use for the trailing elements of each row of the resulting + regular array. + + Returns + ------- + np.ndarray + A two-dimensional array. + + Examples + -------- + By default, the fill value used is NaN: + + >>> ragged_to_regular(np.array([1, 2, 3, 4, 5]), np.array([2, 1, 2])) + array([[ 1., 2.], + [ 3., nan], + [ 4., 5.]]) + + You can specify an alternative fill value: + + >>> ragged_to_regular(np.array([1, 2, 3, 4, 5]), np.array([2, 1, 2]), fill_value=999) + array([[ 1., 2.], + [ 3., -999.], + [ 4., 5.]]) + + See Also + -------- + :func:`regular_to_ragged` + """ + res = fill_value * np.ones((len(rowsize), int(max(rowsize))), dtype=ragged.dtype) + unpacked = unpack(ragged, rowsize) + for n in range(len(rowsize)): + res[n, : int(rowsize[n])] = unpacked[n] + return res
+ + + +
+[docs] +def regular_to_ragged( + array: np.ndarray, fill_value: float = np.nan +) -> tuple[np.ndarray, np.ndarray]: + """Convert a two-dimensional array to a ragged array. Fill values in the input array are + excluded from the output ragged array. + + Parameters + ---------- + array : np.ndarray + A two-dimensional array. + fill_value : float, optional + Fill value used to determine the bounds of contiguous segments. + + Returns + ------- + tuple[np.ndarray, np.ndarray] + A tuple of the ragged array and the size of each row. + + Examples + -------- + By default, NaN values found in the input regular array are excluded from + the output ragged array: + + >>> regular_to_ragged(np.array([[1, 2], [3, np.nan], [4, 5]])) + (array([1., 2., 3., 4., 5.]), array([2, 1, 2])) + + Alternatively, a different fill value can be specified: + + >>> regular_to_ragged(np.array([[1, 2], [3, -999], [4, 5]]), fill_value=-999) + (array([1., 2., 3., 4., 5.]), array([2, 1, 2])) + + See Also + -------- + :func:`ragged_to_regular` + """ + if np.isnan(fill_value): + valid = ~np.isnan(array) + else: + valid = array != fill_value + return array[valid], np.sum(valid, axis=1)
+ + + +
+[docs] +def rowsize_to_index(rowsize: Union[list, np.ndarray, xr.DataArray]) -> np.ndarray: + """Convert a list of row sizes to a list of indices. + + This function is typically used to obtain the indices of data rows organized + in a ragged array. + + Parameters + ---------- + rowsize : list or np.ndarray or xr.DataArray + A list of row sizes. + + Returns + ------- + np.ndarray + A list of indices. + + Examples + -------- + To obtain the indices within a ragged array of three consecutive rows of sizes 100, 202, and 53: + + >>> rowsize_to_index([100, 202, 53]) + array([0, 100, 302, 355]) + """ + return np.cumsum(np.insert(np.array(rowsize), 0, 0))
+ + + +
+[docs] +def segment( + x: np.ndarray, + tolerance: Union[float, np.timedelta64, timedelta, pd.Timedelta], + rowsize: np.ndarray[int] = None, +) -> np.ndarray[int]: + """Divide an array into segments based on a tolerance value. + + Parameters + ---------- + x : list, np.ndarray, or xr.DataArray + An array to divide into segment. + tolerance : float, np.timedelta64, timedelta, pd.Timedelta + The maximum signed difference between consecutive points in a segment. + The array x will be segmented wherever differences exceed the tolerance. + rowsize : np.ndarray[int], optional + The size of rows if x is originally a ragged array. If present, x will be + divided both by gaps that exceed the tolerance, and by the original rows + of the ragged array. + + Returns + ------- + np.ndarray[int] + An array of row sizes that divides the input array into segments. + + Examples + -------- + The simplest use of ``segment`` is to provide a tolerance value that is + used to divide an array into segments: + + >>> x = [0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4] + >>> segment(x, 0.5) + array([1, 3, 2, 4, 1]) + + If the array is already previously segmented (e.g. multiple rows in + a ragged array), then the ``rowsize`` argument can be used to preserve + the original segments: + + >>> x = [0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4] + >>> rowsize = [3, 2, 6] + >>> segment(x, 0.5, rowsize) + array([1, 2, 1, 1, 1, 4, 1]) + + The tolerance can also be negative. In this case, the input array is + segmented where the negative difference exceeds the negative + value of the tolerance, i.e. where ``x[n+1] - x[n] < -tolerance``: + + >>> x = [0, 1, 2, 0, 1, 2] + >>> segment(x, -0.5) + array([3, 3]) + + To segment an array for both positive and negative gaps, invoke the function + twice, once for a positive tolerance and once for a negative tolerance. + The result of the first invocation can be passed as the ``rowsize`` argument + to the first ``segment`` invocation: + + >>> x = [1, 1, 2, 2, 1, 1, 2, 2] + >>> segment(x, 0.5, rowsize=segment(x, -0.5)) + array([2, 2, 2, 2]) + + If the input array contains time objects, the tolerance must be a time interval: + + >>> x = np.array([np.datetime64("2023-01-01"), np.datetime64("2023-01-02"), + np.datetime64("2023-01-03"), np.datetime64("2023-02-01"), + np.datetime64("2023-02-02")]) + >>> segment(x, np.timedelta64(1, "D")) + np.array([3, 2]) + """ + + # for compatibility with datetime list or np.timedelta64 arrays + if type(tolerance) in [np.timedelta64, timedelta]: + tolerance = pd.Timedelta(tolerance) + + if type(tolerance) == pd.Timedelta: + positive_tol = tolerance >= pd.Timedelta("0 seconds") + else: + positive_tol = tolerance >= 0 + + if rowsize is None: + if positive_tol: + exceeds_tolerance = np.diff(x) > tolerance + else: + exceeds_tolerance = np.diff(x) < tolerance + segment_sizes = np.diff(np.insert(np.where(exceeds_tolerance)[0] + 1, 0, 0)) + segment_sizes = np.append(segment_sizes, len(x) - np.sum(segment_sizes)) + return segment_sizes + else: + if not np.sum(rowsize) == len(x): + raise ValueError("The sum of rowsize must equal the length of x.") + segment_sizes = [] + start = 0 + for r in rowsize: + end = start + int(r) + segment_sizes.append(segment(x[start:end], tolerance)) + start = end + return np.concatenate(segment_sizes)
+ + + +
+[docs] +def subset( + ds: xr.Dataset, + criteria: dict, + id_var_name: str = "id", + rowsize_var_name: str = "rowsize", + traj_dim_name: str = "traj", + obs_dim_name: str = "obs", + full_trajectories=False, +) -> xr.Dataset: + """Subset a ragged array dataset as a function of one or more criteria. + The criteria are passed with a dictionary, where a dictionary key + is a variable to subset and the associated dictionary value is either a range + (valuemin, valuemax), a list [value1, value2, valueN], a single value, or a + masking function applied to every row of the ragged array using ``apply_ragged``. + + This function needs to know the names of the dimensions of the ragged array dataset + (`traj_dim_name` and `obs_dim_name`), and the name of the rowsize variable (`rowsize_var_name`). + Default values are provided for these arguments (see below), but they can be changed if needed. + + Parameters + ---------- + ds : xr.Dataset + Dataset stored as ragged arrays + criteria : dict + dictionary containing the variables (as keys) and the ranges/values/functions (as values) to subset + id_var_name : str, optional + Name of the variable containing the ID of the trajectories (default is "id") + rowsize_var_name : str, optional + Name of the variable containing the number of observations per trajectory (default is "rowsize") + traj_dim_name : str, optional + Name of the trajectory dimension (default is "traj") + obs_dim_name : str, optional + Name of the observation dimension (default is "obs") + full_trajectories : bool, optional + If True, it returns the complete trajectories (rows) where at least one observation + matches the criteria, rather than just the segments where the criteria are satisfied. + Default is False. + + Returns + ------- + xr.Dataset + subset Dataset matching the criterion(a) + + Examples + -------- + Criteria are combined on any data or metadata variables part of the Dataset. + The following examples are based on NOAA GDP datasets which can be accessed with the + ``clouddrift.datasets`` module. + + Retrieve a region, like the Gulf of Mexico, using ranges of latitude and longitude: + + >>> subset(ds, {"lat": (21, 31), "lon": (-98, -78)}) + + The parameter `full_trajectories` can be used to retrieve trajectories passing through a region, for example all trajectories passing through the Gulf of Mexico: + + >>> subset(ds, {"lat": (21, 31), "lon": (-98, -78)}, full_trajectories=True) + + Retrieve drogued trajectory segments: + + >>> subset(ds, {"drogue_status": True}) + + Retrieve trajectory segments with temperature higher than 25°C (303.15K): + + >>> subset(ds, {"sst": (303.15, np.inf)}) + + You can use the same approach to return only the trajectories that are + shorter than some number of observations (similar to :func:`prune` but for + the entire dataset): + + >>> subset(ds, {"rowsize": (0, 1000)}) + + Retrieve specific drifters from their IDs: + + >>> subset(ds, {"id": [2578, 2582, 2583]}) + + Sometimes, you may want to retrieve specific rows of a ragged array. + You can do that by filtering along the trajectory dimension directly, since + this one corresponds to row numbers: + + >>> rows = [5, 6, 7] + >>> subset(ds, {"traj": rows}) + + Retrieve a specific time period: + + >>> subset(ds, {"time": (np.datetime64("2000-01-01"), np.datetime64("2020-01-31"))}) + + Note that to subset time variable, the range has to be defined as a function + type of the variable. By default, ``xarray`` uses ``np.datetime64`` to + represent datetime data. If the datetime data is a ``datetime.datetime``, or + ``pd.Timestamp``, the range would have to be defined accordingly. + + Those criteria can also be combined: + + >>> subset(ds, {"lat": (21, 31), "lon": (-98, -78), "drogue_status": True, "sst": (303.15, np.inf), "time": (np.datetime64("2000-01-01"), np.datetime64("2020-01-31"))}) + + You can also use a function to filter the data. For example, retrieve every other observation + of each trajectory (row): + + >>> func = (lambda arr: ((arr - arr[0]) % 2) == 0) + >>> subset(ds, {"time": func}) + + Raises + ------ + ValueError + If one of the variable in a criterion is not found in the Dataset + """ + mask_traj = xr.DataArray( + data=np.ones(ds.sizes[traj_dim_name], dtype="bool"), dims=[traj_dim_name] + ) + mask_obs = xr.DataArray( + data=np.ones(ds.sizes[obs_dim_name], dtype="bool"), dims=[obs_dim_name] + ) + + for key in criteria.keys(): + if key in ds or key in ds.dims: + if ds[key].dims == (traj_dim_name,): + mask_traj = np.logical_and( + mask_traj, + _mask_var( + ds[key], criteria[key], ds[rowsize_var_name], traj_dim_name + ), + ) + elif ds[key].dims == (obs_dim_name,): + mask_obs = np.logical_and( + mask_obs, + _mask_var( + ds[key], criteria[key], ds[rowsize_var_name], obs_dim_name + ), + ) + else: + raise ValueError(f"Unknown variable '{key}'.") + + # remove data when trajectories are filtered + traj_idx = rowsize_to_index(ds[rowsize_var_name].values) + for i in np.where(~mask_traj)[0]: + mask_obs[slice(traj_idx[i], traj_idx[i + 1])] = False + + # remove trajectory completely filtered in mask_obs + ids_with_mask_obs = np.repeat(ds[id_var_name].values, ds[rowsize_var_name].values)[ + mask_obs + ] + mask_traj = np.logical_and( + mask_traj, np.in1d(ds[id_var_name], np.unique(ids_with_mask_obs)) + ) + + # reset mask_obs to True to keep complete trajectories + if full_trajectories: + for i in np.where(mask_traj)[0]: + mask_obs[slice(traj_idx[i], traj_idx[i + 1])] = True + ids_with_mask_obs = np.repeat( + ds[id_var_name].values, ds[rowsize_var_name].values + )[mask_obs] + + if not any(mask_traj): + warnings.warn("No data matches the criteria; returning an empty dataset.") + return xr.Dataset() + else: + # apply the filtering for both dimensions + ds_sub = ds.isel({traj_dim_name: mask_traj, obs_dim_name: mask_obs}) + _, unique_idx, sorted_rowsize = np.unique( + ids_with_mask_obs, return_index=True, return_counts=True + ) + ds_sub[rowsize_var_name].values = sorted_rowsize[np.argsort(unique_idx)] + return ds_sub
+ + + +
+[docs] +def unpack( + ragged_array: np.ndarray, + rowsize: np.ndarray[int], + rows: Union[int, Iterable[int]] = None, + axis: int = 0, +) -> list[np.ndarray]: + """Unpack a ragged array into a list of regular arrays. + + Unpacking a ``np.ndarray`` ragged array is about 2 orders of magnitude + faster than unpacking an ``xr.DataArray`` ragged array, so unless you need a + ``DataArray`` as the result, we recommend passing ``np.ndarray`` as input. + + Parameters + ---------- + ragged_array : array-like + A ragged_array to unpack + rowsize : array-like + An array of integers whose values is the size of each row in the ragged + array + rows : int or Iterable[int], optional + A row or list of rows to unpack. Default is None, which unpacks all rows. + axis : int, optional + The axis along which to unpack the ragged array. Default is 0. + + Returns + ------- + list + A list of array-likes with sizes that correspond to the values in + rowsize, and types that correspond to the type of ragged_array + + Examples + -------- + + Unpacking longitude arrays from a ragged Xarray Dataset: + + .. code-block:: python + + lon = unpack(ds.lon, ds["rowsize"]) # return a list[xr.DataArray] (slower) + lon = unpack(ds.lon.values, ds["rowsize"]) # return a list[np.ndarray] (faster) + first_lon = unpack(ds.lon.values, ds["rowsize"], rows=0) # return only the first row + first_two_lons = unpack(ds.lon.values, ds["rowsize"], rows=[0, 1]) # return first two rows + + Looping over trajectories in a ragged Xarray Dataset to compute velocities + for each: + + .. code-block:: python + + for lon, lat, time in list(zip( + unpack(ds.lon.values, ds["rowsize"]), + unpack(ds.lat.values, ds["rowsize"]), + unpack(ds.time.values, ds["rowsize"]) + )): + u, v = velocity_from_position(lon, lat, time) + """ + indices = rowsize_to_index(rowsize) + + if rows is None: + rows = range(indices.size - 1) + if isinstance(rows, (int, np.integer)): + rows = [rows] + + unpacked = np.split(ragged_array, indices[1:-1], axis=axis) + + return [unpacked[i] for i in rows]
+ + + +def _mask_var( + var: xr.DataArray, + criterion: Union[tuple, list, np.ndarray, xr.DataArray, bool, float, int, Callable], + rowsize: xr.DataArray = None, + dim_name: str = "dim_0", +) -> xr.DataArray: + """Return the mask of a subset of the data matching a test criterion. + + Parameters + ---------- + var : xr.DataArray + DataArray to be subset by the criterion + criterion : array-like or scalar or Callable + The criterion can take four forms: + - tuple: (min, max) defining a range + - list, np.ndarray, or xr.DataArray: An array-like defining multiples values + - scalar: value defining a single value + - function: a function applied against each trajectory using ``apply_ragged`` and returning a mask + rowsize : xr.DataArray, optional + List of integers specifying the number of data points in each row + dim_name : str, optional + Name of the masked dimension (default is "dim_0") + + Examples + -------- + >>> x = xr.DataArray(data=np.arange(0, 5)) + >>> _mask_var(x, (2, 4)) + <xarray.DataArray (dim_0: 5)> + array([False, False, True, True, True]) + Dimensions without coordinates: dim_0 + + >>> _mask_var(x, [0, 2, 4]) + <xarray.DataArray (dim_0: 5)> + array([ True, False, True, False, True]) + Dimensions without coordinates: dim_0 + + >>> _mask_var(x, 4) + <xarray.DataArray (dim_0: 5)> + array([False, False, False, True, False]) + Dimensions without coordinates: dim_0 + + >>> rowsize = xr.DataArray(data=[2, 3]) + >>> _mask_var(x, lambda arr: arr==arr[0]+1, rowsize, "dim_0") + <xarray.DataArray (dim_0: 5)> + array([False, True, False, True, False]) + Dimensions without coordinates: dim_0 + + Returns + ------- + mask : xr.DataArray + The mask of the subset of the data matching the criteria + """ + if isinstance(criterion, tuple): # min/max defining range + mask = np.logical_and(var >= criterion[0], var <= criterion[1]) + elif isinstance(criterion, (list, np.ndarray, xr.DataArray)): + # select multiple values + mask = np.isin(var, criterion) + elif callable(criterion): + # mask directly created by applying `criterion` function + if len(var) == len(rowsize): + mask = criterion(var) + else: + mask = apply_ragged(criterion, var, rowsize) + + mask = xr.DataArray(data=mask, dims=[dim_name]).astype(bool) + + if not len(var) == len(mask): + raise ValueError( + "The `Callable` function must return a masked array that matches the length of the variable to filter." + ) + else: # select one specific value + mask = var == criterion + return mask +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/raggedarray.html b/_modules/clouddrift/raggedarray.html new file mode 100644 index 00000000..121adb5d --- /dev/null +++ b/_modules/clouddrift/raggedarray.html @@ -0,0 +1,999 @@ + + + + + + + + + + clouddrift.raggedarray — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.raggedarray

+"""
+This module defines the RaggedArray class, which is the intermediate data
+structure used by CloudDrift to process custom Lagrangian datasets to Xarray
+Datasets and Awkward Arrays.
+"""
+import awkward as ak
+from clouddrift.ragged import rowsize_to_index
+import xarray as xr
+import numpy as np
+from collections.abc import Callable
+from typing import Tuple, Optional
+from tqdm import tqdm
+import warnings
+
+
+
+[docs] +class RaggedArray: +
+[docs] + def __init__( + self, + coords: dict, + metadata: dict, + data: dict, + attrs_global: Optional[dict] = {}, + attrs_variables: Optional[dict] = {}, + ): + self.coords = coords + self.metadata = metadata + self.data = data + self.attrs_global = attrs_global + self.attrs_variables = attrs_variables + self.validate_attributes()
+ + +
+[docs] + @classmethod + def from_awkward( + cls, + array: ak.Array, + name_coords: Optional[list] = ["time", "lon", "lat", "ids"], + ): + """Load a RaggedArray instance from an Awkward Array. + + Parameters + ---------- + array : ak.Array + Awkward Array instance to load the data from + name_coords : list, optional + Names of the coordinate variables in the ragged arrays + + Returns + ------- + RaggedArray + A RaggedArray instance + """ + coords = {} + metadata = {} + data = {} + attrs_variables = {} + + attrs_global = array.layout.parameters["attrs"] + + for var in name_coords: + coords[var] = ak.flatten(array.obs[var]).to_numpy() + attrs_variables[var] = array.obs[var].layout.parameters["attrs"] + + for var in [v for v in array.fields if v != "obs"]: + metadata[var] = array[var].to_numpy() + attrs_variables[var] = array[var].layout.parameters["attrs"] + + for var in [v for v in array.obs.fields if v not in name_coords]: + data[var] = ak.flatten(array.obs[var]).to_numpy() + attrs_variables[var] = array.obs[var].layout.parameters["attrs"] + + return cls(coords, metadata, data, attrs_global, attrs_variables)
+ + +
+[docs] + @classmethod + def from_files( + cls, + indices: list, + preprocess_func: Callable[[int], xr.Dataset], + name_coords: list, + name_meta: Optional[list] = [], + name_data: Optional[list] = [], + rowsize_func: Optional[Callable[[int], int]] = None, + **kwargs, + ): + """Generate a ragged array archive from a list of trajectory files + + Parameters + ---------- + indices : list + Identification numbers list to iterate + preprocess_func : Callable[[int], xr.Dataset] + Returns a processed xarray Dataset from an identification number + name_coords : list + Name of the coordinate variables to include in the archive + name_meta : list, optional + Name of metadata variables to include in the archive (Defaults to []) + name_data : list, optional + Name of the data variables to include in the archive (Defaults to []) + rowsize_func : Optional[Callable[[int], int]], optional + Returns the number of observations from an identification number (to speed up processing) (Defaults to None) + + Returns + ------- + RaggedArray + A RaggedArray instance + """ + # if no method is supplied, get the dimension from the preprocessing function + rowsize_func = ( + rowsize_func + if rowsize_func + else lambda i, **kwargs: preprocess_func(i, **kwargs).sizes["obs"] + ) + rowsize = cls.number_of_observations(rowsize_func, indices, **kwargs) + coords, metadata, data = cls.allocate( + preprocess_func, + indices, + rowsize, + name_coords, + name_meta, + name_data, + **kwargs, + ) + attrs_global, attrs_variables = cls.attributes( + preprocess_func(indices[0], **kwargs), + name_coords, + name_meta, + name_data, + ) + + return cls(coords, metadata, data, attrs_global, attrs_variables)
+ + +
+[docs] + @classmethod + def from_netcdf(cls, filename: str): + """Read a ragged arrays archive from a NetCDF file. + + This is a thin wrapper around ``from_xarray()``. + + Parameters + ---------- + filename : str + File name of the NetCDF archive to read. + + Returns + ------- + RaggedArray + A ragged array instance + """ + return cls.from_xarray(xr.open_dataset(filename))
+ + +
+[docs] + @classmethod + def from_parquet( + cls, filename: str, name_coords: Optional[list] = ["time", "lon", "lat", "ids"] + ): + """Read a ragged array from a parquet file. + + Parameters + ---------- + filename : str + File name of the parquet archive to read. + name_coords : list, optional + Names of the coordinate variables in the ragged arrays + + Returns + ------- + RaggedArray + A ragged array instance + """ + return cls.from_awkward(ak.from_parquet(filename), name_coords)
+ + +
+[docs] + @classmethod + def from_xarray(cls, ds: xr.Dataset, dim_traj: str = "traj", dim_obs: str = "obs"): + """Populate a RaggedArray instance from an xarray Dataset instance. + + Parameters + ---------- + ds : xr.Dataset + Xarray Dataset from which to load the RaggedArray + dim_traj : str, optional + Name of the trajectories dimension in the xarray Dataset + dim_obs : str, optional + Name of the observations dimension in the xarray Dataset + + Returns + ------- + RaggedArray + A RaggedArray instance + """ + coords = {} + metadata = {} + data = {} + attrs_global = {} + attrs_variables = {} + + attrs_global = ds.attrs + + for var in ds.coords.keys(): + coords[var] = ds[var].data + attrs_variables[var] = ds[var].attrs + + for var in ds.data_vars.keys(): + if len(ds[var]) == ds.sizes[dim_traj]: + metadata[var] = ds[var].data + elif len(ds[var]) == ds.sizes[dim_obs]: + data[var] = ds[var].data + else: + warnings.warn( + f""" + Variable '{var}' has unknown dimension size of + {len(ds[var])}, which is not traj={ds.sizes[dim_traj]} or + obs={ds.sizes[dim_obs]}; skipping. + """ + ) + attrs_variables[var] = ds[var].attrs + + return cls(coords, metadata, data, attrs_global, attrs_variables)
+ + +
+[docs] + @staticmethod + def number_of_observations( + rowsize_func: Callable[[int], int], indices: list, **kwargs + ) -> np.array: + """Iterate through the files and evaluate the number of observations. + + Parameters + ---------- + rowsize_func : Callable[[int], int]] + Function that returns the number observations of a trajectory from + its identification number + indices : list + Identification numbers list to iterate + + Returns + ------- + np.ndarray + Number of observations of each trajectory + """ + rowsize = np.zeros(len(indices), dtype="int") + + for i, index in tqdm( + enumerate(indices), + total=len(indices), + desc="Retrieving the number of obs", + ncols=80, + ): + rowsize[i] = rowsize_func(index, **kwargs) + return rowsize
+ + +
+[docs] + @staticmethod + def attributes( + ds: xr.Dataset, name_coords: list, name_meta: list, name_data: list + ) -> Tuple[dict, dict]: + """Return global attributes and the attributes of all variables + (name_coords, name_meta, and name_data) from an Xarray Dataset. + + Parameters + ---------- + ds : xr.Dataset + _description_ + name_coords : list + Name of the coordinate variables to include in the archive + name_meta : list, optional + Name of metadata variables to include in the archive (default is []) + name_data : list, optional + Name of the data variables to include in the archive (default is []) + + Returns + ------- + Tuple[dict, dict] + The global and variables attributes + """ + attrs_global = ds.attrs + + # coordinates, metadata, and data + attrs_variables = {} + for var in name_coords + name_meta + name_data: + if var in ds.keys(): + attrs_variables[var] = ds[var].attrs + else: + warnings.warn(f"Variable {var} requested but not found; skipping.") + + return attrs_global, attrs_variables
+ + +
+[docs] + @staticmethod + def allocate( + preprocess_func: Callable[[int], xr.Dataset], + indices: list, + rowsize: list, + name_coords: list, + name_meta: list, + name_data: list, + **kwargs, + ) -> Tuple[dict, dict, dict]: + """ + Iterate through the files and fill for the ragged array associated + with coordinates, and selected metadata and data variables. + + Parameters + ---------- + preprocess_func : Callable[[int], xr.Dataset] + Returns a processed xarray Dataset from an identification number. + indices : list + List of indices separating trajectory in the ragged arrays. + rowsize : list + List of the number of observations per trajectory. + name_coords : list + Name of the coordinate variables to include in the archive. + name_meta : list, optional + Name of metadata variables to include in the archive (Defaults to []). + name_data : list, optional + Name of the data variables to include in the archive (Defaults to []). + + Returns + ------- + Tuple[dict, dict, dict] + Dictionaries containing numerical data and attributes of coordinates, metadata and data variables. + """ + + # open one file to get dtype of variables + ds = preprocess_func(indices[0], **kwargs) + nb_traj = len(rowsize) + nb_obs = np.sum(rowsize).astype("int") + index_traj = rowsize_to_index(rowsize) + + # allocate memory + coords = {} + for var in name_coords: + coords[var] = np.zeros(nb_obs, dtype=ds[var].dtype) + + metadata = {} + for var in name_meta: + try: + metadata[var] = np.zeros(nb_traj, dtype=ds[var].dtype) + except KeyError: + warnings.warn(f"Variable {var} requested but not found; skipping.") + + data = {} + for var in name_data: + if var in ds.keys(): + data[var] = np.zeros(nb_obs, dtype=ds[var].dtype) + else: + warnings.warn(f"Variable {var} requested but not found; skipping.") + ds.close() + + # loop and fill the ragged array + for i, index in tqdm( + enumerate(indices), + total=len(indices), + desc="Filling the Ragged Array", + ncols=80, + ): + with preprocess_func(index, **kwargs) as ds: + size = rowsize[i] + oid = index_traj[i] + + for var in name_coords: + coords[var][oid : oid + size] = ds[var].data + + for var in name_meta: + try: + metadata[var][i] = ds[var][0].data + except KeyError: + warnings.warn( + f"Variable {var} requested but not found; skipping." + ) + + for var in name_data: + if var in ds.keys(): + data[var][oid : oid + size] = ds[var].data + else: + warnings.warn( + f"Variable {var} requested but not found; skipping." + ) + + return coords, metadata, data
+ + +
+[docs] + def validate_attributes(self): + """Validate that each variable has an assigned attribute tag.""" + for key in ( + list(self.coords.keys()) + + list(self.metadata.keys()) + + list(self.data.keys()) + ): + if key not in self.attrs_variables: + self.attrs_variables[key] = {}
+ + +
+[docs] + def to_xarray(self, cast_to_float32: bool = True): + """Convert ragged array object to a xarray Dataset. + + Parameters + ---------- + cast_to_float32 : bool, optional + Cast all float64 variables to float32 (default is True). This option aims at + minimizing the size of the xarray dataset. + + Returns + ------- + xr.Dataset + Xarray Dataset containing the ragged arrays and their attributes + """ + + xr_coords = {} + for var in self.coords.keys(): + xr_coords[var] = (["obs"], self.coords[var], self.attrs_variables[var]) + + xr_data = {} + for var in self.metadata.keys(): + xr_data[var] = (["traj"], self.metadata[var], self.attrs_variables[var]) + + for var in self.data.keys(): + xr_data[var] = (["obs"], self.data[var], self.attrs_variables[var]) + + return xr.Dataset(coords=xr_coords, data_vars=xr_data, attrs=self.attrs_global)
+ + +
+[docs] + def to_awkward(self): + """Convert ragged array object to an Awkward Array. + + Returns + ------- + ak.Array + Awkward Array containing the ragged array and its attributes + """ + index_traj = rowsize_to_index(self.metadata["rowsize"]) + offset = ak.index.Index64(index_traj) + + data = [] + for var in self.coords.keys(): + data.append( + ak.contents.ListOffsetArray( + offset, + ak.contents.NumpyArray(self.coords[var]), + parameters={"attrs": self.attrs_variables[var]}, + ) + ) + for var in self.data.keys(): + data.append( + ak.contents.ListOffsetArray( + offset, + ak.contents.NumpyArray(self.data[var]), + parameters={"attrs": self.attrs_variables[var]}, + ) + ) + data_names = list(self.coords.keys()) + list(self.data.keys()) + + metadata = [] + for var in self.metadata.keys(): + metadata.append( + ak.with_parameter( + self.metadata[var], + "attrs", + self.attrs_variables[var], + highlevel=False, + ) + ) + metadata_names = list(self.metadata.keys()) + + # include the data inside the metadata list as a nested array + metadata_names.append("obs") + metadata.append(ak.Array(ak.contents.RecordArray(data, data_names)).layout) + + return ak.Array( + ak.contents.RecordArray( + metadata, metadata_names, parameters={"attrs": self.attrs_global} + ) + )
+ + +
+[docs] + def to_netcdf(self, filename: str): + """Export ragged array object to a NetCDF file. + + Parameters + ---------- + filename : str + Name of the NetCDF file to create. + """ + + self.to_xarray().to_netcdf(filename)
+ + +
+[docs] + def to_parquet(self, filename: str): + """Export ragged array object to a parquet file. + + Parameters + ---------- + filename : str + Name of the parquet file to create. + """ + ak.to_parquet(self.to_awkward(), filename)
+
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/signal.html b/_modules/clouddrift/signal.html new file mode 100644 index 00000000..7f8c9174 --- /dev/null +++ b/_modules/clouddrift/signal.html @@ -0,0 +1,951 @@ + + + + + + + + + + clouddrift.signal — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.signal

+"""
+This module provides signal processing functions.
+"""
+
+import numpy as np
+from typing import Optional, Tuple, Union
+import xarray as xr
+
+
+
+[docs] +def analytic_signal( + x: Union[np.ndarray, xr.DataArray], + boundary: Optional[str] = "mirror", + time_axis: Optional[int] = -1, +) -> Union[np.ndarray, Tuple[np.ndarray, np.ndarray]]: + """Return the analytic signal from a real-valued signal or the analytic and + conjugate analytic signals from a complex-valued signal. + + If the input is a real-valued signal, the analytic signal is calculated as + the inverse Fourier transform of the positive-frequency part of the Fourier + transform. If the input is a complex-valued signal, the conjugate analytic signal + is additionally calculated as the inverse Fourier transform of the positive-frequency + part of the Fourier transform of the complex conjugate of the input signal. + + For a complex-valued signal, the mean is evenly divided between the analytic and + conjugate analytic signal. + + The calculation is performed along the last axis of the input array by default. + Alternatively, the user can specify the time axis of the input. The user can also + specify the boundary conditions to be applied to the input array (default is "mirror"). + + Parameters + ---------- + x : array_like + Real- or complex-valued signal. + boundary : str, optional + The boundary condition to be imposed at the edges of the time series. + Allowed values are "mirror", "zeros", and "periodic". + Default is "mirror". + time_axis : int, optional + Axis on which the time is defined (default is -1). + + Returns + ------- + xa : np.ndarray + Analytic signal. It is a tuple if the input is a complex-valed signal + with the first element being the analytic signal and the second element + being the conjugate analytic signal. + + Examples + -------- + + To obtain the analytic signal of a real-valued signal: + + >>> x = np.random.rand(99) + >>> xa = analytic_signal(x) + + To obtain the analytic and conjugate analytic signals of a complex-valued signal: + + >>> w = np.random.rand(99)+1j*np.random.rand(99) + >>> wp, wn = analytic_signal(w) + + To specify that a periodic boundary condition should be used: + + >>> x = np.random.rand(99) + >>> xa = analytic_signal(x, boundary="periodic") + + To specify that the time axis is along the first axis and apply + zero boundary conditions: + + >>> x = np.random.rand(100, 99) + >>> xa = analytic_signal(x, time_axis=0, boundary="zeros") + + Raises + ------ + ValueError + If the time axis is outside of the valid range ([-1, N-1]). + If ``boundary not in ["mirror", "zeros", "periodic"]``. + + References + ---------- + [1] Gabor D. 1946 Theory of communication. Proc. IEE 93, 429–457. (10.1049/ji-1.1947.0015). + + [2] Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. + IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729). + + See Also + -------- + :func:`rotary_to_cartesian`, :func:`cartesian_to_rotary` + """ + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(x.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(x.shape) - 1}])." + ) + + # Swap the axis to make the time axis last (fast-varying). + # np.swapaxes returns a view to the input array, so no copy is made. + if time_axis != -1 and time_axis != len(x.shape) - 1: + x_ = np.swapaxes(x, time_axis, -1) + else: + x_ = x + + # time dimension length + N = np.shape(x_)[-1] + + # Subtract mean along time axis (-1); convert to np.array for compatibility + # with xarray.DataArray. + mx_ = np.array(np.mean(x_, axis=-1, keepdims=True)) + xa = x_ - mx_ + + # apply boundary conditions + if boundary == "mirror": + xa = np.concatenate((np.flip(xa, axis=-1), xa, np.flip(xa, axis=-1)), axis=-1) + elif boundary == "zeros": + xa = np.concatenate((np.zeros_like(xa), xa, np.zeros_like(xa)), axis=-1) + elif boundary == "periodic": + xa = np.concatenate((xa, xa, xa), axis=-1) + else: + raise ValueError("boundary must be one of 'mirror', 'align', or 'zeros'.") + + # analytic signal + xap = np.fft.fft(xa) + # conjugate analytic signal + xan = np.fft.fft(np.conj(xa)) + + # time dimension of extended time series + M = np.shape(xa)[-1] + + # zero negative frequencies + if M % 2 == 0: + xap[..., int(M / 2 + 2) - 1 : int(M + 1) + 1] = 0 + xan[..., int(M / 2 + 2) - 1 : int(M + 1) + 1] = 0 + # divide Nyquist component by 2 in even case + xap[..., int(M / 2 + 1) - 1] = xap[..., int(M / 2 + 1) - 1] / 2 + xan[..., int(M / 2 + 1) - 1] = xan[..., int(M / 2 + 1) - 1] / 2 + else: + xap[..., int((M + 3) / 2) - 1 : int(M + 1) + 1] = 0 + xan[..., int((M + 3) / 2) - 1 : int(M + 1) + 1] = 0 + + # inverse Fourier transform along last axis + xap = np.fft.ifft(xap) + xan = np.fft.ifft(xan) + + # return central part plus half the mean + xap = xap[..., int(N + 1) - 1 : int(2 * N + 1) - 1] + 0.5 * mx_ + xan = xan[..., int(N + 1) - 1 : int(2 * N + 1) - 1] + 0.5 * np.conj(mx_) + + if np.isrealobj(x): + xa = xap + xan + else: + xa = (xap, xan) + + # return after reorganizing the axes + if time_axis != -1 and time_axis != len(x.shape) - 1: + return np.swapaxes(xa, time_axis, -1) + else: + return xa
+ + + +
+[docs] +def cartesian_to_rotary( + ua: Union[np.ndarray, xr.DataArray], + va: Union[np.ndarray, xr.DataArray], + time_axis: Optional[int] = -1, +) -> Tuple[np.ndarray, np.ndarray]: + """Return rotary signals (wp,wn) from analytic Cartesian signals (ua,va). + + If ua is the analytic signal from real-valued signal u, and va the analytic signal + from real-valued signal v, then the positive (counterclockwise) and negative (clockwise) + signals are defined by wp = 0.5*(up+1j*vp), wp = 0.5*(up-1j*vp). + + This function is the inverse of :func:`rotary_to_cartesian`. + + Parameters + ---------- + ua : array_like + Complex-valued analytic signal for first Cartesian component (zonal, east-west) + va : array_like + Complex-valued analytic signal for second Cartesian component (meridional, north-south) + time_axis : int, optional + The axis of the time array. Default is -1, which corresponds to the + last axis. + + Returns + ------- + wp : np.ndarray + Complex-valued positive (counterclockwise) rotary signal. + wn : np.ndarray + Complex-valued negative (clockwise) rotary signal. + + Examples + -------- + To obtain the rotary signals from a pair of real-valued signal: + + >>> u = np.random.rand(99) + >>> v = np.random.rand(99) + >>> wp, wn = cartesian_to_rotary(analytic_signal(u), analytic_signal(v)) + + To specify that the time axis is along the first axis: + + >>> u = np.random.rand(100, 99) + >>> v = np.random.rand(100, 99) + >>> wp, wn = cartesian_to_rotary(analytic_signal(u), analytic_signal(v), time_axis=0) + + Raises + ------ + ValueError + If the input arrays do not have the same shape. + If the time axis is outside of the valid range ([-1, N-1]). + + References + ---------- + Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. + IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729) + + See Also + -------- + :func:`analytic_signal`, :func:`rotary_to_cartesian` + """ + # u and v arrays must have the same shape. + if not ua.shape == va.shape: + raise ValueError("u and v must have the same shape.") + + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(ua.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(ua.shape) - 1}])." + ) + + wp = 0.5 * (ua + 1j * va) + wn = 0.5 * (ua - 1j * va) + + return wp, wn
+ + + +
+[docs] +def ellipse_parameters( + xa: Union[np.ndarray, xr.DataArray], + ya: Union[np.ndarray, xr.DataArray], +) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + """Return the instantaneous parameters of a modulated elliptical signal from its analytic Cartesian signals. + + Parameters + ---------- + xa : array_like + Complex-valued analytic signal for first Cartesian component (zonal, east-west). + ya : array_like + Complex-valued analytic signal for second Cartesian component (meridional, north-south). + + Returns + ------- + kappa : np.ndarray + Ellipse root-mean-square amplitude. + lambda : np.ndarray + Ellipse linearity between -1 and 1, or departure from circular motion (lambda=0). + theta : np.ndarray + Ellipse orientation in radian. + phi : np.ndarray + Ellipse phase in radian. + + Examples + -------- + + To obtain the ellipse parameters from a pair of real-valued signals (x, y): + + >>> kappa, lambda, theta, phi = ellipse_parameters(analytic_signal(x), analytic_signal(y)) + + Raises + ------ + ValueError + If the input arrays do not have the same shape. + + References + ---------- + Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. + IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729). + + See Also + -------- + :func:`modulated_ellipse_signal`, :func:`analytic_signal`, :func:`rotary_to_cartesian`, :func:`cartesian_to_rotary` + + """ + + # u and v arrays must have the same shape. + if not xa.shape == ya.shape: + raise ValueError("xa and ya must have the same shape.") + + X = np.abs(xa) + Y = np.abs(ya) + phix = np.angle(xa) + phiy = np.angle(ya) + + phia = 0.5 * (phix + phiy + 0.5 * np.pi) + phid = 0.5 * (phix - phiy - 0.5 * np.pi) + + P = 0.5 * np.sqrt(X**2 + Y**2 + 2 * X * Y * np.cos(2 * phid)) + N = 0.5 * np.sqrt(X**2 + Y**2 - 2 * X * Y * np.cos(2 * phid)) + + phip = np.unwrap( + phia + + np.unwrap(np.imag(np.log(X * np.exp(1j * phid) + Y * np.exp(-1j * phid)))) + ) + phin = np.unwrap( + phia + + np.unwrap(np.imag(np.log(X * np.exp(1j * phid) - Y * np.exp(-1j * phid)))) + ) + + kappa = np.sqrt(P**2 + N**2) + lambda_ = (2 * P * N * np.sign(P - N)) / (P**2 + N**2) + + # For vanishing linearity, put in very small number to have sign information + lambda_[lambda_ == 0] = np.sign(P[lambda_ == 0] - N[lambda_ == 0]) * (1e-12) + + theta = np.unwrap(0.5 * (phip - phin)) + phi = np.unwrap(0.5 * (phip + phin)) + + lambda_ = np.real(lambda_) + + return kappa, lambda_, theta, phi
+ + + +
+[docs] +def modulated_ellipse_signal( + kappa: Union[np.ndarray, xr.DataArray], + lambda_: Union[np.ndarray, xr.DataArray], + theta: Union[np.ndarray, xr.DataArray], + phi: Union[np.ndarray, xr.DataArray], +) -> Tuple[np.ndarray, np.ndarray]: + """Return the analytic Cartesian signals (xa, ya) from the instantaneous parameters of a modulated elliptical signal. + + This function is the inverse of :func:`ellipse_parameters`. + + Parameters + ---------- + kappa : array_like + Ellipse root-mean-square amplitude. + lambda : array_like + Ellipse linearity between -1 and 1, or departure from circular motion (lambda=0). + theta : array_like + Ellipse orientation in radian. + phi : array_like + Ellipse phase in radian. + time_axis : int, optional + The axis of the time array. Default is -1, which corresponds to the + last axis. + + Returns + ------- + xa : np.ndarray + Complex-valued analytic signal for first Cartesian component (zonal, east-west). + ya : np.ndarray + Complex-valued analytic signal for second Cartesian component (meridional, north-south). + + Examples + -------- + + To obtain the analytic signals from the instantaneous parameters of a modulated elliptical signal: + + >>> xa, ya = modulated_ellipse_signal(kappa, lambda, theta, phi) + + Raises + ------ + ValueError + If the input arrays do not have the same shape. + + References + ---------- + Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. + IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729). + + See Also + -------- + :func:`ellipse_parameters`, :func:`analytic_signal`, :func:`rotary_to_cartesian`, :func:`cartesian_to_rotary` + + """ + + # make sure all input arrays have the same shape + if not kappa.shape == lambda_.shape == theta.shape == phi.shape: + raise ValueError("All input arrays must have the same shape.") + + # calculate semi major and semi minor axes + a = kappa * np.sqrt(1 + np.abs(lambda_)) + b = np.sign(lambda_) * kappa * np.sqrt(1 - np.abs(lambda_)) + + # define b to be positive for lambda exactly zero + b[lambda_ == 0] = kappa[lambda_ == 0] + + xa = np.exp(1j * phi) * (a * np.cos(theta) + 1j * b * np.sin(theta)) + ya = np.exp(1j * phi) * (a * np.sin(theta) - 1j * b * np.cos(theta)) + + mask = np.isinf(kappa * lambda_ * theta * phi) + xa[mask] = np.inf + 1j * np.inf + ya[mask] = np.inf + 1j * np.inf + + return xa, ya
+ + + +
+[docs] +def rotary_to_cartesian( + wp: Union[np.ndarray, xr.DataArray], + wn: Union[np.ndarray, xr.DataArray], + time_axis: Optional[int] = -1, +) -> Tuple[np.ndarray, np.ndarray]: + """Return Cartesian analytic signals (ua, va) from rotary signals (wp, wn) + as ua = wp + wn and va = -1j * (wp - wn). + + This function is the inverse of :func:`cartesian_to_rotary`. + + Parameters + ---------- + wp : array_like + Complex-valued positive (counterclockwise) rotary signal. + wn : array_like + Complex-valued negative (clockwise) rotary signal. + time_axis : int, optional + The axis of the time array. Default is -1, which corresponds to the + last axis. + + Returns + ------- + ua : array_like + Complex-valued analytic signal, first Cartesian component (zonal, east-west) + va : array_like + Complex-valued analytic signal, second Cartesian component (meridional, north-south) + + Examples + -------- + + To obtain the Cartesian analytic signals from a pair of rotary signals (wp,wn): + + >>> ua, va = rotary_to_cartesian(wp, wn) + + To specify that the time axis is along the first axis: + + >>> ua, va = rotary_to_cartesian(wp, wn, time_axis=0) + + Raises + ------ + ValueError + If the input arrays do not have the same shape. + If the time axis is outside of the valid range ([-1, N-1]). + + References + ---------- + Lilly JM, Olhede SC. 2010 Bivariate instantaneous frequency and bandwidth. + IEEE T. Signal Proces. 58, 591–603. (10.1109/TSP.2009.2031729) + + See Also + -------- + :func:`analytic_signal`, :func:`cartesian_to_rotary` + """ + + if not wp.shape == wn.shape: + raise ValueError("u and v must have the same shape.") + + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(wp.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(wp.shape) - 1}])." + ) + + # I think this may return xarray dataarrays if that's the input + ua = wp + wn + va = -1j * (wp - wn) + + return ua, va
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/sphere.html b/_modules/clouddrift/sphere.html new file mode 100644 index 00000000..9cdae7dc --- /dev/null +++ b/_modules/clouddrift/sphere.html @@ -0,0 +1,1320 @@ + + + + + + + + + + clouddrift.sphere — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.sphere

+"""
+This module provides functions for spherical geometry calculations.
+"""
+
+import numpy as np
+from typing import Optional, Tuple, Union
+import xarray as xr
+import warnings
+
+EARTH_RADIUS_METERS = 6.3781e6
+EARTH_DAY_SECONDS = 86164.091
+EARTH_ROTATION_RATE = 2 * np.pi / EARTH_DAY_SECONDS
+
+
+
+[docs] +def cumulative_distance( + longitude: Union[list, np.ndarray, xr.DataArray], + latitude: Union[list, np.ndarray, xr.DataArray], +) -> np.ndarray: + """Return the cumulative great circle distance in meters along a sequence of geographical locations. + + Parameters + ---------- + latitude : array-like + Latitude sequence, in degrees. + longitude : array-like + Longitude sequence, in degrees. + + Returns + ------- + out : np.ndarray + Cumulative distance. + + See Also + -------- + :func:`distance` + + Examples + -------- + Calculate the cumulative distance in meters along a path of three points: + + >>> cumulative_distance(np.array([0, 1, 2]), np.array([0, 1, 2])) + array([ 0. , 157424.62387233, 314825.27182116]) + """ + return np.cumsum( + np.concatenate( + ( + [0], + distance(latitude[0:-1], longitude[0:-1], latitude[1:], longitude[1:]), + ) + ) + )
+ + + +
+[docs] +def distance( + lon1: Union[float, list, np.ndarray, xr.DataArray], + lat1: Union[float, list, np.ndarray, xr.DataArray], + lon2: Union[float, list, np.ndarray, xr.DataArray], + lat2: Union[float, list, np.ndarray, xr.DataArray], +) -> Union[float, np.ndarray]: + """Return elementwise great circle distance in meters between one or more + points from arrays of their latitudes and longitudes, using the Haversine + formula. + + d = 2⋅r⋅asin √[sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)] + + where (φ, λ) is (lat, lon) in radians and r is the radius of the sphere in + meters. + + Parameters + ---------- + lon1 : np.ndarray + Longitudes of the first set of points, in degrees + lat1 : np.ndarray + Latitudes of the first set of points, in degrees + lon2 : np.ndarray + Longitudes of the second set of points, in degrees + lat2 : np.ndarray + Latitudes of the second set of points, in degrees + + Returns + ------- + out : np.ndarray + Great circle distance + + Examples + -------- + Calculate the distance of one degree longitude on the equator: + + >>> distance(0, 0, 0, 1) + 111318.84502145034 + + Calculate the distance of one degree longitude at 45-degrees North latitude: + + >>> distance(0, 45, 1, 45) + 78713.81064540472 + + You can also pass array-like inputs to calculate an array of distances: + + >>> distance([0, 0], [0, 45], [0, 1], [1, 45]) + array([111318.84502145, 78713.8106454 ]) + """ + + # Input coordinates are in degrees; convert to radians. + # If any of the input arrays are xr.DataArray, extract the values first + # because Xarray enforces alignment between coordinates. + if type(lat1) is xr.DataArray: + lat1_rad = np.deg2rad(lat1.values) + else: + lat1_rad = np.deg2rad(lat1) + if type(lon1) is xr.DataArray: + lon1_rad = np.deg2rad(lon1.values) + else: + lon1_rad = np.deg2rad(lon1) + if type(lat2) is xr.DataArray: + lat2_rad = np.deg2rad(lat2.values) + else: + lat2_rad = np.deg2rad(lat2) + if type(lon2) is xr.DataArray: + lon2_rad = np.deg2rad(lon2.values) + else: + lon2_rad = np.deg2rad(lon2) + + dlat = lat2_rad - lat1_rad + dlon = lon2_rad - lon1_rad + + h = ( + np.sin(0.5 * dlat) ** 2 + + np.cos(lat1_rad) * np.cos(lat2_rad) * np.sin(0.5 * dlon) ** 2 + ) + + return 2 * np.arcsin(np.sqrt(h)) * EARTH_RADIUS_METERS
+ + + +
+[docs] +def bearing( + lon1: Union[float, list, np.ndarray, xr.DataArray], + lat1: Union[float, list, np.ndarray, xr.DataArray], + lon2: Union[float, list, np.ndarray, xr.DataArray], + lat2: Union[float, list, np.ndarray, xr.DataArray], +) -> Union[float, np.ndarray]: + """Return elementwise initial (forward) bearing in radians from arrays of + latitude and longitude in degrees, based on the spherical law of cosines. + + The formula is: + + θ = atan2(cos φ1 ⋅ sin φ2 - sin φ1 ⋅ cos φ2 ⋅ cos Δλ, sin Δλ ⋅ cos φ2) + + where (φ, λ) is (lat, lon) and θ is bearing, all in radians. + Bearing is defined as zero toward East and positive counterclockwise. + + Parameters + ---------- + lon1 : float or array-like + Longitudes of the first set of points, in degrees + lat1 : float or array-like + Latitudes of the first set of points, in degrees + lon2 : float or array-like + Longitudes of the second set of points, in degrees + lat2 : float or array-like + Latitudes of the second set of points, in degrees + + Returns + ------- + theta : float or np.ndarray + Bearing angles in radians + + Examples + -------- + Calculate the bearing of one degree longitude on the equator: + + >>> bearing(0, 0, 1, 0) + 0.0 + + Calculate the bearing of 10 degrees longitude at 45-degrees North latitude: + + >>> bearing(0, 45, 10, 45) + 0.06178508761798218 + """ + # Input coordinates are in degrees; convert to radians. + # If any of the input arrays are xr.DataArray, extract the values first + # because Xarray enforces alignment between coordinates. + if type(lat1) is xr.DataArray: + lat1_rad = np.deg2rad(lat1.values) + else: + lat1_rad = np.deg2rad(lat1) + if type(lon1) is xr.DataArray: + lon1_rad = np.deg2rad(lon1.values) + else: + lon1_rad = np.deg2rad(lon1) + if type(lat2) is xr.DataArray: + lat2_rad = np.deg2rad(lat2.values) + else: + lat2_rad = np.deg2rad(lat2) + if type(lon2) is xr.DataArray: + lon2_rad = np.deg2rad(lon2.values) + else: + lon2_rad = np.deg2rad(lon2) + + dlon = lon2_rad - lon1_rad + + theta = np.arctan2( + np.cos(lat1_rad) * np.sin(lat2_rad) + - np.sin(lat1_rad) * np.cos(lat2_rad) * np.cos(dlon), + np.sin(dlon) * np.cos(lat2_rad), + ) + + return theta
+ + + +
+[docs] +def position_from_distance_and_bearing( + lon: float, lat: float, distance: float, bearing: float +) -> Tuple[float, float]: + """Return elementwise new position in degrees from arrays of latitude and + longitude in degrees, distance in meters, and bearing in radians, based on + the spherical law of cosines. + + The formula is: + + φ2 = asin( sin φ1 ⋅ cos δ + cos φ1 ⋅ sin δ ⋅ cos θ ) + λ2 = λ1 + atan2( sin θ ⋅ sin δ ⋅ cos φ1, cos δ − sin φ1 ⋅ sin φ2 ) + + where (φ, λ) is (lat, lon) and θ is bearing, all in radians. + Bearing is defined as zero toward East and positive counterclockwise. + + Parameters + ---------- + lon : float + Longitude of the first set of points, in degrees + lat : float + Latitude of the first set of points, in degrees + distance : array_like + Distance in meters + bearing : array_like + Bearing angles in radians + + Returns + ------- + lon2 : array_like + Latitudes of the second set of points, in degrees, in the range [-90, 90] + lat2 : array_like + Longitudes of the second set of points, in degrees, in the range [-180, 180] + + Examples + -------- + Calculate the position of one degree longitude distance on the equator: + + >>> position_from_distance_and_bearing(0, 0, 111318.84502145034, 0) + (1.0, 0.0) + + Calculate the position of one degree latitude distance from 45 degrees North latitude: + + >>> position_from_distance_and_bearing(0, 45, 111318.84502145034, np.pi / 2) + (8.81429402840006e-17, 45.99999999999999) + """ + lat_rad = np.deg2rad(lat) + lon_rad = np.deg2rad(lon) + + distance_rad = distance / EARTH_RADIUS_METERS + + lat2_rad = np.arcsin( + np.sin(lat_rad) * np.cos(distance_rad) + + np.cos(lat_rad) * np.sin(distance_rad) * np.sin(bearing) + ) + lon2_rad = lon_rad + np.arctan2( + np.cos(bearing) * np.sin(distance_rad) * np.cos(lat_rad), + np.cos(distance_rad) - np.sin(lat_rad) * np.sin(lat2_rad), + ) + + return np.rad2deg(lon2_rad), np.rad2deg(lat2_rad)
+ + + +
+[docs] +def recast_lon(lon: np.ndarray, lon0: Optional[float] = -180) -> np.ndarray: + """Recast (convert) longitude values to a selected range of 360 degrees + starting from ``lon0``. + + Parameters + ---------- + lon : np.ndarray or float + An N-d array of longitudes in degrees + lon0 : float, optional + Starting longitude of the recasted range (default -180). + + Returns + ------- + np.ndarray or float + Converted longitudes in the range `[lon0, lon0+360[` + + Examples + -------- + By default, ``recast_lon`` converts longitude values to the range + `[-180, 180[`: + + >>> recast_lon(200) + -160 + + >>> recast_lon(180) + -180 + + The range of the output longitude is controlled by ``lon0``. + For example, with ``lon0 = 0``, the longitude values are converted to the + range `[0, 360[`. + + >>> recast_lon(200, -180) + -160 + + With ``lon0 = 20``, longitude values are converted to range `[20, 380]`, + which can be useful to avoid cutting the major ocean basins. + + >>> recast_lon(10, 20) + 370 + + See Also + -------- + :func:`recast_lon360`, :func:`recast_lon180` + """ + return np.mod(lon - lon0, 360) + lon0
+ + + +
+[docs] +def recast_lon360(lon: np.ndarray) -> np.ndarray: + """Recast (convert) longitude values to the range `[0, 360[`. + This is a convenience wrapper around :func:`recast_lon` with ``lon0 = 0``. + + Parameters + ---------- + lon : np.ndarray + An N-d array of longitudes in degrees + + Returns + ------- + np.ndarray + Converted longitudes in the range `[0, 360[` + + Examples + -------- + >>> recast_lon360(200) + 200 + + >>> recast_lon360(-200) + 160 + + See Also + -------- + :func:`recast_lon`, :func:`recast_lon180` + """ + return recast_lon(lon, 0)
+ + + +
+[docs] +def recast_lon180(lon: np.ndarray) -> np.ndarray: + """Recast (convert) longitude values to the range `[-180, 180[`. + This is a convenience wrapper around :func:`recast_lon` with ``lon0 = -180``. + + Parameters + ---------- + lon : np.ndarray + An N-d array of longitudes in degrees + + Returns + ------- + np.ndarray + Converted longitudes in the range `[-180, 180[` + + Examples + -------- + >>> recast_lon180(200) + -160 + + >>> recast_lon180(-200) + 160 + + See Also + -------- + :func:`recast_lon`, :func:`recast_lon360` + """ + return recast_lon(lon, -180)
+ + + +
+[docs] +def plane_to_sphere( + x: np.ndarray, y: np.ndarray, lon_origin: float = 0, lat_origin: float = 0 +) -> Tuple[np.ndarray, np.ndarray]: + """Convert Cartesian coordinates on a plane to spherical coordinates. + + The arrays of input zonal and meridional displacements ``x`` and ``y`` are + assumed to follow a contiguous trajectory. The spherical coordinate of each + successive point is determined by following a great circle path from the + previous point. The spherical coordinate of the first point is determined by + following a great circle path from the origin, by default (0, 0). + + The output arrays have the same floating-point output type as the input. + + If projecting multiple trajectories onto the same plane, use + :func:`apply_ragged` for highest accuracy. + + Parameters + ---------- + x : np.ndarray + An N-d array of zonal displacements in meters + y : np.ndarray + An N-d array of meridional displacements in meters + lon_origin : float, optional + Origin longitude of the tangent plane in degrees, default 0 + lat_origin : float, optional + Origin latitude of the tangent plane in degrees, default 0 + + Returns + ------- + lon : np.ndarray + Longitude in degrees + lat : np.ndarray + Latitude in degrees + + Examples + -------- + >>> plane_to_sphere(np.array([0., 0.]), np.array([0., 1000.])) + (array([0.00000000e+00, 5.50062664e-19]), array([0. , 0.0089832])) + + You can also specify an origin longitude and latitude: + + >>> plane_to_sphere(np.array([0., 0.]), np.array([0., 1000.]), lon_origin=1, lat_origin=0) + (array([1., 1.]), array([0. , 0.0089832])) + + Raises + ------ + AttributeError + If ``x`` and ``y`` are not NumPy arrays + + See Also + -------- + :func:`sphere_to_plane` + """ + lon = np.empty_like(x) + lat = np.empty_like(y) + + # Cartesian distances between each point + dx = np.diff(x, prepend=0) + dy = np.diff(y, prepend=0) + + distances = np.sqrt(dx**2 + dy**2) + bearings = np.arctan2(dy, dx) + + # Compute spherical coordinates following great circles between each + # successive point. + lon[..., 0], lat[..., 0] = position_from_distance_and_bearing( + lon_origin, lat_origin, distances[..., 0], bearings[..., 0] + ) + for n in range(1, lon.shape[-1]): + lon[..., n], lat[..., n] = position_from_distance_and_bearing( + lon[..., n - 1], lat[..., n - 1], distances[..., n], bearings[..., n] + ) + + return lon, lat
+ + + +
+[docs] +def sphere_to_plane( + lon: np.ndarray, lat: np.ndarray, lon_origin: float = 0, lat_origin: float = 0 +) -> Tuple[np.ndarray, np.ndarray]: + """Convert spherical coordinates to a tangent (Cartesian) plane. + + The arrays of input longitudes and latitudes are assumed to be following + a contiguous trajectory. The Cartesian coordinate of each successive point + is determined by following a great circle path from the previous point. + The Cartesian coordinate of the first point is determined by following a + great circle path from the origin, by default (0, 0). + + The output arrays have the same floating-point output type as the input. + + If projecting multiple trajectories onto the same plane, use + :func:`apply_ragged` for highest accuracy. + + Parameters + ---------- + lon : np.ndarray + An N-d array of longitudes in degrees + lat : np.ndarray + An N-d array of latitudes in degrees + lon_origin : float, optional + Origin longitude of the tangent plane in degrees, default 0 + lat_origin : float, optional + Origin latitude of the tangent plane in degrees, default 0 + + Returns + ------- + x : np.ndarray + x-coordinates on the tangent plane + y : np.ndarray + y-coordinates on the tangent plane + + Examples + -------- + >>> sphere_to_plane(np.array([0., 1.]), np.array([0., 0.])) + (array([ 0. , 111318.84502145]), array([0., 0.])) + + You can also specify an origin longitude and latitude: + + >>> sphere_to_plane(np.array([0., 1.]), np.array([0., 0.]), lon_origin=1, lat_origin=0) + (array([-111318.84502145, 0. ]), + array([1.36326267e-11, 1.36326267e-11])) + + Raises + ------ + AttributeError + If ``lon`` and ``lat`` are not NumPy arrays + + See Also + -------- + :func:`plane_to_sphere` + """ + x = np.empty_like(lon) + y = np.empty_like(lat) + + distances = np.empty_like(x) + bearings = np.empty_like(x) + + # Distance and bearing of the starting point relative to the origin + distances[0] = distance(lon_origin, lat_origin, lon[..., 0], lat[..., 0]) + bearings[0] = bearing(lon_origin, lat_origin, lon[..., 0], lat[..., 0]) + + # Distance and bearing of the remaining points + distances[1:] = distance(lon[..., :-1], lat[..., :-1], lon[..., 1:], lat[..., 1:]) + bearings[1:] = bearing(lon[..., :-1], lat[..., :-1], lon[..., 1:], lat[..., 1:]) + + dx = distances * np.cos(bearings) + dy = distances * np.sin(bearings) + + x[..., :] = np.cumsum(dx, axis=-1) + y[..., :] = np.cumsum(dy, axis=-1) + + return x, y
+ + + +
+[docs] +def spherical_to_cartesian( + lon: Union[float, list, np.ndarray, xr.DataArray], + lat: Union[float, list, np.ndarray, xr.DataArray], + radius: Optional[float] = EARTH_RADIUS_METERS, +) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: + """Converts latitude and longitude on a spherical body to + three-dimensional Cartesian coordinates. + + The Cartesian coordinate system is a right-handed system whose + origin lies at the center of a sphere. It is oriented with the + Z-axis passing through the poles and the X-axis passing through + the point lon = 0, lat = 0. This function is inverted by + :func:`cartesian_to_spherical`. + + Parameters + ---------- + lon : array-like + An N-d array of longitudes in degrees. + lat : array-like + An N-d array of latitudes in degrees. + radius: float, optional + The radius of the spherical body in meters. The default assumes the Earth with + EARTH_RADIUS_METERS = 6.3781e6. + + Returns + ------- + x : float or array-like + x-coordinates in 3D in meters. + y : float or array-like + y-coordinates in 3D in meters. + z : float or array-like + z-coordinates in 3D in meters. + + Examples + -------- + >>> spherical_to_cartesian(np.array([0, 45]), np.array([0, 45])) + (array([6378100., 3189050.]), + array([ 0., 3189050.]), + array([ 0. , 4509997.76108592])) + + >>> spherical_to_cartesian(np.array([0, 45, 90]), np.array([0, 90, 180]), radius=1) + (array([ 1.00000000e+00, 4.32978028e-17, -6.12323400e-17]), + array([ 0.00000000e+00, 4.32978028e-17, -1.00000000e+00]), + array([0.0000000e+00, 1.0000000e+00, 1.2246468e-16])) + + >>> x, y, z = spherical_to_cartesian(np.array([0, 5]), np.array([0, 5])) + + Raises + ------ + AttributeError + If ``lon`` and ``lat`` are not NumPy arrays. + + See Also + -------- + :func:`cartesian_to_spherical` + """ + lonr, latr = np.deg2rad(lon), np.deg2rad(lat) + + x = radius * np.cos(latr) * np.cos(lonr) + y = radius * np.cos(latr) * np.sin(lonr) + z = radius * np.sin(latr) + + return x, y, z
+ + + +
+[docs] +def cartesian_to_spherical( + x: Union[float, np.ndarray, xr.DataArray], + y: Union[float, np.ndarray, xr.DataArray], + z: Union[float, np.ndarray, xr.DataArray], +) -> Tuple[np.ndarray, np.ndarray]: + """Converts Cartesian three-dimensional coordinates to latitude and longitude on a + spherical body. + + The Cartesian coordinate system is a right-handed system whose + origin lies at the center of the sphere. It is oriented with the + Z-axis passing through the poles and the X-axis passing through + the point lon = 0, lat = 0. This function is inverted by `spherical_to_cartesian`. + + Parameters + ---------- + x : float or array-like + x-coordinates in 3D. + y : float or array-like + y-coordinates in 3D. + z : float or array-like + z-coordinates in 3D. + + Returns + ------- + lon : float or array-like + An N-d array of longitudes in degrees in range [-180, 180]. + lat : float or array-like + An N-d array of latitudes in degrees. + + Examples + -------- + >>> x = EARTH_RADIUS_METERS * np.cos(np.deg2rad(45)) + >>> y = EARTH_RADIUS_METERS * np.cos(np.deg2rad(45)) + >>> z = 0 * x + >>> cartesian_to_spherical(x, y, z) + (44.99999999999985, 0.0) + + ``cartesian_to_spherical`` is inverted by ``spherical_to_cartesian``: + + >>> x, y, z = spherical_to_cartesian(np.array([45]),np.array(0)) + >>> cartesian_to_spherical(x, y, z) + (array([45.]), array([0.])) + + Raises + ------ + AttributeError + If ``x``, ``y``, and ``z`` are not NumPy arrays. + + See Also + -------- + :func:`spherical_to_cartesian` + """ + + R = np.sqrt(x**2 + y**2 + z**2) + x /= R + y /= R + z /= R + + with np.errstate(divide="ignore"): + lon = np.where( + np.logical_and(x == 0, y == 0), + 0, + recast_lon180(np.rad2deg(np.imag(np.log((x + 1j * y))))), + ) + lat = np.rad2deg(np.arcsin(z)) + + return lon, lat
+ + + +
+[docs] +def cartesian_to_tangentplane( + u: Union[float, np.ndarray], + v: Union[float, np.ndarray], + w: Union[float, np.ndarray], + longitude: Union[float, np.ndarray], + latitude: Union[float, np.ndarray], +) -> Union[Tuple[float], Tuple[np.ndarray]]: + """ + Project a three-dimensional Cartesian vector on a plane tangent to + a spherical Earth. + + The Cartesian coordinate system is a right-handed system whose + origin lies at the center of a sphere. It is oriented with the + Z-axis passing through the north pole at lat = 90, the X-axis passing through + the point lon = 0, lat = 0, and the Y-axis passing through the point lon = 90, + lat = 0. + + Parameters + ---------- + u : float or np.ndarray + First component of Cartesian vector. + v : float or np.ndarray + Second component of Cartesian vector. + w : float or np.ndarray + Third component of Cartesian vector. + longitude : float or np.ndarray + Longitude in degrees of tangent point of plane. + latitude : float or np.ndarray + Latitude in degrees of tangent point of plane. + + Returns + ------- + up: float or np.ndarray + First component of projected vector on tangent plane (positive eastward). + vp: float or np.ndarray + Second component of projected vector on tangent plane (positive northward). + + Raises + ------ + Warning + Raised if the input latitude is not in the expected range [-90, 90]. + + Examples + -------- + >>> u, v = cartesian_to_tangentplane(1, 1, 1, 45, 90) + + See Also + -------- + :func:`tangentplane_to_cartesian` + """ + if np.any(latitude < -90) or np.any(latitude > 90): + warnings.warn("Input latitude outside of range [-90,90].") + + phi = np.radians(latitude) + theta = np.radians(longitude) + u_projected = v * np.cos(theta) - u * np.sin(theta) + v_projected = ( + w * np.cos(phi) + - u * np.cos(theta) * np.sin(phi) + - v * np.sin(theta) * np.sin(phi) + ) + # JML says vh = w.*cos(phi)-u.*cos(theta).*sin(phi)-v.*sin(theta).*sin(phi) but vh=w./cos(phi) is the same + return u_projected, v_projected
+ + + +
+[docs] +def tangentplane_to_cartesian( + up: Union[float, np.ndarray], + vp: Union[float, np.ndarray], + longitude: Union[float, np.ndarray], + latitude: Union[float, np.ndarray], +) -> Union[Tuple[float], Tuple[np.ndarray]]: + """ + Return the three-dimensional Cartesian components of a vector contained in + a plane tangent to a spherical Earth. + + The Cartesian coordinate system is a right-handed system whose + origin lies at the center of a sphere. It is oriented with the + Z-axis passing through the north pole at lat = 90, the X-axis passing through + the point lon = 0, lat = 0, and the Y-axis passing through the point lon = 90, + lat = 0. + + Parameters + ---------- + up: float or np.ndarray + First component of vector on tangent plane (positive eastward). + vp: float or np.ndarray + Second component of vector on tangent plane (positive northward). + longitude : float or np.ndarray + Longitude in degrees of tangent point of plane. + latitude : float or np.ndarray + Latitude in degrees of tangent point of plane. + + Returns + ------- + u : float or np.ndarray + First component of Cartesian vector. + v : float or np.ndarray + Second component of Cartesian vector. + w : float or np.ndarray + Third component of Cartesian vector. + + Examples + -------- + >>> u, v, w = tangentplane_to_cartesian(1, 1, 45, 90) + + Notes + ----- + This function is inverted by :func:`cartesian_to_tangetplane`. + + See Also + -------- + :func:`cartesian_to_tangentplane` + """ + phi = np.radians(latitude) + theta = np.radians(longitude) + u = -up * np.sin(theta) - vp * np.sin(phi) * np.cos(theta) + v = up * np.cos(theta) - vp * np.sin(phi) * np.sin(theta) + w = vp * np.cos(phi) + + return u, v, w
+ + + +
+[docs] +def coriolis_frequency( + latitude: Union[float, np.ndarray], +) -> Union[float, np.ndarray]: + """ + Return the Coriolis frequency or commonly known `f` parameter in geophysical fluid dynamics. + + Parameters + ---------- + latitude : float or np.ndarray + Latitude in degrees. + + Returns + ------- + f : float or np.ndarray + Signed Coriolis frequency in radian per seconds. + + Examples + -------- + >>> f = coriolis_frequency(np.array([0, 45, 90])) + """ + f = 2 * EARTH_ROTATION_RATE * np.sin(np.radians(latitude)) + + return f
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/clouddrift/wavelet.html b/_modules/clouddrift/wavelet.html new file mode 100644 index 00000000..024a63a3 --- /dev/null +++ b/_modules/clouddrift/wavelet.html @@ -0,0 +1,1322 @@ + + + + + + + + + + clouddrift.wavelet — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + +
+ +

Source code for clouddrift.wavelet

+"""
+This module provides functions for computing wavelet transforms and time-frequency analyses,
+notably using generalized Morse wavelets.
+
+The Python code in this module was translated from the MATLAB implementation
+by J. M. Lilly in the jWavelet module of jLab (http://jmlilly.net/code.html).
+
+Lilly, J. M. (2021), jLab: A data analysis package for Matlab, v.1.7.1,
+doi:10.5281/zenodo.4547006, http://www.jmlilly.net/software.
+
+jLab is licensed under the Creative Commons Attribution-Noncommercial-ShareAlike
+License (https://creativecommons.org/licenses/by-nc-sa/4.0/). The code that is
+directly translated from jLab/jWavelet is licensed under the same license.
+Any other code that is added to this module and that is specific to Python and
+not the MATLAB implementation is licensed under CloudDrift's MIT license.
+"""
+
+import numpy as np
+from typing import Optional, Tuple, Union
+from scipy.special import gamma as _gamma, gammaln as _lgamma
+
+
+
+[docs] +def morse_wavelet_transform( + x: np.ndarray, + gamma: float, + beta: float, + radian_frequency: np.ndarray, + complex: Optional[bool] = False, + order: Optional[int] = 1, + normalization: Optional[str] = "bandpass", + boundary: Optional[str] = "mirror", + time_axis: Optional[int] = -1, +) -> Union[Tuple[np.ndarray], np.ndarray]: + """ + Apply a continuous wavelet transform to an input signal using the generalized Morse + wavelets of Olhede and Walden (2002). The wavelet transform is normalized differently + for complex-valued input than for real-valued input, and this in turns depends on whether the + optional argument ``normalization`` is set to ``"bandpass"`` or ``"energy"`` normalizations. + + Parameters + ---------- + x : np.ndarray + Real- or complex-valued signals. The time axis is assumed to be the last. If not, specify optional + argument `time_axis`. + gamma : float + Gamma parameter of the Morse wavelets. + beta : float + Beta parameter of the Morse wavelets. + radian_frequency : np.ndarray + An array of radian frequencies at which the Fourier transform of the wavelets + reach their maximum amplitudes. ``radian_frequency`` is typically between 0 and 2 * np.pi * 0.5, + the normalized Nyquist radian frequency. + complex : boolean, optional + Specify explicitely if the input signal ``x`` is a complex signal. Default is False which + means that the input is real but that is not explicitely tested by the function. + This choice affects the normalization of the outputs and their interpretation. + See examples below. + time_axis : int, optional + Axis on which the time is defined for input ``x`` (default is last, or -1). + normalization : str, optional + Normalization for the wavelet transforms. By default it is assumed to be + ``"bandpass"`` which uses a bandpass normalization, meaning that the FFT + of the wavelets have peak value of 2 for all central frequencies + ``radian_frequency``. However, if the optional argument ``complex=True`` + is specified, the wavelets will be divided by 2 so that the total + variance of the input complex signal is equal to the sum of the + variances of the returned analytic (positive) and conjugate analytic + (negative) parts. See examples below. The other option is ``"energy"`` + which uses the unit energy normalization. In this last case, the + time-domain wavelet energies ``np.sum(np.abs(wave)**2)`` are always + unity. + boundary : str, optional + The boundary condition to be imposed at the edges of the input signal ``x``. + Allowed values are ``"mirror"``, ``"zeros"``, and ``"periodic"``. Default is ``"mirror"``. + order : int, optional + Order of Morse wavelets, default is 1. + + Returns + ------- + If the input signal is real as specificied by ``complex=False``: + + wtx : np.ndarray + Time-domain wavelet transform of input ``x`` with shape ((x shape without time_axis), orders, frequencies, time_axis) + but with dimensions of length 1 removed (squeezed). + + If the input signal is complex as specificied by ``complex=True``, a tuple is returned: + + wtx_p : np.array + Time-domain positive wavelet transform of input ``x`` with shape ((x shape without time_axis), frequencies, orders), + but with dimensions of length 1 removed (squeezed). + wtx_n : np.array + Time-domain negative wavelet transform of input ``x`` with shape ((x shape without time_axis), frequencies, orders), + but with dimensions of length 1 removed (squeezed). + + Examples + -------- + Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta parameter 4, + at radian frequency 0.2 cycles per unit time: + + >>> x = np.random.random(1024) + >>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2])) + + Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta parameter 4, + for a complex input signal at radian frequency 0.2 cycles per unit time. This case returns the + analytic and conjugate analytic components: + + >>> z = np.random.random(1024) + 1j*np.random.random(1024) + >>> wtz_p, wtz_n = morse_wavelet_transform(z, 3, 4, np.array([2*np.pi*0.2]), complex=True) + + The same result as above can be otained by applying the Morse transform on the real and imaginary + component of z and recombining the results as follows for the "bandpass" normalization: + >>> wtz_real = morse_wavelet_transform(np.real(z)), 3, 4, np.array([2*np.pi*0.2])) + >>> wtz_imag = morse_wavelet_transform(np.imag(z)), 3, 4, np.array([2*np.pi*0.2])) + >>> wtz_p, wtz_n = (wtz_real + 1j*wtz_imag) / 2, (wtz_real - 1j*wtz_imag) / 2 + + For the "energy" normalization, the analytic and conjugate analytic components are obtained as follows + with this alternative method: + >>> wtz_real = morse_wavelet_transform(np.real(z)), 3, 4, np.array([2*np.pi*0.2])) + >>> wtz_imag = morse_wavelet_transform(np.imag(z)), 3, 4, np.array([2*np.pi*0.2])) + >>> wtz_p, wtz_n = (wtz_real + 1j*wtz_imag) / np.sqrt(2), (wtz_real - 1j*wtz_imag) / np.sqrt(2) + + The input signal can have an arbitrary number of dimensions but its ``time_axis`` must be + specified if it is not the last: + + >>> x = np.random.random((1024,10,15)) + >>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]), time_axis=0) + + The default way to handle the boundary conditions is to mirror the ends points + but this can be changed by specifying the chosen boundary method: + + >>> x = np.random.random((10,15,1024)) + >>> wtx = morse_wavelet_transform(x, 3, 4, np.array([2*np.pi*0.2]), boundary="periodic") + + This function can be used to conduct a time-frequency analysis of the input signal by specifying + a range of randian frequencies using the ``morse_logspace_freq`` function as an example: + + >>> x = np.random.random(1024) + >>> gamma = 3 + >>> beta = 4 + >>> radian_frequency = morse_logspace_freq(gamma, beta, np.shape(x)[0]) + >>> wtx = morse_wavelet_transform(x, gamma, beta, radian_frequency) + + Raises + ------ + ValueError + If the time axis is outside of the valid range ([-1, np.ndim(x)-1]). + If boundary optional argument is not in ["mirror", "zeros", "periodic"]``. + If normalization optional argument is not in ["bandpass", "energy"]``. + + See Also + -------- + :func:`morse_wavelet`, :func:`wavelet_transform`, :func:`morse_logspace_freq` + + """ + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(x.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(x.shape) - 1}])." + ) + # generate the wavelet + wavelet, _ = morse_wavelet( + np.shape(x)[time_axis], + gamma, + beta, + radian_frequency, + normalization=normalization, + order=order, + ) + + # apply the wavelet transform, distinguish complex and real cases + if complex: + # imaginary case, divide by 2 the wavelet and return analytic and conjugate analytic + if normalization == "bandpass": + wtx_p = wavelet_transform( + 0.5 * x, wavelet, boundary="mirror", time_axis=time_axis + ) + wtx_n = wavelet_transform( + np.conj(0.5 * x), wavelet, boundary="mirror", time_axis=time_axis + ) + elif normalization == "energy": + wtx_p = wavelet_transform( + x / np.sqrt(2), wavelet, boundary="mirror", time_axis=time_axis + ) + wtx_n = wavelet_transform( + np.conj(x / np.sqrt(2)), wavelet, boundary="mirror", time_axis=time_axis + ) + wtx = wtx_p, wtx_n + + elif not complex: + # real case + wtx = wavelet_transform(x, wavelet, boundary=boundary, time_axis=time_axis) + + else: + raise ValueError( + "`complex` optional argument must be boolean 'True' or 'False'" + ) + + return wtx
+ + + +
+[docs] +def wavelet_transform( + x: np.ndarray, + wavelet: np.ndarray, + boundary: Optional[str] = "mirror", + time_axis: Optional[int] = -1, + freq_axis: Optional[int] = -2, + order_axis: Optional[int] = -3, +) -> np.ndarray: + """ + Apply a continuous wavelet transform to an input signal using an input wavelet + function. Such wavelet can be provided by the function ``morse_wavelet``. + + Parameters + ---------- + x : np.ndarray + Real- or complex-valued signals. + wavelet : np.ndarray + A suite of time-domain wavelets, typically returned by the function ``morse_wavelet``. + The length of the time axis of the wavelets must be the last one and matches the + length of the time axis of x. The other dimensions (axes) of the wavelets (such as orders and frequencies) are + typically organized as orders, frequencies, and time, unless specified by optional arguments freq_axis and order_axis. + The normalization of the wavelets is assumed to be "bandpass", if not, use kwarg normalization="energy", see ``morse_wavelet``. + boundary : str, optional + The boundary condition to be imposed at the edges of the input signal ``x``. + Allowed values are ``"mirror"``, ``"zeros"``, and ``"periodic"``. Default is ``"mirror"``. + time_axis : int, optional + Axis on which the time is defined for input ``x`` (default is last, or -1). Note that the time axis of the + wavelets must be last. + freq_axis : int, optional + Axis of ``wavelet`` for the frequencies (default is second or 1) + order_axis : int, optional + Axis of ``wavelet`` for the orders (default is first or 0) + + Returns + ------- + wtx : np.ndarray + Time-domain wavelet transform of ``x`` with shape ((x shape without time_axis), orders, frequencies, time_axis) + but with dimensions of length 1 removed (squeezed). + + Examples + -------- + Apply a wavelet transform with a Morse wavelet with gamma parameter 3, beta + parameter 4, at radian frequency 0.2 cycles per unit time: + + >>> x = np.random.random(1024) + >>> wavelet, _ = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2])) + >>> wtx = wavelet_transform(x, wavelet) + + The input signal can have an arbitrary number of dimensions but its + ``time_axis`` must be specified if it is not the last: + + >>> x = np.random.random((1024,10,15)) + >>> wavelet, _ = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2])) + >>> wtx = wavelet_transform(x, wavelet,time_axis=0) + + Raises + ------ + ValueError + If the time axis is outside of the valid range ([-1, N-1]). + If the shape of time axis is different for input signal and wavelet. + If boundary optional argument is not in ["mirror", "zeros", "periodic"]``. + + See Also + -------- + :func:`morse_wavelet`, :func:`morse_wavelet_transform`, :func:`morse_freq` + """ + # time_axis must be in valid range + if time_axis < -1 or time_axis > len(x.shape) - 1: + raise ValueError( + f"time_axis ({time_axis}) is outside of the valid range ([-1," + f" {len(x.shape) - 1}])." + ) + # Positions and time arrays must have the same shape. + if x.shape[time_axis] != wavelet.shape[-1]: + raise ValueError("x and wavelet time axes must have the same length.") + + wavelet_ = np.moveaxis(wavelet, [freq_axis, order_axis], [-2, -3]) + + # if x is of dimension 1 we need to expand + # otherwise make sure time axis is last + if np.ndim(x) < 2: + x_ = np.expand_dims(x, axis=0) + else: + x_ = np.moveaxis(x, time_axis, -1) + + # add detrending option eventually + + # apply boundary conditions + if boundary == "mirror": + x_ = np.concatenate((np.flip(x_, axis=-1), x_, np.flip(x_, axis=-1)), axis=-1) + elif boundary == "zeros": + x_ = np.concatenate((np.zeros_like(x_), x_, np.zeros_like(x_)), axis=-1) + elif boundary == "periodic": + pass + else: + raise ValueError("boundary must be one of 'mirror', 'zeros', or 'periodic'.") + + time_length = np.shape(x)[time_axis] + time_length_ = np.shape(x_)[-1] + + # pad wavelet with zeros: JML ok + order_length, freq_length, _ = np.shape(wavelet) + _wavelet = np.zeros((order_length, freq_length, time_length_), dtype=np.cdouble) + + index = slice( + int(np.floor(time_length_ - time_length) / 2), + int(time_length + np.floor(time_length_ - time_length) / 2), + ) + _wavelet[:, :, index] = wavelet_ + + # take fft along axis = -1 + _wavelet_fft = np.fft.fft(_wavelet) + om = 2 * np.pi * np.linspace(0, 1 - 1 / time_length_, time_length_) + if time_length_ % 2 == 0: + _wavelet_fft = ( + _wavelet_fft + * np.exp(1j * -om * (time_length_ + 1) / 2) + * np.sign(np.pi - om) + ) + else: + _wavelet_fft = _wavelet_fft * np.exp(1j * -om * (time_length_ + 1) / 2) + + # here we should be able to automate the tiling without assuming extra dimensions of wave + X_ = np.tile( + np.expand_dims(np.fft.fft(x_), (-3, -2)), + (1, order_length, freq_length, 1), + ) + + # finally the transform; return precision of input `x``; central part only + complex_dtype = np.cdouble if x.dtype == np.single else np.csingle + wtx = np.fft.ifft(X_ * np.conj(_wavelet_fft)).astype(complex_dtype) + wtx = wtx[..., index] + + # reposition the time axis if needed from axis -1 + if time_axis != -1: + wtx = np.moveaxis(wtx, -1, time_axis) + + # remove extra dimensions if needed + wtx = np.squeeze(wtx) + + return wtx
+ + + +
+[docs] +def morse_wavelet( + length: int, + gamma: float, + beta: float, + radian_frequency: np.ndarray, + order: Optional[int] = 1, + normalization: Optional[str] = "bandpass", +) -> Tuple[np.ndarray, np.ndarray]: + """ + Compute the generalized Morse wavelets of Olhede and Walden (2002), doi: 10.1109/TSP.2002.804066. + + Parameters + ---------- + length : int + Length of the wavelets. + gamma : float + Gamma parameter of the wavelets. + beta : float + Beta parameter of the wavelets. + radian_frequency : np.ndarray + The radian frequencies at which the Fourier transform of the wavelets + reach their maximum amplitudes. radian_frequency is between 0 and 2 * np.pi * 0.5, + the normalized Nyquist radian frequency. + order : int, optional + Order of wavelets, default is 1. + normalization : str, optional + Normalization for the ``wavelet`` output. By default it is assumed to be ``"bandpass"`` + which uses a bandpass normalization, meaning that the FFT of the wavelets + have peak value of 2 for all central frequencies ``radian_frequency``. The other option is + ``"energy"``which uses the unit energy normalization. In this last case, the time-domain wavelet + energies ``np.sum(np.abs(wave)**2)`` are always unity. + + Returns + ------- + wavelet : np.ndarray + Time-domain wavelets with shape (order, radian_frequency, length). + wavelet_fft: np.ndarray + Frequency-domain wavelets with shape (order, radian_frequency, length). + + Examples + -------- + Compute a Morse wavelet with gamma parameter 3, beta parameter 4, at radian + frequency 0.2 cycles per unit time: + + >>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2])) + >>> np.shape(wavelet) + (1, 1, 1024) + + Compute a suite of Morse wavelets with gamma parameter 3, beta parameter 4, up to order 3, + at radian frequencies 0.2 and 0.3 cycles per unit time: + + >>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2, 2*np.pi*0.3]), order=3) + >>> np.shape(wavelet) + (3, 2, 1024) + + Compute a Morse wavelet specifying an energy normalization : + >>> wavelet, wavelet_fft = morse_wavelet(1024, 3, 4, np.array([2*np.pi*0.2]), normalization="energy") + + Raises + ------ + ValueError + If normalization optional argument is not in ["bandpass", "energy"]``. + + See Also + -------- + :func:`wavelet_transform`, :func:`morse_wavelet_transform`, :func:`morse_freq`, :func:`morse_logspace_freq`, :func:`morse_amplitude`, :func:`morse_properties` + """ + # ad test for radian_frequency being a numpy array + # initialization + wavelet = np.zeros((length, order, len(radian_frequency)), dtype=np.cdouble) + waveletfft = np.zeros((length, order, len(radian_frequency)), dtype=np.cdouble) + + # call to morse_wavelet take only gamma and be as float, no array + fo, _, _ = morse_freq(gamma, beta) + for i in range(len(radian_frequency)): + wavelet_tmp = np.zeros((length, order), dtype=np.cdouble) + waveletfft_tmp = np.zeros((length, order), dtype=np.cdouble) + + # wavelet frequencies + fact = np.abs(radian_frequency[i]) / fo + # norm_radian_frequency first dim is n points + norm_radian_frequency = ( + 2 * np.pi * np.linspace(0, 1 - 1 / length, length) / fact + ) + if normalization == "energy": + with np.errstate(divide="ignore"): + waveletzero = np.exp( + beta * np.log(norm_radian_frequency) + - norm_radian_frequency**gamma + ) + elif normalization == "bandpass": + if beta == 0: + waveletzero = 2 * np.exp(-(norm_radian_frequency**gamma)) + else: + with np.errstate(divide="ignore"): + waveletzero = 2 * np.exp( + -beta * np.log(fo) + + fo**gamma + + beta * np.log(norm_radian_frequency) + - norm_radian_frequency**gamma + ) + else: + raise ValueError( + "Normalization option (norm) must be one of 'energy' or 'bandpass'." + ) + waveletzero[0] = 0.5 * waveletzero[0] + # Replace NaN with zeros in waveletzero + waveletzero = np.nan_to_num(waveletzero, copy=False, nan=0.0) + # second family is never used + waveletfft_tmp = _morse_wavelet_first_family( + fact, + gamma, + beta, + norm_radian_frequency, + waveletzero, + order=order, + normalization=normalization, + ) + waveletfft_tmp = np.nan_to_num(waveletfft_tmp, posinf=0, neginf=0) + # shape of waveletfft_tmp is points, order + # center wavelet + norm_radian_frequency_mat = np.tile( + np.expand_dims(norm_radian_frequency, -1), (order) + ) + waveletfft_tmp = waveletfft_tmp * np.exp( + 1j * norm_radian_frequency_mat * (length + 1) / 2 * fact + ) + # time domain waveletlet + wavelet_tmp = np.fft.ifft(waveletfft_tmp, axis=0) + if radian_frequency[i] < 0: + wavelet[:, :, i] = np.conj(wavelet_tmp) + waveletfft_tmp[1:-1, :] = np.flip(waveletfft_tmp[1:-1, :], axis=0) + waveletfft[:, :, i] = waveletfft_tmp + else: + waveletfft[:, :, i] = waveletfft_tmp + wavelet[:, :, i] = wavelet_tmp + + # reorder dimension to be (order, frequency, time steps) + # enforce length 1 for first axis if order=1 (no squeezing) + wavelet = np.moveaxis(wavelet, [0, 1, 2], [2, 0, 1]) + waveletfft = np.moveaxis(waveletfft, [0, 1, 2], [2, 0, 1]) + + return wavelet, waveletfft
+ + + +def _morse_wavelet_first_family( + fact: float, + gamma: float, + beta: float, + norm_radian_frequency: np.ndarray, + wavezero: np.ndarray, + order: Optional[int] = 1, + normalization: Optional[str] = "bandpass", +) -> np.ndarray: + """ + Derive first family of Morse wavelets. Internal use only. + """ + r = (2 * beta + 1) / gamma + c = r - 1 + L = np.zeros_like(norm_radian_frequency, dtype=np.float64) + wavefft1 = np.zeros((np.shape(wavezero)[0], order)) + + for i in np.arange(0, order): + if normalization == "energy": + A = morse_amplitude(gamma, beta, order=i + 1, normalization=normalization) + coeff = np.sqrt(1 / fact) * A + elif normalization == "bandpass": + if beta != 0: + coeff = np.sqrt(np.exp(_lgamma(r) + _lgamma(i + 1) - _lgamma(i + r))) + else: + coeff = 1 + + index = slice( + 0, int(np.round(np.shape(wavezero)[0] / 2)) + ) # how to define indices? + L[index] = _laguerre(2 * norm_radian_frequency[index] ** gamma, i, c) + wavefft1[:, i] = coeff * wavezero * L + + return wavefft1 + + +
+[docs] +def morse_freq( + gamma: Union[np.ndarray, float], + beta: Union[np.ndarray, float], +) -> Union[Tuple[np.ndarray], Tuple[float]]: + """ + Frequency measures for generalized Morse wavelets. This functions calculates + three different measures fm, fe, and fi of the frequency of the lowest-order generalized Morse + wavelet specified by parameters ``gamma`` and ``beta``. + + Note that all frequency quantities here are in *radian* as in cos(f t) and not + cyclic as in np.cos(2 np.pi f t). + + For ``beta=0``, the corresponding wavelet becomes an analytic lowpass filter, and fm + is not defined in the usual way but as the point at which the filter has decayed + to one-half of its peak power. + + For details see Lilly and Olhede (2009), doi: 10.1109/TSP.2008.2007607. + + Parameters + ---------- + gamma : np.ndarray or float + Gamma parameter of the wavelets. + beta : np.ndarray or float + Beta parameter of the wavelets. + + Returns + ------- + fm : np.ndarray + The modal or peak frequency. + fe : np.ndarray + The energy frequency. + fi : np.ndarray + The instantaneous frequency at the wavelets' centers. + + Examples + -------- + >>> fm, fe, fi = morse_freq(3, 4) + + >>> morse_freq(3, 4) + (array(1.10064242), 1.1025129235952809, 1.1077321674324723) + + >>> morse_freq(3, np.array([10, 20, 30])) + (array([1.49380158, 1.88207206, 2.15443469]), + array([1.49421505, 1.88220264, 2.15450116]), + array([1.49543843, 1.88259299, 2.15470024])) + + >>> morse_freq(np.array([3, 4, 5]), np.array([10, 20, 30])) + (array([1.49380158, 1.49534878, 1.43096908]), + array([1.49421505, 1.49080278, 1.4262489 ]), + array([1.49543843, 1.48652036, 1.42163583])) + + >>> morse_freq(np.array([3, 4, 5]), 10) + (array([1.49380158, 1.25743343, 1.14869835]), + array([1.49421505, 1.25000964, 1.13759731]), + array([1.49543843, 1.24350315, 1.12739747])) + + See Also + -------- + :func:`morse_wavelet`, :func:`morse_amplitude` + """ + with np.errstate(divide="ignore"): # ignore warning when beta=0 + fm = np.where( + beta == 0, + np.log(2) ** (1 / gamma), + np.exp((1 / gamma) * (np.log(beta) - np.log(gamma))), + ) + + fe = ( + 1 + / (2 ** (1 / gamma)) + * _gamma((2 * beta + 2) / gamma) + / _gamma((2 * beta + 1) / gamma) + ) + + fi = _gamma((beta + 2) / gamma) / _gamma((beta + 1) / gamma) + + return fm, fe, fi
+ + + +
+[docs] +def morse_logspace_freq( + gamma: float, + beta: float, + length: int, + highset: Optional[Tuple[float]] = (0.1, np.pi), + lowset: Optional[Tuple[float]] = (5, 0), + density: Optional[int] = 4, +) -> np.ndarray: + """ + Compute logarithmically-spaced frequencies for generalized Morse wavelets + with parameters gamma and beta. This is a useful function to obtain the frequencies + needed for time-frequency analyses using wavelets. If ``radian_frequencies`` is the + output, ``np.log(radian_frequencies)`` is uniformly spaced, following convention + for wavelet analysis. See Lilly (2017), doi: 10.1098/rspa.2016.0776. + + Default settings to compute the frequencies can be changed by passing optional + arguments ``lowset``, ``highset``, and ``density``. See below. + + Parameters + ---------- + gamma : float + Gamma parameter of the Morse wavelets. + beta : float + Beta parameter of the Morse wavelets. + length : int + Length of the Morse wavelets and input signals. + highset : tuple of floats, optional. + Tuple of values (eta, high) used for high-frequency cutoff calculation. The highest + frequency is set to be the minimum of a specified value and a cutoff frequency + based on a Nyquist overlap condition: the highest frequency is the minimum of + the specified value high, and the largest frequency for which the wavelet will + satisfy the threshold level eta. Here eta be a number between zero and one + specifying the ratio of a frequency-domain wavelet at the Nyquist frequency + to its peak value. Default is (eta, high) = (0.1, np.pi). + lowset : tuple of floats, optional. + Tupe of values (P, low) set used for low-frequency cutoff calculation based on an + endpoint overlap condition. The lowest frequency is set such that the lowest-frequency + wavelet will reach some number P, called the packing number, times its central window + width at the ends of the time series. A choice of P=1 corresponds to roughly 95% of + the time-domain wavelet energy being contained within the time series endpoints for + a wavelet at the center of the domain. The second value of the tuple is the absolute + lowest frequency. Default is (P, low) = (5, 0). + density : int, optional + This optional argument controls the number of points in the returned frequency + array. Higher values of ``density`` mean more overlap in the frequency + domain between transforms. When ``density=1``, the peak of one wavelet is located at the + half-power points of the adjacent wavelet. The default ``density=4`` means + that four other wavelets will occur between the peak of one wavelet and + its half-power point. + + Returns + ------- + radian_frequency : np.ndarray + Logarithmically-spaced frequencies in radians cycles per unit time, + sorted in descending order. + + Examples + -------- + Generate a frequency array for the generalized Morse wavelet + with parameters gamma=3 and beta=5 for a time series of length n=1024: + + >>> radian_frequency = morse_logspace_freq(3, 5, 1024) + >>> radian_frequency = morse_logspace_freq(3, 5, 1024, highset=(0.2, np.pi), lowset=(5, 0)) + >>> radian_frequency = morse_logspace_freq(3, 5, 1024, highset=(0.2, np.pi), lowset=(5, 0), density=10) + + See Also + -------- + :func:`morse_wavelet`, :func:`morse_freq`, :func:`morse_properties` + """ + gamma_ = np.array([gamma]) + beta_ = np.array([beta]) + width, _, _ = morse_properties(gamma_, beta_) + + _high = _morsehigh(gamma_, beta_, highset[0]) + high_ = np.min(np.append(_high, highset[1])) + + low = 2 * np.sqrt(2) * width * lowset[0] / length + low_ = np.max(np.append(low, lowset[1])) + + r = 1 + 1 / (density * width) + m = np.floor(np.log10(high_ / low_) / np.log10(r)).astype(int)[0] + radian_frequency = high_ * np.ones(int(m + 1)) / r ** np.arange(0, m + 1) + + return radian_frequency
+ + + +def _morsehigh( + gamma: np.ndarray, + beta: np.ndarray, + eta: float, +) -> Union[np.ndarray, float]: + """High-frequency cutoff of the generalized Morse wavelets. + gamma and be should be arrays of the same length. Internal use only. + """ + m = 10000 + omhigh = np.linspace(0, np.pi, m) + f = np.zeros_like(gamma, dtype="float") + + for i in range(0, len(gamma)): + fm, _, _ = morse_freq(gamma[i], beta[i]) + with np.errstate(all="ignore"): + om = fm * np.pi / omhigh + lnwave1 = beta[i] / gamma[i] * np.log(np.exp(1) * gamma[i] / beta[i]) + lnwave2 = beta[i] * np.log(om) - om ** gamma[i] + lnwave = lnwave1 + lnwave2 + index = np.nonzero(np.log(eta) - lnwave < 0)[0][0] + f[i] = omhigh[index] + + return f + + +
+[docs] +def morse_properties( + gamma: Union[np.ndarray, float], + beta: Union[np.ndarray, float], +) -> Union[Tuple[np.ndarray], Tuple[float]]: + """ + Calculate the properties of the demodulated generalized Morse wavelets. + See Lilly and Olhede (2009), doi: 10.1109/TSP.2008.2007607. + + Parameters + ---------- + gamma : np.ndarray or float + Gamma parameter of the wavelets. + beta : np.ndarray or float + Beta parameter of the wavelets. + + Returns + ------- + width : np.ndarray or float + Dimensionless time-domain window width of the wavelets. + skew : np.ndarray or float + Imaginary part of normalized third moment of the time-domain demodulate, + or 'demodulate skewness'. + kurt : np.ndarray or float + Normalized fourth moment of the time-domain demodulate, + or 'demodulate kurtosis'. + + Examples + -------- + TODO + + See Also + -------- + :func:`morse_wavelet`, :func:`morse_freq`, :func:`morse_amplitude`, :func:`morse_logspace_freq`. + """ + # test common size? or could be broadcasted + width = np.sqrt(gamma * beta) + skew = (gamma - 3) / width + kurt = 3 - skew**2 - 2 / width**2 + + return width, skew, kurt
+ + + +
+[docs] +def morse_amplitude( + gamma: Union[np.ndarray, float], + beta: Union[np.ndarray, float], + order: Optional[np.int64] = 1, + normalization: Optional[str] = "bandpass", +) -> float: + """ + Calculate the amplitude coefficient of the generalized Morse wavelets. + By default, the amplitude is calculated such that the maximum of the + frequency-domain wavelet is equal to 2, which is the bandpass normalization. + Optionally, specify ``normalization="energy"`` in order to return the coefficient + giving the wavelets unit energies. See Lilly and Olhede (2009), doi doi: 10.1109/TSP.2008.2007607. + + Parameters + ---------- + gamma : np.ndarray or float + Gamma parameter of the wavelets. + beta : np.ndarray or float + Beta parameter of the wavelets. + order : int, optional + Order of wavelets, default is 1. + normalization : str, optional + Normalization for the wavelets. By default it is assumed to be ``"bandpass"`` + which uses a bandpass normalization, meaning that the FFT of the wavelets + have peak value of 2 for all central frequencies ``radian_frequency``. The other option is ``"energy"`` + which uses the unit energy normalization. In this last case the time-domain wavelet + energies ``np.sum(np.abs(wave)**2)`` are always unity. + + Returns + ------- + amp : np.ndarray or float + The amplitude coefficient of the wavelets. + + Examples + -------- + TODO + + See Also + -------- + :func:`morse_wavelet`, :func:`morse_freq`, :func:`morse_properties`, :func:`morse_logspace_freq`. + """ + # add test for type and shape in case of ndarray + if normalization == "energy": + r = (2 * beta + 1) / gamma + amp = ( + 2 + * np.pi + * gamma + * (2**r) + * np.exp(_lgamma(order) - _lgamma(order + r - 1)) + ) ** 0.5 + elif normalization == "bandpass": + fm, _, _ = morse_freq(gamma, beta) + amp = np.where(beta == 0, 2, 2 / (np.exp(beta * np.log(fm) - fm**gamma))) + else: + raise ValueError( + "Normalization option (normalization) must be one of 'energy' or 'bandpass'." + ) + + return amp
+ + + +def _laguerre( + x: Union[np.ndarray, float], + k: float, + c: float, +) -> np.ndarray: + """Generalized Laguerre polynomials""" + y = np.zeros_like(x, dtype="float") + for i in np.arange(0, k + 1): + fact = np.exp(_lgamma(k + c + 1) - _lgamma(c + i + 1) - _lgamma(k - i + 1)) + y = y + (-1) ** i * fact * x**i / _gamma(i + 1) + return y +
+ +
+ + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 00000000..bf527bb0 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,486 @@ + + + + + + + + + + Overview: module code — CloudDrift documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

+ +
+
+ +
+
+
+ + + + + + + + + + + +
+ +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.rst b/_sources/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.rst new file mode 100644 index 00000000..dbea8a8e --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.cast_float64_variables_to_float32.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.cast\_float64\_variables\_to\_float32 +============================================================= + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: cast_float64_variables_to_float32 \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.cut_str.rst b/_sources/_autosummary/clouddrift.adapters.gdp.cut_str.rst new file mode 100644 index 00000000..bb1786e9 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.cut_str.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.cut\_str +================================ + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: cut_str \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.decode_date.rst b/_sources/_autosummary/clouddrift.adapters.gdp.decode_date.rst new file mode 100644 index 00000000..62449b7a --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.decode_date.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.decode\_date +==================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: decode_date \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.drogue_presence.rst b/_sources/_autosummary/clouddrift.adapters.gdp.drogue_presence.rst new file mode 100644 index 00000000..0a7a649e --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.drogue_presence.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.drogue\_presence +======================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: drogue_presence \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.rst b/_sources/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.rst new file mode 100644 index 00000000..4d08cedd --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.fetch_netcdf.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.fetch\_netcdf +===================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: fetch_netcdf \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.fill_values.rst b/_sources/_autosummary/clouddrift.adapters.gdp.fill_values.rst new file mode 100644 index 00000000..fdaf3967 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.fill_values.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.fill\_values +==================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: fill_values \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.rst b/_sources/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.rst new file mode 100644 index 00000000..bfae0290 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.get_gdp_metadata.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.get\_gdp\_metadata +========================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: get_gdp_metadata \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.order_by_date.rst b/_sources/_autosummary/clouddrift.adapters.gdp.order_by_date.rst new file mode 100644 index 00000000..f0e80cb5 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.order_by_date.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.order\_by\_date +======================================= + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: order_by_date \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.parse_directory_file.rst b/_sources/_autosummary/clouddrift.adapters.gdp.parse_directory_file.rst new file mode 100644 index 00000000..fbf192b9 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.parse_directory_file.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.parse\_directory\_file +============================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: parse_directory_file \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.rowsize.rst b/_sources/_autosummary/clouddrift.adapters.gdp.rowsize.rst new file mode 100644 index 00000000..71432532 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.rowsize.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.rowsize +=============================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: rowsize \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.rst b/_sources/_autosummary/clouddrift.adapters.gdp.rst new file mode 100644 index 00000000..2088d1b8 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.rst @@ -0,0 +1,41 @@ +clouddrift.adapters.gdp +======================= + +.. automodule:: clouddrift.adapters.gdp + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + cast_float64_variables_to_float32 + cut_str + decode_date + drogue_presence + fetch_netcdf + fill_values + get_gdp_metadata + order_by_date + parse_directory_file + rowsize + str_to_float + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.adapters.gdp.str_to_float.rst b/_sources/_autosummary/clouddrift.adapters.gdp.str_to_float.rst new file mode 100644 index 00000000..eea69cd5 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp.str_to_float.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp.str\_to\_float +====================================== + +.. currentmodule:: clouddrift.adapters.gdp + +.. autofunction:: str_to_float \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp1h.download.rst b/_sources/_autosummary/clouddrift.adapters.gdp1h.download.rst new file mode 100644 index 00000000..73404cf7 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp1h.download.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp1h.download +================================== + +.. currentmodule:: clouddrift.adapters.gdp1h + +.. autofunction:: download \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp1h.preprocess.rst b/_sources/_autosummary/clouddrift.adapters.gdp1h.preprocess.rst new file mode 100644 index 00000000..4eefda7a --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp1h.preprocess.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp1h.preprocess +==================================== + +.. currentmodule:: clouddrift.adapters.gdp1h + +.. autofunction:: preprocess \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp1h.rst b/_sources/_autosummary/clouddrift.adapters.gdp1h.rst new file mode 100644 index 00000000..908c49e0 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp1h.rst @@ -0,0 +1,33 @@ +clouddrift.adapters.gdp1h +========================= + +.. automodule:: clouddrift.adapters.gdp1h + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + download + preprocess + to_raggedarray + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.rst b/_sources/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.rst new file mode 100644 index 00000000..046b40dc --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp1h.to_raggedarray.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp1h.to\_raggedarray +========================================= + +.. currentmodule:: clouddrift.adapters.gdp1h + +.. autofunction:: to_raggedarray \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp6h.download.rst b/_sources/_autosummary/clouddrift.adapters.gdp6h.download.rst new file mode 100644 index 00000000..30fa0927 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp6h.download.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp6h.download +================================== + +.. currentmodule:: clouddrift.adapters.gdp6h + +.. autofunction:: download \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp6h.preprocess.rst b/_sources/_autosummary/clouddrift.adapters.gdp6h.preprocess.rst new file mode 100644 index 00000000..a9653f9e --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp6h.preprocess.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp6h.preprocess +==================================== + +.. currentmodule:: clouddrift.adapters.gdp6h + +.. autofunction:: preprocess \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.gdp6h.rst b/_sources/_autosummary/clouddrift.adapters.gdp6h.rst new file mode 100644 index 00000000..2d038ddf --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp6h.rst @@ -0,0 +1,33 @@ +clouddrift.adapters.gdp6h +========================= + +.. automodule:: clouddrift.adapters.gdp6h + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + download + preprocess + to_raggedarray + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.rst b/_sources/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.rst new file mode 100644 index 00000000..d455ad5d --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.gdp6h.to_raggedarray.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.gdp6h.to\_raggedarray +========================================= + +.. currentmodule:: clouddrift.adapters.gdp6h + +.. autofunction:: to_raggedarray \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.glad.get_dataframe.rst b/_sources/_autosummary/clouddrift.adapters.glad.get_dataframe.rst new file mode 100644 index 00000000..3bc0c352 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.glad.get_dataframe.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.glad.get\_dataframe +======================================= + +.. currentmodule:: clouddrift.adapters.glad + +.. autofunction:: get_dataframe \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.glad.rst b/_sources/_autosummary/clouddrift.adapters.glad.rst new file mode 100644 index 00000000..4c3608fa --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.glad.rst @@ -0,0 +1,32 @@ +clouddrift.adapters.glad +======================== + +.. automodule:: clouddrift.adapters.glad + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + get_dataframe + to_xarray + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.adapters.glad.to_xarray.rst b/_sources/_autosummary/clouddrift.adapters.glad.to_xarray.rst new file mode 100644 index 00000000..c4709c86 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.glad.to_xarray.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.glad.to\_xarray +=================================== + +.. currentmodule:: clouddrift.adapters.glad + +.. autofunction:: to_xarray \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.mosaic.get_dataframes.rst b/_sources/_autosummary/clouddrift.adapters.mosaic.get_dataframes.rst new file mode 100644 index 00000000..3cab1328 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.mosaic.get_dataframes.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.mosaic.get\_dataframes +========================================== + +.. currentmodule:: clouddrift.adapters.mosaic + +.. autofunction:: get_dataframes \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.mosaic.get_file_urls.rst b/_sources/_autosummary/clouddrift.adapters.mosaic.get_file_urls.rst new file mode 100644 index 00000000..9bcb3c25 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.mosaic.get_file_urls.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.mosaic.get\_file\_urls +========================================== + +.. currentmodule:: clouddrift.adapters.mosaic + +.. autofunction:: get_file_urls \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.rst b/_sources/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.rst new file mode 100644 index 00000000..b349a8cd --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.mosaic.get_repository_metadata.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.mosaic.get\_repository\_metadata +==================================================== + +.. currentmodule:: clouddrift.adapters.mosaic + +.. autofunction:: get_repository_metadata \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.mosaic.rst b/_sources/_autosummary/clouddrift.adapters.mosaic.rst new file mode 100644 index 00000000..556f64be --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.mosaic.rst @@ -0,0 +1,34 @@ +clouddrift.adapters.mosaic +========================== + +.. automodule:: clouddrift.adapters.mosaic + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + get_dataframes + get_file_urls + get_repository_metadata + to_xarray + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.adapters.mosaic.to_xarray.rst b/_sources/_autosummary/clouddrift.adapters.mosaic.to_xarray.rst new file mode 100644 index 00000000..8041998e --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.mosaic.to_xarray.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.mosaic.to\_xarray +===================================== + +.. currentmodule:: clouddrift.adapters.mosaic + +.. autofunction:: to_xarray \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.subsurface_floats.download.rst b/_sources/_autosummary/clouddrift.adapters.subsurface_floats.download.rst new file mode 100644 index 00000000..9d08b36e --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.subsurface_floats.download.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.subsurface\_floats.download +=============================================== + +.. currentmodule:: clouddrift.adapters.subsurface_floats + +.. autofunction:: download \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.adapters.subsurface_floats.rst b/_sources/_autosummary/clouddrift.adapters.subsurface_floats.rst new file mode 100644 index 00000000..d6701ce1 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.subsurface_floats.rst @@ -0,0 +1,32 @@ +clouddrift.adapters.subsurface\_floats +====================================== + +.. automodule:: clouddrift.adapters.subsurface_floats + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + download + to_xarray + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.rst b/_sources/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.rst new file mode 100644 index 00000000..d609c841 --- /dev/null +++ b/_sources/_autosummary/clouddrift.adapters.subsurface_floats.to_xarray.rst @@ -0,0 +1,6 @@ +clouddrift.adapters.subsurface\_floats.to\_xarray +================================================= + +.. currentmodule:: clouddrift.adapters.subsurface_floats + +.. autofunction:: to_xarray \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.andro.rst b/_sources/_autosummary/clouddrift.datasets.andro.rst new file mode 100644 index 00000000..4c098fea --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.andro.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.andro +========================= + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: andro \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.gdp1h.rst b/_sources/_autosummary/clouddrift.datasets.gdp1h.rst new file mode 100644 index 00000000..81957f3c --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.gdp1h.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.gdp1h +========================= + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: gdp1h \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.gdp6h.rst b/_sources/_autosummary/clouddrift.datasets.gdp6h.rst new file mode 100644 index 00000000..bf7159b0 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.gdp6h.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.gdp6h +========================= + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: gdp6h \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.glad.rst b/_sources/_autosummary/clouddrift.datasets.glad.rst new file mode 100644 index 00000000..5fba87d8 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.glad.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.glad +======================== + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: glad \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.mosaic.rst b/_sources/_autosummary/clouddrift.datasets.mosaic.rst new file mode 100644 index 00000000..00d04959 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.mosaic.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.mosaic +========================== + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: mosaic \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.rst b/_sources/_autosummary/clouddrift.datasets.rst new file mode 100644 index 00000000..87f043a1 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.rst @@ -0,0 +1,38 @@ +clouddrift.datasets +=================== + +.. automodule:: clouddrift.datasets + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + andro + gdp1h + gdp6h + glad + mosaic + spotters + subsurface_floats + yomaha + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.datasets.spotters.rst b/_sources/_autosummary/clouddrift.datasets.spotters.rst new file mode 100644 index 00000000..e36c57d3 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.spotters.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.spotters +============================ + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: spotters \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.subsurface_floats.rst b/_sources/_autosummary/clouddrift.datasets.subsurface_floats.rst new file mode 100644 index 00000000..92168de2 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.subsurface_floats.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.subsurface\_floats +====================================== + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: subsurface_floats \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.datasets.yomaha.rst b/_sources/_autosummary/clouddrift.datasets.yomaha.rst new file mode 100644 index 00000000..eb39b026 --- /dev/null +++ b/_sources/_autosummary/clouddrift.datasets.yomaha.rst @@ -0,0 +1,6 @@ +clouddrift.datasets.yomaha +========================== + +.. currentmodule:: clouddrift.datasets + +.. autofunction:: yomaha \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.rst b/_sources/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.rst new file mode 100644 index 00000000..05ef021c --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.inertial_oscillation_from_position.rst @@ -0,0 +1,6 @@ +clouddrift.kinematics.inertial\_oscillation\_from\_position +=========================================================== + +.. currentmodule:: clouddrift.kinematics + +.. autofunction:: inertial_oscillation_from_position \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.kinematics.kinetic_energy.rst b/_sources/_autosummary/clouddrift.kinematics.kinetic_energy.rst new file mode 100644 index 00000000..67455f5b --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.kinetic_energy.rst @@ -0,0 +1,6 @@ +clouddrift.kinematics.kinetic\_energy +===================================== + +.. currentmodule:: clouddrift.kinematics + +.. autofunction:: kinetic_energy \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.kinematics.position_from_velocity.rst b/_sources/_autosummary/clouddrift.kinematics.position_from_velocity.rst new file mode 100644 index 00000000..e7f6e94e --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.position_from_velocity.rst @@ -0,0 +1,6 @@ +clouddrift.kinematics.position\_from\_velocity +============================================== + +.. currentmodule:: clouddrift.kinematics + +.. autofunction:: position_from_velocity \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.kinematics.residual_position_from_displacement.rst b/_sources/_autosummary/clouddrift.kinematics.residual_position_from_displacement.rst new file mode 100644 index 00000000..a3662a4b --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.residual_position_from_displacement.rst @@ -0,0 +1,6 @@ +clouddrift.kinematics.residual\_position\_from\_displacement +============================================================ + +.. currentmodule:: clouddrift.kinematics + +.. autofunction:: residual_position_from_displacement \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.kinematics.rst b/_sources/_autosummary/clouddrift.kinematics.rst new file mode 100644 index 00000000..f2f7e742 --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.rst @@ -0,0 +1,36 @@ +clouddrift.kinematics +===================== + +.. automodule:: clouddrift.kinematics + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + inertial_oscillation_from_position + kinetic_energy + position_from_velocity + residual_position_from_displacement + spin + velocity_from_position + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.kinematics.spin.rst b/_sources/_autosummary/clouddrift.kinematics.spin.rst new file mode 100644 index 00000000..1e635bda --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.spin.rst @@ -0,0 +1,6 @@ +clouddrift.kinematics.spin +========================== + +.. currentmodule:: clouddrift.kinematics + +.. autofunction:: spin \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.kinematics.velocity_from_position.rst b/_sources/_autosummary/clouddrift.kinematics.velocity_from_position.rst new file mode 100644 index 00000000..c4981723 --- /dev/null +++ b/_sources/_autosummary/clouddrift.kinematics.velocity_from_position.rst @@ -0,0 +1,6 @@ +clouddrift.kinematics.velocity\_from\_position +============================================== + +.. currentmodule:: clouddrift.kinematics + +.. autofunction:: velocity_from_position \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.chance_pair.rst b/_sources/_autosummary/clouddrift.pairs.chance_pair.rst new file mode 100644 index 00000000..1ec1fa3d --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.chance_pair.rst @@ -0,0 +1,6 @@ +clouddrift.pairs.chance\_pair +============================= + +.. currentmodule:: clouddrift.pairs + +.. autofunction:: chance_pair \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.rst b/_sources/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.rst new file mode 100644 index 00000000..685fb995 --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.chance_pairs_from_ragged.rst @@ -0,0 +1,6 @@ +clouddrift.pairs.chance\_pairs\_from\_ragged +============================================ + +.. currentmodule:: clouddrift.pairs + +.. autofunction:: chance_pairs_from_ragged \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.rst b/_sources/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.rst new file mode 100644 index 00000000..b3ea30b2 --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.pair_bounding_box_overlap.rst @@ -0,0 +1,6 @@ +clouddrift.pairs.pair\_bounding\_box\_overlap +============================================= + +.. currentmodule:: clouddrift.pairs + +.. autofunction:: pair_bounding_box_overlap \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.pair_space_distance.rst b/_sources/_autosummary/clouddrift.pairs.pair_space_distance.rst new file mode 100644 index 00000000..876afc5a --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.pair_space_distance.rst @@ -0,0 +1,6 @@ +clouddrift.pairs.pair\_space\_distance +====================================== + +.. currentmodule:: clouddrift.pairs + +.. autofunction:: pair_space_distance \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.pair_time_distance.rst b/_sources/_autosummary/clouddrift.pairs.pair_time_distance.rst new file mode 100644 index 00000000..62e06df9 --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.pair_time_distance.rst @@ -0,0 +1,6 @@ +clouddrift.pairs.pair\_time\_distance +===================================== + +.. currentmodule:: clouddrift.pairs + +.. autofunction:: pair_time_distance \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.pair_time_overlap.rst b/_sources/_autosummary/clouddrift.pairs.pair_time_overlap.rst new file mode 100644 index 00000000..692f5d5b --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.pair_time_overlap.rst @@ -0,0 +1,6 @@ +clouddrift.pairs.pair\_time\_overlap +==================================== + +.. currentmodule:: clouddrift.pairs + +.. autofunction:: pair_time_overlap \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.pairs.rst b/_sources/_autosummary/clouddrift.pairs.rst new file mode 100644 index 00000000..0c6ac09d --- /dev/null +++ b/_sources/_autosummary/clouddrift.pairs.rst @@ -0,0 +1,36 @@ +clouddrift.pairs +================ + +.. automodule:: clouddrift.pairs + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + chance_pair + chance_pairs_from_ragged + pair_bounding_box_overlap + pair_space_distance + pair_time_distance + pair_time_overlap + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.plotting.plot_ragged.rst b/_sources/_autosummary/clouddrift.plotting.plot_ragged.rst new file mode 100644 index 00000000..922dad62 --- /dev/null +++ b/_sources/_autosummary/clouddrift.plotting.plot_ragged.rst @@ -0,0 +1,6 @@ +clouddrift.plotting.plot\_ragged +================================ + +.. currentmodule:: clouddrift.plotting + +.. autofunction:: plot_ragged \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.plotting.rst b/_sources/_autosummary/clouddrift.plotting.rst new file mode 100644 index 00000000..f5010642 --- /dev/null +++ b/_sources/_autosummary/clouddrift.plotting.rst @@ -0,0 +1,31 @@ +clouddrift.plotting +=================== + +.. automodule:: clouddrift.plotting + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + plot_ragged + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.ragged.apply_ragged.rst b/_sources/_autosummary/clouddrift.ragged.apply_ragged.rst new file mode 100644 index 00000000..7f8ebef0 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.apply_ragged.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.apply\_ragged +=============================== + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: apply_ragged \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.chunk.rst b/_sources/_autosummary/clouddrift.ragged.chunk.rst new file mode 100644 index 00000000..fd5a8e75 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.chunk.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.chunk +======================= + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: chunk \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.prune.rst b/_sources/_autosummary/clouddrift.ragged.prune.rst new file mode 100644 index 00000000..77ef6d8c --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.prune.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.prune +======================= + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: prune \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.ragged_to_regular.rst b/_sources/_autosummary/clouddrift.ragged.ragged_to_regular.rst new file mode 100644 index 00000000..50c0a58a --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.ragged_to_regular.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.ragged\_to\_regular +===================================== + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: ragged_to_regular \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.regular_to_ragged.rst b/_sources/_autosummary/clouddrift.ragged.regular_to_ragged.rst new file mode 100644 index 00000000..fac8b976 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.regular_to_ragged.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.regular\_to\_ragged +===================================== + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: regular_to_ragged \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.rowsize_to_index.rst b/_sources/_autosummary/clouddrift.ragged.rowsize_to_index.rst new file mode 100644 index 00000000..49758c65 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.rowsize_to_index.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.rowsize\_to\_index +==================================== + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: rowsize_to_index \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.rst b/_sources/_autosummary/clouddrift.ragged.rst new file mode 100644 index 00000000..57219478 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.rst @@ -0,0 +1,39 @@ +clouddrift.ragged +================= + +.. automodule:: clouddrift.ragged + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + apply_ragged + chunk + prune + ragged_to_regular + regular_to_ragged + rowsize_to_index + segment + subset + unpack + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.ragged.segment.rst b/_sources/_autosummary/clouddrift.ragged.segment.rst new file mode 100644 index 00000000..9291fd1d --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.segment.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.segment +========================= + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: segment \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.subset.rst b/_sources/_autosummary/clouddrift.ragged.subset.rst new file mode 100644 index 00000000..5c3953d6 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.subset.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.subset +======================== + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: subset \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.ragged.unpack.rst b/_sources/_autosummary/clouddrift.ragged.unpack.rst new file mode 100644 index 00000000..e9b6faf2 --- /dev/null +++ b/_sources/_autosummary/clouddrift.ragged.unpack.rst @@ -0,0 +1,6 @@ +clouddrift.ragged.unpack +======================== + +.. currentmodule:: clouddrift.ragged + +.. autofunction:: unpack \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.raggedarray.RaggedArray.rst b/_sources/_autosummary/clouddrift.raggedarray.RaggedArray.rst new file mode 100644 index 00000000..b68a671d --- /dev/null +++ b/_sources/_autosummary/clouddrift.raggedarray.RaggedArray.rst @@ -0,0 +1,38 @@ +clouddrift.raggedarray.RaggedArray +================================== + +.. currentmodule:: clouddrift.raggedarray + +.. autoclass:: RaggedArray + :members: + :show-inheritance: + :inherited-members: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~RaggedArray.__init__ + ~RaggedArray.allocate + ~RaggedArray.attributes + ~RaggedArray.from_awkward + ~RaggedArray.from_files + ~RaggedArray.from_netcdf + ~RaggedArray.from_parquet + ~RaggedArray.from_xarray + ~RaggedArray.number_of_observations + ~RaggedArray.to_awkward + ~RaggedArray.to_netcdf + ~RaggedArray.to_parquet + ~RaggedArray.to_xarray + ~RaggedArray.validate_attributes + + + + + + \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.raggedarray.rst b/_sources/_autosummary/clouddrift.raggedarray.rst new file mode 100644 index 00000000..867a9006 --- /dev/null +++ b/_sources/_autosummary/clouddrift.raggedarray.rst @@ -0,0 +1,32 @@ +clouddrift.raggedarray +====================== + +.. automodule:: clouddrift.raggedarray + :members: + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: class.rst + + RaggedArray + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.signal.analytic_signal.rst b/_sources/_autosummary/clouddrift.signal.analytic_signal.rst new file mode 100644 index 00000000..29c06519 --- /dev/null +++ b/_sources/_autosummary/clouddrift.signal.analytic_signal.rst @@ -0,0 +1,6 @@ +clouddrift.signal.analytic\_signal +================================== + +.. currentmodule:: clouddrift.signal + +.. autofunction:: analytic_signal \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.signal.cartesian_to_rotary.rst b/_sources/_autosummary/clouddrift.signal.cartesian_to_rotary.rst new file mode 100644 index 00000000..12e02aaf --- /dev/null +++ b/_sources/_autosummary/clouddrift.signal.cartesian_to_rotary.rst @@ -0,0 +1,6 @@ +clouddrift.signal.cartesian\_to\_rotary +======================================= + +.. currentmodule:: clouddrift.signal + +.. autofunction:: cartesian_to_rotary \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.signal.ellipse_parameters.rst b/_sources/_autosummary/clouddrift.signal.ellipse_parameters.rst new file mode 100644 index 00000000..5b167071 --- /dev/null +++ b/_sources/_autosummary/clouddrift.signal.ellipse_parameters.rst @@ -0,0 +1,6 @@ +clouddrift.signal.ellipse\_parameters +===================================== + +.. currentmodule:: clouddrift.signal + +.. autofunction:: ellipse_parameters \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.signal.modulated_ellipse_signal.rst b/_sources/_autosummary/clouddrift.signal.modulated_ellipse_signal.rst new file mode 100644 index 00000000..e83afcfb --- /dev/null +++ b/_sources/_autosummary/clouddrift.signal.modulated_ellipse_signal.rst @@ -0,0 +1,6 @@ +clouddrift.signal.modulated\_ellipse\_signal +============================================ + +.. currentmodule:: clouddrift.signal + +.. autofunction:: modulated_ellipse_signal \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.signal.rotary_to_cartesian.rst b/_sources/_autosummary/clouddrift.signal.rotary_to_cartesian.rst new file mode 100644 index 00000000..1ee02b9f --- /dev/null +++ b/_sources/_autosummary/clouddrift.signal.rotary_to_cartesian.rst @@ -0,0 +1,6 @@ +clouddrift.signal.rotary\_to\_cartesian +======================================= + +.. currentmodule:: clouddrift.signal + +.. autofunction:: rotary_to_cartesian \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.signal.rst b/_sources/_autosummary/clouddrift.signal.rst new file mode 100644 index 00000000..c8716d8a --- /dev/null +++ b/_sources/_autosummary/clouddrift.signal.rst @@ -0,0 +1,35 @@ +clouddrift.signal +================= + +.. automodule:: clouddrift.signal + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + analytic_signal + cartesian_to_rotary + ellipse_parameters + modulated_ellipse_signal + rotary_to_cartesian + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.sphere.bearing.rst b/_sources/_autosummary/clouddrift.sphere.bearing.rst new file mode 100644 index 00000000..d28ddcf8 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.bearing.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.bearing +========================= + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: bearing \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.cartesian_to_spherical.rst b/_sources/_autosummary/clouddrift.sphere.cartesian_to_spherical.rst new file mode 100644 index 00000000..9287d08b --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.cartesian_to_spherical.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.cartesian\_to\_spherical +========================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: cartesian_to_spherical \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.rst b/_sources/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.rst new file mode 100644 index 00000000..9c7ec442 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.cartesian_to_tangentplane.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.cartesian\_to\_tangentplane +============================================= + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: cartesian_to_tangentplane \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.coriolis_frequency.rst b/_sources/_autosummary/clouddrift.sphere.coriolis_frequency.rst new file mode 100644 index 00000000..5a125065 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.coriolis_frequency.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.coriolis\_frequency +===================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: coriolis_frequency \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.cumulative_distance.rst b/_sources/_autosummary/clouddrift.sphere.cumulative_distance.rst new file mode 100644 index 00000000..b28978eb --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.cumulative_distance.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.cumulative\_distance +====================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: cumulative_distance \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.distance.rst b/_sources/_autosummary/clouddrift.sphere.distance.rst new file mode 100644 index 00000000..8e60bd83 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.distance.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.distance +========================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: distance \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.plane_to_sphere.rst b/_sources/_autosummary/clouddrift.sphere.plane_to_sphere.rst new file mode 100644 index 00000000..1d8e161e --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.plane_to_sphere.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.plane\_to\_sphere +=================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: plane_to_sphere \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.rst b/_sources/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.rst new file mode 100644 index 00000000..e13860d3 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.position_from_distance_and_bearing.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.position\_from\_distance\_and\_bearing +======================================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: position_from_distance_and_bearing \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.recast_lon.rst b/_sources/_autosummary/clouddrift.sphere.recast_lon.rst new file mode 100644 index 00000000..324878dd --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.recast_lon.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.recast\_lon +============================= + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: recast_lon \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.recast_lon180.rst b/_sources/_autosummary/clouddrift.sphere.recast_lon180.rst new file mode 100644 index 00000000..a569e3e6 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.recast_lon180.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.recast\_lon180 +================================ + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: recast_lon180 \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.recast_lon360.rst b/_sources/_autosummary/clouddrift.sphere.recast_lon360.rst new file mode 100644 index 00000000..da3b5567 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.recast_lon360.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.recast\_lon360 +================================ + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: recast_lon360 \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.rst b/_sources/_autosummary/clouddrift.sphere.rst new file mode 100644 index 00000000..e102c875 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.rst @@ -0,0 +1,44 @@ +clouddrift.sphere +================= + +.. automodule:: clouddrift.sphere + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + bearing + cartesian_to_spherical + cartesian_to_tangentplane + coriolis_frequency + cumulative_distance + distance + plane_to_sphere + position_from_distance_and_bearing + recast_lon + recast_lon180 + recast_lon360 + sphere_to_plane + spherical_to_cartesian + tangentplane_to_cartesian + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.sphere.sphere_to_plane.rst b/_sources/_autosummary/clouddrift.sphere.sphere_to_plane.rst new file mode 100644 index 00000000..a3d411fe --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.sphere_to_plane.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.sphere\_to\_plane +=================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: sphere_to_plane \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.spherical_to_cartesian.rst b/_sources/_autosummary/clouddrift.sphere.spherical_to_cartesian.rst new file mode 100644 index 00000000..656b2ab1 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.spherical_to_cartesian.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.spherical\_to\_cartesian +========================================== + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: spherical_to_cartesian \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.rst b/_sources/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.rst new file mode 100644 index 00000000..c60f14a9 --- /dev/null +++ b/_sources/_autosummary/clouddrift.sphere.tangentplane_to_cartesian.rst @@ -0,0 +1,6 @@ +clouddrift.sphere.tangentplane\_to\_cartesian +============================================= + +.. currentmodule:: clouddrift.sphere + +.. autofunction:: tangentplane_to_cartesian \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.morse_amplitude.rst b/_sources/_autosummary/clouddrift.wavelet.morse_amplitude.rst new file mode 100644 index 00000000..a76397b5 --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.morse_amplitude.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.morse\_amplitude +=================================== + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: morse_amplitude \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.morse_freq.rst b/_sources/_autosummary/clouddrift.wavelet.morse_freq.rst new file mode 100644 index 00000000..f2d7b9ac --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.morse_freq.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.morse\_freq +============================== + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: morse_freq \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.morse_logspace_freq.rst b/_sources/_autosummary/clouddrift.wavelet.morse_logspace_freq.rst new file mode 100644 index 00000000..8f13e282 --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.morse_logspace_freq.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.morse\_logspace\_freq +======================================== + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: morse_logspace_freq \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.morse_properties.rst b/_sources/_autosummary/clouddrift.wavelet.morse_properties.rst new file mode 100644 index 00000000..5135106c --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.morse_properties.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.morse\_properties +==================================== + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: morse_properties \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.morse_wavelet.rst b/_sources/_autosummary/clouddrift.wavelet.morse_wavelet.rst new file mode 100644 index 00000000..2358902d --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.morse_wavelet.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.morse\_wavelet +================================= + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: morse_wavelet \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.morse_wavelet_transform.rst b/_sources/_autosummary/clouddrift.wavelet.morse_wavelet_transform.rst new file mode 100644 index 00000000..7549d08b --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.morse_wavelet_transform.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.morse\_wavelet\_transform +============================================ + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: morse_wavelet_transform \ No newline at end of file diff --git a/_sources/_autosummary/clouddrift.wavelet.rst b/_sources/_autosummary/clouddrift.wavelet.rst new file mode 100644 index 00000000..17e01f58 --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.rst @@ -0,0 +1,37 @@ +clouddrift.wavelet +================== + +.. automodule:: clouddrift.wavelet + :members: + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + morse_amplitude + morse_freq + morse_logspace_freq + morse_properties + morse_wavelet + morse_wavelet_transform + wavelet_transform + + + + + + + + + + + + + diff --git a/_sources/_autosummary/clouddrift.wavelet.wavelet_transform.rst b/_sources/_autosummary/clouddrift.wavelet.wavelet_transform.rst new file mode 100644 index 00000000..9458246c --- /dev/null +++ b/_sources/_autosummary/clouddrift.wavelet.wavelet_transform.rst @@ -0,0 +1,6 @@ +clouddrift.wavelet.wavelet\_transform +===================================== + +.. currentmodule:: clouddrift.wavelet + +.. autofunction:: wavelet_transform \ No newline at end of file diff --git a/_sources/api.rst b/_sources/api.rst new file mode 100644 index 00000000..7517f546 --- /dev/null +++ b/_sources/api.rst @@ -0,0 +1,27 @@ +API +=== + +Auto-generated summary of CloudDrift's API. For more details and examples, refer to the different Jupyter Notebooks. + +.. currentmodule:: clouddrift + +.. autosummary:: + :toctree: _autosummary + :template: module.rst + :recursive: + + adapters.gdp + adapters.gdp1h + adapters.gdp6h + adapters.glad + adapters.mosaic + adapters.subsurface_floats + datasets + kinematics + pairs + plotting + ragged + raggedarray + signal + sphere + wavelet diff --git a/_sources/contributing.rst b/_sources/contributing.rst new file mode 100644 index 00000000..a18b0302 --- /dev/null +++ b/_sources/contributing.rst @@ -0,0 +1,37 @@ +.. _contributing: + +Contributing +============ + +This project follows `NumFOCUS `_ code of conduct, the short version is: + +- Be kind to others. Do not insult or put down others. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are not appropriate. +- All communication should be appropriate for a professional audience including people of many different backgrounds. Sexual language and imagery is not appropriate. +- We are dedicated to providing a harassment-free community for everyone, regardless of gender, sexual orientation, gender identity and expression, disability, physical appearance, body size, race, or religion. +- We do not tolerate harassment of community members in any form. + +Thank you for helping make this a welcoming, friendly community for all. + +Bug reports and requests +------------------------ + +We encourage users to participate in the development of CloudDrift by filling out bug reports, participating in discussions, and requesting features on `https://github.com/Cloud-Drift/clouddrift `_. + +Contributing to the documentation +--------------------------------- + +We also welcome contributions to improving the documentation of the project. To create a local static documentation website, the following packages are required: + +.. code-block:: console + + conda install sphinx + pip install sphinx_book_theme + pip install sphinx-copybutton + +Then, from the ``clouddrift/docs`` directory, run + +.. code-block:: console + + make html + +to compile and output the documentation website to ``clouddrift/docs/_build/html/``. The index page ``index.html`` can be visualized in a web browser. Note that after modifying the documentation, it might be necessary to run ``make clean`` before rebuilding. diff --git a/_sources/datasets.rst b/_sources/datasets.rst new file mode 100644 index 00000000..e12ec970 --- /dev/null +++ b/_sources/datasets.rst @@ -0,0 +1,78 @@ +.. _datasets: + +Datasets +======== + +CloudDrift provides convenience functions to access real-world ragged-array +datasets. + +>>> from clouddrift.datasets import gdp1h +>>> ds = gdp1h() + + Dimensions: (traj: 17324, obs: 165754333) + Coordinates: + ids (obs) int64 ... + lat (obs) float32 ... + lon (obs) float32 ... + time (obs) datetime64[ns] ... + Dimensions without coordinates: traj, obs + Data variables: (12/55) + BuoyTypeManufacturer (traj) |S20 ... + BuoyTypeSensorArray (traj) |S20 ... + CurrentProgram (traj) float64 ... + DeployingCountry (traj) |S20 ... + DeployingShip (traj) |S20 ... + DeploymentComments (traj) |S20 ... + ... ... + sst1 (obs) float64 ... + sst2 (obs) float64 ... + typebuoy (traj) |S10 ... + typedeath (traj) int8 ... + ve (obs) float32 ... + vn (obs) float32 ... + Attributes: (12/16) + Conventions: CF-1.6 + acknowledgement: Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurio... + contributor_name: NOAA Global Drifter Program + contributor_role: Data Acquisition Center + date_created: 2022-12-09T06:02:29.684949 + doi: 10.25921/x46c-3620 + ... ... + processing_level: Level 2 QC by GDP drifter DAC + publisher_email: aoml.dftr@noaa.gov + publisher_name: GDP Drifter DAC + publisher_url: https://www.aoml.noaa.gov/phod/gdp + summary: Global Drifter Program hourly data + title: Global Drifter Program hourly drifting buoy collection + +Currently available datasets are: + +- :func:`clouddrift.datasets.andro`: The ANDRO dataset as a ragged array + processed from the upstream dataset hosted at the `SEANOE repository + `_. +- :func:`clouddrift.datasets.gdp1h`: 1-hourly Global Drifter Program (GDP) data + from a `cloud-optimized Zarr dataset on AWS `_. +- :func:`clouddrift.datasets.gdp6h`: 6-hourly GDP data from a ragged-array + NetCDF file hosted by the public HTTPS server at + `NOAA's Atlantic Oceanographic and Meteorological Laboratory (AOML) `_. +- :func:`clouddrift.datasets.glad`: 15-minute Grand LAgrangian Deployment (GLAD) + data produced by the Consortium for Advanced Research on Transport of + Hydrocarbon in the Environment (CARTHE) and hosted upstream at the `Gulf of + Mexico Research Initiative Information and Data Cooperative (GRIIDC) + `_. +- :func:`clouddrift.datasets.mosaic`: MOSAiC sea-ice drift dataset as a ragged + array processed from the upstream dataset hosted at the + `NSF's Arctic Data Center `_. +- :func:`clouddrift.datasets.subsurface_floats`: The subsurface float trajectories dataset as + hosted by NOAA AOML at + `NOAA's Atlantic Oceanographic and Meteorological Laboratory (AOML) _` + and maintained by Andree Ramsey and Heather Furey from the Woods Hole Oceanographic Institution. +- :func:`clouddrift.datasets.spotters`: The Sofar Ocean Spotters archive dataset as hosted at the public `AWS S3 bucket `_. +- :func:`clouddrift.datasets.yomaha`: The YoMaHa'07 dataset as a ragged array + processed from the upstream dataset hosted at the `Asia-Pacific Data-Research + Center (APDRC) `_. + +The GDP and the Spotters datasets are accessed lazily, so the data is only downloaded when +specific array values are referenced. The ANDRO, GLAD, MOSAiC, Subsurface Floats, and YoMaHa'07 +datasets are downloaded in their entirety when the function is called for the first +time and stored locally for later use. \ No newline at end of file diff --git a/_sources/index.rst b/_sources/index.rst new file mode 100644 index 00000000..1ec0e625 --- /dev/null +++ b/_sources/index.rst @@ -0,0 +1,62 @@ +CloudDrift, a platform for accelerating research with Lagrangian climate data +============================================================================= + +Lagrangian data typically refers to oceanic and atmosphere information acquired by observing platforms drifting with the flow they are embedded within, but also refers more broadly to the data originating from uncrewed platforms, vehicles, and animals that gather data along their unrestricted and often complex paths. Because such paths traverse both spatial and temporal dimensions, Lagrangian data can convolve spatial and temporal information that cannot always readily be organized in common data structures and stored in standard file formats with the help of common libraries and standards. + +As such, for both originators and users, Lagrangian data present challenges that the CloudDrift project aims to overcome. This project is funded by the `NSF EarthCube program `_ through `EarthCube Capabilities Grant No. 2126413 `_. + +Motivations +----------- + +The `Global Drifter Program (GDP) `_ of the US National Oceanic and Atmospheric Administration has released to date nearly 25,000 drifting buoys, or drifters, with the goal of obtaining observations of oceanic velocity, sea surface temperature, and sea level pressure. From these drifter observations, the GDP generates two data products: one of oceanic variables estimated along drifter trajectories at `hourly `_ time steps, and one at `six-hourly `_ steps. + +There are a few ways to retrieve the data, but all typically require time-consuming preprocessing steps in order to prepare the data for analysis. As an example, the datasets can be retrieved through an `ERDDAP server `_, but requests are limited in size. The latest `6-hourly dataset `_ is distributed as a collection of thousands of individual NetCDF files or as a series of `ASCII files `_. Until recently, the `hourly dataset `_ was distributed as a collection of individual NetCDF files (17,324 for version 1.04c) but is now distributed by NOAA NCEI as a `single NetCDF file `_ containing a series of ragged arrays, thanks to the work of CloudDrift. A single file simplifies data distribution, decreases metadata redundancies, and efficiently stores a Lagrangian data collection of uneven lengths. + +CloudDrift's analysis functions are centered around the ragged-array data +structure: + +.. image:: img/ragged_array.png + :width: 800 + :align: center + :alt: Ragged array schematic + +CloudDrift's goals are to simplify the necessary steps to get started with +Lagrangian datasets and to provide a cloud-ready library to accelerate +Lagrangian analysis. + +Getting started +--------------- + +* :doc:`install` +* :doc:`usage` +* :doc:`datasets` + +.. toctree:: + :hidden: + :maxdepth: 2 + :caption: Getting started + + install + usage + datasets + +Reference +--------- + +* :doc:`contributing` +* :doc:`api` + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Reference + + contributing + api + +.. Indices and tables +.. ================== + +.. * :ref:`genindex` +.. * :ref:`modindex` +.. * :ref:`search` diff --git a/_sources/install.rst b/_sources/install.rst new file mode 100644 index 00000000..efcc947c --- /dev/null +++ b/_sources/install.rst @@ -0,0 +1,78 @@ +.. _install: + +Installation +============ + +You can install the latest release of CloudDrift using pip or Conda. +You can also install the latest development (unreleased) version from GitHub. + +pip +--- + +In your virtual environment, type: + +.. code-block:: text + + pip install clouddrift + +To install optional dependencies needed by the ``clouddrift.plotting`` module, +type: + +.. code-block:: text + + pip install matplotlib-base cartopy + +Conda +----- + +First add ``conda-forge`` to your channels in your Conda environment: + +.. code-block:: text + + conda config --add channels conda-forge + conda config --set channel_priority strict + +then install CloudDrift: + +.. code-block:: text + + conda install clouddrift + +To install optional dependencies needed by the ``clouddrift.plotting`` module, +type: + +.. code-block:: text + + conda install matplotlib-base cartopy + +Developers +---------- + +If you need the latest development version, get it from GitHub using pip: + +.. code-block:: text + + pip install git+https://github.com/Cloud-Drift/clouddrift + +Running tests +============= + +To run the tests, you need to first download the CloudDrift source code from +GitHub and install it in your virtual environment: + + +.. code-block:: text + + git clone https://github.com/cloud-drift/clouddrift + cd clouddrift + python3 -m venv venv + source venv/bin/activate + pip install . + +Then, run the tests like this: + +.. code-block:: text + + python -m unittest tests/*.py + +A quick how-to guide is provided on the `Usage `_ page. diff --git a/_sources/usage.rst b/_sources/usage.rst new file mode 100644 index 00000000..e9bae403 --- /dev/null +++ b/_sources/usage.rst @@ -0,0 +1,265 @@ +.. _usage: + +Usage +===== + +The CloudDrift library provides functions for: + +* Easy access to cloud-ready Lagrangian ragged-array datasets; +* Common Lagrangian analysis tasks on ragged arrays; +* Adapting custom Lagrangian datasets into ragged arrays. + +Let's start by importing the library and accessing a ready-to-use ragged-array +dataset. + +Accessing ragged-array Lagrangian datasets +------------------------------------------ + +We recommend to import the ``clouddrift`` using the ``cd`` shorthand, for convenience: + +>>> import clouddrift as cd + +CloudDrift provides a set of Lagrangian datasets that are ready to use. +They can be accessed via the ``datasets`` submodule. +In this example, we will load the NOAA's Global Drifter Program (GDP) hourly +dataset, which is hosted in a public AWS bucket as a cloud-optimized Zarr +dataset: + +>>> ds = cd.datasets.gdp1h() +>>> ds + +Dimensions: (traj: 17324, obs: 165754333) +Coordinates: + ids (obs) int64 ... + lat (obs) float32 ... + lon (obs) float32 ... + time (obs) datetime64[ns] ... +Dimensions without coordinates: traj, obs +Data variables: (12/55) + BuoyTypeManufacturer (traj) |S20 ... + BuoyTypeSensorArray (traj) |S20 ... + CurrentProgram (traj) float64 ... + DeployingCountry (traj) |S20 ... + DeployingShip (traj) |S20 ... + DeploymentComments (traj) |S20 ... + ... ... + sst1 (obs) float64 ... + sst2 (obs) float64 ... + typebuoy (traj) |S10 ... + typedeath (traj) int8 ... + ve (obs) float32 ... + vn (obs) float32 ... +Attributes: (12/16) + Conventions: CF-1.6 + acknowledgement: Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurio... + contributor_name: NOAA Global Drifter Program + contributor_role: Data Acquisition Center + date_created: 2022-12-09T06:02:29.684949 + doi: 10.25921/x46c-3620 + ... ... + processing_level: Level 2 QC by GDP drifter DAC + publisher_email: aoml.dftr@noaa.gov + publisher_name: GDP Drifter DAC + publisher_url: https://www.aoml.noaa.gov/phod/gdp + summary: Global Drifter Program hourly data + title: Global Drifter Program hourly drifting buoy collection + +The ``gdp1h`` function returns an Xarray ``Dataset`` instance of the ragged-array dataset. +While the dataset is quite large, around a dozen GB, it is not downloaded to your +local machine. Instead, the dataset is accessed directly from the cloud, and only +the data that is needed for the analysis is downloaded. This is possible thanks to +the cloud-optimized Zarr format, which allows for efficient access to the data +stored in the cloud. + +Let's look at some variables in this dataset: + +>>> ds.lon + +[165754333 values with dtype=float32] +Coordinates: + ids (obs) int64 ... + lat (obs) float32 ... + lon (obs) float32 ... + time (obs) datetime64[ns] ... +Dimensions without coordinates: obs +Attributes: + long_name: Longitude + units: degrees_east + +You see that this array is very long--it has 165754333 elements. +This is because in a ragged array, many varying-length arrays are laid out as a +contiguous 1-dimensional array in memory. + +Let's look at the dataset dimensions: + +>>> ds.sizes +Frozen({'traj': 17324, 'obs': 165754333}) + +The ``traj`` dimension has 17324 elements, which is the number of individual +trajectories in the dataset. +The sum of their lengths equals the length of the ``obs`` dimension. +Internally, these dimensions, their lengths, and the ``rowsize`` +variable are used internally to make CloudDrift's analysis functions aware of +the bounds of each contiguous array within the ragged-array data structure. + +Doing common analysis tasks on ragged arrays +-------------------------------------------- + +Now that we have a ragged-array dataset loaded as an Xarray ``Dataset`` instance, +let's do some common analysis tasks on it. +Our dataset is on a remote server and fairly large (a dozen GB or so), so let's +first subset it to several trajectories so that we can more easily work with it. +The variable ``ID`` is the unique identifier for each trajectory: + +>>> ds.ID[:10].values +array([2578, 2582, 2583, 2592, 2612, 2613, 2622, 2623, 2931, 2932]) + +>>> from clouddrift.ragged import subset + +``subset`` allows you to subset a ragged array by some criterion. +In this case, we will subset it by the ``ID`` variable: + +>>> ds_sub = subset(ds, {"ID": list(ds.ID[:5])}) +>>> ds_sub + +Dimensions: (traj: 5, obs: 13612) +Coordinates: + ids (obs) int64 2578 2578 2578 2578 ... 2612 2612 2612 + lat (obs) float32 ... + lon (obs) float32 ... + time (obs) datetime64[ns] ... +Dimensions without coordinates: traj, obs +Data variables: (12/55) + BuoyTypeManufacturer (traj) |S20 ... + BuoyTypeSensorArray (traj) |S20 ... + CurrentProgram (traj) float64 ... + DeployingCountry (traj) |S20 ... + DeployingShip (traj) |S20 ... + DeploymentComments (traj) |S20 ... + ... ... + sst1 (obs) float64 ... + sst2 (obs) float64 ... + typebuoy (traj) |S10 ... + typedeath (traj) int8 ... + ve (obs) float32 ... + vn (obs) float32 ... +Attributes: (12/16) + Conventions: CF-1.6 + acknowledgement: Elipot, Shane; Sykulski, Adam; Lumpkin, Rick; Centurio... + contributor_name: NOAA Global Drifter Program + contributor_role: Data Acquisition Center + date_created: 2022-12-09T06:02:29.684949 + doi: 10.25921/x46c-3620 + ... ... + processing_level: Level 2 QC by GDP drifter DAC + publisher_email: aoml.dftr@noaa.gov + publisher_name: GDP Drifter DAC + publisher_url: https://www.aoml.noaa.gov/phod/gdp + summary: Global Drifter Program hourly data + title: Global Drifter Program hourly drifting buoy collection + +You see that we now have a subset of the original dataset, with 5 trajectories +and a total of 13612 observations. +This subset is small enough to quickly and easily work with for demonstration +purposes. +Let's see how we can compute the mean and maximum velocities of each trajectory. +To start, we'll need to obtain the velocities over all trajectory times. +Although the GDP dataset already comes with velocity variables, we won't use +them here so that we can learn how to compute them ourselves from positions. +``clouddrift``'s ``kinematics`` module provides the ``velocity_from_position`` +function that allows you to do just that. + +>>> from clouddrift.kinematics import velocity_from_position + +At a minimum ``velocity_from_position`` requires three input parameters: +consecutive x- and y-coordinates and time, so we could do: + +>>> u, v = velocity_from_position(ds_sub.lon, ds_sub.lat, ds_sub.time) + +``velocity_from_position`` returns two arrays, ``u`` and ``v``, which are the +zonal and meridional velocities, respectively. +By default, it assumes that the coordinates are in degrees, and it handles the +great circle path calculation and longitude wraparound under the hood. +However, recall that ``ds_sub.lon``, ``ds_sub.lat``, and ``ds_sub.time`` are +ragged arrays, so we need a different approach to calculate velocities while +respecting the trajectory boundaries. +For this, we can use the ``ragged_apply`` function, which applies a function +to each trajectory in a ragged array, and returns the concatenated result. + +>>> from clouddrift.ragged import apply_ragged +>>> u, v = apply_ragged(velocity_from_position, [ds_sub.lon, ds_sub.lat, ds_sub.time], ds_sub.rowsize) + +``u`` and ``v`` here are still ragged arrays, which means that the five +contiguous trajectories are concatenated into 1-dimensional arrays. + +Now, let's compute the velocity magnitude in meters per second. +The time in this dataset is loaded in nanoseconds by default: + +>>> ds_sub.time.values +array(['2005-04-15T20:00:00.000000000', '2005-04-15T21:00:00.000000000', + '2005-04-15T22:00:00.000000000', ..., + '2005-10-02T03:00:00.000000000', '2005-10-02T04:00:00.000000000', + '2005-10-02T05:00:00.000000000'], dtype='datetime64[ns]') + +So, to obtain the velocity magnitude in meters per second, we'll need to +multiply our velocities by ``1e9``. + +>>> velocity_magnitude = np.sqrt(u**2 + v**2) * 1e9 +>>> velocity_magnitude +array([0.28053388, 0.6164632 , 0.89032112, ..., 0.2790803 , 0.20095603, + 0.20095603]) + +>>> velocity_magnitude.mean(), velocity_magnitude.max() +(0.22115242718877506, 1.6958275672626286) + +However, these aren't the results we are looking for! Recall that we have the +velocity magnitude of five different trajectories concatenated into one array. +This means that we need to use ``apply_ragged`` again to compute the mean and +maximum values: + +>>> apply_ragged(np.mean, [velocity_magnitude], ds_sub.rowsize) +array([0.32865148, 0.17752435, 0.1220523 , 0.13281067, 0.14041268]) +>>> apply_ragged(np.max, [velocity_magnitude], ds_sub.rowsize) +array([1.69582757, 1.36804354, 0.97343434, 0.60353528, 1.05044213]) + +And there you go! We used ``clouddrift`` to: + +#. Load a real-world Lagrangian dataset from the cloud; +#. Subset the dataset by trajectory IDs; +#. Compute the velocity vectors and their magnitudes for each trajectory; +#. Compute the mean and maximum velocity magnitudes for each trajectory. + +``clouddrift`` offers many more functions for common Lagrangian analysis tasks. +Please explore the `API `_ +to learn about other functions and how to use them. + +Adapting custom Lagrangian datasets into ragged arrays +------------------------------------------------------ + +CloudDrift provides an easy way to convert custom Lagrangian datasets into +`contiguous ragged arrays `_. + +.. code-block:: python + + # Import a GDP-hourly adapter function + from clouddrift.adapters.gdp import to_raggedarray + + # Download 100 random GDP-hourly trajectories as a ragged array + ra = to_raggedarray(n_random_id=100) + + # Store to NetCDF and Parquet files + ra.to_netcdf("gdp.nc") + ra.to_parquet("gdp.parquet") + + # Convert to Xarray Dataset for analysis + ds = ra.to_xarray() + + # Alternatively, convert to Awkward Array for analysis + ds = ra.to_awkward() + +This snippet is specific to the hourly GDP dataset, however, you can use the +``RaggedArray`` class directly to convert other custom datasets into a ragged +array structure that is analysis ready via Xarray or Awkward Array packages. +The functions to do that are defined in the ``clouddrift.adapters`` submodule. +You can use these examples as a reference to ingest your own or other custom +Lagrangian datasets into ``RaggedArray``. \ No newline at end of file diff --git a/_static/basic.css b/_static/basic.css index 01192852..e760386b 100644 --- a/_static/basic.css +++ b/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -15,6 +15,12 @@ div.clearer { clear: both; } +div.section::after { + display: block; + content: ''; + clear: left; +} + /* -- relbar ---------------------------------------------------------------- */ div.related { @@ -49,7 +55,7 @@ div.sphinxsidebarwrapper { div.sphinxsidebar { float: left; - width: 230px; + width: 270px; margin-left: -100%; font-size: 90%; word-wrap: break-word; @@ -124,7 +130,7 @@ ul.search li a { font-weight: bold; } -ul.search li div.context { +ul.search li p.context { color: #888; margin: 2px 0 0 30px; text-align: left; @@ -216,7 +222,7 @@ table.modindextable td { /* -- general body styles --------------------------------------------------- */ div.body { - min-width: 450px; + min-width: 360px; max-width: 800px; } @@ -231,14 +237,8 @@ a.headerlink { visibility: hidden; } -a.brackets:before, -span.brackets > a:before{ - content: "["; -} - -a.brackets:after, -span.brackets > a:after { - content: "]"; +a:visited { + color: #551A8B; } h1:hover > a.headerlink, @@ -271,25 +271,25 @@ p.rubric { font-weight: bold; } -img.align-left, .figure.align-left, object.align-left { +img.align-left, figure.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } -img.align-right, .figure.align-right, object.align-right { +img.align-right, figure.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } -img.align-center, .figure.align-center, object.align-center { +img.align-center, figure.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } -img.align-default, .figure.align-default { +img.align-default, figure.align-default, .figure.align-default { display: block; margin-left: auto; margin-right: auto; @@ -313,24 +313,35 @@ img.align-default, .figure.align-default { /* -- sidebars -------------------------------------------------------------- */ -div.sidebar { +div.sidebar, +aside.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; - padding: 7px 7px 0 7px; + padding: 7px; background-color: #ffe; width: 40%; float: right; + clear: right; + overflow-x: auto; } p.sidebar-title { font-weight: bold; } +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + /* -- topics ---------------------------------------------------------------- */ +nav.contents, +aside.topic, div.topic { border: 1px solid #ccc; - padding: 7px 7px 0 7px; + padding: 7px; margin: 10px 0 10px 0; } @@ -352,10 +363,6 @@ div.admonition dt { font-weight: bold; } -div.admonition dl { - margin-bottom: 0; -} - p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; @@ -366,9 +373,34 @@ div.body p.centered { margin-top: 25px; } +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + /* -- tables ---------------------------------------------------------------- */ table.docutils { + margin-top: 10px; + margin-bottom: 10px; border: 0; border-collapse: collapse; } @@ -398,10 +430,6 @@ table.docutils td, table.docutils th { border-bottom: 1px solid #aaa; } -table.footnote td, table.footnote th { - border: 0 !important; -} - th { text-align: left; padding-right: 5px; @@ -416,32 +444,34 @@ table.citation td { border-bottom: none; } -th > p:first-child, -td > p:first-child { +th > :first-child, +td > :first-child { margin-top: 0px; } -th > p:last-child, -td > p:last-child { +th > :last-child, +td > :last-child { margin-bottom: 0px; } /* -- figures --------------------------------------------------------------- */ -div.figure { +div.figure, figure { margin: 0.5em; padding: 0.5em; } -div.figure p.caption { +div.figure p.caption, figcaption { padding: 0.3em; } -div.figure p.caption span.caption-number { +div.figure p.caption span.caption-number, +figcaption span.caption-number { font-style: italic; } -div.figure p.caption span.caption-text { +div.figure p.caption span.caption-text, +figcaption span.caption-text { } /* -- field list styles ----------------------------------------------------- */ @@ -468,10 +498,71 @@ table.field-list td, table.field-list th { /* -- hlist styles ---------------------------------------------------------- */ +table.hlist { + margin: 1em 0; +} + table.hlist td { vertical-align: top; } +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + /* -- other body styles ----------------------------------------------------- */ @@ -495,26 +586,53 @@ ol.upperroman { list-style: upper-roman; } -li > p:first-child { +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { margin-top: 0px; } -li > p:last-child { +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { margin-bottom: 0px; } -dl.footnote > dt, -dl.citation > dt { - float: left; +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; } -dl.footnote > dd, -dl.citation > dd { - margin-bottom: 0em; +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; } -dl.footnote > dd:after, -dl.citation > dd:after { +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { content: ""; clear: both; } @@ -531,10 +649,6 @@ dl.field-list > dt { padding-right: 5px; } -dl.field-list > dt:after { - content: ":"; -} - dl.field-list > dd { padding-left: 0.5em; margin-top: 0em; @@ -546,7 +660,7 @@ dl { margin-bottom: 15px; } -dd > p:first-child { +dd > :first-child { margin-top: 0px; } @@ -560,6 +674,21 @@ dd { margin-left: 30px; } +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + dt:target, span.highlighted { background-color: #fbe54e; } @@ -573,14 +702,6 @@ dl.glossary dt { font-size: 1.1em; } -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - .versionmodified { font-style: italic; } @@ -621,8 +742,9 @@ dl.glossary dt { .classifier:before { font-style: normal; - margin: 0.5em; + margin: 0 0.5em; content: ":"; + display: inline-block; } abbr, acronym { @@ -630,6 +752,14 @@ abbr, acronym { cursor: help; } +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + /* -- code displays --------------------------------------------------------- */ pre { @@ -637,29 +767,69 @@ pre { overflow-y: hidden; /* fixes display issues on Chrome browsers */ } +pre, div[class*="highlight-"] { + clear: both; +} + span.pre { -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; } td.linenos pre { - padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { - margin-left: 0.5em; + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; } table.highlighttable td { - padding: 0 0.5em 0 0.5em; + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; } div.code-block-caption { + margin-top: 1em; padding: 2px 5px; font-size: small; } @@ -668,12 +838,14 @@ div.code-block-caption code { background-color: transparent; } -div.code-block-caption + div > div.highlight > pre { - margin-top: 0; -} - -div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ } div.code-block-caption span.caption-number { @@ -685,21 +857,7 @@ div.code-block-caption span.caption-text { } div.literal-block-wrapper { - padding: 1em 1em 0; -} - -div.literal-block-wrapper div.highlight { - margin: 0; -} - -code.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -code.descclassname { - background-color: transparent; + margin: 1em 0; } code.xref, a code { @@ -740,8 +898,7 @@ span.eqno { } span.eqno a.headerlink { - position: relative; - left: 0px; + position: absolute; z-index: 1; } diff --git a/_static/check-solid.svg b/_static/check-solid.svg new file mode 100644 index 00000000..92fad4b5 --- /dev/null +++ b/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/_static/clipboard.min.js b/_static/clipboard.min.js new file mode 100644 index 00000000..54b3c463 --- /dev/null +++ b/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/_static/copybutton.css b/_static/copybutton.css new file mode 100644 index 00000000..f1916ec7 --- /dev/null +++ b/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/_static/copybutton.js b/_static/copybutton.js new file mode 100644 index 00000000..b3987037 --- /dev/null +++ b/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos, .gp'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/_static/copybutton_funcs.js b/_static/copybutton_funcs.js new file mode 100644 index 00000000..dbe1aaad --- /dev/null +++ b/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/_static/doctools.js b/_static/doctools.js index daccd209..d06a71d7 100644 --- a/_static/doctools.js +++ b/_static/doctools.js @@ -2,314 +2,155 @@ * doctools.js * ~~~~~~~~~~~ * - * Sphinx JavaScript utilities for all documentation. + * Base JavaScript utilities for all Sphinx HTML documentation. * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - */ -jQuery.urldecode = function(x) { - return decodeURIComponent(x).replace(/\+/g, ' '); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); } - return result; }; -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} - /** * Small JavaScript module for the documentation. */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { - this.initOnKeyListeners(); - } +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); }, /** * i18n support */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, - LOCALE : 'unknown', + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated === 'undefined') - return string; - return (typeof translated === 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated === 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } }, - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; }, - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; }, /** - * workaround a firefox stupidity - * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + * helper function to focus on search bar */ - fixFirefoxAnchorBug : function() { - if (document.location.hash && $.browser.mozilla) - window.setTimeout(function() { - document.location.href += ''; - }, 10); + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); }, /** - * highlight the search words provided in the url in the text + * Initialise the domain index toggle buttons */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - if (!body.length) { - body = $('body'); + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); } - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('#searchbox')); - } - }, - - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) === 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('#searchbox .highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - }, - - /** - * make the url absolute - */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, + }; - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this === '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); }, - initOnKeyListeners: function() { - $(document).keydown(function(event) { - var activeElementType = document.activeElement.tagName; - // don't navigate when in search box or textarea - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' - && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) { - switch (event.keyCode) { - case 37: // left - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); } - case 39: // right - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); } + break; } } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } }); - } + }, }; // quick alias for translations -_ = Documentation.gettext; +const _ = Documentation.gettext; -$(document).ready(function() { - Documentation.init(); -}); +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js index 4790c4d3..dab586c0 100644 --- a/_static/documentation_options.js +++ b/_static/documentation_options.js @@ -1,11 +1,13 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), +const DOCUMENTATION_OPTIONS = { VERSION: '', - LANGUAGE: 'None', + LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false + SOURCELINK_SUFFIX: '', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, }; \ No newline at end of file diff --git a/_static/favicon.ico b/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..77b7bd318bc42ae86f076d9a2c45424fcb468215 GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/_static/graphviz.css b/_static/graphviz.css new file mode 100644 index 00000000..8d81c02e --- /dev/null +++ b/_static/graphviz.css @@ -0,0 +1,19 @@ +/* + * graphviz.css + * ~~~~~~~~~~~~ + * + * Sphinx stylesheet -- graphviz extension. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +img.graphviz { + border: 0; + max-width: 100%; +} + +object.graphviz { + max-width: 100%; +} diff --git a/_static/images/logo_binder.svg b/_static/images/logo_binder.svg new file mode 100644 index 00000000..45fecf75 --- /dev/null +++ b/_static/images/logo_binder.svg @@ -0,0 +1,19 @@ + + + + +logo + + + + + + + + diff --git a/_static/images/logo_colab.png b/_static/images/logo_colab.png new file mode 100644 index 0000000000000000000000000000000000000000..b7560ec216b2d1b6f77855525fe966c741833428 GIT binary patch literal 7601 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 diff --git a/_static/images/logo_jupyterhub.svg b/_static/images/logo_jupyterhub.svg new file mode 100644 index 00000000..60cfe9f2 --- /dev/null +++ b/_static/images/logo_jupyterhub.svg @@ -0,0 +1 @@ +logo_jupyterhubHub diff --git a/_static/language_data.js b/_static/language_data.js index d2b4ee91..250f5665 100644 --- a/_static/language_data.js +++ b/_static/language_data.js @@ -5,15 +5,16 @@ * This script contains the language-specific data used by searchtools.js, * namely the list of stopwords, stemmer, scorer and splitter. * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ -var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; -/* Non-minified version JS is _stemmer.js if file is provided */ +/* Non-minified version is copied as a separate JS file, is available */ + /** * Porter Stemmer */ @@ -196,102 +197,3 @@ var Stemmer = function() { } } - - - - -var splitChars = (function() { - var result = {}; - var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, - 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, - 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, - 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, - 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, - 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, - 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, - 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, - 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, - 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; - var i, j, start, end; - for (i = 0; i < singles.length; i++) { - result[singles[i]] = true; - } - var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], - [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], - [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], - [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], - [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], - [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], - [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], - [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], - [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], - [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], - [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], - [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], - [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], - [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], - [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], - [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], - [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], - [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], - [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], - [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], - [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], - [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], - [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], - [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], - [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], - [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], - [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], - [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], - [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], - [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], - [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], - [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], - [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], - [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], - [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], - [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], - [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], - [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], - [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], - [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], - [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], - [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], - [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], - [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], - [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], - [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], - [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], - [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], - [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; - for (i = 0; i < ranges.length; i++) { - start = ranges[i][0]; - end = ranges[i][1]; - for (j = start; j <= end; j++) { - result[j] = true; - } - } - return result; -})(); - -function splitQuery(query) { - var result = []; - var start = -1; - for (var i = 0; i < query.length; i++) { - if (splitChars[query.charCodeAt(i)]) { - if (start !== -1) { - result.push(query.slice(start, i)); - start = -1; - } - } else if (start === -1) { - start = i; - } - } - if (start !== -1) { - result.push(query.slice(start)); - } - return result; -} - - diff --git a/_static/locales/ar/LC_MESSAGES/booktheme.mo b/_static/locales/ar/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..15541a6a375f93efed3f410c2f892174ba91aaa0 GIT binary patch literal 1541 zcmZvaJ!}+56vrn40$lhsA5n;v39lh z&UUPnK|(?lfROD&7suGxxK0yMQ@o*|gesy+5vu&(?mBh?qn-WTn|=G<|NZw~b#1&Y zus*}?#(shQ752{`;fA&4V5qyTPS`e-!60i}(%5{r(0^;D!zP`#V66yFspV7<>kvF5*86z5`j$ z=8ez}?gu^a8}Li;DtHLIQScsk0P*i2&-V)CK7WC%Q*07qAJ7GU4juvd{a%p0tQWim zeu4N7$oY#!{2XK-Ul-?ZLAIP{VE@?5Oee^5uV0WLc46~8yjT}6*2P}4uiOhI#i!V; zXZ>RTx%Xyl*phu;(K~`m+PV^FjkZeL1V5sYI1K7moHI9c!}v9+ja5U&{2;G|4YhWh zm^7}c{~g+Tn8?Tvl<2F47Nu9i{l>4L9=6uy?FAD0FiY3w(=eiIKTWvQbqOe&{(Wd5^qM9YH}dGcsaNzja& zq-k29Wt#nO;9At7wwrWQc-|J&abpO^Bu%@f8>dB@7kE5QPu!GiO4q{asH8bJN^P3Y zvv7uYJM=8C@P0OzYSB}gLot+ZNt#(-bAo@Zj6?Yfp?anYnoPQR?;I# z{we#%LHPn31obOfkF`-+I9KUX>gUj zW@~ literal 0 HcmV?d00001 diff --git a/_static/locales/ar/LC_MESSAGES/booktheme.po b/_static/locales/ar/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..1237f343 --- /dev/null +++ b/_static/locales/ar/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "تنزيل ملف المصدر" + +msgid "suggest edit" +msgstr "أقترح تحرير" + +msgid "Toggle navigation" +msgstr "تبديل التنقل" + +msgid "open issue" +msgstr "قضية مفتوحة" + +msgid "Download notebook file" +msgstr "تنزيل ملف دفتر الملاحظات" + +msgid "repository" +msgstr "مخزن" + +msgid "Theme by the" +msgstr "موضوع بواسطة" + +msgid "Print to PDF" +msgstr "طباعة إلى PDF" + +msgid "Download this page" +msgstr "قم بتنزيل هذه الصفحة" + +msgid "Copyright" +msgstr "حقوق النشر" + +msgid "Last updated on" +msgstr "آخر تحديث في" + +msgid "Launch" +msgstr "إطلاق" + +msgid "Open an issue" +msgstr "افتح قضية" + +msgid "Fullscreen mode" +msgstr "وضع ملء الشاشة" + +msgid "Sphinx Book Theme" +msgstr "موضوع كتاب أبو الهول" + +msgid "Contents" +msgstr "محتويات" + +msgid "Edit this page" +msgstr "قم بتحرير هذه الصفحة" + +msgid "next page" +msgstr "الصفحة التالية" + +msgid "Source repository" +msgstr "مستودع المصدر" + +msgid "By" +msgstr "بواسطة" + +msgid "By the" +msgstr "بواسطة" + +msgid "previous page" +msgstr "الصفحة السابقة" diff --git a/_static/locales/bg/LC_MESSAGES/booktheme.mo b/_static/locales/bg/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..da95120037f8d7c52ad1f166a7682ea55ca47a01 GIT binary patch literal 1708 zcmaKqOKcQJ5QaOv0vkhkhC?jT2nh&cNkBwFYxY90B_t3AOpcMpyUpy7b@wpSL+}lZ zc_s=RKte*|C2`<_7URcy7jLdPR->G9h;qvTamgjhjlX8bj}R-P?fIs=y6dm{dw*ZQ z?5@DG8KWEHSBxzfKYoB0o|Q|4z)!5gYX#T^t^_xLtH5sX6L34Y5iEo2!IR(`P=OzV zHs>hFdG3I#!TVqr_zYYJPUie2U;izi{|U0*KVSh|x->h#2IP4+$a!{vO>jTB41AmO zFOci|8~haPLhws)C%7B@Hs=rEKFpioR`3nD2VA{8JAV*le@=j0?>TT6cp2OVJ_ot4 z*WiBe50LY0LeuQ=S0K-igY45ea0fUFvgOv1JgO3NWrRpO`@TbYDa&#J04 z8uLU~YT|f^4W5=k94AWjM}bBXBl{2ciBp+gq(T!1)p!vCDOMX z%z7FyzF${Td*=h+vjIf3x?r>F4C`bfVWiFnCdtcQkUma)U!h8cPEd+Dt17m5q+0w& zMKQ9KWTsza{bH(IICkV%?|gjko-YcyvBiPmP?e-b0iTC;FVH=*QuCr%+4AXuzT$!T zeUYc*Gb$?f>WZlb+AqligMlp^^|YVB*ODCc3;p#Z^6JGt6Ai^Bsl#*{m-qF^?6bU6 z%dKU(_p_dYpa*V5&_n77dhBk}xVz~t(j+x#hMF`X=r)bH5$d>$?h>`ABk5bs2r;-dTfq#Q2#?t@q|9teP3*uNPWy^ACfqd~8<8}Y{+a1%CJzCK zxEruG6KALRIVJ-U$3Yy!~NpG7AK|w8QyPuG1485SvTmo%i zrHNb3JL61fEcXDLQBPwL`;mLLOPayeL#0F0B5ju4Yr5-c6aTq5cjf(V=MS}!0~aLI KlK*|VZ0$SA#iddJ literal 0 HcmV?d00001 diff --git a/_static/locales/bg/LC_MESSAGES/booktheme.po b/_static/locales/bg/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..45a6ed0a --- /dev/null +++ b/_static/locales/bg/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Изтеглете изходния файл" + +msgid "suggest edit" +msgstr "предложи редактиране" + +msgid "Toggle navigation" +msgstr "Превключване на навигацията" + +msgid "open issue" +msgstr "отворен брой" + +msgid "Download notebook file" +msgstr "Изтеглете файла на бележника" + +msgid "repository" +msgstr "хранилище" + +msgid "Theme by the" +msgstr "Тема от" + +msgid "Print to PDF" +msgstr "Печат в PDF" + +msgid "Download this page" +msgstr "Изтеглете тази страница" + +msgid "Copyright" +msgstr "Авторско право" + +msgid "Last updated on" +msgstr "Последна актуализация на" + +msgid "Launch" +msgstr "Стартиране" + +msgid "Open an issue" +msgstr "Отворете проблем" + +msgid "Fullscreen mode" +msgstr "Режим на цял екран" + +msgid "Sphinx Book Theme" +msgstr "Тема на книгата Sphinx" + +msgid "Contents" +msgstr "Съдържание" + +msgid "Edit this page" +msgstr "Редактирайте тази страница" + +msgid "next page" +msgstr "Следваща страница" + +msgid "Source repository" +msgstr "Хранилище на източника" + +msgid "By" +msgstr "От" + +msgid "By the" +msgstr "По" + +msgid "previous page" +msgstr "предишна страница" diff --git a/_static/locales/bn/LC_MESSAGES/booktheme.mo b/_static/locales/bn/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..6b96639b726a2fa959a6419b6f8b7e0dfcce33ae GIT binary patch literal 1646 zcmbV~&5IOA7>8S2xE{WN>)mqrjbP_+ zD|`%n|9`+8@Gtlc{Cs5;eF=|2zkdOGUHYZ{3U0$*$xxrd?Ipj1NbvXay{#>+)sQwK zLc@BGr=Q8s@3s2pVyti%e$UVEm)Gmv@K$Kxb@iIkGQ)QH3Dc6%KAm>6q}ejje*L3r z>$oA5HgZzyAH?ybE$6p$-O1{5(WYr7xk%%tj7A!XA>+Uti*qA7X(KkWA+(Cd;*P4f zqC=@vB32^F^Nx(hvqTZ3#rXcw=x~uglc~-VqqA;wIBg~Bl-TQgnP|xqG73*IS+qW( zo6WWqDn6MsW0O!s$y282M*BKNku;Mh6WuA>9MAOkvTmve8r7pR%ZaLqqE6Ml~R{3$6RYz1^ zHxkvXiQSWlsf@*{*+H+Gm{gVVb|;J5)lr?D$ZJBS!OVxh8WP3p@HQnr8y3617^+0h zTGzYm>~GFKb#|8L(pyu`-gfp`;o|IhXQy$z<$9NR^WnYI&Q1wu?}S90&tc32?JEMg4wtZV(;LB0u<-^*y2)npB|JLL@f}SDrcO%Hi&xc%8I{oPgE$%7j?Kgl1>Fz ze@F9IjWZ|r@GsvuUE*t^AN05zoTs2{kFZmI~m25V-8`&>S^dPTx z$^cEyl^jJ+?oOKAsWhagj`qI>dC8~bzq_0hZSgC)LsF@U6+9F=tR`Ky;!WHMs_vF; z;&hv=3*2(}kGreju(wh1_KV>qMpKtu5HHORr>y#KY7MM6T^uJ&R^K(T z4hABYyJ6tQiOxVI^L*F1qO_S8am=vBunT>6i=$ATZdb3f&v8VJ2BK9Ft@hoIsQAhin!}wxzs(N*6pVu~DVqb08$hD1)Yjm|` zLS;tVxWMJrDAJYrr0_baPC1|EHL_WMn2%o?qrvC+h@~^*GMofV4`)o0LtLbidwpll9h6X)!5Y za@FKiW0X*mn3iX1k|l^w_?&_QX>NDCJM7-fGBbN{ zu90Yv ze2zJT`3vTkm``?L!Pxha5O~CXEFXgh!F}K{a6dQ$o&?W;$H6Xm6ub={0u}ff7#cnT z+0QfZQ*aGD2(E)iz#kj_+}M9>_J4vL?;Y3zckiz69|Czl1G1m9;7jl_xEK7Z;olA4 zfrnxL7yKGLyhn&Hz$@Tsa2Y%S-Uqp^$KWaO2ax0Z1af_E!2{s0AfNlAvHt_IJ_it- z&m9L@hqKN83dlMwfSm7Lkn7GsmYi+Vd*Crl_RV$g90)P3f&KE}ym+u5)|z$Y8sKu8 zBlmXaVEsAAPcR|Fw7=ro7!QS1iR;z`WrD|#V(fI1264kaFu9d685`8V+Kg6ouC~qI zmM&5s7(=Q(6*5s`F4h6A|KHA+dF~^pl%b)GmAEN=pt6W%P%&A9eQBapEEYH*4QcO7 zC3;R9II+~bF)xtNkjEETCX59u1`)=$+?iRns%x~9HOl3bCIBb~^g5yYs6 zq0Y{7oH|J1)JWU1NqdKTUnYq{mI{?16?;!bp}i2dzgNz~TZiiSZI0ibMsD3&xHY%^ z{^Gd{twz{(e_W^z1tf63$fY*36s6L66}rp)`S#WAb50t+qFj5Cn}I4y~Kg zBqen1P~=;^ymT^e&s#V29Wupq>${g`ss7ph#?V(?y7=vEOZ04vuGQ<}z{^y~66*P^ zno!}Y$w-Q&P)$-}%RuPqz&a}Is;MT!%#Nz{)Y2fgS=pT0Tnmc4rqvjN;Qj07&Ihjp zVvrB;Z*XvQD zxu;CEAr^xgZM{%PrEqqD`$N&!KBKt)RPHp%tyA?Xw}`Se37c!8k8_eTqth`htw3AZ zm~1S1a92z`@RU9C@Xu~NJj63$#L LZS{&p7>oY^Ev$2? literal 0 HcmV?d00001 diff --git a/_static/locales/cs/LC_MESSAGES/booktheme.po b/_static/locales/cs/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..3571c23b --- /dev/null +++ b/_static/locales/cs/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Stáhněte si zdrojový soubor" + +msgid "suggest edit" +msgstr "navrhnout úpravy" + +msgid "Toggle navigation" +msgstr "Přepnout navigaci" + +msgid "open issue" +msgstr "otevřené číslo" + +msgid "Download notebook file" +msgstr "Stáhnout soubor poznámkového bloku" + +msgid "repository" +msgstr "úložiště" + +msgid "Theme by the" +msgstr "Téma od" + +msgid "Print to PDF" +msgstr "Tisk do PDF" + +msgid "Download this page" +msgstr "Stáhněte si tuto stránku" + +msgid "Copyright" +msgstr "autorská práva" + +msgid "Last updated on" +msgstr "Naposledy aktualizováno" + +msgid "Launch" +msgstr "Zahájení" + +msgid "Open an issue" +msgstr "Otevřete problém" + +msgid "Fullscreen mode" +msgstr "Režim celé obrazovky" + +msgid "Sphinx Book Theme" +msgstr "Téma knihy Sfinga" + +msgid "Contents" +msgstr "Obsah" + +msgid "Edit this page" +msgstr "Upravit tuto stránku" + +msgid "next page" +msgstr "další strana" + +msgid "Source repository" +msgstr "Zdrojové úložiště" + +msgid "By" +msgstr "Podle" + +msgid "By the" +msgstr "Podle" + +msgid "previous page" +msgstr "předchozí stránka" diff --git a/_static/locales/da/LC_MESSAGES/booktheme.mo b/_static/locales/da/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..f43157d70c63ff21b4385dc36cb73f5b14eb6b01 GIT binary patch literal 1304 zcmZ9KyKmG$5XKi02pkaJ&;+qGJPH$nD9}aMKoTh;K$JVu@15uDO?nzn&U>A+XM4Phfw-zKH#7 zA8uHO_6vba9LDV+coaMYo(2zt6W}@UGI$1TfTzGEa2zD?I2bB!f*j{Lcno|A9tB^6 zC&9NBKUV%PmHi!Ly?>3CQ(qR(uY!{wt8{eFL)2d+-GK0XzbJ2D#pEAm_OQa=bqv z>yEt{#_?I3XFI&O|2#v^6KxpGSKQga zB|}Q$t~G&7@Oa2KoKDgpX6$2=SrtoT1GTMPm0g|DuG`zfb!d+>q}t0|B_w8J9T57T zIag$v?>HhOdp0JqpnQ-;9;-mHv<7xzI;nV=;{#=+_P!vo=(Ir)D;H<{wy4q`3h#>~ zA!JFY1gY2+>V#-Mj+V)JM61hEKVto8pj^8@e}8uO{nYgvwW_gEYa^$+3`k%y&y+UP zvXd(3DKs9n=AzrX-#KM`ms~V!IyTlOsmt4K9cl~8BnA3fm$9lXW`$E(G-qAU*QLn^ zrf=MwmgQsPs*#r(a_ZW2O)OJ9*z+b%Z59igr)teR+B0C^wn>Bm@6LBsXEFWfiOCp} zUSoVqXi7p(4!JPl*su1tkyFr_56Z-%sbe(I4#o^g{#-PJazXT;wvB`*ceb5TPdvg| zr`IHo4yJvN)iV_A{*4(42I?u%!cD5KXs+sR7@qEf{)q=$-v3Mo~pNRgs6dB45A_~g;fK07nJ@Atd!PtN@)FuuTCzw-;3=>No&-0+;~;^bfwAQikaeDcpMpPw z$G{ih3Gh|R-`o9n?fMUp?fnCGz(a>7-ya8gy#TV#x8N_}HSiTa&9^9*#YUsChPKG9Ug3-wb>5ahNSoell`9^ zoCmHU$Afe<^%ebHTryT9ZaN#u#(;-<*Xy#1V#z(Q#;HPD7is9+wj60gd)vV!pVPk0 zSm_{ZRgzdPbcFPDxsr?txhJx6>8J8fdK zt=*csGQxpNwNctG%DhrOQ0(2=TFGwgz2}t;Bl6j@&0V2w*_AhjI(F8SEfezEl?8P+ zO!CTPE6$HYSK7K+hThdhIeF}TXXUw`ymDc&BbHF5O7u~OM`4rK)5Mn;Zwdn zburuA-y2y!aDY4^_ YHT)aX(-~_xf`&nTEYd88)4;9x4>RdeS^xk5 literal 0 HcmV?d00001 diff --git a/_static/locales/de/LC_MESSAGES/booktheme.po b/_static/locales/de/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..e22b505f --- /dev/null +++ b/_static/locales/de/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Quelldatei herunterladen" + +msgid "suggest edit" +msgstr "vorschlagen zu bearbeiten" + +msgid "Toggle navigation" +msgstr "Navigation umschalten" + +msgid "open issue" +msgstr "offenes Thema" + +msgid "Download notebook file" +msgstr "Notebook-Datei herunterladen" + +msgid "repository" +msgstr "Repository" + +msgid "Theme by the" +msgstr "Thema von der" + +msgid "Print to PDF" +msgstr "In PDF drucken" + +msgid "Download this page" +msgstr "Laden Sie diese Seite herunter" + +msgid "Copyright" +msgstr "Urheberrechte ©" + +msgid "Last updated on" +msgstr "Zuletzt aktualisiert am" + +msgid "Launch" +msgstr "Starten" + +msgid "Open an issue" +msgstr "Öffnen Sie ein Problem" + +msgid "Fullscreen mode" +msgstr "Vollbildmodus" + +msgid "Sphinx Book Theme" +msgstr "Sphinx-Buch-Thema" + +msgid "Contents" +msgstr "Inhalt" + +msgid "Edit this page" +msgstr "Bearbeite diese Seite" + +msgid "next page" +msgstr "Nächste Seite" + +msgid "Source repository" +msgstr "Quell-Repository" + +msgid "By" +msgstr "Durch" + +msgid "By the" +msgstr "Bis zum" + +msgid "previous page" +msgstr "vorherige Seite" diff --git a/_static/locales/el/LC_MESSAGES/booktheme.mo b/_static/locales/el/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..fca6e9355f314677f2890f5679fd79dd67a7a5a2 GIT binary patch literal 1722 zcmZ{iPiS047{Euewt4U5n=fkKPHMz8X+JKcS{dGGPw+nU_c zCZPt>L)D-XMN9P{m<`*yO}BBoS3#I}@#Mj)Cp~!cBL2SFE!h-0?96ZHoA3Yk{@Ax; zMX{b{53_$`KhIu%fP=N`L8bVq-5d|WJ#ZJ?4|l_1_!N8@J_(C(AAASyg$6zb(>@oV z`1uSz3RmGC_yc?b-t6<2zWn$8{ZAG}N=-3*|lx#m@-51&_iV@GtlX{0B;& z|G|Us0FOuETkutwLXlsEZ^B>UVYqXrQitFhQ0g-9MK}YWfvbJC;B(wFD1G=Fz66IT z_E|X6=LsnC_o4J>9*)3IptM|SkT~LFKU;E^x(64jsmIx3FH7o|CH<3LOJ5JLNx{`F zvmIQ7ax;7w(hfIYb$phePOCsWALdpYv;G zOPqxDxMc1Trd2=DkykNltn8<_zIz?7*J?>AHYU*1VcDqDUXtp1RQ6I+)?vWC9+ax; z?Fa=g(0-ECjhcx404JfII61D)_Tt4R3KKsK<5_h!s`|lJua|GifioP~!B0M6o&VhxLBi1MZW0rDDj^PzkAoADB{_KUL1ZXW|5J z1>K9Em-u-XId|sNnX#?+BZm&>`i;#`&PJx7QxbSBs(F4es!LTbPE1;ScXB*`Y)dcp zg5;cu^J76NEc-#FppQ-YY3{TaRO_9ar-jjaZW8iNR~zWhPCd z!IGORj47br#qth1q_-xG*Y+m$QJl1ldYsi|#&y>pn)3O}2r<588%%~cb6DJv&M0zR z6Ju?!Gpp;aJ2H>n=Q;4)9QX)UBsQv>oVXExo49XqkvY35v_#)clq&D(UelG*<`bgE k?KNN}BbD^J+2#A$4_2dkCejtU)5(_TEbrUqDh*fv19*CpTMYflop9djWEuuR*>)1Ua4$Am958?gqbuT!-Hv=RLl? ztm83|e|Hk(lCvi7xt0eoxwahd<^hR9n|*n(9}lh{d$2y|1j)ji^V&Q(5ANYkOq8Lh zleoHqM}{7WYt{rZ!Q&-caXRS*F>UXd)T&q-8)(7WzFgEPZ5(@>yDt567<$^vOeG|m zu?~=4-?s8J^<76~z&terQmeydOn{H3s$Z$a!slCrhw4F8(v9dkg67!{> zqs)38tXmQDSx=k0@+!yH>Cu2hvC4%qr;bgMl%!G1I#EHx#L(SPMrYZlG|3z-YnxYL zZ<6X6Bk3-!Gg!U#kimbyhN}%YXpR zWvS9;N_Kn7c?ykNomO;Zym7(o#sxZQOml4 zuS=5^Ti>`iCCk^wX(LZG)Bqh@I0@tnvqcu0^K+ literal 0 HcmV?d00001 diff --git a/_static/locales/eo/LC_MESSAGES/booktheme.po b/_static/locales/eo/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..4614fe0a --- /dev/null +++ b/_static/locales/eo/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Elŝutu fontodosieron" + +msgid "suggest edit" +msgstr "sugesti redaktadon" + +msgid "Toggle navigation" +msgstr "Ŝalti navigadon" + +msgid "open issue" +msgstr "malferma numero" + +msgid "Download notebook file" +msgstr "Elŝutu kajeran dosieron" + +msgid "repository" +msgstr "deponejo" + +msgid "Theme by the" +msgstr "Temo de la" + +msgid "Print to PDF" +msgstr "Presi al PDF" + +msgid "Download this page" +msgstr "Elŝutu ĉi tiun paĝon" + +msgid "Copyright" +msgstr "Kopirajto" + +msgid "Last updated on" +msgstr "Laste ĝisdatigita la" + +msgid "Launch" +msgstr "Lanĉo" + +msgid "Open an issue" +msgstr "Malfermu numeron" + +msgid "Fullscreen mode" +msgstr "Plenekrana reĝimo" + +msgid "Sphinx Book Theme" +msgstr "Sfinksa Libro-Temo" + +msgid "Contents" +msgstr "Enhavo" + +msgid "Edit this page" +msgstr "Redaktu ĉi tiun paĝon" + +msgid "next page" +msgstr "sekva paĝo" + +msgid "Source repository" +msgstr "Fonto-deponejo" + +msgid "By" +msgstr "De" + +msgid "By the" +msgstr "Per la" + +msgid "previous page" +msgstr "antaŭa paĝo" diff --git a/_static/locales/es/LC_MESSAGES/booktheme.mo b/_static/locales/es/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..ba2ee4dc22148ed53f2aeba32c5965654d4a5a2f GIT binary patch literal 1396 zcmZ9Kzi$;s5XU#z;m3pU!zKwxjKJWQQZ~wEO{|$=X8*l*5%yj3EgEC(L#m|@E3-CIKPyLHQ^!@|o{A*Bj z4$La`8F(5z16~6q{%=5u|2}vYjQ#o}@F?a_K{@|BDEE2^ehj_>C4c{bvhUD`U0&uv z*?$p~_`U+=+!`qRz6aYpfs%6BBl;4{Ji6po;@;mNp-!U9Icai#X`&;(C9e__T(%nW zw)>mpL*DQZy5tBcRcdJ)pH3yKo8BdMDdMNz4yGuRTJ{f|^^|Mp6HmSWQEwW{d*1tzb%mTC1mCsq-qL_43=ae|t-eKOjtW>vaY#^sij18-e zU>uxyy|KKi?sj^CYadPWVO!m;OXD8uC5dfPa>c40^|ZUw#21BS?P$vslng{1KTKV8 zUUWKW55MCO;ccWl{h{a&Tjjy}+WN}g`qfKU z27O|OlkJ*EIw63|wI$;gbyiY{oW}PitHT?6`vSSR$zizSGM^h)jP#AENrPMDiUxTd zX^w*p+XS-1RUfK2(ynf&aeQr2cfaHFPM;g=s}~jrYQqQVnr;8cCiiNY181d=I%iD{ zk_k)9C=?Vlg{(ANUY4?kat==RzrVWKpj=Q5{Q{y&B&juy+NY=9viqbpt^2(7Sd&X+ zE$PfxwdF+Wo=v7AO<8KlnjOl_?lY%ZD#GnhWgz3#*VABvZk(=zpIWX+tyOg}6^wXC zsg65u%fhre9yJUf6KusrthQzv+672++(cecEV5X4sri<+xahTU@tQ2Tj8rs5BN4#T iU!*-mQ^Nsab@xTRCJqKkd{;ciD^w4Rh!536LH!R)!cyS? literal 0 HcmV?d00001 diff --git a/_static/locales/es/LC_MESSAGES/booktheme.po b/_static/locales/es/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..b4fccf19 --- /dev/null +++ b/_static/locales/es/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Descargar archivo fuente" + +msgid "suggest edit" +msgstr "sugerir editar" + +msgid "Toggle navigation" +msgstr "Navegación de palanca" + +msgid "open issue" +msgstr "Tema abierto" + +msgid "Download notebook file" +msgstr "Descargar archivo de cuaderno" + +msgid "repository" +msgstr "repositorio" + +msgid "Theme by the" +msgstr "Tema por el" + +msgid "Print to PDF" +msgstr "Imprimir en PDF" + +msgid "Download this page" +msgstr "Descarga esta pagina" + +msgid "Copyright" +msgstr "Derechos de autor" + +msgid "Last updated on" +msgstr "Ultima actualización en" + +msgid "Launch" +msgstr "Lanzamiento" + +msgid "Open an issue" +msgstr "Abrir un problema" + +msgid "Fullscreen mode" +msgstr "Modo de pantalla completa" + +msgid "Sphinx Book Theme" +msgstr "Tema del libro de la esfinge" + +msgid "Contents" +msgstr "Contenido" + +msgid "Edit this page" +msgstr "Edita esta página" + +msgid "next page" +msgstr "siguiente página" + +msgid "Source repository" +msgstr "Repositorio de origen" + +msgid "By" +msgstr "Por" + +msgid "By the" +msgstr "Por el" + +msgid "previous page" +msgstr "pagina anterior" diff --git a/_static/locales/et/LC_MESSAGES/booktheme.mo b/_static/locales/et/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..983b82391f499b67a9046c15d0dd8744650ad925 GIT binary patch literal 1341 zcmZ9Kzi%8x6vqb=^5gOYNC*@$VrY^ev%C-5~0q6cNoSQvQHcDIz*5N(ux8-*>yj7Nec{?37 zm@hCt!hG}w7K~$WDuqWK$8rQb2_6H_g2%xn@O|(C_#QX{&wyWnr$GYW22;<6py+%D zo&tXWPl7*z?}ESdeBSTB?Csw{@%I-v01qANzCR6$y#$KRMeqsu1$Y$v1AGho6Fdz5 z4az++J_JsIlKZFNIq(K3aoh#Zg45o90E(Y)LCNb!P;`Fo`2>{wpMm1IA0b zcW{Vb>7mpIdO`vjME%rCbb#Z zLB#9Ln`>&T^B1V~k&_R*YOAf;-PhM8wsB1jsl}?dyPU?psw`<|W?Y%XaN_8G>Z0@F zr*qN&8_XbscI- zgH4-*vBjDXO&n_1F3dRkd|7v|qf1VIJknP`Sstj{^T%OktXj#ancCu*yH}n+<|;=N z-jrOCj`OFMOqk`wddINU##;0GR19tBdvzi?e7zruw52+Aw>NT5Q%F&X%h*Lj=6f7z z8jNuq=-IE#jk<#c{m?m+L;rJ$825O_Nq(D^8CKl}zio+{#UD_z^uJ)WVl7Wi?YTr` zTRZHgk)aH+jLK4D)OfM3BNeE1ohJ(1utQX6H>rE`y-+P|2~e4t1fZw$r;!^}gUIe5 P_MW2m5}a<3ol*Y+f5$~k literal 0 HcmV?d00001 diff --git a/_static/locales/et/LC_MESSAGES/booktheme.po b/_static/locales/et/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..b748b37f --- /dev/null +++ b/_static/locales/et/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Laadige alla lähtefail" + +msgid "suggest edit" +msgstr "soovita muuta" + +msgid "Toggle navigation" +msgstr "Lülita navigeerimine sisse" + +msgid "open issue" +msgstr "avatud küsimus" + +msgid "Download notebook file" +msgstr "Laadige sülearvuti fail alla" + +msgid "repository" +msgstr "hoidla" + +msgid "Theme by the" +msgstr "Teema" + +msgid "Print to PDF" +msgstr "Prindi PDF-i" + +msgid "Download this page" +msgstr "Laadige see leht alla" + +msgid "Copyright" +msgstr "Autoriõigus" + +msgid "Last updated on" +msgstr "Viimati uuendatud" + +msgid "Launch" +msgstr "Käivitage" + +msgid "Open an issue" +msgstr "Avage probleem" + +msgid "Fullscreen mode" +msgstr "Täisekraanirežiim" + +msgid "Sphinx Book Theme" +msgstr "Sfinksiraamatu teema" + +msgid "Contents" +msgstr "Sisu" + +msgid "Edit this page" +msgstr "Muutke seda lehte" + +msgid "next page" +msgstr "järgmine leht" + +msgid "Source repository" +msgstr "Allikahoidla" + +msgid "By" +msgstr "Kõrval" + +msgid "By the" +msgstr "Autor" + +msgid "previous page" +msgstr "eelmine leht" diff --git a/_static/locales/fi/LC_MESSAGES/booktheme.mo b/_static/locales/fi/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..d8ac054597c924e3010f629caeac1c748b7211cd GIT binary patch literal 1368 zcmZ9KJ#5r46vquMU&lA4Af!r|g^wXX5kqz52B58kprWEjclYv|xbfLh>>S*}#K;Cr ztS2O9B*cCTVrBw~l?gF1AR)y6B`K}2;{5K}=lB1=7k@o5`BGq<#+lRCrOA1CaQ!^kKlhsTrZJIH9K_^ryK`_q_#3i5+EIO9achW2 zhLpr@X9L;b@gpA=I!S|AaF48UDwfs-T6Zp!8`{wJvUg?CqyH8|s=drrLSix20jamb zrP3JRD~PP@yO_j1<%2BqSOtouvxrOEOU3;he^6Fx?@JOZg|3?XUWo3*(Ha#V+1j$!k61sdlv~SpmKV48XD?rEHI0qB!<^bOz`&KTmRqe+kV}^cf!#bT&>G1)AQnFuaA9SXR zO>~T6=Ywl@%y^W>^xt9_kNV@0^m3c4B9BMrgfh( zuVp?S>46Ru!ccTe7eieYS*GF0;G*3eAeplXnZCllffvOWA=>i5w+5yH-zgk~ao1dl zs44(@M0}Rt9Mp|iQ#yrKbuAq3msY|P`l$x0E<_Em{7-o?CS$aPMpfmO5T&sTb;r2u H66VBTf3Z^G literal 0 HcmV?d00001 diff --git a/_static/locales/fi/LC_MESSAGES/booktheme.po b/_static/locales/fi/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..f58cf58d --- /dev/null +++ b/_static/locales/fi/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Lataa lähdetiedosto" + +msgid "suggest edit" +msgstr "ehdottaa muokkausta" + +msgid "Toggle navigation" +msgstr "Vaihda navigointia" + +msgid "open issue" +msgstr "avoin ongelma" + +msgid "Download notebook file" +msgstr "Lataa muistikirjatiedosto" + +msgid "repository" +msgstr "arkisto" + +msgid "Theme by the" +msgstr "Teeman tekijä" + +msgid "Print to PDF" +msgstr "Tulosta PDF-tiedostoon" + +msgid "Download this page" +msgstr "Lataa tämä sivu" + +msgid "Copyright" +msgstr "Tekijänoikeus" + +msgid "Last updated on" +msgstr "Viimeksi päivitetty" + +msgid "Launch" +msgstr "Tuoda markkinoille" + +msgid "Open an issue" +msgstr "Avaa ongelma" + +msgid "Fullscreen mode" +msgstr "Koko näytön tila" + +msgid "Sphinx Book Theme" +msgstr "Sphinx-kirjan teema" + +msgid "Contents" +msgstr "Sisällys" + +msgid "Edit this page" +msgstr "Muokkaa tätä sivua" + +msgid "next page" +msgstr "seuraava sivu" + +msgid "Source repository" +msgstr "Lähteen arkisto" + +msgid "By" +msgstr "Tekijä" + +msgid "By the" +msgstr "Mukaan" + +msgid "previous page" +msgstr "Edellinen sivu" diff --git a/_static/locales/fr/LC_MESSAGES/booktheme.mo b/_static/locales/fr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..f663d39f0faa76c5b9bd504c51252eef74cca5de GIT binary patch literal 1412 zcmZ{jJ!}+56vv0pm9t{vhm&8^IIO`h6wqyy*798~B-FLeKdo!!~aIl*+ zlr)i&DosjGX-Sm+nxs!ffzqWyh>mpmzuUEJBQe_9-_FOq|NFX^vnPL27*{aoG5^N= z4D;zRyf9{tD}_g$!Rs`57MuYuf@i>a@G^KEoCEvdEO-|@2Qqjbj4hvlV&_NjBk*VN zEI0-~27hn)XS@HRUH=P;-hW^RJaMA={W(z9^Pt$d0saAg1L9Gy@DjZ@;0NGaQ2bFR zmAVF8043f<@DuPZcoBRAia+0jpMpPtqW^1q{u?N9{{>2%|FrAZpu~0hRC7KD%K8iN z5_lUFyPKf+qrt170VU-UgXB+gDSn8C=pG)BP!}*oSBAtdL+nayq9N(OOB9IrIvT`P%K$}>uh8j13v0qZ;CRi75AO3oX*L*$lK06qM@nyU^}?vGk#|? zmL^cG3s$SSi7>stTuW6IGS6&j2uDVy3#y+NH@oiA@h}HB>+f7UZR}>YK)jOup(LluVV6L*Ln| zlGjyt&G}L2k*%l8&|h4l=Cgm((zQMpFVk1~#tn>=qIhM|}`x`)$>jU}ieUbVvBn#nWIG%|r{ z@(VpgvBl*|+YE)ZQEjFj&wG?C)!uDalV>RR`l$A11nWA{5XsPS+9@lOaXon+Y2Ue0 zE>oVUGO*E>4ZSkmuAAH}>yV{N!q_?5zAzp!&O#! TA2+cw{Vw>h7Yg+MtLz81? literal 0 HcmV?d00001 diff --git a/_static/locales/fr/LC_MESSAGES/booktheme.po b/_static/locales/fr/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..8a6c9461 --- /dev/null +++ b/_static/locales/fr/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Télécharger le fichier source" + +msgid "suggest edit" +msgstr "suggestion de modification" + +msgid "Toggle navigation" +msgstr "Basculer la navigation" + +msgid "open issue" +msgstr "signaler un problème" + +msgid "Download notebook file" +msgstr "Télécharger le fichier notebook" + +msgid "repository" +msgstr "dépôt" + +msgid "Theme by the" +msgstr "Thème par le" + +msgid "Print to PDF" +msgstr "Imprimer au format PDF" + +msgid "Download this page" +msgstr "Téléchargez cette page" + +msgid "Copyright" +msgstr "droits d'auteur" + +msgid "Last updated on" +msgstr "Dernière mise à jour le" + +msgid "Launch" +msgstr "lancement" + +msgid "Open an issue" +msgstr "Ouvrez un problème" + +msgid "Fullscreen mode" +msgstr "Mode plein écran" + +msgid "Sphinx Book Theme" +msgstr "Thème du livre Sphinx" + +msgid "Contents" +msgstr "Contenu" + +msgid "Edit this page" +msgstr "Modifier cette page" + +msgid "next page" +msgstr "page suivante" + +msgid "Source repository" +msgstr "Dépôt source" + +msgid "By" +msgstr "Par" + +msgid "By the" +msgstr "Par le" + +msgid "previous page" +msgstr "page précédente" diff --git a/_static/locales/hr/LC_MESSAGES/booktheme.mo b/_static/locales/hr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..eca4a1a2842830f06bd5f6235bf01d07bdd313d2 GIT binary patch literal 1402 zcmZ9KJ!~9B6vu}+kmLvh)-Bbu!YZ&sL*)#Wq0oOW>)iY z#I7UJKoJQlD$3MIh{}~uqNJdrprN2bqC$d-|Jz;1r;K*?xAU?8_kVBZ_tmrCDzsP8 z*U*1Oe;xg+XYfKhe?}=h>H=QRffvE^;1%!!xCXugz6HJv4#8FMQ}7bV;EQ1F_z)DG zZ@?G8@4$=TWAG*L$BsXD^S^cDKS7E2FW3WDR@(nBfihkLMdxksC-6Fmt?DmO{`(sg z-~WN)YvpX4?<)8j#_OQu@i8cQeBP}`P-^oC6rIQ5W$*{^dGHvNe1GZqM>qcuD0MvZ zY`gv@DF5B)#v@RCe+FI!b5KeyIf$NkxPmU8B<^y9bfYDCNE01tQa`D+)KxSg*?1KH z%T4MpwK#{4ax`^Pw+`@7ELnZzY-Ae)KI#K+iZZI(?h9Kvos)Hu_nn*4eN*x2ba2UM z{M2MDO`uvAtTuBKA$>9&rK$>r--+ODxdTQVUeRy*EU zh&bB0JyN@EJkPZYCOUthcI(pE2XsrkjZ2=fYTmTp<}`LiQ88IPH-(M{K`cLrtve@i z+90*(xpAqpy(Aw}Q7~LGGJzF0;VkyI^8P*c0crzk0e zJ5}W`eCg#p>R8HV8p8`ORd-?8+@kgmPE(NjB4ZRZpsbXo1{+%JywM17c0!7$ZS zdp+04j?>}H5RL>u+?)6`B(!QC;nQ(E%YYHwOi5)9EgF2Tundr{ymsm2Z;f2mKh k(#nYgw(f}olqHrfw@Z7L48TfWxy6y8Q4`jSBkXa^hFIaGO(a}_Drr&ngPIpyPhwkKtCW1zS zxtWoenhB;xBBn-yn24D8zwTalu&Ao9Uv<5s{`Yli#|wdR9BT&a6V_?0r`xb$Ol}tf zQ|!UE3)}}zg45t0a0WaEo&}G9U2qD#3myOoJP3w{Pe6|I9NZ7S1owfj!NcI&h98>q z&yD>JoIl_+xD%H+@5zQ2!9%dS z4R3=dU_S)+f*T;`dD8G1$o{WD_Im?z{P&Ih5#&5yK-S?0$ohz#wGPuD`<((=a*oaa zSxfd~Z8_ffK#0nR_2t3u=fQPw4%YQ37D84vb8p87>(4#hjm4TkQX%F>m@;G}=B){2 zg2zWWayrd|Sg?;xZdD?U4b-=GDA#mOTgTo;H=zFxL#DkfRZ3zp(E*`1&83*aj(wjsI*=O>qg>UnQ5~j z=eV|BMg@s#m;L%pJ)5RENuwU=R0WMBhBiW7o#i}rlG4#5ZDUjRSa=`Plu#w%B`C$N z(;&2$llB909??3o&fn(z?J9F?WqD;KhDS6Yp*?cS)QjtnT^a+xb_X5}DL&Qs{# z?=7`&Y~6Fp_%(9vMKiF8HfcxR=o0auv z_q>s3y7KCU*_ODI6J+IW*=v!hp&aNkC~@B;F{`@wufgMIJ{Em)%}J(mRd82~uKPNE zu!45VT#b~I5H)6^M@|hh?PQ`$a((5ZmR_kKRwzf4qZ=wC=HgJvLU}~a#5@JmHKeM~ zcQ+dhueyjH6-vS(Hi{zy4lKXvX09`YYnog=urAe8uFQH2W~4-u2I{*$(n5sIJAG7C T@Rc+s5Lgrh10CRyRonjp5+F85 literal 0 HcmV?d00001 diff --git a/_static/locales/id/LC_MESSAGES/booktheme.po b/_static/locales/id/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..1eca5994 --- /dev/null +++ b/_static/locales/id/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Unduh file sumber" + +msgid "suggest edit" +msgstr "menyarankan edit" + +msgid "Toggle navigation" +msgstr "Alihkan navigasi" + +msgid "open issue" +msgstr "masalah terbuka" + +msgid "Download notebook file" +msgstr "Unduh file notebook" + +msgid "repository" +msgstr "gudang" + +msgid "Theme by the" +msgstr "Tema oleh" + +msgid "Print to PDF" +msgstr "Cetak ke PDF" + +msgid "Download this page" +msgstr "Unduh halaman ini" + +msgid "Copyright" +msgstr "hak cipta" + +msgid "Last updated on" +msgstr "Terakhir diperbarui saat" + +msgid "Launch" +msgstr "Meluncurkan" + +msgid "Open an issue" +msgstr "Buka masalah" + +msgid "Fullscreen mode" +msgstr "Mode layar penuh" + +msgid "Sphinx Book Theme" +msgstr "Tema Buku Sphinx" + +msgid "Contents" +msgstr "Isi" + +msgid "Edit this page" +msgstr "Edit halaman ini" + +msgid "next page" +msgstr "halaman selanjutnya" + +msgid "Source repository" +msgstr "Repositori sumber" + +msgid "By" +msgstr "Oleh" + +msgid "By the" +msgstr "Oleh" + +msgid "previous page" +msgstr "halaman sebelumnya" diff --git a/_static/locales/it/LC_MESSAGES/booktheme.mo b/_static/locales/it/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..53ba476edd2df2a802917e9df402257ceca1a130 GIT binary patch literal 1403 zcmZXSJ&aXF6vsyafhY1QYQiQS8W$5EU!j1vc?Gb$351Os-eM!oynD~ycVOPkWoGWm zTH9#}m5qrNiM6q@vN55xvLLatGO@6+(D*<1-gP%Hxii0e=Htvc|2Z#C?tf~~-bG(P z{{{Vh^sipSfOhD0WAK^77~TMnfQP_S;9+n9db5tC&9bmQINr7VD9+^sD7S+ zZ-HNfN5E&`3Gn-#Klk&$_V(|f-uE{+0Qc?d&L0KUUI5k4BKQM%1;keK2Z+!7i9yf* z1s(_g1vTGe`;B=I{0KY^u7H})r~P~cRhutC&HGzW&wmGM{6B(v?m2h{{0%$^{sW!` z4;<+7S_JjnwcfrBYTWn1Q(y(ER@tjRN(zMHIBUF`R@^(uqn+2D6ew@4L zg5J|zQb*pB(DY&Nai5y1VnoTv1fhfnT;$=ca`*|y1aBki?jP#?!}jLE+O4&f-Stc7 zFAjQPha1~9k0>L63$?T2m#CQ8m^hE`ZLAKj?(U1$r%jH-6<>r>d^Mu0Q^|un)>jR5 z9TALm*F@`vt0B(QhBFUgSr)TwUH`yMh9yxlG%Xix0~y&& z3LB-cB(8l-D%nxCMbU^4uPmkzD-_D^sYeYovZ|_hYt|6+raF6N+B(TUeM703ahwOj z!*UGfp34HuR+WV4?HsPL=1>m45R2fh*HNhPRL3xNJhx_&?Yu^?zAcKo|5pQ*LIIU4 z9%X=yZ5mFd5t*`cmL{7}b7xJ=^_*qP(gmDLw)@AXu2??D^RnquqSO=xr-aR>O-k3u a)*Q3l*@6-(xNK#4xqhOgLbT*tS;gN$Zm<*V0gr*F!6RT6JPeM4`#}XB0Byp@Am^!p`@mOV z7q|)@0zW4Fn)rVt_HU5uZGb6o$Bx$f{UF;tAm=#)eg-dtd%-^-*V_PDx7aDf37`|? zeoukD;5CqS=MqLB_wxkgxVgmt1?-0X4dj{qO1J@X+@W2qe$Rs(cQvs`6FUcTpOYZ# zd6M|6Adj4TU>#hW-}7v_@AidK;vhE9mlyZXi}UiVd9FvXkushE>ug^<53aoj8)J$8 zzT$crKWU3f+%VcIZ9^RVa^Sf|D{h)8T{2EVYGYN-m<~=w|xXST6$p^DKQdw8cB>C zxj87tTJ-|uo6xf+D2p+_=;?>@I%^v*stG0HugtZ28aJ+6Qc^pUp6gf-MYMWoTj~tg zX%+DUHR+isk=>R)j9gbir9vl=V(zQFO%D~)cU2G~TSm6(r@4MQuACYk8XnlX?>m1n zl?*mLUiMW+S_rt{mmE*`%Y4xZLS?ge#s||^w&DUuhxb&F9?*GH@U)weS8|?B-Ey=W zVXhhJO{GRkQQ(x)gC>{=GgAAp8D=l_%hoY_R?FV3>^s+=67+^$;pPAU literal 0 HcmV?d00001 diff --git a/_static/locales/iw/LC_MESSAGES/booktheme.po b/_static/locales/iw/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..9e6d753e --- /dev/null +++ b/_static/locales/iw/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: iw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "הורד את קובץ המקור" + +msgid "suggest edit" +msgstr "מציע לערוך" + +msgid "Toggle navigation" +msgstr "החלף ניווט" + +msgid "open issue" +msgstr "בעיה פתוחה" + +msgid "Download notebook file" +msgstr "הורד קובץ מחברת" + +msgid "repository" +msgstr "מאגר" + +msgid "Theme by the" +msgstr "נושא מאת" + +msgid "Print to PDF" +msgstr "הדפס לקובץ PDF" + +msgid "Download this page" +msgstr "הורד דף זה" + +msgid "Copyright" +msgstr "זכויות יוצרים" + +msgid "Last updated on" +msgstr "עודכן לאחרונה ב" + +msgid "Launch" +msgstr "לְהַשִׁיק" + +msgid "Open an issue" +msgstr "פתח גיליון" + +msgid "Fullscreen mode" +msgstr "מצב מסך מלא" + +msgid "Sphinx Book Theme" +msgstr "נושא ספר ספינקס" + +msgid "Contents" +msgstr "תוכן" + +msgid "Edit this page" +msgstr "ערוך דף זה" + +msgid "next page" +msgstr "עמוד הבא" + +msgid "Source repository" +msgstr "מאגר המקורות" + +msgid "By" +msgstr "על ידי" + +msgid "By the" +msgstr "דרך" + +msgid "previous page" +msgstr "עמוד קודם" diff --git a/_static/locales/ja/LC_MESSAGES/booktheme.mo b/_static/locales/ja/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..1cefd29ce3cc08792667a82dc7ff47e9843107be GIT binary patch literal 1471 zcma))U2GIp6vr=uT2=%temyktnh+I|RZ$+uHv1sbO-LX%QhlH9-p&qe?;Yo((zoth z!EFJNkCxzqu~zx0SU`c+ubA-Uv++eAe7Tv~_Q5w};+y|7GulOC;?11-%{lkn^L6K! z-gVOq>v2dQu6IDn_Xk)2*RIXZZv;v211Zik;1ak4q&&ao z_TO@S&AKd35BL)Hd%6F@2|fYNfYiq|km|n!QoJ8>{U?y}t$^hJJGcehbZ=(g z0h0bQNasgDiZ_<)lR3|UkHUThq>)oh@}pU9hR|%O@9u?E>>&uvmlpL;i{?kUXs#3! zA=v{Ey4&tWeb61=55ZW{`(?Yv@$jH7*egl~LIyrQ+;Pvb>jB%X-jWSv)wooF7*^^a zA8{ID)$FU#tBQXZgSz8$*Rlm0s5t>b|D{&KM#HaqLP$QUYJ%;x{D6mU%?d<~D+xW6 z)jE6Cg@Yxz75=BO|)yDPjO+O|NI0-c}~bwE^u;+|UZ4dMBS zR^nOyBIPfpnG5^&>>F6!-~QYSg?zBZp>bD~cz^<)cN>-?`+2o)dAX*25Q`IlO*w3@i^0SgZ zRp#5b_7~Xl$+OE7hnZ=9YND2D&Y9*#)@d&!S7*EK+UR$U{>JE*(KAMC6J0ZU+C;M^ z`q*e3JZ1ERi7p!bh0&j-o|DW(-_lp~<^OPPo;J+|qu);tEd58ke>rs)FR!$Zu=w!h z&Y7=QE_`G(9#lEWlJgUtTT#-!nao^I&VIs{Z!N}0r&&CGVrBLi!p9%ph)+&2{5I%2 zK7KuJEq2#CZ}bHdEv5a=V6`%k-R^d(Xw}Jf>8QN5e!h zBbA`3bkQ)WS=dVKSy@;~B<{I88!P_b+$$|{a=-hV^ZNe(@4NG5)%+^MSdZvHd_rtS zROaA?v3M?Hcvu@=3&Ew}VsJIs26lk!z^&jKFbl2%PlD~B0GES0VHu=655Q&M6L2Xw z0j>n66Mjh6KPU5VAnE-CQ{cRL@%?s?<{cpA*#_Ef2kG3A zWc>t4Ehi1?A9+}fAZZd{dqh6EFS_D$EB?$Vqvj_EszTqMS+R^&H z>|hBG*9E~2DXE3jK7P0*&#?=d9aa}*QCWE|l@|R-n>7qsZZHEJ ziA7vbTyRv7*q)W%4{Te&r9dUHqRxq&PWR-~XN2b?TZYH_Y0^)(lvBrgj&;rK@7cLK zl{7ZpS8_#$YZ%z&7A;41@?634e4(?a`?}KyX3lw*^v?<}-6eA>??^kt5A-`ab<~n} zfWBto^Y9)w_0g!> zVBythE}X>$!Q{z_su`ZeFjL;phL~syBFa zXVlaiX8iI$xBl9S?ljH#2qeqqHLg5*5Kc5=W8s^|_vRD}$A^$29KXrU!@=^_j5Dv6%;4cA#sHtggl>eA))${_687xQDk?6`Kc@OWFO}WOS!3uO( zjPOmFMc3|`Ymgi(M~_AsRb8*l6oj5N!k1G#oNSsg^a1i?<=NZRz?N8C9`e*ob%^~2 D6Q!<* literal 0 HcmV?d00001 diff --git a/_static/locales/ko/LC_MESSAGES/booktheme.po b/_static/locales/ko/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..80142313 --- /dev/null +++ b/_static/locales/ko/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "소스 파일 다운로드" + +msgid "suggest edit" +msgstr "편집 제안" + +msgid "Toggle navigation" +msgstr "탐색 전환" + +msgid "open issue" +msgstr "열린 문제" + +msgid "Download notebook file" +msgstr "노트북 파일 다운로드" + +msgid "repository" +msgstr "저장소" + +msgid "Theme by the" +msgstr "테마별" + +msgid "Print to PDF" +msgstr "PDF로 인쇄" + +msgid "Download this page" +msgstr "이 페이지 다운로드" + +msgid "Copyright" +msgstr "저작권" + +msgid "Last updated on" +msgstr "마지막 업데이트" + +msgid "Launch" +msgstr "시작하다" + +msgid "Open an issue" +msgstr "이슈 열기" + +msgid "Fullscreen mode" +msgstr "전체 화면으로보기" + +msgid "Sphinx Book Theme" +msgstr "스핑크스 도서 테마" + +msgid "Contents" +msgstr "내용" + +msgid "Edit this page" +msgstr "이 페이지 편집" + +msgid "next page" +msgstr "다음 페이지" + +msgid "Source repository" +msgstr "소스 저장소" + +msgid "By" +msgstr "으로" + +msgid "By the" +msgstr "에 의해" + +msgid "previous page" +msgstr "이전 페이지" diff --git a/_static/locales/lt/LC_MESSAGES/booktheme.mo b/_static/locales/lt/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..4468ba04bc134a84fea5e3c973461cf02c9c2da3 GIT binary patch literal 1413 zcmZvaJ*-qk6vsyag_RElKVp1=p+SgQ1!6(=Ws8Trm%IpJ!!Cq&-rn=>&feLX$$UJx zy>yfs3mYDtv7j(9R@&?)#@fol&{Y(AbXL(_rUwj`9qL(er@8vgIw=pko$cKo&XOVSm=ES z^8O^qK3oL({z?6$1#4Nz2(054oJ;=;JiGzE*_kpy=GszcBB+< zVRAov2m8<3><4U^|G(mLjYp;ti7%W@WK+ZsUk6=|lDOjTSmRV7txL4wTqQTPq1|wF zISlEQU>fNty(&qp7CIsI&UP&u6NiDw%84sTTvaj2>KHSL zUeFdvoa|j$6a9r=An&41F4Us$N7~+%m$|mVh$bZFtK3-hG;n2UNLsa}OO-T4EZt3u z>KyAVM0}tv?Q&E0p7b%7C80_}Cn&{@X_(sUMf(ENwtj7O_x!@A z=Ua`j?LqCSBNGbv%p0ZcvK)?7h?KfF2W#z1yZ3^!ag#!O)ec>uZP}5RHgsxTRkqCV zwIfYx^-K=RwAWmi#E!InzKz|B%X0Cvd)CU+U3uZ$a!agNntg;f8E)25tYny{XFsAC z9jD(SkfM$V#H6LA*|v6LHF0AnD>v~vCkoohO{LBB-b;69+sY(u|L3sMiR5g1`bhd5 zjq=k+;szC}%nlMS$9vjXC#gc)P6nF&q9-bfo{CjQZe*xbNYi^#C9ConpM%1oLFKH0 za&)0WJ=gQWZ5W!M$i7!O!aIl|0e?HQ2Ro%kmCL#^O7u6its3{(8W!QLNCjg(=>2Jsvw ClWZvf literal 0 HcmV?d00001 diff --git a/_static/locales/lt/LC_MESSAGES/booktheme.po b/_static/locales/lt/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..2e6915a9 --- /dev/null +++ b/_static/locales/lt/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Atsisiųsti šaltinio failą" + +msgid "suggest edit" +msgstr "pasiūlyti redaguoti" + +msgid "Toggle navigation" +msgstr "Perjungti naršymą" + +msgid "open issue" +msgstr "atviras klausimas" + +msgid "Download notebook file" +msgstr "Atsisiųsti nešiojamojo kompiuterio failą" + +msgid "repository" +msgstr "saugykla" + +msgid "Theme by the" +msgstr "Tema" + +msgid "Print to PDF" +msgstr "Spausdinti į PDF" + +msgid "Download this page" +msgstr "Atsisiųskite šį puslapį" + +msgid "Copyright" +msgstr "Autorių teisės" + +msgid "Last updated on" +msgstr "Paskutinį kartą atnaujinta" + +msgid "Launch" +msgstr "Paleiskite" + +msgid "Open an issue" +msgstr "Atidarykite problemą" + +msgid "Fullscreen mode" +msgstr "Pilno ekrano režimas" + +msgid "Sphinx Book Theme" +msgstr "Sfinkso knygos tema" + +msgid "Contents" +msgstr "Turinys" + +msgid "Edit this page" +msgstr "Redaguoti šį puslapį" + +msgid "next page" +msgstr "Kitas puslapis" + +msgid "Source repository" +msgstr "Šaltinio saugykla" + +msgid "By" +msgstr "Iki" + +msgid "By the" +msgstr "Prie" + +msgid "previous page" +msgstr "Ankstesnis puslapis" diff --git a/_static/locales/lv/LC_MESSAGES/booktheme.mo b/_static/locales/lv/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..74aa4d8985d96a07c4c9be96f006f3b58d884342 GIT binary patch literal 1404 zcmZ9K&5ImG7{*_dsL7ZQP5eMvump*E7&XB|oMjFhcNYS?IAk~8Yi8c*sqUVtras2( zdKwT<9)#7Cr{GC*^B|r)^?-kXCk3y9;7t%O;`2^-vdb1-{p+f(exK)k=-;oN`-(7L z!d%1r1@l$R&!4~zPs;uHG2 zUH=1$um8Z;!As|eUIA~m+y%w|6qJ5G0bd5c0G|fGYu|qlzJT=-lzP8`lHs4A_&D=q zlgkxQ>Rkt~f$z861tmufO5Zssk;}JoUbN-BWGj829FU-AF-2E~^e;o|NY;|8ctc5g z22*^U9FmJ@OFxKVl@HxMz@_4p=>umY+Zgar9e9&XBW=2mZRzw_Sr>WeT%jhWmHkCxl1EW^k%TQzfIrX3xkO4V3L9xG?DPIfe<4=WtdR+$hI z)4&^xB2Eo9w`s4@^IW-LqVor|S51w*uWpOC{VC6wR(CaQdfIncRMGG) zBv*eURUdB+Oli45Wvi9v9Ia6vne84ZIht?0o$f< A2mk;8 literal 0 HcmV?d00001 diff --git a/_static/locales/lv/LC_MESSAGES/booktheme.po b/_static/locales/lv/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..d4f4b150 --- /dev/null +++ b/_static/locales/lv/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Lejupielādēt avota failu" + +msgid "suggest edit" +msgstr "ieteikt rediģēt" + +msgid "Toggle navigation" +msgstr "Pārslēgt navigāciju" + +msgid "open issue" +msgstr "atklāts jautājums" + +msgid "Download notebook file" +msgstr "Lejupielādēt piezīmju grāmatiņu" + +msgid "repository" +msgstr "krātuve" + +msgid "Theme by the" +msgstr "Autora tēma" + +msgid "Print to PDF" +msgstr "Drukāt PDF formātā" + +msgid "Download this page" +msgstr "Lejupielādējiet šo lapu" + +msgid "Copyright" +msgstr "Autortiesības" + +msgid "Last updated on" +msgstr "Pēdējoreiz atjaunināts" + +msgid "Launch" +msgstr "Uzsākt" + +msgid "Open an issue" +msgstr "Atveriet problēmu" + +msgid "Fullscreen mode" +msgstr "Pilnekrāna režīms" + +msgid "Sphinx Book Theme" +msgstr "Sfinksa grāmatas tēma" + +msgid "Contents" +msgstr "Saturs" + +msgid "Edit this page" +msgstr "Rediģēt šo lapu" + +msgid "next page" +msgstr "nākamā lapaspuse" + +msgid "Source repository" +msgstr "Avota krātuve" + +msgid "By" +msgstr "Autors" + +msgid "By the" +msgstr "Ar" + +msgid "previous page" +msgstr "iepriekšējā lapa" diff --git a/_static/locales/ml/LC_MESSAGES/booktheme.mo b/_static/locales/ml/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..2736e8fcf6f9e923c2403307f0b366086d37b335 GIT binary patch literal 1883 zcmbW0%ZnUE9LGydG>*^22ObnFl0!U=*`!Gj=35eWDu@Vn6%SYIC#v~L=<+PV8oUUd{}t%`e}*gYclZSS_^!ZZxSjb`_!_(p zTd=uFh;ewl;wqeG{x{qKTbqR#gE5?hpTno&U(oq&;Si6(7JLc50p0#-xD$R4pMlrl zez^G_At=eHx!OEj&F+K95`^|`3%xs|tB0$dYp$lQaXj&eABB3jp*ug}eRDN&btbLg zC_?O6*AzH~{-A|&9)JdV{ljJRVAnvQRl4{_?&D7b7KD1k z&HJ`jzT)e&M4gbqlB?mhqaXMpAZg<;-hlh5ZiX1=e36nUswzgb&SN${bnp4Gv=IQ6$P05hgaiFop^2w W+5FkQ^s?wV7=JSkIl3Km4aE({iDO&< literal 0 HcmV?d00001 diff --git a/_static/locales/ml/LC_MESSAGES/booktheme.po b/_static/locales/ml/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..5d8ed33b --- /dev/null +++ b/_static/locales/ml/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "ഉറവിട ഫയൽ ഡൗൺലോഡുചെയ്യുക" + +msgid "suggest edit" +msgstr "എഡിറ്റുചെയ്യാൻ നിർദ്ദേശിക്കുക" + +msgid "Toggle navigation" +msgstr "നാവിഗേഷൻ ടോഗിൾ ചെയ്യുക" + +msgid "open issue" +msgstr "തുറന്ന പ്രശ്നം" + +msgid "Download notebook file" +msgstr "നോട്ട്ബുക്ക് ഫയൽ ഡൺലോഡ് ചെയ്യുക" + +msgid "Theme by the" +msgstr "പ്രമേയം" + +msgid "Print to PDF" +msgstr "PDF- ലേക്ക് പ്രിന്റുചെയ്യുക" + +msgid "Download this page" +msgstr "ഈ പേജ് ഡൗൺലോഡുചെയ്യുക" + +msgid "Copyright" +msgstr "പകർപ്പവകാശം" + +msgid "Last updated on" +msgstr "അവസാനം അപ്‌ഡേറ്റുചെയ്‌തത്" + +msgid "Launch" +msgstr "സമാരംഭിക്കുക" + +msgid "Open an issue" +msgstr "ഒരു പ്രശ്നം തുറക്കുക" + +msgid "Sphinx Book Theme" +msgstr "സ്ഫിങ്ക്സ് പുസ്തക തീം" + +msgid "Edit this page" +msgstr "ഈ പേജ് എഡിറ്റുചെയ്യുക" + +msgid "next page" +msgstr "അടുത്ത പേജ്" + +msgid "Source repository" +msgstr "ഉറവിട ശേഖരം" + +msgid "By" +msgstr "എഴുതിയത്" + +msgid "By the" +msgstr "എഴുതിയത്" + +msgid "previous page" +msgstr "മുൻപത്തെ താൾ" diff --git a/_static/locales/mr/LC_MESSAGES/booktheme.mo b/_static/locales/mr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..fe530100d7715cdc19a6f9db33a971665835f3c4 GIT binary patch literal 1674 zcma))-D_M$7>7rVU#qnriYO?KB2uYGt)hetL1>ylCBZ;a@uD{;yVJ8rH#3KG&bG~6 zRisua;ze5NO^wW!;71IF+EldSwKo+61wrPsjrLTQ<5nO9X$iPPmDi?R5_3f- z*T>{OU(0+)Eh-V7av_#JZ?debq)w0ISz70aXmzZP)flf6MT$}#$xUxiX4T6wMQMt1 z(Km0ZR-GJZC$ForB1Kb1(Zq`;L9Q`#U}kc-zxUba8xuy?O4rH!QlXl%M)kR(o922< zwmNB9se1h2{8TbJJXfZ=I;_fMQnySy*I84JF64D%I@MVZ^O|z8Y|M6hW!g=qOu1M! zr7ps>8h>F-#@F%PT0TB5_dY$=5YC=={Zr0fboPp~>pX9~wCwsPo&DVPkH=Hao^bXY zXIEYSL*AVI()HhVc3C?6MacEOvlp1GgbA^$%){9gR+l%mHiEnj&-JixH&Y;SGbt{+ z{t03z?p+g;%KlU0jXnJ;6hm+E zO4d<`2T4o{Hn?Oyg$)#jm)Q^UYaHJCp>S-t$!CBi7ej)}A>Wy>@(p%y@Lc$O&cyp1 zdP#?v^I4GaH+|g|B8k!Ldl%Wfwrg(}`)i>kl#a*D@zz$^*>a1%2AcIZ5x;fu4@Sqm A6951J literal 0 HcmV?d00001 diff --git a/_static/locales/mr/LC_MESSAGES/booktheme.po b/_static/locales/mr/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..64389fac --- /dev/null +++ b/_static/locales/mr/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "स्त्रोत फाइल डाउनलोड करा" + +msgid "suggest edit" +msgstr "संपादन सुचवा" + +msgid "Toggle navigation" +msgstr "नेव्हिगेशन टॉगल करा" + +msgid "open issue" +msgstr "खुला मुद्दा" + +msgid "Download notebook file" +msgstr "नोटबुक फाईल डाउनलोड करा" + +msgid "Theme by the" +msgstr "द्वारा थीम" + +msgid "Print to PDF" +msgstr "पीडीएफवर मुद्रित करा" + +msgid "Download this page" +msgstr "हे पृष्ठ डाउनलोड करा" + +msgid "Copyright" +msgstr "कॉपीराइट" + +msgid "Last updated on" +msgstr "अखेरचे अद्यतनित" + +msgid "Launch" +msgstr "लाँच करा" + +msgid "Open an issue" +msgstr "एक मुद्दा उघडा" + +msgid "Sphinx Book Theme" +msgstr "स्फिंक्स बुक थीम" + +msgid "Edit this page" +msgstr "हे पृष्ठ संपादित करा" + +msgid "next page" +msgstr "पुढील पृष्ठ" + +msgid "Source repository" +msgstr "स्त्रोत भांडार" + +msgid "By" +msgstr "द्वारा" + +msgid "By the" +msgstr "द्वारा" + +msgid "previous page" +msgstr "मागील पान" diff --git a/_static/locales/ms/LC_MESSAGES/booktheme.mo b/_static/locales/ms/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..f02603fa2522a40060bd3f1b5d65052c77530de6 GIT binary patch literal 1213 zcmZXRJ8Km|6vs!6uj@1M0TG1}Eworov@58TBL2_ajS)TU%x`DrywA6>k!K8Y7V9F`8>~xM5BFh% zd;s@@AHhT5C-5lv6+91q2g&v)I0lYF`6PH1JO$nc$*v2Y0Pldu!3W?dC>w4z_m7+N zHb`+^fGzM9NcL|*vVRZ02ETwK;L`&&w?VSo0ms4TAm#b4;b-tP&Og8l;4hH$$Kizh zUTHW1Qhptf^p`=>djwK_>)<(X03HLMfK>lZ^ZpV{}g%EROCaZxzWLzM_G6K*tH6hX%sTdt($LUZL@kZi>& z4I{%>X6M;z?cd7EIOUBUu+=J4dW+9cF1<{ak_~s>uT$@tG%Y08Vne0ED+JMU%h%Z$ zic<%vtlUs0G-K1wUB*6INTU1FI=E=_I%q^eqhYw#(!$c*-uvW@iB{KW zFSU<)gG#o!N7S2DA(WoxaVD&jzH_fPA5HD)S)tvUw9%Z7O`>$#=2Ly;TZ=-c0nKak z(zRBKU_}wl8(X?I*VXXoI=7~I{oA>w`Q;9uyguDx%Y{TQY0E^;V^w*;2yki7=)(TYV{?8_pQ^c*8Iog%4v$iD&q$RjNP literal 0 HcmV?d00001 diff --git a/_static/locales/ms/LC_MESSAGES/booktheme.po b/_static/locales/ms/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..4365ff54 --- /dev/null +++ b/_static/locales/ms/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Muat turun fail sumber" + +msgid "suggest edit" +msgstr "cadangkan edit" + +msgid "Toggle navigation" +msgstr "Togol navigasi" + +msgid "open issue" +msgstr "isu terbuka" + +msgid "Download notebook file" +msgstr "Muat turun fail buku nota" + +msgid "Theme by the" +msgstr "Tema oleh" + +msgid "Print to PDF" +msgstr "Cetak ke PDF" + +msgid "Download this page" +msgstr "Muat turun halaman ini" + +msgid "Copyright" +msgstr "hak cipta" + +msgid "Last updated on" +msgstr "Terakhir dikemas kini pada" + +msgid "Launch" +msgstr "Lancarkan" + +msgid "Open an issue" +msgstr "Buka masalah" + +msgid "Sphinx Book Theme" +msgstr "Tema Buku Sphinx" + +msgid "Edit this page" +msgstr "Edit halaman ini" + +msgid "next page" +msgstr "muka surat seterusnya" + +msgid "Source repository" +msgstr "Repositori sumber" + +msgid "By" +msgstr "Oleh" + +msgid "By the" +msgstr "Oleh" + +msgid "previous page" +msgstr "halaman sebelumnya" diff --git a/_static/locales/nl/LC_MESSAGES/booktheme.mo b/_static/locales/nl/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..e59e7ecb308a7648cd23aa6342a9ad98a61d0009 GIT binary patch literal 1356 zcmZXTJ5Los6vqcag)1TtUj+$cqf)Gju^^CJh(JODkqBZvyL;~La`(<`W@dTSmfC47 z`~-XfW8nv|v9q$Ewb8~-3*-OXUAP1%JNw%?Gxz+@WA4%Tz*~WF19KAdE9MmDt3JFi z2G0qBM-1V00UQPg!3l5(oCL3fx52Am6C4Mhfg>P+S3qC$CCGl>fS1Ad;4pXyj)5O) zey;7`>h*V!^?rj5u)n|h{RqhGNs#^A0Y8F|zya_lcoF;svhE*{ng4G|2HU zfE@n|kmKI2*9Rc$zXmzZceVWx9L4%m%`YJ5bp-OcA0YetTieIZSNl^S#~pwZ;4H`` z=N$Mv$HI25E$f~haMji1Jb17l9<0YPv;H+qxD=N#xwoeW*MWP;bwN40{S^!Qc%)BB zJTcmn_6{G#zRi--xzS!`5#mI~uCZ|uI< zDAG*t$pwyWGo=oR?puacPMao4a*|r@WQp<_L^SRBDmueDl}KS}Co^Ro_9^$SOcFwr zgiH{M*`~+`D{-(z*1_AHtn>rc54y^YwUxD{-u}$J2aUS0!RCHJbJ8P#`$euYJujnF zSx3J4d~-RN?VYnqyB67CNk=BmbTTJr!^}5Ul}<|3bx!KMv7VP!<-xMC9S1|vUApGO zd0Bln?`nCgDQBkV8|as@-IqkwS9EI1Sg6udX`Q7gMb~>RJ??afw3Uu~8!34iTBHBl zi0Od1qM24Aq+POY$n;EGCeKm6M7k&?+d-F=M@18=IxkHDla2^|PO9GX1u3ivbE1xT z+=^}4Zo{ONva*On--8-OUjI=r94V1Y}`N=IHv19Ut jbWAeLReX?b<52fDoT%;?`~gm~I(s23S;SN2irW1H>^?=m literal 0 HcmV?d00001 diff --git a/_static/locales/nl/LC_MESSAGES/booktheme.po b/_static/locales/nl/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..f7b18e5d --- /dev/null +++ b/_static/locales/nl/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Download het bronbestand" + +msgid "suggest edit" +msgstr "suggereren bewerken" + +msgid "Toggle navigation" +msgstr "Schakel navigatie" + +msgid "open issue" +msgstr "open probleem" + +msgid "Download notebook file" +msgstr "Download notebookbestand" + +msgid "repository" +msgstr "repository" + +msgid "Theme by the" +msgstr "Thema door de" + +msgid "Print to PDF" +msgstr "Afdrukken naar pdf" + +msgid "Download this page" +msgstr "Download deze pagina" + +msgid "Copyright" +msgstr "auteursrechten" + +msgid "Last updated on" +msgstr "Laatst geupdate op" + +msgid "Launch" +msgstr "Lancering" + +msgid "Open an issue" +msgstr "Open een probleem" + +msgid "Fullscreen mode" +msgstr "Volledig scherm" + +msgid "Sphinx Book Theme" +msgstr "Sphinx-boekthema" + +msgid "Contents" +msgstr "Inhoud" + +msgid "Edit this page" +msgstr "bewerk deze pagina" + +msgid "next page" +msgstr "volgende bladzijde" + +msgid "Source repository" +msgstr "Bronopslagplaats" + +msgid "By" +msgstr "Door" + +msgid "By the" +msgstr "Door de" + +msgid "previous page" +msgstr "vorige pagina" diff --git a/_static/locales/no/LC_MESSAGES/booktheme.mo b/_static/locales/no/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..6cd15c88de675226c00ca4d0430171075e5559ff GIT binary patch literal 1317 zcmZ9KJ#5r46vxeXdz6pzxm3a|d<+2!3{|TeDD*@{E2`eX#NxZWChjG6WIIQ@F#r=I zh=CaiW+cQ+7sSlefekSsA;E&g!2exRwZe-1i=UnMe;@gJZ0`$!aT;?1^9$w~%xAl> zV2tb*0*@HQvL74+N5JFYC^!M00?&abz$SPMTm}z=1ReoH&Bq}7c@7=|Ux8!bTW}nF zU-MIK->moFLDu^NHo!f5s_zejyq^Hs&w20zcpb!5@dLyoequQQ{ss?%e?g9WWG`|7 z&ww2NwR(RWJc|7Tkn_pGec+?o{vnrOx2I^Ydmn%A>ZL_zf>(PJ4kZLarm5`W=b%5)w zZL7>O-*ZGp<~Am=pnQ;J5vxG4v+R9LTr zb?c&Cq}r^>S&prfQchyH%5IfY$0kWe(x`z>RL~GHv=*x9EbCMvg`Y>jh2AfB-HRnbKxP z_EP0Mh336ZE1KHA=alg)i!%*zV<7HREar_#Z59h#6sa0`M0_gBf~5&B$u(bn(=RqnJ4d{?xCazSi7Dd36F5NEp? z<)YnpdLTAmS7{(1PP{Mcl94asi9}+1PF;uA{A!sWqQCgLP1e#J@rEvuCjIeG)u_ z_zHL&oC3+mBarlB@FchjQl1we?OzAU{{~3=--1+!&*l7gkoNrokAjC_hW4EWNq-dF z2i^p!UUxt$Ipw67YDs=blg_=fL9(w&^`%C>sF5z^AYYUllKnH&-R^8uf4W1;k81~m7!h)9ylfZ~^CgwY?O|s!8_53#eN#D}ib%4l zPdl`G0* zrR^Q^E{h@wml7v|6|*b@U!4i752bZbtMMX#mGW2nnJcq1vs2siW24t9Wnrs}c`9q% z!@$)v5lT<+ped}AzW!iwx;nnS&I;|8q^(Zrz=TRiH9p=@zH(RSC_`OqJWVR|NoGY- zoi?`RYFwxN(ABR`V3KC)moz_L=VO;ADlp!Wow9!{+QNF%d)$vmWXUlwR2&%HTrgJW19E;7l zzACcDJ`;)Rh+tW;2Q~|urlsI%&bL2qk_T%ViEOb+o5j!ziwCfPoA2cCtFji~wj$ZA z@p+raPIaI5KE$fLmvXo`p>N|Ts6=nA`!wj_O|+>xW d^Crc{P^+yKEfI-Mu31OGXlgVp$}sP%{Q=l!SrY&N literal 0 HcmV?d00001 diff --git a/_static/locales/pl/LC_MESSAGES/booktheme.po b/_static/locales/pl/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..dfba3f69 --- /dev/null +++ b/_static/locales/pl/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Pobierz plik źródłowy" + +msgid "suggest edit" +msgstr "zaproponuj edycję" + +msgid "Toggle navigation" +msgstr "Przełącz nawigację" + +msgid "open issue" +msgstr "otwarty problem" + +msgid "Download notebook file" +msgstr "Pobierz plik notatnika" + +msgid "repository" +msgstr "magazyn" + +msgid "Theme by the" +msgstr "Motyw autorstwa" + +msgid "Print to PDF" +msgstr "Drukuj do PDF" + +msgid "Download this page" +msgstr "Pobierz tę stronę" + +msgid "Copyright" +msgstr "prawa autorskie" + +msgid "Last updated on" +msgstr "Ostatnia aktualizacja" + +msgid "Launch" +msgstr "Uruchomić" + +msgid "Open an issue" +msgstr "Otwórz problem" + +msgid "Fullscreen mode" +msgstr "Pełny ekran" + +msgid "Sphinx Book Theme" +msgstr "Motyw książki Sphinx" + +msgid "Contents" +msgstr "Zawartość" + +msgid "Edit this page" +msgstr "Edytuj tę strone" + +msgid "next page" +msgstr "Następna strona" + +msgid "Source repository" +msgstr "Repozytorium źródłowe" + +msgid "By" +msgstr "Przez" + +msgid "By the" +msgstr "Przez" + +msgid "previous page" +msgstr "Poprzednia strona" diff --git a/_static/locales/pt/LC_MESSAGES/booktheme.mo b/_static/locales/pt/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..d0ddb8728e1d5ef72dddc1537f66aa32251a83c8 GIT binary patch literal 1364 zcmZ9KJ!lj`6vsyszs~RYi3A)AKVkhsL@peXm>dKW4Dqy|yM5Uk-JMxyXV09qrC4bb zE3pu<6hyS##>&dd!p6cz!N$T$|8I9gLWZ0D-MpQB@BjWY-^NCt35+9{h16S(zZ$SR;BglC^gY3_DkUjkg^8V2+RlY+YuTO%k z_iDYq0kY*B<9wX!0496Oy4Me+EOW5GJh*=z>>q1pUk_m-WvQ8UtRL(@Yuttj8%m$V z)DS=E`y_5yrAF9A~6$c zkJPKnb{@xB&k-4!*pS4W%Dl|ePxSZ1+Sg`TPO-L5pAr(~Q+BJKIyQ=8l12@5q`XEEL(9HWXSq&QBy}{>iJ+c4DOK2kgX}J`T^Gu%F2!T+4-5Z_m|FJY}CdEoncB%=^@}k z8Y^ukWUsGWM!t2s(+;k!?Q_axOXPwX)3c#AQBz*)YTuYsCd%P!Q>MPL5a&+CLEE|{ zYf6)r%dB;ILRNoUXN)}2l9$d-G{iJ)q}Wy`Tzm+v2(=>^C{+#@RV=2IURF*jcR$wy zD??aTpZLaCOMFYpAW1l*WLmt4v{B_@b0}L2&D+qT-&mnh(n=I7vDb-`%I7N94^{E1 zcxfdiIC)dNQVDLK6_Z`3WS+>>*=|gU60=F_bfO(LmX~0$I{o6U(^gh;I@l*sE7k*N z>oXB$Fttuh#-5x(d)$^9P*fEbsVm+tv!2x!?&s);C8;hsuS6ZkWkdpvO!dtuOAFi$ LL?J8GWh3H0!r)O_ literal 0 HcmV?d00001 diff --git a/_static/locales/pt/LC_MESSAGES/booktheme.po b/_static/locales/pt/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..4c24eb9e --- /dev/null +++ b/_static/locales/pt/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Baixar arquivo fonte" + +msgid "suggest edit" +msgstr "sugerir edição" + +msgid "Toggle navigation" +msgstr "Alternar de navegação" + +msgid "open issue" +msgstr "questão aberta" + +msgid "Download notebook file" +msgstr "Baixar arquivo de notebook" + +msgid "repository" +msgstr "repositório" + +msgid "Theme by the" +msgstr "Tema por" + +msgid "Print to PDF" +msgstr "Imprimir em PDF" + +msgid "Download this page" +msgstr "Baixe esta página" + +msgid "Copyright" +msgstr "direito autoral" + +msgid "Last updated on" +msgstr "Última atualização em" + +msgid "Launch" +msgstr "Lançamento" + +msgid "Open an issue" +msgstr "Abra um problema" + +msgid "Fullscreen mode" +msgstr "Modo tela cheia" + +msgid "Sphinx Book Theme" +msgstr "Tema do livro Sphinx" + +msgid "Contents" +msgstr "Conteúdo" + +msgid "Edit this page" +msgstr "Edite essa página" + +msgid "next page" +msgstr "próxima página" + +msgid "Source repository" +msgstr "Repositório fonte" + +msgid "By" +msgstr "De" + +msgid "By the" +msgstr "Pelo" + +msgid "previous page" +msgstr "página anterior" diff --git a/_static/locales/ro/LC_MESSAGES/booktheme.mo b/_static/locales/ro/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..3c36ab1df7c589ad82614599b8c91f072a25d4a6 GIT binary patch literal 1390 zcmZ{jxo;Ce6vhX_5zG}5ZUr$kT#~s&fgHI>97~Z1L||yB#=9@;f%VL44!~(cNeM!T zzkmW7Bt%b&NVHTGv{Xn`NHmD=truc}813$F=kWX9`}X8CsJNO-Bou44rIk82E zW8ekwD0mG#0%~vyTm=t+&p?jz3S_U|fL!MXkn8*mPJmxQ*7*st&Nlprc^KsLXDc>A z&U>kv-vQZju7S_7m#oj;a^0f?p-U~+<-u`yunv38zH-h8DR$!Kd`AcS&)<;qgbk%n zVs?N_h8~GIYXX_z@lp(&&U!(#>;scql}cj+b*;T8mvv4X%iczp&|iz8r@bsxMq)nI z0il0S+cD35;)smw+mysr<%5hxssg3b8qA|fdg6M41IkG4eI&8uv_TLnms)LcbExO2 zuwDo22I6MX)8?U^<=i?w>XRs+vOBD)W3wzLY1Dn4sh}ZZ=wTRUXIW<`QaHM=ZLHEB z3GZW;5wavyf>i8XN#8^5U79nrN}tCR1WA7O>Nc7D^1!X_=B#5k}&OPu5mlqSjw% ze9!ggnq18PeE0wD`{?}IYPqW%0!Wn*zA9eO0NP-Sd!P*Z&(5Mvp+E_$mG57h;3yNf z@}T<)Q9@L?UQv!@t~hzGN|ByUi8HjaaJHLM9|{Y76xA;^5T@*t78+y)y;r5zA;cW% z6j3gq1Ltf%1{N7Mh$B&^tz>kF94xj(C8Xe$PteOytPUysU!2AvEWuE6Fj7Z>o*_qS K1txIYaExD}s9q8P literal 0 HcmV?d00001 diff --git a/_static/locales/ro/LC_MESSAGES/booktheme.po b/_static/locales/ro/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..5f03d9cd --- /dev/null +++ b/_static/locales/ro/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Descărcați fișierul sursă" + +msgid "suggest edit" +msgstr "sugerează editare" + +msgid "Toggle navigation" +msgstr "Comutare navigare" + +msgid "open issue" +msgstr "problema deschisă" + +msgid "Download notebook file" +msgstr "Descărcați fișierul notebook" + +msgid "repository" +msgstr "repertoriu" + +msgid "Theme by the" +msgstr "Tema de" + +msgid "Print to PDF" +msgstr "Imprimați în PDF" + +msgid "Download this page" +msgstr "Descarcă această pagină" + +msgid "Copyright" +msgstr "Drepturi de autor" + +msgid "Last updated on" +msgstr "Ultima actualizare la" + +msgid "Launch" +msgstr "Lansa" + +msgid "Open an issue" +msgstr "Deschideți o problemă" + +msgid "Fullscreen mode" +msgstr "Modul ecran întreg" + +msgid "Sphinx Book Theme" +msgstr "Tema Sphinx Book" + +msgid "Contents" +msgstr "Cuprins" + +msgid "Edit this page" +msgstr "Editați această pagină" + +msgid "next page" +msgstr "pagina următoare" + +msgid "Source repository" +msgstr "Depozit sursă" + +msgid "By" +msgstr "De" + +msgid "By the" +msgstr "Langa" + +msgid "previous page" +msgstr "pagina anterioară" diff --git a/_static/locales/ru/LC_MESSAGES/booktheme.mo b/_static/locales/ru/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..6b8ca41f36ebf869818399a9584cdb15619bea78 GIT binary patch literal 1722 zcmZ{iPiz!b9LJx6N>>C0{~WCHj6uL;MNkv6buUP3NFY{Oy-#-^yQABg$;>R!8?=By zpk6eZkcjo>ZEd^jw#)9`jK?>LiHQeq#*-Is-2D7zrnWZnvTr^!zxmDY_x*j}{=RSL zmx}cqdz}3X`vCjaLtI$99#)E<8sqXP+zofZ{csG9!)M_u@M&0v```y~4>WKujB{Rv zQs)c!1iS-x!|&l!u$%MeJpNn${3n!t_hA9<*pYp|2g>s}lsboC555U^!oQ&C`x}bB zF@i6^7vWp*ZFm@l@KtyR9)~}{gYZ5)1P?rt)qfX0&vOMzodC-FMW|sH%3Qy~Bk&LS zGTh71lK%!g2;Ya|(?xg`eg?&InL*;Bbw69Q%iLQRlGKxI@mH42FH8IruciMpY+9?w z*>bj97p>AWd<Owguyc8|lEQ8#P&TV@hv4PPLlNs2UpM=~=&K)EOs=bt|Yjv8id_3$EYFWp61Twd!?)O2Z^b@jo`zxOlo&{K$k6 z)k-?+UzGmEv~%I?>9doY?~lFqdLcKqSeXk!s4V?^=qzIFXM1NyDcB~ z^h;%Z?8rnx*}Ha_UXm-xW!tfr6}wJC zN81q@gr(9Fv3Bw)dp^0PldHtnY+u_Sxf$6W-wgO>O_L_|y0EwXD@jYPrM(BqO_Ddt zDEk#lk9`p%b*uDr%Zu6PU zG_bh>@urJlTp^1w`f2$AR}2{1AJVy&({OH-XdNXBVw1Appn{Ug&D59FU~!E~qO?uY z2%}Tqa+P*D{a@R!x0@kSMzqWv;2@B-rtEiw@7eZ-vn#fz?Gn!QP_`~@{!JJr^D>2; zYX|@P$s&z$lLI4H4zg!gP;s5$q8v^-E0ZiHHwb^e&1~CN%&|G1oY;Q{yqk7fcCfJk literal 0 HcmV?d00001 diff --git a/_static/locales/ru/LC_MESSAGES/booktheme.po b/_static/locales/ru/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..2886570d --- /dev/null +++ b/_static/locales/ru/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Скачать исходный файл" + +msgid "suggest edit" +msgstr "предложить редактировать" + +msgid "Toggle navigation" +msgstr "Переключить навигацию" + +msgid "open issue" +msgstr "открытый вопрос" + +msgid "Download notebook file" +msgstr "Скачать файл записной книжки" + +msgid "repository" +msgstr "хранилище" + +msgid "Theme by the" +msgstr "Тема от" + +msgid "Print to PDF" +msgstr "Распечатать в PDF" + +msgid "Download this page" +msgstr "Загрузите эту страницу" + +msgid "Copyright" +msgstr "авторское право" + +msgid "Last updated on" +msgstr "Последнее обновление" + +msgid "Launch" +msgstr "Запуск" + +msgid "Open an issue" +msgstr "Открыть вопрос" + +msgid "Fullscreen mode" +msgstr "Полноэкранный режим" + +msgid "Sphinx Book Theme" +msgstr "Тема книги Сфинкс" + +msgid "Contents" +msgstr "Содержание" + +msgid "Edit this page" +msgstr "Редактировать эту страницу" + +msgid "next page" +msgstr "Следующая страница" + +msgid "Source repository" +msgstr "Исходный репозиторий" + +msgid "By" +msgstr "По" + +msgid "By the" +msgstr "Посредством" + +msgid "previous page" +msgstr "Предыдущая страница" diff --git a/_static/locales/sk/LC_MESSAGES/booktheme.mo b/_static/locales/sk/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..59bd0ddfa341477cf5ccfdc88f4c3e6127046f7a GIT binary patch literal 1393 zcmZ9KKWrRD6vijSKyrit=ARHoJeoj?1A-``v#uc6mLesxmAg<-Am(Iw==v>7a08THd<;rm`=IpY4k&eh2g>u`gW~ryD0Tk|O5J~fa_(Nc zzXDUK|0PiBy9|o{Iw-jZpgi{xC@mLFS&OFRlMGV#=>h3w2I;R1(UBqg;w6239ut!4 z2~6=jJ)|#^@o`MFWBGp7wHbaCb5`#=8`;KyKjqAuERSl#ePRozQ?f4d$hk4?nu1TZ zgR6YP4{gTW1S)mLYBMzv(*G~Fs-g&qXSOtPDXSYgM5@YEM^4FEtSg)3YP-Y%ZOMdC zvD)#*Ld4O|#+Dj1ex6GgOmu#x24!ySK3$V+!<;9qmRA}zH4R;s6--u7O{SxPiRJy+ zq;ulan3SHU##L?XQ}Ut8GDb>9C5YnoIEmfsY4-#60ct&J{JY}cT{?GeUcb3{a{tPk zZ+F_pc89Z)dlV7it+LR@u2Yh0A2{}J54XBkPtJL5!!G;orcGRGY}TWzBNIC}w9P8? zwMSvx*(oZoi|&^5lh7kuE|;PI&N?-J`)^o!txs1juXogY6?)ZEJ1#xCtJU@>=)Bnr zU1l0t--9arjh>CyA! zZ|R}^TYP-iOeo=k_sEUBK5*0V4ADZtsjcUv$Fb6dIjHA}(Ucy4hGb%cXdqT-thpkjw8w z94mEnM;EAFODWoF<;0UM`ZS%T+8S2)Skfe~=jnmos~5@rll9m4U7_dmM!H@|Co1(H Di}h+h literal 0 HcmV?d00001 diff --git a/_static/locales/sk/LC_MESSAGES/booktheme.po b/_static/locales/sk/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..25517aa5 --- /dev/null +++ b/_static/locales/sk/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Stiahnite si zdrojový súbor" + +msgid "suggest edit" +msgstr "navrhnúť úpravu" + +msgid "Toggle navigation" +msgstr "Prepnúť navigáciu" + +msgid "open issue" +msgstr "otvorené vydanie" + +msgid "Download notebook file" +msgstr "Stiahnite si zošit" + +msgid "repository" +msgstr "Úložisko" + +msgid "Theme by the" +msgstr "Téma od" + +msgid "Print to PDF" +msgstr "Tlač do PDF" + +msgid "Download this page" +msgstr "Stiahnite si túto stránku" + +msgid "Copyright" +msgstr "Autorské práva" + +msgid "Last updated on" +msgstr "Posledná aktualizácia dňa" + +msgid "Launch" +msgstr "Spustiť" + +msgid "Open an issue" +msgstr "Otvorte problém" + +msgid "Fullscreen mode" +msgstr "Režim celej obrazovky" + +msgid "Sphinx Book Theme" +msgstr "Téma knihy Sfinga" + +msgid "Contents" +msgstr "Obsah" + +msgid "Edit this page" +msgstr "Upraviť túto stránku" + +msgid "next page" +msgstr "ďalšia strana" + +msgid "Source repository" +msgstr "Zdrojové úložisko" + +msgid "By" +msgstr "Autor:" + +msgid "By the" +msgstr "Podľa" + +msgid "previous page" +msgstr "predchádzajúca strana" diff --git a/_static/locales/sl/LC_MESSAGES/booktheme.mo b/_static/locales/sl/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..87bf26de683cb18c73bd23c2b4c57ef6a02545ec GIT binary patch literal 1374 zcmZ9KyKfXR5XQ}$9PjWFC=#aOAvj*5h%UN@MVlwf1j4YtMW$vtK7Sz7QA(F{dy;VIIMJx(*A* z*7ZW*5ffN8gWJKa;9hV7oB|Jk$H0AH8=M61fIC3~cY(3y6OjEp2X}z4!0q5`a1Z#l z=EvIprQUx7Io@xu0dCk(-QNlFehOqi$H8~tMQ{`NqvlU=3--Uk-Qc>7LL34o!NcHb zkab@J`TGNq^T|Ly_ZVc|FG1Eh0$KkXa4+~CYpSj^k88a!&*8idy!V z`%t7QK_wv*NO67Y#^!v|yiY#BTT52)n;gGcMsD1kzd5`1{rs78jk>VS#g&{|GD5)F z+$e2lWVfe$pxC~*IM2jgT5~@lP4MDpz zCx-(XW@_w<9uAzh?%#>APv}sH5H9X{E*5diD#H~rZm5EBHe?#D`0z|yaZ3$VV*3d1 zf=gV-^ojji64%jMWljW5^x#&@4 literal 0 HcmV?d00001 diff --git a/_static/locales/sl/LC_MESSAGES/booktheme.po b/_static/locales/sl/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..346c3648 --- /dev/null +++ b/_static/locales/sl/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Prenesite izvorno datoteko" + +msgid "suggest edit" +msgstr "predlagajte urejanje" + +msgid "Toggle navigation" +msgstr "Preklopi navigacijo" + +msgid "open issue" +msgstr "odprto vprašanje" + +msgid "Download notebook file" +msgstr "Prenesite datoteko zvezka" + +msgid "repository" +msgstr "odlagališče" + +msgid "Theme by the" +msgstr "Tema avtorja" + +msgid "Print to PDF" +msgstr "Natisni v PDF" + +msgid "Download this page" +msgstr "Prenesite to stran" + +msgid "Copyright" +msgstr "avtorske pravice" + +msgid "Last updated on" +msgstr "Nazadnje posodobljeno dne" + +msgid "Launch" +msgstr "Kosilo" + +msgid "Open an issue" +msgstr "Odprite številko" + +msgid "Fullscreen mode" +msgstr "Celozaslonski način" + +msgid "Sphinx Book Theme" +msgstr "Tema knjige Sphinx" + +msgid "Contents" +msgstr "Vsebina" + +msgid "Edit this page" +msgstr "Uredite to stran" + +msgid "next page" +msgstr "Naslednja stran" + +msgid "Source repository" +msgstr "Izvorno skladišče" + +msgid "By" +msgstr "Avtor" + +msgid "By the" +msgstr "Avtor" + +msgid "previous page" +msgstr "Prejšnja stran" diff --git a/_static/locales/sr/LC_MESSAGES/booktheme.mo b/_static/locales/sr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..ec740f4852f3973fa72ed0c7f7cf59273b8dba41 GIT binary patch literal 1679 zcmZ{i&2Jk;7>5TMpf#n12FigTrXZCM$qB70R5|j2(nPA%iiifpt=iZVd#SU#+K*9wix4UV%CCk|YD;tzleJn!xzyAg~$`^-$R zf|BP7d;(sF`{57pDcCFcOL6{NvA++c-k-1p_w32;FeHVeLgQ7^hJ zGdzy`B&?ZThjG)5bl^0MnyI@nssG*1CaqRf3ytygl3zFKtP{mL3F=O4>e~0%Ctj_o z-VO+GJncqNV$@vddL;4n-04|$KCc&=z>nP650};Xpy_&-^(oOd-!w}`WnaCJdz$wf zjh4}#bIENuu}cxpT#j>fzSPN!1fjX)`bi;sBz=@L8U~dHCrI%>FtxaRre1!}gb~>) zID-xfGsC|hn|!@gG`2jy9GHrZ5ik|B9M_xHwWbqBCa%6aKU+RIj0+tv zS~OvK#;f^t*K1Vt$ptqqoproMLSHL73QKdXBy?KkSwCEgD%uOOZB#uzt@CB|6;B_j z>SM1?mz2F>J33uW*U}Z+wmY_)ohZA>uESZ+w$lw|zev~9H9JUG(p9@{2io4t;AJmR@7g|5U2Qwul5jS5J6+fI7K$b?*B^Gym(vvm#N%kCu@EWomq3c>6awm HD*E*gL}ZXP literal 0 HcmV?d00001 diff --git a/_static/locales/sr/LC_MESSAGES/booktheme.po b/_static/locales/sr/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..b1a97ada --- /dev/null +++ b/_static/locales/sr/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Преузми изворну датотеку" + +msgid "suggest edit" +msgstr "предложи уређивање" + +msgid "Toggle navigation" +msgstr "Укључи / искључи навигацију" + +msgid "open issue" +msgstr "отворено издање" + +msgid "Download notebook file" +msgstr "Преузмите датотеку бележнице" + +msgid "repository" +msgstr "спремиште" + +msgid "Theme by the" +msgstr "Тхеме би" + +msgid "Print to PDF" +msgstr "Испис у ПДФ" + +msgid "Download this page" +msgstr "Преузмите ову страницу" + +msgid "Copyright" +msgstr "Ауторско право" + +msgid "Last updated on" +msgstr "Последње ажурирање" + +msgid "Launch" +msgstr "Лансирање" + +msgid "Open an issue" +msgstr "Отворите издање" + +msgid "Fullscreen mode" +msgstr "Режим целог екрана" + +msgid "Sphinx Book Theme" +msgstr "Тема књиге Спхинк" + +msgid "Contents" +msgstr "Садржај" + +msgid "Edit this page" +msgstr "Уредите ову страницу" + +msgid "next page" +msgstr "Следећа страна" + +msgid "Source repository" +msgstr "Изворно спремиште" + +msgid "By" +msgstr "Од стране" + +msgid "By the" +msgstr "Од" + +msgid "previous page" +msgstr "Претходна страница" diff --git a/_static/locales/sv/LC_MESSAGES/booktheme.mo b/_static/locales/sv/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..b07dc76ff21128244172d2e415cc899555d8b49d GIT binary patch literal 1365 zcmZ9Ky>App7{XZ}|d=zQVMY>d0>TJUwK!GS|siLHd(&c$~H~3(*Gryg$_j%@>d3o;WBZ2ZE>JsWR z)Jv%M7to-bct;3);v|}P!BgM~@H}`DTmmnGm%$If0eB9)11^FDo&i(GpFxiE5Ihb3 z0-geY1>Xk`IzH{jUv&LfAnW}L_P`@Y+Wm_l_m@D9a|Qez{0hWU@h8Z7e}laLACT8A z9Bq9sg6#KG@FQ>;^|ue&MB7Xc{&_$WV4fmrpPUX_NMBC1d<&HLVI2>ISM)cNT zDs_}z6(rVjoe=u}?s{cR90ejPCoU&(OT{EBpQ}W+2Kkatlh7xu)KFSXs3tL$x9(u73Q%I)?{Lst}rq*YU0sH7ocX*ad*9P6|q zKG0OVs2vT8zb&|U%F`w^(-Z1 zKF^i36kcC+hKrsX9@jHt-W)0~UWJ0RHRwJIJFG|WNq7Z50sn;0!@U&o7(5PV;9F4M{{RobKj41& z@a;;?!xtbeX@>OX{(5y6M3y47A9wJS8l@l7I~meb8I-3U@UzelnM(bH_d|LjeI~u4 zB&Ck5^3z4%s2P{8W=Y&H)T}#g2QKPq>k6~t+?)DDGB7*axf^C(bKPdqPja0`u~Boq zq#)vWxe(=r9;UshFg@+8T8M_W+gC58#_GuGB+rLNEoOcl%M6n_~Kv<@xsE9lI>D`3aM?=WN&Y5*v5);gzIlEkrgR(mY~Bt;NAGiw5m^ zmz~Tz+NOS)Pd_uI!*qJT)%&LPp{J%=sw%gu@~f)+wA%QnDo0iMT~%)Q%}sWAT~-@s zt8&XvWPPzJFLmFFj3kCLZVZKXbJg6qObpgpYXhKc{dPQvXD4*l1`&-oR|ZVWnD5S zLMPGk+4yL_MW)wWJ7GI+sWh)Cq}dE7ao%TGqX8uPK%$P%oUIVNaozG6uhIA~XTs-( z77E8j3VKIkNhd=@QrBItuMs9x^kr3kK4HautE;{2cexG}GQN=#P4;o6q{&7}8xZ++ zl w$ZZQ&WaeX;?9mtGBq&}escqTfGyJc(*W8(47(T)#0?{xcP9tpFr||Or2L57y?*IS* literal 0 HcmV?d00001 diff --git a/_static/locales/ta/LC_MESSAGES/booktheme.po b/_static/locales/ta/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..116d7433 --- /dev/null +++ b/_static/locales/ta/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "மூல கோப்பைப் பதிவிறக்குக" + +msgid "suggest edit" +msgstr "திருத்த பரிந்துரைக்கவும்" + +msgid "Toggle navigation" +msgstr "வழிசெலுத்தலை நிலைமாற்று" + +msgid "open issue" +msgstr "திறந்த பிரச்சினை" + +msgid "Download notebook file" +msgstr "நோட்புக் கோப்பைப் பதிவிறக்கவும்" + +msgid "Theme by the" +msgstr "வழங்கிய தீம்" + +msgid "Print to PDF" +msgstr "PDF இல் அச்சிடுக" + +msgid "Download this page" +msgstr "இந்தப் பக்கத்தைப் பதிவிறக்கவும்" + +msgid "Copyright" +msgstr "பதிப்புரிமை" + +msgid "Last updated on" +msgstr "கடைசியாக புதுப்பிக்கப்பட்டது" + +msgid "Launch" +msgstr "தொடங்க" + +msgid "Open an issue" +msgstr "சிக்கலைத் திறக்கவும்" + +msgid "Sphinx Book Theme" +msgstr "ஸ்பிங்க்ஸ் புத்தக தீம்" + +msgid "Edit this page" +msgstr "இந்தப் பக்கத்தைத் திருத்தவும்" + +msgid "next page" +msgstr "அடுத்த பக்கம்" + +msgid "Source repository" +msgstr "மூல களஞ்சியம்" + +msgid "By" +msgstr "வழங்கியவர்" + +msgid "By the" +msgstr "மூலம்" + +msgid "previous page" +msgstr "முந்தைய பக்கம்" diff --git a/_static/locales/te/LC_MESSAGES/booktheme.mo b/_static/locales/te/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..0a5f4b46adfda1551ae6791c3c3782525b61be04 GIT binary patch literal 1806 zcmbu8?`s@I7{^DgzpiR+74e1QD2kPOYU&G1LO_}((2{DPsaEjK=5D&TdYxHz_mbva zT2L$M3z1kXg(AcfwAS4~Neb5f0lujqQV?VieD5FN3qLcn=UrpK7cRH^*?DH3U*CQ1 zw_V$o1=qvek8yv`{W$mAxAEY*0dI#t!Motk@Lu>Ud<6aho$p_87u?C=2jJ6i2YeYi zzX^ChJOuB9$KXz=YA)3F59{^k(B)Z$4Y&rK|263Re}o(GCUki}y(4f1KFWF>z6o!@ z*Wm7LLQKL1xEEf7ufjj!vvA~2A@;zx;Pdc3_zYZw?)**o1l&$Dhu|Lg6r6|7{snaU zU4^f}Um%kFbGaHHtXJD1WeGz1>mHu2N2iC=&RtGZchR1B$iD?W+^g&V?%L)waXOPu z(25ZI7x~Geqr`+s7qcYp6yktc&|MR?r8b3{Gv-}+Jn5=|IXAtmr8XIhPLj(sij|mb zCj}Av%jqaDWG`(;g=$Nq#dOrut&Vs-Ra!<`CVAddVkS#8PDaigm=Z@q{7j`LPYRPQ ziX&+!(I@48SIcZiolwF*xU=VM^?@zFv*l@L zDz6jwvaMLG-4f{crQm*REN}ghN#a8coKPu>p z%YTFt$m|qAXTDh&g5gT~hljsJ*ry=A+<9Nb1sA(o5-xGw{Z;?6OlS@gI#jemLQG%z zrpf6>XY=H3-bW;Qrf>v2>%ZN4n4aM|U<|2-ZBn^mBghuhM0)Dv2+@ei()B(V2&(za uuMrF7ToguSy%w`N&3+IHSt#2LVBfiP)B5iT;9Jx)h5&elIS4O(ZT|-CPABOA literal 0 HcmV?d00001 diff --git a/_static/locales/te/LC_MESSAGES/booktheme.po b/_static/locales/te/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..635bdf96 --- /dev/null +++ b/_static/locales/te/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "మూల ఫైల్‌ను డౌన్‌లోడ్ చేయండి" + +msgid "suggest edit" +msgstr "సవరించమని సూచించండి" + +msgid "Toggle navigation" +msgstr "నావిగేషన్‌ను టోగుల్ చేయండి" + +msgid "open issue" +msgstr "ఓపెన్ ఇష్యూ" + +msgid "Download notebook file" +msgstr "నోట్బుక్ ఫైల్ను డౌన్లోడ్ చేయండి" + +msgid "Theme by the" +msgstr "ద్వారా థీమ్" + +msgid "Print to PDF" +msgstr "PDF కి ముద్రించండి" + +msgid "Download this page" +msgstr "ఈ పేజీని డౌన్‌లోడ్ చేయండి" + +msgid "Copyright" +msgstr "కాపీరైట్" + +msgid "Last updated on" +msgstr "చివరిగా నవీకరించబడింది" + +msgid "Launch" +msgstr "ప్రారంభించండి" + +msgid "Open an issue" +msgstr "సమస్యను తెరవండి" + +msgid "Sphinx Book Theme" +msgstr "సింహిక పుస్తక థీమ్" + +msgid "Edit this page" +msgstr "ఈ పేజీని సవరించండి" + +msgid "next page" +msgstr "తరువాతి పేజీ" + +msgid "Source repository" +msgstr "మూల రిపోజిటరీ" + +msgid "By" +msgstr "ద్వారా" + +msgid "By the" +msgstr "ద్వారా" + +msgid "previous page" +msgstr "ముందు పేజి" diff --git a/_static/locales/tg/LC_MESSAGES/booktheme.mo b/_static/locales/tg/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..b21c6c6340194fdf35f7e5660deb42479c8dbff9 GIT binary patch literal 1628 zcmaiyO^6gn6vxZY=tNE8S5Q|hA#9RE$8XSGCI@vF1jR*HLCB?drtIlBTh(+|t9#pZ z_b^Dr#19Y@K@`-J?Yg?{x;qOwd8{6D@{o&%oP^*d#K?f}Wpw_pnH1Q&v@ z3%&tK*FWF}u!PNBU}wRfz%8&Zfe!dP_zn0sxE@@yD9?KJ9kAteKMU^WF zJC>CiI~?GEE4d#GJ20M-!R?)~ z>>S<1-6l7a<}oHySZKVs&CQhc{Mbyqb88w7X3RqzI{&F#*USvhMoiLrM6s>Hk4E|6 zc@o%qM9F2t?V4KSrinZf?58}t0JXzb84{b#Mr}$-{y{=+V#Xn)X(lNzTPtR6wl32O zGdJL5Bs-5oxB+T`zIGRrAt`^lPLZT?M?g!0angPB{%GR5vxHp0oR8Arqi zbZiRp&%w__8!lf*NbDpe;WA2%r?Xi$atSF8VXr;q_FB@_W_A(5kPfr&0p+;^8?eY= pg1vVOUqyoB&tBYSn9xh&7BjPW`v%MukJU629MMs5Ow+8v{s(GpYQg{j literal 0 HcmV?d00001 diff --git a/_static/locales/tg/LC_MESSAGES/booktheme.po b/_static/locales/tg/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..a92c069a --- /dev/null +++ b/_static/locales/tg/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Файли манбаъро зеркашӣ кунед" + +msgid "suggest edit" +msgstr "пешниҳод вироиш" + +msgid "Toggle navigation" +msgstr "Гузаришро иваз кунед" + +msgid "open issue" +msgstr "барориши кушод" + +msgid "Download notebook file" +msgstr "Файли дафтарро зеркашӣ кунед" + +msgid "repository" +msgstr "анбор" + +msgid "Theme by the" +msgstr "Мавзӯъи аз" + +msgid "Print to PDF" +msgstr "Чоп ба PDF" + +msgid "Download this page" +msgstr "Ин саҳифаро зеркашӣ кунед" + +msgid "Copyright" +msgstr "Ҳуқуқи муаллиф" + +msgid "Last updated on" +msgstr "Last навсозӣ дар" + +msgid "Launch" +msgstr "Оғоз" + +msgid "Open an issue" +msgstr "Масъаларо кушоед" + +msgid "Fullscreen mode" +msgstr "Ҳолати экрани пурра" + +msgid "Sphinx Book Theme" +msgstr "Сфинкс Мавзӯи китоб" + +msgid "Contents" +msgstr "Мундариҷа" + +msgid "Edit this page" +msgstr "Ин саҳифаро таҳрир кунед" + +msgid "next page" +msgstr "саҳифаи оянда" + +msgid "Source repository" +msgstr "Анбори манбаъ" + +msgid "By" +msgstr "Бо" + +msgid "By the" +msgstr "Бо" + +msgid "previous page" +msgstr "саҳифаи қаблӣ" diff --git a/_static/locales/th/LC_MESSAGES/booktheme.mo b/_static/locales/th/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..abede98aa11b163e580a26b545980ace31e61ccf GIT binary patch literal 1766 zcma)*-)|K~6vqcarB^@&)CU_K663GrYB9uM>wQ7mgal$EMW46#4trN`XEwWgD~&H; zNI=2(Qi7!k28|(VOaz2Z{{sC3d@_d21Bp*Q8{hn#*{fZQQ8%6a%*>u2-*e9G?VVdL zD4xeyEM|9;NtGW4!Kz+u&BX3y#5Y_$YiD?uH$>6TSg=Km#9y)rhB| z#94;h;VRq)zl0CNTOLHf&S01Tf9_gR-TKX!nk)j@8 z$!wbssp1UphqNWmR~=a5Pgi}TUURlGwkp}=OGTFUD|OJlYX>grY3nL8@7z23cs4K_ z*QFa4UGulgs-KlQPg0|%ds#*3KaVrR!JzCG##p`JdPW^i%1RIOUQ(H!c9!$dcKhn} z9D~H_tSpB{%@&y@h|{wNXVlR;Utw}rW|b?J)X}`3*%SJJXq)Ss1*76y&(}50xilRZ zZIi_;O{$C})|{wnbx!isN%F!hW^Oo=-3VU})6}5SPzh4p+ooH!5B1t_nxZ7yq^|R~ zC4W0+ZXG#vWP0QK-WMiXqsF%9mU1(xD+Iil50cDI>25zMN>g=?&CRs;Z`c)yEsvX` zJ#D+Lm)Ueu@1M`A*5SmaL;6aLert9xERsQc#uW?Yq_%lHmYtWTbiM67YxSOv-uv8C zONI6KgI^B*v*yl!75w$!KM(#=@YjO>NCp2z@ZSZGG2hr+4E__@te@u_{+M44euZ<4 z_;qwx4(q3b|5Wzei|3W#eYCFwuf#yNf&j$Yu0#;+cXcn64J%wUT=~$4O>SO5=h=^

cLPeiV0|6qlnFzL#U0qn`*`iT?nxl@xb2Mx-{rpyeF$L|PmGL73Xj zjT&US*r9DL+Oc6=XyNi4J`IP)4~3RpiSp}N5WkMWZ=`O(hjnrBo?i;ppCMASYj{fI qV*6MBqwc03(drtRAFXAoSBd=B?a4S*sk|OB^ZqtY{YJQZ;_45RC*i9A literal 0 HcmV?d00001 diff --git a/_static/locales/th/LC_MESSAGES/booktheme.po b/_static/locales/th/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..25d9837f --- /dev/null +++ b/_static/locales/th/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "ดาวน์โหลดไฟล์ต้นฉบับ" + +msgid "suggest edit" +msgstr "แนะนำแก้ไข" + +msgid "Toggle navigation" +msgstr "ไม่ต้องสลับช่องทาง" + +msgid "open issue" +msgstr "เปิดปัญหา" + +msgid "Download notebook file" +msgstr "ดาวน์โหลดไฟล์สมุดบันทึก" + +msgid "repository" +msgstr "ที่เก็บ" + +msgid "Theme by the" +msgstr "ธีมโดย" + +msgid "Print to PDF" +msgstr "พิมพ์เป็น PDF" + +msgid "Download this page" +msgstr "ดาวน์โหลดหน้านี้" + +msgid "Copyright" +msgstr "ลิขสิทธิ์" + +msgid "Last updated on" +msgstr "ปรับปรุงล่าสุดเมื่อ" + +msgid "Launch" +msgstr "เปิด" + +msgid "Open an issue" +msgstr "เปิดปัญหา" + +msgid "Fullscreen mode" +msgstr "โหมดเต็มหน้าจอ" + +msgid "Sphinx Book Theme" +msgstr "ธีมหนังสือสฟิงซ์" + +msgid "Contents" +msgstr "สารบัญ" + +msgid "Edit this page" +msgstr "แก้ไขหน้านี้" + +msgid "next page" +msgstr "หน้าต่อไป" + +msgid "Source repository" +msgstr "ที่เก็บซอร์ส" + +msgid "By" +msgstr "โดย" + +msgid "By the" +msgstr "โดย" + +msgid "previous page" +msgstr "หน้าที่แล้ว" diff --git a/_static/locales/tl/LC_MESSAGES/booktheme.mo b/_static/locales/tl/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..8df1b73310e0c606251d1abff7e6033d1f6b273f GIT binary patch literal 1273 zcmZ{iJ#P~+7{?8ixA4}MHz7bWh@lJz6qYJggw!_(YD=U9)PcpxxsJ)jKAr8h8TbH< zl>mt^fEW=h3@|dWP{DwN#01}fk%9knmnKyup2YV%`|Ricw;%r;A9>CYr_e5-eL%a2 z_Gk|th%ew?a0@&DeghAKKfp8KZ;;mh1;@cLOg;`?0Z)LpKw38o9s}=zN5K_v43vGY z_s5_1`!7J!c@37pw;-+m2-5n`;Ct{ph(FuhSLAyJ(z;h52j75~!7cDS_y;@-j*b-m zC%}W~-v&p)J0SUA0Z)SpJPAGlY2GGy4txoc|92qy`UKMYuOOYrFAzsE2s#`3PH_Yc zHrRgZAP%9?9w{GbQ&0{H+8gOp(7q^W|Kx>&wCSAbj3LR`Ob>tV+mg-Nw3lhs_H53s zo5YHk8|!7$+74gUi5w0)8?u(%HR#*g@l+_u=40)Val5-HoaZ5pg_kk6hAoOEtD7`fpKHxt1^q`P0PmGs4|~w zYF}CuMg<%mawMf%5;BoQ3pVSzGB;`7b(Ndbym+ll7=Ee3C$CPI*s^AIft_~oQ`+M| zjoMMlC845tP)?QC3^N9mW&fLyY9mxPB*L)jFaumd3$>sZlm_4E_)y1P<99=X&7mSu zQF#bj7^^11I1!U-GjxO_E86t}@}&6i_@% literal 0 HcmV?d00001 diff --git a/_static/locales/tl/LC_MESSAGES/booktheme.po b/_static/locales/tl/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..7e28b05f --- /dev/null +++ b/_static/locales/tl/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Mag-download ng file ng pinagmulan" + +msgid "suggest edit" +msgstr "iminumungkahi i-edit" + +msgid "Toggle navigation" +msgstr "I-toggle ang pag-navigate" + +msgid "open issue" +msgstr "bukas na isyu" + +msgid "Download notebook file" +msgstr "Mag-download ng file ng notebook" + +msgid "Theme by the" +msgstr "Tema ng" + +msgid "Print to PDF" +msgstr "I-print sa PDF" + +msgid "Download this page" +msgstr "I-download ang pahinang ito" + +msgid "Copyright" +msgstr "Copyright" + +msgid "Last updated on" +msgstr "Huling na-update noong" + +msgid "Launch" +msgstr "Ilunsad" + +msgid "Open an issue" +msgstr "Magbukas ng isyu" + +msgid "Sphinx Book Theme" +msgstr "Tema ng Sphinx Book" + +msgid "Edit this page" +msgstr "I-edit ang pahinang ito" + +msgid "next page" +msgstr "Susunod na pahina" + +msgid "Source repository" +msgstr "Pinagmulan ng imbakan" + +msgid "By" +msgstr "Ni" + +msgid "By the" +msgstr "Sa pamamagitan ng" + +msgid "previous page" +msgstr "Nakaraang pahina" diff --git a/_static/locales/tr/LC_MESSAGES/booktheme.mo b/_static/locales/tr/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..029ae18afb5360a8c238a052e8d3971761759d3d GIT binary patch literal 1373 zcmZ{izi%8x6vqdWKynFz!~~?sQXUOIiX{o62)3@sVLOWA2n!$dC&=i7J19yL{j6T0W2%?d)gY?96-L@67yl{`g~s z_CESD`XA_*&>y~r7uw0!mBOP=;q?Z120RHafv3P_@ICND@LjMEo(I1M&w>oT4aSc5 zLCNz7d<%R6o&kRZ&w(7D`FN2cjBk&jSbMQ3yvf}|L z^-dgb=PiL35fdohSHUH48x$WIDEhw##oq%^>ihtT&YwW>`D+*d4$8W}!FRxeF7BOZ z>s|syPtwI-fS96gfHHp*lr0wzl2>wx9;q$97n`h;HKI?N=#nP7WUs~N1$3mG*A#z? zP4-{T@J)1V%lv%Rpus~iXZ5ACk!=k4s2XpwJgPPKoh_YC$-2lp&J{E^B_9n3SNjqF zXE5d_P^B|g>#2!IeHd=kWf?}E+0w+NtTuIsR9C5voRYJMYdgx-R~05`OD2Sx)s{CF zNgQphZK&MIp`-&XC zw^i0&m&u0nldwXznunqP*($Z4{f{ku(5I`PtoGDUdp(}*+f>_seb0WLJ~cMw0*C6= zkV`YBTo=V`U#;;tvZvIAMh7gN?Gt7i9EQ538>@@sDR7=_PxgBv?;s7aXZ*rps`o&(U<3tx~U_1rqYg?0^K7|^E%RsJ#t%4f8 zo6h$Ap{&BCl*;`;;xXGI&@B^nMMIv5kwyPFiiuV?c-PnoHwMdQd*;PnG+qT~k=xL= f7*f}zXhDUuwVFPIQ2d!&RZ>YE8iRKH#ZJBgJpfrQ literal 0 HcmV?d00001 diff --git a/_static/locales/tr/LC_MESSAGES/booktheme.po b/_static/locales/tr/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..54d6f583 --- /dev/null +++ b/_static/locales/tr/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "Kaynak dosyayı indirin" + +msgid "suggest edit" +msgstr "düzenleme öner" + +msgid "Toggle navigation" +msgstr "Gezinmeyi değiştir" + +msgid "open issue" +msgstr "Açık konu" + +msgid "Download notebook file" +msgstr "Defter dosyasını indirin" + +msgid "repository" +msgstr "depo" + +msgid "Theme by the" +msgstr "Tarafından tema" + +msgid "Print to PDF" +msgstr "PDF olarak yazdır" + +msgid "Download this page" +msgstr "Bu sayfayı indirin" + +msgid "Copyright" +msgstr "Telif hakkı" + +msgid "Last updated on" +msgstr "Son güncelleme tarihi" + +msgid "Launch" +msgstr "Başlatmak" + +msgid "Open an issue" +msgstr "Bir sorunu açın" + +msgid "Fullscreen mode" +msgstr "Tam ekran modu" + +msgid "Sphinx Book Theme" +msgstr "Sfenks Kitap Teması" + +msgid "Contents" +msgstr "İçindekiler" + +msgid "Edit this page" +msgstr "Bu sayfayı düzenle" + +msgid "next page" +msgstr "sonraki Sayfa" + +msgid "Source repository" +msgstr "Kaynak kod deposu" + +msgid "By" +msgstr "Tarafından" + +msgid "By the" +msgstr "Tarafından" + +msgid "previous page" +msgstr "önceki sayfa" diff --git a/_static/locales/uk/LC_MESSAGES/booktheme.mo b/_static/locales/uk/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..16ab78909cfbaba7fa199f47fdfc2934426ac699 GIT binary patch literal 1681 zcmZvaO>7%Q6vv0QKx#^WmXAw-X;52=V^7yhotb5Kwlue- zPJ@uD1fdWPh|e20*TKPc;zZ)a@r}d@A+B8DUJjM|f4dvvq>McK+j;xuef*#QJbLI0 zf%O{p5cY4_Z(`qj3JD;1Tdg@Fj3P=dZc__x$`9$oc*S3*fo^agnKo4Zexd+ydwLFH++H&9h3nhscvH3nP?w=Ry$GKV8 zSFn*%JcrG*?O#Zh&hS|fa-{PW7iaO4wx+~;Mq8zAjF)gW3jCTCm(0hyZoI10#;R#! zZps@$UG17A`bVb!y$DvicD z(UqEbKZJv)We~@S5))CN5yZ%eOXK2NmM>DFi34k*S#d3_1^TwU$hA$?)Ql48Q%+|+ zO&Q;>E2+I(f$!M>Nwm6cv+4}z$&!STx)qotFS{>%ocO*%l?t7p6!W2~*y81C@dFjb zh*pwW{vziurkM*@FJB$o{eEubY#|r6I5iuplC&t`Oj!2O`(TSv<;z`$dL~;A5u^%qBgBK^s=!h>rLI6)qdpT zRwLUoA{Qc+BL{@CNd#$~fM}{TM=rgzQV%n0sfS7&;BP2WpLe~9L#0ZLy!)G(eLtS} z@uTBCHyGACc;3gei{}G8S6;vi>pu7*_yBwvdd_{ zw7^~PH24qrDR`oXv3~FiknZO|ioXGV2*%(?;Gf{z;NRf8;J+FBUg~@w04eVRNO2|b zJ#Z2H7+e8i$-yFT-pWp-6LJ_r(sdMXnvv>}ceKb;S{N^_PkZu%7R~=ky6bpCK9k3g z$k@3h{CHRvY(#lWzU!1jHmVk6McE}TRVZeZy2@wWis)VkD)Nisnai;32Hdk9!Ny8% zh>H8iNjnI6>?(vD=Y%)au3|&?BFFX~vq4Jm5 zMX&72MShO7Oqazq!O}OM=}4bej#Cj_+Vieshc22(u^4vLDC*N`;`w6URZ%80h#W^i znt)vNS978mS`#JfvhV|x$n#E9i<(+#yWIJS^JCrbgJ(X=jVKuk8Cugzp2+hMT?f31 z?aE=i4%v6}~kli>l;GC(nmw+%Pw3ODBSPc^>(>sY>MA6>D7i z*MdBkUV01)pAYlSw$Ly6$pRnzWH`t4n!cr5?Pa~wuCipkz0CC=x@BmuW3xx+mX7tR z*NZtNFp)tbr@2L4}dj%B? z$~?F1e_~CYdU3r0$=I6uq5ePVO_Bn=P}riFSZ}qf6oE57w5w3K+FoX+hEW?y<4|&p zx|p)Aw=sGx%}Vw#el49X^(ARiaRizwH+vA!fH?=_BQ=JATO9Uo!rm6_g(Z9Fvrf~J ziFzY}!KTjO`w9hS|3mkKY2Z8hBsWpwH*$FgF5fip{lMp#&N|*Vkp4MHrJJsNw1%8D c^9?3>eEmE8GP@z_uy-`khW>?G>aA{%rxd0lq5uE@ literal 0 HcmV?d00001 diff --git a/_static/locales/ur/LC_MESSAGES/booktheme.po b/_static/locales/ur/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..818e03de --- /dev/null +++ b/_static/locales/ur/LC_MESSAGES/booktheme.po @@ -0,0 +1,66 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "سورس فائل ڈاؤن لوڈ کریں" + +msgid "suggest edit" +msgstr "ترمیم کی تجویز کریں" + +msgid "Toggle navigation" +msgstr "نیویگیشن ٹوگل کریں" + +msgid "open issue" +msgstr "کھلا مسئلہ" + +msgid "Download notebook file" +msgstr "نوٹ بک فائل ڈاؤن لوڈ کریں" + +msgid "Theme by the" +msgstr "کے ذریعہ تھیم" + +msgid "Print to PDF" +msgstr "پی ڈی ایف پرنٹ کریں" + +msgid "Download this page" +msgstr "اس صفحے کو ڈاؤن لوڈ کریں" + +msgid "Copyright" +msgstr "کاپی رائٹ" + +msgid "Last updated on" +msgstr "آخری بار تازہ کاری ہوئی" + +msgid "Launch" +msgstr "لانچ کریں" + +msgid "Open an issue" +msgstr "ایک مسئلہ کھولیں" + +msgid "Sphinx Book Theme" +msgstr "سپنکس بک تھیم" + +msgid "Edit this page" +msgstr "اس صفحے میں ترمیم کریں" + +msgid "next page" +msgstr "اگلا صفحہ" + +msgid "Source repository" +msgstr "ماخذ ذخیرہ" + +msgid "By" +msgstr "بذریعہ" + +msgid "By the" +msgstr "کی طرف" + +msgid "previous page" +msgstr "سابقہ ​​صفحہ" diff --git a/_static/locales/vi/LC_MESSAGES/booktheme.mo b/_static/locales/vi/LC_MESSAGES/booktheme.mo new file mode 100644 index 0000000000000000000000000000000000000000..2bb32555c3ea0dab08ed37b71cb863fbe75698c6 GIT binary patch literal 1431 zcmZvb&x;&I6vr#s{2bR9catc(#OK8%htWiG2(!#(H#@MntBVvV&v#)!JFr^_{KP>F`@nJV05}OA1gF4b;9KAkunA6pAA*NK z3BCmSiq}An^CkEqxCxGf--9oMKUe&tTK}_}KL%Ov30MQi#>)GLK%P&59Onf13wRdX z3;qSN-ajCp`xj*0y?e@hC&AY-KMlSLE>x7&{%7EEtZ#xGrw?+zzkx4+4=O$aInLi8 z=P?fP6X0=>=PmFs_%X6t9{djXqq7H;REU`#e&m%Dv(|WNyu(A%OLe5YIB!2Su?;$8te4By zUZxct%bjIsvow_dS@cRfN`gp=xsLV-{cPIG;@E|$l!jJqM~a2OdCHPb;AMxb!8|je z5+5Wu5E#l0;esOMR|IFK`YgJ+E?Oq}qlDRK7TFmDND~hLNUKno*_5*I#duC ze1pUH?uya95XS7fK6vqb$6da&5d>$e(Tqr%5FL8(*`2r*YiH`^Z>aE(?ll6i#v)Y{nLNAmS zVZLM|@+Cqff{+L(H9>+X*h#n|&YXJarQWrDsNf1G{?EIRgwekJ?VFu>|Np%Cx20*2 zVQfXTBHkmmBW^Fl3uEes3ZOb zQk?;C9XJZE1)qXHfzuJ+M)Utfc@-qRPhbpOu_D~R9;Cb#q&h!?W$*w<>pw>P43chB zQ^;m;Gx8RY{OyX^7V!v3^?n6uod9Y7@6r5Kko@OC(isEk+)qHNR|2Y~glBh97KqDQIoyw}Q#g=trLPD*?? zsWX<#ZNn6-BW-Dv{+f1r*{qv#gpj;Xr3E`?xSD%*+R!4+l|=5zREC|jvA~era$Qfb zF2|B6qIlQgPIfxfbA+v2ODm_JowhTUyu=TZx9*JS6Rh#(J>i+Um1$-Lm&OIlG_(Z~ zDK6>Iog$r3#CF65OL>v)Mde-3GzDA=oCH?XIg!%wqv`lr;kc-l;Guq;^y3ZX*zu#s zI~M-$+r2jyH8$SeZ;J%iFtEqY8kTJ5sf^*cLMP93cgEWm);WfBdxaD4kSUe6q?zDt zJ(i9gGoRpuVl zu3Y;tdw+Y?BAIRa)rh7%Q6vqb|O6z_>OFs^gI=uiz7%1XUIrvhVNR?8ES{E)zXk$;;3!9nM?rdo| zg(?BJNt;NGU78fyR1pmy`2barI!U>5;l_yr7d&hG1XmCT{?EI?hS9$L&6|(+{`20i zd%MaE;~=aX_A~4-Y~m68Ft$C)7(TWgzpda-a2vP}+zxhw2f(Mnr@$<@7d!**1_ihW z)CosHiZc!F0%yUU;1}SN;CBgsOxAx%{5nYa{sdFtmM!u9-5~khAjNqGTmxSL>HHrF z{{ks*S695g10>!1LDKhp!dDaaCwv>+k9`-U`l4+X18A zb`E+6_3&{R%F^mDJ28xp>!M(W-N{d0I-s9&TSG1P{ z75aJczeQbi0`6J1V7&!LBlM=*7rJhc_l1yrNEHO@w*t*WuV86W;7Y;|WxmMX@NmGA z+zEnEumRtZ2%`AF$v$>A&gTnH1&&t!FgxoN9eI(TAZ@v#7!s`Y=Y#Q^a>}+{!KHP< zu`TT&i4+%gtWHs$IEm+r3yumC*&X47(6$9s3cLhT)Vm_D)29mQH-#S{T878@)098m z%A7iV>U3{=|JVyJrINy?bHkpi>0X&v z1xMN$etgi;seVh^A?ljp9~9roy_FhpL*H`KeaasSGF*BsH^{!+!{cf8S;>!N`LUxt zDOTIK)fgH3eSM~5R-avJPKqIR9T5`UTRjZlMYk9ZN|&2 zSsBNyvAEKln_#AN!(3g7N>iJPqMOUL)it`->9il( zoLjEXSEEv;IrB~9#-v%f*7$q_8AyL^bp+y>8T%Uf>ocRKJlP7gdS!Fx->lK(l=-+? P`(Y`Xeqh$BP|E%Rvo4ks literal 0 HcmV?d00001 diff --git a/_static/locales/zh_TW/LC_MESSAGES/booktheme.po b/_static/locales/zh_TW/LC_MESSAGES/booktheme.po new file mode 100644 index 00000000..0ed32f74 --- /dev/null +++ b/_static/locales/zh_TW/LC_MESSAGES/booktheme.po @@ -0,0 +1,75 @@ + +msgid "" +msgstr "" +"Project-Id-Version: Sphinx-Book-Theme\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Download source file" +msgstr "下載原始檔" + +msgid "suggest edit" +msgstr "提出修改建議" + +msgid "Toggle navigation" +msgstr "顯示或隱藏導覽列" + +msgid "open issue" +msgstr "公開的問題" + +msgid "Download notebook file" +msgstr "下載 Notebook 檔案" + +msgid "repository" +msgstr "儲存庫" + +msgid "Theme by the" +msgstr "佈景主題作者:" + +msgid "Print to PDF" +msgstr "列印成 PDF" + +msgid "Download this page" +msgstr "下載此頁面" + +msgid "Copyright" +msgstr "Copyright" + +msgid "Last updated on" +msgstr "最後更新時間:" + +msgid "Launch" +msgstr "啟動" + +msgid "Open an issue" +msgstr "開啟議題" + +msgid "Fullscreen mode" +msgstr "全螢幕模式" + +msgid "Sphinx Book Theme" +msgstr "Sphinx Book 佈景主題" + +msgid "Contents" +msgstr "目錄" + +msgid "Edit this page" +msgstr "編輯此頁面" + +msgid "next page" +msgstr "下一頁" + +msgid "Source repository" +msgstr "來源儲存庫" + +msgid "By" +msgstr "作者:" + +msgid "By the" +msgstr "作者:" + +msgid "previous page" +msgstr "上一頁" diff --git a/_static/logo.png b/_static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1e902eedd4368e8cc93c988a5dd98b38226f642a GIT binary patch literal 605248 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

#eR(uK{ySPkix#pDok$Hl;t<0up^QGWae$C_g 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

c~}h#iEpbNS->ca%a4BmFvQoG}RPGe_BIo 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≺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 literal 0 HcmV?d00001 diff --git a/_static/pygments.css b/_static/pygments.css index dd6621d8..997797f2 100644 --- a/_static/pygments.css +++ b/_static/pygments.css @@ -1,77 +1,152 @@ -.highlight .hll { background-color: #ffffcc } -.highlight { background: #f8f8f8; } -.highlight .c { color: #8f5902; font-style: italic } /* Comment */ -.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ -.highlight .g { color: #000000 } /* Generic */ -.highlight .k { color: #004461; font-weight: bold } /* Keyword */ -.highlight .l { color: #000000 } /* Literal */ -.highlight .n { color: #000000 } /* Name */ -.highlight .o { color: #582800 } /* Operator */ -.highlight .x { color: #000000 } /* Other */ -.highlight .p { color: #000000; font-weight: bold } /* Punctuation */ -.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ -.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #8f5902 } /* Comment.Preproc */ -.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ -.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ -.highlight .gd { color: #a40000 } /* Generic.Deleted */ -.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #ef2929 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #00A000 } /* Generic.Inserted */ -.highlight .go { color: #888888 } /* Generic.Output */ -.highlight .gp { color: #745334 } /* Generic.Prompt */ -.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ -.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ -.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ -.highlight .ld { color: #000000 } /* Literal.Date */ -.highlight .m { color: #990000 } /* Literal.Number */ -.highlight .s { color: #4e9a06 } /* Literal.String */ -.highlight .na { color: #c4a000 } /* Name.Attribute */ -.highlight .nb { color: #004461 } /* Name.Builtin */ -.highlight .nc { color: #000000 } /* Name.Class */ -.highlight .no { color: #000000 } /* Name.Constant */ -.highlight .nd { color: #888888 } /* Name.Decorator */ -.highlight .ni { color: #ce5c00 } /* Name.Entity */ -.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #000000 } /* Name.Function */ -.highlight .nl { color: #f57900 } /* Name.Label */ -.highlight .nn { color: #000000 } /* Name.Namespace */ -.highlight .nx { color: #000000 } /* Name.Other */ -.highlight .py { color: #000000 } /* Name.Property */ -.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #000000 } /* Name.Variable */ -.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ -.highlight .mb { color: #990000 } /* Literal.Number.Bin */ -.highlight .mf { color: #990000 } /* Literal.Number.Float */ -.highlight .mh { color: #990000 } /* Literal.Number.Hex */ -.highlight .mi { color: #990000 } /* Literal.Number.Integer */ -.highlight .mo { color: #990000 } /* Literal.Number.Oct */ -.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ -.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ -.highlight .sc { color: #4e9a06 } /* Literal.String.Char */ -.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ -.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ -.highlight .se { color: #4e9a06 } /* Literal.String.Escape */ -.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ -.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ -.highlight .sx { color: #4e9a06 } /* Literal.String.Other */ -.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ -.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ -.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ -.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ -.highlight .fm { color: #000000 } /* Name.Function.Magic */ -.highlight .vc { color: #000000 } /* Name.Variable.Class */ -.highlight .vg { color: #000000 } /* Name.Variable.Global */ -.highlight .vi { color: #000000 } /* Name.Variable.Instance */ -.highlight .vm { color: #000000 } /* Name.Variable.Magic */ -.highlight .il { color: #990000 } /* Literal.Number.Integer.Long */ \ No newline at end of file +html[data-theme="light"] .highlight pre { line-height: 125%; } +html[data-theme="light"] .highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="light"] .highlight .hll { background-color: #7971292e } +html[data-theme="light"] .highlight { background: #fefefe; color: #545454 } +html[data-theme="light"] .highlight .c { color: #797129 } /* Comment */ +html[data-theme="light"] .highlight .err { color: #d91e18 } /* Error */ +html[data-theme="light"] .highlight .k { color: #7928a1 } /* Keyword */ +html[data-theme="light"] .highlight .l { color: #797129 } /* Literal */ +html[data-theme="light"] .highlight .n { color: #545454 } /* Name */ +html[data-theme="light"] .highlight .o { color: #008000 } /* Operator */ +html[data-theme="light"] .highlight .p { color: #545454 } /* Punctuation */ +html[data-theme="light"] .highlight .ch { color: #797129 } /* Comment.Hashbang */ +html[data-theme="light"] .highlight .cm { color: #797129 } /* Comment.Multiline */ +html[data-theme="light"] .highlight .cp { color: #797129 } /* Comment.Preproc */ +html[data-theme="light"] .highlight .cpf { color: #797129 } /* Comment.PreprocFile */ +html[data-theme="light"] .highlight .c1 { color: #797129 } /* Comment.Single */ +html[data-theme="light"] .highlight .cs { color: #797129 } /* Comment.Special */ +html[data-theme="light"] .highlight .gd { color: #007faa } /* Generic.Deleted */ +html[data-theme="light"] .highlight .ge { font-style: italic } /* Generic.Emph */ +html[data-theme="light"] .highlight .gh { color: #007faa } /* Generic.Heading */ +html[data-theme="light"] .highlight .gs { font-weight: bold } /* Generic.Strong */ +html[data-theme="light"] .highlight .gu { color: #007faa } /* Generic.Subheading */ +html[data-theme="light"] .highlight .kc { color: #7928a1 } /* Keyword.Constant */ +html[data-theme="light"] .highlight .kd { color: #7928a1 } /* Keyword.Declaration */ +html[data-theme="light"] .highlight .kn { color: #7928a1 } /* Keyword.Namespace */ +html[data-theme="light"] .highlight .kp { color: #7928a1 } /* Keyword.Pseudo */ +html[data-theme="light"] .highlight .kr { color: #7928a1 } /* Keyword.Reserved */ +html[data-theme="light"] .highlight .kt { color: #797129 } /* Keyword.Type */ +html[data-theme="light"] .highlight .ld { color: #797129 } /* Literal.Date */ +html[data-theme="light"] .highlight .m { color: #797129 } /* Literal.Number */ +html[data-theme="light"] .highlight .s { color: #008000 } /* Literal.String */ +html[data-theme="light"] .highlight .na { color: #797129 } /* Name.Attribute */ +html[data-theme="light"] .highlight .nb { color: #797129 } /* Name.Builtin */ +html[data-theme="light"] .highlight .nc { color: #007faa } /* Name.Class */ +html[data-theme="light"] .highlight .no { color: #007faa } /* Name.Constant */ +html[data-theme="light"] .highlight .nd { color: #797129 } /* Name.Decorator */ +html[data-theme="light"] .highlight .ni { color: #008000 } /* Name.Entity */ +html[data-theme="light"] .highlight .ne { color: #7928a1 } /* Name.Exception */ +html[data-theme="light"] .highlight .nf { color: #007faa } /* Name.Function */ +html[data-theme="light"] .highlight .nl { color: #797129 } /* Name.Label */ +html[data-theme="light"] .highlight .nn { color: #545454 } /* Name.Namespace */ +html[data-theme="light"] .highlight .nx { color: #545454 } /* Name.Other */ +html[data-theme="light"] .highlight .py { color: #007faa } /* Name.Property */ +html[data-theme="light"] .highlight .nt { color: #007faa } /* Name.Tag */ +html[data-theme="light"] .highlight .nv { color: #d91e18 } /* Name.Variable */ +html[data-theme="light"] .highlight .ow { color: #7928a1 } /* Operator.Word */ +html[data-theme="light"] .highlight .pm { color: #545454 } /* Punctuation.Marker */ +html[data-theme="light"] .highlight .w { color: #545454 } /* Text.Whitespace */ +html[data-theme="light"] .highlight .mb { color: #797129 } /* Literal.Number.Bin */ +html[data-theme="light"] .highlight .mf { color: #797129 } /* Literal.Number.Float */ +html[data-theme="light"] .highlight .mh { color: #797129 } /* Literal.Number.Hex */ +html[data-theme="light"] .highlight .mi { color: #797129 } /* Literal.Number.Integer */ +html[data-theme="light"] .highlight .mo { color: #797129 } /* Literal.Number.Oct */ +html[data-theme="light"] .highlight .sa { color: #008000 } /* Literal.String.Affix */ +html[data-theme="light"] .highlight .sb { color: #008000 } /* Literal.String.Backtick */ +html[data-theme="light"] .highlight .sc { color: #008000 } /* Literal.String.Char */ +html[data-theme="light"] .highlight .dl { color: #008000 } /* Literal.String.Delimiter */ +html[data-theme="light"] .highlight .sd { color: #008000 } /* Literal.String.Doc */ +html[data-theme="light"] .highlight .s2 { color: #008000 } /* Literal.String.Double */ +html[data-theme="light"] .highlight .se { color: #008000 } /* Literal.String.Escape */ +html[data-theme="light"] .highlight .sh { color: #008000 } /* Literal.String.Heredoc */ +html[data-theme="light"] .highlight .si { color: #008000 } /* Literal.String.Interpol */ +html[data-theme="light"] .highlight .sx { color: #008000 } /* Literal.String.Other */ +html[data-theme="light"] .highlight .sr { color: #d91e18 } /* Literal.String.Regex */ +html[data-theme="light"] .highlight .s1 { color: #008000 } /* Literal.String.Single */ +html[data-theme="light"] .highlight .ss { color: #007faa } /* Literal.String.Symbol */ +html[data-theme="light"] .highlight .bp { color: #797129 } /* Name.Builtin.Pseudo */ +html[data-theme="light"] .highlight .fm { color: #007faa } /* Name.Function.Magic */ +html[data-theme="light"] .highlight .vc { color: #d91e18 } /* Name.Variable.Class */ +html[data-theme="light"] .highlight .vg { color: #d91e18 } /* Name.Variable.Global */ +html[data-theme="light"] .highlight .vi { color: #d91e18 } /* Name.Variable.Instance */ +html[data-theme="light"] .highlight .vm { color: #797129 } /* Name.Variable.Magic */ +html[data-theme="light"] .highlight .il { color: #797129 } /* Literal.Number.Integer.Long */ +html[data-theme="dark"] .highlight pre { line-height: 125%; } +html[data-theme="dark"] .highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +html[data-theme="dark"] .highlight .hll { background-color: #ffd9002e } +html[data-theme="dark"] .highlight { background: #2b2b2b; color: #f8f8f2 } +html[data-theme="dark"] .highlight .c { color: #ffd900 } /* Comment */ +html[data-theme="dark"] .highlight .err { color: #ffa07a } /* Error */ +html[data-theme="dark"] .highlight .k { color: #dcc6e0 } /* Keyword */ +html[data-theme="dark"] .highlight .l { color: #ffd900 } /* Literal */ +html[data-theme="dark"] .highlight .n { color: #f8f8f2 } /* Name */ +html[data-theme="dark"] .highlight .o { color: #abe338 } /* Operator */ +html[data-theme="dark"] .highlight .p { color: #f8f8f2 } /* Punctuation */ +html[data-theme="dark"] .highlight .ch { color: #ffd900 } /* Comment.Hashbang */ +html[data-theme="dark"] .highlight .cm { color: #ffd900 } /* Comment.Multiline */ +html[data-theme="dark"] .highlight .cp { color: #ffd900 } /* Comment.Preproc */ +html[data-theme="dark"] .highlight .cpf { color: #ffd900 } /* Comment.PreprocFile */ +html[data-theme="dark"] .highlight .c1 { color: #ffd900 } /* Comment.Single */ +html[data-theme="dark"] .highlight .cs { color: #ffd900 } /* Comment.Special */ +html[data-theme="dark"] .highlight .gd { color: #00e0e0 } /* Generic.Deleted */ +html[data-theme="dark"] .highlight .ge { font-style: italic } /* Generic.Emph */ +html[data-theme="dark"] .highlight .gh { color: #00e0e0 } /* Generic.Heading */ +html[data-theme="dark"] .highlight .gs { font-weight: bold } /* Generic.Strong */ +html[data-theme="dark"] .highlight .gu { color: #00e0e0 } /* Generic.Subheading */ +html[data-theme="dark"] .highlight .kc { color: #dcc6e0 } /* Keyword.Constant */ +html[data-theme="dark"] .highlight .kd { color: #dcc6e0 } /* Keyword.Declaration */ +html[data-theme="dark"] .highlight .kn { color: #dcc6e0 } /* Keyword.Namespace */ +html[data-theme="dark"] .highlight .kp { color: #dcc6e0 } /* Keyword.Pseudo */ +html[data-theme="dark"] .highlight .kr { color: #dcc6e0 } /* Keyword.Reserved */ +html[data-theme="dark"] .highlight .kt { color: #ffd900 } /* Keyword.Type */ +html[data-theme="dark"] .highlight .ld { color: #ffd900 } /* Literal.Date */ +html[data-theme="dark"] .highlight .m { color: #ffd900 } /* Literal.Number */ +html[data-theme="dark"] .highlight .s { color: #abe338 } /* Literal.String */ +html[data-theme="dark"] .highlight .na { color: #ffd900 } /* Name.Attribute */ +html[data-theme="dark"] .highlight .nb { color: #ffd900 } /* Name.Builtin */ +html[data-theme="dark"] .highlight .nc { color: #00e0e0 } /* Name.Class */ +html[data-theme="dark"] .highlight .no { color: #00e0e0 } /* Name.Constant */ +html[data-theme="dark"] .highlight .nd { color: #ffd900 } /* Name.Decorator */ +html[data-theme="dark"] .highlight .ni { color: #abe338 } /* Name.Entity */ +html[data-theme="dark"] .highlight .ne { color: #dcc6e0 } /* Name.Exception */ +html[data-theme="dark"] .highlight .nf { color: #00e0e0 } /* Name.Function */ +html[data-theme="dark"] .highlight .nl { color: #ffd900 } /* Name.Label */ +html[data-theme="dark"] .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ +html[data-theme="dark"] .highlight .nx { color: #f8f8f2 } /* Name.Other */ +html[data-theme="dark"] .highlight .py { color: #00e0e0 } /* Name.Property */ +html[data-theme="dark"] .highlight .nt { color: #00e0e0 } /* Name.Tag */ +html[data-theme="dark"] .highlight .nv { color: #ffa07a } /* Name.Variable */ +html[data-theme="dark"] .highlight .ow { color: #dcc6e0 } /* Operator.Word */ +html[data-theme="dark"] .highlight .pm { color: #f8f8f2 } /* Punctuation.Marker */ +html[data-theme="dark"] .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ +html[data-theme="dark"] .highlight .mb { color: #ffd900 } /* Literal.Number.Bin */ +html[data-theme="dark"] .highlight .mf { color: #ffd900 } /* Literal.Number.Float */ +html[data-theme="dark"] .highlight .mh { color: #ffd900 } /* Literal.Number.Hex */ +html[data-theme="dark"] .highlight .mi { color: #ffd900 } /* Literal.Number.Integer */ +html[data-theme="dark"] .highlight .mo { color: #ffd900 } /* Literal.Number.Oct */ +html[data-theme="dark"] .highlight .sa { color: #abe338 } /* Literal.String.Affix */ +html[data-theme="dark"] .highlight .sb { color: #abe338 } /* Literal.String.Backtick */ +html[data-theme="dark"] .highlight .sc { color: #abe338 } /* Literal.String.Char */ +html[data-theme="dark"] .highlight .dl { color: #abe338 } /* Literal.String.Delimiter */ +html[data-theme="dark"] .highlight .sd { color: #abe338 } /* Literal.String.Doc */ +html[data-theme="dark"] .highlight .s2 { color: #abe338 } /* Literal.String.Double */ +html[data-theme="dark"] .highlight .se { color: #abe338 } /* Literal.String.Escape */ +html[data-theme="dark"] .highlight .sh { color: #abe338 } /* Literal.String.Heredoc */ +html[data-theme="dark"] .highlight .si { color: #abe338 } /* Literal.String.Interpol */ +html[data-theme="dark"] .highlight .sx { color: #abe338 } /* Literal.String.Other */ +html[data-theme="dark"] .highlight .sr { color: #ffa07a } /* Literal.String.Regex */ +html[data-theme="dark"] .highlight .s1 { color: #abe338 } /* Literal.String.Single */ +html[data-theme="dark"] .highlight .ss { color: #00e0e0 } /* Literal.String.Symbol */ +html[data-theme="dark"] .highlight .bp { color: #ffd900 } /* Name.Builtin.Pseudo */ +html[data-theme="dark"] .highlight .fm { color: #00e0e0 } /* Name.Function.Magic */ +html[data-theme="dark"] .highlight .vc { color: #ffa07a } /* Name.Variable.Class */ +html[data-theme="dark"] .highlight .vg { color: #ffa07a } /* Name.Variable.Global */ +html[data-theme="dark"] .highlight .vi { color: #ffa07a } /* Name.Variable.Instance */ +html[data-theme="dark"] .highlight .vm { color: #ffd900 } /* Name.Variable.Magic */ +html[data-theme="dark"] .highlight .il { color: #ffd900 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/sbt-webpack-macros.html b/_static/sbt-webpack-macros.html new file mode 100644 index 00000000..6cbf559f --- /dev/null +++ b/_static/sbt-webpack-macros.html @@ -0,0 +1,11 @@ + +{% macro head_pre_bootstrap() %} + +{% endmacro %} + +{% macro body_post() %} + +{% endmacro %} diff --git a/_static/scripts/bootstrap.js b/_static/scripts/bootstrap.js new file mode 100644 index 00000000..4e209b0e --- /dev/null +++ b/_static/scripts/bootstrap.js @@ -0,0 +1,3 @@ +/*! For license information please see bootstrap.js.LICENSE.txt */ +(()=>{"use strict";var t={d:(e,i)=>{for(var n in i)t.o(i,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:i[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{afterMain:()=>E,afterRead:()=>v,afterWrite:()=>C,applyStyles:()=>$,arrow:()=>J,auto:()=>a,basePlacements:()=>l,beforeMain:()=>y,beforeRead:()=>_,beforeWrite:()=>A,bottom:()=>s,clippingParents:()=>d,computeStyles:()=>it,createPopper:()=>Dt,createPopperBase:()=>St,createPopperLite:()=>$t,detectOverflow:()=>_t,end:()=>h,eventListeners:()=>st,flip:()=>bt,hide:()=>wt,left:()=>r,main:()=>w,modifierPhases:()=>O,offset:()=>Et,placements:()=>g,popper:()=>f,popperGenerator:()=>Lt,popperOffsets:()=>At,preventOverflow:()=>Tt,read:()=>b,reference:()=>p,right:()=>o,start:()=>c,top:()=>n,variationPlacements:()=>m,viewport:()=>u,write:()=>T});var i={};t.r(i),t.d(i,{Alert:()=>Oe,Button:()=>ke,Carousel:()=>ri,Collapse:()=>yi,Dropdown:()=>Vi,Modal:()=>xn,Offcanvas:()=>Vn,Popover:()=>fs,ScrollSpy:()=>Ts,Tab:()=>Ks,Toast:()=>lo,Tooltip:()=>hs});var n="top",s="bottom",o="right",r="left",a="auto",l=[n,s,o,r],c="start",h="end",d="clippingParents",u="viewport",f="popper",p="reference",m=l.reduce((function(t,e){return t.concat([e+"-"+c,e+"-"+h])}),[]),g=[].concat(l,[a]).reduce((function(t,e){return t.concat([e,e+"-"+c,e+"-"+h])}),[]),_="beforeRead",b="read",v="afterRead",y="beforeMain",w="main",E="afterMain",A="beforeWrite",T="write",C="afterWrite",O=[_,b,v,y,w,E,A,T,C];function x(t){return t?(t.nodeName||"").toLowerCase():null}function k(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function L(t){return t instanceof k(t).Element||t instanceof Element}function S(t){return t instanceof k(t).HTMLElement||t instanceof HTMLElement}function D(t){return"undefined"!=typeof ShadowRoot&&(t instanceof k(t).ShadowRoot||t instanceof ShadowRoot)}const $={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];S(s)&&x(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});S(n)&&x(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function I(t){return t.split("-")[0]}var N=Math.max,P=Math.min,M=Math.round;function j(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function F(){return!/^((?!chrome|android).)*safari/i.test(j())}function H(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&S(t)&&(s=t.offsetWidth>0&&M(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&M(n.height)/t.offsetHeight||1);var r=(L(t)?k(t):window).visualViewport,a=!F()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function B(t){var e=H(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function W(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&D(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function z(t){return k(t).getComputedStyle(t)}function R(t){return["table","td","th"].indexOf(x(t))>=0}function q(t){return((L(t)?t.ownerDocument:t.document)||window.document).documentElement}function V(t){return"html"===x(t)?t:t.assignedSlot||t.parentNode||(D(t)?t.host:null)||q(t)}function Y(t){return S(t)&&"fixed"!==z(t).position?t.offsetParent:null}function K(t){for(var e=k(t),i=Y(t);i&&R(i)&&"static"===z(i).position;)i=Y(i);return i&&("html"===x(i)||"body"===x(i)&&"static"===z(i).position)?e:i||function(t){var e=/firefox/i.test(j());if(/Trident/i.test(j())&&S(t)&&"fixed"===z(t).position)return null;var i=V(t);for(D(i)&&(i=i.host);S(i)&&["html","body"].indexOf(x(i))<0;){var n=z(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function Q(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function X(t,e,i){return N(t,P(e,i))}function U(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function G(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const J={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,a=t.name,c=t.options,h=i.elements.arrow,d=i.modifiersData.popperOffsets,u=I(i.placement),f=Q(u),p=[r,o].indexOf(u)>=0?"height":"width";if(h&&d){var m=function(t,e){return U("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:G(t,l))}(c.padding,i),g=B(h),_="y"===f?n:r,b="y"===f?s:o,v=i.rects.reference[p]+i.rects.reference[f]-d[f]-i.rects.popper[p],y=d[f]-i.rects.reference[f],w=K(h),E=w?"y"===f?w.clientHeight||0:w.clientWidth||0:0,A=v/2-y/2,T=m[_],C=E-g[p]-m[b],O=E/2-g[p]/2+A,x=X(T,O,C),k=f;i.modifiersData[a]=((e={})[k]=x,e.centerOffset=x-O,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&W(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Z(t){return t.split("-")[1]}var tt={top:"auto",right:"auto",bottom:"auto",left:"auto"};function et(t){var e,i=t.popper,a=t.popperRect,l=t.placement,c=t.variation,d=t.offsets,u=t.position,f=t.gpuAcceleration,p=t.adaptive,m=t.roundOffsets,g=t.isFixed,_=d.x,b=void 0===_?0:_,v=d.y,y=void 0===v?0:v,w="function"==typeof m?m({x:b,y}):{x:b,y};b=w.x,y=w.y;var E=d.hasOwnProperty("x"),A=d.hasOwnProperty("y"),T=r,C=n,O=window;if(p){var x=K(i),L="clientHeight",S="clientWidth";x===k(i)&&"static"!==z(x=q(i)).position&&"absolute"===u&&(L="scrollHeight",S="scrollWidth"),(l===n||(l===r||l===o)&&c===h)&&(C=s,y-=(g&&x===O&&O.visualViewport?O.visualViewport.height:x[L])-a.height,y*=f?1:-1),l!==r&&(l!==n&&l!==s||c!==h)||(T=o,b-=(g&&x===O&&O.visualViewport?O.visualViewport.width:x[S])-a.width,b*=f?1:-1)}var D,$=Object.assign({position:u},p&&tt),I=!0===m?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:M(i*s)/s||0,y:M(n*s)/s||0}}({x:b,y},k(i)):{x:b,y};return b=I.x,y=I.y,f?Object.assign({},$,((D={})[C]=A?"0":"",D[T]=E?"0":"",D.transform=(O.devicePixelRatio||1)<=1?"translate("+b+"px, "+y+"px)":"translate3d("+b+"px, "+y+"px, 0)",D)):Object.assign({},$,((e={})[C]=A?y+"px":"",e[T]=E?b+"px":"",e.transform="",e))}const it={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:I(e.placement),variation:Z(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,et(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,et(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var nt={passive:!0};const st={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=k(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,nt)})),a&&l.addEventListener("resize",i.update,nt),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,nt)})),a&&l.removeEventListener("resize",i.update,nt)}},data:{}};var ot={left:"right",right:"left",bottom:"top",top:"bottom"};function rt(t){return t.replace(/left|right|bottom|top/g,(function(t){return ot[t]}))}var at={start:"end",end:"start"};function lt(t){return t.replace(/start|end/g,(function(t){return at[t]}))}function ct(t){var e=k(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function ht(t){return H(q(t)).left+ct(t).scrollLeft}function dt(t){var e=z(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function ut(t){return["html","body","#document"].indexOf(x(t))>=0?t.ownerDocument.body:S(t)&&dt(t)?t:ut(V(t))}function ft(t,e){var i;void 0===e&&(e=[]);var n=ut(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=k(n),r=s?[o].concat(o.visualViewport||[],dt(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(ft(V(r)))}function pt(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function mt(t,e,i){return e===u?pt(function(t,e){var i=k(t),n=q(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=F();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+ht(t),y:l}}(t,i)):L(e)?function(t,e){var i=H(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):pt(function(t){var e,i=q(t),n=ct(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=N(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=N(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+ht(t),l=-n.scrollTop;return"rtl"===z(s||i).direction&&(a+=N(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(q(t)))}function gt(t){var e,i=t.reference,a=t.element,l=t.placement,d=l?I(l):null,u=l?Z(l):null,f=i.x+i.width/2-a.width/2,p=i.y+i.height/2-a.height/2;switch(d){case n:e={x:f,y:i.y-a.height};break;case s:e={x:f,y:i.y+i.height};break;case o:e={x:i.x+i.width,y:p};break;case r:e={x:i.x-a.width,y:p};break;default:e={x:i.x,y:i.y}}var m=d?Q(d):null;if(null!=m){var g="y"===m?"height":"width";switch(u){case c:e[m]=e[m]-(i[g]/2-a[g]/2);break;case h:e[m]=e[m]+(i[g]/2-a[g]/2)}}return e}function _t(t,e){void 0===e&&(e={});var i=e,r=i.placement,a=void 0===r?t.placement:r,c=i.strategy,h=void 0===c?t.strategy:c,m=i.boundary,g=void 0===m?d:m,_=i.rootBoundary,b=void 0===_?u:_,v=i.elementContext,y=void 0===v?f:v,w=i.altBoundary,E=void 0!==w&&w,A=i.padding,T=void 0===A?0:A,C=U("number"!=typeof T?T:G(T,l)),O=y===f?p:f,k=t.rects.popper,D=t.elements[E?O:y],$=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=ft(V(t)),i=["absolute","fixed"].indexOf(z(t).position)>=0&&S(t)?K(t):t;return L(i)?e.filter((function(t){return L(t)&&W(t,i)&&"body"!==x(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=mt(t,i,n);return e.top=N(s.top,e.top),e.right=P(s.right,e.right),e.bottom=P(s.bottom,e.bottom),e.left=N(s.left,e.left),e}),mt(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(L(D)?D:D.contextElement||q(t.elements.popper),g,b,h),I=H(t.elements.reference),M=gt({reference:I,element:k,strategy:"absolute",placement:a}),j=pt(Object.assign({},k,M)),F=y===f?j:I,B={top:$.top-F.top+C.top,bottom:F.bottom-$.bottom+C.bottom,left:$.left-F.left+C.left,right:F.right-$.right+C.right},R=t.modifiersData.offset;if(y===f&&R){var Y=R[a];Object.keys(B).forEach((function(t){var e=[o,s].indexOf(t)>=0?1:-1,i=[n,s].indexOf(t)>=0?"y":"x";B[t]+=Y[i]*e}))}return B}const bt={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,h=t.name;if(!e.modifiersData[h]._skip){for(var d=i.mainAxis,u=void 0===d||d,f=i.altAxis,p=void 0===f||f,_=i.fallbackPlacements,b=i.padding,v=i.boundary,y=i.rootBoundary,w=i.altBoundary,E=i.flipVariations,A=void 0===E||E,T=i.allowedAutoPlacements,C=e.options.placement,O=I(C),x=_||(O!==C&&A?function(t){if(I(t)===a)return[];var e=rt(t);return[lt(t),e,lt(e)]}(C):[rt(C)]),k=[C].concat(x).reduce((function(t,i){return t.concat(I(i)===a?function(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,c=i.allowedAutoPlacements,h=void 0===c?g:c,d=Z(n),u=d?a?m:m.filter((function(t){return Z(t)===d})):l,f=u.filter((function(t){return h.indexOf(t)>=0}));0===f.length&&(f=u);var p=f.reduce((function(e,i){return e[i]=_t(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[I(i)],e}),{});return Object.keys(p).sort((function(t,e){return p[t]-p[e]}))}(e,{placement:i,boundary:v,rootBoundary:y,padding:b,flipVariations:A,allowedAutoPlacements:T}):i)}),[]),L=e.rects.reference,S=e.rects.popper,D=new Map,$=!0,N=k[0],P=0;P=0,B=H?"width":"height",W=_t(e,{placement:M,boundary:v,rootBoundary:y,altBoundary:w,padding:b}),z=H?F?o:r:F?s:n;L[B]>S[B]&&(z=rt(z));var R=rt(z),q=[];if(u&&q.push(W[j]<=0),p&&q.push(W[z]<=0,W[R]<=0),q.every((function(t){return t}))){N=M,$=!1;break}D.set(M,q)}if($)for(var V=function(t){var e=k.find((function(e){var i=D.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return N=e,"break"},Y=A?3:1;Y>0&&"break"!==V(Y);Y--);e.placement!==N&&(e.modifiersData[h]._skip=!0,e.placement=N,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function vt(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function yt(t){return[n,o,s,r].some((function(e){return t[e]>=0}))}const wt={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=_t(e,{elementContext:"reference"}),a=_t(e,{altBoundary:!0}),l=vt(r,n),c=vt(a,s,o),h=yt(l),d=yt(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},Et={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,s=t.name,a=i.offset,l=void 0===a?[0,0]:a,c=g.reduce((function(t,i){return t[i]=function(t,e,i){var s=I(t),a=[r,n].indexOf(s)>=0?-1:1,l="function"==typeof i?i(Object.assign({},e,{placement:t})):i,c=l[0],h=l[1];return c=c||0,h=(h||0)*a,[r,o].indexOf(s)>=0?{x:h,y:c}:{x:c,y:h}}(i,e.rects,l),t}),{}),h=c[e.placement],d=h.x,u=h.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=d,e.modifiersData.popperOffsets.y+=u),e.modifiersData[s]=c}},At={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=gt({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},Tt={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,a=t.name,l=i.mainAxis,h=void 0===l||l,d=i.altAxis,u=void 0!==d&&d,f=i.boundary,p=i.rootBoundary,m=i.altBoundary,g=i.padding,_=i.tether,b=void 0===_||_,v=i.tetherOffset,y=void 0===v?0:v,w=_t(e,{boundary:f,rootBoundary:p,padding:g,altBoundary:m}),E=I(e.placement),A=Z(e.placement),T=!A,C=Q(E),O="x"===C?"y":"x",x=e.modifiersData.popperOffsets,k=e.rects.reference,L=e.rects.popper,S="function"==typeof y?y(Object.assign({},e.rects,{placement:e.placement})):y,D="number"==typeof S?{mainAxis:S,altAxis:S}:Object.assign({mainAxis:0,altAxis:0},S),$=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,M={x:0,y:0};if(x){if(h){var j,F="y"===C?n:r,H="y"===C?s:o,W="y"===C?"height":"width",z=x[C],R=z+w[F],q=z-w[H],V=b?-L[W]/2:0,Y=A===c?k[W]:L[W],U=A===c?-L[W]:-k[W],G=e.elements.arrow,J=b&&G?B(G):{width:0,height:0},tt=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},et=tt[F],it=tt[H],nt=X(0,k[W],J[W]),st=T?k[W]/2-V-nt-et-D.mainAxis:Y-nt-et-D.mainAxis,ot=T?-k[W]/2+V+nt+it+D.mainAxis:U+nt+it+D.mainAxis,rt=e.elements.arrow&&K(e.elements.arrow),at=rt?"y"===C?rt.clientTop||0:rt.clientLeft||0:0,lt=null!=(j=null==$?void 0:$[C])?j:0,ct=z+ot-lt,ht=X(b?P(R,z+st-lt-at):R,z,b?N(q,ct):q);x[C]=ht,M[C]=ht-z}if(u){var dt,ut="x"===C?n:r,ft="x"===C?s:o,pt=x[O],mt="y"===O?"height":"width",gt=pt+w[ut],bt=pt-w[ft],vt=-1!==[n,r].indexOf(E),yt=null!=(dt=null==$?void 0:$[O])?dt:0,wt=vt?gt:pt-k[mt]-L[mt]-yt+D.altAxis,Et=vt?pt+k[mt]+L[mt]-yt-D.altAxis:bt,At=b&&vt?function(t,e,i){var n=X(t,e,i);return n>i?i:n}(wt,pt,Et):X(b?wt:gt,pt,b?Et:bt);x[O]=At,M[O]=At-pt}e.modifiersData[a]=M}},requiresIfExists:["offset"]};function Ct(t,e,i){void 0===i&&(i=!1);var n,s,o=S(e),r=S(e)&&function(t){var e=t.getBoundingClientRect(),i=M(e.width)/t.offsetWidth||1,n=M(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=q(e),l=H(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==x(e)||dt(a))&&(c=(n=e)!==k(n)&&S(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:ct(n)),S(e)?((h=H(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=ht(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function Ot(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var xt={placement:"bottom",modifiers:[],strategy:"absolute"};function kt(){for(var t=arguments.length,e=new Array(t),i=0;iIt.has(t)&&It.get(t).get(e)||null,remove(t,e){if(!It.has(t))return;const i=It.get(t);i.delete(e),0===i.size&&It.delete(t)}},Pt="transitionend",Mt=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),jt=t=>{t.dispatchEvent(new Event(Pt))},Ft=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),Ht=t=>Ft(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(Mt(t)):null,Bt=t=>{if(!Ft(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},Wt=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),zt=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?zt(t.parentNode):null},Rt=()=>{},qt=t=>{t.offsetHeight},Vt=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,Yt=[],Kt=()=>"rtl"===document.documentElement.dir,Qt=t=>{var e;e=()=>{const e=Vt();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(Yt.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of Yt)t()})),Yt.push(e)):e()},Xt=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,Ut=(t,e,i=!0)=>{if(!i)return void Xt(t);const n=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let s=!1;const o=({target:i})=>{i===e&&(s=!0,e.removeEventListener(Pt,o),Xt(t))};e.addEventListener(Pt,o),setTimeout((()=>{s||jt(e)}),n)},Gt=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},Jt=/[^.]*(?=\..*)\.|.*/,Zt=/\..*/,te=/::\d+$/,ee={};let ie=1;const ne={mouseenter:"mouseover",mouseleave:"mouseout"},se=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function oe(t,e){return e&&`${e}::${ie++}`||t.uidEvent||ie++}function re(t){const e=oe(t);return t.uidEvent=e,ee[e]=ee[e]||{},ee[e]}function ae(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function le(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=ue(t);return se.has(o)||(o=t),[n,s,o]}function ce(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=le(e,i,n);if(e in ne){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=re(t),c=l[a]||(l[a]={}),h=ae(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=oe(r,e.replace(Jt,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return pe(s,{delegateTarget:r}),n.oneOff&&fe.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return pe(n,{delegateTarget:t}),i.oneOff&&fe.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function he(t,e,i,n,s){const o=ae(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function de(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&he(t,e,i,r.callable,r.delegationSelector)}function ue(t){return t=t.replace(Zt,""),ne[t]||t}const fe={on(t,e,i,n){ce(t,e,i,n,!1)},one(t,e,i,n){ce(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=le(e,i,n),a=r!==e,l=re(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))de(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(te,"");a&&!e.includes(s)||he(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;he(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=Vt();let s=null,o=!0,r=!0,a=!1;e!==ue(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=pe(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function pe(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function me(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function ge(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const _e={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${ge(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${ge(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=me(t.dataset[n])}return e},getDataAttribute:(t,e)=>me(t.getAttribute(`data-bs-${ge(e)}`))};class be{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=Ft(e)?_e.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...Ft(e)?_e.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],o=Ft(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(o))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${o}" but expected type "${s}".`)}var i}}class ve extends be{constructor(t,e){super(),(t=Ht(t))&&(this._element=t,this._config=this._getConfig(e),Nt.set(this._element,this.constructor.DATA_KEY,this))}dispose(){Nt.remove(this._element,this.constructor.DATA_KEY),fe.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){Ut(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return Nt.get(Ht(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.2"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const ye=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?Mt(i.trim()):null}return e},we={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!Wt(t)&&Bt(t)))},getSelectorFromElement(t){const e=ye(t);return e&&we.findOne(e)?e:null},getElementFromSelector(t){const e=ye(t);return e?we.findOne(e):null},getMultipleElementsFromSelector(t){const e=ye(t);return e?we.find(e):[]}},Ee=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;fe.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),Wt(this))return;const s=we.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},Ae=".bs.alert",Te=`close${Ae}`,Ce=`closed${Ae}`;class Oe extends ve{static get NAME(){return"alert"}close(){if(fe.trigger(this._element,Te).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),fe.trigger(this._element,Ce),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Oe.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}Ee(Oe,"close"),Qt(Oe);const xe='[data-bs-toggle="button"]';class ke extends ve{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=ke.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}fe.on(document,"click.bs.button.data-api",xe,(t=>{t.preventDefault();const e=t.target.closest(xe);ke.getOrCreateInstance(e).toggle()})),Qt(ke);const Le=".bs.swipe",Se=`touchstart${Le}`,De=`touchmove${Le}`,$e=`touchend${Le}`,Ie=`pointerdown${Le}`,Ne=`pointerup${Le}`,Pe={endCallback:null,leftCallback:null,rightCallback:null},Me={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class je extends be{constructor(t,e){super(),this._element=t,t&&je.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return Pe}static get DefaultType(){return Me}static get NAME(){return"swipe"}dispose(){fe.off(this._element,Le)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),Xt(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&Xt(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(fe.on(this._element,Ie,(t=>this._start(t))),fe.on(this._element,Ne,(t=>this._end(t))),this._element.classList.add("pointer-event")):(fe.on(this._element,Se,(t=>this._start(t))),fe.on(this._element,De,(t=>this._move(t))),fe.on(this._element,$e,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const Fe=".bs.carousel",He=".data-api",Be="next",We="prev",ze="left",Re="right",qe=`slide${Fe}`,Ve=`slid${Fe}`,Ye=`keydown${Fe}`,Ke=`mouseenter${Fe}`,Qe=`mouseleave${Fe}`,Xe=`dragstart${Fe}`,Ue=`load${Fe}${He}`,Ge=`click${Fe}${He}`,Je="carousel",Ze="active",ti=".active",ei=".carousel-item",ii=ti+ei,ni={ArrowLeft:Re,ArrowRight:ze},si={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},oi={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class ri extends ve{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=we.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===Je&&this.cycle()}static get Default(){return si}static get DefaultType(){return oi}static get NAME(){return"carousel"}next(){this._slide(Be)}nextWhenVisible(){!document.hidden&&Bt(this._element)&&this.next()}prev(){this._slide(We)}pause(){this._isSliding&&jt(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?fe.one(this._element,Ve,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void fe.one(this._element,Ve,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?Be:We;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&fe.on(this._element,Ye,(t=>this._keydown(t))),"hover"===this._config.pause&&(fe.on(this._element,Ke,(()=>this.pause())),fe.on(this._element,Qe,(()=>this._maybeEnableCycle()))),this._config.touch&&je.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of we.find(".carousel-item img",this._element))fe.on(t,Xe,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(ze)),rightCallback:()=>this._slide(this._directionToOrder(Re)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new je(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=ni[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=we.findOne(ti,this._indicatorsElement);e.classList.remove(Ze),e.removeAttribute("aria-current");const i=we.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(Ze),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===Be,s=e||Gt(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>fe.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(qe).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),qt(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(Ze),i.classList.remove(Ze,c,l),this._isSliding=!1,r(Ve)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return we.findOne(ii,this._element)}_getItems(){return we.find(ei,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return Kt()?t===ze?We:Be:t===ze?Be:We}_orderToDirection(t){return Kt()?t===We?ze:Re:t===We?Re:ze}static jQueryInterface(t){return this.each((function(){const e=ri.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}fe.on(document,Ge,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=we.getElementFromSelector(this);if(!e||!e.classList.contains(Je))return;t.preventDefault();const i=ri.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===_e.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),fe.on(window,Ue,(()=>{const t=we.find('[data-bs-ride="carousel"]');for(const e of t)ri.getOrCreateInstance(e)})),Qt(ri);const ai=".bs.collapse",li=`show${ai}`,ci=`shown${ai}`,hi=`hide${ai}`,di=`hidden${ai}`,ui=`click${ai}.data-api`,fi="show",pi="collapse",mi="collapsing",gi=`:scope .${pi} .${pi}`,_i='[data-bs-toggle="collapse"]',bi={parent:null,toggle:!0},vi={parent:"(null|element)",toggle:"boolean"};class yi extends ve{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=we.find(_i);for(const t of i){const e=we.getSelectorFromElement(t),i=we.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return bi}static get DefaultType(){return vi}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>yi.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(fe.trigger(this._element,li).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(pi),this._element.classList.add(mi),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(mi),this._element.classList.add(pi,fi),this._element.style[e]="",fe.trigger(this._element,ci)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(fe.trigger(this._element,hi).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,qt(this._element),this._element.classList.add(mi),this._element.classList.remove(pi,fi);for(const t of this._triggerArray){const e=we.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(mi),this._element.classList.add(pi),fe.trigger(this._element,di)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(fi)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=Ht(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(_i);for(const e of t){const t=we.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=we.find(gi,this._config.parent);return we.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=yi.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}fe.on(document,ui,_i,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of we.getMultipleElementsFromSelector(this))yi.getOrCreateInstance(t,{toggle:!1}).toggle()})),Qt(yi);const wi="dropdown",Ei=".bs.dropdown",Ai=".data-api",Ti="ArrowUp",Ci="ArrowDown",Oi=`hide${Ei}`,xi=`hidden${Ei}`,ki=`show${Ei}`,Li=`shown${Ei}`,Si=`click${Ei}${Ai}`,Di=`keydown${Ei}${Ai}`,$i=`keyup${Ei}${Ai}`,Ii="show",Ni='[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)',Pi=`${Ni}.${Ii}`,Mi=".dropdown-menu",ji=Kt()?"top-end":"top-start",Fi=Kt()?"top-start":"top-end",Hi=Kt()?"bottom-end":"bottom-start",Bi=Kt()?"bottom-start":"bottom-end",Wi=Kt()?"left-start":"right-start",zi=Kt()?"right-start":"left-start",Ri={autoClose:!0,boundary:"clippingParents",display:"dynamic",offset:[0,2],popperConfig:null,reference:"toggle"},qi={autoClose:"(boolean|string)",boundary:"(string|element)",display:"string",offset:"(array|string|function)",popperConfig:"(null|object|function)",reference:"(string|element|object)"};class Vi extends ve{constructor(t,e){super(t,e),this._popper=null,this._parent=this._element.parentNode,this._menu=we.next(this._element,Mi)[0]||we.prev(this._element,Mi)[0]||we.findOne(Mi,this._parent),this._inNavbar=this._detectNavbar()}static get Default(){return Ri}static get DefaultType(){return qi}static get NAME(){return wi}toggle(){return this._isShown()?this.hide():this.show()}show(){if(Wt(this._element)||this._isShown())return;const t={relatedTarget:this._element};if(!fe.trigger(this._element,ki,t).defaultPrevented){if(this._createPopper(),"ontouchstart"in document.documentElement&&!this._parent.closest(".navbar-nav"))for(const t of[].concat(...document.body.children))fe.on(t,"mouseover",Rt);this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(Ii),this._element.classList.add(Ii),fe.trigger(this._element,Li,t)}}hide(){if(Wt(this._element)||!this._isShown())return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(t){if(!fe.trigger(this._element,Oi,t).defaultPrevented){if("ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))fe.off(t,"mouseover",Rt);this._popper&&this._popper.destroy(),this._menu.classList.remove(Ii),this._element.classList.remove(Ii),this._element.setAttribute("aria-expanded","false"),_e.removeDataAttribute(this._menu,"popper"),fe.trigger(this._element,xi,t)}}_getConfig(t){if("object"==typeof(t=super._getConfig(t)).reference&&!Ft(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError(`${wi.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return t}_createPopper(){if(void 0===e)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let t=this._element;"parent"===this._config.reference?t=this._parent:Ft(this._config.reference)?t=Ht(this._config.reference):"object"==typeof this._config.reference&&(t=this._config.reference);const i=this._getPopperConfig();this._popper=Dt(t,this._menu,i)}_isShown(){return this._menu.classList.contains(Ii)}_getPlacement(){const t=this._parent;if(t.classList.contains("dropend"))return Wi;if(t.classList.contains("dropstart"))return zi;if(t.classList.contains("dropup-center"))return"top";if(t.classList.contains("dropdown-center"))return"bottom";const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?Fi:ji:e?Bi:Hi}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(_e.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...Xt(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=we.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>Bt(t)));i.length&&Gt(i,e,t===Ci,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=Vi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=we.find(Pi);for(const i of e){const e=Vi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ti,Ci].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ni)?this:we.prev(this,Ni)[0]||we.next(this,Ni)[0]||we.findOne(Ni,t.delegateTarget.parentNode),o=Vi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}fe.on(document,Di,Ni,Vi.dataApiKeydownHandler),fe.on(document,Di,Mi,Vi.dataApiKeydownHandler),fe.on(document,Si,Vi.clearMenus),fe.on(document,$i,Vi.clearMenus),fe.on(document,Si,Ni,(function(t){t.preventDefault(),Vi.getOrCreateInstance(this).toggle()})),Qt(Vi);const Yi="backdrop",Ki="show",Qi=`mousedown.bs.${Yi}`,Xi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Ui={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Gi extends be{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Xi}static get DefaultType(){return Ui}static get NAME(){return Yi}show(t){if(!this._config.isVisible)return void Xt(t);this._append();const e=this._getElement();this._config.isAnimated&&qt(e),e.classList.add(Ki),this._emulateAnimation((()=>{Xt(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Ki),this._emulateAnimation((()=>{this.dispose(),Xt(t)}))):Xt(t)}dispose(){this._isAppended&&(fe.off(this._element,Qi),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=Ht(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),fe.on(t,Qi,(()=>{Xt(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){Ut(t,this._getElement(),this._config.isAnimated)}}const Ji=".bs.focustrap",Zi=`focusin${Ji}`,tn=`keydown.tab${Ji}`,en="backward",nn={autofocus:!0,trapElement:null},sn={autofocus:"boolean",trapElement:"element"};class on extends be{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return nn}static get DefaultType(){return sn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),fe.off(document,Ji),fe.on(document,Zi,(t=>this._handleFocusin(t))),fe.on(document,tn,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,fe.off(document,Ji))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=we.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===en?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?en:"forward")}}const rn=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",an=".sticky-top",ln="padding-right",cn="margin-right";class hn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,ln,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e+t)),this._setElementAttributes(an,cn,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,ln),this._resetElementAttributes(rn,ln),this._resetElementAttributes(an,cn)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&_e.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=_e.getDataAttribute(t,e);null!==i?(_e.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(Ft(t))e(t);else for(const i of we.find(t,this._element))e(i)}}const dn=".bs.modal",un=`hide${dn}`,fn=`hidePrevented${dn}`,pn=`hidden${dn}`,mn=`show${dn}`,gn=`shown${dn}`,_n=`resize${dn}`,bn=`click.dismiss${dn}`,vn=`mousedown.dismiss${dn}`,yn=`keydown.dismiss${dn}`,wn=`click${dn}.data-api`,En="modal-open",An="show",Tn="modal-static",Cn={backdrop:!0,focus:!0,keyboard:!0},On={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class xn extends ve{constructor(t,e){super(t,e),this._dialog=we.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new hn,this._addEventListeners()}static get Default(){return Cn}static get DefaultType(){return On}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||fe.trigger(this._element,mn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(En),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(fe.trigger(this._element,un).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(An),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){fe.off(window,dn),fe.off(this._dialog,dn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Gi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new on({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=we.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),qt(this._element),this._element.classList.add(An),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,fe.trigger(this._element,gn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){fe.on(this._element,yn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),fe.on(window,_n,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),fe.on(this._element,vn,(t=>{fe.one(this._element,bn,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(En),this._resetAdjustments(),this._scrollBar.reset(),fe.trigger(this._element,pn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(fe.trigger(this._element,fn).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(Tn)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(Tn),this._queueCallback((()=>{this._element.classList.remove(Tn),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=Kt()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=Kt()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=xn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}fe.on(document,wn,'[data-bs-toggle="modal"]',(function(t){const e=we.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),fe.one(e,mn,(t=>{t.defaultPrevented||fe.one(e,pn,(()=>{Bt(this)&&this.focus()}))}));const i=we.findOne(".modal.show");i&&xn.getInstance(i).hide(),xn.getOrCreateInstance(e).toggle(this)})),Ee(xn),Qt(xn);const kn=".bs.offcanvas",Ln=".data-api",Sn=`load${kn}${Ln}`,Dn="show",$n="showing",In="hiding",Nn=".offcanvas.show",Pn=`show${kn}`,Mn=`shown${kn}`,jn=`hide${kn}`,Fn=`hidePrevented${kn}`,Hn=`hidden${kn}`,Bn=`resize${kn}`,Wn=`click${kn}${Ln}`,zn=`keydown.dismiss${kn}`,Rn={backdrop:!0,keyboard:!0,scroll:!1},qn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class Vn extends ve{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Rn}static get DefaultType(){return qn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||fe.trigger(this._element,Pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new hn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add($n),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Dn),this._element.classList.remove($n),fe.trigger(this._element,Mn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(fe.trigger(this._element,jn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(In),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Dn,In),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new hn).reset(),fe.trigger(this._element,Hn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Gi({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():fe.trigger(this._element,Fn)}:null})}_initializeFocusTrap(){return new on({trapElement:this._element})}_addEventListeners(){fe.on(this._element,zn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():fe.trigger(this._element,Fn))}))}static jQueryInterface(t){return this.each((function(){const e=Vn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}fe.on(document,Wn,'[data-bs-toggle="offcanvas"]',(function(t){const e=we.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),Wt(this))return;fe.one(e,Hn,(()=>{Bt(this)&&this.focus()}));const i=we.findOne(Nn);i&&i!==e&&Vn.getInstance(i).hide(),Vn.getOrCreateInstance(e).toggle(this)})),fe.on(window,Sn,(()=>{for(const t of we.find(Nn))Vn.getOrCreateInstance(t).show()})),fe.on(window,Bn,(()=>{for(const t of we.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&Vn.getOrCreateInstance(t).hide()})),Ee(Vn),Qt(Vn);const Yn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Qn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Kn.has(i)||Boolean(Qn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Un={allowList:Yn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"

"},Gn={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Jn={entry:"(string|element|function|null)",selector:"(string|element)"};class Zn extends be{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Un}static get DefaultType(){return Gn}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Jn)}_setContent(t,e,i){const n=we.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?Ft(e)?this._putElementInTemplate(Ht(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Xn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return Xt(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const ts=new Set(["sanitize","allowList","sanitizeFn"]),es="fade",is="show",ns=".modal",ss="hide.bs.modal",os="hover",rs="focus",as={AUTO:"auto",TOP:"top",RIGHT:Kt()?"left":"right",BOTTOM:"bottom",LEFT:Kt()?"right":"left"},ls={allowList:Yn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},cs={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class hs extends ve{constructor(t,i){if(void 0===e)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,i),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return ls}static get DefaultType(){return cs}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),fe.off(this._element.closest(ns),ss,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=fe.trigger(this._element,this.constructor.eventName("show")),e=(zt(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),fe.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(is),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))fe.on(t,"mouseover",Rt);this._queueCallback((()=>{fe.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!fe.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(is),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))fe.off(t,"mouseover",Rt);this._activeTrigger.click=!1,this._activeTrigger[rs]=!1,this._activeTrigger[os]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),fe.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(es,is),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(es),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Zn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(es)}_isShown(){return this.tip&&this.tip.classList.contains(is)}_createPopper(t){const e=Xt(this._config.placement,[this,t,this._element]),i=as[e.toUpperCase()];return Dt(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return Xt(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...Xt(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)fe.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===os?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===os?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");fe.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?rs:os]=!0,e._enter()})),fe.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?rs:os]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},fe.on(this._element.closest(ns),ss,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=_e.getDataAttributes(this._element);for(const t of Object.keys(e))ts.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:Ht(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=hs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}Qt(hs);const ds={...hs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},us={...hs.DefaultType,content:"(null|string|element|function)"};class fs extends hs{static get Default(){return ds}static get DefaultType(){return us}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=fs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}Qt(fs);const ps=".bs.scrollspy",ms=`activate${ps}`,gs=`click${ps}`,_s=`load${ps}.data-api`,bs="active",vs="[href]",ys=".nav-link",ws=`${ys}, .nav-item > ${ys}, .list-group-item`,Es={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},As={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Ts extends ve{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return Es}static get DefaultType(){return As}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=Ht(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(fe.off(this._config.target,gs),fe.on(this._config.target,gs,vs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=we.find(vs,this._config.target);for(const e of t){if(!e.hash||Wt(e))continue;const t=we.findOne(decodeURI(e.hash),this._element);Bt(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(bs),this._activateParents(t),fe.trigger(this._element,ms,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))we.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(bs);else for(const e of we.parents(t,".nav, .list-group"))for(const t of we.prev(e,ws))t.classList.add(bs)}_clearActiveClass(t){t.classList.remove(bs);const e=we.find(`${vs}.${bs}`,t);for(const t of e)t.classList.remove(bs)}static jQueryInterface(t){return this.each((function(){const e=Ts.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}fe.on(window,_s,(()=>{for(const t of we.find('[data-bs-spy="scroll"]'))Ts.getOrCreateInstance(t)})),Qt(Ts);const Cs=".bs.tab",Os=`hide${Cs}`,xs=`hidden${Cs}`,ks=`show${Cs}`,Ls=`shown${Cs}`,Ss=`click${Cs}`,Ds=`keydown${Cs}`,$s=`load${Cs}`,Is="ArrowLeft",Ns="ArrowRight",Ps="ArrowUp",Ms="ArrowDown",js="Home",Fs="End",Hs="active",Bs="fade",Ws="show",zs=".dropdown-toggle",Rs=`:not(${zs})`,qs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Vs=`.nav-link${Rs}, .list-group-item${Rs}, [role="tab"]${Rs}, ${qs}`,Ys=`.${Hs}[data-bs-toggle="tab"], .${Hs}[data-bs-toggle="pill"], .${Hs}[data-bs-toggle="list"]`;class Ks extends ve{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),fe.on(this._element,Ds,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?fe.trigger(e,Os,{relatedTarget:t}):null;fe.trigger(t,ks,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Hs),this._activate(we.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),fe.trigger(t,Ls,{relatedTarget:e})):t.classList.add(Ws)}),t,t.classList.contains(Bs)))}_deactivate(t,e){t&&(t.classList.remove(Hs),t.blur(),this._deactivate(we.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),fe.trigger(t,xs,{relatedTarget:e})):t.classList.remove(Ws)}),t,t.classList.contains(Bs)))}_keydown(t){if(![Is,Ns,Ps,Ms,js,Fs].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!Wt(t)));let i;if([js,Fs].includes(t.key))i=e[t.key===js?0:e.length-1];else{const n=[Ns,Ms].includes(t.key);i=Gt(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Ks.getOrCreateInstance(i).show())}_getChildren(){return we.find(Vs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=we.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=we.findOne(t,i);s&&s.classList.toggle(n,e)};n(zs,Hs),n(".dropdown-menu",Ws),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Hs)}_getInnerElement(t){return t.matches(Vs)?t:we.findOne(Vs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Ks.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}fe.on(document,Ss,qs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),Wt(this)||Ks.getOrCreateInstance(this).show()})),fe.on(window,$s,(()=>{for(const t of we.find(Ys))Ks.getOrCreateInstance(t)})),Qt(Ks);const Qs=".bs.toast",Xs=`mouseover${Qs}`,Us=`mouseout${Qs}`,Gs=`focusin${Qs}`,Js=`focusout${Qs}`,Zs=`hide${Qs}`,to=`hidden${Qs}`,eo=`show${Qs}`,io=`shown${Qs}`,no="hide",so="show",oo="showing",ro={animation:"boolean",autohide:"boolean",delay:"number"},ao={animation:!0,autohide:!0,delay:5e3};class lo extends ve{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return ao}static get DefaultType(){return ro}static get NAME(){return"toast"}show(){fe.trigger(this._element,eo).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(no),qt(this._element),this._element.classList.add(so,oo),this._queueCallback((()=>{this._element.classList.remove(oo),fe.trigger(this._element,io),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(fe.trigger(this._element,Zs).defaultPrevented||(this._element.classList.add(oo),this._queueCallback((()=>{this._element.classList.add(no),this._element.classList.remove(oo,so),fe.trigger(this._element,to)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(so),super.dispose()}isShown(){return this._element.classList.contains(so)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){fe.on(this._element,Xs,(t=>this._onInteraction(t,!0))),fe.on(this._element,Us,(t=>this._onInteraction(t,!1))),fe.on(this._element,Gs,(t=>this._onInteraction(t,!0))),fe.on(this._element,Js,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=lo.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}function co(t){"loading"!=document.readyState?t():document.addEventListener("DOMContentLoaded",t)}Ee(lo),Qt(lo),co((function(){[].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')).map((function(t){return new hs(t,{delay:{show:500,hide:100}})}))})),co((function(){document.getElementById("pst-back-to-top").addEventListener("click",(function(){document.body.scrollTop=0,document.documentElement.scrollTop=0}))})),co((function(){var t=document.getElementById("pst-back-to-top"),e=document.getElementsByClassName("bd-header")[0].getBoundingClientRect();window.addEventListener("scroll",(function(){this.oldScroll>this.scrollY&&this.scrollY>e.bottom?t.style.display="block":t.style.display="none",this.oldScroll=this.scrollY}))})),window.bootstrap=i})(); +//# sourceMappingURL=bootstrap.js.map \ No newline at end of file diff --git a/_static/scripts/bootstrap.js.LICENSE.txt b/_static/scripts/bootstrap.js.LICENSE.txt new file mode 100644 index 00000000..10f979d0 --- /dev/null +++ b/_static/scripts/bootstrap.js.LICENSE.txt @@ -0,0 +1,5 @@ +/*! + * Bootstrap v5.3.2 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ diff --git a/_static/scripts/bootstrap.js.map b/_static/scripts/bootstrap.js.map new file mode 100644 index 00000000..64e212b1 --- /dev/null +++ b/_static/scripts/bootstrap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scripts/bootstrap.js","mappings":"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","sources":["webpack://pydata_sphinx_theme/webpack/bootstrap","webpack://pydata_sphinx_theme/webpack/runtime/define property getters","webpack://pydata_sphinx_theme/webpack/runtime/hasOwnProperty shorthand","webpack://pydata_sphinx_theme/webpack/runtime/make namespace object","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/enums.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getWindow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/applyStyles.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getBasePlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/math.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/userAgent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/contains.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/isTableElement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getParentNode.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/within.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/mergePaddingObject.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getFreshSideObject.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/expandToHashMap.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/arrow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getVariation.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/computeStyles.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/eventListeners.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getOppositePlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/rectToClientRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/computeOffsets.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/detectOverflow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/flip.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/hide.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/offset.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/popperOffsets.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/modifiers/preventOverflow.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/getAltAxis.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/orderModifiers.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/createPopper.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/debounce.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/utils/mergeByName.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/popper.js","webpack://pydata_sphinx_theme/./node_modules/@popperjs/core/lib/popper-lite.js","webpack://pydata_sphinx_theme/./node_modules/bootstrap/dist/js/bootstrap.esm.js","webpack://pydata_sphinx_theme/./src/pydata_sphinx_theme/assets/scripts/mixin.js","webpack://pydata_sphinx_theme/./src/pydata_sphinx_theme/assets/scripts/bootstrap.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export var top = 'top';\nexport var bottom = 'bottom';\nexport var right = 'right';\nexport var left = 'left';\nexport var auto = 'auto';\nexport var basePlacements = [top, bottom, right, left];\nexport var start = 'start';\nexport var end = 'end';\nexport var clippingParents = 'clippingParents';\nexport var viewport = 'viewport';\nexport var popper = 'popper';\nexport var reference = 'reference';\nexport var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {\n return acc.concat([placement + \"-\" + start, placement + \"-\" + end]);\n}, []);\nexport var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {\n return acc.concat([placement, placement + \"-\" + start, placement + \"-\" + end]);\n}, []); // modifiers that need to read the DOM\n\nexport var beforeRead = 'beforeRead';\nexport var read = 'read';\nexport var afterRead = 'afterRead'; // pure-logic modifiers\n\nexport var beforeMain = 'beforeMain';\nexport var main = 'main';\nexport var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)\n\nexport var beforeWrite = 'beforeWrite';\nexport var write = 'write';\nexport var afterWrite = 'afterWrite';\nexport var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];","export default function getNodeName(element) {\n return element ? (element.nodeName || '').toLowerCase() : null;\n}","export default function getWindow(node) {\n if (node == null) {\n return window;\n }\n\n if (node.toString() !== '[object Window]') {\n var ownerDocument = node.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView || window : window;\n }\n\n return node;\n}","import getWindow from \"./getWindow.js\";\n\nfunction isElement(node) {\n var OwnElement = getWindow(node).Element;\n return node instanceof OwnElement || node instanceof Element;\n}\n\nfunction isHTMLElement(node) {\n var OwnElement = getWindow(node).HTMLElement;\n return node instanceof OwnElement || node instanceof HTMLElement;\n}\n\nfunction isShadowRoot(node) {\n // IE 11 has no ShadowRoot\n if (typeof ShadowRoot === 'undefined') {\n return false;\n }\n\n var OwnElement = getWindow(node).ShadowRoot;\n return node instanceof OwnElement || node instanceof ShadowRoot;\n}\n\nexport { isElement, isHTMLElement, isShadowRoot };","import getNodeName from \"../dom-utils/getNodeName.js\";\nimport { isHTMLElement } from \"../dom-utils/instanceOf.js\"; // This modifier takes the styles prepared by the `computeStyles` modifier\n// and applies them to the HTMLElements such as popper and arrow\n\nfunction applyStyles(_ref) {\n var state = _ref.state;\n Object.keys(state.elements).forEach(function (name) {\n var style = state.styles[name] || {};\n var attributes = state.attributes[name] || {};\n var element = state.elements[name]; // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n } // Flow doesn't support to extend this property, but it's the most\n // effective way to apply styles to an HTMLElement\n // $FlowFixMe[cannot-write]\n\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (name) {\n var value = attributes[name];\n\n if (value === false) {\n element.removeAttribute(name);\n } else {\n element.setAttribute(name, value === true ? '' : value);\n }\n });\n });\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state;\n var initialStyles = {\n popper: {\n position: state.options.strategy,\n left: '0',\n top: '0',\n margin: '0'\n },\n arrow: {\n position: 'absolute'\n },\n reference: {}\n };\n Object.assign(state.elements.popper.style, initialStyles.popper);\n state.styles = initialStyles;\n\n if (state.elements.arrow) {\n Object.assign(state.elements.arrow.style, initialStyles.arrow);\n }\n\n return function () {\n Object.keys(state.elements).forEach(function (name) {\n var element = state.elements[name];\n var attributes = state.attributes[name] || {};\n var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them\n\n var style = styleProperties.reduce(function (style, property) {\n style[property] = '';\n return style;\n }, {}); // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n }\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (attribute) {\n element.removeAttribute(attribute);\n });\n });\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'applyStyles',\n enabled: true,\n phase: 'write',\n fn: applyStyles,\n effect: effect,\n requires: ['computeStyles']\n};","import { auto } from \"../enums.js\";\nexport default function getBasePlacement(placement) {\n return placement.split('-')[0];\n}","export var max = Math.max;\nexport var min = Math.min;\nexport var round = Math.round;","export default function getUAString() {\n var uaData = navigator.userAgentData;\n\n if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {\n return uaData.brands.map(function (item) {\n return item.brand + \"/\" + item.version;\n }).join(' ');\n }\n\n return navigator.userAgent;\n}","import getUAString from \"../utils/userAgent.js\";\nexport default function isLayoutViewport() {\n return !/^((?!chrome|android).)*safari/i.test(getUAString());\n}","import { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport { round } from \"../utils/math.js\";\nimport getWindow from \"./getWindow.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getBoundingClientRect(element, includeScale, isFixedStrategy) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n\n var clientRect = element.getBoundingClientRect();\n var scaleX = 1;\n var scaleY = 1;\n\n if (includeScale && isHTMLElement(element)) {\n scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;\n scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;\n }\n\n var _ref = isElement(element) ? getWindow(element) : window,\n visualViewport = _ref.visualViewport;\n\n var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;\n var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;\n var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;\n var width = clientRect.width / scaleX;\n var height = clientRect.height / scaleY;\n return {\n width: width,\n height: height,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x,\n x: x,\n y: y\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\"; // Returns the layout rect of an element relative to its offsetParent. Layout\n// means it doesn't take into account transforms.\n\nexport default function getLayoutRect(element) {\n var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.\n // Fixes https://github.com/popperjs/popper-core/issues/1223\n\n var width = element.offsetWidth;\n var height = element.offsetHeight;\n\n if (Math.abs(clientRect.width - width) <= 1) {\n width = clientRect.width;\n }\n\n if (Math.abs(clientRect.height - height) <= 1) {\n height = clientRect.height;\n }\n\n return {\n x: element.offsetLeft,\n y: element.offsetTop,\n width: width,\n height: height\n };\n}","import { isShadowRoot } from \"./instanceOf.js\";\nexport default function contains(parent, child) {\n var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method\n\n if (parent.contains(child)) {\n return true;\n } // then fallback to custom implementation with Shadow DOM support\n else if (rootNode && isShadowRoot(rootNode)) {\n var next = child;\n\n do {\n if (next && parent.isSameNode(next)) {\n return true;\n } // $FlowFixMe[prop-missing]: need a better way to handle this...\n\n\n next = next.parentNode || next.host;\n } while (next);\n } // Give up, the result is false\n\n\n return false;\n}","import getWindow from \"./getWindow.js\";\nexport default function getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}","import getNodeName from \"./getNodeName.js\";\nexport default function isTableElement(element) {\n return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;\n}","import { isElement } from \"./instanceOf.js\";\nexport default function getDocumentElement(element) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]\n element.document) || window.document).documentElement;\n}","import getNodeName from \"./getNodeName.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport { isShadowRoot } from \"./instanceOf.js\";\nexport default function getParentNode(element) {\n if (getNodeName(element) === 'html') {\n return element;\n }\n\n return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle\n // $FlowFixMe[incompatible-return]\n // $FlowFixMe[prop-missing]\n element.assignedSlot || // step into the shadow DOM of the parent of a slotted node\n element.parentNode || ( // DOM Element detected\n isShadowRoot(element) ? element.host : null) || // ShadowRoot detected\n // $FlowFixMe[incompatible-call]: HTMLElement is a Node\n getDocumentElement(element) // fallback\n\n );\n}","import getWindow from \"./getWindow.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isHTMLElement, isShadowRoot } from \"./instanceOf.js\";\nimport isTableElement from \"./isTableElement.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getUAString from \"../utils/userAgent.js\";\n\nfunction getTrueOffsetParent(element) {\n if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837\n getComputedStyle(element).position === 'fixed') {\n return null;\n }\n\n return element.offsetParent;\n} // `.offsetParent` reports `null` for fixed elements, while absolute elements\n// return the containing block\n\n\nfunction getContainingBlock(element) {\n var isFirefox = /firefox/i.test(getUAString());\n var isIE = /Trident/i.test(getUAString());\n\n if (isIE && isHTMLElement(element)) {\n // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport\n var elementCss = getComputedStyle(element);\n\n if (elementCss.position === 'fixed') {\n return null;\n }\n }\n\n var currentNode = getParentNode(element);\n\n if (isShadowRoot(currentNode)) {\n currentNode = currentNode.host;\n }\n\n while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {\n var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that\n // create a containing block.\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n\n if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {\n return currentNode;\n } else {\n currentNode = currentNode.parentNode;\n }\n }\n\n return null;\n} // Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\n\n\nexport default function getOffsetParent(element) {\n var window = getWindow(element);\n var offsetParent = getTrueOffsetParent(element);\n\n while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {\n offsetParent = getTrueOffsetParent(offsetParent);\n }\n\n if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {\n return window;\n }\n\n return offsetParent || getContainingBlock(element) || window;\n}","export default function getMainAxisFromPlacement(placement) {\n return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';\n}","import { max as mathMax, min as mathMin } from \"./math.js\";\nexport function within(min, value, max) {\n return mathMax(min, mathMin(value, max));\n}\nexport function withinMaxClamp(min, value, max) {\n var v = within(min, value, max);\n return v > max ? max : v;\n}","import getFreshSideObject from \"./getFreshSideObject.js\";\nexport default function mergePaddingObject(paddingObject) {\n return Object.assign({}, getFreshSideObject(), paddingObject);\n}","export default function getFreshSideObject() {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n}","export default function expandToHashMap(value, keys) {\n return keys.reduce(function (hashMap, key) {\n hashMap[key] = value;\n return hashMap;\n }, {});\n}","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport contains from \"../dom-utils/contains.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport { within } from \"../utils/within.js\";\nimport mergePaddingObject from \"../utils/mergePaddingObject.js\";\nimport expandToHashMap from \"../utils/expandToHashMap.js\";\nimport { left, right, basePlacements, top, bottom } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar toPaddingObject = function toPaddingObject(padding, state) {\n padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {\n placement: state.placement\n })) : padding;\n return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n};\n\nfunction arrow(_ref) {\n var _state$modifiersData$;\n\n var state = _ref.state,\n name = _ref.name,\n options = _ref.options;\n var arrowElement = state.elements.arrow;\n var popperOffsets = state.modifiersData.popperOffsets;\n var basePlacement = getBasePlacement(state.placement);\n var axis = getMainAxisFromPlacement(basePlacement);\n var isVertical = [left, right].indexOf(basePlacement) >= 0;\n var len = isVertical ? 'height' : 'width';\n\n if (!arrowElement || !popperOffsets) {\n return;\n }\n\n var paddingObject = toPaddingObject(options.padding, state);\n var arrowRect = getLayoutRect(arrowElement);\n var minProp = axis === 'y' ? top : left;\n var maxProp = axis === 'y' ? bottom : right;\n var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];\n var startDiff = popperOffsets[axis] - state.rects.reference[axis];\n var arrowOffsetParent = getOffsetParent(arrowElement);\n var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;\n var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is\n // outside of the popper bounds\n\n var min = paddingObject[minProp];\n var max = clientSize - arrowRect[len] - paddingObject[maxProp];\n var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;\n var offset = within(min, center, max); // Prevents breaking syntax highlighting...\n\n var axisProp = axis;\n state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state,\n options = _ref2.options;\n var _options$element = options.element,\n arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;\n\n if (arrowElement == null) {\n return;\n } // CSS selector\n\n\n if (typeof arrowElement === 'string') {\n arrowElement = state.elements.popper.querySelector(arrowElement);\n\n if (!arrowElement) {\n return;\n }\n }\n\n if (!contains(state.elements.popper, arrowElement)) {\n return;\n }\n\n state.elements.arrow = arrowElement;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'arrow',\n enabled: true,\n phase: 'main',\n fn: arrow,\n effect: effect,\n requires: ['popperOffsets'],\n requiresIfExists: ['preventOverflow']\n};","export default function getVariation(placement) {\n return placement.split('-')[1];\n}","import { top, left, right, bottom, end } from \"../enums.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getWindow from \"../dom-utils/getWindow.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getComputedStyle from \"../dom-utils/getComputedStyle.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport { round } from \"../utils/math.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar unsetSides = {\n top: 'auto',\n right: 'auto',\n bottom: 'auto',\n left: 'auto'\n}; // Round the offsets to the nearest suitable subpixel based on the DPR.\n// Zooming can change the DPR, but it seems to report a value that will\n// cleanly divide the values into the appropriate subpixels.\n\nfunction roundOffsetsByDPR(_ref, win) {\n var x = _ref.x,\n y = _ref.y;\n var dpr = win.devicePixelRatio || 1;\n return {\n x: round(x * dpr) / dpr || 0,\n y: round(y * dpr) / dpr || 0\n };\n}\n\nexport function mapToStyles(_ref2) {\n var _Object$assign2;\n\n var popper = _ref2.popper,\n popperRect = _ref2.popperRect,\n placement = _ref2.placement,\n variation = _ref2.variation,\n offsets = _ref2.offsets,\n position = _ref2.position,\n gpuAcceleration = _ref2.gpuAcceleration,\n adaptive = _ref2.adaptive,\n roundOffsets = _ref2.roundOffsets,\n isFixed = _ref2.isFixed;\n var _offsets$x = offsets.x,\n x = _offsets$x === void 0 ? 0 : _offsets$x,\n _offsets$y = offsets.y,\n y = _offsets$y === void 0 ? 0 : _offsets$y;\n\n var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({\n x: x,\n y: y\n }) : {\n x: x,\n y: y\n };\n\n x = _ref3.x;\n y = _ref3.y;\n var hasX = offsets.hasOwnProperty('x');\n var hasY = offsets.hasOwnProperty('y');\n var sideX = left;\n var sideY = top;\n var win = window;\n\n if (adaptive) {\n var offsetParent = getOffsetParent(popper);\n var heightProp = 'clientHeight';\n var widthProp = 'clientWidth';\n\n if (offsetParent === getWindow(popper)) {\n offsetParent = getDocumentElement(popper);\n\n if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {\n heightProp = 'scrollHeight';\n widthProp = 'scrollWidth';\n }\n } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it\n\n\n offsetParent = offsetParent;\n\n if (placement === top || (placement === left || placement === right) && variation === end) {\n sideY = bottom;\n var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]\n offsetParent[heightProp];\n y -= offsetY - popperRect.height;\n y *= gpuAcceleration ? 1 : -1;\n }\n\n if (placement === left || (placement === top || placement === bottom) && variation === end) {\n sideX = right;\n var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]\n offsetParent[widthProp];\n x -= offsetX - popperRect.width;\n x *= gpuAcceleration ? 1 : -1;\n }\n }\n\n var commonStyles = Object.assign({\n position: position\n }, adaptive && unsetSides);\n\n var _ref4 = roundOffsets === true ? roundOffsetsByDPR({\n x: x,\n y: y\n }, getWindow(popper)) : {\n x: x,\n y: y\n };\n\n x = _ref4.x;\n y = _ref4.y;\n\n if (gpuAcceleration) {\n var _Object$assign;\n\n return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? \"translate(\" + x + \"px, \" + y + \"px)\" : \"translate3d(\" + x + \"px, \" + y + \"px, 0)\", _Object$assign));\n }\n\n return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + \"px\" : '', _Object$assign2[sideX] = hasX ? x + \"px\" : '', _Object$assign2.transform = '', _Object$assign2));\n}\n\nfunction computeStyles(_ref5) {\n var state = _ref5.state,\n options = _ref5.options;\n var _options$gpuAccelerat = options.gpuAcceleration,\n gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,\n _options$adaptive = options.adaptive,\n adaptive = _options$adaptive === void 0 ? true : _options$adaptive,\n _options$roundOffsets = options.roundOffsets,\n roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;\n var commonStyles = {\n placement: getBasePlacement(state.placement),\n variation: getVariation(state.placement),\n popper: state.elements.popper,\n popperRect: state.rects.popper,\n gpuAcceleration: gpuAcceleration,\n isFixed: state.options.strategy === 'fixed'\n };\n\n if (state.modifiersData.popperOffsets != null) {\n state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.popperOffsets,\n position: state.options.strategy,\n adaptive: adaptive,\n roundOffsets: roundOffsets\n })));\n }\n\n if (state.modifiersData.arrow != null) {\n state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.arrow,\n position: 'absolute',\n adaptive: false,\n roundOffsets: roundOffsets\n })));\n }\n\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-placement': state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'computeStyles',\n enabled: true,\n phase: 'beforeWrite',\n fn: computeStyles,\n data: {}\n};","import getWindow from \"../dom-utils/getWindow.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar passive = {\n passive: true\n};\n\nfunction effect(_ref) {\n var state = _ref.state,\n instance = _ref.instance,\n options = _ref.options;\n var _options$scroll = options.scroll,\n scroll = _options$scroll === void 0 ? true : _options$scroll,\n _options$resize = options.resize,\n resize = _options$resize === void 0 ? true : _options$resize;\n var window = getWindow(state.elements.popper);\n var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);\n\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.addEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.addEventListener('resize', instance.update, passive);\n }\n\n return function () {\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.removeEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.removeEventListener('resize', instance.update, passive);\n }\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'eventListeners',\n enabled: true,\n phase: 'write',\n fn: function fn() {},\n effect: effect,\n data: {}\n};","var hash = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nexport default function getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}","var hash = {\n start: 'end',\n end: 'start'\n};\nexport default function getOppositeVariationPlacement(placement) {\n return placement.replace(/start|end/g, function (matched) {\n return hash[matched];\n });\n}","import getWindow from \"./getWindow.js\";\nexport default function getWindowScroll(node) {\n var win = getWindow(node);\n var scrollLeft = win.pageXOffset;\n var scrollTop = win.pageYOffset;\n return {\n scrollLeft: scrollLeft,\n scrollTop: scrollTop\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nexport default function getWindowScrollBarX(element) {\n // If has a CSS width greater than the viewport, then this will be\n // incorrect for RTL.\n // Popper 1 is broken in this case and never had a bug report so let's assume\n // it's not an issue. I don't think anyone ever specifies width on \n // anyway.\n // Browsers where the left scrollbar doesn't cause an issue report `0` for\n // this (e.g. Edge 2019, IE11, Safari)\n return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;\n}","import getComputedStyle from \"./getComputedStyle.js\";\nexport default function isScrollParent(element) {\n // Firefox wants us to check `-x` and `-y` variations as well\n var _getComputedStyle = getComputedStyle(element),\n overflow = _getComputedStyle.overflow,\n overflowX = _getComputedStyle.overflowX,\n overflowY = _getComputedStyle.overflowY;\n\n return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);\n}","import getParentNode from \"./getParentNode.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nexport default function getScrollParent(node) {\n if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return node.ownerDocument.body;\n }\n\n if (isHTMLElement(node) && isScrollParent(node)) {\n return node;\n }\n\n return getScrollParent(getParentNode(node));\n}","import getScrollParent from \"./getScrollParent.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getWindow from \"./getWindow.js\";\nimport isScrollParent from \"./isScrollParent.js\";\n/*\ngiven a DOM element, return the list of all scroll parents, up the list of ancesors\nuntil we get to the top window object. This list is what we attach scroll listeners\nto, because if any of these parent elements scroll, we'll need to re-calculate the\nreference element's position.\n*/\n\nexport default function listScrollParents(element, list) {\n var _element$ownerDocumen;\n\n if (list === void 0) {\n list = [];\n }\n\n var scrollParent = getScrollParent(element);\n var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);\n var win = getWindow(scrollParent);\n var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;\n var updatedList = list.concat(target);\n return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here\n updatedList.concat(listScrollParents(getParentNode(target)));\n}","export default function rectToClientRect(rect) {\n return Object.assign({}, rect, {\n left: rect.x,\n top: rect.y,\n right: rect.x + rect.width,\n bottom: rect.y + rect.height\n });\n}","import { viewport } from \"../enums.js\";\nimport getViewportRect from \"./getViewportRect.js\";\nimport getDocumentRect from \"./getDocumentRect.js\";\nimport listScrollParents from \"./listScrollParents.js\";\nimport getOffsetParent from \"./getOffsetParent.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport contains from \"./contains.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport rectToClientRect from \"../utils/rectToClientRect.js\";\nimport { max, min } from \"../utils/math.js\";\n\nfunction getInnerBoundingClientRect(element, strategy) {\n var rect = getBoundingClientRect(element, false, strategy === 'fixed');\n rect.top = rect.top + element.clientTop;\n rect.left = rect.left + element.clientLeft;\n rect.bottom = rect.top + element.clientHeight;\n rect.right = rect.left + element.clientWidth;\n rect.width = element.clientWidth;\n rect.height = element.clientHeight;\n rect.x = rect.left;\n rect.y = rect.top;\n return rect;\n}\n\nfunction getClientRectFromMixedType(element, clippingParent, strategy) {\n return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));\n} // A \"clipping parent\" is an overflowable container with the characteristic of\n// clipping (or hiding) overflowing elements with a position different from\n// `initial`\n\n\nfunction getClippingParents(element) {\n var clippingParents = listScrollParents(getParentNode(element));\n var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;\n var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;\n\n if (!isElement(clipperElement)) {\n return [];\n } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414\n\n\n return clippingParents.filter(function (clippingParent) {\n return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';\n });\n} // Gets the maximum area that the element is visible in due to any number of\n// clipping parents\n\n\nexport default function getClippingRect(element, boundary, rootBoundary, strategy) {\n var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);\n var clippingParents = [].concat(mainClippingParents, [rootBoundary]);\n var firstClippingParent = clippingParents[0];\n var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {\n var rect = getClientRectFromMixedType(element, clippingParent, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromMixedType(element, firstClippingParent, strategy));\n clippingRect.width = clippingRect.right - clippingRect.left;\n clippingRect.height = clippingRect.bottom - clippingRect.top;\n clippingRect.x = clippingRect.left;\n clippingRect.y = clippingRect.top;\n return clippingRect;\n}","import getWindow from \"./getWindow.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getViewportRect(element, strategy) {\n var win = getWindow(element);\n var html = getDocumentElement(element);\n var visualViewport = win.visualViewport;\n var width = html.clientWidth;\n var height = html.clientHeight;\n var x = 0;\n var y = 0;\n\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n var layoutViewport = isLayoutViewport();\n\n if (layoutViewport || !layoutViewport && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n\n return {\n width: width,\n height: height,\n x: x + getWindowScrollBarX(element),\n y: y\n };\n}","import getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nimport { max } from \"../utils/math.js\"; // Gets the entire size of the scrollable document area, even extending outside\n// of the `` and `` rect bounds if horizontally scrollable\n\nexport default function getDocumentRect(element) {\n var _element$ownerDocumen;\n\n var html = getDocumentElement(element);\n var winScroll = getWindowScroll(element);\n var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;\n var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);\n var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);\n var x = -winScroll.scrollLeft + getWindowScrollBarX(element);\n var y = -winScroll.scrollTop;\n\n if (getComputedStyle(body || html).direction === 'rtl') {\n x += max(html.clientWidth, body ? body.clientWidth : 0) - width;\n }\n\n return {\n width: width,\n height: height,\n x: x,\n y: y\n };\n}","import getBasePlacement from \"./getBasePlacement.js\";\nimport getVariation from \"./getVariation.js\";\nimport getMainAxisFromPlacement from \"./getMainAxisFromPlacement.js\";\nimport { top, right, bottom, left, start, end } from \"../enums.js\";\nexport default function computeOffsets(_ref) {\n var reference = _ref.reference,\n element = _ref.element,\n placement = _ref.placement;\n var basePlacement = placement ? getBasePlacement(placement) : null;\n var variation = placement ? getVariation(placement) : null;\n var commonX = reference.x + reference.width / 2 - element.width / 2;\n var commonY = reference.y + reference.height / 2 - element.height / 2;\n var offsets;\n\n switch (basePlacement) {\n case top:\n offsets = {\n x: commonX,\n y: reference.y - element.height\n };\n break;\n\n case bottom:\n offsets = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n\n case right:\n offsets = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n\n case left:\n offsets = {\n x: reference.x - element.width,\n y: commonY\n };\n break;\n\n default:\n offsets = {\n x: reference.x,\n y: reference.y\n };\n }\n\n var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;\n\n if (mainAxis != null) {\n var len = mainAxis === 'y' ? 'height' : 'width';\n\n switch (variation) {\n case start:\n offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);\n break;\n\n case end:\n offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);\n break;\n\n default:\n }\n }\n\n return offsets;\n}","import getClippingRect from \"../dom-utils/getClippingRect.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getBoundingClientRect from \"../dom-utils/getBoundingClientRect.js\";\nimport computeOffsets from \"./computeOffsets.js\";\nimport rectToClientRect from \"./rectToClientRect.js\";\nimport { clippingParents, reference, popper, bottom, top, right, basePlacements, viewport } from \"../enums.js\";\nimport { isElement } from \"../dom-utils/instanceOf.js\";\nimport mergePaddingObject from \"./mergePaddingObject.js\";\nimport expandToHashMap from \"./expandToHashMap.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport default function detectOverflow(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n _options$placement = _options.placement,\n placement = _options$placement === void 0 ? state.placement : _options$placement,\n _options$strategy = _options.strategy,\n strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,\n _options$boundary = _options.boundary,\n boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,\n _options$rootBoundary = _options.rootBoundary,\n rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,\n _options$elementConte = _options.elementContext,\n elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,\n _options$altBoundary = _options.altBoundary,\n altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,\n _options$padding = _options.padding,\n padding = _options$padding === void 0 ? 0 : _options$padding;\n var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n var altContext = elementContext === popper ? reference : popper;\n var popperRect = state.rects.popper;\n var element = state.elements[altBoundary ? altContext : elementContext];\n var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);\n var referenceClientRect = getBoundingClientRect(state.elements.reference);\n var popperOffsets = computeOffsets({\n reference: referenceClientRect,\n element: popperRect,\n strategy: 'absolute',\n placement: placement\n });\n var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));\n var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect\n // 0 or negative = within the clipping rect\n\n var overflowOffsets = {\n top: clippingClientRect.top - elementClientRect.top + paddingObject.top,\n bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - elementClientRect.left + paddingObject.left,\n right: elementClientRect.right - clippingClientRect.right + paddingObject.right\n };\n var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element\n\n if (elementContext === popper && offsetData) {\n var offset = offsetData[placement];\n Object.keys(overflowOffsets).forEach(function (key) {\n var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;\n var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key] += offset[axis] * multiply;\n });\n }\n\n return overflowOffsets;\n}","import getOppositePlacement from \"../utils/getOppositePlacement.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getOppositeVariationPlacement from \"../utils/getOppositeVariationPlacement.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport computeAutoPlacement from \"../utils/computeAutoPlacement.js\";\nimport { bottom, top, start, right, left, auto } from \"../enums.js\";\nimport getVariation from \"../utils/getVariation.js\"; // eslint-disable-next-line import/no-unused-modules\n\nfunction getExpandedFallbackPlacements(placement) {\n if (getBasePlacement(placement) === auto) {\n return [];\n }\n\n var oppositePlacement = getOppositePlacement(placement);\n return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];\n}\n\nfunction flip(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n\n if (state.modifiersData[name]._skip) {\n return;\n }\n\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,\n specifiedFallbackPlacements = options.fallbackPlacements,\n padding = options.padding,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n _options$flipVariatio = options.flipVariations,\n flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,\n allowedAutoPlacements = options.allowedAutoPlacements;\n var preferredPlacement = state.options.placement;\n var basePlacement = getBasePlacement(preferredPlacement);\n var isBasePlacement = basePlacement === preferredPlacement;\n var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));\n var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {\n return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n flipVariations: flipVariations,\n allowedAutoPlacements: allowedAutoPlacements\n }) : placement);\n }, []);\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var checksMap = new Map();\n var makeFallbackChecks = true;\n var firstFittingPlacement = placements[0];\n\n for (var i = 0; i < placements.length; i++) {\n var placement = placements[i];\n\n var _basePlacement = getBasePlacement(placement);\n\n var isStartVariation = getVariation(placement) === start;\n var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;\n var len = isVertical ? 'width' : 'height';\n var overflow = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n altBoundary: altBoundary,\n padding: padding\n });\n var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;\n\n if (referenceRect[len] > popperRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide);\n }\n\n var altVariationSide = getOppositePlacement(mainVariationSide);\n var checks = [];\n\n if (checkMainAxis) {\n checks.push(overflow[_basePlacement] <= 0);\n }\n\n if (checkAltAxis) {\n checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);\n }\n\n if (checks.every(function (check) {\n return check;\n })) {\n firstFittingPlacement = placement;\n makeFallbackChecks = false;\n break;\n }\n\n checksMap.set(placement, checks);\n }\n\n if (makeFallbackChecks) {\n // `2` may be desired in some cases – research later\n var numberOfChecks = flipVariations ? 3 : 1;\n\n var _loop = function _loop(_i) {\n var fittingPlacement = placements.find(function (placement) {\n var checks = checksMap.get(placement);\n\n if (checks) {\n return checks.slice(0, _i).every(function (check) {\n return check;\n });\n }\n });\n\n if (fittingPlacement) {\n firstFittingPlacement = fittingPlacement;\n return \"break\";\n }\n };\n\n for (var _i = numberOfChecks; _i > 0; _i--) {\n var _ret = _loop(_i);\n\n if (_ret === \"break\") break;\n }\n }\n\n if (state.placement !== firstFittingPlacement) {\n state.modifiersData[name]._skip = true;\n state.placement = firstFittingPlacement;\n state.reset = true;\n }\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'flip',\n enabled: true,\n phase: 'main',\n fn: flip,\n requiresIfExists: ['offset'],\n data: {\n _skip: false\n }\n};","import getVariation from \"./getVariation.js\";\nimport { variationPlacements, basePlacements, placements as allPlacements } from \"../enums.js\";\nimport detectOverflow from \"./detectOverflow.js\";\nimport getBasePlacement from \"./getBasePlacement.js\";\nexport default function computeAutoPlacement(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n placement = _options.placement,\n boundary = _options.boundary,\n rootBoundary = _options.rootBoundary,\n padding = _options.padding,\n flipVariations = _options.flipVariations,\n _options$allowedAutoP = _options.allowedAutoPlacements,\n allowedAutoPlacements = _options$allowedAutoP === void 0 ? allPlacements : _options$allowedAutoP;\n var variation = getVariation(placement);\n var placements = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {\n return getVariation(placement) === variation;\n }) : basePlacements;\n var allowedPlacements = placements.filter(function (placement) {\n return allowedAutoPlacements.indexOf(placement) >= 0;\n });\n\n if (allowedPlacements.length === 0) {\n allowedPlacements = placements;\n } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...\n\n\n var overflows = allowedPlacements.reduce(function (acc, placement) {\n acc[placement] = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding\n })[getBasePlacement(placement)];\n return acc;\n }, {});\n return Object.keys(overflows).sort(function (a, b) {\n return overflows[a] - overflows[b];\n });\n}","import { top, bottom, left, right } from \"../enums.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\n\nfunction getSideOffsets(overflow, rect, preventedOffsets) {\n if (preventedOffsets === void 0) {\n preventedOffsets = {\n x: 0,\n y: 0\n };\n }\n\n return {\n top: overflow.top - rect.height - preventedOffsets.y,\n right: overflow.right - rect.width + preventedOffsets.x,\n bottom: overflow.bottom - rect.height + preventedOffsets.y,\n left: overflow.left - rect.width - preventedOffsets.x\n };\n}\n\nfunction isAnySideFullyClipped(overflow) {\n return [top, right, bottom, left].some(function (side) {\n return overflow[side] >= 0;\n });\n}\n\nfunction hide(_ref) {\n var state = _ref.state,\n name = _ref.name;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var preventedOffsets = state.modifiersData.preventOverflow;\n var referenceOverflow = detectOverflow(state, {\n elementContext: 'reference'\n });\n var popperAltOverflow = detectOverflow(state, {\n altBoundary: true\n });\n var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);\n var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);\n var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);\n var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);\n state.modifiersData[name] = {\n referenceClippingOffsets: referenceClippingOffsets,\n popperEscapeOffsets: popperEscapeOffsets,\n isReferenceHidden: isReferenceHidden,\n hasPopperEscaped: hasPopperEscaped\n };\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-reference-hidden': isReferenceHidden,\n 'data-popper-escaped': hasPopperEscaped\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'hide',\n enabled: true,\n phase: 'main',\n requiresIfExists: ['preventOverflow'],\n fn: hide\n};","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport { top, left, right, placements } from \"../enums.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport function distanceAndSkiddingToXY(placement, rects, offset) {\n var basePlacement = getBasePlacement(placement);\n var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;\n\n var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {\n placement: placement\n })) : offset,\n skidding = _ref[0],\n distance = _ref[1];\n\n skidding = skidding || 0;\n distance = (distance || 0) * invertDistance;\n return [left, right].indexOf(basePlacement) >= 0 ? {\n x: distance,\n y: skidding\n } : {\n x: skidding,\n y: distance\n };\n}\n\nfunction offset(_ref2) {\n var state = _ref2.state,\n options = _ref2.options,\n name = _ref2.name;\n var _options$offset = options.offset,\n offset = _options$offset === void 0 ? [0, 0] : _options$offset;\n var data = placements.reduce(function (acc, placement) {\n acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);\n return acc;\n }, {});\n var _data$state$placement = data[state.placement],\n x = _data$state$placement.x,\n y = _data$state$placement.y;\n\n if (state.modifiersData.popperOffsets != null) {\n state.modifiersData.popperOffsets.x += x;\n state.modifiersData.popperOffsets.y += y;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'offset',\n enabled: true,\n phase: 'main',\n requires: ['popperOffsets'],\n fn: offset\n};","import computeOffsets from \"../utils/computeOffsets.js\";\n\nfunction popperOffsets(_ref) {\n var state = _ref.state,\n name = _ref.name;\n // Offsets are the actual position the popper needs to have to be\n // properly positioned near its reference element\n // This is the most basic placement, and will be adjusted by\n // the modifiers in the next step\n state.modifiersData[name] = computeOffsets({\n reference: state.rects.reference,\n element: state.rects.popper,\n strategy: 'absolute',\n placement: state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'popperOffsets',\n enabled: true,\n phase: 'read',\n fn: popperOffsets,\n data: {}\n};","import { top, left, right, bottom, start } from \"../enums.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport getAltAxis from \"../utils/getAltAxis.js\";\nimport { within, withinMaxClamp } from \"../utils/within.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport getFreshSideObject from \"../utils/getFreshSideObject.js\";\nimport { min as mathMin, max as mathMax } from \"../utils/math.js\";\n\nfunction preventOverflow(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n padding = options.padding,\n _options$tether = options.tether,\n tether = _options$tether === void 0 ? true : _options$tether,\n _options$tetherOffset = options.tetherOffset,\n tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;\n var overflow = detectOverflow(state, {\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n altBoundary: altBoundary\n });\n var basePlacement = getBasePlacement(state.placement);\n var variation = getVariation(state.placement);\n var isBasePlacement = !variation;\n var mainAxis = getMainAxisFromPlacement(basePlacement);\n var altAxis = getAltAxis(mainAxis);\n var popperOffsets = state.modifiersData.popperOffsets;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {\n placement: state.placement\n })) : tetherOffset;\n var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {\n mainAxis: tetherOffsetValue,\n altAxis: tetherOffsetValue\n } : Object.assign({\n mainAxis: 0,\n altAxis: 0\n }, tetherOffsetValue);\n var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;\n var data = {\n x: 0,\n y: 0\n };\n\n if (!popperOffsets) {\n return;\n }\n\n if (checkMainAxis) {\n var _offsetModifierState$;\n\n var mainSide = mainAxis === 'y' ? top : left;\n var altSide = mainAxis === 'y' ? bottom : right;\n var len = mainAxis === 'y' ? 'height' : 'width';\n var offset = popperOffsets[mainAxis];\n var min = offset + overflow[mainSide];\n var max = offset - overflow[altSide];\n var additive = tether ? -popperRect[len] / 2 : 0;\n var minLen = variation === start ? referenceRect[len] : popperRect[len];\n var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go\n // outside the reference bounds\n\n var arrowElement = state.elements.arrow;\n var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {\n width: 0,\n height: 0\n };\n var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();\n var arrowPaddingMin = arrowPaddingObject[mainSide];\n var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want\n // to include its full size in the calculation. If the reference is small\n // and near the edge of a boundary, the popper can overflow even if the\n // reference is not overflowing as well (e.g. virtual elements with no\n // width or height)\n\n var arrowLen = within(0, referenceRect[len], arrowRect[len]);\n var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;\n var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;\n var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);\n var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;\n var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;\n var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;\n var tetherMax = offset + maxOffset - offsetModifierValue;\n var preventedOffset = within(tether ? mathMin(min, tetherMin) : min, offset, tether ? mathMax(max, tetherMax) : max);\n popperOffsets[mainAxis] = preventedOffset;\n data[mainAxis] = preventedOffset - offset;\n }\n\n if (checkAltAxis) {\n var _offsetModifierState$2;\n\n var _mainSide = mainAxis === 'x' ? top : left;\n\n var _altSide = mainAxis === 'x' ? bottom : right;\n\n var _offset = popperOffsets[altAxis];\n\n var _len = altAxis === 'y' ? 'height' : 'width';\n\n var _min = _offset + overflow[_mainSide];\n\n var _max = _offset - overflow[_altSide];\n\n var isOriginSide = [top, left].indexOf(basePlacement) !== -1;\n\n var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;\n\n var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;\n\n var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;\n\n var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);\n\n popperOffsets[altAxis] = _preventedOffset;\n data[altAxis] = _preventedOffset - _offset;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'preventOverflow',\n enabled: true,\n phase: 'main',\n fn: preventOverflow,\n requiresIfExists: ['offset']\n};","export default function getAltAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getNodeScroll from \"./getNodeScroll.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport { round } from \"../utils/math.js\";\n\nfunction isElementScaled(element) {\n var rect = element.getBoundingClientRect();\n var scaleX = round(rect.width) / element.offsetWidth || 1;\n var scaleY = round(rect.height) / element.offsetHeight || 1;\n return scaleX !== 1 || scaleY !== 1;\n} // Returns the composite rect of an element relative to its offsetParent.\n// Composite means it takes into account transforms as well as layout.\n\n\nexport default function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n\n var isOffsetParentAnElement = isHTMLElement(offsetParent);\n var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);\n var documentElement = getDocumentElement(offsetParent);\n var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);\n var scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n var offsets = {\n x: 0,\n y: 0\n };\n\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078\n isScrollParent(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n\n if (isHTMLElement(offsetParent)) {\n offsets = getBoundingClientRect(offsetParent, true);\n offsets.x += offsetParent.clientLeft;\n offsets.y += offsetParent.clientTop;\n } else if (documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n\n return {\n x: rect.left + scroll.scrollLeft - offsets.x,\n y: rect.top + scroll.scrollTop - offsets.y,\n width: rect.width,\n height: rect.height\n };\n}","import getWindowScroll from \"./getWindowScroll.js\";\nimport getWindow from \"./getWindow.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getHTMLElementScroll from \"./getHTMLElementScroll.js\";\nexport default function getNodeScroll(node) {\n if (node === getWindow(node) || !isHTMLElement(node)) {\n return getWindowScroll(node);\n } else {\n return getHTMLElementScroll(node);\n }\n}","export default function getHTMLElementScroll(element) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n}","import { modifierPhases } from \"../enums.js\"; // source: https://stackoverflow.com/questions/49875255\n\nfunction order(modifiers) {\n var map = new Map();\n var visited = new Set();\n var result = [];\n modifiers.forEach(function (modifier) {\n map.set(modifier.name, modifier);\n }); // On visiting object, check for its dependencies and visit them recursively\n\n function sort(modifier) {\n visited.add(modifier.name);\n var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);\n requires.forEach(function (dep) {\n if (!visited.has(dep)) {\n var depModifier = map.get(dep);\n\n if (depModifier) {\n sort(depModifier);\n }\n }\n });\n result.push(modifier);\n }\n\n modifiers.forEach(function (modifier) {\n if (!visited.has(modifier.name)) {\n // check for visited object\n sort(modifier);\n }\n });\n return result;\n}\n\nexport default function orderModifiers(modifiers) {\n // order based on dependencies\n var orderedModifiers = order(modifiers); // order based on phase\n\n return modifierPhases.reduce(function (acc, phase) {\n return acc.concat(orderedModifiers.filter(function (modifier) {\n return modifier.phase === phase;\n }));\n }, []);\n}","import getCompositeRect from \"./dom-utils/getCompositeRect.js\";\nimport getLayoutRect from \"./dom-utils/getLayoutRect.js\";\nimport listScrollParents from \"./dom-utils/listScrollParents.js\";\nimport getOffsetParent from \"./dom-utils/getOffsetParent.js\";\nimport orderModifiers from \"./utils/orderModifiers.js\";\nimport debounce from \"./utils/debounce.js\";\nimport mergeByName from \"./utils/mergeByName.js\";\nimport detectOverflow from \"./utils/detectOverflow.js\";\nimport { isElement } from \"./dom-utils/instanceOf.js\";\nvar DEFAULT_OPTIONS = {\n placement: 'bottom',\n modifiers: [],\n strategy: 'absolute'\n};\n\nfunction areValidElements() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return !args.some(function (element) {\n return !(element && typeof element.getBoundingClientRect === 'function');\n });\n}\n\nexport function popperGenerator(generatorOptions) {\n if (generatorOptions === void 0) {\n generatorOptions = {};\n }\n\n var _generatorOptions = generatorOptions,\n _generatorOptions$def = _generatorOptions.defaultModifiers,\n defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,\n _generatorOptions$def2 = _generatorOptions.defaultOptions,\n defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;\n return function createPopper(reference, popper, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n var state = {\n placement: 'bottom',\n orderedModifiers: [],\n options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),\n modifiersData: {},\n elements: {\n reference: reference,\n popper: popper\n },\n attributes: {},\n styles: {}\n };\n var effectCleanupFns = [];\n var isDestroyed = false;\n var instance = {\n state: state,\n setOptions: function setOptions(setOptionsAction) {\n var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;\n cleanupModifierEffects();\n state.options = Object.assign({}, defaultOptions, state.options, options);\n state.scrollParents = {\n reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],\n popper: listScrollParents(popper)\n }; // Orders the modifiers based on their dependencies and `phase`\n // properties\n\n var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers\n\n state.orderedModifiers = orderedModifiers.filter(function (m) {\n return m.enabled;\n });\n runModifierEffects();\n return instance.update();\n },\n // Sync update – it will always be executed, even if not necessary. This\n // is useful for low frequency updates where sync behavior simplifies the\n // logic.\n // For high frequency updates (e.g. `resize` and `scroll` events), always\n // prefer the async Popper#update method\n forceUpdate: function forceUpdate() {\n if (isDestroyed) {\n return;\n }\n\n var _state$elements = state.elements,\n reference = _state$elements.reference,\n popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements\n // anymore\n\n if (!areValidElements(reference, popper)) {\n return;\n } // Store the reference and popper rects to be read by modifiers\n\n\n state.rects = {\n reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),\n popper: getLayoutRect(popper)\n }; // Modifiers have the ability to reset the current update cycle. The\n // most common use case for this is the `flip` modifier changing the\n // placement, which then needs to re-run all the modifiers, because the\n // logic was previously ran for the previous placement and is therefore\n // stale/incorrect\n\n state.reset = false;\n state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier\n // is filled with the initial data specified by the modifier. This means\n // it doesn't persist and is fresh on each update.\n // To ensure persistent data, use `${name}#persistent`\n\n state.orderedModifiers.forEach(function (modifier) {\n return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);\n });\n\n for (var index = 0; index < state.orderedModifiers.length; index++) {\n if (state.reset === true) {\n state.reset = false;\n index = -1;\n continue;\n }\n\n var _state$orderedModifie = state.orderedModifiers[index],\n fn = _state$orderedModifie.fn,\n _state$orderedModifie2 = _state$orderedModifie.options,\n _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,\n name = _state$orderedModifie.name;\n\n if (typeof fn === 'function') {\n state = fn({\n state: state,\n options: _options,\n name: name,\n instance: instance\n }) || state;\n }\n }\n },\n // Async and optimistically optimized update – it will not be executed if\n // not necessary (debounced to run at most once-per-tick)\n update: debounce(function () {\n return new Promise(function (resolve) {\n instance.forceUpdate();\n resolve(state);\n });\n }),\n destroy: function destroy() {\n cleanupModifierEffects();\n isDestroyed = true;\n }\n };\n\n if (!areValidElements(reference, popper)) {\n return instance;\n }\n\n instance.setOptions(options).then(function (state) {\n if (!isDestroyed && options.onFirstUpdate) {\n options.onFirstUpdate(state);\n }\n }); // Modifiers have the ability to execute arbitrary code before the first\n // update cycle runs. They will be executed in the same order as the update\n // cycle. This is useful when a modifier adds some persistent data that\n // other modifiers need to use, but the modifier is run after the dependent\n // one.\n\n function runModifierEffects() {\n state.orderedModifiers.forEach(function (_ref) {\n var name = _ref.name,\n _ref$options = _ref.options,\n options = _ref$options === void 0 ? {} : _ref$options,\n effect = _ref.effect;\n\n if (typeof effect === 'function') {\n var cleanupFn = effect({\n state: state,\n name: name,\n instance: instance,\n options: options\n });\n\n var noopFn = function noopFn() {};\n\n effectCleanupFns.push(cleanupFn || noopFn);\n }\n });\n }\n\n function cleanupModifierEffects() {\n effectCleanupFns.forEach(function (fn) {\n return fn();\n });\n effectCleanupFns = [];\n }\n\n return instance;\n };\n}\nexport var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules\n\nexport { detectOverflow };","export default function debounce(fn) {\n var pending;\n return function () {\n if (!pending) {\n pending = new Promise(function (resolve) {\n Promise.resolve().then(function () {\n pending = undefined;\n resolve(fn());\n });\n });\n }\n\n return pending;\n };\n}","export default function mergeByName(modifiers) {\n var merged = modifiers.reduce(function (merged, current) {\n var existing = merged[current.name];\n merged[current.name] = existing ? Object.assign({}, existing, current, {\n options: Object.assign({}, existing.options, current.options),\n data: Object.assign({}, existing.data, current.data)\n }) : current;\n return merged;\n }, {}); // IE11 does not support Object.values\n\n return Object.keys(merged).map(function (key) {\n return merged[key];\n });\n}","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nimport offset from \"./modifiers/offset.js\";\nimport flip from \"./modifiers/flip.js\";\nimport preventOverflow from \"./modifiers/preventOverflow.js\";\nimport arrow from \"./modifiers/arrow.js\";\nimport hide from \"./modifiers/hide.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles, offset, flip, preventOverflow, arrow, hide];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow }; // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper as createPopperLite } from \"./popper-lite.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport * from \"./modifiers/index.js\";","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow };","/*!\n * Bootstrap v5.3.2 (https://getbootstrap.com/)\n * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\nimport * as Popper from '@popperjs/core';\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n/**\n * Constants\n */\n\nconst elementMap = new Map();\nconst Data = {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map());\n }\n const instanceMap = elementMap.get(element);\n\n // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`);\n return;\n }\n instanceMap.set(key, instance);\n },\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null;\n }\n return null;\n },\n remove(element, key) {\n if (!elementMap.has(element)) {\n return;\n }\n const instanceMap = elementMap.get(element);\n instanceMap.delete(key);\n\n // free up element references if there are no instances left for an element\n if (instanceMap.size === 0) {\n elementMap.delete(element);\n }\n }\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst MAX_UID = 1000000;\nconst MILLISECONDS_MULTIPLIER = 1000;\nconst TRANSITION_END = 'transitionend';\n\n/**\n * Properly escape IDs selectors to handle weird IDs\n * @param {string} selector\n * @returns {string}\n */\nconst parseSelector = selector => {\n if (selector && window.CSS && window.CSS.escape) {\n // document.querySelector needs escaping to handle IDs (html5+) containing for instance /\n selector = selector.replace(/#([^\\s\"#']+)/g, (match, id) => `#${CSS.escape(id)}`);\n }\n return selector;\n};\n\n// Shout-out Angus Croll (https://goo.gl/pxwQGp)\nconst toType = object => {\n if (object === null || object === undefined) {\n return `${object}`;\n }\n return Object.prototype.toString.call(object).match(/\\s([a-z]+)/i)[1].toLowerCase();\n};\n\n/**\n * Public Util API\n */\n\nconst getUID = prefix => {\n do {\n prefix += Math.floor(Math.random() * MAX_UID);\n } while (document.getElementById(prefix));\n return prefix;\n};\nconst getTransitionDurationFromElement = element => {\n if (!element) {\n return 0;\n }\n\n // Get transition-duration of the element\n let {\n transitionDuration,\n transitionDelay\n } = window.getComputedStyle(element);\n const floatTransitionDuration = Number.parseFloat(transitionDuration);\n const floatTransitionDelay = Number.parseFloat(transitionDelay);\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0;\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0];\n transitionDelay = transitionDelay.split(',')[0];\n return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n};\nconst triggerTransitionEnd = element => {\n element.dispatchEvent(new Event(TRANSITION_END));\n};\nconst isElement = object => {\n if (!object || typeof object !== 'object') {\n return false;\n }\n if (typeof object.jquery !== 'undefined') {\n object = object[0];\n }\n return typeof object.nodeType !== 'undefined';\n};\nconst getElement = object => {\n // it's a jQuery object or a node element\n if (isElement(object)) {\n return object.jquery ? object[0] : object;\n }\n if (typeof object === 'string' && object.length > 0) {\n return document.querySelector(parseSelector(object));\n }\n return null;\n};\nconst isVisible = element => {\n if (!isElement(element) || element.getClientRects().length === 0) {\n return false;\n }\n const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';\n // Handle `details` element as its content may falsie appear visible when it is closed\n const closedDetails = element.closest('details:not([open])');\n if (!closedDetails) {\n return elementIsVisible;\n }\n if (closedDetails !== element) {\n const summary = element.closest('summary');\n if (summary && summary.parentNode !== closedDetails) {\n return false;\n }\n if (summary === null) {\n return false;\n }\n }\n return elementIsVisible;\n};\nconst isDisabled = element => {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return true;\n }\n if (element.classList.contains('disabled')) {\n return true;\n }\n if (typeof element.disabled !== 'undefined') {\n return element.disabled;\n }\n return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';\n};\nconst findShadowRoot = element => {\n if (!document.documentElement.attachShadow) {\n return null;\n }\n\n // Can find the shadow root otherwise it'll return the document\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode();\n return root instanceof ShadowRoot ? root : null;\n }\n if (element instanceof ShadowRoot) {\n return element;\n }\n\n // when we don't find a shadow root\n if (!element.parentNode) {\n return null;\n }\n return findShadowRoot(element.parentNode);\n};\nconst noop = () => {};\n\n/**\n * Trick to restart an element's animation\n *\n * @param {HTMLElement} element\n * @return void\n *\n * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation\n */\nconst reflow = element => {\n element.offsetHeight; // eslint-disable-line no-unused-expressions\n};\n\nconst getjQuery = () => {\n if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n return window.jQuery;\n }\n return null;\n};\nconst DOMContentLoadedCallbacks = [];\nconst onDOMContentLoaded = callback => {\n if (document.readyState === 'loading') {\n // add listener on the first call when the document is in loading state\n if (!DOMContentLoadedCallbacks.length) {\n document.addEventListener('DOMContentLoaded', () => {\n for (const callback of DOMContentLoadedCallbacks) {\n callback();\n }\n });\n }\n DOMContentLoadedCallbacks.push(callback);\n } else {\n callback();\n }\n};\nconst isRTL = () => document.documentElement.dir === 'rtl';\nconst defineJQueryPlugin = plugin => {\n onDOMContentLoaded(() => {\n const $ = getjQuery();\n /* istanbul ignore if */\n if ($) {\n const name = plugin.NAME;\n const JQUERY_NO_CONFLICT = $.fn[name];\n $.fn[name] = plugin.jQueryInterface;\n $.fn[name].Constructor = plugin;\n $.fn[name].noConflict = () => {\n $.fn[name] = JQUERY_NO_CONFLICT;\n return plugin.jQueryInterface;\n };\n }\n });\n};\nconst execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {\n return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue;\n};\nconst executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n if (!waitForTransition) {\n execute(callback);\n return;\n }\n const durationPadding = 5;\n const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;\n let called = false;\n const handler = ({\n target\n }) => {\n if (target !== transitionElement) {\n return;\n }\n called = true;\n transitionElement.removeEventListener(TRANSITION_END, handler);\n execute(callback);\n };\n transitionElement.addEventListener(TRANSITION_END, handler);\n setTimeout(() => {\n if (!called) {\n triggerTransitionEnd(transitionElement);\n }\n }, emulatedDuration);\n};\n\n/**\n * Return the previous/next element of a list.\n *\n * @param {array} list The list of elements\n * @param activeElement The active element\n * @param shouldGetNext Choose to get next or previous element\n * @param isCycleAllowed\n * @return {Element|elem} The proper element\n */\nconst getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n const listLength = list.length;\n let index = list.indexOf(activeElement);\n\n // if the element does not exist in the list return an element\n // depending on the direction and if cycle is allowed\n if (index === -1) {\n return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];\n }\n index += shouldGetNext ? 1 : -1;\n if (isCycleAllowed) {\n index = (index + listLength) % listLength;\n }\n return list[Math.max(0, Math.min(index, listLength - 1))];\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/event-handler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst namespaceRegex = /[^.]*(?=\\..*)\\.|.*/;\nconst stripNameRegex = /\\..*/;\nconst stripUidRegex = /::\\d+$/;\nconst eventRegistry = {}; // Events storage\nlet uidEvent = 1;\nconst customEvents = {\n mouseenter: 'mouseover',\n mouseleave: 'mouseout'\n};\nconst nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']);\n\n/**\n * Private methods\n */\n\nfunction makeEventUid(element, uid) {\n return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++;\n}\nfunction getElementEvents(element) {\n const uid = makeEventUid(element);\n element.uidEvent = uid;\n eventRegistry[uid] = eventRegistry[uid] || {};\n return eventRegistry[uid];\n}\nfunction bootstrapHandler(element, fn) {\n return function handler(event) {\n hydrateObj(event, {\n delegateTarget: element\n });\n if (handler.oneOff) {\n EventHandler.off(element, event.type, fn);\n }\n return fn.apply(element, [event]);\n };\n}\nfunction bootstrapDelegationHandler(element, selector, fn) {\n return function handler(event) {\n const domElements = element.querySelectorAll(selector);\n for (let {\n target\n } = event; target && target !== this; target = target.parentNode) {\n for (const domElement of domElements) {\n if (domElement !== target) {\n continue;\n }\n hydrateObj(event, {\n delegateTarget: target\n });\n if (handler.oneOff) {\n EventHandler.off(element, event.type, selector, fn);\n }\n return fn.apply(target, [event]);\n }\n }\n };\n}\nfunction findHandler(events, callable, delegationSelector = null) {\n return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector);\n}\nfunction normalizeParameters(originalTypeEvent, handler, delegationFunction) {\n const isDelegated = typeof handler === 'string';\n // TODO: tooltip passes `false` instead of selector, so we need to check\n const callable = isDelegated ? delegationFunction : handler || delegationFunction;\n let typeEvent = getTypeEvent(originalTypeEvent);\n if (!nativeEvents.has(typeEvent)) {\n typeEvent = originalTypeEvent;\n }\n return [isDelegated, callable, typeEvent];\n}\nfunction addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return;\n }\n let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);\n\n // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n if (originalTypeEvent in customEvents) {\n const wrapFunction = fn => {\n return function (event) {\n if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) {\n return fn.call(this, event);\n }\n };\n };\n callable = wrapFunction(callable);\n }\n const events = getElementEvents(element);\n const handlers = events[typeEvent] || (events[typeEvent] = {});\n const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null);\n if (previousFunction) {\n previousFunction.oneOff = previousFunction.oneOff && oneOff;\n return;\n }\n const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''));\n const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable);\n fn.delegationSelector = isDelegated ? handler : null;\n fn.callable = callable;\n fn.oneOff = oneOff;\n fn.uidEvent = uid;\n handlers[uid] = fn;\n element.addEventListener(typeEvent, fn, isDelegated);\n}\nfunction removeHandler(element, events, typeEvent, handler, delegationSelector) {\n const fn = findHandler(events[typeEvent], handler, delegationSelector);\n if (!fn) {\n return;\n }\n element.removeEventListener(typeEvent, fn, Boolean(delegationSelector));\n delete events[typeEvent][fn.uidEvent];\n}\nfunction removeNamespacedHandlers(element, events, typeEvent, namespace) {\n const storeElementEvent = events[typeEvent] || {};\n for (const [handlerKey, event] of Object.entries(storeElementEvent)) {\n if (handlerKey.includes(namespace)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);\n }\n }\n}\nfunction getTypeEvent(event) {\n // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n event = event.replace(stripNameRegex, '');\n return customEvents[event] || event;\n}\nconst EventHandler = {\n on(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, false);\n },\n one(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, true);\n },\n off(element, originalTypeEvent, handler, delegationFunction) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return;\n }\n const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);\n const inNamespace = typeEvent !== originalTypeEvent;\n const events = getElementEvents(element);\n const storeElementEvent = events[typeEvent] || {};\n const isNamespace = originalTypeEvent.startsWith('.');\n if (typeof callable !== 'undefined') {\n // Simplest case: handler is passed, remove that listener ONLY.\n if (!Object.keys(storeElementEvent).length) {\n return;\n }\n removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null);\n return;\n }\n if (isNamespace) {\n for (const elementEvent of Object.keys(events)) {\n removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1));\n }\n }\n for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {\n const handlerKey = keyHandlers.replace(stripUidRegex, '');\n if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);\n }\n }\n },\n trigger(element, event, args) {\n if (typeof event !== 'string' || !element) {\n return null;\n }\n const $ = getjQuery();\n const typeEvent = getTypeEvent(event);\n const inNamespace = event !== typeEvent;\n let jQueryEvent = null;\n let bubbles = true;\n let nativeDispatch = true;\n let defaultPrevented = false;\n if (inNamespace && $) {\n jQueryEvent = $.Event(event, args);\n $(element).trigger(jQueryEvent);\n bubbles = !jQueryEvent.isPropagationStopped();\n nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();\n defaultPrevented = jQueryEvent.isDefaultPrevented();\n }\n const evt = hydrateObj(new Event(event, {\n bubbles,\n cancelable: true\n }), args);\n if (defaultPrevented) {\n evt.preventDefault();\n }\n if (nativeDispatch) {\n element.dispatchEvent(evt);\n }\n if (evt.defaultPrevented && jQueryEvent) {\n jQueryEvent.preventDefault();\n }\n return evt;\n }\n};\nfunction hydrateObj(obj, meta = {}) {\n for (const [key, value] of Object.entries(meta)) {\n try {\n obj[key] = value;\n } catch (_unused) {\n Object.defineProperty(obj, key, {\n configurable: true,\n get() {\n return value;\n }\n });\n }\n }\n return obj;\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nfunction normalizeData(value) {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n if (value === Number(value).toString()) {\n return Number(value);\n }\n if (value === '' || value === 'null') {\n return null;\n }\n if (typeof value !== 'string') {\n return value;\n }\n try {\n return JSON.parse(decodeURIComponent(value));\n } catch (_unused) {\n return value;\n }\n}\nfunction normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`);\n}\nconst Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value);\n },\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`);\n },\n getDataAttributes(element) {\n if (!element) {\n return {};\n }\n const attributes = {};\n const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));\n for (const key of bsKeys) {\n let pureKey = key.replace(/^bs/, '');\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);\n attributes[pureKey] = normalizeData(element.dataset[key]);\n }\n return attributes;\n },\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`));\n }\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/config.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Class definition\n */\n\nclass Config {\n // Getters\n static get Default() {\n return {};\n }\n static get DefaultType() {\n return {};\n }\n static get NAME() {\n throw new Error('You have to implement the static method \"NAME\", for each component!');\n }\n _getConfig(config) {\n config = this._mergeConfigObj(config);\n config = this._configAfterMerge(config);\n this._typeCheckConfig(config);\n return config;\n }\n _configAfterMerge(config) {\n return config;\n }\n _mergeConfigObj(config, element) {\n const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse\n\n return {\n ...this.constructor.Default,\n ...(typeof jsonConfig === 'object' ? jsonConfig : {}),\n ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),\n ...(typeof config === 'object' ? config : {})\n };\n }\n _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {\n for (const [property, expectedTypes] of Object.entries(configTypes)) {\n const value = config[property];\n const valueType = isElement(value) ? 'element' : toType(value);\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`);\n }\n }\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst VERSION = '5.3.2';\n\n/**\n * Class definition\n */\n\nclass BaseComponent extends Config {\n constructor(element, config) {\n super();\n element = getElement(element);\n if (!element) {\n return;\n }\n this._element = element;\n this._config = this._getConfig(config);\n Data.set(this._element, this.constructor.DATA_KEY, this);\n }\n\n // Public\n dispose() {\n Data.remove(this._element, this.constructor.DATA_KEY);\n EventHandler.off(this._element, this.constructor.EVENT_KEY);\n for (const propertyName of Object.getOwnPropertyNames(this)) {\n this[propertyName] = null;\n }\n }\n _queueCallback(callback, element, isAnimated = true) {\n executeAfterTransition(callback, element, isAnimated);\n }\n _getConfig(config) {\n config = this._mergeConfigObj(config, this._element);\n config = this._configAfterMerge(config);\n this._typeCheckConfig(config);\n return config;\n }\n\n // Static\n static getInstance(element) {\n return Data.get(getElement(element), this.DATA_KEY);\n }\n static getOrCreateInstance(element, config = {}) {\n return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);\n }\n static get VERSION() {\n return VERSION;\n }\n static get DATA_KEY() {\n return `bs.${this.NAME}`;\n }\n static get EVENT_KEY() {\n return `.${this.DATA_KEY}`;\n }\n static eventName(name) {\n return `${name}${this.EVENT_KEY}`;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dom/selector-engine.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst getSelector = element => {\n let selector = element.getAttribute('data-bs-target');\n if (!selector || selector === '#') {\n let hrefAttribute = element.getAttribute('href');\n\n // The only valid content that could double as a selector are IDs or classes,\n // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n // `document.querySelector` will rightfully complain it is invalid.\n // See https://github.com/twbs/bootstrap/issues/32273\n if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) {\n return null;\n }\n\n // Just in case some CMS puts out a full URL with the anchor appended\n if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {\n hrefAttribute = `#${hrefAttribute.split('#')[1]}`;\n }\n selector = hrefAttribute && hrefAttribute !== '#' ? parseSelector(hrefAttribute.trim()) : null;\n }\n return selector;\n};\nconst SelectorEngine = {\n find(selector, element = document.documentElement) {\n return [].concat(...Element.prototype.querySelectorAll.call(element, selector));\n },\n findOne(selector, element = document.documentElement) {\n return Element.prototype.querySelector.call(element, selector);\n },\n children(element, selector) {\n return [].concat(...element.children).filter(child => child.matches(selector));\n },\n parents(element, selector) {\n const parents = [];\n let ancestor = element.parentNode.closest(selector);\n while (ancestor) {\n parents.push(ancestor);\n ancestor = ancestor.parentNode.closest(selector);\n }\n return parents;\n },\n prev(element, selector) {\n let previous = element.previousElementSibling;\n while (previous) {\n if (previous.matches(selector)) {\n return [previous];\n }\n previous = previous.previousElementSibling;\n }\n return [];\n },\n // TODO: this is now unused; remove later along with prev()\n next(element, selector) {\n let next = element.nextElementSibling;\n while (next) {\n if (next.matches(selector)) {\n return [next];\n }\n next = next.nextElementSibling;\n }\n return [];\n },\n focusableChildren(element) {\n const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable=\"true\"]'].map(selector => `${selector}:not([tabindex^=\"-\"])`).join(',');\n return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el));\n },\n getSelectorFromElement(element) {\n const selector = getSelector(element);\n if (selector) {\n return SelectorEngine.findOne(selector) ? selector : null;\n }\n return null;\n },\n getElementFromSelector(element) {\n const selector = getSelector(element);\n return selector ? SelectorEngine.findOne(selector) : null;\n },\n getMultipleElementsFromSelector(element) {\n const selector = getSelector(element);\n return selector ? SelectorEngine.find(selector) : [];\n }\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/component-functions.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst enableDismissTrigger = (component, method = 'hide') => {\n const clickEvent = `click.dismiss${component.EVENT_KEY}`;\n const name = component.NAME;\n EventHandler.on(document, clickEvent, `[data-bs-dismiss=\"${name}\"]`, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault();\n }\n if (isDisabled(this)) {\n return;\n }\n const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`);\n const instance = component.getOrCreateInstance(target);\n\n // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method\n instance[method]();\n });\n};\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$f = 'alert';\nconst DATA_KEY$a = 'bs.alert';\nconst EVENT_KEY$b = `.${DATA_KEY$a}`;\nconst EVENT_CLOSE = `close${EVENT_KEY$b}`;\nconst EVENT_CLOSED = `closed${EVENT_KEY$b}`;\nconst CLASS_NAME_FADE$5 = 'fade';\nconst CLASS_NAME_SHOW$8 = 'show';\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME$f;\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE);\n if (closeEvent.defaultPrevented) {\n return;\n }\n this._element.classList.remove(CLASS_NAME_SHOW$8);\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5);\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated);\n }\n\n // Private\n _destroyElement() {\n this._element.remove();\n EventHandler.trigger(this._element, EVENT_CLOSED);\n this.dispose();\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Alert.getOrCreateInstance(this);\n if (typeof config !== 'string') {\n return;\n }\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config](this);\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close');\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Alert);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$e = 'button';\nconst DATA_KEY$9 = 'bs.button';\nconst EVENT_KEY$a = `.${DATA_KEY$9}`;\nconst DATA_API_KEY$6 = '.data-api';\nconst CLASS_NAME_ACTIVE$3 = 'active';\nconst SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle=\"button\"]';\nconst EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`;\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME$e;\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Button.getOrCreateInstance(this);\n if (config === 'toggle') {\n data[config]();\n }\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => {\n event.preventDefault();\n const button = event.target.closest(SELECTOR_DATA_TOGGLE$5);\n const data = Button.getOrCreateInstance(button);\n data.toggle();\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Button);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/swipe.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$d = 'swipe';\nconst EVENT_KEY$9 = '.bs.swipe';\nconst EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`;\nconst EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`;\nconst EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`;\nconst EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`;\nconst EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`;\nconst POINTER_TYPE_TOUCH = 'touch';\nconst POINTER_TYPE_PEN = 'pen';\nconst CLASS_NAME_POINTER_EVENT = 'pointer-event';\nconst SWIPE_THRESHOLD = 40;\nconst Default$c = {\n endCallback: null,\n leftCallback: null,\n rightCallback: null\n};\nconst DefaultType$c = {\n endCallback: '(function|null)',\n leftCallback: '(function|null)',\n rightCallback: '(function|null)'\n};\n\n/**\n * Class definition\n */\n\nclass Swipe extends Config {\n constructor(element, config) {\n super();\n this._element = element;\n if (!element || !Swipe.isSupported()) {\n return;\n }\n this._config = this._getConfig(config);\n this._deltaX = 0;\n this._supportPointerEvents = Boolean(window.PointerEvent);\n this._initEvents();\n }\n\n // Getters\n static get Default() {\n return Default$c;\n }\n static get DefaultType() {\n return DefaultType$c;\n }\n static get NAME() {\n return NAME$d;\n }\n\n // Public\n dispose() {\n EventHandler.off(this._element, EVENT_KEY$9);\n }\n\n // Private\n _start(event) {\n if (!this._supportPointerEvents) {\n this._deltaX = event.touches[0].clientX;\n return;\n }\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX;\n }\n }\n _end(event) {\n if (this._eventIsPointerPenTouch(event)) {\n this._deltaX = event.clientX - this._deltaX;\n }\n this._handleSwipe();\n execute(this._config.endCallback);\n }\n _move(event) {\n this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX;\n }\n _handleSwipe() {\n const absDeltaX = Math.abs(this._deltaX);\n if (absDeltaX <= SWIPE_THRESHOLD) {\n return;\n }\n const direction = absDeltaX / this._deltaX;\n this._deltaX = 0;\n if (!direction) {\n return;\n }\n execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback);\n }\n _initEvents() {\n if (this._supportPointerEvents) {\n EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event));\n EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event));\n this._element.classList.add(CLASS_NAME_POINTER_EVENT);\n } else {\n EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event));\n EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event));\n EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event));\n }\n }\n _eventIsPointerPenTouch(event) {\n return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);\n }\n\n // Static\n static isSupported() {\n return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$c = 'carousel';\nconst DATA_KEY$8 = 'bs.carousel';\nconst EVENT_KEY$8 = `.${DATA_KEY$8}`;\nconst DATA_API_KEY$5 = '.data-api';\nconst ARROW_LEFT_KEY$1 = 'ArrowLeft';\nconst ARROW_RIGHT_KEY$1 = 'ArrowRight';\nconst TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\nconst ORDER_NEXT = 'next';\nconst ORDER_PREV = 'prev';\nconst DIRECTION_LEFT = 'left';\nconst DIRECTION_RIGHT = 'right';\nconst EVENT_SLIDE = `slide${EVENT_KEY$8}`;\nconst EVENT_SLID = `slid${EVENT_KEY$8}`;\nconst EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`;\nconst EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`;\nconst EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`;\nconst EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`;\nconst EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`;\nconst EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`;\nconst CLASS_NAME_CAROUSEL = 'carousel';\nconst CLASS_NAME_ACTIVE$2 = 'active';\nconst CLASS_NAME_SLIDE = 'slide';\nconst CLASS_NAME_END = 'carousel-item-end';\nconst CLASS_NAME_START = 'carousel-item-start';\nconst CLASS_NAME_NEXT = 'carousel-item-next';\nconst CLASS_NAME_PREV = 'carousel-item-prev';\nconst SELECTOR_ACTIVE = '.active';\nconst SELECTOR_ITEM = '.carousel-item';\nconst SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM;\nconst SELECTOR_ITEM_IMG = '.carousel-item img';\nconst SELECTOR_INDICATORS = '.carousel-indicators';\nconst SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';\nconst SELECTOR_DATA_RIDE = '[data-bs-ride=\"carousel\"]';\nconst KEY_TO_DIRECTION = {\n [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT,\n [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT\n};\nconst Default$b = {\n interval: 5000,\n keyboard: true,\n pause: 'hover',\n ride: false,\n touch: true,\n wrap: true\n};\nconst DefaultType$b = {\n interval: '(number|boolean)',\n // TODO:v6 remove boolean support\n keyboard: 'boolean',\n pause: '(string|boolean)',\n ride: '(boolean|string)',\n touch: 'boolean',\n wrap: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Carousel extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._interval = null;\n this._activeElement = null;\n this._isSliding = false;\n this.touchTimeout = null;\n this._swipeHelper = null;\n this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element);\n this._addEventListeners();\n if (this._config.ride === CLASS_NAME_CAROUSEL) {\n this.cycle();\n }\n }\n\n // Getters\n static get Default() {\n return Default$b;\n }\n static get DefaultType() {\n return DefaultType$b;\n }\n static get NAME() {\n return NAME$c;\n }\n\n // Public\n next() {\n this._slide(ORDER_NEXT);\n }\n nextWhenVisible() {\n // FIXME TODO use `document.visibilityState`\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden && isVisible(this._element)) {\n this.next();\n }\n }\n prev() {\n this._slide(ORDER_PREV);\n }\n pause() {\n if (this._isSliding) {\n triggerTransitionEnd(this._element);\n }\n this._clearInterval();\n }\n cycle() {\n this._clearInterval();\n this._updateInterval();\n this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval);\n }\n _maybeEnableCycle() {\n if (!this._config.ride) {\n return;\n }\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.cycle());\n return;\n }\n this.cycle();\n }\n to(index) {\n const items = this._getItems();\n if (index > items.length - 1 || index < 0) {\n return;\n }\n if (this._isSliding) {\n EventHandler.one(this._element, EVENT_SLID, () => this.to(index));\n return;\n }\n const activeIndex = this._getItemIndex(this._getActive());\n if (activeIndex === index) {\n return;\n }\n const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;\n this._slide(order, items[index]);\n }\n dispose() {\n if (this._swipeHelper) {\n this._swipeHelper.dispose();\n }\n super.dispose();\n }\n\n // Private\n _configAfterMerge(config) {\n config.defaultInterval = config.interval;\n return config;\n }\n _addEventListeners() {\n if (this._config.keyboard) {\n EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event));\n }\n if (this._config.pause === 'hover') {\n EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause());\n EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle());\n }\n if (this._config.touch && Swipe.isSupported()) {\n this._addTouchEventListeners();\n }\n }\n _addTouchEventListeners() {\n for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {\n EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault());\n }\n const endCallBack = () => {\n if (this._config.pause !== 'hover') {\n return;\n }\n\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause();\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout);\n }\n this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval);\n };\n const swipeConfig = {\n leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),\n rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),\n endCallback: endCallBack\n };\n this._swipeHelper = new Swipe(this._element, swipeConfig);\n }\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return;\n }\n const direction = KEY_TO_DIRECTION[event.key];\n if (direction) {\n event.preventDefault();\n this._slide(this._directionToOrder(direction));\n }\n }\n _getItemIndex(element) {\n return this._getItems().indexOf(element);\n }\n _setActiveIndicatorElement(index) {\n if (!this._indicatorsElement) {\n return;\n }\n const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement);\n activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2);\n activeIndicator.removeAttribute('aria-current');\n const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to=\"${index}\"]`, this._indicatorsElement);\n if (newActiveIndicator) {\n newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2);\n newActiveIndicator.setAttribute('aria-current', 'true');\n }\n }\n _updateInterval() {\n const element = this._activeElement || this._getActive();\n if (!element) {\n return;\n }\n const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);\n this._config.interval = elementInterval || this._config.defaultInterval;\n }\n _slide(order, element = null) {\n if (this._isSliding) {\n return;\n }\n const activeElement = this._getActive();\n const isNext = order === ORDER_NEXT;\n const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap);\n if (nextElement === activeElement) {\n return;\n }\n const nextElementIndex = this._getItemIndex(nextElement);\n const triggerEvent = eventName => {\n return EventHandler.trigger(this._element, eventName, {\n relatedTarget: nextElement,\n direction: this._orderToDirection(order),\n from: this._getItemIndex(activeElement),\n to: nextElementIndex\n });\n };\n const slideEvent = triggerEvent(EVENT_SLIDE);\n if (slideEvent.defaultPrevented) {\n return;\n }\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n // TODO: change tests that use empty divs to avoid this check\n return;\n }\n const isCycling = Boolean(this._interval);\n this.pause();\n this._isSliding = true;\n this._setActiveIndicatorElement(nextElementIndex);\n this._activeElement = nextElement;\n const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;\n const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;\n nextElement.classList.add(orderClassName);\n reflow(nextElement);\n activeElement.classList.add(directionalClassName);\n nextElement.classList.add(directionalClassName);\n const completeCallBack = () => {\n nextElement.classList.remove(directionalClassName, orderClassName);\n nextElement.classList.add(CLASS_NAME_ACTIVE$2);\n activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName);\n this._isSliding = false;\n triggerEvent(EVENT_SLID);\n };\n this._queueCallback(completeCallBack, activeElement, this._isAnimated());\n if (isCycling) {\n this.cycle();\n }\n }\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_SLIDE);\n }\n _getActive() {\n return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);\n }\n _getItems() {\n return SelectorEngine.find(SELECTOR_ITEM, this._element);\n }\n _clearInterval() {\n if (this._interval) {\n clearInterval(this._interval);\n this._interval = null;\n }\n }\n _directionToOrder(direction) {\n if (isRTL()) {\n return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;\n }\n return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV;\n }\n _orderToDirection(order) {\n if (isRTL()) {\n return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;\n }\n return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Carousel.getOrCreateInstance(this, config);\n if (typeof config === 'number') {\n data.to(config);\n return;\n }\n if (typeof config === 'string') {\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n }\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function (event) {\n const target = SelectorEngine.getElementFromSelector(this);\n if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {\n return;\n }\n event.preventDefault();\n const carousel = Carousel.getOrCreateInstance(target);\n const slideIndex = this.getAttribute('data-bs-slide-to');\n if (slideIndex) {\n carousel.to(slideIndex);\n carousel._maybeEnableCycle();\n return;\n }\n if (Manipulator.getDataAttribute(this, 'slide') === 'next') {\n carousel.next();\n carousel._maybeEnableCycle();\n return;\n }\n carousel.prev();\n carousel._maybeEnableCycle();\n});\nEventHandler.on(window, EVENT_LOAD_DATA_API$3, () => {\n const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);\n for (const carousel of carousels) {\n Carousel.getOrCreateInstance(carousel);\n }\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Carousel);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$b = 'collapse';\nconst DATA_KEY$7 = 'bs.collapse';\nconst EVENT_KEY$7 = `.${DATA_KEY$7}`;\nconst DATA_API_KEY$4 = '.data-api';\nconst EVENT_SHOW$6 = `show${EVENT_KEY$7}`;\nconst EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`;\nconst EVENT_HIDE$6 = `hide${EVENT_KEY$7}`;\nconst EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`;\nconst EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`;\nconst CLASS_NAME_SHOW$7 = 'show';\nconst CLASS_NAME_COLLAPSE = 'collapse';\nconst CLASS_NAME_COLLAPSING = 'collapsing';\nconst CLASS_NAME_COLLAPSED = 'collapsed';\nconst CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;\nconst CLASS_NAME_HORIZONTAL = 'collapse-horizontal';\nconst WIDTH = 'width';\nconst HEIGHT = 'height';\nconst SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';\nconst SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle=\"collapse\"]';\nconst Default$a = {\n parent: null,\n toggle: true\n};\nconst DefaultType$a = {\n parent: '(null|element)',\n toggle: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Collapse extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._isTransitioning = false;\n this._triggerArray = [];\n const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4);\n for (const elem of toggleList) {\n const selector = SelectorEngine.getSelectorFromElement(elem);\n const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element);\n if (selector !== null && filterElement.length) {\n this._triggerArray.push(elem);\n }\n }\n this._initializeChildren();\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());\n }\n if (this._config.toggle) {\n this.toggle();\n }\n }\n\n // Getters\n static get Default() {\n return Default$a;\n }\n static get DefaultType() {\n return DefaultType$a;\n }\n static get NAME() {\n return NAME$b;\n }\n\n // Public\n toggle() {\n if (this._isShown()) {\n this.hide();\n } else {\n this.show();\n }\n }\n show() {\n if (this._isTransitioning || this._isShown()) {\n return;\n }\n let activeChildren = [];\n\n // find active children\n if (this._config.parent) {\n activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, {\n toggle: false\n }));\n }\n if (activeChildren.length && activeChildren[0]._isTransitioning) {\n return;\n }\n const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6);\n if (startEvent.defaultPrevented) {\n return;\n }\n for (const activeInstance of activeChildren) {\n activeInstance.hide();\n }\n const dimension = this._getDimension();\n this._element.classList.remove(CLASS_NAME_COLLAPSE);\n this._element.classList.add(CLASS_NAME_COLLAPSING);\n this._element.style[dimension] = 0;\n this._addAriaAndCollapsedClass(this._triggerArray, true);\n this._isTransitioning = true;\n const complete = () => {\n this._isTransitioning = false;\n this._element.classList.remove(CLASS_NAME_COLLAPSING);\n this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7);\n this._element.style[dimension] = '';\n EventHandler.trigger(this._element, EVENT_SHOWN$6);\n };\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n const scrollSize = `scroll${capitalizedDimension}`;\n this._queueCallback(complete, this._element, true);\n this._element.style[dimension] = `${this._element[scrollSize]}px`;\n }\n hide() {\n if (this._isTransitioning || !this._isShown()) {\n return;\n }\n const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6);\n if (startEvent.defaultPrevented) {\n return;\n }\n const dimension = this._getDimension();\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`;\n reflow(this._element);\n this._element.classList.add(CLASS_NAME_COLLAPSING);\n this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7);\n for (const trigger of this._triggerArray) {\n const element = SelectorEngine.getElementFromSelector(trigger);\n if (element && !this._isShown(element)) {\n this._addAriaAndCollapsedClass([trigger], false);\n }\n }\n this._isTransitioning = true;\n const complete = () => {\n this._isTransitioning = false;\n this._element.classList.remove(CLASS_NAME_COLLAPSING);\n this._element.classList.add(CLASS_NAME_COLLAPSE);\n EventHandler.trigger(this._element, EVENT_HIDDEN$6);\n };\n this._element.style[dimension] = '';\n this._queueCallback(complete, this._element, true);\n }\n _isShown(element = this._element) {\n return element.classList.contains(CLASS_NAME_SHOW$7);\n }\n\n // Private\n _configAfterMerge(config) {\n config.toggle = Boolean(config.toggle); // Coerce string values\n config.parent = getElement(config.parent);\n return config;\n }\n _getDimension() {\n return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;\n }\n _initializeChildren() {\n if (!this._config.parent) {\n return;\n }\n const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4);\n for (const element of children) {\n const selected = SelectorEngine.getElementFromSelector(element);\n if (selected) {\n this._addAriaAndCollapsedClass([element], this._isShown(selected));\n }\n }\n }\n _getFirstLevelChildren(selector) {\n const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);\n // remove children if greater depth\n return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element));\n }\n _addAriaAndCollapsedClass(triggerArray, isOpen) {\n if (!triggerArray.length) {\n return;\n }\n for (const element of triggerArray) {\n element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen);\n element.setAttribute('aria-expanded', isOpen);\n }\n }\n\n // Static\n static jQueryInterface(config) {\n const _config = {};\n if (typeof config === 'string' && /show|hide/.test(config)) {\n _config.toggle = false;\n }\n return this.each(function () {\n const data = Collapse.getOrCreateInstance(this, _config);\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n }\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') {\n event.preventDefault();\n }\n for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {\n Collapse.getOrCreateInstance(element, {\n toggle: false\n }).toggle();\n }\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Collapse);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$a = 'dropdown';\nconst DATA_KEY$6 = 'bs.dropdown';\nconst EVENT_KEY$6 = `.${DATA_KEY$6}`;\nconst DATA_API_KEY$3 = '.data-api';\nconst ESCAPE_KEY$2 = 'Escape';\nconst TAB_KEY$1 = 'Tab';\nconst ARROW_UP_KEY$1 = 'ArrowUp';\nconst ARROW_DOWN_KEY$1 = 'ArrowDown';\nconst RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button\n\nconst EVENT_HIDE$5 = `hide${EVENT_KEY$6}`;\nconst EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`;\nconst EVENT_SHOW$5 = `show${EVENT_KEY$6}`;\nconst EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`;\nconst EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`;\nconst EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`;\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`;\nconst CLASS_NAME_SHOW$6 = 'show';\nconst CLASS_NAME_DROPUP = 'dropup';\nconst CLASS_NAME_DROPEND = 'dropend';\nconst CLASS_NAME_DROPSTART = 'dropstart';\nconst CLASS_NAME_DROPUP_CENTER = 'dropup-center';\nconst CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center';\nconst SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle=\"dropdown\"]:not(.disabled):not(:disabled)';\nconst SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`;\nconst SELECTOR_MENU = '.dropdown-menu';\nconst SELECTOR_NAVBAR = '.navbar';\nconst SELECTOR_NAVBAR_NAV = '.navbar-nav';\nconst SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';\nconst PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start';\nconst PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end';\nconst PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start';\nconst PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end';\nconst PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start';\nconst PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start';\nconst PLACEMENT_TOPCENTER = 'top';\nconst PLACEMENT_BOTTOMCENTER = 'bottom';\nconst Default$9 = {\n autoClose: true,\n boundary: 'clippingParents',\n display: 'dynamic',\n offset: [0, 2],\n popperConfig: null,\n reference: 'toggle'\n};\nconst DefaultType$9 = {\n autoClose: '(boolean|string)',\n boundary: '(string|element)',\n display: 'string',\n offset: '(array|string|function)',\n popperConfig: '(null|object|function)',\n reference: '(string|element|object)'\n};\n\n/**\n * Class definition\n */\n\nclass Dropdown extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._popper = null;\n this._parent = this._element.parentNode; // dropdown wrapper\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent);\n this._inNavbar = this._detectNavbar();\n }\n\n // Getters\n static get Default() {\n return Default$9;\n }\n static get DefaultType() {\n return DefaultType$9;\n }\n static get NAME() {\n return NAME$a;\n }\n\n // Public\n toggle() {\n return this._isShown() ? this.hide() : this.show();\n }\n show() {\n if (isDisabled(this._element) || this._isShown()) {\n return;\n }\n const relatedTarget = {\n relatedTarget: this._element\n };\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget);\n if (showEvent.defaultPrevented) {\n return;\n }\n this._createPopper();\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop);\n }\n }\n this._element.focus();\n this._element.setAttribute('aria-expanded', true);\n this._menu.classList.add(CLASS_NAME_SHOW$6);\n this._element.classList.add(CLASS_NAME_SHOW$6);\n EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget);\n }\n hide() {\n if (isDisabled(this._element) || !this._isShown()) {\n return;\n }\n const relatedTarget = {\n relatedTarget: this._element\n };\n this._completeHide(relatedTarget);\n }\n dispose() {\n if (this._popper) {\n this._popper.destroy();\n }\n super.dispose();\n }\n update() {\n this._inNavbar = this._detectNavbar();\n if (this._popper) {\n this._popper.update();\n }\n }\n\n // Private\n _completeHide(relatedTarget) {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget);\n if (hideEvent.defaultPrevented) {\n return;\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop);\n }\n }\n if (this._popper) {\n this._popper.destroy();\n }\n this._menu.classList.remove(CLASS_NAME_SHOW$6);\n this._element.classList.remove(CLASS_NAME_SHOW$6);\n this._element.setAttribute('aria-expanded', 'false');\n Manipulator.removeDataAttribute(this._menu, 'popper');\n EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget);\n }\n _getConfig(config) {\n config = super._getConfig(config);\n if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {\n // Popper virtual elements require a getBoundingClientRect method\n throw new TypeError(`${NAME$a.toUpperCase()}: Option \"reference\" provided type \"object\" without a required \"getBoundingClientRect\" method.`);\n }\n return config;\n }\n _createPopper() {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s dropdowns require Popper (https://popper.js.org)');\n }\n let referenceElement = this._element;\n if (this._config.reference === 'parent') {\n referenceElement = this._parent;\n } else if (isElement(this._config.reference)) {\n referenceElement = getElement(this._config.reference);\n } else if (typeof this._config.reference === 'object') {\n referenceElement = this._config.reference;\n }\n const popperConfig = this._getPopperConfig();\n this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig);\n }\n _isShown() {\n return this._menu.classList.contains(CLASS_NAME_SHOW$6);\n }\n _getPlacement() {\n const parentDropdown = this._parent;\n if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {\n return PLACEMENT_RIGHT;\n }\n if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {\n return PLACEMENT_LEFT;\n }\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {\n return PLACEMENT_TOPCENTER;\n }\n if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {\n return PLACEMENT_BOTTOMCENTER;\n }\n\n // We need to trim the value because custom properties can also include spaces\n const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end';\n if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {\n return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP;\n }\n return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM;\n }\n _detectNavbar() {\n return this._element.closest(SELECTOR_NAVBAR) !== null;\n }\n _getOffset() {\n const {\n offset\n } = this._config;\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10));\n }\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element);\n }\n return offset;\n }\n _getPopperConfig() {\n const defaultBsPopperConfig = {\n placement: this._getPlacement(),\n modifiers: [{\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n }, {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n }]\n };\n\n // Disable Popper if we have a static display or Dropdown is in Navbar\n if (this._inNavbar || this._config.display === 'static') {\n Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // TODO: v6 remove\n defaultBsPopperConfig.modifiers = [{\n name: 'applyStyles',\n enabled: false\n }];\n }\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n };\n }\n _selectMenuItem({\n key,\n target\n }) {\n const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element));\n if (!items.length) {\n return;\n }\n\n // if target isn't included in items (e.g. when expanding the dropdown)\n // allow cycling to get the last item in case key equals ARROW_UP_KEY\n getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Dropdown.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n });\n }\n static clearMenus(event) {\n if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {\n return;\n }\n const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN);\n for (const toggle of openToggles) {\n const context = Dropdown.getInstance(toggle);\n if (!context || context._config.autoClose === false) {\n continue;\n }\n const composedPath = event.composedPath();\n const isMenuTarget = composedPath.includes(context._menu);\n if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {\n continue;\n }\n\n // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu\n if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) {\n continue;\n }\n const relatedTarget = {\n relatedTarget: context._element\n };\n if (event.type === 'click') {\n relatedTarget.clickEvent = event;\n }\n context._completeHide(relatedTarget);\n }\n }\n static dataApiKeydownHandler(event) {\n // If not an UP | DOWN | ESCAPE key => not a dropdown command\n // If input/textarea && if key is other than ESCAPE => not a dropdown command\n\n const isInput = /input|textarea/i.test(event.target.tagName);\n const isEscapeEvent = event.key === ESCAPE_KEY$2;\n const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key);\n if (!isUpOrDownEvent && !isEscapeEvent) {\n return;\n }\n if (isInput && !isEscapeEvent) {\n return;\n }\n event.preventDefault();\n\n // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/\n const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$3, event.delegateTarget.parentNode);\n const instance = Dropdown.getOrCreateInstance(getToggleButton);\n if (isUpOrDownEvent) {\n event.stopPropagation();\n instance.show();\n instance._selectMenuItem(event);\n return;\n }\n if (instance._isShown()) {\n // else is escape and we check if it is shown\n event.stopPropagation();\n instance.hide();\n getToggleButton.focus();\n }\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);\nEventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);\nEventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus);\nEventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);\nEventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) {\n event.preventDefault();\n Dropdown.getOrCreateInstance(this).toggle();\n});\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Dropdown);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/backdrop.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$9 = 'backdrop';\nconst CLASS_NAME_FADE$4 = 'fade';\nconst CLASS_NAME_SHOW$5 = 'show';\nconst EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`;\nconst Default$8 = {\n className: 'modal-backdrop',\n clickCallback: null,\n isAnimated: false,\n isVisible: true,\n // if false, we use the backdrop helper without adding any element to the dom\n rootElement: 'body' // give the choice to place backdrop under different elements\n};\n\nconst DefaultType$8 = {\n className: 'string',\n clickCallback: '(function|null)',\n isAnimated: 'boolean',\n isVisible: 'boolean',\n rootElement: '(element|string)'\n};\n\n/**\n * Class definition\n */\n\nclass Backdrop extends Config {\n constructor(config) {\n super();\n this._config = this._getConfig(config);\n this._isAppended = false;\n this._element = null;\n }\n\n // Getters\n static get Default() {\n return Default$8;\n }\n static get DefaultType() {\n return DefaultType$8;\n }\n static get NAME() {\n return NAME$9;\n }\n\n // Public\n show(callback) {\n if (!this._config.isVisible) {\n execute(callback);\n return;\n }\n this._append();\n const element = this._getElement();\n if (this._config.isAnimated) {\n reflow(element);\n }\n element.classList.add(CLASS_NAME_SHOW$5);\n this._emulateAnimation(() => {\n execute(callback);\n });\n }\n hide(callback) {\n if (!this._config.isVisible) {\n execute(callback);\n return;\n }\n this._getElement().classList.remove(CLASS_NAME_SHOW$5);\n this._emulateAnimation(() => {\n this.dispose();\n execute(callback);\n });\n }\n dispose() {\n if (!this._isAppended) {\n return;\n }\n EventHandler.off(this._element, EVENT_MOUSEDOWN);\n this._element.remove();\n this._isAppended = false;\n }\n\n // Private\n _getElement() {\n if (!this._element) {\n const backdrop = document.createElement('div');\n backdrop.className = this._config.className;\n if (this._config.isAnimated) {\n backdrop.classList.add(CLASS_NAME_FADE$4);\n }\n this._element = backdrop;\n }\n return this._element;\n }\n _configAfterMerge(config) {\n // use getElement() with the default \"body\" to get a fresh Element on each instantiation\n config.rootElement = getElement(config.rootElement);\n return config;\n }\n _append() {\n if (this._isAppended) {\n return;\n }\n const element = this._getElement();\n this._config.rootElement.append(element);\n EventHandler.on(element, EVENT_MOUSEDOWN, () => {\n execute(this._config.clickCallback);\n });\n this._isAppended = true;\n }\n _emulateAnimation(callback) {\n executeAfterTransition(callback, this._getElement(), this._config.isAnimated);\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/focustrap.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$8 = 'focustrap';\nconst DATA_KEY$5 = 'bs.focustrap';\nconst EVENT_KEY$5 = `.${DATA_KEY$5}`;\nconst EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`;\nconst EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`;\nconst TAB_KEY = 'Tab';\nconst TAB_NAV_FORWARD = 'forward';\nconst TAB_NAV_BACKWARD = 'backward';\nconst Default$7 = {\n autofocus: true,\n trapElement: null // The element to trap focus inside of\n};\n\nconst DefaultType$7 = {\n autofocus: 'boolean',\n trapElement: 'element'\n};\n\n/**\n * Class definition\n */\n\nclass FocusTrap extends Config {\n constructor(config) {\n super();\n this._config = this._getConfig(config);\n this._isActive = false;\n this._lastTabNavDirection = null;\n }\n\n // Getters\n static get Default() {\n return Default$7;\n }\n static get DefaultType() {\n return DefaultType$7;\n }\n static get NAME() {\n return NAME$8;\n }\n\n // Public\n activate() {\n if (this._isActive) {\n return;\n }\n if (this._config.autofocus) {\n this._config.trapElement.focus();\n }\n EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop\n EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event));\n EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event));\n this._isActive = true;\n }\n deactivate() {\n if (!this._isActive) {\n return;\n }\n this._isActive = false;\n EventHandler.off(document, EVENT_KEY$5);\n }\n\n // Private\n _handleFocusin(event) {\n const {\n trapElement\n } = this._config;\n if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {\n return;\n }\n const elements = SelectorEngine.focusableChildren(trapElement);\n if (elements.length === 0) {\n trapElement.focus();\n } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {\n elements[elements.length - 1].focus();\n } else {\n elements[0].focus();\n }\n }\n _handleKeydown(event) {\n if (event.key !== TAB_KEY) {\n return;\n }\n this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/scrollBar.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';\nconst SELECTOR_STICKY_CONTENT = '.sticky-top';\nconst PROPERTY_PADDING = 'padding-right';\nconst PROPERTY_MARGIN = 'margin-right';\n\n/**\n * Class definition\n */\n\nclass ScrollBarHelper {\n constructor() {\n this._element = document.body;\n }\n\n // Public\n getWidth() {\n // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes\n const documentWidth = document.documentElement.clientWidth;\n return Math.abs(window.innerWidth - documentWidth);\n }\n hide() {\n const width = this.getWidth();\n this._disableOverFlow();\n // give padding to element to balance the hidden scrollbar width\n this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width);\n // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth\n this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width);\n this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width);\n }\n reset() {\n this._resetElementAttributes(this._element, 'overflow');\n this._resetElementAttributes(this._element, PROPERTY_PADDING);\n this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING);\n this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN);\n }\n isOverflowing() {\n return this.getWidth() > 0;\n }\n\n // Private\n _disableOverFlow() {\n this._saveInitialAttribute(this._element, 'overflow');\n this._element.style.overflow = 'hidden';\n }\n _setElementAttributes(selector, styleProperty, callback) {\n const scrollbarWidth = this.getWidth();\n const manipulationCallBack = element => {\n if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {\n return;\n }\n this._saveInitialAttribute(element, styleProperty);\n const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty);\n element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`);\n };\n this._applyManipulationCallback(selector, manipulationCallBack);\n }\n _saveInitialAttribute(element, styleProperty) {\n const actualValue = element.style.getPropertyValue(styleProperty);\n if (actualValue) {\n Manipulator.setDataAttribute(element, styleProperty, actualValue);\n }\n }\n _resetElementAttributes(selector, styleProperty) {\n const manipulationCallBack = element => {\n const value = Manipulator.getDataAttribute(element, styleProperty);\n // We only want to remove the property if the value is `null`; the value can also be zero\n if (value === null) {\n element.style.removeProperty(styleProperty);\n return;\n }\n Manipulator.removeDataAttribute(element, styleProperty);\n element.style.setProperty(styleProperty, value);\n };\n this._applyManipulationCallback(selector, manipulationCallBack);\n }\n _applyManipulationCallback(selector, callBack) {\n if (isElement(selector)) {\n callBack(selector);\n return;\n }\n for (const sel of SelectorEngine.find(selector, this._element)) {\n callBack(sel);\n }\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$7 = 'modal';\nconst DATA_KEY$4 = 'bs.modal';\nconst EVENT_KEY$4 = `.${DATA_KEY$4}`;\nconst DATA_API_KEY$2 = '.data-api';\nconst ESCAPE_KEY$1 = 'Escape';\nconst EVENT_HIDE$4 = `hide${EVENT_KEY$4}`;\nconst EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`;\nconst EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`;\nconst EVENT_SHOW$4 = `show${EVENT_KEY$4}`;\nconst EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`;\nconst EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`;\nconst EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`;\nconst EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`;\nconst EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`;\nconst EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`;\nconst CLASS_NAME_OPEN = 'modal-open';\nconst CLASS_NAME_FADE$3 = 'fade';\nconst CLASS_NAME_SHOW$4 = 'show';\nconst CLASS_NAME_STATIC = 'modal-static';\nconst OPEN_SELECTOR$1 = '.modal.show';\nconst SELECTOR_DIALOG = '.modal-dialog';\nconst SELECTOR_MODAL_BODY = '.modal-body';\nconst SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle=\"modal\"]';\nconst Default$6 = {\n backdrop: true,\n focus: true,\n keyboard: true\n};\nconst DefaultType$6 = {\n backdrop: '(boolean|string)',\n focus: 'boolean',\n keyboard: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Modal extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);\n this._backdrop = this._initializeBackDrop();\n this._focustrap = this._initializeFocusTrap();\n this._isShown = false;\n this._isTransitioning = false;\n this._scrollBar = new ScrollBarHelper();\n this._addEventListeners();\n }\n\n // Getters\n static get Default() {\n return Default$6;\n }\n static get DefaultType() {\n return DefaultType$6;\n }\n static get NAME() {\n return NAME$7;\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget);\n }\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return;\n }\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, {\n relatedTarget\n });\n if (showEvent.defaultPrevented) {\n return;\n }\n this._isShown = true;\n this._isTransitioning = true;\n this._scrollBar.hide();\n document.body.classList.add(CLASS_NAME_OPEN);\n this._adjustDialog();\n this._backdrop.show(() => this._showElement(relatedTarget));\n }\n hide() {\n if (!this._isShown || this._isTransitioning) {\n return;\n }\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4);\n if (hideEvent.defaultPrevented) {\n return;\n }\n this._isShown = false;\n this._isTransitioning = true;\n this._focustrap.deactivate();\n this._element.classList.remove(CLASS_NAME_SHOW$4);\n this._queueCallback(() => this._hideModal(), this._element, this._isAnimated());\n }\n dispose() {\n EventHandler.off(window, EVENT_KEY$4);\n EventHandler.off(this._dialog, EVENT_KEY$4);\n this._backdrop.dispose();\n this._focustrap.deactivate();\n super.dispose();\n }\n handleUpdate() {\n this._adjustDialog();\n }\n\n // Private\n _initializeBackDrop() {\n return new Backdrop({\n isVisible: Boolean(this._config.backdrop),\n // 'static' option will be translated to true, and booleans will keep their value,\n isAnimated: this._isAnimated()\n });\n }\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n });\n }\n _showElement(relatedTarget) {\n // try to append dynamic modal\n if (!document.body.contains(this._element)) {\n document.body.append(this._element);\n }\n this._element.style.display = 'block';\n this._element.removeAttribute('aria-hidden');\n this._element.setAttribute('aria-modal', true);\n this._element.setAttribute('role', 'dialog');\n this._element.scrollTop = 0;\n const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog);\n if (modalBody) {\n modalBody.scrollTop = 0;\n }\n reflow(this._element);\n this._element.classList.add(CLASS_NAME_SHOW$4);\n const transitionComplete = () => {\n if (this._config.focus) {\n this._focustrap.activate();\n }\n this._isTransitioning = false;\n EventHandler.trigger(this._element, EVENT_SHOWN$4, {\n relatedTarget\n });\n };\n this._queueCallback(transitionComplete, this._dialog, this._isAnimated());\n }\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => {\n if (event.key !== ESCAPE_KEY$1) {\n return;\n }\n if (this._config.keyboard) {\n this.hide();\n return;\n }\n this._triggerBackdropTransition();\n });\n EventHandler.on(window, EVENT_RESIZE$1, () => {\n if (this._isShown && !this._isTransitioning) {\n this._adjustDialog();\n }\n });\n EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => {\n // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks\n EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => {\n if (this._element !== event.target || this._element !== event2.target) {\n return;\n }\n if (this._config.backdrop === 'static') {\n this._triggerBackdropTransition();\n return;\n }\n if (this._config.backdrop) {\n this.hide();\n }\n });\n });\n }\n _hideModal() {\n this._element.style.display = 'none';\n this._element.setAttribute('aria-hidden', true);\n this._element.removeAttribute('aria-modal');\n this._element.removeAttribute('role');\n this._isTransitioning = false;\n this._backdrop.hide(() => {\n document.body.classList.remove(CLASS_NAME_OPEN);\n this._resetAdjustments();\n this._scrollBar.reset();\n EventHandler.trigger(this._element, EVENT_HIDDEN$4);\n });\n }\n _isAnimated() {\n return this._element.classList.contains(CLASS_NAME_FADE$3);\n }\n _triggerBackdropTransition() {\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1);\n if (hideEvent.defaultPrevented) {\n return;\n }\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n const initialOverflowY = this._element.style.overflowY;\n // return if the following background transition hasn't yet completed\n if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {\n return;\n }\n if (!isModalOverflowing) {\n this._element.style.overflowY = 'hidden';\n }\n this._element.classList.add(CLASS_NAME_STATIC);\n this._queueCallback(() => {\n this._element.classList.remove(CLASS_NAME_STATIC);\n this._queueCallback(() => {\n this._element.style.overflowY = initialOverflowY;\n }, this._dialog);\n }, this._dialog);\n this._element.focus();\n }\n\n /**\n * The following methods are used to handle overflowing modals\n */\n\n _adjustDialog() {\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n const scrollbarWidth = this._scrollBar.getWidth();\n const isBodyOverflowing = scrollbarWidth > 0;\n if (isBodyOverflowing && !isModalOverflowing) {\n const property = isRTL() ? 'paddingLeft' : 'paddingRight';\n this._element.style[property] = `${scrollbarWidth}px`;\n }\n if (!isBodyOverflowing && isModalOverflowing) {\n const property = isRTL() ? 'paddingRight' : 'paddingLeft';\n this._element.style[property] = `${scrollbarWidth}px`;\n }\n }\n _resetAdjustments() {\n this._element.style.paddingLeft = '';\n this._element.style.paddingRight = '';\n }\n\n // Static\n static jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n const data = Modal.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config](relatedTarget);\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) {\n const target = SelectorEngine.getElementFromSelector(this);\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault();\n }\n EventHandler.one(target, EVENT_SHOW$4, showEvent => {\n if (showEvent.defaultPrevented) {\n // only register focus restorer if modal will actually get shown\n return;\n }\n EventHandler.one(target, EVENT_HIDDEN$4, () => {\n if (isVisible(this)) {\n this.focus();\n }\n });\n });\n\n // avoid conflict when clicking modal toggler while another one is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1);\n if (alreadyOpen) {\n Modal.getInstance(alreadyOpen).hide();\n }\n const data = Modal.getOrCreateInstance(target);\n data.toggle(this);\n});\nenableDismissTrigger(Modal);\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Modal);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap offcanvas.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$6 = 'offcanvas';\nconst DATA_KEY$3 = 'bs.offcanvas';\nconst EVENT_KEY$3 = `.${DATA_KEY$3}`;\nconst DATA_API_KEY$1 = '.data-api';\nconst EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`;\nconst ESCAPE_KEY = 'Escape';\nconst CLASS_NAME_SHOW$3 = 'show';\nconst CLASS_NAME_SHOWING$1 = 'showing';\nconst CLASS_NAME_HIDING = 'hiding';\nconst CLASS_NAME_BACKDROP = 'offcanvas-backdrop';\nconst OPEN_SELECTOR = '.offcanvas.show';\nconst EVENT_SHOW$3 = `show${EVENT_KEY$3}`;\nconst EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`;\nconst EVENT_HIDE$3 = `hide${EVENT_KEY$3}`;\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`;\nconst EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`;\nconst EVENT_RESIZE = `resize${EVENT_KEY$3}`;\nconst EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`;\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`;\nconst SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle=\"offcanvas\"]';\nconst Default$5 = {\n backdrop: true,\n keyboard: true,\n scroll: false\n};\nconst DefaultType$5 = {\n backdrop: '(boolean|string)',\n keyboard: 'boolean',\n scroll: 'boolean'\n};\n\n/**\n * Class definition\n */\n\nclass Offcanvas extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n this._isShown = false;\n this._backdrop = this._initializeBackDrop();\n this._focustrap = this._initializeFocusTrap();\n this._addEventListeners();\n }\n\n // Getters\n static get Default() {\n return Default$5;\n }\n static get DefaultType() {\n return DefaultType$5;\n }\n static get NAME() {\n return NAME$6;\n }\n\n // Public\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget);\n }\n show(relatedTarget) {\n if (this._isShown) {\n return;\n }\n const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, {\n relatedTarget\n });\n if (showEvent.defaultPrevented) {\n return;\n }\n this._isShown = true;\n this._backdrop.show();\n if (!this._config.scroll) {\n new ScrollBarHelper().hide();\n }\n this._element.setAttribute('aria-modal', true);\n this._element.setAttribute('role', 'dialog');\n this._element.classList.add(CLASS_NAME_SHOWING$1);\n const completeCallBack = () => {\n if (!this._config.scroll || this._config.backdrop) {\n this._focustrap.activate();\n }\n this._element.classList.add(CLASS_NAME_SHOW$3);\n this._element.classList.remove(CLASS_NAME_SHOWING$1);\n EventHandler.trigger(this._element, EVENT_SHOWN$3, {\n relatedTarget\n });\n };\n this._queueCallback(completeCallBack, this._element, true);\n }\n hide() {\n if (!this._isShown) {\n return;\n }\n const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3);\n if (hideEvent.defaultPrevented) {\n return;\n }\n this._focustrap.deactivate();\n this._element.blur();\n this._isShown = false;\n this._element.classList.add(CLASS_NAME_HIDING);\n this._backdrop.hide();\n const completeCallback = () => {\n this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING);\n this._element.removeAttribute('aria-modal');\n this._element.removeAttribute('role');\n if (!this._config.scroll) {\n new ScrollBarHelper().reset();\n }\n EventHandler.trigger(this._element, EVENT_HIDDEN$3);\n };\n this._queueCallback(completeCallback, this._element, true);\n }\n dispose() {\n this._backdrop.dispose();\n this._focustrap.deactivate();\n super.dispose();\n }\n\n // Private\n _initializeBackDrop() {\n const clickCallback = () => {\n if (this._config.backdrop === 'static') {\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);\n return;\n }\n this.hide();\n };\n\n // 'static' option will be translated to true, and booleans will keep their value\n const isVisible = Boolean(this._config.backdrop);\n return new Backdrop({\n className: CLASS_NAME_BACKDROP,\n isVisible,\n isAnimated: true,\n rootElement: this._element.parentNode,\n clickCallback: isVisible ? clickCallback : null\n });\n }\n _initializeFocusTrap() {\n return new FocusTrap({\n trapElement: this._element\n });\n }\n _addEventListeners() {\n EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n if (event.key !== ESCAPE_KEY) {\n return;\n }\n if (this._config.keyboard) {\n this.hide();\n return;\n }\n EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);\n });\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Offcanvas.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config](this);\n });\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) {\n const target = SelectorEngine.getElementFromSelector(this);\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault();\n }\n if (isDisabled(this)) {\n return;\n }\n EventHandler.one(target, EVENT_HIDDEN$3, () => {\n // focus on trigger when it is closed\n if (isVisible(this)) {\n this.focus();\n }\n });\n\n // avoid conflict when clicking a toggler of an offcanvas, while another is open\n const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR);\n if (alreadyOpen && alreadyOpen !== target) {\n Offcanvas.getInstance(alreadyOpen).hide();\n }\n const data = Offcanvas.getOrCreateInstance(target);\n data.toggle(this);\n});\nEventHandler.on(window, EVENT_LOAD_DATA_API$2, () => {\n for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {\n Offcanvas.getOrCreateInstance(selector).show();\n }\n});\nEventHandler.on(window, EVENT_RESIZE, () => {\n for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {\n if (getComputedStyle(element).position !== 'fixed') {\n Offcanvas.getOrCreateInstance(element).hide();\n }\n }\n});\nenableDismissTrigger(Offcanvas);\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Offcanvas);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/sanitizer.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n// js-docs-start allow-list\nconst ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i;\nconst DefaultAllowlist = {\n // Global attributes allowed on any supplied element below.\n '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n a: ['target', 'href', 'title', 'rel'],\n area: [],\n b: [],\n br: [],\n col: [],\n code: [],\n div: [],\n em: [],\n hr: [],\n h1: [],\n h2: [],\n h3: [],\n h4: [],\n h5: [],\n h6: [],\n i: [],\n img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n li: [],\n ol: [],\n p: [],\n pre: [],\n s: [],\n small: [],\n span: [],\n sub: [],\n sup: [],\n strong: [],\n u: [],\n ul: []\n};\n// js-docs-end allow-list\n\nconst uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);\n\n/**\n * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation\n * contexts.\n *\n * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38\n */\n// eslint-disable-next-line unicorn/better-regex\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;\nconst allowedAttribute = (attribute, allowedAttributeList) => {\n const attributeName = attribute.nodeName.toLowerCase();\n if (allowedAttributeList.includes(attributeName)) {\n if (uriAttributes.has(attributeName)) {\n return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue));\n }\n return true;\n }\n\n // Check if a regular expression validates the attribute.\n return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName));\n};\nfunction sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {\n if (!unsafeHtml.length) {\n return unsafeHtml;\n }\n if (sanitizeFunction && typeof sanitizeFunction === 'function') {\n return sanitizeFunction(unsafeHtml);\n }\n const domParser = new window.DOMParser();\n const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');\n const elements = [].concat(...createdDocument.body.querySelectorAll('*'));\n for (const element of elements) {\n const elementName = element.nodeName.toLowerCase();\n if (!Object.keys(allowList).includes(elementName)) {\n element.remove();\n continue;\n }\n const attributeList = [].concat(...element.attributes);\n const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);\n for (const attribute of attributeList) {\n if (!allowedAttribute(attribute, allowedAttributes)) {\n element.removeAttribute(attribute.nodeName);\n }\n }\n }\n return createdDocument.body.innerHTML;\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap util/template-factory.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$5 = 'TemplateFactory';\nconst Default$4 = {\n allowList: DefaultAllowlist,\n content: {},\n // { selector : text , selector2 : text2 , }\n extraClass: '',\n html: false,\n sanitize: true,\n sanitizeFn: null,\n template: '
'\n};\nconst DefaultType$4 = {\n allowList: 'object',\n content: 'object',\n extraClass: '(string|function)',\n html: 'boolean',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n template: 'string'\n};\nconst DefaultContentType = {\n entry: '(string|element|function|null)',\n selector: '(string|element)'\n};\n\n/**\n * Class definition\n */\n\nclass TemplateFactory extends Config {\n constructor(config) {\n super();\n this._config = this._getConfig(config);\n }\n\n // Getters\n static get Default() {\n return Default$4;\n }\n static get DefaultType() {\n return DefaultType$4;\n }\n static get NAME() {\n return NAME$5;\n }\n\n // Public\n getContent() {\n return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean);\n }\n hasContent() {\n return this.getContent().length > 0;\n }\n changeContent(content) {\n this._checkContent(content);\n this._config.content = {\n ...this._config.content,\n ...content\n };\n return this;\n }\n toHtml() {\n const templateWrapper = document.createElement('div');\n templateWrapper.innerHTML = this._maybeSanitize(this._config.template);\n for (const [selector, text] of Object.entries(this._config.content)) {\n this._setContent(templateWrapper, text, selector);\n }\n const template = templateWrapper.children[0];\n const extraClass = this._resolvePossibleFunction(this._config.extraClass);\n if (extraClass) {\n template.classList.add(...extraClass.split(' '));\n }\n return template;\n }\n\n // Private\n _typeCheckConfig(config) {\n super._typeCheckConfig(config);\n this._checkContent(config.content);\n }\n _checkContent(arg) {\n for (const [selector, content] of Object.entries(arg)) {\n super._typeCheckConfig({\n selector,\n entry: content\n }, DefaultContentType);\n }\n }\n _setContent(template, content, selector) {\n const templateElement = SelectorEngine.findOne(selector, template);\n if (!templateElement) {\n return;\n }\n content = this._resolvePossibleFunction(content);\n if (!content) {\n templateElement.remove();\n return;\n }\n if (isElement(content)) {\n this._putElementInTemplate(getElement(content), templateElement);\n return;\n }\n if (this._config.html) {\n templateElement.innerHTML = this._maybeSanitize(content);\n return;\n }\n templateElement.textContent = content;\n }\n _maybeSanitize(arg) {\n return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;\n }\n _resolvePossibleFunction(arg) {\n return execute(arg, [this]);\n }\n _putElementInTemplate(element, templateElement) {\n if (this._config.html) {\n templateElement.innerHTML = '';\n templateElement.append(element);\n return;\n }\n templateElement.textContent = element.textContent;\n }\n}\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$4 = 'tooltip';\nconst DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);\nconst CLASS_NAME_FADE$2 = 'fade';\nconst CLASS_NAME_MODAL = 'modal';\nconst CLASS_NAME_SHOW$2 = 'show';\nconst SELECTOR_TOOLTIP_INNER = '.tooltip-inner';\nconst SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;\nconst EVENT_MODAL_HIDE = 'hide.bs.modal';\nconst TRIGGER_HOVER = 'hover';\nconst TRIGGER_FOCUS = 'focus';\nconst TRIGGER_CLICK = 'click';\nconst TRIGGER_MANUAL = 'manual';\nconst EVENT_HIDE$2 = 'hide';\nconst EVENT_HIDDEN$2 = 'hidden';\nconst EVENT_SHOW$2 = 'show';\nconst EVENT_SHOWN$2 = 'shown';\nconst EVENT_INSERTED = 'inserted';\nconst EVENT_CLICK$1 = 'click';\nconst EVENT_FOCUSIN$1 = 'focusin';\nconst EVENT_FOCUSOUT$1 = 'focusout';\nconst EVENT_MOUSEENTER = 'mouseenter';\nconst EVENT_MOUSELEAVE = 'mouseleave';\nconst AttachmentMap = {\n AUTO: 'auto',\n TOP: 'top',\n RIGHT: isRTL() ? 'left' : 'right',\n BOTTOM: 'bottom',\n LEFT: isRTL() ? 'right' : 'left'\n};\nconst Default$3 = {\n allowList: DefaultAllowlist,\n animation: true,\n boundary: 'clippingParents',\n container: false,\n customClass: '',\n delay: 0,\n fallbackPlacements: ['top', 'right', 'bottom', 'left'],\n html: false,\n offset: [0, 6],\n placement: 'top',\n popperConfig: null,\n sanitize: true,\n sanitizeFn: null,\n selector: false,\n template: '
' + '
' + '
' + '
',\n title: '',\n trigger: 'hover focus'\n};\nconst DefaultType$3 = {\n allowList: 'object',\n animation: 'boolean',\n boundary: '(string|element)',\n container: '(string|element|boolean)',\n customClass: '(string|function)',\n delay: '(number|object)',\n fallbackPlacements: 'array',\n html: 'boolean',\n offset: '(array|string|function)',\n placement: '(string|function)',\n popperConfig: '(null|object|function)',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n selector: '(string|boolean)',\n template: 'string',\n title: '(string|element|function)',\n trigger: 'string'\n};\n\n/**\n * Class definition\n */\n\nclass Tooltip extends BaseComponent {\n constructor(element, config) {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s tooltips require Popper (https://popper.js.org)');\n }\n super(element, config);\n\n // Private\n this._isEnabled = true;\n this._timeout = 0;\n this._isHovered = null;\n this._activeTrigger = {};\n this._popper = null;\n this._templateFactory = null;\n this._newContent = null;\n\n // Protected\n this.tip = null;\n this._setListeners();\n if (!this._config.selector) {\n this._fixTitle();\n }\n }\n\n // Getters\n static get Default() {\n return Default$3;\n }\n static get DefaultType() {\n return DefaultType$3;\n }\n static get NAME() {\n return NAME$4;\n }\n\n // Public\n enable() {\n this._isEnabled = true;\n }\n disable() {\n this._isEnabled = false;\n }\n toggleEnabled() {\n this._isEnabled = !this._isEnabled;\n }\n toggle() {\n if (!this._isEnabled) {\n return;\n }\n this._activeTrigger.click = !this._activeTrigger.click;\n if (this._isShown()) {\n this._leave();\n return;\n }\n this._enter();\n }\n dispose() {\n clearTimeout(this._timeout);\n EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);\n if (this._element.getAttribute('data-bs-original-title')) {\n this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'));\n }\n this._disposePopper();\n super.dispose();\n }\n show() {\n if (this._element.style.display === 'none') {\n throw new Error('Please use show on visible elements');\n }\n if (!(this._isWithContent() && this._isEnabled)) {\n return;\n }\n const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2));\n const shadowRoot = findShadowRoot(this._element);\n const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);\n if (showEvent.defaultPrevented || !isInTheDom) {\n return;\n }\n\n // TODO: v6 remove this or make it optional\n this._disposePopper();\n const tip = this._getTipElement();\n this._element.setAttribute('aria-describedby', tip.getAttribute('id'));\n const {\n container\n } = this._config;\n if (!this._element.ownerDocument.documentElement.contains(this.tip)) {\n container.append(tip);\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));\n }\n this._popper = this._createPopper(tip);\n tip.classList.add(CLASS_NAME_SHOW$2);\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.on(element, 'mouseover', noop);\n }\n }\n const complete = () => {\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2));\n if (this._isHovered === false) {\n this._leave();\n }\n this._isHovered = false;\n };\n this._queueCallback(complete, this.tip, this._isAnimated());\n }\n hide() {\n if (!this._isShown()) {\n return;\n }\n const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2));\n if (hideEvent.defaultPrevented) {\n return;\n }\n const tip = this._getTipElement();\n tip.classList.remove(CLASS_NAME_SHOW$2);\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n for (const element of [].concat(...document.body.children)) {\n EventHandler.off(element, 'mouseover', noop);\n }\n }\n this._activeTrigger[TRIGGER_CLICK] = false;\n this._activeTrigger[TRIGGER_FOCUS] = false;\n this._activeTrigger[TRIGGER_HOVER] = false;\n this._isHovered = null; // it is a trick to support manual triggering\n\n const complete = () => {\n if (this._isWithActiveTrigger()) {\n return;\n }\n if (!this._isHovered) {\n this._disposePopper();\n }\n this._element.removeAttribute('aria-describedby');\n EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2));\n };\n this._queueCallback(complete, this.tip, this._isAnimated());\n }\n update() {\n if (this._popper) {\n this._popper.update();\n }\n }\n\n // Protected\n _isWithContent() {\n return Boolean(this._getTitle());\n }\n _getTipElement() {\n if (!this.tip) {\n this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());\n }\n return this.tip;\n }\n _createTipElement(content) {\n const tip = this._getTemplateFactory(content).toHtml();\n\n // TODO: remove this check in v6\n if (!tip) {\n return null;\n }\n tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2);\n // TODO: v6 the following can be achieved with CSS only\n tip.classList.add(`bs-${this.constructor.NAME}-auto`);\n const tipId = getUID(this.constructor.NAME).toString();\n tip.setAttribute('id', tipId);\n if (this._isAnimated()) {\n tip.classList.add(CLASS_NAME_FADE$2);\n }\n return tip;\n }\n setContent(content) {\n this._newContent = content;\n if (this._isShown()) {\n this._disposePopper();\n this.show();\n }\n }\n _getTemplateFactory(content) {\n if (this._templateFactory) {\n this._templateFactory.changeContent(content);\n } else {\n this._templateFactory = new TemplateFactory({\n ...this._config,\n // the `content` var has to be after `this._config`\n // to override config.content in case of popover\n content,\n extraClass: this._resolvePossibleFunction(this._config.customClass)\n });\n }\n return this._templateFactory;\n }\n _getContentForTemplate() {\n return {\n [SELECTOR_TOOLTIP_INNER]: this._getTitle()\n };\n }\n _getTitle() {\n return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title');\n }\n\n // Private\n _initializeOnDelegatedTarget(event) {\n return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());\n }\n _isAnimated() {\n return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2);\n }\n _isShown() {\n return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2);\n }\n _createPopper(tip) {\n const placement = execute(this._config.placement, [this, tip, this._element]);\n const attachment = AttachmentMap[placement.toUpperCase()];\n return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment));\n }\n _getOffset() {\n const {\n offset\n } = this._config;\n if (typeof offset === 'string') {\n return offset.split(',').map(value => Number.parseInt(value, 10));\n }\n if (typeof offset === 'function') {\n return popperData => offset(popperData, this._element);\n }\n return offset;\n }\n _resolvePossibleFunction(arg) {\n return execute(arg, [this._element]);\n }\n _getPopperConfig(attachment) {\n const defaultBsPopperConfig = {\n placement: attachment,\n modifiers: [{\n name: 'flip',\n options: {\n fallbackPlacements: this._config.fallbackPlacements\n }\n }, {\n name: 'offset',\n options: {\n offset: this._getOffset()\n }\n }, {\n name: 'preventOverflow',\n options: {\n boundary: this._config.boundary\n }\n }, {\n name: 'arrow',\n options: {\n element: `.${this.constructor.NAME}-arrow`\n }\n }, {\n name: 'preSetPlacement',\n enabled: true,\n phase: 'beforeMain',\n fn: data => {\n // Pre-set Popper's placement attribute in order to read the arrow sizes properly.\n // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement\n this._getTipElement().setAttribute('data-popper-placement', data.state.placement);\n }\n }]\n };\n return {\n ...defaultBsPopperConfig,\n ...execute(this._config.popperConfig, [defaultBsPopperConfig])\n };\n }\n _setListeners() {\n const triggers = this._config.trigger.split(' ');\n for (const trigger of triggers) {\n if (trigger === 'click') {\n EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event);\n context.toggle();\n });\n } else if (trigger !== TRIGGER_MANUAL) {\n const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1);\n const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1);\n EventHandler.on(this._element, eventIn, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event);\n context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;\n context._enter();\n });\n EventHandler.on(this._element, eventOut, this._config.selector, event => {\n const context = this._initializeOnDelegatedTarget(event);\n context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);\n context._leave();\n });\n }\n }\n this._hideModalHandler = () => {\n if (this._element) {\n this.hide();\n }\n };\n EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);\n }\n _fixTitle() {\n const title = this._element.getAttribute('title');\n if (!title) {\n return;\n }\n if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {\n this._element.setAttribute('aria-label', title);\n }\n this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility\n this._element.removeAttribute('title');\n }\n _enter() {\n if (this._isShown() || this._isHovered) {\n this._isHovered = true;\n return;\n }\n this._isHovered = true;\n this._setTimeout(() => {\n if (this._isHovered) {\n this.show();\n }\n }, this._config.delay.show);\n }\n _leave() {\n if (this._isWithActiveTrigger()) {\n return;\n }\n this._isHovered = false;\n this._setTimeout(() => {\n if (!this._isHovered) {\n this.hide();\n }\n }, this._config.delay.hide);\n }\n _setTimeout(handler, timeout) {\n clearTimeout(this._timeout);\n this._timeout = setTimeout(handler, timeout);\n }\n _isWithActiveTrigger() {\n return Object.values(this._activeTrigger).includes(true);\n }\n _getConfig(config) {\n const dataAttributes = Manipulator.getDataAttributes(this._element);\n for (const dataAttribute of Object.keys(dataAttributes)) {\n if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {\n delete dataAttributes[dataAttribute];\n }\n }\n config = {\n ...dataAttributes,\n ...(typeof config === 'object' && config ? config : {})\n };\n config = this._mergeConfigObj(config);\n config = this._configAfterMerge(config);\n this._typeCheckConfig(config);\n return config;\n }\n _configAfterMerge(config) {\n config.container = config.container === false ? document.body : getElement(config.container);\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n };\n }\n if (typeof config.title === 'number') {\n config.title = config.title.toString();\n }\n if (typeof config.content === 'number') {\n config.content = config.content.toString();\n }\n return config;\n }\n _getDelegateConfig() {\n const config = {};\n for (const [key, value] of Object.entries(this._config)) {\n if (this.constructor.Default[key] !== value) {\n config[key] = value;\n }\n }\n config.selector = false;\n config.trigger = 'manual';\n\n // In the future can be replaced with:\n // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])\n // `Object.fromEntries(keysWithDifferentValues)`\n return config;\n }\n _disposePopper() {\n if (this._popper) {\n this._popper.destroy();\n this._popper = null;\n }\n if (this.tip) {\n this.tip.remove();\n this.tip = null;\n }\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Tooltip.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n });\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Tooltip);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$3 = 'popover';\nconst SELECTOR_TITLE = '.popover-header';\nconst SELECTOR_CONTENT = '.popover-body';\nconst Default$2 = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '
' + '
' + '

' + '
' + '
',\n trigger: 'click'\n};\nconst DefaultType$2 = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n};\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default$2;\n }\n static get DefaultType() {\n return DefaultType$2;\n }\n static get NAME() {\n return NAME$3;\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent();\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n };\n }\n _getContent() {\n return this._resolvePossibleFunction(this._config.content);\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Popover.getOrCreateInstance(this, config);\n if (typeof config !== 'string') {\n return;\n }\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n data[config]();\n });\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Popover);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\n/**\n * Constants\n */\n\nconst NAME$2 = 'scrollspy';\nconst DATA_KEY$2 = 'bs.scrollspy';\nconst EVENT_KEY$2 = `.${DATA_KEY$2}`;\nconst DATA_API_KEY = '.data-api';\nconst EVENT_ACTIVATE = `activate${EVENT_KEY$2}`;\nconst EVENT_CLICK = `click${EVENT_KEY$2}`;\nconst EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`;\nconst CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';\nconst CLASS_NAME_ACTIVE$1 = 'active';\nconst SELECTOR_DATA_SPY = '[data-bs-spy=\"scroll\"]';\nconst SELECTOR_TARGET_LINKS = '[href]';\nconst SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';\nconst SELECTOR_NAV_LINKS = '.nav-link';\nconst SELECTOR_NAV_ITEMS = '.nav-item';\nconst SELECTOR_LIST_ITEMS = '.list-group-item';\nconst SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`;\nconst SELECTOR_DROPDOWN = '.dropdown';\nconst SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';\nconst Default$1 = {\n offset: null,\n // TODO: v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: '0px 0px -25%',\n smoothScroll: false,\n target: null,\n threshold: [0.1, 0.5, 1]\n};\nconst DefaultType$1 = {\n offset: '(number|null)',\n // TODO v6 @deprecated, keep it for backwards compatibility reasons\n rootMargin: 'string',\n smoothScroll: 'boolean',\n target: 'element',\n threshold: 'array'\n};\n\n/**\n * Class definition\n */\n\nclass ScrollSpy extends BaseComponent {\n constructor(element, config) {\n super(element, config);\n\n // this._element is the observablesContainer and config.target the menu links wrapper\n this._targetLinks = new Map();\n this._observableSections = new Map();\n this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element;\n this._activeTarget = null;\n this._observer = null;\n this._previousScrollData = {\n visibleEntryTop: 0,\n parentScrollTop: 0\n };\n this.refresh(); // initialize\n }\n\n // Getters\n static get Default() {\n return Default$1;\n }\n static get DefaultType() {\n return DefaultType$1;\n }\n static get NAME() {\n return NAME$2;\n }\n\n // Public\n refresh() {\n this._initializeTargetsAndObservables();\n this._maybeEnableSmoothScroll();\n if (this._observer) {\n this._observer.disconnect();\n } else {\n this._observer = this._getNewObserver();\n }\n for (const section of this._observableSections.values()) {\n this._observer.observe(section);\n }\n }\n dispose() {\n this._observer.disconnect();\n super.dispose();\n }\n\n // Private\n _configAfterMerge(config) {\n // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case\n config.target = getElement(config.target) || document.body;\n\n // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only\n config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin;\n if (typeof config.threshold === 'string') {\n config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value));\n }\n return config;\n }\n _maybeEnableSmoothScroll() {\n if (!this._config.smoothScroll) {\n return;\n }\n\n // unregister any previous listeners\n EventHandler.off(this._config.target, EVENT_CLICK);\n EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {\n const observableSection = this._observableSections.get(event.target.hash);\n if (observableSection) {\n event.preventDefault();\n const root = this._rootElement || window;\n const height = observableSection.offsetTop - this._element.offsetTop;\n if (root.scrollTo) {\n root.scrollTo({\n top: height,\n behavior: 'smooth'\n });\n return;\n }\n\n // Chrome 60 doesn't support `scrollTo`\n root.scrollTop = height;\n }\n });\n }\n _getNewObserver() {\n const options = {\n root: this._rootElement,\n threshold: this._config.threshold,\n rootMargin: this._config.rootMargin\n };\n return new IntersectionObserver(entries => this._observerCallback(entries), options);\n }\n\n // The logic of selection\n _observerCallback(entries) {\n const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`);\n const activate = entry => {\n this._previousScrollData.visibleEntryTop = entry.target.offsetTop;\n this._process(targetElement(entry));\n };\n const parentScrollTop = (this._rootElement || document.documentElement).scrollTop;\n const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop;\n this._previousScrollData.parentScrollTop = parentScrollTop;\n for (const entry of entries) {\n if (!entry.isIntersecting) {\n this._activeTarget = null;\n this._clearActiveClass(targetElement(entry));\n continue;\n }\n const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop;\n // if we are scrolling down, pick the bigger offsetTop\n if (userScrollsDown && entryIsLowerThanPrevious) {\n activate(entry);\n // if parent isn't scrolled, let's keep the first visible item, breaking the iteration\n if (!parentScrollTop) {\n return;\n }\n continue;\n }\n\n // if we are scrolling up, pick the smallest offsetTop\n if (!userScrollsDown && !entryIsLowerThanPrevious) {\n activate(entry);\n }\n }\n }\n _initializeTargetsAndObservables() {\n this._targetLinks = new Map();\n this._observableSections = new Map();\n const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target);\n for (const anchor of targetLinks) {\n // ensure that the anchor has an id and is not disabled\n if (!anchor.hash || isDisabled(anchor)) {\n continue;\n }\n const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element);\n\n // ensure that the observableSection exists & is visible\n if (isVisible(observableSection)) {\n this._targetLinks.set(decodeURI(anchor.hash), anchor);\n this._observableSections.set(anchor.hash, observableSection);\n }\n }\n }\n _process(target) {\n if (this._activeTarget === target) {\n return;\n }\n this._clearActiveClass(this._config.target);\n this._activeTarget = target;\n target.classList.add(CLASS_NAME_ACTIVE$1);\n this._activateParents(target);\n EventHandler.trigger(this._element, EVENT_ACTIVATE, {\n relatedTarget: target\n });\n }\n _activateParents(target) {\n // Activate dropdown parents\n if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {\n SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1);\n return;\n }\n for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {\n // Set triggered links parents as active\n // With both