diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml deleted file mode 100644 index b31d4a0..0000000 --- a/.JuliaFormatter.toml +++ /dev/null @@ -1,3 +0,0 @@ -indent = 4 -margin = 92 -normalize_line_endings = "unix" diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a525f03..8c1edee 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -19,12 +19,13 @@ SolarPosition.jl provides a simple, unified interface to a collection of validat ### General Style -1. **Indentation**: Use 4 spaces (configured in `.JuliaFormatter.toml`) -2. **Line length**: Maximum 92 characters (configured in `.JuliaFormatter.toml`) +1. **Indentation**: Use 4 spaces +2. **Line length**: Maximum 92 characters (soft limit, not enforced) 3. **Line endings**: Unix-style LF only -4. **Formatting**: Code is automatically formatted with JuliaFormatter - - Run manually: `julia -e 'using JuliaFormatter; format(".")'` +4. **Formatting**: Code is automatically formatted with Runic + - Run manually: `julia -m Runic --inplace .` (requires Runic to be installed) - Pre-commit hooks ensure formatting before commits + - Note: Runic has no configuration - formatting rules are set in stone ### Documentation @@ -115,7 +116,7 @@ pip install pre-commit pre-commit run --all-files # Individual tools: -# - JuliaFormatter: Code formatting +# - Runic: Code formatting # - ExplicitImports: Check for explicit imports # - markdownlint: Markdown linting # - yamllint: YAML linting @@ -172,8 +173,8 @@ The project uses GitHub Actions workflows: ## Useful Commands ```bash -# Format code -julia -e 'using Pkg; pkg"add JuliaFormatter"; using JuliaFormatter; format(".")' +# Format code (requires Runic to be installed: julia --project=@runic -e 'using Pkg; Pkg.add("Runic")') +julia --project=@runic --startup-file=no -m Runic --inplace . # Run tests julia --project=. -e 'using Pkg; Pkg.test()' @@ -192,6 +193,6 @@ See [docs/src/contributing.md](../docs/src/contributing.md) for detailed contrib ## References -- [JuliaFormatter documentation](https://domluna.github.io/JuliaFormatter.jl/stable/) +- [Runic documentation](https://github.com/fredrikekre/Runic.jl) - [DocStringExtensions documentation](https://juliadocs.org/DocStringExtensions.jl/stable/) - [Julia Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/) diff --git a/.github/workflows/Copier.yml b/.github/workflows/Copier.yml index cf27080..d1e70b1 100644 --- a/.github/workflows/Copier.yml +++ b/.github/workflows/Copier.yml @@ -17,8 +17,6 @@ jobs: version: "1" - name: Use Julia cache uses: julia-actions/cache@v2 - - name: Install JuliaFormatter.jl - run: julia -e 'using Pkg; pkg"add JuliaFormatter"' - name: Hack for setup-python cache # https://github.com/actions/setup-python/issues/807 run: touch requirements.txt - name: Setup Python diff --git a/.github/workflows/Lint.yml b/.github/workflows/Lint.yml index 73c97ec..bdc3e60 100644 --- a/.github/workflows/Lint.yml +++ b/.github/workflows/Lint.yml @@ -30,7 +30,7 @@ jobs: - name: Build package (required for ExplicitImports) uses: julia-actions/julia-buildpkg@v1 - name: Install Julia packages - run: julia -e 'using Pkg; pkg"add ExplicitImports, JuliaFormatter"' + run: julia -e 'using Pkg; pkg"add ExplicitImports"' - name: Hack for setup-python cache # https://github.com/actions/setup-python/issues/807 run: touch requirements.txt - name: Setup Python diff --git a/.gitignore b/.gitignore index 3f34835..e4af5c3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ node_modules play/Project.toml docs/.CondaPkg/meta *.mem +**/Manifest-*.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cefdb0e..5b6470d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,9 +13,6 @@ repos: - id: check-json - id: check-toml - id: check-yaml - - id: file-contents-sorter - files: .JuliaFormatter.toml - args: [--unique] - id: mixed-line-ending args: [--fix=lf] - id: no-commit-to-branch @@ -47,10 +44,10 @@ repos: - id: explicit-imports name: ExplicitImports checks args: [--print, --checklist, exclude_all_qualified_accesses_are_public] - - repo: https://github.com/domluna/JuliaFormatter.jl - rev: v2.2.1 + - repo: https://github.com/fredrikekre/runic-pre-commit + rev: v2.0.1 hooks: - - id: julia-formatter + - id: runic - repo: https://github.com/crate-ci/typos rev: v1 hooks: diff --git a/benchmark/.CondaPkg/meta b/benchmark/.CondaPkg/meta index 58dfb19..55f68b0 100644 Binary files a/benchmark/.CondaPkg/meta and b/benchmark/.CondaPkg/meta differ diff --git a/benchmark/.CondaPkg/pixi.lock b/benchmark/.CondaPkg/pixi.lock index a2d2560..0723ba7 100644 --- a/benchmark/.CondaPkg/pixi.lock +++ b/benchmark/.CondaPkg/pixi.lock @@ -7,34 +7,71 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py313h843e2db_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/copier-9.11.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py313heb322e3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/dunamai-1.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/eval-type-backport-0.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/eval_type_backport-0.2.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/funcy-2.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-ansible-filters-1.3.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/paramiko-4.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/plumbum-1.10.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.51-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py313h843e2db_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.6.2-py313h07c4f96_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.10-hc97d973_100_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pywin32-on-windows-0.1.0-pyh1179c8e_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/questionary-2.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 md5: d7c89558ba9fa0495403155b64376d81 - arch: x86_64 - platform: linux license: None size: 2562 timestamp: 1578324546067 @@ -47,20 +84,42 @@ packages: - libgomp >=7.5.0 constrains: - openmp_impl 9999 - arch: x86_64 - platform: linux license: BSD-3-Clause license_family: BSD size: 23621 timestamp: 1650670423406 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda + sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 + md5: 2934f256a8acfe48f6ebb4fce6cde29c + depends: + - python >=3.9 + - typing-extensions >=4.0.0 + license: MIT + license_family: MIT + size: 18074 + timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py313h843e2db_1.conda + sha256: cdf7496797af275f8bb5edd270aa06303dde623c7dd3a5941b0ce085d8f4cdc5 + md5: b59ec3796cba93d0db5f71e361176f27 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.13.* *_cp313 + constrains: + - __glibc >=2.17 + arch: x86_64 + platform: linux + license: Apache-2.0 + license_family: APACHE + size: 292710 + timestamp: 1762497710166 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 md5: 51a19bba1b8ebfb60df25cde030b7ebc depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - arch: x86_64 - platform: linux license: bzip2-1.0.6 license_family: BSD size: 260341 @@ -73,6 +132,158 @@ packages: license: ISC size: 152432 timestamp: 1762967197890 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda + sha256: 2162a91819945c826c6ef5efe379e88b1df0fe9a387eeba23ddcf7ebeacd5bd6 + md5: d0616e7935acab407d1543b28c446f6f + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 298357 + timestamp: 1761202966461 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/copier-9.11.3-pyhcf101f3_0.conda + sha256: 0760286714848e8af7aade73da886e9f5cfe4126e6d10501f10135e50e94c2c0 + md5: fed521ea8b179bf63e9986b3108ed5f3 + depends: + - python >=3.10 + - colorama >=0.4.6 + - dunamai >=1.7.0 + - funcy >=1.17 + - jinja2 >=3.1.5 + - jinja2-ansible-filters >=1.3.1 + - packaging >=23.0 + - pathspec >=0.9.0 + - plumbum >=1.6.9 + - prompt-toolkit <3.0.52 + - pydantic >=2.4.2 + - pygments >=2.7.1 + - pyyaml >=5.3.1 + - questionary >=1.8.1 + - eval-type-backport >=0.1.3,<0.3.0 + - platformdirs >=4.3.6 + - typing_extensions >=4.0.0,<5.0.0 + - python + license: MIT + license_family: MIT + size: 54229 + timestamp: 1769272985745 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py313heb322e3_1.conda + sha256: beb4f2fa46bf3d550bf5bf2a07796be14cbe73ceebe43b28e634ee778b547e99 + md5: 4e6278c519f2766ea707361f81b33364 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.14 + - libgcc >=14 + - openssl >=3.5.4,<4.0a0 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + constrains: + - __glibc >=2.17 + arch: x86_64 + platform: linux + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + size: 1723198 + timestamp: 1764805305302 +- conda: https://conda.anaconda.org/conda-forge/noarch/dunamai-1.25.0-pyhd8ed1ab_0.conda + sha256: 16d78408ed520b0951425cdfae280392813794e29ea6d3cb95f6c479347c4e1c + md5: 4b6cc280feef9e74ffe9ea1c875b5f8c + depends: + - packaging >=20.9 + - python >=3.9 + license: MIT + license_family: MIT + size: 30075 + timestamp: 1751991836363 +- conda: https://conda.anaconda.org/conda-forge/noarch/eval-type-backport-0.2.2-pyhd8ed1ab_0.conda + sha256: 05ffdcb83903c159bfbb78a07fbcce6fd6dda41df9c55ed75e0eb1db5528048f + md5: 879479fda1dddb002fdc4885cea33740 + depends: + - eval_type_backport >=0.2.2,<0.2.3.0a0 + - python >=3.9 + license: MIT + license_family: MIT + size: 6662 + timestamp: 1734857849281 +- conda: https://conda.anaconda.org/conda-forge/noarch/eval_type_backport-0.2.2-pyha770c72_0.conda + sha256: 2d721421a60676216e10837a240c75e2190e093920a4016a469fa9a62c95ab5f + md5: 8681d7f876da5e66a1c7fce424509383 + depends: + - python >=3.9 + constrains: + - eval-type-backport >=0.2.2,<0.2.3.0a0 + license: MIT + license_family: MIT + size: 11520 + timestamp: 1734857840035 +- conda: https://conda.anaconda.org/conda-forge/noarch/funcy-2.0-pyhd8ed1ab_1.conda + sha256: 4a3e3e86b7b49aaa2a0faa57da2bcf39f7ee858499e8335132f83bfeed79191e + md5: 84f8955e99a8944fdee49da39edb0add + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + size: 30249 + timestamp: 1734381235500 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + sha256: acc1d991837c0afb67c75b77fdc72b4bf022aac71fedd8b9ea45918ac9b08a80 + md5: c85c76dc67d75619a92f51dfbce06992 + depends: + - python >=3.9 + - zipp >=3.1.0 + constrains: + - importlib-resources >=6.5.2,<6.5.3.0a0 + license: Apache-2.0 + license_family: APACHE + size: 33781 + timestamp: 1736252433366 +- conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda + sha256: 5a4e3a01f626c8de15ddada622d364e94ff28e8d6bdedf1665442ef03a4e0140 + md5: 3a804714ed59be1969ffca10f703ec2a + depends: + - python >=3.10 + license: BSD-2-Clause + license_family: BSD + size: 132825 + timestamp: 1760146119847 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b + md5: 04558c96691bed63104678757beb4f8d + depends: + - markupsafe >=2.0 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + size: 120685 + timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-ansible-filters-1.3.2-pyhd8ed1ab_1.conda + sha256: a36789229ca9ce5315265b9d425abce9acb4691f5864aea69e935020545a9acb + md5: 974c5b3e353f031cfcf2365c9d375926 + depends: + - jinja2 + - python >=3.9 + - pyyaml + license: BSD-2-Clause + license_family: BSD + size: 20315 + timestamp: 1734906203051 - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda sha256: 9e191baf2426a19507f1d0a17be0fdb7aa155cdf0f61d5a09c808e0a69464312 md5: a6abd2796fc332536735f68ba23f7901 @@ -81,8 +292,6 @@ packages: - zstd >=1.5.7,<1.6.0a0 constrains: - binutils_impl_linux-64 2.45 - arch: x86_64 - platform: linux license: GPL-3.0-only license_family: GPL size: 725545 @@ -95,8 +304,6 @@ packages: - libgcc >=14 constrains: - expat 2.7.3.* - arch: x86_64 - platform: linux license: MIT license_family: MIT size: 76643 @@ -107,8 +314,6 @@ packages: depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - arch: x86_64 - platform: linux license: MIT license_family: MIT size: 57821 @@ -122,19 +327,26 @@ packages: constrains: - libgomp 15.1.0 h767d61c_5 - libgcc-ng ==15.1.0=*_5 - arch: x86_64 - platform: linux license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL size: 824191 timestamp: 1757042543820 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_5.conda + sha256: f54bb9c3be12b24be327f4c1afccc2969712e0b091cdfbd1d763fb3e61cda03f + md5: 069afdf8ea72504e48d23ae1171d951c + depends: + - libgcc 15.1.0 h767d61c_5 + arch: x86_64 + platform: linux + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 29187 + timestamp: 1757042549554 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_5.conda sha256: 125051d51a8c04694d0830f6343af78b556dd88cc249dfec5a97703ebfb1832d md5: dcd5ff1940cd38f6df777cac86819d60 depends: - __glibc >=2.17,<3.0.a0 - arch: x86_64 - platform: linux license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL size: 447215 @@ -147,8 +359,6 @@ packages: - libgcc >=13 constrains: - xz 5.8.1.* - arch: x86_64 - platform: linux license: 0BSD size: 112894 timestamp: 1749230047870 @@ -158,12 +368,20 @@ packages: depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - arch: x86_64 - platform: linux license: BSD-2-Clause license_family: BSD size: 91183 timestamp: 1748393666725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda + sha256: 0105bd108f19ea8e6a78d2d994a6d4a8db16d19a41212070d2d1d48a63c34161 + md5: a587892d3c13b6621a6091be690dbca2 + depends: + - libgcc-ng >=12 + arch: x86_64 + platform: linux + license: ISC + size: 205978 + timestamp: 1716828628198 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda sha256: 6f0e8a812e8e33a4d8b7a0e595efe28373080d27b78ee4828aa4f6649a088454 md5: 2e1b84d273b01835256e53fd938de355 @@ -171,8 +389,6 @@ packages: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 - arch: x86_64 - platform: linux license: blessing size: 938979 timestamp: 1764359444435 @@ -182,8 +398,6 @@ packages: depends: - __glibc >=2.17,<3.0.a0 - libgcc 15.1.0 h767d61c_5 - arch: x86_64 - platform: linux license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL size: 3896432 @@ -193,8 +407,6 @@ packages: md5: 8bba50c7f4679f08c861b597ad2bda6b depends: - libstdcxx 15.1.0 h8f9b012_5 - arch: x86_64 - platform: linux license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL size: 29233 @@ -205,8 +417,6 @@ packages: depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - arch: x86_64 - platform: linux license: BSD-3-Clause size: 40235 timestamp: 1764790744114 @@ -218,20 +428,32 @@ packages: - libgcc >=13 constrains: - zlib 1.3.1 *_2 - arch: x86_64 - platform: linux license: Zlib license_family: Other size: 60963 timestamp: 1727963148474 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda + sha256: a530a411bdaaf0b1e4de8869dfaca46cb07407bc7dc0702a9e231b0e5ce7ca85 + md5: c14389156310b8ed3520d84f854be1ee + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + constrains: + - jinja2 >=3.0.0 + arch: x86_64 + platform: linux + license: BSD-3-Clause + license_family: BSD + size: 25909 + timestamp: 1759055357045 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 md5: 47e340acb35de30501a76c7c799c41d7 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=13 - arch: x86_64 - platform: linux license: X11 AND BSD-3-Clause size: 891641 timestamp: 1738195959188 @@ -242,12 +464,154 @@ packages: - __glibc >=2.17,<3.0.a0 - ca-certificates - libgcc >=14 - arch: x86_64 - platform: linux license: Apache-2.0 license_family: Apache size: 3119624 timestamp: 1759324353651 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 + md5: b76541e68fea4d511b1ac46a28dcd2c6 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + size: 72010 + timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/noarch/paramiko-4.0.0-pyhd8ed1ab_0.conda + sha256: ce76d5a1fc6c7ef636cbdbf14ce2d601a1bfa0dd8d286507c1fd02546fccb94b + md5: 1a884d2b1ea21abfb73911dcdb8342e4 + depends: + - bcrypt >=3.2 + - cryptography >=3.3 + - invoke >=2.0 + - pynacl >=1.5 + - python >=3.9 + license: LGPL-2.1-or-later + license_family: LGPL + size: 159896 + timestamp: 1755102147074 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + sha256: 29ea20d0faf20374fcd61c25f6d32fb8e9a2c786a7f1473a0c3ead359470fbe1 + md5: 2908273ac396d2cd210a8127f5f1c0d6 + depends: + - python >=3.10 + license: MPL-2.0 + license_family: MOZILLA + size: 53739 + timestamp: 1769677743677 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda + sha256: 04c64fb78c520e5c396b6e07bc9082735a5cc28175dbe23138201d0a9441800b + md5: 1bd2e65c8c7ef24f4639ae6e850dacc2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 23922 + timestamp: 1764950726246 +- conda: https://conda.anaconda.org/conda-forge/noarch/plumbum-1.10.0-pyhcf101f3_0.conda + sha256: 972e0c1c9f0b1763d482e885732baef7f9a0cbe8686f5e2c6bdd88838619a59a + md5: 7fd2e38f4e608f5ebd80f871352c5495 + depends: + - python >=3.10 + - pywin32-on-windows + - paramiko + - importlib_resources + - python + license: MIT + license_family: MIT + size: 103911 + timestamp: 1761911487086 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + sha256: ebc1bb62ac612af6d40667da266ff723662394c0ca78935340a5b5c14831227b + md5: d17ae9db4dc594267181bd199bf9a551 + depends: + - python >=3.9 + - wcwidth + constrains: + - prompt_toolkit 3.0.51 + license: BSD-3-Clause + license_family: BSD + size: 271841 + timestamp: 1744724188108 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.51-hd8ed1ab_0.conda + sha256: 936189f0373836c1c77cd2d6e71ba1e583e2d3920bf6d015e96ee2d729b5e543 + md5: 1e61ab85dd7c60e5e73d853ea035dc29 + depends: + - prompt-toolkit >=3.0.51,<3.0.52.0a0 + license: BSD-3-Clause + license_family: BSD + size: 7182 + timestamp: 1744724189376 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 + md5: 12c566707c80111f9799308d9e265aef + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + size: 110100 + timestamp: 1733195786147 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda + sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d + md5: c3946ed24acdb28db1b5d63321dbca7d + depends: + - typing-inspection >=0.4.2 + - typing_extensions >=4.14.1 + - python >=3.10 + - typing-extensions >=4.6.1 + - annotated-types >=0.6.0 + - pydantic-core ==2.41.5 + - python + license: MIT + license_family: MIT + size: 340482 + timestamp: 1764434463101 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py313h843e2db_1.conda + sha256: b15568ddc03bd33ea41610e5df951be4e245cd61957cbf8c2cfd12557f3d53b5 + md5: f27c39a1906771bbe56cd26a76bf0b8b + depends: + - python + - typing-extensions >=4.6.0,!=4.7.0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.13.* *_cp313 + constrains: + - __glibc >=2.17 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 1940186 + timestamp: 1762989000579 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a + md5: 6b6ece66ebcae2d5f326c77ef2c5a066 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + size: 889287 + timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.6.2-py313h07c4f96_0.conda + sha256: 28c2b34c8a5542631b47ef48ccfb32fbf19eab5b46cd39ac0bf546af0c337d31 + md5: 69b90b328f1a57bc4bbffcaa990128cf + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.4.1 + - libgcc >=14 + - libsodium >=1.0.20,<1.0.21.0a0 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + - six + arch: x86_64 + platform: linux + license: Apache-2.0 + license_family: Apache + size: 1192806 + timestamp: 1767324184629 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.10-hc97d973_100_cp313.conda build_number: 100 sha256: fbc193c94b72b09b1e5b4ae7d65764b90bb9e6e4d672481d91d8769ab20e909e @@ -270,8 +634,6 @@ packages: - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata - arch: x86_64 - platform: linux license: Python-2.0 size: 37104697 timestamp: 1764755723771 @@ -286,18 +648,61 @@ packages: license_family: BSD size: 7002 timestamp: 1752805902938 +- conda: https://conda.anaconda.org/conda-forge/noarch/pywin32-on-windows-0.1.0-pyh1179c8e_3.tar.bz2 + sha256: 6502696aaef571913b22a808b15c185bd8ea4aabb952685deb29e6a6765761cb + md5: 2807a0becd1d986fe1ef9b7f8135f215 + depends: + - __unix + - python >=2.7 + license: BSD-3-Clause + license_family: BSD + size: 4856 + timestamp: 1646866525560 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_1.conda + sha256: ef7df29b38ef04ec67a8888a4aa039973eaa377e8c4b59a7be0a1c50cd7e4ac6 + md5: f256753e840c3cd3766488c9437a8f8b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + - yaml >=0.2.5,<0.3.0a0 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 201616 + timestamp: 1770223543730 +- conda: https://conda.anaconda.org/conda-forge/noarch/questionary-2.1.1-pyhd8ed1ab_0.conda + sha256: 0604c6dff3af5f53e34fceb985395d08287137f220450108a795bcd1959caf14 + md5: 34fa231b5c5927684b03bb296bb94ddc + depends: + - prompt_toolkit >=2.0,<4.0 + - python >=3.10 + license: MIT + license_family: MIT + size: 31257 + timestamp: 1757356458097 - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda sha256: 2d6d0c026902561ed77cd646b5021aef2d4db22e57a5b0178dfc669231e06d2c md5: 283b96675859b20a825f8fa30f311446 depends: - libgcc >=13 - ncurses >=6.5,<7.0a0 - arch: x86_64 - platform: linux license: GPL-3.0-only license_family: GPL size: 282480 timestamp: 1740379431762 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + size: 18455 + timestamp: 1753199211006 - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64 md5: 86bc20552bf46075e3d92b67f089172d @@ -307,26 +712,82 @@ packages: - libzlib >=1.3.1,<2.0a0 constrains: - xorg-libx11 >=1.8.12,<2.0a0 - arch: x86_64 - platform: linux license: TCL license_family: BSD size: 3284905 timestamp: 1763054914403 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c + md5: edd329d7d3a4ab45dcf905899a7a6115 + depends: + - typing_extensions ==4.15.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + size: 91383 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda + sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 + md5: a0a4a3035667fc34f29bfbd5c190baa6 + depends: + - python >=3.10 + - typing_extensions >=4.12.0 + license: MIT + license_family: MIT + size: 18923 + timestamp: 1764158430324 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + size: 51692 + timestamp: 1756220668932 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda sha256: 5aaa366385d716557e365f0a4e9c3fca43ba196872abbbe3d56bb610d131e192 md5: 4222072737ccff51314b5ece9c7d6f5a license: LicenseRef-Public-Domain size: 122968 timestamp: 1742727099393 +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.5.3-pyhd8ed1ab_0.conda + sha256: 2395599ec9e37e6f21838bb26e7f2336fa03a4b1460ba10897ec856b21ac7d59 + md5: 36432484e9ce3b073a51bf138767a593 + depends: + - python >=3.10 + license: MIT + license_family: MIT + size: 70539 + timestamp: 1769858722627 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad + md5: a77f85f77be52ff59391544bfe73390a + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 85189 + timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae + md5: 30cd29cb87d819caead4d55184c1d115 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 24194 + timestamp: 1764460141901 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 depends: - __glibc >=2.17,<3.0.a0 - libzlib >=1.3.1,<2.0a0 - arch: x86_64 - platform: linux license: BSD-3-Clause size: 601375 timestamp: 1764777111296 diff --git a/benchmark/.CondaPkg/pixi.toml b/benchmark/.CondaPkg/pixi.toml index 2b3f67a..6aa29ae 100644 --- a/benchmark/.CondaPkg/pixi.toml +++ b/benchmark/.CondaPkg/pixi.toml @@ -2,11 +2,12 @@ openssl = ">=3, <3.6" libstdcxx = ">=3.4,<=15.1" libstdcxx-ng = ">=3.4,<=15.1" +copier = "*" [dependencies.python] channel = "conda-forge" build = "*cp*" - version = ">=3.10,<3.14" + version = ">=3.10,!=3.14.0,!=3.14.1,<4" [project] name = ".CondaPkg" diff --git a/benchmark/algorithms.jl b/benchmark/algorithms.jl index 09b30f1..6471a1f 100644 --- a/benchmark/algorithms.jl +++ b/benchmark/algorithms.jl @@ -1,4 +1,3 @@ - # ============================================================================ # Single Position Benchmarks # ============================================================================ diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index 11f3844..cfa89ca 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -34,7 +34,7 @@ const TEST_DT = DateTime(2024, 6, 21, 12, 0, 0) # Generate test time vectors of different sizes function generate_times(n::Int) - return collect(DateTime(2024, 1, 1):Hour(1):(DateTime(2024, 1, 1)+Hour(n-1))) + return collect(DateTime(2024, 1, 1):Hour(1):(DateTime(2024, 1, 1) + Hour(n - 1))) end # Available algorithms to benchmark diff --git a/benchmark/python.jl b/benchmark/python.jl index 4f19bf4..0710ff1 100644 --- a/benchmark/python.jl +++ b/benchmark/python.jl @@ -18,7 +18,7 @@ pd = pyimport("pandas") # Create pandas DatetimeIndex for Python benchmarks (same timestamps as Julia) function create_pandas_times(n::Int) - pd.date_range(start = "2024-01-01 00:00:00", periods = n, freq = "h", tz = "UTC") + return pd.date_range(start = "2024-01-01 00:00:00", periods = n, freq = "h", tz = "UTC") end # Map algorithm names to solposx functions diff --git a/docs/make.jl b/docs/make.jl index 0850fad..a848d20 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -6,10 +6,12 @@ using DocumenterCitations DocMeta.setdocmeta!( SolarPosition, :DocTestSetup, - :(using SolarPosition; - using Dates; - obs = Observer(37.7749, -122.4194, 100.0); - dt = DateTime(2023, 6, 21, 12, 0, 0)); + :( + using SolarPosition; + using Dates; + obs = Observer(37.7749, -122.4194, 100.0); + dt = DateTime(2023, 6, 21, 12, 0, 0) + ); recursive = true, ) @@ -19,7 +21,7 @@ bib = CitationBibliography(joinpath(@__DIR__, "src", "refs.bib"), style = :alpha page_rename = Dict("developer.md" => "Developer docs") # Without the numbers numbered_pages = [ file for file in readdir(joinpath(@__DIR__, "src")) if - file != "index.md" && splitext(file)[2] == ".md" + file != "index.md" && splitext(file)[2] == ".md" ] makedocs(; diff --git a/docs/src/guides/new-algorithm.md b/docs/src/guides/new-algorithm.md index a4f2965..198d4c1 100644 --- a/docs/src/guides/new-algorithm.md +++ b/docs/src/guides/new-algorithm.md @@ -261,7 +261,7 @@ pre-commit run Pre-commit runs several checks including: -- **JuliaFormatter** - Ensures consistent code formatting +- **Runic** - Ensures consistent code formatting - **ExplicitImports** - Checks for explicit imports - **markdownlint** - Lints markdown files - **typos** - Catches common spelling mistakes diff --git a/examples/profiling.jl b/examples/profiling.jl index 4a9200a..a6ea204 100644 --- a/examples/profiling.jl +++ b/examples/profiling.jl @@ -17,6 +17,6 @@ times = collect(DateTime(2023):Minute(1):DateTime(2024)) solar_position(obs, times, PSA()) # profile the PSA algorithm with multiple iterations for better sampling -@profview for _ = 1:1000 +@profview for _ in 1:1000 solar_position(obs, times, PSA()) end diff --git a/ext/SolarPositionMakieExt.jl b/ext/SolarPositionMakieExt.jl index b06e4d6..8570f6a 100644 --- a/ext/SolarPositionMakieExt.jl +++ b/ext/SolarPositionMakieExt.jl @@ -64,7 +64,7 @@ function _add_hour_labels!(ax, observer, year, hours, coords; algorithm = PSA()) # For each hour, find the day when the sun reaches maximum elevation at that hour for hour in hours # Sample a few days throughout the year to find max elevation - dates = [Date(year, m, 15) for m = 1:12] + dates = [Date(year, m, 15) for m in 1:12] max_el = -90.0 best_pos = nothing @@ -100,6 +100,7 @@ function _add_hour_labels!(ax, observer, year, hours, coords; algorithm = PSA()) ) end end + return end """ @@ -113,7 +114,7 @@ function _configure_axis!(ax::Axis) ax.xlabel = "Azimuth (°)" ax.ylabel = "Elevation (°)" ax.xticks = 0:30:360 - ax.yticks = 0:10:90 + return ax.yticks = 0:10:90 end """ @@ -124,7 +125,7 @@ Configure polar axis for analemma plot. function _configure_axis!(ax::PolarAxis) ax.direction = -1 ax.theta_0 = -π / 2 - ax.rlimits = (0, 90) + return ax.rlimits = (0, 90) end """ @@ -191,7 +192,7 @@ end Theme(colorscheme = :twilight, markersize = 3, hour_labels = true) end -function Makie.plot!(sp::Analemmas{<:Tuple{Observer,Int}}) +function Makie.plot!(sp::Analemmas{<:Tuple{Observer, Int}}) observer = sp[1][] year = sp[2][] diff --git a/ext/SolarPositionModelingToolkitExt.jl b/ext/SolarPositionModelingToolkitExt.jl index e481d6d..8b4e959 100644 --- a/ext/SolarPositionModelingToolkitExt.jl +++ b/ext/SolarPositionModelingToolkitExt.jl @@ -11,7 +11,7 @@ import Symbolics import SolarPosition: SolarPositionBlock, solar_position -seconds_to_datetime(t_sec, t0::DateTime) = t0 + Millisecond(round(Int, t_sec * 1e3)) +seconds_to_datetime(t_sec, t0::DateTime) = t0 + Millisecond(round(Int, t_sec * 1.0e3)) # helper functions to extract fields from solar position get_azimuth(pos) = pos.azimuth @@ -37,12 +37,12 @@ Symbolics.@register_symbolic get_elevation(pos)::Real Symbolics.@register_symbolic get_zenith(pos)::Real function SolarPositionBlock(; - name, - t0 = Dates.now(), - observer::Observer{T} = Observer(0.0, 0.0, 0.0), - algorithm = PSA(), - refraction = NoRefraction(), -) where {T<:AbstractFloat} + name, + t0 = Dates.now(), + observer::Observer{T} = Observer(0.0, 0.0, 0.0), + algorithm = PSA(), + refraction = NoRefraction(), + ) where {T <: AbstractFloat} @parameters t0::DateTime = t0 [tunable = false] @parameters observer::Observer{T} = observer [tunable = false] @parameters algorithm::SolarAlgorithm = algorithm [tunable = false] diff --git a/ext/SolarPositionOhMyThreadsExt.jl b/ext/SolarPositionOhMyThreadsExt.jl index 92b678d..98a8352 100644 --- a/ext/SolarPositionOhMyThreadsExt.jl +++ b/ext/SolarPositionOhMyThreadsExt.jl @@ -51,13 +51,13 @@ solar_position!(pos, obs, times, PSA(), NoRefraction(), StaticScheduler()) See also: [`solar_position`](@ref), [`OhMyThreads.Scheduler`] """ function SolarPosition.solar_position!( - pos::StructArrays.StructVector{T}, - obs::Observer, - dts::AbstractVector{Z}, - alg::SolarAlgorithm, - refraction::RefractionAlgorithm, - executor::OhMyThreads.Scheduler, -) where {T<:AbstractSolPos,Z<:Union{DateTime,ZonedDateTime}} + pos::StructArrays.StructVector{T}, + obs::Observer, + dts::AbstractVector{Z}, + alg::SolarAlgorithm, + refraction::RefractionAlgorithm, + executor::OhMyThreads.Scheduler, + ) where {T <: AbstractSolPos, Z <: Union{DateTime, ZonedDateTime}} f = dt -> SolarPosition.solar_position(obs, dt, alg, refraction) tmap!(f, pos, dts; scheduler = executor) return pos @@ -103,22 +103,22 @@ positions = solar_position(obs, times, PSA(), NoRefraction(), StaticScheduler()) See also: [`solar_position!`](@ref), [`OhMyThreads.Scheduler`] """ function SolarPosition.solar_position( - obs::Observer{T}, - dts::AbstractVector{Z}, - alg::SolarAlgorithm, - refraction::RefractionAlgorithm, - executor::OhMyThreads.Scheduler, -) where {T<:AbstractFloat,Z<:Union{DateTime,ZonedDateTime}} + obs::Observer{T}, + dts::AbstractVector{Z}, + alg::SolarAlgorithm, + refraction::RefractionAlgorithm, + executor::OhMyThreads.Scheduler, + ) where {T <: AbstractFloat, Z <: Union{DateTime, ZonedDateTime}} f = dt -> SolarPosition.solar_position(obs, dt, alg, refraction) results = tmap(f, dts; scheduler = executor) return StructArrays.StructVector(results) end function SolarPosition.solar_position( - obs::Observer{T}, - dts::AbstractVector{Z}, - executor::OhMyThreads.Scheduler, -) where {T<:AbstractFloat,Z<:Union{DateTime,ZonedDateTime}} + obs::Observer{T}, + dts::AbstractVector{Z}, + executor::OhMyThreads.Scheduler, + ) where {T <: AbstractFloat, Z <: Union{DateTime, ZonedDateTime}} return SolarPosition.solar_position( obs, dts, diff --git a/src/Positioning/Positioning.jl b/src/Positioning/Positioning.jl index eaae4bf..1a5f78b 100644 --- a/src/Positioning/Positioning.jl +++ b/src/Positioning/Positioning.jl @@ -45,7 +45,7 @@ defined by inheriting from this abstract type, see for example [`SPAObserver`](@ struct MyObserver <: AbstractObserver{Float64} end ``` """ -abstract type AbstractObserver{T<:AbstractFloat} end +abstract type AbstractObserver{T <: AbstractFloat} end """ $(TYPEDEF) @@ -74,7 +74,7 @@ The `horizon` parameter can be specified as: - A number in degrees (e.g., `0.5667`) - A `degrees=>arcminutes` pair (e.g., `0=>34` for 34 arcminutes = 0.5667°) """ -struct Observer{T<:AbstractFloat} <: AbstractObserver{T} +struct Observer{T <: AbstractFloat} <: AbstractObserver{T} "Geodetic latitude (+N)" latitude::T "Longitude (+E)" @@ -93,27 +93,27 @@ struct Observer{T<:AbstractFloat} <: AbstractObserver{T} cos_lat::T function Observer{T}( - lat::T, - lon::T, - alt::T = zero(T), - horiz::T = zero(T), - ) where {T<:AbstractFloat} + lat::T, + lon::T, + alt::T = zero(T), + horiz::T = zero(T), + ) where {T <: AbstractFloat} lat_rad = deg2rad(lat) lon_rad = deg2rad(lon) (sin_lat, cos_lat) = sincos(lat_rad) - new{T}(lat, lon, alt, horiz, lat_rad, lon_rad, sin_lat, cos_lat) + return new{T}(lat, lon, alt, horiz, lat_rad, lon_rad, sin_lat, cos_lat) end end # helper to convert horizon from different formats to degrees -_horizon_to_degrees(h::Pair{<:Real,<:Real}) = h.first + h.second / 60.0 +_horizon_to_degrees(h::Pair{<:Real, <:Real}) = h.first + h.second / 60.0 _horizon_to_degrees(h::AbstractFloat) = h Observer(lat::T, lon::T; altitude = 0.0, horizon = 0.0) where {T} = Observer{T}(lat, lon, T(altitude), T(_horizon_to_degrees(horizon))) Observer(lat::T, lon::T, alt::T) where {T} = Observer{T}(lat, lon, alt) Observer(lat::T, lon::T, alt::T, horiz::T) where {T} = Observer{T}(lat, lon, alt, horiz) -Observer(lat::T, lon::T, alt::T, horiz::Pair{<:Real,<:Real}) where {T} = +Observer(lat::T, lon::T, alt::T, horiz::Pair{<:Real, <:Real}) where {T} = Observer{T}(lat, lon, alt, T(_horizon_to_degrees(horiz))) Base.show(io::IO, obs::Observer) = print( @@ -135,7 +135,7 @@ observer and time. # Fields $(TYPEDFIELDS) """ -struct SolPos{T} <: AbstractSolPos where {T<:AbstractFloat} +struct SolPos{T} <: AbstractSolPos where {T <: AbstractFloat} "Azimuth (degrees, 0=N, +clockwise, range [-180, 180])" azimuth::T "Elevation (degrees, range [-90, 90])" @@ -153,7 +153,7 @@ Also includes apparent elevation and zenith angles. # Fields $(TYPEDFIELDS) """ -struct ApparentSolPos{T} <: AbstractApparentSolPos where {T<:AbstractFloat} +struct ApparentSolPos{T} <: AbstractApparentSolPos where {T <: AbstractFloat} "Azimuth (degrees, 0=N, +clockwise, range [-180, 180])" azimuth::T "Elevation (degrees, range [-90, 90])" @@ -285,30 +285,30 @@ function _solar_position(obs, dt, alg::SolarAlgorithm, refraction::RefractionAlg end function solar_position( - obs::AbstractObserver{T}, - dt::DateTime, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractFloat} + obs::AbstractObserver{T}, + dt::DateTime, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractFloat} return _solar_position(obs, dt, alg, refraction) end function solar_position( - obs::AbstractObserver{T}, - dt::ZonedDateTime, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractFloat} + obs::AbstractObserver{T}, + dt::ZonedDateTime, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractFloat} return solar_position(obs, DateTime(dt, UTC), alg, refraction) end function solar_position!( - pos::StructArrays.StructVector{T}, - obs::AbstractObserver, - dts::AbstractVector{Union{DateTime,ZonedDateTime}}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractSolPos} + pos::StructArrays.StructVector{T}, + obs::AbstractObserver, + dts::AbstractVector{Union{DateTime, ZonedDateTime}}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractSolPos} @inbounds for i in eachindex(dts, pos) pos[i] = solar_position(obs, dts[i], alg, refraction) end @@ -316,12 +316,12 @@ function solar_position!( end function solar_position!( - pos::StructArrays.StructVector{T}, - obs::AbstractObserver, - dts::AbstractVector{DateTime}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractSolPos} + pos::StructArrays.StructVector{T}, + obs::AbstractObserver, + dts::AbstractVector{DateTime}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractSolPos} @inbounds for i in eachindex(dts, pos) pos[i] = solar_position(obs, dts[i], alg, refraction) end @@ -329,12 +329,12 @@ function solar_position!( end function solar_position!( - pos::StructArrays.StructVector{T}, - obs::AbstractObserver, - dts::AbstractVector{ZonedDateTime}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractSolPos} + pos::StructArrays.StructVector{T}, + obs::AbstractObserver, + dts::AbstractVector{ZonedDateTime}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractSolPos} @inbounds for i in eachindex(dts, pos) pos[i] = solar_position(obs, dts[i], alg, refraction) end @@ -342,11 +342,11 @@ function solar_position!( end function solar_position( - obs::AbstractObserver{T}, - dts::AbstractVector{Union{DateTime,ZonedDateTime}}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractFloat} + obs::AbstractObserver{T}, + dts::AbstractVector{Union{DateTime, ZonedDateTime}}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractFloat} RetType = result_type(typeof(alg), typeof(refraction), T) pos = StructArrays.StructVector{RetType}(undef, length(dts)) solar_position!(pos, obs, dts, alg, refraction) @@ -354,11 +354,11 @@ function solar_position( end function solar_position( - obs::AbstractObserver{T}, - dts::AbstractVector{DateTime}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractFloat} + obs::AbstractObserver{T}, + dts::AbstractVector{DateTime}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractFloat} RetType = result_type(typeof(alg), typeof(refraction), T) pos = StructArrays.StructVector{RetType}(undef, length(dts)) solar_position!(pos, obs, dts, alg, refraction) @@ -366,11 +366,11 @@ function solar_position( end function solar_position( - obs::AbstractObserver{T}, - dts::AbstractVector{ZonedDateTime}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {T<:AbstractFloat} + obs::AbstractObserver{T}, + dts::AbstractVector{ZonedDateTime}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {T <: AbstractFloat} RetType = result_type(typeof(alg), typeof(refraction), T) pos = StructArrays.StructVector{RetType}(undef, length(dts)) solar_position!(pos, obs, dts, alg, refraction) @@ -400,12 +400,12 @@ Compute solar positions for all times in a table and add the results as new colu The input table is modified **in-place** by adding new columns. """ function solar_position!( - table, - obs::AbstractObserver{T}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(); - dt_col::Symbol = :datetime, -) where {T<:AbstractFloat} + table, + obs::AbstractObserver{T}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(); + dt_col::Symbol = :datetime, + ) where {T <: AbstractFloat} tbl = Tables.columntable(table) if !haskey(tbl, dt_col) throw(ArgumentError("Input table must have a $(dt_col) column")) @@ -418,6 +418,7 @@ function solar_position!( for (key, value) in pairs(result) table[!, key] = value end + return end """ @@ -428,12 +429,12 @@ Non-mutating version of [`solar_position!`](@ref) that returns a modified copy o See [`solar_position!`](@ref) for detailed documentation of arguments, examples, and usage patterns. """ function solar_position( - table, - obs::AbstractObserver{T}, - alg::SolarAlgorithm = PSA(), - refraction::RefractionAlgorithm = DefaultRefraction(); - kwargs..., -) where {T<:AbstractFloat} + table, + obs::AbstractObserver{T}, + alg::SolarAlgorithm = PSA(), + refraction::RefractionAlgorithm = DefaultRefraction(); + kwargs..., + ) where {T <: AbstractFloat} table_copy = copy(table) solar_position!(table_copy, obs, alg, refraction; kwargs...) return table_copy diff --git a/src/Positioning/deltat.jl b/src/Positioning/deltat.jl index 4f73b3b..b32ad9a 100644 --- a/src/Positioning/deltat.jl +++ b/src/Positioning/deltat.jl @@ -41,11 +41,13 @@ const DELTAT_TABLE = ( evalpoly(u, p) end, ), - (1600.0, 1700.0, y -> begin - t = y - 1600.0 - # TODO: use `evalpoly`/Horner's scheme instead! - 120.0 - 0.9808 * t - 0.01532 * t^2 + t^3 / 7129.0 - end), + ( + 1600.0, 1700.0, y -> begin + t = y - 1600.0 + # TODO: use `evalpoly`/Horner's scheme instead! + 120.0 - 0.9808 * t - 0.01532 * t^2 + t^3 / 7129.0 + end, + ), ( 1700.0, 1800.0, @@ -82,26 +84,34 @@ const DELTAT_TABLE = ( 7.62 + 0.5737 * t - 0.251754 * t^2 + 0.01680668 * t^3 - 0.0004473624 * t^4 + t^5 / 233174.0 end, ), - (1900.0, 1920.0, y -> begin - t = y - 1900.0 - p = (-2.79, 1.494119, -0.0598939, 0.0061966, -0.000197) - evalpoly(t, p) - end), - (1920.0, 1941.0, y -> begin - t = y - 1920.0 - p = (21.20, 0.84493, -0.076100, 0.0020936) - evalpoly(t, p) - end), - (1941.0, 1961.0, y -> begin - t = y - 1950.0 - # TODO: use `evalpoly`/Horner's scheme instead! - 29.07 + 0.407 * t - t^2 / 233.0 + t^3 / 2547.0 - end), - (1961.0, 1986.0, y -> begin - t = y - 1975.0 - # TODO: use `evalpoly`/Horner's scheme instead! - 45.45 + 1.067 * t - t^2 / 260.0 - t^3 / 718.0 - end), + ( + 1900.0, 1920.0, y -> begin + t = y - 1900.0 + p = (-2.79, 1.494119, -0.0598939, 0.0061966, -0.000197) + evalpoly(t, p) + end, + ), + ( + 1920.0, 1941.0, y -> begin + t = y - 1920.0 + p = (21.2, 0.84493, -0.0761, 0.0020936) + evalpoly(t, p) + end, + ), + ( + 1941.0, 1961.0, y -> begin + t = y - 1950.0 + # TODO: use `evalpoly`/Horner's scheme instead! + 29.07 + 0.407 * t - t^2 / 233.0 + t^3 / 2547.0 + end, + ), + ( + 1961.0, 1986.0, y -> begin + t = y - 1975.0 + # TODO: use `evalpoly`/Horner's scheme instead! + 45.45 + 1.067 * t - t^2 / 260.0 - t^3 / 718.0 + end, + ), ( 1986.0, 2005.0, @@ -111,11 +121,13 @@ const DELTAT_TABLE = ( evalpoly(t, p) end, ), - (2005.0, 2050.0, y -> begin - t = y - 2000.0 - p = (62.92, 0.32217, 0.005589) - evalpoly(t, p) - end), + ( + 2005.0, 2050.0, y -> begin + t = y - 2000.0 + p = (62.92, 0.32217, 0.005589) + evalpoly(t, p) + end, + ), (2050.0, 2150.0, y -> -20.0 + 32.0 * ((y - 1820.0) / 100.0)^2 - 0.5628 * (2150.0 - y)), (2150.0, Inf, y -> -20.0 + 32.0 * ((y - 1820.0) / 100.0)^2), ) @@ -176,7 +188,7 @@ function calculate_deltat(year::Real, month::Real)::Float64 return _deltat_lookup(DELTAT_TABLE, year, y) end -function calculate_deltat(date::Union{DateTime,Date}) +function calculate_deltat(date::Union{DateTime, Date}) y = year(date) m = month(date) d = day(date) diff --git a/src/Positioning/noaa.jl b/src/Positioning/noaa.jl index ed69506..a6fee3a 100644 --- a/src/Positioning/noaa.jl +++ b/src/Positioning/noaa.jl @@ -28,7 +28,7 @@ $(TYPEDFIELDS) """ struct NOAA <: SolarAlgorithm "Difference between terrestrial time and UT1 [seconds]. If `nothing`, uses automatic calculation." - delta_t::Union{Float64,Nothing} + delta_t::Union{Float64, Nothing} end NOAA() = NOAA(67.0) # default delta_t value (2020 default from pvlib) @@ -57,8 +57,8 @@ function _solar_position(obs::Observer{T}, dt::DateTime, alg::NOAA) where {T} # sun equation of center [degrees] sun_eq_ctr = ( sind(mean_anom) * (1.914602 - jc * (0.004817 + 0.000014 * jc)) + - sind(2 * mean_anom) * (0.019993 - 0.000101 * jc) + - sind(3 * mean_anom) * 0.000289 + sind(2 * mean_anom) * (0.019993 - 0.000101 * jc) + + sind(3 * mean_anom) * 0.000289 ) # sun true/apparent longitude [degrees] @@ -78,10 +78,10 @@ function _solar_position(obs::Observer{T}, dt::DateTime, alg::NOAA) where {T} var_y = tand(obliq_corr / 2.0)^2 eot = 4.0 * rad2deg( - var_y * sind(2.0 * mean_long) - 2.0 * eccent * sind(mean_anom) + + var_y * sind(2.0 * mean_long) - 2.0 * eccent * sind(mean_anom) + 4.0 * eccent * var_y * sind(mean_anom) * cosd(2.0 * mean_long) - 0.5 * var_y^2 * sind(4.0 * mean_long) - 1.25 * eccent^2 * sind(2.0 * mean_anom), - ) + ) # true solar time [minutes] hour_frac = fractional_hour(dt) diff --git a/src/Positioning/psa.jl b/src/Positioning/psa.jl index aca92e1..ec1da5e 100644 --- a/src/Positioning/psa.jl +++ b/src/Positioning/psa.jl @@ -34,7 +34,7 @@ PSA() = PSA(2020) 3.338320972e-2, 3.497596876e-4, -1.544353226e-4, - -8.689729360e-6, + -8.68972936e-6, 4.090904909e-1, -6.213605399e-9, 4.418094944e-5, @@ -45,16 +45,16 @@ PSA() = PSA(2020) return ( 2.1429, -0.0010394594, - 4.8950630, + 4.895063, 0.017202791698, - 6.2400600, + 6.24006, 0.0172019699, 0.03341607, 0.00034894, -0.0001134, -0.0000203, 0.4090928, - -6.2140e-09, + -6.214e-9, 0.0000396, 6.6974243242, 0.0657098283, diff --git a/src/Positioning/spa.jl b/src/Positioning/spa.jl index e6f0e56..1ed0f8b 100644 --- a/src/Positioning/spa.jl +++ b/src/Positioning/spa.jl @@ -23,7 +23,7 @@ $(TYPEDFIELDS) """ struct SPA <: SolarAlgorithm "Difference between terrestrial time and UT1 [seconds]. If `nothing`, uses automatic calculation." - delta_t::Union{Float64,Nothing} + delta_t::Union{Float64, Nothing} "Annual average air pressure [Pa]" pressure::Float64 "Annual average air temperature [°C]" @@ -32,22 +32,22 @@ struct SPA <: SolarAlgorithm atmos_refract::Float64 function SPA( - delta_t::Union{Float64,Nothing}, - pressure::Float64, - temperature::Float64, - atmos_refract::Float64, - ) - new(delta_t, pressure, temperature, atmos_refract) + delta_t::Union{Float64, Nothing}, + pressure::Float64, + temperature::Float64, + atmos_refract::Float64, + ) + return new(delta_t, pressure, temperature, atmos_refract) end end # keyword argument constructor with default values function SPA(; - delta_t::Union{Float64,Nothing} = 67.0, - pressure::Float64 = 101325.0, - temperature::Float64 = 12.0, - atmos_refract::Float64 = 0.5667, -) + delta_t::Union{Float64, Nothing} = 67.0, + pressure::Float64 = 101325.0, + temperature::Float64 = 12.0, + atmos_refract::Float64 = 0.5667, + ) return SPA(delta_t, pressure, temperature, atmos_refract) end @@ -65,7 +65,7 @@ multiple times at the same location. # Internal Fields $(TYPEDFIELDS) """ -struct SPAObserver{T<:AbstractFloat} <: AbstractObserver{T} +struct SPAObserver{T <: AbstractFloat} <: AbstractObserver{T} "Geodetic latitude (+N)" latitude::T "Longitude (+E)" @@ -87,7 +87,7 @@ struct SPAObserver{T<:AbstractFloat} <: AbstractObserver{T} "Cached y term for parallax correction" y::T - function SPAObserver{T}(lat::T, lon::T, alt::T = zero(T)) where {T<:AbstractFloat} + function SPAObserver{T}(lat::T, lon::T, alt::T = zero(T)) where {T <: AbstractFloat} lat_rad = deg2rad(lat) lon_rad = deg2rad(lon) (sin_lat, cos_lat) = sincos(lat_rad) @@ -98,13 +98,13 @@ struct SPAObserver{T<:AbstractFloat} <: AbstractObserver{T} x = x_term(sin_u, cos_u, alt, cos_lat) y = y_term(sin_u, cos_u, alt, sin_lat) - new{T}(lat, lon, alt, lat_rad, lon_rad, sin_lat, cos_lat, u, x, y) + return new{T}(lat, lon, alt, lat_rad, lon_rad, sin_lat, cos_lat, u, x, y) end end -SPAObserver(lat::T, lon::T; altitude = 0.0) where {T<:AbstractFloat} = +SPAObserver(lat::T, lon::T; altitude = 0.0) where {T <: AbstractFloat} = SPAObserver{T}(lat, lon, altitude) -SPAObserver(lat::T, lon::T, alt::T) where {T<:AbstractFloat} = SPAObserver{T}(lat, lon, alt) +SPAObserver(lat::T, lon::T, alt::T) where {T <: AbstractFloat} = SPAObserver{T}(lat, lon, alt) # heliocentric longitude coefficients (L0-L5) @@ -125,7 +125,7 @@ end end # calculate sum of A * cos(B + C*x) for coefficient array -@inline function sum_periodic_terms(coeffs::Matrix{T}, x) where {T<:AbstractFloat} +@inline function sum_periodic_terms(coeffs::Matrix{T}, x) where {T <: AbstractFloat} s = zero(T) for i in axes(coeffs, 1) s += coeffs[i, 1] * cos(coeffs[i, 2] + coeffs[i, 3] * x) @@ -141,7 +141,7 @@ function heliocentric_longitude(jme) l4 = sum_periodic_terms(L4, jme) l5 = sum_periodic_terms(L5, jme) - l_rad = evalpoly(jme, (l0, l1, l2, l3, l4, l5)) / 1e8 + l_rad = evalpoly(jme, (l0, l1, l2, l3, l4, l5)) / 1.0e8 return mod(rad2deg(l_rad), 360.0) end @@ -149,7 +149,7 @@ function heliocentric_latitude(jme) b0 = sum_periodic_terms(B0, jme) b1 = sum_periodic_terms(B1, jme) - b_rad = (b0 + b1 * jme) / 1e8 + b_rad = (b0 + b1 * jme) / 1.0e8 return rad2deg(b_rad) end @@ -160,16 +160,16 @@ function heliocentric_radius_vector(jme) r3 = sum_periodic_terms(R3, jme) r4 = sum_periodic_terms(R4, jme) - return evalpoly(jme, (r0, r1, r2, r3, r4)) / 1e8 + return evalpoly(jme, (r0, r1, r2, r3, r4)) / 1.0e8 end # nutation calculations function mean_elongation(jce) - return evalpoly(jce, (297.85036, 445267.111480, -0.0019142, 1.0 / 189474.0)) + return evalpoly(jce, (297.85036, 445267.11148, -0.0019142, 1.0 / 189474.0)) end function mean_anomaly_sun(jce) - return evalpoly(jce, (357.52772, 35999.050340, -0.0001603, -1.0 / 300000.0)) + return evalpoly(jce, (357.52772, 35999.05034, -0.0001603, -1.0 / 300000.0)) end function mean_anomaly_moon(jce) @@ -217,21 +217,21 @@ end function mean_ecliptic_obliquity(jme) u = jme / 10.0 ε0 = - let p = ( - 84381.448, - -4680.93, - -1.55, - 1999.25, - -51.38, - -249.67, - -39.05, - 7.12, - 27.87, - 5.79, - 2.45, - ) - evalpoly(u, p) - end + let p = ( + 84381.448, + -4680.93, + -1.55, + 1999.25, + -51.38, + -249.67, + -39.05, + 7.12, + 27.87, + 5.79, + 2.45, + ) + evalpoly(u, p) + end return ε0 # arcseconds end @@ -386,10 +386,10 @@ function _compute_spa_srt_parameters(dt::DateTime, δt::Float64) end function _solar_position( - obs::SPAObserver{T}, - dt::DateTime, - alg::SPA, -) where {T<:AbstractFloat} + obs::SPAObserver{T}, + dt::DateTime, + alg::SPA, + ) where {T <: AbstractFloat} δt::Float64 = if alg.delta_t === nothing calculate_deltat(dt) else @@ -433,17 +433,17 @@ function _solar_position( return SolPos{T}(az, e0, θz0) end -function _solar_position(obs::Observer{T}, dt::DateTime, alg::SPA) where {T<:AbstractFloat} +function _solar_position(obs::Observer{T}, dt::DateTime, alg::SPA) where {T <: AbstractFloat} spa_obs = SPAObserver{T}(obs.latitude, obs.longitude, obs.altitude) return _solar_position(spa_obs, dt, alg) end function _solar_position( - obs::AbstractObserver{T}, - dt, - alg::SPA, - ::DefaultRefraction, -) where {T<:AbstractFloat} + obs::AbstractObserver{T}, + dt, + alg::SPA, + ::DefaultRefraction, + ) where {T <: AbstractFloat} return _solar_position( obs, dt, @@ -457,12 +457,12 @@ function _solar_position( end function solar_position!( - pos::StructArrays.StructVector{S}, - obs::AbstractObserver{T}, - dts::AbstractVector{DateTime}, - alg::SPA, - refraction::RefractionAlgorithm = DefaultRefraction(), -) where {S<:AbstractSolPos,T<:AbstractFloat} + pos::StructArrays.StructVector{S}, + obs::AbstractObserver{T}, + dts::AbstractVector{DateTime}, + alg::SPA, + refraction::RefractionAlgorithm = DefaultRefraction(), + ) where {S <: AbstractSolPos, T <: AbstractFloat} spa_obs = SPAObserver{T}(obs.latitude, obs.longitude, obs.altitude) @inbounds for i in eachindex(dts, pos) pos[i] = solar_position(spa_obs, dts[i], alg, refraction) diff --git a/src/Positioning/usno.jl b/src/Positioning/usno.jl index e807fd7..7d934f2 100644 --- a/src/Positioning/usno.jl +++ b/src/Positioning/usno.jl @@ -16,22 +16,22 @@ $(TYPEDFIELDS) """ struct USNO <: SolarAlgorithm "Difference between terrestrial time and UT1 [seconds]. If `nothing`, uses automatic calculation." - delta_t::Union{Float64,Nothing} + delta_t::Union{Float64, Nothing} "Option for calculating Greenwich mean sidereal time (1 or 2)" gmst_option::Int - function USNO(delta_t::Union{Float64,Nothing}, gmst_option::Int) + function USNO(delta_t::Union{Float64, Nothing}, gmst_option::Int) if gmst_option != 1 && gmst_option != 2 error("gmst_option must be either 1 or 2") end - new(delta_t, gmst_option) + return new(delta_t, gmst_option) end end USNO() = USNO(67.0, 1) # default delta_t value and gmst_option -function _solar_position(obs::Observer{T}, dt::DateTime, alg::USNO) where {T<:AbstractFloat} +function _solar_position(obs::Observer{T}, dt::DateTime, alg::USNO) where {T <: AbstractFloat} δt::T = if alg.delta_t === nothing calculate_deltat(dt) else @@ -53,7 +53,7 @@ function _solar_position(obs::Observer{T}, dt::DateTime, alg::USNO) where {T<:Ab q = mod(q, 360.0) # geocentric apparent ecliptic longitude of the sun (adjusted for aberration) [deg] - L = q + 1.915 * sind(g) + 0.020 * sind(2 * g) + L = q + 1.915 * sind(g) + 0.02 * sind(2 * g) L = mod(L, 360.0) # mean obliquity of the ecliptic [deg] @@ -83,10 +83,10 @@ function _solar_position(obs::Observer{T}, dt::DateTime, alg::USNO) where {T<:Ab gmst = if alg.gmst_option == 1 ( 6.697375 + - 0.065707485828 * day_ut + - 1.0027379 * H + - 0.0854103 * t_cent + - 0.0000258 * t_cent^2 + 0.065707485828 * day_ut + + 1.0027379 * H + + 0.0854103 * t_cent + + 0.0000258 * t_cent^2 ) else # gmst_option == 2 (6.697375 + 0.065709824279 * day_ut + 1.0027379 * H + 0.0000258 * t_cent^2) diff --git a/src/Positioning/walraven.jl b/src/Positioning/walraven.jl index af6d787..d852261 100644 --- a/src/Positioning/walraven.jl +++ b/src/Positioning/walraven.jl @@ -42,14 +42,14 @@ function _solar_position(obs::Observer{T}, dt::DateTime, ::Walraven) where {T} # longitude of the sun [rad] lon_sun = ( 4.900968 + - 3.67474e-7 * time + - (0.033434 - 2.3e-9 * time) * sin(g) + - 0.000349 * sin(2 * g) + - θ + 3.67474e-7 * time + + (0.033434 - 2.3e-9 * time) * sin(g) + + 0.000349 * sin(2 * g) + + θ ) # obliquity of ecliptic [rad] - ϵ = deg2rad(T(23.4420)) - deg2rad(T(3.56e-7)) * time + ϵ = deg2rad(T(23.442)) - deg2rad(T(3.56e-7)) * time (sin_lon_sun, cos_lon_sun) = sincos(lon_sun) (sin_ϵ, cos_ϵ) = sincos(ϵ) diff --git a/src/Refraction/Refraction.jl b/src/Refraction/Refraction.jl index f627719..2c0f5fa 100644 --- a/src/Refraction/Refraction.jl +++ b/src/Refraction/Refraction.jl @@ -63,7 +63,7 @@ correction = refraction(hughes, elevation) apparent_elevation = elevation + correction ``` """ -function refraction(model::RefractionAlgorithm, elevation::T) where {T<:AbstractFloat} +function refraction(model::RefractionAlgorithm, elevation::T) where {T <: AbstractFloat} return _refraction(model, elevation) end diff --git a/src/Refraction/archer.jl b/src/Refraction/archer.jl index e8af957..164d683 100644 --- a/src/Refraction/archer.jl +++ b/src/Refraction/archer.jl @@ -47,7 +47,7 @@ apparent_elevation = elevation + refraction_correction """ struct ARCHER <: RefractionAlgorithm end -function _refraction(::ARCHER, elevation_deg::T) where {T<:AbstractFloat} +function _refraction(::ARCHER, elevation_deg::T) where {T <: AbstractFloat} zenith = T(90.0) - elevation_deg # calculate cosine of zenith angle diff --git a/src/Refraction/bennett.jl b/src/Refraction/bennett.jl index 89fad28..19c9f70 100644 --- a/src/Refraction/bennett.jl +++ b/src/Refraction/bennett.jl @@ -44,7 +44,7 @@ refraction_correction = refraction(bennett, elevation) apparent_elevation = elevation + refraction_correction ``` """ -struct BENNETT{T} <: RefractionAlgorithm where {T<:AbstractFloat} +struct BENNETT{T} <: RefractionAlgorithm where {T <: AbstractFloat} "Annual average atmospheric pressure [Pascal]" pressure::T "Annual average temperature [°C]" @@ -53,7 +53,7 @@ end BENNETT() = BENNETT{Float64}(101325.0, 12.0) -function _refraction(model::BENNETT{T}, elevation_deg::T) where {T<:AbstractFloat} +function _refraction(model::BENNETT{T}, elevation_deg::T) where {T <: AbstractFloat} # convert pressure from Pascal to hPa pressure_hPa = model.pressure / T(100.0) r = T(0.016667) / tand(elevation_deg + T(7.31) / (elevation_deg + T(4.4))) diff --git a/src/Refraction/hughes.jl b/src/Refraction/hughes.jl index feeae0b..da6e46f 100644 --- a/src/Refraction/hughes.jl +++ b/src/Refraction/hughes.jl @@ -63,7 +63,7 @@ refraction_correction = refraction(hughes, elevation) apparent_elevation = elevation + refraction_correction ``` """ -struct HUGHES{T} <: RefractionAlgorithm where {T<:AbstractFloat} +struct HUGHES{T} <: RefractionAlgorithm where {T <: AbstractFloat} "Annual average atmospheric pressure [Pascal]" pressure::T "Annual average temperature [°C]" @@ -72,7 +72,7 @@ end HUGHES() = HUGHES{Float64}(101325.0, 10.0) -function _refraction(model::HUGHES{T}, elevation_deg::T) where {T<:AbstractFloat} +function _refraction(model::HUGHES{T}, elevation_deg::T) where {T <: AbstractFloat} # this avoids numerical instability at very high elevations if elevation_deg > T(85.0) return T(0.0) diff --git a/src/Refraction/michalsky.jl b/src/Refraction/michalsky.jl index 0900285..a01c8d8 100644 --- a/src/Refraction/michalsky.jl +++ b/src/Refraction/michalsky.jl @@ -45,7 +45,7 @@ apparent_elevation = elevation + refraction_correction """ struct MICHALSKY <: RefractionAlgorithm end -function _refraction(::MICHALSKY, elevation_deg::T) where {T<:AbstractFloat} +function _refraction(::MICHALSKY, elevation_deg::T) where {T <: AbstractFloat} # ref = 3.51561 * (0.1594 + 0.0196 * el + 0.00002 * el^2) / (1 + 0.505 * el + 0.0845 * el^2) numerator = let p = (0.1594, 0.0196, 0.00002), q = map(T, p) T(3.51561) * evalpoly(elevation_deg, q) diff --git a/src/Refraction/sg2.jl b/src/Refraction/sg2.jl index 38bba47..82a3286 100644 --- a/src/Refraction/sg2.jl +++ b/src/Refraction/sg2.jl @@ -50,7 +50,7 @@ refraction_correction = refraction(sg2, elevation) apparent_elevation = elevation + refraction_correction ``` """ -struct SG2{T} <: RefractionAlgorithm where {T<:AbstractFloat} +struct SG2{T} <: RefractionAlgorithm where {T <: AbstractFloat} "Annual average atmospheric pressure [Pascal]" pressure::T "Annual average temperature [°C]" @@ -59,7 +59,7 @@ end SG2() = SG2{Float64}(101325.0, 12.0) -function _refraction(model::SG2{T}, elevation_deg::T) where {T<:AbstractFloat} +function _refraction(model::SG2{T}, elevation_deg::T) where {T <: AbstractFloat} # Convert pressure from Pascal to hPa (hectopascal) pressure_hPa = model.pressure / T(100.0) @@ -71,7 +71,7 @@ function _refraction(model::SG2{T}, elevation_deg::T) where {T<:AbstractFloat} # For elevations above -0.01 radians refraction_rad = ( T(2.96706e-4) / - tan(elevation_rad + T(0.0031376) / (elevation_rad + T(0.089186))) + tan(elevation_rad + T(0.0031376) / (elevation_rad + T(0.089186))) ) else # Apply correction term of Cornwall et al. (2011) for low elevations diff --git a/src/Refraction/spa.jl b/src/Refraction/spa.jl index 85f3816..1773002 100644 --- a/src/Refraction/spa.jl +++ b/src/Refraction/spa.jl @@ -53,7 +53,7 @@ refraction_correction = refraction(spa, elevation) apparent_elevation = elevation + refraction_correction ``` """ -@kwdef struct SPARefraction{T<:AbstractFloat} <: RefractionAlgorithm +@kwdef struct SPARefraction{T <: AbstractFloat} <: RefractionAlgorithm "Annual average atmospheric pressure [Pascal]" pressure::T = 101325.0 "Annual average temperature [°C]" @@ -62,10 +62,10 @@ apparent_elevation = elevation + refraction_correction atmos_refract::T = -0.5667 end -SPARefraction(pressure::T, temperature::T) where {T<:AbstractFloat} = +SPARefraction(pressure::T, temperature::T) where {T <: AbstractFloat} = SPARefraction{T}(pressure, temperature, T(-0.5667)) -function _refraction(model::SPARefraction{T}, elevation_deg::T) where {T<:AbstractFloat} +function _refraction(model::SPARefraction{T}, elevation_deg::T) where {T <: AbstractFloat} # Convert pressure from Pascal to hPa/mbar pressure_hPa = model.pressure / T(100.0) @@ -78,7 +78,7 @@ function _refraction(model::SPARefraction{T}, elevation_deg::T) where {T<:Abstra # ref = (P/1010) * (283/(273+T)) * 1.02 / (60 * tan(radians(el + 10.3/(el+5.11)))) refraction_correction = ( (pressure_hPa / T(1010.0)) * (T(283.0) / (T(273.0) + model.temperature)) * T(1.02) / - (T(60.0) * tan(deg2rad(elevation_deg + T(10.3) / (elevation_deg + T(5.11))))) + (T(60.0) * tan(deg2rad(elevation_deg + T(10.3) / (elevation_deg + T(5.11))))) ) return refraction_correction diff --git a/src/Utilities/spa.jl b/src/Utilities/spa.jl index eae830c..2145eb7 100644 --- a/src/Utilities/spa.jl +++ b/src/Utilities/spa.jl @@ -20,30 +20,30 @@ function _compute_srt_parameters(dt::DateTime, δt::Float64) end function _transit_sunrise_sunset( - ::Type{R}, - obs::Observer{T}, - dt::DateTime, - alg::SPA, -) where {T<:AbstractFloat,R<:DateTime} + ::Type{R}, + obs::Observer{T}, + dt::DateTime, + alg::SPA, + ) where {T <: AbstractFloat, R <: DateTime} return _transit_sunrise_sunset_impl(R, obs, dt, alg, nothing) end function _transit_sunrise_sunset( - tz::TimeZone, - obs::Observer{T}, - dt::DateTime, - alg::SPA, -) where {T<:AbstractFloat} + tz::TimeZone, + obs::Observer{T}, + dt::DateTime, + alg::SPA, + ) where {T <: AbstractFloat} return _transit_sunrise_sunset_impl(ZonedDateTime, obs, dt, alg, tz) end function _transit_sunrise_sunset_impl( - ::Type{R}, - obs::Observer{T}, - dt::DateTime, - alg::SPA, - tz::Union{Nothing,TimeZone}, -) where {T<:AbstractFloat,R<:Union{DateTime,ZonedDateTime}} + ::Type{R}, + obs::Observer{T}, + dt::DateTime, + alg::SPA, + tz::Union{Nothing, TimeZone}, + ) where {T <: AbstractFloat, R <: Union{DateTime, ZonedDateTime}} """Calculate the sun transit, sunrise, and sunset for a given date at an Observer location using the SPA algorithm. diff --git a/src/Utilities/srt.jl b/src/Utilities/srt.jl index c4e1eaa..7b461f4 100644 --- a/src/Utilities/srt.jl +++ b/src/Utilities/srt.jl @@ -27,7 +27,7 @@ TransitSunriseSunset{ZonedDateTime}( # Fields $(TYPEDFIELDS) """ -struct TransitSunriseSunset{T<:Union{DateTime,ZonedDateTime}} +struct TransitSunriseSunset{T <: Union{DateTime, ZonedDateTime}} transit::T sunrise::T sunset::T @@ -35,21 +35,21 @@ end # Constructor for DateTime (no timezone conversion) function TransitSunriseSunset{DateTime}( - transit::DateTime, - sunrise::DateTime, - sunset::DateTime, - ::Nothing, -) + transit::DateTime, + sunrise::DateTime, + sunset::DateTime, + ::Nothing, + ) return TransitSunriseSunset{DateTime}(transit, sunrise, sunset) end # Constructor for ZonedDateTime (with timezone conversion) function TransitSunriseSunset{ZonedDateTime}( - transit::DateTime, - sunrise::DateTime, - sunset::DateTime, - tz::TimeZone, -) + transit::DateTime, + sunrise::DateTime, + sunset::DateTime, + tz::TimeZone, + ) return TransitSunriseSunset{ZonedDateTime}( ZonedDateTime(transit, tz; from_utc = true), ZonedDateTime(sunrise, tz; from_utc = true), @@ -61,27 +61,27 @@ end for a given date at an Observer location. """ function transit_sunrise_sunset( - obs::Observer{T}, - dt::DateTime, - alg::SolarAlgorithm = SPA(), -)::TransitSunriseSunset{DateTime} where {T<:AbstractFloat} - _transit_sunrise_sunset(DateTime, obs, dt, alg) + obs::Observer{T}, + dt::DateTime, + alg::SolarAlgorithm = SPA(), + )::TransitSunriseSunset{DateTime} where {T <: AbstractFloat} + return _transit_sunrise_sunset(DateTime, obs, dt, alg) end function transit_sunrise_sunset( - obs::Observer{T}, - dt::Date, - alg::SolarAlgorithm = SPA(), -)::TransitSunriseSunset{DateTime} where {T<:AbstractFloat} - transit_sunrise_sunset(obs, DateTime(dt), alg) + obs::Observer{T}, + dt::Date, + alg::SolarAlgorithm = SPA(), + )::TransitSunriseSunset{DateTime} where {T <: AbstractFloat} + return transit_sunrise_sunset(obs, DateTime(dt), alg) end function transit_sunrise_sunset( - obs::Observer{T}, - zdt::ZonedDateTime, - alg::SolarAlgorithm = SPA(), -)::TransitSunriseSunset{ZonedDateTime} where {T<:AbstractFloat} - _transit_sunrise_sunset(timezone(zdt), obs, DateTime(zdt, UTC), alg) + obs::Observer{T}, + zdt::ZonedDateTime, + alg::SolarAlgorithm = SPA(), + )::TransitSunriseSunset{ZonedDateTime} where {T <: AbstractFloat} + return _transit_sunrise_sunset(timezone(zdt), obs, DateTime(zdt, UTC), alg) end # Helper function for next_* functions @@ -102,11 +102,11 @@ end # Helper function for previous_* functions function _previous_event( - obs::Observer, - dt::DateTime, - alg::SolarAlgorithm, - event_field::Symbol, -) + obs::Observer, + dt::DateTime, + alg::SolarAlgorithm, + event_field::Symbol, + ) date_only = Date(dt) midnight_utc = DateTime(date_only) result = transit_sunrise_sunset(obs, midnight_utc, alg) diff --git a/test/.CondaPkg/.gitattributes b/test/.CondaPkg/.gitattributes new file mode 100644 index 0000000..887a2c1 --- /dev/null +++ b/test/.CondaPkg/.gitattributes @@ -0,0 +1,2 @@ +# SCM syntax highlighting & preventing 3-way merges +pixi.lock merge=binary linguist-language=YAML linguist-generated=true diff --git a/test/.CondaPkg/.gitignore b/test/.CondaPkg/.gitignore new file mode 100644 index 0000000..740bb7d --- /dev/null +++ b/test/.CondaPkg/.gitignore @@ -0,0 +1,4 @@ + +# pixi environments +.pixi +*.egg-info diff --git a/test/.CondaPkg/meta b/test/.CondaPkg/meta new file mode 100644 index 0000000..728d60f Binary files /dev/null and b/test/.CondaPkg/meta differ diff --git a/test/.CondaPkg/pixi.lock b/test/.CondaPkg/pixi.lock new file mode 100644 index 0000000..42d9e6d --- /dev/null +++ b/test/.CondaPkg/pixi.lock @@ -0,0 +1,851 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py314h2e6c369_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/copier-9.11.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.4-py314h7fe84b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/dunamai-1.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/eval-type-backport-0.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/eval_type_backport-0.2.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/funcy-2.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-ansible-filters-1.3.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.5-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/paramiko-4.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/plumbum-1.10.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.51-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.6.2-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pywin32-on-windows-0.1.0-pyh1179c8e_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/questionary-2.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + arch: x86_64 + platform: linux + license: None + size: 2562 + timestamp: 1578324546067 +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + build_number: 16 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + arch: x86_64 + platform: linux + license: BSD-3-Clause + license_family: BSD + size: 23621 + timestamp: 1650670423406 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda + sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 + md5: 2934f256a8acfe48f6ebb4fce6cde29c + depends: + - python >=3.9 + - typing-extensions >=4.0.0 + license: MIT + license_family: MIT + size: 18074 + timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bcrypt-5.0.0-py314h2e6c369_1.conda + sha256: 1ca9b0d228362574bd503f557152eb3ca2eb8bf70663b3a755d8020202e03885 + md5: 6f7d83cec0fff00ca9a772034411fa12 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + arch: x86_64 + platform: linux + license: Apache-2.0 + license_family: APACHE + size: 292368 + timestamp: 1762497706993 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 + md5: 51a19bba1b8ebfb60df25cde030b7ebc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + arch: x86_64 + platform: linux + license: bzip2-1.0.6 + license_family: BSD + size: 260341 + timestamp: 1757437258798 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + sha256: b5974ec9b50e3c514a382335efa81ed02b05906849827a34061c496f4defa0b2 + md5: bddacf101bb4dd0e51811cb69c7790e2 + depends: + - __unix + license: ISC + size: 146519 + timestamp: 1767500828366 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + sha256: c6339858a0aaf5d939e00d345c98b99e4558f285942b27232ac098ad17ac7f8e + md5: cf45f4278afd6f4e6d03eda0f435d527 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 300271 + timestamp: 1761203085220 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/copier-9.11.3-pyhcf101f3_0.conda + sha256: 0760286714848e8af7aade73da886e9f5cfe4126e6d10501f10135e50e94c2c0 + md5: fed521ea8b179bf63e9986b3108ed5f3 + depends: + - python >=3.10 + - colorama >=0.4.6 + - dunamai >=1.7.0 + - funcy >=1.17 + - jinja2 >=3.1.5 + - jinja2-ansible-filters >=1.3.1 + - packaging >=23.0 + - pathspec >=0.9.0 + - plumbum >=1.6.9 + - prompt-toolkit <3.0.52 + - pydantic >=2.4.2 + - pygments >=2.7.1 + - pyyaml >=5.3.1 + - questionary >=1.8.1 + - eval-type-backport >=0.1.3,<0.3.0 + - platformdirs >=4.3.6 + - typing_extensions >=4.0.0,<5.0.0 + - python + license: MIT + license_family: MIT + size: 54229 + timestamp: 1769272985745 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.4-py314h7fe84b3_0.conda + sha256: 90738c26981732357d71b97df1994a1a74f87701468d61e19755af7d9e35edf8 + md5: afabda22fe5163200fc59f31b58d9e6a + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.14 + - libgcc >=14 + - openssl >=3.5.5,<4.0a0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + arch: x86_64 + platform: linux + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + size: 1719239 + timestamp: 1769650654007 +- conda: https://conda.anaconda.org/conda-forge/noarch/dunamai-1.25.0-pyhd8ed1ab_0.conda + sha256: 16d78408ed520b0951425cdfae280392813794e29ea6d3cb95f6c479347c4e1c + md5: 4b6cc280feef9e74ffe9ea1c875b5f8c + depends: + - packaging >=20.9 + - python >=3.9 + license: MIT + license_family: MIT + size: 30075 + timestamp: 1751991836363 +- conda: https://conda.anaconda.org/conda-forge/noarch/eval-type-backport-0.2.2-pyhd8ed1ab_0.conda + sha256: 05ffdcb83903c159bfbb78a07fbcce6fd6dda41df9c55ed75e0eb1db5528048f + md5: 879479fda1dddb002fdc4885cea33740 + depends: + - eval_type_backport >=0.2.2,<0.2.3.0a0 + - python >=3.9 + license: MIT + license_family: MIT + size: 6662 + timestamp: 1734857849281 +- conda: https://conda.anaconda.org/conda-forge/noarch/eval_type_backport-0.2.2-pyha770c72_0.conda + sha256: 2d721421a60676216e10837a240c75e2190e093920a4016a469fa9a62c95ab5f + md5: 8681d7f876da5e66a1c7fce424509383 + depends: + - python >=3.9 + constrains: + - eval-type-backport >=0.2.2,<0.2.3.0a0 + license: MIT + license_family: MIT + size: 11520 + timestamp: 1734857840035 +- conda: https://conda.anaconda.org/conda-forge/noarch/funcy-2.0-pyhd8ed1ab_1.conda + sha256: 4a3e3e86b7b49aaa2a0faa57da2bcf39f7ee858499e8335132f83bfeed79191e + md5: 84f8955e99a8944fdee49da39edb0add + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + size: 30249 + timestamp: 1734381235500 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 + md5: 186a18e3ba246eccfc7cff00cd19a870 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 12728445 + timestamp: 1767969922681 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + sha256: acc1d991837c0afb67c75b77fdc72b4bf022aac71fedd8b9ea45918ac9b08a80 + md5: c85c76dc67d75619a92f51dfbce06992 + depends: + - python >=3.9 + - zipp >=3.1.0 + constrains: + - importlib-resources >=6.5.2,<6.5.3.0a0 + license: Apache-2.0 + license_family: APACHE + size: 33781 + timestamp: 1736252433366 +- conda: https://conda.anaconda.org/conda-forge/noarch/invoke-2.2.1-pyhd8ed1ab_0.conda + sha256: 5a4e3a01f626c8de15ddada622d364e94ff28e8d6bdedf1665442ef03a4e0140 + md5: 3a804714ed59be1969ffca10f703ec2a + depends: + - python >=3.10 + license: BSD-2-Clause + license_family: BSD + size: 132825 + timestamp: 1760146119847 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b + md5: 04558c96691bed63104678757beb4f8d + depends: + - markupsafe >=2.0 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + size: 120685 + timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-ansible-filters-1.3.2-pyhd8ed1ab_1.conda + sha256: a36789229ca9ce5315265b9d425abce9acb4691f5864aea69e935020545a9acb + md5: 974c5b3e353f031cfcf2365c9d375926 + depends: + - jinja2 + - python >=3.9 + - pyyaml + license: BSD-2-Clause + license_family: BSD + size: 20315 + timestamp: 1734906203051 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + sha256: 565941ac1f8b0d2f2e8f02827cbca648f4d18cd461afc31f15604cd291b5c5f3 + md5: 12bd9a3f089ee6c9266a37dab82afabd + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + arch: x86_64 + platform: linux + license: GPL-3.0-only + license_family: GPL + size: 725507 + timestamp: 1770267139900 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda + sha256: 1e1b08f6211629cbc2efe7a5bca5953f8f6b3cae0eeb04ca4dacee1bd4e2db2f + md5: 8b09ae86839581147ef2e5c5e229d164 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.3.* + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 76643 + timestamp: 1763549731408 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_5.conda + sha256: 0caed73aac3966bfbf5710e06c728a24c6c138605121a3dacb2e03440e8baa6a + md5: 264fbfba7fb20acf3b29cde153e345ce + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgomp 15.1.0 h767d61c_5 + - libgcc-ng ==15.1.0=*_5 + arch: x86_64 + platform: linux + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 824191 + timestamp: 1757042543820 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_5.conda + sha256: f54bb9c3be12b24be327f4c1afccc2969712e0b091cdfbd1d763fb3e61cda03f + md5: 069afdf8ea72504e48d23ae1171d951c + depends: + - libgcc 15.1.0 h767d61c_5 + arch: x86_64 + platform: linux + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 29187 + timestamp: 1757042549554 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_5.conda + sha256: 125051d51a8c04694d0830f6343af78b556dd88cc249dfec5a97703ebfb1832d + md5: dcd5ff1940cd38f6df777cac86819d60 + depends: + - __glibc >=2.17,<3.0.a0 + arch: x86_64 + platform: linux + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 447215 + timestamp: 1757042483384 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb + md5: c7c83eecbb72d88b940c249af56c8b17 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.2.* + arch: x86_64 + platform: linux + license: 0BSD + size: 113207 + timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 + md5: 2c21e66f50753a083cbe6b80f38268fa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + arch: x86_64 + platform: linux + license: BSD-2-Clause + license_family: BSD + size: 92400 + timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda + sha256: 0105bd108f19ea8e6a78d2d994a6d4a8db16d19a41212070d2d1d48a63c34161 + md5: a587892d3c13b6621a6091be690dbca2 + depends: + - libgcc-ng >=12 + arch: x86_64 + platform: linux + license: ISC + size: 205978 + timestamp: 1716828628198 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.2-hf4e2dac_0.conda + sha256: 04596fcee262a870e4b7c9807224680ff48d4d0cc0dac076a602503d3dc6d217 + md5: da5be73701eecd0e8454423fd6ffcf30 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + arch: x86_64 + platform: linux + license: blessing + size: 942808 + timestamp: 1768147973361 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_5.conda + sha256: 0f5f61cab229b6043541c13538d75ce11bd96fb2db76f94ecf81997b1fde6408 + md5: 4e02a49aaa9d5190cb630fa43528fbe6 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.1.0 h767d61c_5 + arch: x86_64 + platform: linux + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3896432 + timestamp: 1757042571458 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_5.conda + sha256: 7b8cabbf0ab4fe3581ca28fe8ca319f964078578a51dd2ca3f703c1d21ba23ff + md5: 8bba50c7f4679f08c861b597ad2bda6b + depends: + - libstdcxx 15.1.0 h8f9b012_5 + arch: x86_64 + platform: linux + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 29233 + timestamp: 1757042603319 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee + md5: db409b7c1720428638e7c0d509d3e1b5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + arch: x86_64 + platform: linux + license: BSD-3-Clause + license_family: BSD + size: 40311 + timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4 + md5: edb0dca6bc32e4f4789199455a1dbeb8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + constrains: + - zlib 1.3.1 *_2 + arch: x86_64 + platform: linux + license: Zlib + license_family: Other + size: 60963 + timestamp: 1727963148474 +- conda: https://conda.anaconda.org/conda-forge/noarch/markupsafe-3.0.3-pyh7db6752_0.conda + sha256: e0cbfea51a19b3055ca19428bd9233a25adca956c208abb9d00b21e7259c7e03 + md5: fab1be106a50e20f10fe5228fd1d1651 + depends: + - python >=3.10 + constrains: + - jinja2 >=3.0.0 + track_features: + - markupsafe_no_compile + license: BSD-3-Clause + license_family: BSD + size: 15499 + timestamp: 1759055275624 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 + md5: 47e340acb35de30501a76c7c799c41d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + arch: x86_64 + platform: linux + license: X11 AND BSD-3-Clause + size: 891641 + timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.5-h35e630c_1.conda + sha256: 752b58a5886596fd791e559f8f35f1f4304f924410a3ff47cf999fc89ee5a610 + md5: f146d5fd47c519c44fe459300a170ae3 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + arch: x86_64 + platform: linux + license: Apache-2.0 + license_family: Apache + size: 3115300 + timestamp: 1769560205194 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 + md5: b76541e68fea4d511b1ac46a28dcd2c6 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + size: 72010 + timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/noarch/paramiko-4.0.0-pyhd8ed1ab_0.conda + sha256: ce76d5a1fc6c7ef636cbdbf14ce2d601a1bfa0dd8d286507c1fd02546fccb94b + md5: 1a884d2b1ea21abfb73911dcdb8342e4 + depends: + - bcrypt >=3.2 + - cryptography >=3.3 + - invoke >=2.0 + - pynacl >=1.5 + - python >=3.9 + license: LGPL-2.1-or-later + license_family: LGPL + size: 159896 + timestamp: 1755102147074 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + sha256: 29ea20d0faf20374fcd61c25f6d32fb8e9a2c786a7f1473a0c3ead359470fbe1 + md5: 2908273ac396d2cd210a8127f5f1c0d6 + depends: + - python >=3.10 + license: MPL-2.0 + license_family: MOZILLA + size: 53739 + timestamp: 1769677743677 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda + sha256: 04c64fb78c520e5c396b6e07bc9082735a5cc28175dbe23138201d0a9441800b + md5: 1bd2e65c8c7ef24f4639ae6e850dacc2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 23922 + timestamp: 1764950726246 +- conda: https://conda.anaconda.org/conda-forge/noarch/plumbum-1.10.0-pyhcf101f3_0.conda + sha256: 972e0c1c9f0b1763d482e885732baef7f9a0cbe8686f5e2c6bdd88838619a59a + md5: 7fd2e38f4e608f5ebd80f871352c5495 + depends: + - python >=3.10 + - pywin32-on-windows + - paramiko + - importlib_resources + - python + license: MIT + license_family: MIT + size: 103911 + timestamp: 1761911487086 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + sha256: ebc1bb62ac612af6d40667da266ff723662394c0ca78935340a5b5c14831227b + md5: d17ae9db4dc594267181bd199bf9a551 + depends: + - python >=3.9 + - wcwidth + constrains: + - prompt_toolkit 3.0.51 + license: BSD-3-Clause + license_family: BSD + size: 271841 + timestamp: 1744724188108 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.51-hd8ed1ab_0.conda + sha256: 936189f0373836c1c77cd2d6e71ba1e583e2d3920bf6d015e96ee2d729b5e543 + md5: 1e61ab85dd7c60e5e73d853ea035dc29 + depends: + - prompt-toolkit >=3.0.51,<3.0.52.0a0 + license: BSD-3-Clause + license_family: BSD + size: 7182 + timestamp: 1744724189376 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 + md5: 12c566707c80111f9799308d9e265aef + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + size: 110100 + timestamp: 1733195786147 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda + sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d + md5: c3946ed24acdb28db1b5d63321dbca7d + depends: + - typing-inspection >=0.4.2 + - typing_extensions >=4.14.1 + - python >=3.10 + - typing-extensions >=4.6.1 + - annotated-types >=0.6.0 + - pydantic-core ==2.41.5 + - python + license: MIT + license_family: MIT + size: 340482 + timestamp: 1764434463101 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda + sha256: 7e0ae379796e28a429f8e48f2fe22a0f232979d65ec455e91f8dac689247d39f + md5: 432b0716a1dfac69b86aa38fdd59b7e6 + depends: + - python + - typing-extensions >=4.6.0,!=4.7.0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 1943088 + timestamp: 1762988995556 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a + md5: 6b6ece66ebcae2d5f326c77ef2c5a066 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + size: 889287 + timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.6.2-py314h5bd0f2a_0.conda + sha256: 86093b979cb28efb72bb03693857d300abd16cba91b50120a403bdd85c8629a9 + md5: 11c74c76b6a6e1dd89c5fe98d65ed37f + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.4.1 + - libgcc >=14 + - libsodium >=1.0.20,<1.0.21.0a0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - six + arch: x86_64 + platform: linux + license: Apache-2.0 + license_family: Apache + size: 1163036 + timestamp: 1767324013517 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_100_cp314.conda + build_number: 100 + sha256: ff087b19d158644d3b0708eca10a5e40d692cdc8e95f53715f4490c6959f3768 + md5: b40594d5da041824087eebe12228af42 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + arch: x86_64 + platform: linux + license: Python-2.0 + size: 36529771 + timestamp: 1770271970971 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + size: 6989 + timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/noarch/pywin32-on-windows-0.1.0-pyh1179c8e_3.tar.bz2 + sha256: 6502696aaef571913b22a808b15c185bd8ea4aabb952685deb29e6a6765761cb + md5: 2807a0becd1d986fe1ef9b7f8135f215 + depends: + - __unix + - python >=2.7 + license: BSD-3-Clause + license_family: BSD + size: 4856 + timestamp: 1646866525560 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/noarch/questionary-2.1.1-pyhd8ed1ab_0.conda + sha256: 0604c6dff3af5f53e34fceb985395d08287137f220450108a795bcd1959caf14 + md5: 34fa231b5c5927684b03bb296bb94ddc + depends: + - prompt_toolkit >=2.0,<4.0 + - python >=3.10 + license: MIT + license_family: MIT + size: 31257 + timestamp: 1757356458097 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + arch: x86_64 + platform: linux + license: GPL-3.0-only + license_family: GPL + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + size: 18455 + timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + arch: x86_64 + platform: linux + license: TCL + license_family: BSD + size: 3301196 + timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c + md5: edd329d7d3a4ab45dcf905899a7a6115 + depends: + - typing_extensions ==4.15.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + size: 91383 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda + sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 + md5: a0a4a3035667fc34f29bfbd5c190baa6 + depends: + - python >=3.10 + - typing_extensions >=4.12.0 + license: MIT + license_family: MIT + size: 18923 + timestamp: 1764158430324 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + size: 51692 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.5.3-pyhd8ed1ab_0.conda + sha256: 2395599ec9e37e6f21838bb26e7f2336fa03a4b1460ba10897ec856b21ac7d59 + md5: 36432484e9ce3b073a51bf138767a593 + depends: + - python >=3.10 + license: MIT + license_family: MIT + size: 70539 + timestamp: 1769858722627 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad + md5: a77f85f77be52ff59391544bfe73390a + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + arch: x86_64 + platform: linux + license: MIT + license_family: MIT + size: 85189 + timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae + md5: 30cd29cb87d819caead4d55184c1d115 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + size: 24194 + timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + arch: x86_64 + platform: linux + license: BSD-3-Clause + license_family: BSD + size: 601375 + timestamp: 1764777111296 diff --git a/test/.CondaPkg/pixi.toml b/test/.CondaPkg/pixi.toml new file mode 100644 index 0000000..6aa29ae --- /dev/null +++ b/test/.CondaPkg/pixi.toml @@ -0,0 +1,17 @@ +[dependencies] +openssl = ">=3, <3.6" +libstdcxx = ">=3.4,<=15.1" +libstdcxx-ng = ">=3.4,<=15.1" +copier = "*" + + [dependencies.python] + channel = "conda-forge" + build = "*cp*" + version = ">=3.10,!=3.14.0,!=3.14.1,<4" + +[project] +name = ".CondaPkg" +platforms = ["linux-64"] +channels = ["conda-forge"] +channel-priority = "strict" +description = "automatically generated by CondaPkg.jl" diff --git a/test/extensions/test-mtk.jl b/test/extensions/test-mtk.jl index fc73555..cc25eb7 100644 --- a/test/extensions/test-mtk.jl +++ b/test/extensions/test-mtk.jl @@ -96,7 +96,7 @@ using CairoMakie @test length(zenith_vals) == length(sol.t) # Check that zenith ≈ 90 - elevation - @test all(isapprox.(zenith_vals, 90 .- elevation_vals; atol = 1e-8)) + @test all(isapprox.(zenith_vals, 90 .- elevation_vals; atol = 1.0e-8)) # For summer solstice in San Francisco, check that: # 1. The sun rises (elevation goes from negative to positive) @@ -165,12 +165,12 @@ using CairoMakie conds = test_conditions() @testset "$alg_name" for (alg_name, alg, exp_func, refr, apparent) in [ - ("PSA", PSA(2020), expected_2020, NoRefraction(), false), - ("Walraven", Walraven(), expected_walraven, NoRefraction(), false), - ("USNO", USNO(), expected_usno, NoRefraction(), false), - ("NOAA", NOAA(), expected_noaa, HUGHES(101325.0, 10.0), true), - ("SPA", SPA(), expected_spa, DefaultRefraction(), true), - ] + ("PSA", PSA(2020), expected_2020, NoRefraction(), false), + ("Walraven", Walraven(), expected_walraven, NoRefraction(), false), + ("USNO", USNO(), expected_usno, NoRefraction(), false), + ("NOAA", NOAA(), expected_noaa, HUGHES(101325.0, 10.0), true), + ("SPA", SPA(), expected_spa, DefaultRefraction(), true), + ] # Get expected values for all test cases df_expected = exp_func() @@ -204,14 +204,14 @@ using CairoMakie @test isapprox( sol[sys.elevation][1], row.apparent_elevation, - atol = 1e-8, + atol = 1.0e-8, ) - @test isapprox(sol[sys.zenith][1], row.apparent_zenith, atol = 1e-8) + @test isapprox(sol[sys.zenith][1], row.apparent_zenith, atol = 1.0e-8) else - @test isapprox(sol[sys.elevation][1], row.elevation, atol = 1e-8) - @test isapprox(sol[sys.zenith][1], row.zenith, atol = 1e-8) + @test isapprox(sol[sys.elevation][1], row.elevation, atol = 1.0e-8) + @test isapprox(sol[sys.zenith][1], row.zenith, atol = 1.0e-8) end - @test isapprox(sol[sys.azimuth][1], row.azimuth, atol = 1e-8) + @test isapprox(sol[sys.azimuth][1], row.azimuth, atol = 1.0e-8) end end end diff --git a/test/positioning/expected-values.jl b/test/positioning/expected-values.jl index 227cdc5..2b47bb6 100644 --- a/test/positioning/expected-values.jl +++ b/test/positioning/expected-values.jl @@ -95,9 +95,9 @@ function test_conditions() # parse times as ZonedDateTime inputs.time = [ try - ZonedDateTime(t, dateformat"yyyy-mm-ddTHH:MM:SSzzzz") + ZonedDateTime(t, dateformat"yyyy-mm-ddTHH:MM:SSzzzz") catch - ZonedDateTime(t, dateformat"yyyy-mm-ddTHH:MMzzzz") + ZonedDateTime(t, dateformat"yyyy-mm-ddTHH:MMzzzz") end for t in inputs.time ] return inputs diff --git a/test/positioning/test-deltat.jl b/test/positioning/test-deltat.jl index 697c5fa..c48aae6 100644 --- a/test/positioning/test-deltat.jl +++ b/test/positioning/test-deltat.jl @@ -136,13 +136,13 @@ end @testset "Fractional Month Interpolation" begin using Dates - dates = [Date(2020, 6, day) for day = 1:30] + dates = [Date(2020, 6, day) for day in 1:30] deltat_values = [calculate_deltat(d) for d in dates] @test all(isfinite, deltat_values) - for i = 1:(length(deltat_values)-1) - @test deltat_values[i+1] >= deltat_values[i] - 0.01 + for i in 1:(length(deltat_values) - 1) + @test deltat_values[i + 1] >= deltat_values[i] - 0.01 end @test deltat_values[1] < deltat_values[end] diff --git a/test/positioning/test-interface.jl b/test/positioning/test-interface.jl index e88f560..86073a8 100644 --- a/test/positioning/test-interface.jl +++ b/test/positioning/test-interface.jl @@ -16,11 +16,11 @@ using StructArrays: StructVector using Dates: Hour, @dateformat_str @testset "$alg_name" for (alg_name, alg) in [ - ("PSA", PSA()), - ("NOAA", NOAA()), - ("Walraven", Walraven()), - ("SPA", SPA()), -] + ("PSA", PSA()), + ("NOAA", NOAA()), + ("Walraven", Walraven()), + ("SPA", SPA()), + ] @testset "Scalar Interface" begin lat, lon, alt = 45.0, 10.0, 4000.0 @@ -46,7 +46,7 @@ using Dates: Hour, @dateformat_str n_dts = 10 base_dt = DateTime(2020, 10, 17, 12, 30) - dts = [base_dt + Hour(i) for i = 0:(n_dts-1)] + dts = [base_dt + Hour(i) for i in 0:(n_dts - 1)] dts_zoned = [ZonedDateTime(dt, tz"UTC") for dt in dts] single_dt = base_dt @@ -55,29 +55,35 @@ using Dates: Hour, @dateformat_str @testset "In place" begin if alg isa SPA PosType = ApparentSolPos{Float64} - pos = StructVector{ApparentSolPos{Float64}}(( - azimuth = zeros(n_dts), - elevation = zeros(n_dts), - zenith = zeros(n_dts), - apparent_elevation = zeros(n_dts), - apparent_zenith = zeros(n_dts), - )) + pos = StructVector{ApparentSolPos{Float64}}( + ( + azimuth = zeros(n_dts), + elevation = zeros(n_dts), + zenith = zeros(n_dts), + apparent_elevation = zeros(n_dts), + apparent_zenith = zeros(n_dts), + ) + ) elseif alg isa NOAA PosType = ApparentSolPos{Float64} - pos = StructVector{ApparentSolPos{Float64}}(( - azimuth = zeros(n_dts), - elevation = zeros(n_dts), - zenith = zeros(n_dts), - apparent_elevation = zeros(n_dts), - apparent_zenith = zeros(n_dts), - )) + pos = StructVector{ApparentSolPos{Float64}}( + ( + azimuth = zeros(n_dts), + elevation = zeros(n_dts), + zenith = zeros(n_dts), + apparent_elevation = zeros(n_dts), + apparent_zenith = zeros(n_dts), + ) + ) else PosType = SolPos{Float64} - pos = StructVector{SolPos{Float64}}(( - azimuth = zeros(n_dts), - elevation = zeros(n_dts), - zenith = zeros(n_dts), - )) + pos = StructVector{SolPos{Float64}}( + ( + azimuth = zeros(n_dts), + elevation = zeros(n_dts), + zenith = zeros(n_dts), + ) + ) end solar_position!(pos, obs, dts, alg) @@ -126,7 +132,7 @@ using Dates: Hour, @dateformat_str lat, lon, alt = 45.0, 10.0, 4000.0 obs = Observer(lat, lon, alt) base_dt = DateTime(2020, 10, 17, 12, 30) - dt_vector = [base_dt + Hour(i) for i = 0:2] + dt_vector = [base_dt + Hour(i) for i in 0:2] @testset "DataFrame with Observer" begin df = DataFrame(datetime = dt_vector, temperature = [20.0, 21.0, 22.0]) @@ -234,18 +240,18 @@ end dt = DateTime(2023, 6, 21, 12, 0, 0) @testset "$alg_name with refraction" for (alg_name, alg) in [ - ("PSA", PSA()), - ("NOAA", NOAA()), - ("Walraven", Walraven()), - ("USNO", USNO()), - ] - @testset "Returns ApparentSolPos with $refr_name" for (refr_name, refr) in [ - ("BENNETT", BENNETT()), - ("HUGHES", HUGHES()), - ("ARCHER", ARCHER()), - ("MICHALSKY", MICHALSKY()), - ("SG2", SG2()), + ("PSA", PSA()), + ("NOAA", NOAA()), + ("Walraven", Walraven()), + ("USNO", USNO()), ] + @testset "Returns ApparentSolPos with $refr_name" for (refr_name, refr) in [ + ("BENNETT", BENNETT()), + ("HUGHES", HUGHES()), + ("ARCHER", ARCHER()), + ("MICHALSKY", MICHALSKY()), + ("SG2", SG2()), + ] res = solar_position(obs, dt, alg, refr) @test res isa ApparentSolPos @test hasfield(typeof(res), :azimuth) @@ -309,7 +315,7 @@ end dt2 = ZonedDateTime(2020, 6, 21, 13, 0, 0, tz"UTC") # mixed vector of DateTime and ZonedDateTime - dts = Union{DateTime,ZonedDateTime}[dt1, dt2] + dts = Union{DateTime, ZonedDateTime}[dt1, dt2] positions = solar_position(obs, dts, PSA()) @test length(positions) == 2 @test positions isa StructVector diff --git a/test/positioning/test-michalsky.jl b/test/positioning/test-michalsky.jl index 24462d3..f9aa75b 100644 --- a/test/positioning/test-michalsky.jl +++ b/test/positioning/test-michalsky.jl @@ -62,9 +62,9 @@ function expected_michalsky_spencer_false() values = [ [32.21780263, 32.24498279, 57.78219737, 57.75501721, 204.91751387], [32.20533693, 32.23252757, 57.79466307, 57.76747243, 204.96379895], - [34.92279261, 34.94787660, 55.07720739, 55.0521234, 169.37618059], + [34.92279261, 34.9478766, 55.07720739, 55.0521234, 169.37618059], [18.63629794, 18.68330498, 71.36370206, 71.31669502, 234.18898285], - [35.75816111, 35.78266275, 54.24183889, 54.21733725, 197.67475020], + [35.75816111, 35.78266275, 54.24183889, 54.21733725, 197.6747502], [-9.52972383, -8.96972383, 99.52972383, 98.96972383, 201.18805829], [66.85774447, 66.87103396, 23.14225553, 23.12896604, 294.91377478], [9.52972383, 9.62043934, 80.47027617, 80.37956066, 201.18805829], diff --git a/test/positioning/test-noaa.jl b/test/positioning/test-noaa.jl index 6430782..2549035 100644 --- a/test/positioning/test-noaa.jl +++ b/test/positioning/test-noaa.jl @@ -28,11 +28,11 @@ res = solar_position(obs, dt, NOAA(), HUGHES(101325.0, 10.0)) # azimuth calculations have small variations - @test isapprox(res.elevation, exp_elev, atol = 1e-8) - @test isapprox(res.zenith, exp_zen, atol = 1e-8) - @test isapprox(res.azimuth, exp_az, atol = 1e-8) - @test isapprox(res.apparent_elevation, exp_app_elev, atol = 1e-8) - @test isapprox(res.apparent_zenith, exp_app_zen, atol = 1e-8) + @test isapprox(res.elevation, exp_elev, atol = 1.0e-8) + @test isapprox(res.zenith, exp_zen, atol = 1.0e-8) + @test isapprox(res.azimuth, exp_az, atol = 1.0e-8) + @test isapprox(res.apparent_elevation, exp_app_elev, atol = 1.0e-8) + @test isapprox(res.apparent_zenith, exp_app_zen, atol = 1.0e-8) end end @@ -54,11 +54,11 @@ res = solar_position(obs, dt, NOAA(nothing), HUGHES(101325.0, 10.0)) # results can differ when delta_t is nothing - @test isapprox(res.elevation, exp_elev, atol = 1e0) - @test isapprox(res.zenith, exp_zen, atol = 1e0) - @test isapprox(res.azimuth, exp_az, atol = 1e0) - @test isapprox(res.apparent_elevation, exp_app_elev, atol = 1e0) - @test isapprox(res.apparent_zenith, exp_app_zen, atol = 1e0) + @test isapprox(res.elevation, exp_elev, atol = 1.0e0) + @test isapprox(res.zenith, exp_zen, atol = 1.0e0) + @test isapprox(res.azimuth, exp_az, atol = 1.0e0) + @test isapprox(res.apparent_elevation, exp_app_elev, atol = 1.0e0) + @test isapprox(res.apparent_zenith, exp_app_zen, atol = 1.0e0) end end @@ -87,12 +87,12 @@ atol = deg2rad(0.1), ) - @test isapprox(res_with_refraction.azimuth, res_no_refraction.azimuth, atol = 1e-10) + @test isapprox(res_with_refraction.azimuth, res_no_refraction.azimuth, atol = 1.0e-10) @test isapprox( res_with_refraction.elevation, res_no_refraction.elevation, - atol = 1e-10, + atol = 1.0e-10, ) - @test isapprox(res_with_refraction.zenith, res_no_refraction.zenith, atol = 1e-10) + @test isapprox(res_with_refraction.zenith, res_no_refraction.zenith, atol = 1.0e-10) end end diff --git a/test/positioning/test-observer.jl b/test/positioning/test-observer.jl index d91addf..7137a66 100644 --- a/test/positioning/test-observer.jl +++ b/test/positioning/test-observer.jl @@ -2,8 +2,8 @@ @testset "Horizon as degrees => arcminutes" begin obs = Observer(45.0, 10.0, altitude = 100.0, horizon = 0 => 34) - @test obs.horizon ≈ 34 / 60 atol = 1e-10 - @test obs.horizon ≈ 0.5666666666666667 atol = 1e-10 + @test obs.horizon ≈ 34 / 60 atol = 1.0e-10 + @test obs.horizon ≈ 0.5666666666666667 atol = 1.0e-10 end @testset "Horizon default value" begin @@ -17,11 +17,11 @@ @testset "Horizon with different arcminutes" begin # 34 arcminutes obs1 = Observer(45.0, 10.0, horizon = 0 => 34) - @test obs1.horizon ≈ 0.5666666666666667 atol = 1e-10 + @test obs1.horizon ≈ 0.5666666666666667 atol = 1.0e-10 # 1 degree 30 arcminutes obs2 = Observer(45.0, 10.0, horizon = 1 => 30) - @test obs2.horizon ≈ 1.5 atol = 1e-10 + @test obs2.horizon ≈ 1.5 atol = 1.0e-10 # negative horizon as a decimal value h = -0.5666666666666667 @@ -59,14 +59,14 @@ @test obs1.latitude == 45.0 @test obs1.longitude == 10.0 @test obs1.altitude == 100.0 - @test obs1.horizon ≈ 0.5666666666666667 atol = 1e-10 + @test obs1.horizon ≈ 0.5666666666666667 atol = 1.0e-10 # Test with different arcminute values obs2 = Observer(45.0, 10.0, 100.0, 1 => 30) - @test obs2.horizon ≈ 1.5 atol = 1e-10 + @test obs2.horizon ≈ 1.5 atol = 1.0e-10 # Test with negative horizon using Pair obs3 = Observer(45.0, 10.0, 100.0, -1 => 0) - @test obs3.horizon ≈ -1.0 atol = 1e-10 + @test obs3.horizon ≈ -1.0 atol = 1.0e-10 end end diff --git a/test/positioning/test-psa.jl b/test/positioning/test-psa.jl index 0898343..3263b15 100644 --- a/test/positioning/test-psa.jl +++ b/test/positioning/test-psa.jl @@ -22,9 +22,9 @@ end res = solar_position(obs, dt, PSA(i)) - @test isapprox(res.elevation, exp_elev, atol = 1e-8) - @test isapprox(res.zenith, exp_zen, atol = 1e-8) - @test isapprox(res.azimuth, exp_az, atol = 1e-8) + @test isapprox(res.elevation, exp_elev, atol = 1.0e-8) + @test isapprox(res.zenith, exp_zen, atol = 1.0e-8) + @test isapprox(res.azimuth, exp_az, atol = 1.0e-8) end end diff --git a/test/positioning/test-spa.jl b/test/positioning/test-spa.jl index 21c74a0..8afe006 100644 --- a/test/positioning/test-spa.jl +++ b/test/positioning/test-spa.jl @@ -19,11 +19,11 @@ # SPA includes refraction correction res = solar_position(obs, dt, SPA()) - @test isapprox(res.elevation, row.elevation, atol = 1e-8) - @test isapprox(res.zenith, row.zenith, atol = 1e-8) - @test isapprox(res.azimuth, row.azimuth, atol = 1e-8) - @test isapprox(res.apparent_elevation, row.apparent_elevation, atol = 1e-8) - @test isapprox(res.apparent_zenith, row.apparent_zenith, atol = 1e-8) + @test isapprox(res.elevation, row.elevation, atol = 1.0e-8) + @test isapprox(res.zenith, row.zenith, atol = 1.0e-8) + @test isapprox(res.azimuth, row.azimuth, atol = 1.0e-8) + @test isapprox(res.apparent_elevation, row.apparent_elevation, atol = 1.0e-8) + @test isapprox(res.apparent_zenith, row.apparent_zenith, atol = 1.0e-8) end end @@ -38,9 +38,9 @@ res = solar_position(obs, dt, SPA(nothing, 101325.0, 12.0, 0.5667)) # results can differ when delta_t is nothing - @test isapprox(res.elevation, row.elevation, atol = 1e0) - @test isapprox(res.zenith, row.zenith, atol = 1e0) - @test isapprox(res.azimuth, row.azimuth, atol = 1e0) + @test isapprox(res.elevation, row.elevation, atol = 1.0e0) + @test isapprox(res.zenith, row.zenith, atol = 1.0e0) + @test isapprox(res.azimuth, row.azimuth, atol = 1.0e0) end end @@ -50,7 +50,7 @@ res = solar_position(obs, times[1], SPA()) # refraction correction should be minimal - @test isapprox(res.elevation, res.apparent_elevation, atol = 1e-3) + @test isapprox(res.elevation, res.apparent_elevation, atol = 1.0e-3) end @testset "Custom atmospheric parameters" begin @@ -66,10 +66,10 @@ @test !isapprox( res_default.apparent_elevation, res_custom.apparent_elevation, - atol = 1e-8, + atol = 1.0e-8, ) - @test isapprox(res_default.elevation, res_custom.elevation, atol = 1e-10) + @test isapprox(res_default.elevation, res_custom.elevation, atol = 1.0e-10) end @testset "Multiple times at same location" begin @@ -78,7 +78,7 @@ # generate multiple timestamps base_dt = DateTime(2023, 6, 21, 0, 0, 0) - times = [base_dt + Hour(h) for h = 0:23] + times = [base_dt + Hour(h) for h in 0:23] results = [solar_position(obs, dt, SPA()) for dt in times] # verify we got 24 results and they're reasonable @@ -192,9 +192,9 @@ @testset "SPA result_type with NoRefraction" begin # Explicitly test the result_type dispatch @test SolarPosition.Positioning.result_type(SPA, NoRefraction, Float64) == - SolPos{Float64} + SolPos{Float64} @test SolarPosition.Positioning.result_type(SPA, DefaultRefraction, Float64) == - ApparentSolPos{Float64} + ApparentSolPos{Float64} @test SolarPosition.Positioning.result_type( SPA, SolarPosition.Refraction.HUGHES, diff --git a/test/positioning/test-usno.jl b/test/positioning/test-usno.jl index 13b3e3f..a01ceec 100644 --- a/test/positioning/test-usno.jl +++ b/test/positioning/test-usno.jl @@ -19,9 +19,9 @@ res = solar_position(obs, dt, USNO()) - @test isapprox(res.elevation, exp_elev, atol = 1e-8) - @test isapprox(res.zenith, exp_zen, atol = 1e-8) - @test isapprox(res.azimuth, exp_az, atol = 1e-8) + @test isapprox(res.elevation, exp_elev, atol = 1.0e-8) + @test isapprox(res.zenith, exp_zen, atol = 1.0e-8) + @test isapprox(res.azimuth, exp_az, atol = 1.0e-8) end end @@ -39,9 +39,9 @@ res = solar_position(obs, dt, USNO(67.0, 2)) - @test isapprox(res.elevation, exp_elev, atol = 1e-8) - @test isapprox(res.zenith, exp_zen, atol = 1e-8) - @test isapprox(res.azimuth, exp_az, atol = 1e-8) + @test isapprox(res.elevation, exp_elev, atol = 1.0e-8) + @test isapprox(res.zenith, exp_zen, atol = 1.0e-8) + @test isapprox(res.azimuth, exp_az, atol = 1.0e-8) end end @@ -60,9 +60,9 @@ res = solar_position(obs, dt, USNO(nothing, 1)) # results can differ when delta_t is nothing - @test isapprox(res.elevation, exp_elev, atol = 1e0) - @test isapprox(res.zenith, exp_zen, atol = 1e0) - @test isapprox(res.azimuth, exp_az, atol = 1e0) + @test isapprox(res.elevation, exp_elev, atol = 1.0e0) + @test isapprox(res.zenith, exp_zen, atol = 1.0e0) + @test isapprox(res.azimuth, exp_az, atol = 1.0e0) end end diff --git a/test/positioning/test-walraven.jl b/test/positioning/test-walraven.jl index c253807..6a3678f 100644 --- a/test/positioning/test-walraven.jl +++ b/test/positioning/test-walraven.jl @@ -17,9 +17,9 @@ end res = solar_position(obs, dt, Walraven()) - @test isapprox(res.elevation, exp_elev, atol = 1e-8) - @test isapprox(res.zenith, exp_zen, atol = 1e-8) - @test isapprox(res.azimuth, exp_az, atol = 1e-8) + @test isapprox(res.elevation, exp_elev, atol = 1.0e-8) + @test isapprox(res.zenith, exp_zen, atol = 1.0e-8) + @test isapprox(res.azimuth, exp_az, atol = 1.0e-8) end @testset "Walraven edge cases" begin diff --git a/test/refraction/test-refraction.jl b/test/refraction/test-refraction.jl index dfdbf2c..c5a53ae 100644 --- a/test/refraction/test-refraction.jl +++ b/test/refraction/test-refraction.jl @@ -16,7 +16,7 @@ expected = Dict( 0.1875788, 0.13769375, 0.08750312, - 0.00000000, + 0.0, ], "Archer" => [ 0.76852998, @@ -39,8 +39,8 @@ expected = Dict( -0.000022424, ], "Michalsky" => [ - 0.5600000, - 0.560000000, + 0.56, + 0.56, 0.56038823, 0.39595124, 0.19147691, @@ -51,22 +51,22 @@ expected = Dict( "SG2" => [ 0.328796332, 0.548029502, - 0.481177890, + 0.48117789, 0.361009325, 0.188613883, 0.139390534, 0.089783442, - -0.000032010, + -0.00003201, ], "SPA" => [ - 0.00000000, + 0.0, 0.5760885771, 0.481185828, 0.361012918, 0.188614492, 0.139390797, 0.0897835168, - -0.000032010, + -0.00003201, ], ) @@ -88,14 +88,14 @@ elevations = test_elevation_angles() @testset "Scalar computation" begin for (i, elev) in enumerate(elevations) result = refraction(algorithm, elev) - @test result ≈ expected[i] atol = 1e-8 + @test result ≈ expected[i] atol = 1.0e-8 end end @testset "Vectorized computation" begin results = refraction.(Ref(algorithm), elevations) for (i, res) in enumerate(results) - @test res ≈ expected[i] atol = 1e-8 + @test res ≈ expected[i] atol = 1.0e-8 end end end diff --git a/test/utilities/expected-values.jl b/test/utilities/expected-values.jl index b70f394..d7999b7 100644 --- a/test/utilities/expected-values.jl +++ b/test/utilities/expected-values.jl @@ -7,7 +7,7 @@ using Dates function parse_zdt(s::AbstractString) dot_idx = findfirst('.', s) if dot_idx !== nothing - truncated = s[1:(dot_idx+3)] + truncated = s[1:(dot_idx + 3)] dt = DateTime(truncated, "yyyy-mm-dd HH:MM:SS.s") else dt = DateTime(s, "yyyy-mm-dd HH:MM:SS") diff --git a/test/utilities/test-srt.jl b/test/utilities/test-srt.jl index a8d741c..c2ab79c 100644 --- a/test/utilities/test-srt.jl +++ b/test/utilities/test-srt.jl @@ -38,6 +38,7 @@ function test_srt_result(result, row, to_datetime_fn) actual = datetime2unix(to_datetime_fn(getproperty(result, field))) @test actual ≈ expected atol = 1.0 end + return end @testset "SPA" begin @@ -45,7 +46,7 @@ end fields = (:sunset, :sunrise, :transit) @testset "DateTime input - Location: $(row.location), Date: $(row.date)" for row in - eachrow(df) + eachrow(df) obs = Observer(row.latitude, row.longitude) dt_input = DateTime(row.date) result = transit_sunrise_sunset(obs, dt_input, SPA(delta_t = row.delta_t)) @@ -57,7 +58,7 @@ end end @testset "Date input - Location: $(row.location), Date: $(row.date)" for row in - eachrow(df) + eachrow(df) obs = Observer(row.latitude, row.longitude) date_input = Date(row.date) result = transit_sunrise_sunset(obs, date_input, SPA(delta_t = row.delta_t)) @@ -69,9 +70,9 @@ end end @testset "ZonedDateTime input - Location: $(row.location), Date: $(row.date)" for row in - eachrow( - df, - ) + eachrow( + df, + ) obs = Observer(row.latitude, row.longitude) dt_utc = DateTime(row.date) zdt_input = ZonedDateTime(dt_utc, row.timezone; from_utc = true) @@ -98,10 +99,10 @@ end result_polar_day = @test_logs (:warn, r"Sun does not rise or set.*polar day \(sun above horizon\)") transit_sunrise_sunset( - OBS_POLAR, - SUMMER_DATETIME, - SPA(), - ) + OBS_POLAR, + SUMMER_DATETIME, + SPA(), + ) @test result_polar_day.transit isa DateTime @test result_polar_day.transit == result_polar_day.sunrise @@ -111,10 +112,10 @@ end zdt_winter = ZonedDateTime(WINTER_DATETIME, TZ_OSLO; from_utc = true) result_zdt_polar_night = @test_logs (:warn, r"Sun does not rise or set.*polar night") transit_sunrise_sunset( - OBS_POLAR, - zdt_winter, - SPA(), - ) + OBS_POLAR, + zdt_winter, + SPA(), + ) @test result_zdt_polar_night.transit isa ZonedDateTime @test timezone(result_zdt_polar_night.transit) == TZ_OSLO @@ -139,19 +140,19 @@ end # This should give the same result as the default (which is delta_t = 67.0) # but different from delta_t = 0.0 @test result_nothing.transit != result_zero.transit || - result_nothing.sunrise != result_zero.sunrise || - result_nothing.sunset != result_zero.sunset + result_nothing.sunrise != result_zero.sunrise || + result_nothing.sunset != result_zero.sunset @test result_auto.transit != result_zero.transit || - result_auto.sunrise != result_zero.sunrise || - result_auto.sunset != result_zero.sunset + result_auto.sunrise != result_zero.sunrise || + result_auto.sunset != result_zero.sunset @test result_zero.transit != result_custom.transit || - result_zero.sunrise != result_custom.sunrise || - result_zero.sunset != result_custom.sunset + result_zero.sunrise != result_custom.sunrise || + result_zero.sunset != result_custom.sunset @test abs(datetime2unix(result_auto.transit) - datetime2unix(result_zero.transit)) < - 300 + 300 @test abs( datetime2unix(result_auto.sunrise) - datetime2unix(result_custom.sunrise), ) < 300 @@ -173,9 +174,9 @@ end @testset "$(func) before/after event" begin @test func(OBS_NEW_YORK, before_time, SPA()) == getfield(result, field) @test func(OBS_NEW_YORK, after_time, SPA()) == - getfield(next_day_result, field) + getfield(next_day_result, field) @test func(OBS_NEW_YORK, getfield(result, field), SPA()) == - getfield(next_day_result, field) + getfield(next_day_result, field) end @testset "$(func) Date input" begin @@ -184,7 +185,7 @@ end @testset "$(func) different location" begin @test func(OBS_LONDON, DateTime(TEST_DATE), SPA()) == - getfield(london_result, field) + getfield(london_result, field) end @testset "$(func) ZonedDateTime input" begin @@ -228,14 +229,14 @@ end @testset "$(func) before/after event" begin @test func(OBS_NEW_YORK, after_time, SPA()) == getfield(result, field) @test func(OBS_NEW_YORK, before_time, SPA()) == - getfield(prev_day_result, field) + getfield(prev_day_result, field) @test func(OBS_NEW_YORK, getfield(result, field), SPA()) == - getfield(prev_day_result, field) + getfield(prev_day_result, field) end @testset "$(func) Date input at midnight" begin @test func(OBS_NEW_YORK, TEST_DATE, SPA()) == - getfield(prev_day_result, field) + getfield(prev_day_result, field) end @testset "$(func) ZonedDateTime input" begin