diff --git a/CHANGELOG.md b/CHANGELOG.md index 2321f371..3b62179a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,15 @@ -# NEXT_RELEASE +# v0.3.0 * Extract CDR-specific logic from this repository. Moved to the `seaice_ecdr` (https://github.com/nsidc/seaice_ecdr/) * Remove `Hemisphere` type. Import from `pm_tb_data` instead. +* Remove CLI for this library. It is now the responsiblity of programs utlizing + this library to define how inputs/outputs are handled. This library purely + focuses on the implementation of the sea ice concentration algorithms. +* Related to the above, remove code related to reading/handling ancillary files + that define e.g., valid ice masks. This code was very specific to NSIDC's + internal infrastructure and unpublished data. It is now the responsibility of + other programs utlizing this library to provide masks, input TBs, etc. # v0.2.0 diff --git a/README.md b/README.md index 183d39c3..54cd1775 100644 --- a/README.md +++ b/README.md @@ -46,49 +46,7 @@ $ conda activate pm_icecon ## Usage -### CLI - -There is a command line interface defined using common defaults for testing -purposes at NSIDC. - -NOTE: the CLI relies on hard-coded paths to mask files on NSIDC's virtual -machine infrastructure. This CLI will not currently work for those outside of -NSIDC. We plan to change this in the future. - -The CLI can be interacted with via `scripts/cli.sh`: - -``` -$ ./scripts/cli.sh --help -Usage: python -m pm_icecon.cli.entrypoint [OPTIONS] COMMAND [ARGS]... - - Run the nasateam or bootstrap algorithm. - -Options: - --help Show this message and exit. - -Commands: - bootstrap Run the bootstrap algorithm. - nasateam Run the nasateam algorithm. -``` - -E.g., to create a NetCDF file with a `conc` variable containing concentration -values from AU_SI12 from the bootstrap algorithm: - -``` -$ ./scripts/cli.sh bootstrap amsr2 --date 2022-08-01 --hemisphere north --output-dir /tmp/ --resolution 12 -2022-09-12 15:21:44.482 | INFO | pm_icecon.bt.cli:amsr2:82 - Wrote AMSR2 concentration field: /tmp/bt_NH_20220801_u2_12km.nc -``` - -E.g., to create a NetCDF file with a `conc` variable containing concentration -values from AU_SI25 from the nasateam algorithm: - -``` -$ ./scripts/cli.sh nasateam amsr2 --date 2022-08-01 --hemisphere south --output-dir /tmp/ --resolution 25 -2022-09-12 15:23:34.993 | INFO | pm_icecon.nt.cli:amsr2:82 - Wrote AMSR2 concentration field: /tmp/nt_SH_20220801_u2_25km.nc -``` - -### Scripting -#### Bootstrap +### Bootstrap Users can write a script using the functions provided in this repo to run the @@ -104,7 +62,7 @@ hard-coded defaults for testing purposes at NSIDC. This includes paths to data on NSIDC infrastructure that are not available to the public. -#### Nasateam +### Nasateam The main entrypoint to running the nasateam code on input Tbs is the `nasateam` function defined in `pm_icecon/nt/compute_nt_ic.py`. diff --git a/conda-lock.yml b/conda-lock.yml index dbed8216..502dfda9 100644 --- a/conda-lock.yml +++ b/conda-lock.yml @@ -13,7 +13,7 @@ version: 1 metadata: content_hash: - linux-64: 07598089d9adb405bdc426fe233b2c4b754709e1506fcb1cedc8a9d6ca375922 + linux-64: dca25c4c1ac3655244e696e9709a86855c0444774f9eec0e931ec53065cf326f osx-arm64: b3f6876bd5fdf4eb9baab58469293757c66e43400343764746dccc9461459525 osx-64: 294ba8b3bdf409fd8f027ef2c79afd5c9802e0bf6deecbfc939202e0f59cee3c win-64: 4c39fe50554cf6d1d226fd08723552524ab28e0d73927f513feef46e282b26cd @@ -42,14 +42,14 @@ package: category: main optional: false - name: ca-certificates - version: 2023.7.22 + version: 2023.11.17 manager: conda platform: linux-64 dependencies: {} - url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.11.17-hbcca054_0.conda hash: - md5: a73ecd2988327ad4c8f2c331482917f2 - sha256: 525b7b6b5135b952ec1808de84e5eca57c7c7ff144e29ef3e96ae4040ff432c1 + md5: 01ffc8d36f9eba0ce0b3c1955fa780ee + sha256: fb4b9f4b7d885002db0b93e22f44b5b03791ef3d4efdc9d0662185a0faafd6b6 category: main optional: false - name: font-ttf-dejavu-sans-mono @@ -90,10 +90,10 @@ package: manager: conda platform: linux-64 dependencies: {} - url: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-hab24e00_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_1.conda hash: - md5: 19410c3df09dfb12d1206132a1d357c5 - sha256: 470d5db54102bd51dbb0c5990324a2f4a0bc976faa493b22193338adb9882e2e + md5: 6185f640c43843e5ad6fd1c5372c3f80 + sha256: 056c85b482d58faab5fd4670b6c1f5df0986314cca3bc831d458b22e4ef2c792 category: main optional: false - name: ld_impl_linux-64 @@ -112,10 +112,10 @@ package: manager: conda platform: linux-64 dependencies: {} - url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_3.conda hash: - md5: 9172c297304f2a20134fc56c97fbe229 - sha256: ab22ecdc974cdbe148874ea876d9c564294d5eafa760f403ed4fd495307b4243 + md5: 937eaed008f6bf2191c5fe76f87755e9 + sha256: 6c6c49efedcc5709a66f19fb6b26b69c6a5245310fd1d9a901fd5e38aaf7f882 category: main optional: false - name: poppler-data @@ -183,10 +183,10 @@ package: platform: linux-64 dependencies: _libgcc_mutex: '0.1' - url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_3.conda hash: - md5: e2042154faafe61969556f28bade94b9 - sha256: e1e82348f8296abfe344162b3b5f0ddc2f504759ebeb8b337ba99beaae583b15 + md5: 7124cbb46b13d395bdde68f2d215c989 + sha256: 6ebedee39b6bbbc969715d0d7fa4b381cce67e1139862604ffa393f821c08e81 category: main optional: false - name: _openmp_mutex @@ -221,10 +221,10 @@ package: dependencies: _libgcc_mutex: '0.1' _openmp_mutex: '>=4.5' - url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_3.conda hash: - md5: c28003b0be0494f9a7664389146716ff - sha256: d361d3c87c376642b99c1fc25cddec4b9905d3d9b9203c1c545b8c8c1b04539a + md5: 23fdf1fef05baeb7eadc2aed5fb0011f + sha256: 5e88f658e07a30ab41b154b42c59f079b168acfa9551a75bdc972099453f4105 category: main optional: false - name: bzip2 @@ -232,23 +232,23 @@ package: manager: conda platform: linux-64 dependencies: - libgcc-ng: '>=9.3.0' - url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2 + libgcc-ng: '>=12' + url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda hash: - md5: a1fd65c7ccbf10880423d82bca54eb54 - sha256: cb521319804640ff2ad6a9f118d972ed76d86bea44e5626c09a13d38f562e1fa + md5: 69b8b6202a07720f448be700e300ccf4 + sha256: 242c0c324507ee172c0e0dd2045814e746bb303d1eb78870d182ceb0abc726a8 category: main optional: false - name: c-ares - version: 1.20.1 + version: 1.24.0 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' - url: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.20.1-hd590300_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda hash: - md5: 2facbaf5ee1a56967aecaee89799160e - sha256: 1700d9ebfd3b21c8b50e12a502f26e015719e1f3dbb5d491b5be061cf148ca7a + md5: f5842b88e9cbfa177abfaeacd457a45d + sha256: b68b0611d1c9d0222b56d5fe3d634e7a26979c3aef30f5f48b1593e7249e8f7a category: main optional: false - name: fmt @@ -431,11 +431,11 @@ package: manager: conda platform: linux-64 dependencies: - libgcc-ng: '>=7.5.0' - url: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-h516909a_1.tar.bz2 + libgcc-ng: '>=12' + url: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda hash: - md5: 6f8720dff19e17ce5d48cfe7f3d2f0a3 - sha256: 8c9635aa0ea28922877dc96358f9547f6a55fc7e2eb75a556b05f1725496baf9 + md5: 172bf1cd1ff8629f2b1179945ed45055 + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 category: main optional: false - name: libexpat @@ -468,10 +468,10 @@ package: platform: linux-64 dependencies: libgcc-ng: '>=13.2.0' - url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_3.conda hash: - md5: 78fdab09d9138851dde2b5fe2a11019e - sha256: 55ecf5c46c05a98b4822a041d6e1cb196a7b0606126eb96b24131b7d2c8ca561 + md5: c714d905cdfa0e70200f68b80cc04764 + sha256: 0084a1d29a4f8ee3b8edad80eb6c42e5f0480f054f28cf713fb314bebb347a50 category: main optional: false - name: libiconv @@ -479,11 +479,11 @@ package: manager: conda platform: linux-64 dependencies: - libgcc-ng: '>=10.3.0' - url: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-h166bdaf_0.tar.bz2 + libgcc-ng: '>=12' + url: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda hash: - md5: b62b52da46c39ee2bc3c162ac7f1804d - sha256: 6a81ebac9f1aacdf2b4f945c87ad62b972f0f69c8e0981d68e111739e6720fd7 + md5: d66573916ffcf376178462f1b61c941e + sha256: 8ac2f6a9f186e76539439e50505d98581472fedb347a20e7d1f36429849f05c9 category: main optional: false - name: libjpeg-turbo @@ -590,10 +590,10 @@ package: platform: linux-64 dependencies: libgcc-ng: '>=12' - url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-hcb278e6_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda hash: - md5: 681105bccc2a3f7f1a837d47d39c9179 - sha256: ccf61e61d58a8a7b2d66822d5568e2dc9387883dd9b2da61e1d787ece4c4979a + md5: 7dbaa197d7ba6032caf7ae7f32c1efa0 + sha256: 91cc03f14caf96243cead96c76fe91ab5925a695d892e83285461fb927dece5e category: main optional: false - name: nspr @@ -685,15 +685,15 @@ package: category: main optional: false - name: ripgrep - version: 13.0.0 + version: 14.0.3 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' - url: https://conda.anaconda.org/conda-forge/linux-64/ripgrep-13.0.0-he8a937b_3.conda + url: https://conda.anaconda.org/conda-forge/linux-64/ripgrep-14.0.3-he8a937b_1.conda hash: - md5: bcc1bc3df81a43bad48b94c155e8baa1 - sha256: 52ef6180dd50753bb6861e774580d3f6a5bd6aaec6af58cbd25182b6fdab89e6 + md5: febc6d68fd4404694e19f40684b28ccf + sha256: b2a92d08c289f98f8892326f3b0ef53b658bc8eeb0e239f794f64d4f954a05e9 category: main optional: false - name: snappy @@ -929,10 +929,10 @@ package: platform: linux-64 dependencies: libgfortran5: 13.2.0 - url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_3.conda hash: - md5: e75a75a6eaf6f318dae2631158c46575 - sha256: 767d71999e5386210fe2acaf1b67073e7943c2af538efa85c101e3401e94ff62 + md5: 73031c79546ad06f1fe62e57fdd021bc + sha256: 5b918950b84605b6865de438757f507b1eff73c96fd562f7022c80028b088c14 category: main optional: false - name: libkml @@ -952,20 +952,20 @@ package: category: main optional: false - name: libnghttp2 - version: 1.52.0 + version: 1.58.0 manager: conda platform: linux-64 dependencies: - c-ares: '>=1.18.1,<2.0a0' + c-ares: '>=1.21.0,<2.0a0' libev: '>=4.33,<4.34.0a0' libgcc-ng: '>=12' libstdcxx-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - openssl: '>=3.0.8,<4.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.52.0-h61bc06f_0.conda + openssl: '>=3.1.4,<4.0a0' + url: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_0.conda hash: - md5: 613955a50485812985c059e7b269f42e - sha256: ecd6b08c2b5abe7d1586428c4dd257dcfa00ee53700d79cdc8bca098fdfbd79a + md5: 9b13d5ee90fc9f09d54fd403247342b4 + sha256: 151b18e4f92dcca263a6d23e4beb0c4e2287aa1c7d0587ff71ef50035ed34aca category: main optional: false - name: libpng @@ -982,7 +982,7 @@ package: category: main optional: false - name: libprotobuf - version: 4.24.3 + version: 4.24.4 manager: conda platform: linux-64 dependencies: @@ -990,10 +990,10 @@ package: libgcc-ng: '>=12' libstdcxx-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.24.3-hf27288f_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.24.4-hf27288f_0.conda hash: - md5: 5097789a2bc83e697d7509df57f25bfd - sha256: 911ad483f051d96c9f07ecd8177546763c2da601e26941b434c3a09fa9fcd8f8 + md5: 1a0287ab734591ad63603734f923016b + sha256: 3e0f6454190abb27edd2aeb724688ee440de133edb02cbb17d5609ba36aa8be0 category: main optional: false - name: libre2-11 @@ -1025,30 +1025,30 @@ package: category: main optional: false - name: libsolv - version: 0.7.25 + version: 0.7.27 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' libstdcxx-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.25-hfc55251_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.27-hfc55251_0.conda hash: - md5: 17e88b01ca0601d5fd55bb72a9e352d9 - sha256: 87bfa02036c5d813994be1bb270ee3c7bbb754e00d8141dd3fbdb0fb63ff4417 + md5: 7dc82edcd617c399ca7fdb51d993a0c2 + sha256: dccc5ff38a96bb3dd8f8c73664734c61a62358f064995c732090428cb92e52d3 category: main optional: false - name: libsqlite - version: 3.43.2 + version: 3.44.2 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.43.2-h2797004_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.44.2-h2797004_0.conda hash: - md5: 4b441a1ee22397d5a27dc1126b849edd - sha256: b30279b67fce2382a93c638625ff2b284324e2347e30bd0acab813d89289c18a + md5: 3b6a9f225c3dbe0d24f4fedd4625c5bf + sha256: ee2c4d724a3ed60d5b458864d66122fb84c6ce1df62f735f90d8db17b66cd88a category: main optional: false - name: libssh2 @@ -1081,7 +1081,7 @@ package: category: main optional: false - name: libxml2 - version: 2.11.5 + version: 2.11.6 manager: conda platform: linux-64 dependencies: @@ -1090,10 +1090,10 @@ package: libiconv: '>=1.17,<2.0a0' libzlib: '>=1.2.13,<1.3.0a0' xz: '>=5.2.6,<6.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.11.5-h232c23b_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.11.6-h232c23b_0.conda hash: - md5: f3858448893839820d4bcfb14ad3ecdf - sha256: 1b3cb6864de1a558ea5fb144c780121d52507837d15df0600491d8ed92cff90c + md5: 427a3e59d66cb5d145020bd9c6493334 + sha256: e6183d5e57ee48cc1fc4340477c31a6bd8be4d3ba5dded82cbca0d5280591086 category: main optional: false - name: libzip @@ -1159,10 +1159,10 @@ package: dependencies: libgcc-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda hash: - md5: 513336054f884f95d9fd925748f41ef3 - sha256: 679e944eb93fde45d0963a22598fafacbb429bb9e7ee26009ba81c4e0c435055 + md5: d453b98d9c83e71da0741bb0ff4d76bc + sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e category: main optional: false - name: xorg-libsm @@ -1306,7 +1306,7 @@ package: category: main optional: false - name: libglib - version: 2.78.0 + version: 2.78.1 manager: conda platform: linux-64 dependencies: @@ -1317,24 +1317,24 @@ package: libstdcxx-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' pcre2: '>=10.40,<10.41.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.78.0-hebfc3b9_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.78.1-hebfc3b9_0.conda hash: - md5: e618003da3547216310088478e475945 - sha256: 96ec4dc5e38f434aa5862cb46d74923cce1445de3cd0b9d61e3e63102b163af6 + md5: ddd09e8904fde46b85f41896621803e6 + sha256: 44c5f58593b074886436db7d13fdfcba2fe3731867ea52237f049b8400341a2b category: main optional: false - name: libopenblas - version: 0.3.24 + version: 0.3.25 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' libgfortran-ng: '' libgfortran5: '>=12.3.0' - url: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.24-pthreads_h413a1c8_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.25-pthreads_h413a1c8_0.conda hash: - md5: 6e4ef6ca28655124dcde9bd500e44c32 - sha256: c8e080ae4d57506238023e98869928ae93564e6407ef5b0c4d3a337e8c2b7662 + md5: d172b34a443b95f86089e8229ddc9a17 + sha256: 628564517895ee1b09cf72c817548bd80ef1acce6a8214a8520d9f7b44c4cfaf category: main optional: false - name: libtiff @@ -1358,24 +1358,24 @@ package: category: main optional: false - name: nss - version: '3.94' + version: '3.96' manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' libgcc-ng: '>=12' - libsqlite: '>=3.43.0,<4.0a0' + libsqlite: '>=3.44.2,<4.0a0' libstdcxx-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' nspr: '>=4.35,<5.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/nss-3.94-h1d7d5a4_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/nss-3.96-h1d7d5a4_0.conda hash: - md5: 7caef74bbfa730e014b20f0852068509 - sha256: c9b7910fc554c6550905b9150f4c8230e973ca63f41b42f2c18a49e8aa458e78 + md5: 1c8f8b8eb041ecd54053fc4b6ad57957 + sha256: 9f73d55f42085d7bca59c675fea57dae2a21f3d62530e47b3d89db89ca444767 category: main optional: false - name: python - version: 3.10.12 + version: 3.10.13 manager: conda platform: linux-64 dependencies: @@ -1383,20 +1383,20 @@ package: ld_impl_linux-64: '>=2.36.1' libffi: '>=3.4,<4.0a0' libgcc-ng: '>=12' - libnsl: '>=2.0.0,<2.1.0a0' - libsqlite: '>=3.42.0,<4.0a0' + libnsl: '>=2.0.1,<2.1.0a0' + libsqlite: '>=3.43.2,<4.0a0' libuuid: '>=2.38.1,<3.0a0' libzlib: '>=1.2.13,<1.3.0a0' ncurses: '>=6.4,<7.0a0' - openssl: '>=3.1.1,<4.0a0' + openssl: '>=3.1.4,<4.0a0' readline: '>=8.2,<9.0a0' - tk: '>=8.6.12,<8.7.0a0' + tk: '>=8.6.13,<8.7.0a0' tzdata: '' xz: '>=5.2.6,<6.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.12-hd12c33a_0_cpython.conda + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.13-hd12c33a_0_cpython.conda hash: - md5: eb6f1df105f37daedd6dca78523baa75 - sha256: 05e2a7ce916d259f11979634f770f31027d0a5d18463b094e64a30500f900699 + md5: f3a8c32aa764c3e7188b4b810fc9d6ce + sha256: a53410f459f314537b379982717b1c5911efc2f0cc26d63c4d6f831bcb31c964 category: main optional: false - name: re2 @@ -1412,19 +1412,19 @@ package: category: main optional: false - name: sqlite - version: 3.43.2 + version: 3.44.2 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' - libsqlite: 3.43.2 + libsqlite: 3.44.2 libzlib: '>=1.2.13,<1.3.0a0' ncurses: '>=6.4,<7.0a0' readline: '>=8.2,<9.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.43.2-h2c6b66d_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.44.2-h2c6b66d_0.conda hash: - md5: c37b95bcd6c6833dacfd5df0ae2f4303 - sha256: f49389e9cce5bdc451d1c5b56972cf5f75b1ba00350d35ab099848e65b32e94f + md5: 4f2892c672829693fd978d065db4e8be + sha256: bae479520fe770fe11996b4c240923ed097f851fbd2401d55540e551c9dbbef7 category: main optional: false - name: xorg-libx11 @@ -1479,30 +1479,6 @@ package: sha256: 063639cd568f5c7a557b0fb1cc27f098598c0d8ff869088bfeb82934674f8821 category: main optional: false -- name: backcall - version: 0.2.0 - manager: conda - platform: linux-64 - dependencies: - python: '' - url: https://conda.anaconda.org/conda-forge/noarch/backcall-0.2.0-pyh9f0ad1d_0.tar.bz2 - hash: - md5: 6006a6d08a3fa99268a2681c7fb55213 - sha256: ee62d6434090c1327a48551734e06bd10e65a64ef7f3b6e68719500dab0e42b9 - category: main - optional: false -- name: backports - version: '1.0' - manager: conda - platform: linux-64 - dependencies: - python: '>=2.7' - url: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_3.conda - hash: - md5: 54ca2e08b3220c148a1d8329c2678e02 - sha256: 711602276ae39276cb0faaca6fd0ac851fff0ca17151917569174841ef830bbd - category: main - optional: false - name: bounded-pool-executor version: 0.0.3 manager: conda @@ -1545,18 +1521,6 @@ package: sha256: e22268d81905338570786921b3def88e55f9ed6d0ccdd17d9fbae31a02fbef69 category: main optional: false -- name: bump2version - version: 1.0.1 - manager: conda - platform: linux-64 - dependencies: - python: '' - url: https://conda.anaconda.org/conda-forge/noarch/bump2version-1.0.1-pyh9f0ad1d_0.tar.bz2 - hash: - md5: 1b3fd56f54baa99e3c9967caf279f66f - sha256: c3cf2e47b0aee001025ad29061222b552a60362ec9febd355c5eb4d3a06beef8 - category: main - optional: false - name: cached_property version: 1.5.2 manager: conda @@ -1582,15 +1546,15 @@ package: category: main optional: false - name: certifi - version: 2023.7.22 + version: 2023.11.17 manager: conda platform: linux-64 dependencies: python: '>=3.7' - url: https://conda.anaconda.org/conda-forge/noarch/certifi-2023.7.22-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/certifi-2023.11.17-pyhd8ed1ab_0.conda hash: - md5: 7f3dbc9179b4dde7da98dfb151d0ad22 - sha256: db66e31866ff4250c190788769e3a8a1709237c3e9c38d7143aae95ab75fcb31 + md5: 2011bcf45376341dd1d690263fdbc789 + sha256: afa22b77128a812cb57bc707c297d926561bd225a3d9dd74205d87a3b2d14a96 category: main optional: false - name: cfgv @@ -1619,15 +1583,15 @@ package: category: main optional: false - name: charset-normalizer - version: 3.3.1 + version: 3.3.2 manager: conda platform: linux-64 dependencies: python: '>=3.7' - url: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda hash: - md5: 985378f74689fccce52f158027bd9acd - sha256: a31739c49c4b1c8e0cbdec965ba152683d36ce6e23bdaefcfee99937524dabd1 + md5: 7f4a9e3fcff3f6356ae99244a014da6a + sha256: 20cae47d31fdd58d99c4d2e65fbdcefa0b0de0c84e455ba9d6356a4bdbc4b5b9 category: main optional: false - name: click @@ -1730,51 +1694,51 @@ package: category: main optional: false - name: distlib - version: 0.3.7 + version: 0.3.8 manager: conda platform: linux-64 dependencies: python: 2.7|>=3.6 - url: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.7-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda hash: - md5: 12d8aae6994f342618443a8f05c652a0 - sha256: 13c887cb4a29e1e853a118cfc0e42b72a7e1d1c50c66c0974885d37f0db30619 + md5: db16c66b759a64dc5183d69cc3745a52 + sha256: 3ff11acdd5cc2f80227682966916e878e45ced94f59c402efb94911a5774e84e category: main optional: false - name: exceptiongroup - version: 1.1.3 + version: 1.2.0 manager: conda platform: linux-64 dependencies: python: '>=3.7' - url: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_0.conda hash: - md5: e6518222753f519e911e83136d2158d9 - sha256: c28f715e049fe0f09785660bcbffa175ffb438720e5bc5a60d56d4b08364b315 + md5: f6c211fee3c98229652b60a9a42ef363 + sha256: cf83dcaf9006015c8ccab3fc6770f478464a66a8769e1763ca5d7dff09d11d08 category: main optional: false - name: executing - version: 1.2.0 + version: 2.0.1 manager: conda platform: linux-64 dependencies: python: '>=2.7' - url: https://conda.anaconda.org/conda-forge/noarch/executing-1.2.0-pyhd8ed1ab_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/noarch/executing-2.0.1-pyhd8ed1ab_0.conda hash: - md5: 4c1bc140e2be5c8ba6e3acab99e25c50 - sha256: 9c03425cd58c474af20e179c9ba121a82984d6c4bfc896bbc992f5ed75dd7539 + md5: e16be50e378d8a4533b989035b196ab8 + sha256: c738804ab1e6376f8ea63372229a04c8d658dc90fd5a218c6273a2eaf02f4057 category: main optional: false - name: filelock - version: 3.12.4 + version: 3.13.1 manager: conda platform: linux-64 dependencies: python: '>=3.7' - url: https://conda.anaconda.org/conda-forge/noarch/filelock-3.12.4-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda hash: - md5: 5173d4b8267a0699a43d73231e0b6596 - sha256: 7463c64364c14b34a7a69a7550a880ccd1ec6d3014001e55913e6e4e8b0c7395 + md5: 0c1729b74a8152fde6a38ba0a2ab9f45 + sha256: 4d742d91412d1f163e5399d2b50c5d479694ebcd309127abb549ca3977f89d2b category: main optional: false - name: fontconfig @@ -1794,29 +1758,29 @@ package: category: main optional: false - name: frozenlist - version: 1.4.0 + version: 1.4.1 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.0-py310h2372a71_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.1-py310h2372a71_0.conda hash: - md5: c7b2865e86782925a872c8598b760c08 - sha256: cd1e59ceac047d9f692bb7cc2a6a6e2356a7d3db660b076b4afb19d35db2fd02 + md5: f20cd4d9c1f4a8377d0818c819918bbb + sha256: 496d0ae05e81be0bd8e046bc48a3346f867caaad65041aa14ee2f3717af70db6 category: main optional: false - name: fsspec - version: 2023.10.0 + version: 2023.12.2 manager: conda platform: linux-64 dependencies: python: '>=3.8' - url: https://conda.anaconda.org/conda-forge/noarch/fsspec-2023.10.0-pyhca7485f_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/fsspec-2023.12.2-pyhca7485f_0.conda hash: - md5: 5b86cf1ceaaa9be2ec4627377e538db1 - sha256: 1bbdfadb93cc768252fd207dca406cde928f9a81ff985ea1760b6539c55923e6 + md5: bf40f2a8835b78b1f91083d306b493d2 + sha256: 9269a5464698e0fde1f9c78544552817370c26df86e2a5a7518544b6a55ae8ee category: main optional: false - name: glob2 @@ -1832,15 +1796,15 @@ package: category: main optional: false - name: idna - version: '3.4' + version: '3.6' manager: conda platform: linux-64 dependencies: python: '>=3.6' - url: https://conda.anaconda.org/conda-forge/noarch/idna-3.4-pyhd8ed1ab_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda hash: - md5: 34272b248891bddccc64479f9a7fffed - sha256: 9887c35c374ec1847f167292d3fde023cb4c994a4ceeec283072b95440131f09 + md5: 1a76f09108576397c41c0b0c5bd84134 + sha256: 6ee4c986d69ce61e60a20b2459b6f2027baeba153f0a64995fd3cb47c2cc7e07 category: main optional: false - name: iniconfig @@ -1937,11 +1901,11 @@ package: manager: conda platform: linux-64 dependencies: - libopenblas: '>=0.3.24,<1.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-19_linux64_openblas.conda + libopenblas: '>=0.3.25,<1.0a0' + url: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-20_linux64_openblas.conda hash: - md5: 420f4e9be59d0dc9133a0f43f7bab3f3 - sha256: b1311b9414559c5760b08a32e0382ca27fa302c967968aa6f78e042519f728ce + md5: 2b7bb4f7562c8cf334fc2e20c2d28abc + sha256: 8a0ee1de693a9b3da4a11b95ec81b40dd434bd01fa1f5f38f8268cd2146bf8f0 category: main optional: false - name: libcurl @@ -1963,23 +1927,23 @@ package: category: main optional: false - name: libgrpc - version: 1.58.1 + version: 1.59.3 manager: conda platform: linux-64 dependencies: - c-ares: '>=1.20.1,<2.0a0' + c-ares: '>=1.21.0,<2.0a0' libabseil: '>=20230802.1,<20230803.0a0' libgcc-ng: '>=12' - libprotobuf: '>=4.24.3,<4.24.4.0a0' + libprotobuf: '>=4.24.4,<4.24.5.0a0' libre2-11: '>=2023.6.2,<2024.0a0' libstdcxx-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - openssl: '>=3.1.3,<4.0a0' + openssl: '>=3.1.4,<4.0a0' re2: '' - url: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.58.1-he06187c_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.59.3-hd6c4280_0.conda hash: - md5: 42f5e2ba0d41ba270afd3eb5c725ccf5 - sha256: c1b1324525df5376a5af8816a8174d9fcf0f748dd91fee89ecff8013fee5ec1c + md5: 896c137eaf0c22f2fef58332eb4a4b83 + sha256: 3f95a2792e565b628cb284de92017a37a1cddc4a3f83453b8f75d9adc9f8cfdd category: main optional: false - name: libpq @@ -1990,7 +1954,7 @@ package: krb5: '>=1.21.2,<1.22.0a0' libgcc-ng: '>=12' libzlib: '>=1.2.13,<1.3.0a0' - openssl: '>=3.1.3,<4.0a0' + openssl: '>=3.1.3,<3.2.0a0' url: https://conda.anaconda.org/conda-forge/linux-64/libpq-15.4-hfc447b1_2.conda hash: md5: 4a180ab68881a86be49858c9baf4581d @@ -2049,7 +2013,7 @@ package: category: main optional: false - name: msgpack-python - version: 1.0.6 + version: 1.0.7 manager: conda platform: linux-64 dependencies: @@ -2057,10 +2021,10 @@ package: libstdcxx-ng: '>=12' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.0.6-py310hd41b1e2_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.0.7-py310hd41b1e2_0.conda hash: - md5: 03255e1437f31f25ad95bb45c8b398bb - sha256: cf37ee99132533005db95b611377d99f3cf4cb6feed494806d53aa7101768cd4 + md5: dc5263dcaa1347e5a456ead3537be27d + sha256: a5c7612029e3871b0af0bd69e8ee1545d3deb93b5bec29cf1bf72522375fda31 category: main optional: false - name: multidict @@ -2201,6 +2165,18 @@ package: sha256: fecf95377134b0e8944762d92ecf7b0149c07d8186fb5db583125a2705c7ea0a category: main optional: false +- name: platformdirs + version: 4.1.0 + manager: conda + platform: linux-64 + dependencies: + python: '>=3.8' + url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.1.0-pyhd8ed1ab_0.conda + hash: + md5: 45a5065664da0d1dfa8f8cd2eaf05ab9 + sha256: 9e4ff17ce802159ed31344eb913eaa877688226765b77947b102b42255a53853 + category: main + optional: false - name: pluggy version: 1.3.0 manager: conda @@ -2214,17 +2190,17 @@ package: category: main optional: false - name: psutil - version: 5.9.5 + version: 5.9.7 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.5-py310h2372a71_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.7-py310h2372a71_0.conda hash: - md5: cb25177acf28cc35cfa6c1ac1c679e22 - sha256: db8a99bc41c1b0405c8e9daa92b9d4e7711f9717aff7fd3feeba407ca2a91aa2 + md5: eb1f8f278d0b00c7b6d5c01a5b06609f + sha256: 82d01c09f10cdc0b9333c9478a05bfd55f9cf7b5a1db079938b46920fedd9f7b category: main optional: false - name: ptyprocess @@ -2294,15 +2270,15 @@ package: category: main optional: false - name: pygments - version: 2.16.1 + version: 2.17.2 manager: conda platform: linux-64 dependencies: python: '>=3.7' - url: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda hash: - md5: 40e5cb18165466773619e5c963f00a7b - sha256: 3f0f0fadc6084960ec8cc00a32a03529c562ffea3b527eb73b1653183daad389 + md5: 140a7f159396547e9799aa98f9f0742e + sha256: af5f8867450dc292f98ea387d4d8945fc574284677c8f60eaa9846ede7387257 category: main optional: false - name: pylev @@ -2355,15 +2331,15 @@ package: category: main optional: false - name: python-fastjsonschema - version: 2.18.1 + version: 2.19.0 manager: conda platform: linux-64 dependencies: python: '>=3.3' - url: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.18.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.19.0-pyhd8ed1ab_0.conda hash: - md5: 305141cff54af2f90e089d868fffce28 - sha256: 3fb1af1ac7525072c46e111bc4e96ddf971f792ab049ca3aa25dbebbaffb6f7d + md5: e4dbdb3585c0266b4710467fe7b75cf4 + sha256: fdfe3f387c5ebde803605e1e90871c424519d2bfe2eb3bf9caad1c5a07f4c462 category: main optional: false - name: python-libarchive-c @@ -2408,17 +2384,17 @@ package: category: main optional: false - name: rpds-py - version: 0.10.6 + version: 0.15.2 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.10.6-py310hcb5633a_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.15.2-py310hcb5633a_0.conda hash: - md5: 43c12d8f7891a87378eb5339c49ef051 - sha256: a23d2f15c48cc689d26dc3f50ee91be9ed2925c5fbae7bc5d93e49db7517b847 + md5: a1481e37e85122306ab0d5a09e6fe4fd + sha256: 2ab24a0825e297ff40630e2276912b2cf5ac9882aba35e91f5015ded431679aa category: main optional: false - name: ruamel.yaml.clib @@ -2547,15 +2523,15 @@ package: category: main optional: false - name: tomlkit - version: 0.12.1 + version: 0.12.3 manager: conda platform: linux-64 dependencies: python: '>=3.7' - url: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.1-pyha770c72_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda hash: - md5: 62f5b331c53d73e2f6c4c130b53518a0 - sha256: dc4abf58ca42f29e12b8c0f8aadedfca49cc1e97dab025d15cf000b1787df773 + md5: 074d0ce7a6261ab8b497c3518796ef3e + sha256: 53cc436ab92d38683df1320e4468a8b978428e800195bf1c8c2460e90b0bc117 category: main optional: false - name: toolz @@ -2585,27 +2561,27 @@ package: category: main optional: false - name: traitlets - version: 5.12.0 + version: 5.14.0 manager: conda platform: linux-64 dependencies: python: '>=3.8' - url: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.12.0-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.0-pyhd8ed1ab_0.conda hash: - md5: 3ecde21191a20e0e4ab5a4d69aaaa22c - sha256: cd0709a388063aa4024fa9c721b91cac982983435ab12bf564871c27ef983e13 + md5: 886f4a84ddb49b943b1697ac314e85b3 + sha256: c32412029033264140926be474d327d7fd57c0d11db9b1745396b3d4db78a799 category: main optional: false - name: typing_extensions - version: 4.8.0 + version: 4.9.0 manager: conda platform: linux-64 dependencies: python: '>=3.8' - url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda hash: - md5: 5b1be40a26d10a06f6d4f1f9e19fa0c7 - sha256: 38d16b5c53ec1af845d37d22e7bb0e6c934c7f19499123507c5a470f6f8b7dde + md5: a92a6440c3fe7052d63244f3aba2a4a7 + sha256: f3c5be8673bfd905c4665efcb27fa50192f24f84fa8eff2f19cba5d09753d905 category: main optional: false - name: unicodedata2 @@ -2622,6 +2598,18 @@ package: sha256: 5ab2f2d4542ba0cc27d222c08ae61706babe7173b0c6dfa748aa37ff2fa9d824 category: main optional: false +- name: wcwidth + version: 0.2.12 + manager: conda + platform: linux-64 + dependencies: + python: '>=3.8' + url: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.12-pyhd8ed1ab_0.conda + hash: + md5: bf4a1d1a97ca27b0b65bacd9e238b484 + sha256: ca757d0fc2dbd422af9d3238a8b4b630a6e11df3707a447bd89540656770d1d7 + category: main + optional: false - name: webencodings version: 0.5.1 manager: conda @@ -2635,17 +2623,17 @@ package: category: main optional: false - name: wrapt - version: 1.15.0 + version: 1.16.0 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.15.0-py310h2372a71_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.16.0-py310h2372a71_0.conda hash: - md5: 43e5d746d736ae6c71060ed923179d6d - sha256: a48a93a409bed1fbdb2598acebce08343e7f6006110adf8e0335829df3cee41a + md5: d9dc9c45bdc2b38403e6b388581e92f0 + sha256: 2adc15cd1e66845c1ab498735e2f828003e2d5fe20eed1febddb712f58793c31 category: main optional: false - name: xorg-libxext @@ -2731,30 +2719,16 @@ package: category: main optional: false - name: asttokens - version: 2.4.0 + version: 2.4.1 manager: conda platform: linux-64 dependencies: python: '>=3.5' six: '>=1.12.0' - url: https://conda.anaconda.org/conda-forge/noarch/asttokens-2.4.0-pyhd8ed1ab_0.conda - hash: - md5: 056f04e51dd63337e8d7c425c18c86f1 - sha256: e7e91e3fa26abe502be690371893f205d87a82c225668ea6e9a1ba26870388ee - category: main - optional: false -- name: backports.functools_lru_cache - version: 1.6.5 - manager: conda - platform: linux-64 - dependencies: - backports: '' - python: '>=3.6' - setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/backports.functools_lru_cache-1.6.5-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/asttokens-2.4.1-pyhd8ed1ab_0.conda hash: - md5: 6b1b907661838a75d067a22f87996b2e - sha256: 7027bb689dd4ca4a08e3b25805de9d04239be6b31125993558f21f102a9d2700 + md5: 5f25798dcefd8252ce5f9dc494d5f571 + sha256: 708168f026df19a0344983754d27d1f7b28bb21afc7b97a82f02c4798a3d2111 category: main optional: false - name: beautifulsoup4 @@ -2901,12 +2875,12 @@ package: manager: conda platform: linux-64 dependencies: - python: '' + python: '>=3.8' setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/clyent-1.2.2-py_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/noarch/clyent-1.2.2-pyhd8ed1ab_2.conda hash: - md5: b9ee3fdf59f49883497741509ea364b6 - sha256: 2521c43e0e481ad543baa0bb9289aff2bb242d5304eed11f17ca45943300ae62 + md5: 8fe23a7beac17344f551e2060fc17c40 + sha256: aecb610e5b9df8616a172f70679a9b57ea097639814e1c154c00faa373b34c2a category: main optional: false - name: conda-pack @@ -2936,7 +2910,7 @@ package: category: main optional: false - name: coverage - version: 7.3.2 + version: 7.3.3 manager: conda platform: linux-64 dependencies: @@ -2944,14 +2918,14 @@ package: python: '>=3.10,<3.11.0a0' python_abi: 3.10.* tomli: '' - url: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.3.2-py310h2372a71_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.3.3-py310h2372a71_0.conda hash: - md5: 33c03cd5711885c920ddff676fb84f98 - sha256: f9c07ee8807188c39bd415dd8ce39ac7a90c41cb0cc741e9af429e1f886930c6 + md5: c07e83a9bd8f5053b42be842b9871df9 + sha256: be401f8a99aaa4ebe30a78228fb2b4dbdcae22f1023beb31514d01e1c2c4811c category: main optional: false - name: fonttools - version: 4.43.1 + version: 4.46.0 manager: conda platform: linux-64 dependencies: @@ -2961,10 +2935,10 @@ package: python: '>=3.10,<3.11.0a0' python_abi: 3.10.* unicodedata2: '>=14.0.0' - url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.43.1-py310h2372a71_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.46.0-py310h2372a71_0.conda hash: - md5: c7d552c32b87beb736c9658441bf93a9 - sha256: 66f89ff0c0e6cd9940e866b04f5442b4ab802d5d279012c5eb13c639cf18da76 + md5: 3c0109417cbcdabfed289360886b036d + sha256: 48682fe7bc12bae520dd67b3d6a84acdac52488d75278d91be62b266c8bb3c91 category: main optional: false - name: gitdb @@ -3014,42 +2988,42 @@ package: category: main optional: false - name: importlib-metadata - version: 6.8.0 + version: 7.0.0 manager: conda platform: linux-64 dependencies: python: '>=3.8' zipp: '>=0.5' - url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-6.8.0-pyha770c72_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.0-pyha770c72_0.conda hash: - md5: 4e9f59a060c3be52bc4ddc46ee9b6946 - sha256: 2797ed927d65324309b6c630190d917b9f2111e0c217b721f80429aeb57f9fcf + md5: a941237cd06538837b25cd245fcd25d8 + sha256: 9731e82a00d36b182dc515e31723e711ac82890bb1ca86c6a17a4b471135564f category: main optional: false - name: importlib_resources - version: 6.1.0 + version: 6.1.1 manager: conda platform: linux-64 dependencies: python: '>=3.8' zipp: '>=3.1.0' - url: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.1.0-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.1.1-pyhd8ed1ab_0.conda hash: - md5: 48b0d98e0c0ec810d3ccc2a0926c8c0e - sha256: adab6da633ec3b642f036ab5c1196c3e2db0e8db57fb0c7fc9a8e06e29fa9bdc + md5: 3d5fa25cf42f3f32a12b2d874ace8574 + sha256: e584f9ae08fb2d242af0ce7e19e3cd2f85f362d8523119e08f99edb962db99ed category: main optional: false - name: isort - version: 5.12.0 + version: 5.13.2 manager: conda platform: linux-64 dependencies: python: '>=3.8,<4.0' setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/isort-5.12.0-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/isort-5.13.2-pyhd8ed1ab_0.conda hash: - md5: 07ed3421bad60867234c7a9282ea39d4 - sha256: d34a62e33ac7acc8fd3167ceb0e2aee4e7974b94de263f52d752716429d95bcb + md5: 1d25ed2b95b92b026aaa795eabec8d91 + sha256: 78a7e2037029366d2149f73c8d02e93cac903d535e208cc4517808b0b42e85f2 category: main optional: false - name: jaraco.classes @@ -3104,16 +3078,31 @@ package: sha256: 31e05d47970d956206188480b038829d24ac11fe8216409d8584d93d40233878 category: main optional: false +- name: jupyter_core + version: 5.5.1 + manager: conda + platform: linux-64 + dependencies: + platformdirs: '>=2.5' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* + traitlets: '>=5.3' + url: https://conda.anaconda.org/conda-forge/linux-64/jupyter_core-5.5.1-py310hff52083_0.conda + hash: + md5: e2b19aa7d90c247c8995d854fc6a831e + sha256: c737e0bb3740a62efc399f2cb2e395aafea51c5f0beb2d35abc4d18be5b9baf8 + category: main + optional: false - name: libcblas version: 3.9.0 manager: conda platform: linux-64 dependencies: libblas: 3.9.0 - url: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-19_linux64_openblas.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-20_linux64_openblas.conda hash: - md5: d12374af44575413fbbd4a217d46ea33 - sha256: 84fddccaf58f42b07af7fb42512bd617efcb072f17bdef27f4c1884dbd33c86a + md5: 36d486d72ab64ffea932329a1d3729a3 + sha256: 0e34fb0f82262f02fcb279ab4a1db8d50875dc98e3019452f8f387e6bf3c0247 category: main optional: false - name: libgoogle-cloud @@ -3123,16 +3112,16 @@ package: dependencies: libabseil: '>=20230802.1,<20230803.0a0' libcrc32c: '>=1.1.2,<1.2.0a0' - libcurl: '>=8.3.0,<9.0a0' + libcurl: '>=8.4.0,<9.0a0' libgcc-ng: '>=12' - libgrpc: '>=1.58.1,<1.59.0a0' - libprotobuf: '>=4.24.3,<4.24.4.0a0' + libgrpc: '>=1.59.2,<1.60.0a0' + libprotobuf: '>=4.24.4,<4.24.5.0a0' libstdcxx-ng: '>=12' - openssl: '>=3.1.3,<4.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.12.0-h19a6dae_3.conda + openssl: '>=3.1.4,<4.0a0' + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.12.0-h5206363_4.conda hash: - md5: cb26f6b7184480053106ea4713a52daf - sha256: 8d03bf42a533783c692e2e4cd99be300e3f4b62508d7af44d58df19b12d1c37f + md5: b5eb63d2683102be45d17c55021282f6 + sha256: 82a7d211d0df165b073f9e8ba6d789c4b1c7c4882d546ca12d40f201fc3496fc category: main optional: false - name: liblapack @@ -3141,10 +3130,10 @@ package: platform: linux-64 dependencies: libblas: 3.9.0 - url: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-19_linux64_openblas.conda + url: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-20_linux64_openblas.conda hash: - md5: 9f100edf65436e3eabc2a51fc00b2c37 - sha256: 58f402aae605ebd0932e1cbbf855cd49dcdfa2fcb6aab790a4f6068ec5937878 + md5: 6fabc51f5e647d09cc010c40061557e0 + sha256: ad7745b8d0f2ccb9c3ba7aaa7167d62fc9f02e45eb67172ae5f0dfb5a3b1a2cc category: main optional: false - name: libmamba @@ -3194,7 +3183,7 @@ package: category: main optional: false - name: mypy - version: 1.6.1 + version: 1.7.1 manager: conda platform: linux-64 dependencies: @@ -3205,10 +3194,10 @@ package: python_abi: 3.10.* tomli: '>=1.1.0' typing_extensions: '>=4.1.0' - url: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.6.1-py310h2372a71_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.7.1-py310h2372a71_1.conda hash: - md5: 5b55a903c463183b6a7e1be0785c57eb - sha256: 1d1a86da2e680f707a9289497e3c5c745d73733a3b8e923a0ed56176c9519928 + md5: 0bc67f8c98817bce565cb399471b9af0 + sha256: 25c28573cd4940dfc21af623917195fc38924f9a73cbcc7479621ed402688744 category: main optional: false - name: nodeenv @@ -3298,6 +3287,19 @@ package: sha256: 58af9f1e5f448fbbe9526eb6ca17d3efeec867656cb80f3c2ebd74c670205128 category: main optional: false +- name: prompt-toolkit + version: 3.0.42 + manager: conda + platform: linux-64 + dependencies: + python: '>=3.7' + wcwidth: '' + url: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.42-pyha770c72_0.conda + hash: + md5: 0bf64bf10eee21f46ac83c161917fa86 + sha256: 58525b2a9305fb154b2b0d43a48b9a6495441b80e4fbea44f2a34a597d2cef16 + category: main + optional: false - name: pytest version: 7.4.3 manager: conda @@ -3330,21 +3332,21 @@ package: category: main optional: false - name: referencing - version: 0.30.2 + version: 0.32.0 manager: conda platform: linux-64 dependencies: attrs: '>=22.2.0' python: '>=3.8' rpds-py: '>=0.7.0' - url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.30.2-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.32.0-pyhd8ed1ab_0.conda hash: - md5: a33161b983172ba6ef69d5fc850650cd - sha256: a6768fabc12f1eed87fec68c5c65439e908655cded1e458d70a164abbce13287 + md5: a7b5a535cd614e384594530aee7e6061 + sha256: dfd40282910a45e58882ed94b502b2a09f475efb04eaaa3bd8b3b5a9b21a19c3 category: main optional: false - name: ruamel.yaml - version: 0.18.2 + version: 0.18.5 manager: conda platform: linux-64 dependencies: @@ -3353,10 +3355,10 @@ package: python_abi: 3.10.* ruamel.yaml.clib: '>=0.1.2' setuptools: '' - url: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.2-py310h2372a71_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.5-py310h2372a71_0.conda hash: - md5: 01a71da7d9db1108a832ad7e04b8f824 - sha256: 0baf5186fe4b53eef4b2f8ece62ed052b2446f99ae41bfb833fd557b276cd651 + md5: 14fd49048b91c96a8fbf1113a8cc4f49 + sha256: b31d4eb844d1b667a9cddf63eafa2c303049ae559098f88e403c2ab5ebdd274e category: main optional: false - name: tqdm @@ -3373,15 +3375,15 @@ package: category: main optional: false - name: typing-extensions - version: 4.8.0 + version: 4.9.0 manager: conda platform: linux-64 dependencies: - typing_extensions: 4.8.0 - url: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda + typing_extensions: 4.9.0 + url: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.9.0-hd8ed1ab_0.conda hash: - md5: 384462e63262a527bda564fa2d9126c0 - sha256: d6e1dddd0c372218ef15912383d351ac8c73465cbf16238017f0269813cafe2d + md5: c16524c1b7227dc80b36b4fa6f77cc86 + sha256: d795c1eb1db4ea147f01ece74e5a504d7c2e8d5ee8c11ec987884967dd938f9c category: main optional: false - name: urllib3 @@ -3398,6 +3400,21 @@ package: sha256: 1cc0bab65a6ad0f5a8bd7657760a4fb4e670d30377f9dab88b792977cb3687e7 category: main optional: false +- name: virtualenv + version: 20.25.0 + manager: conda + platform: linux-64 + dependencies: + distlib: <1,>=0.3.7 + filelock: <4,>=3.12.2 + platformdirs: <5,>=3.9.1 + python: '>=3.8' + url: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.25.0-pyhd8ed1ab_0.conda + hash: + md5: c119653cba436d8183c27bf6d190e587 + sha256: 50827c3721a9dbf973b568709d4381add2a6552fa562f26a385c5edc16a534af + category: main + optional: false - name: vulture version: '2.7' manager: conda @@ -3428,7 +3445,7 @@ package: category: main optional: false - name: yarl - version: 1.9.2 + version: 1.9.3 manager: conda platform: linux-64 dependencies: @@ -3437,10 +3454,10 @@ package: multidict: '>=4.0' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.2-py310h2372a71_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.3-py310h2372a71_0.conda hash: - md5: 30ae8a8f248b4e7cd2622cff41cb05a7 - sha256: 0a9aeb8cf885ef6dd0a737693823a4e4d27b2ee724fa3af317d8ccd925fa4258 + md5: 10246f66639d9ca55e790410f0dbb465 + sha256: 159e9e292f841477dd1e4c897c055d364472720c79b16fa329faee1e7b878564 category: main optional: false - name: async-timeout @@ -3457,7 +3474,7 @@ package: category: main optional: false - name: botocore - version: 1.31.17 + version: 1.33.13 manager: conda platform: linux-64 dependencies: @@ -3465,14 +3482,14 @@ package: python: '>=3.7' python-dateutil: '>=2.1,<3.0.0' urllib3: '>=1.25.4,<1.27' - url: https://conda.anaconda.org/conda-forge/noarch/botocore-1.31.17-pyhd8ed1ab_3.conda + url: https://conda.anaconda.org/conda-forge/noarch/botocore-1.33.13-pyhd8ed1ab_0.conda hash: - md5: 929cb539ebd6d4b569646a2ba72f875f - sha256: 1e03dc796b6ae7b5177c90b44c860cad3b42905732ce41af028b639141067d7d + md5: d2566fd9134b6f8b8e69a07e9a1fa17e + sha256: 498d08274880ef279e9a6dd68f66b384d71321d92301fa60330712f9edceab0c category: main optional: false - name: cryptography - version: 41.0.5 + version: 41.0.7 manager: conda platform: linux-64 dependencies: @@ -3481,10 +3498,10 @@ package: openssl: '>=3.1.4,<4.0a0' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/cryptography-41.0.5-py310h75e40e8_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/cryptography-41.0.7-py310hb8475ec_1.conda hash: - md5: 33f090627d17c47493b88a5f7d2834e8 - sha256: b81a6dd15052379775c43997a48f4a85db5c0448a80a75ba74c3af78cf33c0da + md5: 8a84d96d106767c08d6154ed5c8aae2c + sha256: 493feafc2492e841d361affb0bba2e29ab41d73b8db2d58c5abdfd4ccf1d29ad category: main optional: false - name: geotiff @@ -3520,29 +3537,29 @@ package: category: main optional: false - name: importlib_metadata - version: 6.8.0 + version: 7.0.0 manager: conda platform: linux-64 dependencies: - importlib-metadata: '>=6.8.0,<6.8.1.0a0' - url: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-6.8.0-hd8ed1ab_0.conda + importlib-metadata: '>=7.0.0,<7.0.1.0a0' + url: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-7.0.0-hd8ed1ab_0.conda hash: - md5: b279b07ce18058034e5b3606ba103a8b - sha256: b96e01dc42d547d6d9ceb1c5b52a5232cc04e40153534350f702c3e0418a6b3f + md5: 12aff14f84c337be5e5636bf612f4140 + sha256: b9e8ed41df6c55222e3777f422e77a22a6a19ff779b2e65aa8dfdea792c1f7de category: main optional: false - name: jsonschema-specifications - version: 2023.7.1 + version: 2023.11.2 manager: conda platform: linux-64 dependencies: importlib_resources: '>=1.4.0' python: '>=3.8' - referencing: '>=0.25.0' - url: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2023.7.1-pyhd8ed1ab_0.conda + referencing: '>=0.31.0' + url: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2023.11.2-pyhd8ed1ab_0.conda hash: - md5: 7c27ea1bdbe520bb830dcadd59f55cbf - sha256: 7b0061e106674f27cc718f79a095e90a5667a3635ec6626dd23b3be0fd2bfbdc + md5: 73884ca36d6d96cbce498cde99fab40f + sha256: e26115d02dc208a05b557c8dd670923270803b9b3b8af4e22b93d659d1ec77ec category: main optional: false - name: kealib @@ -3550,7 +3567,7 @@ package: manager: conda platform: linux-64 dependencies: - hdf5: '>=1.14.2,<1.14.3.0a0' + hdf5: '>=1.14.2,<1.14.4.0a0' libgcc-ng: '>=12' libstdcxx-ng: '>=12' url: https://conda.anaconda.org/conda-forge/linux-64/kealib-1.5.2-hcd42e92_1.conda @@ -3587,7 +3604,7 @@ package: blosc: '>=1.21.4,<2.0a0' bzip2: '>=1.0.8,<2.0a0' hdf4: '>=4.2.15,<4.2.16.0a0' - hdf5: '>=1.14.2,<1.14.3.0a0' + hdf5: '>=1.14.2,<1.14.4.0a0' libaec: '>=1.0.6,<2.0a0' libcurl: '>=8.2.1,<9.0a0' libgcc-ng: '>=12' @@ -3644,19 +3661,6 @@ package: sha256: 89452fcd4270c04dd9e861e0e02cbc97d82f2f7d4b55225f8198ddab4287c480 category: main optional: false -- name: platformdirs - version: 3.11.0 - manager: conda - platform: linux-64 - dependencies: - python: '>=3.7' - typing-extensions: '>=4.6.3' - url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - hash: - md5: 8f567c0a74aa44cf732f15773b4083b0 - sha256: b3d809ff5a18ee8514bba8bc05a23b4cdf1758090a18a2cf742af38aed405144 - category: main - optional: false - name: poppler version: 23.08.0 manager: conda @@ -3702,6 +3706,18 @@ package: sha256: c39a328350cba6e1d3b756e116ffd46e46eed8fc0f6f2e9ed6860d418e6d8186 category: main optional: false +- name: prompt_toolkit + version: 3.0.42 + manager: conda + platform: linux-64 + dependencies: + prompt-toolkit: '>=3.0.42,<3.0.43.0a0' + url: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.42-hd8ed1ab_0.conda + hash: + md5: 85a2189ecd2fcdd86e92b2d4ea8fe461 + sha256: fd2185d501bf34cb4c121f2f5ade9157ac75e1644a9da81355c4c8f9c1b82d4d + category: main + optional: false - name: pydantic version: 1.10.13 manager: conda @@ -3765,7 +3781,7 @@ package: category: main optional: false - name: rich - version: 13.6.0 + version: 13.7.0 manager: conda platform: linux-64 dependencies: @@ -3773,10 +3789,10 @@ package: pygments: '>=2.13.0,<3.0.0' python: '>=3.7.0' typing_extensions: '>=4.0.0,<5.0.0' - url: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda hash: - md5: 3ca4829f40710f581ca1d76bc907e99f - sha256: a2f8838a75ab8c2c1da0a813c7569d4f6efba0d2b5dc3a7659e2cb6d96bd8e19 + md5: d7a11d4f3024b2f4a6e0ae7377dd61e9 + sha256: 4bb25bf1f5664772b2c4c2e3878aa6e7dc2695f97e3da4ee8e47c51e179913bb category: main optional: false - name: stack_data @@ -3844,21 +3860,8 @@ package: sha256: 5139550cbd5d93cb6b3d4954267d21fdaccd81b816d421c7a8ee031f27432179 category: main optional: false -- name: wcwidth - version: 0.2.8 - manager: conda - platform: linux-64 - dependencies: - backports.functools_lru_cache: '' - python: '>=3.6' - url: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.8-pyhd8ed1ab_0.conda - hash: - md5: 367386d2575a0e62412448eda1012efd - sha256: e3b6d2041b4d175a1437dccc71b4ef2e53111dfcc64b219fef4bed379e6ef236 - category: main - optional: false - name: zstandard - version: 0.21.0 + version: 0.22.0 manager: conda platform: linux-64 dependencies: @@ -3867,31 +3870,30 @@ package: python: '>=3.10,<3.11.0a0' python_abi: 3.10.* zstd: '>=1.5.5,<1.6.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.21.0-py310h1275a96_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.22.0-py310h1275a96_0.conda hash: - md5: 552fb8cd05ab3d3608c8e6b55f96e290 - sha256: 2b20cf782b33898b94b69e1deb859e520ad59755a3e048d1bbbff9a4e8bf95e2 + md5: 54698ba13cd3494547b289cd86a2176a + sha256: 1c1b91e5c5246b13ca25728ea6200dfd230d8ce8ca6910cd0b70fc5e43065a04 category: main optional: false - name: aiohttp - version: 3.8.6 + version: 3.9.1 manager: conda platform: linux-64 dependencies: aiosignal: '>=1.1.2' - async-timeout: <5.0,>=4.0.0a3 + async-timeout: '>=4.0,<5.0' attrs: '>=17.3.0' - charset-normalizer: '>=2.0,<4.0' frozenlist: '>=1.1.1' libgcc-ng: '>=12' multidict: '>=4.5,<7.0' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* yarl: '>=1.0,<2.0' - url: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.8.6-py310h2372a71_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.9.1-py310h2372a71_0.conda hash: - md5: d265a71480afd9479c9333ba86375d04 - sha256: e32892fd786dc4ba150701ffd0981c8e942fc77e52754f6f1c331392004bd6f1 + md5: f367877549376e985a3df1dc430692ae + sha256: 6a3983f2ee81308ae0716790ae780f63915f47fcd6a1038d3c75a78fcb675f23 category: main optional: false - name: cachecontrol @@ -3909,7 +3911,7 @@ package: category: main optional: false - name: cftime - version: 1.6.2 + version: 1.6.3 manager: conda platform: linux-64 dependencies: @@ -3917,10 +3919,10 @@ package: numpy: '>=1.22.4,<2.0a0' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/cftime-1.6.2-py310h1f7b6fc_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/cftime-1.6.3-py310h1f7b6fc_0.conda hash: - md5: 7925aaa4330045bc32d334b20f446902 - sha256: 182a5e5584167a51625617775a2c641784985a5e769e74e3dd445bd6f1c0e7e1 + md5: 31beda75384647959d5792a1a7dc571a + sha256: 0983d88068e4bd589031582769ef7d05617edda3a7daa1f4847492f4c3538aad category: main optional: false - name: conda-package-streaming @@ -3937,19 +3939,19 @@ package: category: main optional: false - name: contourpy - version: 1.1.1 + version: 1.2.0 manager: conda platform: linux-64 dependencies: libgcc-ng: '>=12' libstdcxx-ng: '>=12' - numpy: '>=1.16' + numpy: '>=1.20,<2' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.1.1-py310hd41b1e2_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.2.0-py310hd41b1e2_0.conda hash: - md5: 6a38f65d330b74495ad6990280486049 - sha256: 16f44e7e47f7cf9c3c02d760beb9179698510740e0eb1927ade3d8fb69aa1a0d + md5: 85d2aaa7af046528d339da1e813c3a9f + sha256: 73dd7868bfd98fa9e4d2cc524687b5c5c8f9d427d4e521875aacfe152eae4715 category: main optional: false - name: ensureconda @@ -3974,7 +3976,7 @@ package: platform: linux-64 dependencies: cached-property: '' - hdf5: '>=1.14.2,<1.14.3.0a0' + hdf5: '>=1.14.2,<1.14.4.0a0' libgcc-ng: '>=12' numpy: '>=1.22.4,<2.0a0' python: '>=3.10,<3.11.0a0' @@ -3986,20 +3988,44 @@ package: category: main optional: false - name: identify - version: 2.5.30 + version: 2.5.33 manager: conda platform: linux-64 dependencies: python: '>=3.6' ukkonen: '' - url: https://conda.anaconda.org/conda-forge/noarch/identify-2.5.30-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/identify-2.5.33-pyhd8ed1ab_0.conda hash: - md5: b7a2e3bb89bda8c69839485c20aabadf - sha256: dc9901654af0556209bb5b4194ef2deb643bc641ac859a31f13c41b945b60150 + md5: 93c8f8ceb83827d88deeba796f07fba7 + sha256: ce2a64c18221af96226be23278d81f22ff9f64b3c047d8865590f6718915303f + category: main + optional: false +- name: ipython + version: 8.18.1 + manager: conda + platform: linux-64 + dependencies: + __unix: '' + decorator: '' + exceptiongroup: '' + jedi: '>=0.16' + matplotlib-inline: '' + pexpect: '>4.3' + pickleshare: '' + prompt-toolkit: '>=3.0.41,<3.1.0' + pygments: '>=2.4.0' + python: '>=3.9' + stack_data: '' + traitlets: '>=5' + typing_extensions: '' + url: https://conda.anaconda.org/conda-forge/noarch/ipython-8.18.1-pyh707e725_3.conda + hash: + md5: 15c6f45a45f7ac27f6d60b0b084f6761 + sha256: d98d615ac8ad71de698afbc50e8269570d4b89706821c4ff3058a4ceec69bd9b category: main optional: false - name: jsonschema - version: 4.19.1 + version: 4.20.0 manager: conda platform: linux-64 dependencies: @@ -4010,25 +4036,10 @@ package: python: '>=3.8' referencing: '>=0.28.4' rpds-py: '>=0.7.1' - url: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.19.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.20.0-pyhd8ed1ab_0.conda hash: - md5: 78aff5d2af74e6537c1ca73017f01f4f - sha256: b4e50e1d53b984a467e79b7ba69cc408d14e3a2002cad4eaf7798e20268cff2d - category: main - optional: false -- name: jupyter_core - version: 5.4.0 - manager: conda - platform: linux-64 - dependencies: - platformdirs: '>=2.5' - python: '>=3.10,<3.11.0a0' - python_abi: 3.10.* - traitlets: '>=5.3' - url: https://conda.anaconda.org/conda-forge/linux-64/jupyter_core-5.4.0-py310hff52083_0.conda - hash: - md5: 28cdf08d2d44db099a95a176f01f7120 - sha256: d6d0408c6a946e1d9514972e8491363c0bf20bd938e225443b360fa397aef440 + md5: 1116d79def5268414fb0917520b2bbf1 + sha256: 77aae609097d06deedb8ef8407a44b23d5fef95962ba6fe1c959ac7bd6195296 category: main optional: false - name: libgdal @@ -4044,7 +4055,7 @@ package: geotiff: '>=1.7.1,<1.8.0a0' giflib: '>=5.2.1,<5.3.0a0' hdf4: '>=4.2.15,<4.2.16.0a0' - hdf5: '>=1.14.2,<1.14.3.0a0' + hdf5: '>=1.14.2,<1.14.4.0a0' json-c: '>=0.17,<0.18.0a0' kealib: '>=1.5.1,<1.6.0a0' lerc: '>=4.0.0,<5.0a0' @@ -4102,21 +4113,8 @@ package: sha256: 92b692816f1dba43b715a640bc8b8ddf1edd4dfab325b39b65ba3ccef61ed9bb category: main optional: false -- name: prompt-toolkit - version: 3.0.39 - manager: conda - platform: linux-64 - dependencies: - python: '>=3.7' - wcwidth: '' - url: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.39-pyha770c72_0.conda - hash: - md5: a4986c6bb5b0d05a38855b0880a5f425 - sha256: 10e7fdc75d4b85633be6b12a70b857053987127a808caa0f88b2cba4b3ce6359 - category: main - optional: false - name: pykdtree - version: 1.3.9 + version: 1.3.10 manager: conda platform: linux-64 dependencies: @@ -4124,23 +4122,23 @@ package: numpy: '>=1.22.4,<2.0a0' python: '>=3.10,<3.11.0a0' python_abi: 3.10.* - url: https://conda.anaconda.org/conda-forge/linux-64/pykdtree-1.3.9-py310h1f7b6fc_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/pykdtree-1.3.10-py310h1f7b6fc_0.conda hash: - md5: c082bd919ad3f704f7986f3c9b2343a8 - sha256: a88bf3bf6d1221b7f57f972f1985c49d11956239749276e54080e07fde5b2121 + md5: a4572644e146b320644299ca2bcf5931 + sha256: 4d4f00decd805125252cbc1216ffbbdc15dc5ca85776b2055ef36e3c2c43beb2 category: main optional: false - name: pyopenssl - version: 23.2.0 + version: 23.3.0 manager: conda platform: linux-64 dependencies: - cryptography: '>=38.0.0,<42,!=40.0.0,!=40.0.1' - python: '>=3.6' - url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-23.2.0-pyhd8ed1ab_1.conda + cryptography: '>=41.0.5,<42' + python: '>=3.7' + url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-23.3.0-pyhd8ed1ab_0.conda hash: - md5: 34f7d568bf59d18e3fef8c405cbece21 - sha256: 4daea3dc896987cc1334956fccfc0ed738663a84ad0c1d3f576a7a7936091534 + md5: 7819533e674dbbc51468f3228b9b1bb6 + sha256: f7e04c4a49b1593140231d70801e2204e314e26d7141bfbdc8089d04114c0010 category: main optional: false - name: python-cmr @@ -4169,6 +4167,20 @@ package: sha256: 20eaefc5dba74ff6c31e537533dde59b5b20f69e74df49dff19d43be59785fa3 category: main optional: false +- name: rich-click + version: 1.7.2 + manager: conda + platform: linux-64 + dependencies: + click: '>=7,<9' + python: '>=3.7' + rich: '>=10' + url: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.7.2-pyhd8ed1ab_0.conda + hash: + md5: fe1eae76a71246959cefd09b5b00869b + sha256: 4bfddbc5716a09bfea1c3345b1eed0ddb36d0e55f357afb60ca3e73c9231cc68 + category: main + optional: false - name: scipy version: 1.8.1 manager: conda @@ -4236,35 +4248,37 @@ package: sha256: ebb8f5f9e362f186fb7d732e656f85c969b86309494436eba51cc3b8b96683f7 category: main optional: false -- name: virtualenv - version: 20.24.6 +- name: aiobotocore + version: 2.9.0 manager: conda platform: linux-64 dependencies: - distlib: <1,>=0.3.7 - filelock: <4,>=3.12.2 - platformdirs: <4,>=3.9.1 + aiohttp: '>=3.7.4.post0,<4.0.0' + aioitertools: '>=0.5.1,<1.0.0' + botocore: '>=1.33.2,<1.33.14' python: '>=3.8' - url: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.24.6-pyhd8ed1ab_0.conda + wrapt: '>=1.10.10,<2.0.0' + url: https://conda.anaconda.org/conda-forge/noarch/aiobotocore-2.9.0-pyhd8ed1ab_0.conda hash: - md5: fb1fc875719e217ed799a7aae11d3be4 - sha256: 09492f89a22dc17d9b32f2a791deee93d06e99fb312c3d47430fe35343b7fbde + md5: 72f6cca1b44a5333ef97ecb5ae59dcb1 + sha256: 755b88441d79966f3bae165a46fc43be522cf59a1aa8c8181ee1a4c42ebe6d9a category: main optional: false -- name: aiobotocore - version: 2.7.0 +- name: bump-my-version + version: 0.10.0 manager: conda platform: linux-64 dependencies: - aiohttp: '>=3.3.1,<4.0.0' - aioitertools: '>=0.5.1,<1.0.0' - botocore: '>=1.31.17,<1.31.18' - python: '>=3.7' - wrapt: '>=1.10.10,<2.0.0' - url: https://conda.anaconda.org/conda-forge/noarch/aiobotocore-2.7.0-pyhd8ed1ab_0.conda + click: '' + pydantic: <2.0.0 + python: '>=3.8' + rich: '' + rich-click: '' + tomlkit: '' + url: https://conda.anaconda.org/conda-forge/noarch/bump-my-version-0.10.0-pyhd8ed1ab_0.conda hash: - md5: 273a1a421309871b051acd6aef346b63 - sha256: b9f835ad1c95d220f4f7a72e1155d027f5a57c1d109d5eceedd33333562add06 + md5: d0cfdd7365c03381f3d8c4402a88c50c + sha256: 433cc87b7e1700aaf1ed9fe6f402bfda945409379cafb0d78ed757ca74e364e5 category: main optional: false - name: cachecontrol-with-filecache @@ -4295,8 +4309,23 @@ package: sha256: 9a221808405d813d8c555efce6944379b907d36d79e77d526d573efa6b996d26 category: main optional: false +- name: ipdb + version: 0.13.13 + manager: conda + platform: linux-64 + dependencies: + decorator: '' + ipython: '' + python: '>=2.7' + toml: '>=0.10.2' + url: https://conda.anaconda.org/conda-forge/noarch/ipdb-0.13.13-pyhd8ed1ab_0.conda + hash: + md5: 86baea403007ad4898d85c897c80b758 + sha256: 16ea279fae5b3b77a694bf7bc8bcda9c310be39d6fbf78664d3111bcd5f5758a + category: main + optional: false - name: keyring - version: 24.2.0 + version: 24.3.0 manager: conda platform: linux-64 dependencies: @@ -4306,14 +4335,14 @@ package: python: '>=3.10,<3.11.0a0' python_abi: 3.10.* secretstorage: '>=3.2' - url: https://conda.anaconda.org/conda-forge/linux-64/keyring-24.2.0-py310hff52083_1.conda + url: https://conda.anaconda.org/conda-forge/linux-64/keyring-24.3.0-py310hff52083_0.conda hash: - md5: 8992b7970e6996fef7fbd3e890d8c552 - sha256: 53b008f165b677b492dfb67bd1459329260ba21338858f20dd3ed6c9a70b3ea7 + md5: e710fd8e57356a64cace034413da9cb3 + sha256: 886a764e4bc2cfaabf2ea0a98461fbd526affd99c984a2789770eca43dd17c9b category: main optional: false - name: matplotlib-base - version: 3.8.0 + version: 3.8.2 manager: conda platform: linux-64 dependencies: @@ -4322,21 +4351,21 @@ package: cycler: '>=0.10' fonttools: '>=4.22.0' freetype: '>=2.12.1,<3.0a0' - kiwisolver: '>=1.0.1' + kiwisolver: '>=1.3.1' libgcc-ng: '>=12' libstdcxx-ng: '>=12' numpy: '>=1.22.4,<2.0a0' packaging: '>=20.0' - pillow: '>=6.2.0' + pillow: '>=8' pyparsing: '>=2.3.1' python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.7' python_abi: 3.10.* tk: '>=8.6.13,<8.7.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.8.0-py310h62c0568_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.8.2-py310h62c0568_0.conda hash: - md5: 5c0d101ef8fc542778aa80795a759d08 - sha256: 220052334fb2b01b5a487ddf6953c1c7713b401cc0faa0898401422799cdcec1 + md5: 3cbbc7d0b54df02c9a006d3de14911d9 + sha256: 078f5f1ece533a03710dd6d644555f1f2f4cbe18f1412d695ffb304e3d8c9381 category: main optional: false - name: nbformat @@ -4362,7 +4391,7 @@ package: dependencies: certifi: '' cftime: '' - hdf5: '>=1.14.2,<1.14.3.0a0' + hdf5: '>=1.14.2,<1.14.4.0a0' libgcc-ng: '>=12' libnetcdf: '>=4.9.2,<4.9.3.0a0' libzlib: '>=1.2.13,<1.3.0a0' @@ -4377,32 +4406,20 @@ package: category: main optional: false - name: pre-commit - version: 3.5.0 + version: 3.6.0 manager: conda platform: linux-64 dependencies: cfgv: '>=2.0.0' identify: '>=1.0.0' nodeenv: '>=0.11.1' - python: '>=3.8' + python: '>=3.9' pyyaml: '>=5.1' virtualenv: '>=20.10.0' - url: https://conda.anaconda.org/conda-forge/noarch/pre-commit-3.5.0-pyha770c72_0.conda - hash: - md5: 964e3d762e427661c59263435a14c492 - sha256: 51a4a17334a15ec92805cd075776563ff93b3b6c20732c4cb607c98a761ae02f - category: main - optional: false -- name: prompt_toolkit - version: 3.0.39 - manager: conda - platform: linux-64 - dependencies: - prompt-toolkit: '>=3.0.39,<3.0.40.0a0' - url: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.39-hd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pre-commit-3.6.0-pyha770c72_0.conda hash: - md5: 4bbbe67d5df19db30f04b8e344dc9976 - sha256: 89f7fecc7355181dbc2ab851e668a2fce6aa4830b336a34c93b59bda93206270 + md5: 473a7cfca197da0a10cff3f6dded7d4b + sha256: 7d1f4b4a2eb4946b5808769642c5f643788c3a9e090f1c02a6c63f8794fb3d54 category: main optional: false - name: pyresample @@ -4455,7 +4472,7 @@ package: category: main optional: false - name: xarray - version: 2023.10.1 + version: 2023.12.0 manager: conda platform: linux-64 dependencies: @@ -4463,10 +4480,10 @@ package: packaging: '>=21.3' pandas: '>=1.4' python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/xarray-2023.10.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/xarray-2023.12.0-pyhd8ed1ab_0.conda hash: - md5: 9b20e5d68eea6878a0a6fc57a3043889 - sha256: 6062114745e9c01813506527d7e48c75dbe5eb6017e4c60ce8c98ef9fd757db2 + md5: e9b31d3ab1b0dd5fd8c24419f6560b90 + sha256: ab89b70aa3d31a9cacf0e91a7c7a6f8cc45d866d71cdcee1219561cff0e8a9a5 category: main optional: false - name: cartopy @@ -4511,7 +4528,7 @@ package: category: main optional: false - name: conda-lock - version: 2.4.1 + version: 2.5.1 manager: conda platform: linux-64 dependencies: @@ -4539,50 +4556,25 @@ package: typing_extensions: '' urllib3: '>=1.26.5,<2.0' virtualenv: '>=20.0.26' - url: https://conda.anaconda.org/conda-forge/noarch/conda-lock-2.4.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/conda-lock-2.5.1-pyhd8ed1ab_0.conda hash: - md5: deb6e2f8d8b4de933563cc681165b833 - sha256: 08cd768d033db260e043982ba91de007213adbde5210a76fd2decad3c135e666 - category: main - optional: false -- name: ipython - version: 8.16.1 - manager: conda - platform: linux-64 - dependencies: - __linux: '' - backcall: '' - decorator: '' - exceptiongroup: '' - jedi: '>=0.16' - matplotlib-inline: '' - pexpect: '>4.3' - pickleshare: '' - prompt_toolkit: '>=3.0.30,<3.1.0,!=3.0.37' - pygments: '>=2.4.0' - python: '>=3.9' - stack_data: '' - traitlets: '>=5' - typing_extensions: '' - url: https://conda.anaconda.org/conda-forge/noarch/ipython-8.16.1-pyh0d859eb_0.conda - hash: - md5: 7e52cb0dbf01b90365bfe433ec8bd3c0 - sha256: 2dc119746ddac02cb01644ae7c7ac54a296366e2edf0d178f50f833113aaf94a + md5: 22209054c003c84cdabcc74d5733c501 + sha256: c6fc314161263f031eb23ac53868e0d9b0242efe669e176901effdac4bd87376 category: main optional: false - name: s3fs - version: 2023.10.0 + version: 2023.12.2 manager: conda platform: linux-64 dependencies: - aiobotocore: '>=2.7.0,<2.7.1' + aiobotocore: '>=2.5.4,<3.0.0' aiohttp: '' - fsspec: 2023.10.0 + fsspec: 2023.12.2 python: '>=3.8' - url: https://conda.anaconda.org/conda-forge/noarch/s3fs-2023.10.0-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/s3fs-2023.12.2-pyhd8ed1ab_0.conda hash: - md5: 557aa3617c92aa511841887db279dc51 - sha256: 2f190cf0c550d4ba400af6b62afefa47a01ff5b57ece67354d38037a304f0acb + md5: e6de0e35f836bef08cbcfeb50337d2a4 + sha256: d3bdcc9eb8c61a383a1199d62f9c20c124fbcf46289600bfe3dfbdd7f813d7d3 category: main optional: false - name: conda-index @@ -4591,18 +4583,17 @@ package: platform: linux-64 dependencies: click: '>=8' - conda: '>=4.14.0' - conda-package-streaming: '>=0.7.0' + conda: '>=4.12.0' + conda-package-streaming: '' filelock: '' jinja2: '' more-itertools: '' - python: '>=3.10,<3.11.0a0' - python_abi: 3.10.* - ruamel.yaml: '' - url: https://conda.anaconda.org/conda-forge/linux-64/conda-index-0.3.0-py310ha770c72_0.conda + python: '>=3.7' + pyyaml: '>=6' + url: https://conda.anaconda.org/conda-forge/noarch/conda-index-0.3.0-pyhd8ed1ab_1.conda hash: - md5: 0c69b29f6c38f3275f3b77b359674961 - sha256: ad233dd33c68ed87d7d381d2abbe130627907aef431ff768087f53fe946d0039 + md5: bb68b58a48c775ab715029a12ab48a4e + sha256: 792bebd8533ff4f7863f1e5cde882697c49120c24647194f75d9308adc2ff3b9 category: main optional: false - name: earthaccess @@ -4624,21 +4615,6 @@ package: sha256: c8e5ba0a0de59543e73b81df6eb5e73434c4a23dd05bf394edbcd824d9b4223b category: main optional: false -- name: ipdb - version: 0.13.13 - manager: conda - platform: linux-64 - dependencies: - decorator: '' - ipython: '' - python: '>=2.7' - toml: '>=0.10.2' - url: https://conda.anaconda.org/conda-forge/noarch/ipdb-0.13.13-pyhd8ed1ab_0.conda - hash: - md5: 86baea403007ad4898d85c897c80b758 - sha256: 16ea279fae5b3b77a694bf7bc8bcda9c310be39d6fbf78664d3111bcd5f5758a - category: main - optional: false - name: mamba version: 1.4.2 manager: conda diff --git a/environment.yml b/environment.yml index 3d5894d6..d5b43beb 100644 --- a/environment.yml +++ b/environment.yml @@ -13,7 +13,7 @@ dependencies: # debugging/development tools - ipython - ipdb - - bump2version + - bump-my-version ~=0.10.0 - pre-commit - conda-lock # build tools diff --git a/pm_icecon/bt/api.py b/pm_icecon/bt/api.py index 7d37e92f..888822e8 100644 --- a/pm_icecon/bt/api.py +++ b/pm_icecon/bt/api.py @@ -2,6 +2,7 @@ from pathlib import Path import numpy as np +import numpy.typing as npt import xarray as xr from pm_tb_data.fetch.a2l1c_625 import get_a2l1c_625_tbs from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS, get_au_si_tbs @@ -12,11 +13,15 @@ from pm_icecon.bt.params.cetbv2_amsr2 import A2L1C_NORTH_PARAMS from pm_icecon.config.models.bt import BootstrapParams from pm_icecon.interpolation import spatial_interp_tbs -from pm_icecon.masks import get_e2n625_land_mask def amsr2_goddard_bootstrap( - *, date: dt.date, hemisphere: Hemisphere, resolution: AU_SI_RESOLUTIONS + *, + date: dt.date, + hemisphere: Hemisphere, + resolution: AU_SI_RESOLUTIONS, + land_mask: npt.NDArray[np.bool_], + invalid_ice_mask: npt.NDArray[np.bool_], ) -> xr.Dataset: """Compute sea ice concentration from AU_SI TBs. @@ -30,9 +35,7 @@ def amsr2_goddard_bootstrap( ) params = get_amsr2_params( - date=date, hemisphere=hemisphere, - resolution=resolution, ) conc_ds = bt.goddard_bootstrap( @@ -42,6 +45,8 @@ def amsr2_goddard_bootstrap( tb_v22=spatial_interp_tbs(xr_tbs["v23"].data), params=params, date=date, + land_mask=land_mask, + invalid_ice_mask=invalid_ice_mask, ) return conc_ds @@ -52,7 +57,8 @@ def a2l1c_goddard_bootstrap( date: dt.date, hemisphere: Hemisphere, tb_dir: Path, - anc_dir: Path, + land_mask: npt.NDArray[np.bool_], + invalid_ice_mask: npt.NDArray[np.bool_], ncfn_template: str, timeframe: str, ) -> xr.Dataset: @@ -60,6 +66,16 @@ def a2l1c_goddard_bootstrap( Utilizes the bootstrap algorithm as organized by the original code from GSFC. + + Note: an invalid seaice mask can be created from + `valid_seaice_e2n6.25_{date:%m}.dat`. The value of 50 in this file + represents an invalid mask: + + ``` + sst_fn = f"valid_seaice_e2n6.25_{date:%m}.dat" + sst_mask = np.fromfile(sst_fn, dtype=np.uint8).reshape(1680, 1680) + is_high_sst = sst_mask == 50 + ``` """ if hemisphere == "south": raise NotImplementedError("Southern hemisphere is not currently supported.") @@ -72,14 +88,7 @@ def a2l1c_goddard_bootstrap( timeframe=timeframe, ) - sst_fn = anc_dir / f"valid_seaice_e2n6.25_{date:%m}.dat" - sst_mask = np.fromfile(sst_fn, dtype=np.uint8).reshape(1680, 1680) - is_high_sst = sst_mask == 50 - params = BootstrapParams( - land_mask=get_e2n625_land_mask(anc_dir), - pole_mask=None, - invalid_ice_mask=is_high_sst, **A2L1C_NORTH_PARAMS, # type: ignore[arg-type] ) @@ -90,6 +99,8 @@ def a2l1c_goddard_bootstrap( tb_v22=spatial_interp_tbs(xr_tbs["v23"].data), params=params, date=date, + land_mask=land_mask, + invalid_ice_mask=invalid_ice_mask, ) return conc_ds diff --git a/pm_icecon/bt/cli.py b/pm_icecon/bt/cli.py deleted file mode 100644 index d7468b67..00000000 --- a/pm_icecon/bt/cli.py +++ /dev/null @@ -1,214 +0,0 @@ -import datetime as dt -from pathlib import Path -from typing import get_args - -import click -import numpy as np -from loguru import logger -from pm_tb_data.fetch.a2l1c_utils import ( - add_info_to_netcdf_file_a2l1c, - create_equivalent_geotiff_a2l1c, - derive_geotiff_name_a2l1c, -) -from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS -from pm_tb_data._types import Hemisphere - -from pm_icecon.bt.api import a2l1c_goddard_bootstrap, amsr2_goddard_bootstrap -from pm_icecon.cli.util import datetime_to_date -from pm_icecon.util import standard_output_filename - - -# Click definitions for "amsr2" which uses AU25 -@click.command() -@click.option( - "-d", - "--date", - required=True, - type=click.DateTime(formats=("%Y-%m-%d",)), - callback=datetime_to_date, -) -@click.option( - "-h", - "--hemisphere", - required=True, - type=click.Choice(get_args(Hemisphere)), -) -@click.option( - "-o", - "--output-dir", - required=True, - type=click.Path( - exists=True, - file_okay=False, - dir_okay=True, - writable=True, - resolve_path=True, - path_type=Path, - ), -) -@click.option( - "-r", - "--resolution", - required=True, - type=click.Choice(get_args(AU_SI_RESOLUTIONS)), -) -def amsr2( - *, - date: dt.date, - hemisphere: Hemisphere, - output_dir: Path, - resolution: AU_SI_RESOLUTIONS, -): - """Run the bootstrap algorithm with ASMR2 data. - - AMSRU2 brightness temperatures are fetched from AU_SI25. - - The resulting concentration field is saved to a netcdf file in the given - `output_dir` with the form `{N|S}H_{YYYYMMDD}_py_NRT_amsr2.nc` - """ - conc_ds = amsr2_goddard_bootstrap( - date=date, - hemisphere=hemisphere, - resolution=resolution, - ) - - output_fn = standard_output_filename( - hemisphere=hemisphere, - date=date, - sat="u2", - resolution=f"{resolution}km", - algorithm="bt", - ) - output_path = output_dir / output_fn - conc_ds.to_netcdf(output_path) - logger.info(f"Wrote AMSR2 concentration field: {output_path}") - - -# Click definitions for 'a2l1c' which uses 6.25km fields derived from 0763 -@click.command() -@click.option( - "-d", - "--date", - required=True, - type=click.DateTime(formats=("%Y-%m-%d",)), - callback=datetime_to_date, -) -@click.option( - "-h", - "--hemisphere", - required=True, - type=click.Choice(get_args(Hemisphere)), -) -@click.option( - "-o", - "--output-dir", - required=True, - type=click.Path( - exists=True, - file_okay=False, - dir_okay=True, - writable=True, - resolve_path=True, - path_type=Path, - ), -) -@click.option( - "-t", - "--tb_dir", - required=True, - type=click.Path( - exists=True, - file_okay=False, - dir_okay=True, - resolve_path=True, - path_type=Path, - ), -) -@click.option( - "-a", - "--anc_dir", - required=True, - type=click.Path( - exists=True, - file_okay=False, - dir_okay=True, - resolve_path=True, - path_type=Path, - ), -) -@click.option( - "-p", - "--nctbfn_template", - required=False, - default="NSIDC-0763-EASE2_{hemlet}{gridres}km-GCOMW1_AMSR2-{year}{doy}-{capchan}-{tim}-SIR-PPS_XCAL-v1.1.nc", # noqa -) -@click.option( - "-f", - "--timeframe", - required=False, - default="M", -) -def a2l1c( - *, - date: dt.date, - hemisphere: Hemisphere, - output_dir: Path, - tb_dir: Path, - anc_dir: Path, - nctbfn_template: str, - timeframe: str, -): - """Run the bootstrap algorithm with 'a2l1c' data. - - AMSR brightness temperatures are fetched from 6.25km raw data fields - derived from nsidc0763 (unpublished) files created from L1C fields - - The resulting concentration field is saved to a netcdf file in the given - `output_dir`. - """ - resolution = "6.25km" - conc_ds = a2l1c_goddard_bootstrap( - date=date, - hemisphere=hemisphere, - tb_dir=tb_dir, - anc_dir=anc_dir, - ncfn_template=nctbfn_template, - timeframe=timeframe, - ) - - output_fn = standard_output_filename( - hemisphere=hemisphere, - date=date, - sat="a2l1c", - resolution=resolution, - algorithm="bt", - timeframe=timeframe, - ) - output_path = output_dir / output_fn - # conc_ds.to_netcdf(output_path) - conc_ds.astype(np.float32).to_netcdf(output_path, encoding={"conc": {"zlib": True}}) - - logger.info(f"Wrote a2l1c concentration field: {output_path}") - - # Note: the following command replaces the output file - add_info_to_netcdf_file_a2l1c(output_path) - logger.info(f"Re-wrote AMSR2 concentration netCDF file: {output_path}") - - # Write an equivalent geotiff file - geotiff_output_path = derive_geotiff_name_a2l1c(output_path) - create_equivalent_geotiff_a2l1c(output_path, geotiff_output_path) - logger.info(f"Wrote AMSR2 concentration geotiff: {geotiff_output_path}") - - -@click.group(name="bootstrap") -def cli(): - """Run the bootstrap algorithm.""" - ... - - -cli.add_command(amsr2) -cli.add_command(a2l1c) - - -if __name__ == "__main__": - cli() diff --git a/pm_icecon/bt/compute_bt_ic.py b/pm_icecon/bt/compute_bt_ic.py index 56e9b78a..fb42f366 100644 --- a/pm_icecon/bt/compute_bt_ic.py +++ b/pm_icecon/bt/compute_bt_ic.py @@ -873,10 +873,12 @@ def calc_bootstrap_conc( def bootstrap( + *, tb_v37: npt.NDArray, tb_h37: npt.NDArray, tb_v19: npt.NDArray, params: BootstrapParams, + land_mask: npt.NDArray[np.bool_], tb_mask: npt.NDArray[np.bool_], weather_mask: npt.NDArray[np.bool_], missing_flag_value: float | int = DEFAULT_FLAG_VALUES.missing, @@ -888,7 +890,7 @@ def bootstrap( Flags values are not set and spillover correction is not applied. """ line_37v37h = get_linfit( - land_mask=params.land_mask, + land_mask=land_mask, tb_mask=tb_mask, tbx=tb_v37, tby=tb_h37, @@ -915,7 +917,7 @@ def bootstrap( ) line_37v19v = get_linfit( - land_mask=params.land_mask, + land_mask=land_mask, tb_mask=tb_mask, tbx=tb_v37, tby=tb_v19, @@ -1042,6 +1044,8 @@ def goddard_bootstrap( tb_v19: npt.NDArray, tb_v22: npt.NDArray, params: BootstrapParams, + land_mask: npt.NDArray[np.bool_], + invalid_ice_mask: npt.NDArray[np.bool_], date: dt.date, missing_flag_value: float | int = DEFAULT_FLAG_VALUES.missing, ) -> xr.Dataset: @@ -1067,7 +1071,7 @@ def goddard_bootstrap( h37=tb_h37, v22=tb_v22, v19=tb_v19, - land_mask=params.land_mask, + land_mask=land_mask, tb_mask=tb_mask, ln1=params.vh37_params.lnline, date=date, @@ -1081,6 +1085,7 @@ def goddard_bootstrap( tb_h37=tb_h37, tb_v19=tb_v19, params=params, + land_mask=land_mask, tb_mask=tb_mask, weather_mask=weather_mask, missing_flag_value=missing_flag_value, @@ -1089,26 +1094,26 @@ def goddard_bootstrap( # Apply masks and flag values conc[weather_mask] = 0.0 conc[tb_mask] = DEFAULT_FLAG_VALUES.missing - conc[params.land_mask] = DEFAULT_FLAG_VALUES.land + conc[land_mask] = DEFAULT_FLAG_VALUES.land conc = apply_invalid_ice_mask( conc=conc, missing_flag_value=missing_flag_value, land_flag_value=DEFAULT_FLAG_VALUES.land, - invalid_ice_mask=params.invalid_ice_mask, + invalid_ice_mask=invalid_ice_mask, ) conc = coastal_fix( conc=conc, missing_flag_value=missing_flag_value, - land_mask=params.land_mask, + land_mask=land_mask, minic=params.minic, ) conc[conc < params.minic] = 0 jdim, idim = conc.shape # If middle of land_mask is land, this is SH and needs no pole hole fill - if not params.land_mask[jdim // 2, idim // 2]: + if not land_mask[jdim // 2, idim // 2]: conc = fill_pole_hole_bt(conc) ds = xr.Dataset({"conc": (("y", "x"), conc)}) diff --git a/pm_icecon/bt/fields.py b/pm_icecon/bt/fields.py deleted file mode 100644 index 145f0d7e..00000000 --- a/pm_icecon/bt/fields.py +++ /dev/null @@ -1,37 +0,0 @@ -import datetime as dt - -from pm_icecon.bt.masks import get_ps_invalid_ice_mask -from pm_icecon.gridid import get_gridid_hemisphere, get_gridid_resolution -from pm_icecon.masks import get_ps_land_mask, get_ps_pole_hole_mask - - -def get_bootstrap_fields( - *, - date: dt.date, - satellite: str, - # TODO: replace `gridid` with hemisphere & resolution kwargs. Only the - # top-most API of the ECDR should deal with translating gridid into - # appropriate values for downstream functions. - gridid: str, -): - hemisphere = get_gridid_hemisphere(gridid) - resolution = get_gridid_resolution(gridid) - - invalid_ice_mask = get_ps_invalid_ice_mask( - hemisphere=hemisphere, - date=date, - resolution=resolution, - ) - - land_mask = get_ps_land_mask(hemisphere=hemisphere, resolution=resolution) - - # There's no pole hole in the southern hemisphere. - pole_mask = ( - get_ps_pole_hole_mask(resolution=resolution) if hemisphere == "north" else None - ) - - return dict( - invalid_ice_mask=invalid_ice_mask, - land_mask=land_mask, - pole_mask=pole_mask, - ) diff --git a/pm_icecon/bt/masks.py b/pm_icecon/bt/masks.py index 7b9ac942..e69de29b 100644 --- a/pm_icecon/bt/masks.py +++ b/pm_icecon/bt/masks.py @@ -1,58 +0,0 @@ -import datetime as dt -from pathlib import Path - -import numpy as np -import numpy.typing as npt -from loguru import logger -from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS -from pm_tb_data._types import Hemisphere - -from pm_icecon.constants import BT_GODDARD_ANCILLARY_DIR, CDR_TESTDATA_DIR -from pm_icecon.masks import get_pss_12_validice_land_coast_array -from pm_icecon.util import get_ps25_grid_shape - - -def get_ps_invalid_ice_mask( - *, - hemisphere: Hemisphere, - date: dt.date, - resolution: AU_SI_RESOLUTIONS, -) -> npt.NDArray[np.bool_]: - """Read and return the polar stereo invalid ice mask. - - `True` values indicate areas that are masked as invalid. - """ - logger.info( - f"Reading valid ice mask for PS{hemisphere[0].upper()} {resolution}km grid" - ) # noqa - if hemisphere == "north": - if resolution == "25": - sst_fn = ( - BT_GODDARD_ANCILLARY_DIR / f"np_sect_sst1_sst2_mask_{date:%m}.int" - ).resolve() - sst_mask = np.fromfile(sst_fn, dtype=np.int16).reshape( - get_ps25_grid_shape(hemisphere=hemisphere) - ) - elif resolution == "12": - mask_fn = ( - CDR_TESTDATA_DIR - / f"btequiv_psn12.5/bt_validmask_psn12.5km_{date:%m}.dat" - ) - - sst_mask = np.fromfile(mask_fn, dtype=np.int16).reshape(896, 608) - else: - if resolution == "12": - # values of 24 indicate invalid ice. - sst_mask = get_pss_12_validice_land_coast_array(date=date) - elif resolution == "25": - sst_fn = Path( - BT_GODDARD_ANCILLARY_DIR - / f"SH_{date:%m}_SST_avhrr_threshold_{date:%m}_fixd.int" - ) - sst_mask = np.fromfile(sst_fn, dtype=np.int16).reshape( - get_ps25_grid_shape(hemisphere=hemisphere) - ) - - is_high_sst = sst_mask == 24 - - return is_high_sst diff --git a/pm_icecon/bt/params/ausi_amsr2.py b/pm_icecon/bt/params/ausi_amsr2.py index f311db53..838ecb8b 100644 --- a/pm_icecon/bt/params/ausi_amsr2.py +++ b/pm_icecon/bt/params/ausi_amsr2.py @@ -9,11 +9,9 @@ import datetime as dt from typing import cast -from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS from pm_tb_data._types import Hemisphere from pm_icecon.bt._types import Line, Tiepoint -from pm_icecon.bt.masks import get_ps_invalid_ice_mask from pm_icecon.bt.params._types import ParamsDict from pm_icecon.bt.params.util import setup_bootstrap_params_dict from pm_icecon.config.models.bt import ( @@ -23,7 +21,6 @@ WeatherFilterParamsForSeason, ) from pm_icecon.gridid import get_gridid_hemisphere -from pm_icecon.masks import get_ps_land_mask, get_ps_pole_hole_mask GODDARD_AMSR2_NORTH_PARAMS = ParamsDict( vh37_params=TbSetParams( @@ -167,28 +164,11 @@ CDR_AMSR2_SOUTH_PARAMS["weather_filter_seasons"] = _bt_south_weather_filter_seasons -# used to get parameters in `cdr.py`. Not used by the ecdr. def get_amsr2_params( *, - date: dt.date, hemisphere: Hemisphere, - resolution: AU_SI_RESOLUTIONS, ) -> BootstrapParams: - invalid_ice_mask = get_ps_invalid_ice_mask( - hemisphere=hemisphere, - date=date, - resolution=resolution, - ) - bt_params = BootstrapParams( - land_mask=get_ps_land_mask(hemisphere=hemisphere, resolution=resolution), - # There's no pole hole in the southern hemisphere. - pole_mask=( - get_ps_pole_hole_mask(resolution=resolution) - if hemisphere == "north" - else None - ), - invalid_ice_mask=invalid_ice_mask, **(CDR_AMSR2_NORTH_PARAMS if hemisphere == "north" else CDR_AMSR2_SOUTH_PARAMS), ) diff --git a/pm_icecon/bt/params/util.py b/pm_icecon/bt/params/util.py index 280058d4..855180ae 100644 --- a/pm_icecon/bt/params/util.py +++ b/pm_icecon/bt/params/util.py @@ -1,40 +1,7 @@ import datetime as dt -import numpy as np from pm_icecon.bt.compute_bt_ic import _get_wx_params as interpolate_bt_wx_params -from pm_icecon.config.models.bt import BootstrapParams, TbSetParams, cast_as_TiepointSet - - -def convert_to_pmicecon_bt_params(hemisphere, params, fields) -> BootstrapParams: - """Convert to old-style bt_params.""" - # oldstyle_bt_params = {**params, **fields} - oldstyle_bt_params = BootstrapParams( - land_mask=np.array(fields["land_mask"]).squeeze(), - # There's no pole hole in the southern hemisphere. - pole_mask=np.array(fields["pole_mask"]) if hemisphere == "north" else None, - invalid_ice_mask=np.array(fields["invalid_ice_mask"]), - vh37_params=TbSetParams( - water_tie_point_set=cast_as_TiepointSet( - params["bt_wtp_v37"], params["bt_wtp_h37"] - ), - ice_tie_point_set=cast_as_TiepointSet( - params["bt_itp_v37"], params["bt_itp_h37"] - ), - lnline=params["vh37_lnline"], - ), - v1937_params=TbSetParams( - water_tie_point_set=cast_as_TiepointSet( - params["bt_wtp_v37"], params["bt_wtp_v19"] - ), - ice_tie_point_set=cast_as_TiepointSet( - params["bt_itp_v37"], params["bt_itp_v19"] - ), - lnline=params["v1937_lnline"], - ), - **params, - ) - return oldstyle_bt_params def setup_bootstrap_params_dict( diff --git a/pm_icecon/cli/__init__.py b/pm_icecon/cli/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pm_icecon/cli/entrypoint.py b/pm_icecon/cli/entrypoint.py deleted file mode 100644 index 5432fb7f..00000000 --- a/pm_icecon/cli/entrypoint.py +++ /dev/null @@ -1,20 +0,0 @@ -import click - -from pm_icecon.bt.cli import cli as bt_cli -from pm_icecon.nt.cli import cli as nt_cli - - -@click.group() -def cli(): - """Run the nasateam or bootstrap algorithm.""" - ... - - -cli.add_command(bt_cli) -cli.add_command(nt_cli) - - -if __name__ == "__main__": - from pm_icecon.cli.entrypoint import cli - - cli() diff --git a/pm_icecon/cli/util.py b/pm_icecon/cli/util.py deleted file mode 100644 index 64337282..00000000 --- a/pm_icecon/cli/util.py +++ /dev/null @@ -1,6 +0,0 @@ -import datetime as dt - - -def datetime_to_date(_ctx, _param, value: dt.datetime) -> dt.date: - """Click callback that takes a `dt.datetime` and returns `dt.date`.""" - return value.date() diff --git a/pm_icecon/config/models/bt.py b/pm_icecon/config/models/bt.py index 90a7b7f5..a390f901 100644 --- a/pm_icecon/config/models/bt.py +++ b/pm_icecon/config/models/bt.py @@ -1,8 +1,3 @@ -from typing import Optional - -import numpy as np -import numpy.typing as npt - from pm_icecon.bt._types import Line, Tiepoint, TiepointSet from pm_icecon.config.models.base_model import ConfigBaseModel @@ -87,16 +82,6 @@ class BootstrapParams(ConfigBaseModel): maxtb: float = 320.0 """The maximum valid brightness temperature value.""" - # TODO: change to boolean type mask - land_mask: npt.NDArray[np.bool_] - - # TODO: change to boolean type mask - # Hemisphere dependent. Should be required for Northern hemisphere. Should - # be exlcluded in South. TODO: should we create a custom validator for this? - # We would also want to add Hemisphere to this config object as well in that - # case. - pole_mask: Optional[npt.NDArray[np.bool_]] = None - # TODO: validators: # * No overlap between seasons # * If only 1 season, date range should be full range. Otherwise at least @@ -110,6 +95,3 @@ class BootstrapParams(ConfigBaseModel): vh37_params: TbSetParams v1937_params: TbSetParams - - invalid_ice_mask: npt.NDArray[np.bool_] - """Mask representing areas that are invalid for sea ice.""" diff --git a/pm_icecon/constants.py b/pm_icecon/constants.py index a3f48bb1..7977bdec 100644 --- a/pm_icecon/constants.py +++ b/pm_icecon/constants.py @@ -1,15 +1,3 @@ -from pathlib import Path - from pm_icecon.config.models import FlagValues DEFAULT_FLAG_VALUES = FlagValues() - -# NSIDC infrastructure-specific paths: -NSIDC_NFS_SHARE_DIR = Path("/share/apps/amsr2-cdr") -# Produced CDR data files go here. -BOOTSTRAP_MASKS_DIR = NSIDC_NFS_SHARE_DIR / "bootstrap_masks" -# Contains regression data, ancillary data files (masks), etc. -# TODO: move ancillary files out of `cdr_testdata` dir? On the VMs, the -# ancillary nasateam files in cdr_testdata are also in the `NSIDC_NFS_SHARE_DIR` -CDR_TESTDATA_DIR = NSIDC_NFS_SHARE_DIR / "cdr_testdata" -BT_GODDARD_ANCILLARY_DIR = CDR_TESTDATA_DIR / "bt_goddard_ANCILLARY" diff --git a/pm_icecon/masks.py b/pm_icecon/masks.py deleted file mode 100644 index fdbf3c7f..00000000 --- a/pm_icecon/masks.py +++ /dev/null @@ -1,136 +0,0 @@ -"""Code related to land, valid ice, and pole-hole masks. - -Algorithm-specific valid ice masks are in their respective algorithm-specific -modules (e.g., `bt.masks`). - -TODO: should we really use different valid ice masks depending on the algorithm? -Why not one source of truth? Ultimatley we do want to make valid ice masks -configurable for the user. Perhaps these should me moved into the `params` -subpackage (e.g., `bt.params`) -""" -import datetime as dt - -import numpy as np -import numpy.typing as npt -from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS -from pm_tb_data._types import Hemisphere - -from pm_icecon.constants import ( - BOOTSTRAP_MASKS_DIR, - BT_GODDARD_ANCILLARY_DIR, - CDR_TESTDATA_DIR, -) -from pm_icecon.util import get_ps25_grid_shape - - -# TODO: accept `Hemisphere` arg and return None if South? -def get_ps_pole_hole_mask(*, resolution: AU_SI_RESOLUTIONS) -> npt.NDArray[np.bool_]: - # values of 1 indicate the pole hole. - if resolution == "25": - pole_mask_psn = ( - np.fromfile( - (BT_GODDARD_ANCILLARY_DIR / "np_holemask.ssmi_f17").resolve(), - dtype=np.int16, - ).reshape(448, 304) - == 1 - ) - elif resolution == "12": - pole_mask_psn = ( - np.fromfile( - CDR_TESTDATA_DIR / "btequiv_psn12.5/bt_poleequiv_psn12.5km.dat", - dtype=np.int16, - ).reshape(896, 608) - == 1 - ) - else: - raise NotImplementedError(f"No pole hole mask for PS {resolution} available.") - - return pole_mask_psn - - -def get_pss_12_validice_land_coast_array(*, date: dt.date) -> npt.NDArray[np.int16]: - """Get the polar stereo south 12.5km valid ice/land/coast array. - - 4 unique values: - * 0 == land - * 4 == valid ice - * 24 == invalid ice - * 32 == coast. - """ - fn = BOOTSTRAP_MASKS_DIR / f"bt_valid_pss12.5_int16_{date:%m}.dat" - validice_land_coast = np.fromfile(fn, dtype=np.int16).reshape(664, 632) - - return validice_land_coast - - -def get_ps_land_mask( - *, - hemisphere: Hemisphere, - resolution: AU_SI_RESOLUTIONS, -) -> npt.NDArray[np.bool_]: - """Get the polar stereo 25km land mask.""" - # Ocean has a value of 0, land a value of 1, and coast a value of 2. - if resolution == "25": - shape = get_ps25_grid_shape(hemisphere=hemisphere) - _land_coast_array = np.fromfile( - ( - BT_GODDARD_ANCILLARY_DIR - / ( - f"{hemisphere}_land_25" - # NOTE: According to scotts, the 'r' in the southern hemisphere - # filename probably stands for “revised“. - f"{'r' if hemisphere == 'south' else ''}" - ) - ).resolve(), - dtype=np.int16, - ).reshape(shape) - - land_mask = _land_coast_array != 0 - - # TODO: land mask currently includes land and coast. Does this make sense? Are - # we ever going to need to coast values? Maybe rename to `LAND_COAST_MASK`? - elif resolution == "12": - if hemisphere == "south": - # Any date is OK. The land mask is the same for all of the pss 12 - # validice/land masks - _land_coast_array = get_pss_12_validice_land_coast_array( - date=dt.date.today() - ) - land_mask = np.logical_or(_land_coast_array == 0, _land_coast_array == 32) - else: - _land_coast_array = np.fromfile( - CDR_TESTDATA_DIR / "btequiv_psn12.5/bt_landequiv_psn12.5km.dat", - dtype=np.int16, - ).reshape(896, 608) - - land_mask = _land_coast_array != 0 - - return land_mask - - -def get_e2n625_land_mask(anc_dir) -> npt.NDArray[np.bool_]: - """Get the northern hemisphere e2n625 land mask. - - The authoritative mask for the NH EASE2 Arctic subset - is a 1680x1680 (centered) subset of the full 2880x2880 EASE2 NH grid - These data were derived from the MCD12Q1 land type data set - Encoding is - 50: Ocean (= water orthogonally connected to the global ocean) - 100: Lake (= water that is not connected to the global ocean) - 125: Coast (= "Land" that is adjacent to "Ocean" - 150: Land ("land type 1" that is not water and not ice) - 200: Ice (= land classification type "permanent ice" - For the purposes of the Bootstrap algorithm: - 50 --> 0 (= "ocean" where sea ice might occur) - all others -> - """ - _land_coast_array_e2n625 = np.fromfile( - anc_dir / "locli_e2n6.25_1680x1680.dat", - dtype=np.uint8, - ).reshape(1680, 1680) - - # TODO: land mask currently includes land and coast. Does this make sense? Are - # we ever going to need to coast values? Maybe rename to `LAND_COAST_MASK`? - land_mask_e2n625 = _land_coast_array_e2n625 != 50 - - return land_mask_e2n625 diff --git a/pm_icecon/nt/api.py b/pm_icecon/nt/api.py index 00a10f1e..29bc7677 100644 --- a/pm_icecon/nt/api.py +++ b/pm_icecon/nt/api.py @@ -2,8 +2,9 @@ from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS, get_au_si_tbs from pm_tb_data._types import Hemisphere +import numpy as np +import numpy.typing as npt -from pm_icecon.bt.masks import get_ps_invalid_ice_mask from pm_icecon.interpolation import spatial_interp_tbs from pm_icecon.nt.compute_nt_ic import goddard_nasateam from pm_icecon.nt.params.amsr2 import get_amsr2_params @@ -11,7 +12,16 @@ def amsr2_goddard_nasateam( - *, date: dt.date, hemisphere: Hemisphere, resolution: AU_SI_RESOLUTIONS + *, + date: dt.date, + hemisphere: Hemisphere, + resolution: AU_SI_RESOLUTIONS, + invalid_ice_mask: npt.NDArray[np.bool_], + # The shoremap has values 1-5 that indicate land, + # coast, and cells away from coast (3-5). + shoremap: npt.NDArray, + # minic == minimum ice concentration grid. + minic: npt.NDArray, ): """Compute sea ice concentration from AU_SI25 TBs. @@ -26,19 +36,6 @@ def amsr2_goddard_nasateam( nt_params = get_amsr2_params( hemisphere=hemisphere, - resolution=resolution, - ) - - # TODO: this function is currently defined in the bootstrap-specific masks - # module. Should it be moved to the top-level masks? Originally split masks - # between nt and bt modules because the original goddard nasateam example - # used a unique invalid ice mask. Eventually won't matter too much because - # we plan to move most masks into common nc files that will be read on a - # per-grid basis. - invalid_ice_mask = get_ps_invalid_ice_mask( - hemisphere=hemisphere, - date=date, - resolution=resolution, ) conc_ds = goddard_nasateam( @@ -46,8 +43,8 @@ def amsr2_goddard_nasateam( tb_v37=spatial_interp_tbs(xr_tbs["v36"].data), tb_v22=spatial_interp_tbs(xr_tbs["v23"].data), tb_h19=spatial_interp_tbs(xr_tbs["h18"].data), - shoremap=nt_params.shoremap, - minic=nt_params.minic, + shoremap=shoremap, + minic=minic, invalid_ice_mask=invalid_ice_mask, gradient_thresholds=nt_params.gradient_thresholds, tiepoints=get_tiepoints(satellite="u2", hemisphere=hemisphere), diff --git a/pm_icecon/nt/cli.py b/pm_icecon/nt/cli.py deleted file mode 100644 index 7e1b48b7..00000000 --- a/pm_icecon/nt/cli.py +++ /dev/null @@ -1,91 +0,0 @@ -import datetime as dt -from pathlib import Path -from typing import get_args - -import click -from loguru import logger -from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS -from pm_tb_data._types import Hemisphere - -from pm_icecon.cli.util import datetime_to_date -from pm_icecon.nt.api import amsr2_goddard_nasateam -from pm_icecon.util import standard_output_filename - - -# Click definitions for "amsr2" which uses AU25 -@click.command() -@click.option( - "-d", - "--date", - required=True, - type=click.DateTime(formats=("%Y-%m-%d",)), - callback=datetime_to_date, -) -@click.option( - "-h", - "--hemisphere", - required=True, - type=click.Choice(get_args(Hemisphere)), -) -@click.option( - "-o", - "--output-dir", - required=True, - type=click.Path( - exists=True, - file_okay=False, - dir_okay=True, - writable=True, - resolve_path=True, - path_type=Path, - ), -) -@click.option( - "-r", - "--resolution", - required=True, - type=click.Choice(get_args(AU_SI_RESOLUTIONS)), -) -def amsr2( - *, - date: dt.date, - hemisphere: Hemisphere, - output_dir: Path, - resolution: AU_SI_RESOLUTIONS, -): - """Run the nasateam algorithm with ASMR2 data. - - AMSRU2 brightness temperatures are fetched from AU_SI{12|25}. - - The resulting concentration field is saved to a netcdf file in the given - `output_dir` with the form `{N|S}H_{YYYYMMDD}_py_NRT_amsr2.nc` - """ - conc_ds = amsr2_goddard_nasateam( - date=date, - hemisphere=hemisphere, - resolution=resolution, - ) - - output_fn = standard_output_filename( - hemisphere=hemisphere, - date=date, - sat="u2", - algorithm="nt", - resolution=f"{resolution}km", - ) - output_path = output_dir / output_fn - conc_ds.to_netcdf(output_path) - logger.info(f"Wrote AMSR2 concentration field: {output_path}") - - -@click.group(name="nasateam") -def cli(): - """Run the nasateam algorithm.""" - ... - - -cli.add_command(amsr2) - - -if __name__ == "__main__": - cli() diff --git a/pm_icecon/nt/masks.py b/pm_icecon/nt/masks.py deleted file mode 100644 index 1c841f8d..00000000 --- a/pm_icecon/nt/masks.py +++ /dev/null @@ -1,40 +0,0 @@ -import datetime as dt - -import numpy as np -import numpy.typing as npt -from pm_tb_data._types import Hemisphere - -from pm_icecon.constants import CDR_TESTDATA_DIR -from pm_icecon.util import get_ps25_grid_shape - - -def get_ps25_sst_mask( - *, - hemisphere: Hemisphere, - date: dt.date, - sst_threshold=2780, -) -> npt.NDArray[np.bool_]: - """Read and return the ps25 SST mask. - - `True` elements are those which are masked as invalid ice. - """ - # TODO: why are the northern hemisphere files 'fixed' while the southern - # hemisphere are not (except in one case)? - month_abbr = f"{date:%b}".lower() - if hemisphere == "north": - sst_fn = f"{month_abbr}.temp.zdf.ssmi_fixed_25fill.fixed" - else: - sst_fn = f"{month_abbr}.temp.zdf.ssmi_25fill" - - sst_path = ( - CDR_TESTDATA_DIR - / f"nt_datafiles/data36/SST/{hemisphere.capitalize()}/" - / sst_fn - ) - sst_field = np.fromfile(sst_path, dtype=">i2")[150:].reshape( - get_ps25_grid_shape(hemisphere=hemisphere) - ) - - where_sst_high = sst_field >= sst_threshold - - return where_sst_high diff --git a/pm_icecon/nt/params/amsr2.py b/pm_icecon/nt/params/amsr2.py index b74e695a..3ca6fa72 100644 --- a/pm_icecon/nt/params/amsr2.py +++ b/pm_icecon/nt/params/amsr2.py @@ -1,26 +1,19 @@ """Parameters for use with AMSR2 (AU_SI{12|25}) data.""" from dataclasses import dataclass -import numpy as np -import numpy.typing as npt from loguru import logger -from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS from pm_tb_data._types import Hemisphere -from pm_icecon.constants import CDR_TESTDATA_DIR from pm_icecon.nt._types import NasateamGradientRatioThresholds from pm_icecon.nt.params.goddard_rss import ( RSS_F17_NORTH_GRADIENT_THRESHOLDS, RSS_F17_SOUTH_GRADIENT_THRESHOLDS, ) from pm_icecon.nt.tiepoints import NasateamTiePoints, get_tiepoints -from pm_icecon.util import get_ps_grid_shape @dataclass class NasateamParams: - shoremap: npt.NDArray - minic: npt.NDArray tiepoints: NasateamTiePoints gradient_thresholds: NasateamGradientRatioThresholds @@ -28,26 +21,7 @@ class NasateamParams: def get_amsr2_params( *, hemisphere: Hemisphere, - resolution: AU_SI_RESOLUTIONS, ) -> NasateamParams: - # Nasateam specific config - _nasateam_ancillary_dir = CDR_TESTDATA_DIR / "nasateam_ancillary" - # TODO: type for shoremap? The shoremap has values 1-5 that indicate land, - # coast, and cells away from coast (3-5) - nt_shoremap = np.fromfile( - (_nasateam_ancillary_dir / f"shoremap_amsru_{hemisphere[0]}h{resolution}.dat"), - dtype=np.uint8, - ).reshape(get_ps_grid_shape(hemisphere=hemisphere, resolution=resolution)) - # minic == minimum ice concentration grid. Used in the nasateam land - # spillover code. - # TODO: better description/type for minic. - nt_minic = np.fromfile( - (_nasateam_ancillary_dir / f"minic_amsru_{hemisphere[0]}h{resolution}.dat"), - dtype=np.int16, - ).reshape(get_ps_grid_shape(hemisphere=hemisphere, resolution=resolution)) - # Scale down by 10. The original alg. dealt w/ concentrations scaled by 10. - nt_minic = nt_minic / 10 # type: ignore[assignment] - # Get tiepoints nt_tiepoints = get_tiepoints(satellite="u2", hemisphere=hemisphere) @@ -60,8 +34,6 @@ def get_amsr2_params( logger.info("NT gradient threshold values for AMSR2 are copied from f17_final") return NasateamParams( - shoremap=nt_shoremap, - minic=nt_minic, tiepoints=nt_tiepoints, gradient_thresholds=nt_gradient_thresholds, ) diff --git a/pm_icecon/tests/integration/test_paramfiles.py b/pm_icecon/tests/integration/test_paramfiles.py index 8466e63e..98ebbb8f 100644 --- a/pm_icecon/tests/integration/test_paramfiles.py +++ b/pm_icecon/tests/integration/test_paramfiles.py @@ -1,11 +1,9 @@ import datetime as dt import pm_icecon.bt.params.ausi_amsr2 as amsr2_params -from pm_icecon.bt.fields import get_bootstrap_fields from pm_icecon.bt.params.experimental.ausi12_amsr2 import ( get_ausi12_experimental_bootstrap_params, ) -from pm_icecon.bt.params.util import convert_to_pmicecon_bt_params from pm_icecon.tests.unit.test_bt_params import _get_config_hash @@ -23,62 +21,19 @@ def test_get_ausi12_experimental_bootstrap_params(): assert "wintrc" in bt_parameters.keys() -def test_get_bootstrap_fields(): - date = dt.date(2020, 1, 1) - satellite = "amsr2" - gridid = "e2n25" - - bt_field_dict = get_bootstrap_fields( - date=date, - satellite=satellite, - gridid=gridid, - ) - assert "invalid_ice_mask" in bt_field_dict.keys() - - -def test_convert_to_pmicecon_bt_params(): - hemisphere = "north" - date = dt.date(2020, 1, 1) - satellite = "amsr2" - gridid = "e2n25" - - bt_parameters = get_ausi12_experimental_bootstrap_params( - date=date, - satellite=satellite, - gridid=gridid, - ) - bt_field_dict = get_bootstrap_fields( - date=date, - satellite=satellite, - gridid=gridid, - ) - oldstyle_params = convert_to_pmicecon_bt_params( - hemisphere, bt_parameters, bt_field_dict - ) - assert oldstyle_params is not None - - def test_ausi12_amsr2_bt_params_north(): date = dt.date(2022, 1, 1) - fields = get_bootstrap_fields(date=date, satellite="amsr2", gridid="e2ns25") params = amsr2_params.get_ausi_bootstrap_params( date=date, satellite="amsr2", gridid="e2ns25" ) - bt_params = convert_to_pmicecon_bt_params( - hemisphere="north", params=params, fields=fields - ) - assert _get_config_hash(bt_params) == "8e61f93a2f762e962323f159342d282c" + assert _get_config_hash(params) == "af19cc9a1d289c97b0b5cc9dd1bf952c" def test_ausi12_amsr2_bt_params_south(): date = dt.date(2022, 1, 1) - fields = get_bootstrap_fields(date=date, satellite="amsr2", gridid="e2ss25") params = amsr2_params.get_ausi_bootstrap_params( date=date, satellite="amsr2", gridid="e2ss25" ) - bt_params = convert_to_pmicecon_bt_params( - hemisphere="south", params=params, fields=fields - ) - assert _get_config_hash(bt_params) == "a5e1d2959f31ad165a075cd9003fbdff" + assert _get_config_hash(params) == "74764a3d75261eea42a1ee703b5123c2" diff --git a/pm_icecon/tests/regression/__init__.py b/pm_icecon/tests/regression/__init__.py index e69de29b..009f0d80 100644 --- a/pm_icecon/tests/regression/__init__.py +++ b/pm_icecon/tests/regression/__init__.py @@ -0,0 +1,10 @@ +from pathlib import Path + + +# NSIDC infrastructure-specific paths: +NSIDC_NFS_SHARE_DIR = Path("/share/apps/amsr2-cdr") + +# Contains regression data, ancillary data files (masks), etc. +# TODO: move ancillary files out of `cdr_testdata` dir? On the VMs, the +# ancillary nasateam files in cdr_testdata are also in the `NSIDC_NFS_SHARE_DIR` +CDR_TESTDATA_DIR = NSIDC_NFS_SHARE_DIR / "cdr_testdata" diff --git a/pm_icecon/tests/regression/test_bt.py b/pm_icecon/tests/regression/test_bt.py index 43fe524f..d34a04c8 100644 --- a/pm_icecon/tests/regression/test_bt.py +++ b/pm_icecon/tests/regression/test_bt.py @@ -1,22 +1,137 @@ import datetime as dt from pathlib import Path +from typing import Final import numpy as np import xarray as xr from numpy.testing import assert_almost_equal from numpy.typing import NDArray +import numpy.typing as npt from pm_tb_data.fetch.au_si import AU_SI_RESOLUTIONS from pm_tb_data._types import Hemisphere +from loguru import logger import pm_icecon.bt.compute_bt_ic as bt from pm_icecon.bt.api import amsr2_goddard_bootstrap from pm_icecon.bt.compute_bt_ic import xfer_class_tbs -from pm_icecon.bt.masks import get_ps_invalid_ice_mask from pm_icecon.bt.params.class_sats import SSMIS_NORTH_PARAMS from pm_icecon.config.models.bt import BootstrapParams -from pm_icecon.constants import CDR_TESTDATA_DIR from pm_icecon.interpolation import spatial_interp_tbs -from pm_icecon.masks import get_ps_land_mask, get_ps_pole_hole_mask +from pm_icecon.util import get_ps25_grid_shape +from pm_icecon.tests.regression import ( + CDR_TESTDATA_DIR, + NSIDC_NFS_SHARE_DIR, +) + + +BOOTSTRAP_MASKS_DIR = NSIDC_NFS_SHARE_DIR / "bootstrap_masks" +BT_GODDARD_ANCILLARY_DIR = CDR_TESTDATA_DIR / "bt_goddard_ANCILLARY" + + +def _get_pss_12_validice_land_coast_array(*, date: dt.date) -> npt.NDArray[np.int16]: + """Get the polar stereo south 12.5km valid ice/land/coast array. + + 4 unique values: + * 0 == land + * 4 == valid ice + * 24 == invalid ice + * 32 == coast. + """ + fn = BOOTSTRAP_MASKS_DIR / f"bt_valid_pss12.5_int16_{date:%m}.dat" + validice_land_coast = np.fromfile(fn, dtype=np.int16).reshape(664, 632) + + return validice_land_coast + + +def _get_ps_land_mask( + *, + hemisphere: Hemisphere, + resolution: AU_SI_RESOLUTIONS, +) -> npt.NDArray[np.bool_]: + """Get the polar stereo 25km land mask.""" + # Ocean has a value of 0, land a value of 1, and coast a value of 2. + if resolution == "25": + shape = get_ps25_grid_shape(hemisphere=hemisphere) + _land_coast_array = np.fromfile( + ( + BT_GODDARD_ANCILLARY_DIR + / ( + f"{hemisphere}_land_25" + # NOTE: According to scotts, the 'r' in the southern hemisphere + # filename probably stands for “revised“. + f"{'r' if hemisphere == 'south' else ''}" + ) + ).resolve(), + dtype=np.int16, + ).reshape(shape) + + land_mask = _land_coast_array != 0 + + # TODO: land mask currently includes land and coast. Does this make sense? Are + # we ever going to need to coast values? Maybe rename to `LAND_COAST_MASK`? + elif resolution == "12": + if hemisphere == "south": + # Any date is OK. The land mask is the same for all of the pss 12 + # validice/land masks + _land_coast_array = _get_pss_12_validice_land_coast_array( + date=dt.date.today() + ) + land_mask = np.logical_or(_land_coast_array == 0, _land_coast_array == 32) + else: + _land_coast_array = np.fromfile( + CDR_TESTDATA_DIR / "btequiv_psn12.5/bt_landequiv_psn12.5km.dat", + dtype=np.int16, + ).reshape(896, 608) + + land_mask = _land_coast_array != 0 + + return land_mask + + +def _get_ps_invalid_ice_mask( + *, + hemisphere: Hemisphere, + date: dt.date, + resolution: AU_SI_RESOLUTIONS, +) -> npt.NDArray[np.bool_]: + """Read and return the polar stereo invalid ice mask. + + `True` values indicate areas that are masked as invalid. + """ + logger.info( + f"Reading valid ice mask for PS{hemisphere[0].upper()} {resolution}km grid" + ) # noqa + if hemisphere == "north": + if resolution == "25": + sst_fn = ( + BT_GODDARD_ANCILLARY_DIR / f"np_sect_sst1_sst2_mask_{date:%m}.int" + ).resolve() + sst_mask = np.fromfile(sst_fn, dtype=np.int16).reshape( + get_ps25_grid_shape(hemisphere=hemisphere) + ) + elif resolution == "12": + mask_fn = ( + CDR_TESTDATA_DIR + / f"btequiv_psn12.5/bt_validmask_psn12.5km_{date:%m}.dat" + ) + + sst_mask = np.fromfile(mask_fn, dtype=np.int16).reshape(896, 608) + else: + if resolution == "12": + # values of 24 indicate invalid ice. + sst_mask = _get_pss_12_validice_land_coast_array(date=date) + elif resolution == "25": + sst_fn = Path( + BT_GODDARD_ANCILLARY_DIR + / f"SH_{date:%m}_SST_avhrr_threshold_{date:%m}_fixd.int" + ) + sst_mask = np.fromfile(sst_fn, dtype=np.int16).reshape( + get_ps25_grid_shape(hemisphere=hemisphere) + ) + + is_high_sst = sst_mask == 24 + + return is_high_sst def test_bt_amsr2_regression(): @@ -29,11 +144,22 @@ def test_bt_amsr2_regression(): good. These fields may need to be updated as we make tweaks to the algorithm. """ + resolution: Final = "25" + hemisphere: Final = "north" + + land_mask = _get_ps_land_mask(hemisphere=hemisphere, resolution=resolution) for date in (dt.date(2020, 1, 1), dt.date(2022, 5, 4)): + invalid_ice_mask = _get_ps_invalid_ice_mask( + hemisphere=hemisphere, + date=date, + resolution=resolution, + ) actual_ds = amsr2_goddard_bootstrap( date=date, - hemisphere="north", - resolution="25", + hemisphere=hemisphere, + resolution=resolution, + land_mask=land_mask, + invalid_ice_mask=invalid_ice_mask, ) filename = f"NH_{date:%Y%m%d}_py_NRT_amsr2.nc" @@ -68,14 +194,14 @@ def _original_f18_example() -> xr.Dataset: resolution: AU_SI_RESOLUTIONS = "25" date = dt.date(2018, 2, 17) hemisphere: Hemisphere = "north" + + land_mask = _get_ps_land_mask(hemisphere=hemisphere, resolution=resolution) + invalid_ice_mask = _get_ps_invalid_ice_mask( + hemisphere=hemisphere, + date=date, + resolution=resolution, + ) params = BootstrapParams( - land_mask=get_ps_land_mask(hemisphere=hemisphere, resolution=resolution), - pole_mask=get_ps_pole_hole_mask(resolution=resolution), - invalid_ice_mask=get_ps_invalid_ice_mask( - hemisphere=hemisphere, - date=date, - resolution=resolution, - ), **SSMIS_NORTH_PARAMS, # type: ignore[arg-type] ) @@ -109,6 +235,8 @@ def _read_tb_field(tbfn: Path) -> NDArray[np.float32]: ), params=params, date=date, + land_mask=land_mask, + invalid_ice_mask=invalid_ice_mask, ) return conc_ds diff --git a/pm_icecon/tests/regression/test_nt.py b/pm_icecon/tests/regression/test_nt.py index 9f68ca0d..7f6120a9 100644 --- a/pm_icecon/tests/regression/test_nt.py +++ b/pm_icecon/tests/regression/test_nt.py @@ -2,14 +2,14 @@ from typing import get_args import numpy as np +import numpy.typing as npt import xarray as xr from numpy.testing import assert_almost_equal from pm_tb_data._types import Hemisphere -from pm_icecon.constants import CDR_TESTDATA_DIR +from pm_icecon.tests.regression import CDR_TESTDATA_DIR from pm_icecon.interpolation import spatial_interp_tbs from pm_icecon.nt.compute_nt_ic import goddard_nasateam -from pm_icecon.nt.masks import get_ps25_sst_mask from pm_icecon.nt.params.goddard_rss import ( RSS_F17_NORTH_GRADIENT_THRESHOLDS, RSS_F17_SOUTH_GRADIENT_THRESHOLDS, @@ -18,6 +18,38 @@ from pm_icecon.util import get_ps25_grid_shape +def _get_ps25_sst_mask( + *, + hemisphere: Hemisphere, + date: dt.date, + sst_threshold=2780, +) -> npt.NDArray[np.bool_]: + """Read and return the ps25 SST mask. + + `True` elements are those which are masked as invalid ice. + """ + # TODO: why are the northern hemisphere files 'fixed' while the southern + # hemisphere are not (except in one case)? + month_abbr = f"{date:%b}".lower() + if hemisphere == "north": + sst_fn = f"{month_abbr}.temp.zdf.ssmi_fixed_25fill.fixed" + else: + sst_fn = f"{month_abbr}.temp.zdf.ssmi_25fill" + + sst_path = ( + CDR_TESTDATA_DIR + / f"nt_datafiles/data36/SST/{hemisphere.capitalize()}/" + / sst_fn + ) + sst_field = np.fromfile(sst_path, dtype=">i2")[150:].reshape( + get_ps25_grid_shape(hemisphere=hemisphere) + ) + + where_sst_high = sst_field >= sst_threshold + + return where_sst_high + + def _original_example(*, hemisphere: Hemisphere) -> xr.Dataset: """Return the concentration field example for f17_20180101.""" _nt_maps_dir = CDR_TESTDATA_DIR / "nt_datafiles/data36/maps/" @@ -67,7 +99,7 @@ def _get_minic(*, hemisphere: Hemisphere): ).reshape(grid_shape) ) - invalid_ice_mask = get_ps25_sst_mask(hemisphere=hemisphere, date=date) + invalid_ice_mask = _get_ps25_sst_mask(hemisphere=hemisphere, date=date) conc_ds = goddard_nasateam( tb_v19=tbs["v19"], diff --git a/pyproject.toml b/pyproject.toml index 36cfc65e..65d648d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pm_icecon" -version = "0.2.0" +version = "0.3.0" description = "Sea ice concentration estimates from passive microwave data" [tool.setuptools] @@ -30,7 +30,7 @@ max-complexity = 8 inline-quotes = "double" [tool.bumpversion] -current_version = "0.2.0" +current_version = "0.3.0" commit = false tag = false diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 3e039027..bd21125c 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -1,6 +1,6 @@ package: name: pm_icecon - version: "0.2.0" + version: "0.3.0" source: path: ../ diff --git a/scripts/cli.sh b/scripts/cli.sh deleted file mode 100755 index ebaab77d..00000000 --- a/scripts/cli.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -ARGS=$@ - -THIS_DIR="$( cd "$(dirname "$0")"; pwd -P )" -PYTHONPATH=$THIS_DIR/.. python -m pm_icecon.cli.entrypoint $ARGS