diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9d1e5ef4d..07e5f7074 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -29,11 +29,6 @@ jobs: pip install -r test_requirements.txt pip install -r requirements.txt - - name: Set up pysat - run: | - mkdir pysatData - python -c "import pysat; pysat.params['data_dirs'] = 'pysatData'" - - name: Check documentation build run: sphinx-build -E -b html docs dist/docs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b7db83170..b75e83300 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,20 +5,39 @@ name: Pytest with Flake8 -on: [pull_request, push] +on: + pull_request: + push: + schedule: + - cron: "0 3 * * 1" # Runs 03:00 UT on Mondays jobs: build: strategy: fail-fast: false matrix: - os: [ubuntu-latest] - python-version: ["3.9", "3.10"] - numpy_ver: [latest] + os: ["ubuntu-latest"] + python-version: ["3.9", "3.10", "3.11", "3.12"] + numpy_ver: ["latest"] include: - - python-version: "3.8" - numpy_ver: "1.19" + # Support different GA Mac environments + - python-version: "3.9" + os: "macos-13" + numpy_ver: "latest" + - python-version: "3.12" + os: "macos-13" + numpy_ver: "latest" + - python-version: "3.9" + os: "macos-latest" + numpy_ver: "latest" + - python-version: "3.12" + os: "macos-latest" + numpy_ver: "latest" + # NEP29 compliance settings + - python-version: "3.10" + numpy_ver: "1.25" os: "ubuntu-latest" + test_config: "NEP29" name: Python ${{ matrix.python-version }} on ${{ matrix.os }} with numpy ${{ matrix.numpy_ver }} runs-on: ${{ matrix.os }} @@ -29,6 +48,16 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Install Windows-specific dependencies for non-pip install + if: ${{ matrix.os == 'windows-latest' }} + run: | + choco install ninja mingw + choco install rtools --no-progress + echo "c:\rtools40\ucrt64\bin;" >> $env:GITHUB_PATH + gfortran --version + pip install flake8 meson-python pytest pytest-cov pytest-xdist scipy + pip install "numpy>=1.19.5" + - name: Install standard dependencies run: | python -m pip install --upgrade pip @@ -51,14 +80,70 @@ jobs: - name: Evaluate complexity run: flake8 . --count --exit-zero --max-complexity=10 --statistics - - name: Run OMMBV setup.py + - name: Install on Linux + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + pip install --upgrade-strategy only-if-needed . + + - name: Install on MacOS-13 + if: ${{ matrix.os == 'macos-13' }} run: | - python setup.py develop + brew reinstall gcc@14 + CC=/usr/local/bin/gcc-14 pip install --upgrade-strategy only-if-needed . - - name: Run unit and integration tests - run: pytest --cov=OMMBV/ + - name: Install on MacOS-Latest + if: ${{ matrix.os == 'macos-latest' }} + run: | + brew reinstall gcc@14 + CC=/opt/homebrew/bin/gcc-14 pip install --upgrade-strategy only-if-needed . + + - name: Install on Windows + if: ${{ matrix.os == 'windows-latest' }} + run: | + meson setup build + ninja -j 2 -C build + cd build + meson install --destdir=${{ env.Python3_ROOT_DIR }} - - name: Publish results to coveralls - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: coveralls --rcfile=setup.cfg --service=github + - name: Run unit and integration tests Mac/Linux + if: ${{ matrix.os != 'windows-latest' }} + run: | + rm -rf ./OMMBV + mkdir new_dir + cd new_dir + coverage run -m --source=OMMBV --omit=__init__.py pytest ../tests + coverage report + coverage xml + mkdir ../OMMBV + mv coverage.xml ../OMMBV/coverage.xml + + - name: Run unit and integration tests on Windows + if: ${{ matrix.os == 'windows-latest' }} + run: | + rm ./OMMBV -r -force + cd .. + pytest ./OMMBV/tests -v --cov + + coverage report + coverage xml + mv coverage.xml .\OMMBV\. + + - name: Publish results to coveralls upon success + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: run=${{ join(matrix.*, '-') }} + parallel: true + format: cobertura + + finish: + name: Finish Coverage Analysis + needs: build + if: ${{ always() }} + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml index defa293da..5b3ff087f 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,6 +5,12 @@ # Required version: 2 +build: + os: ubuntu-22.04 + tools: + python: "3.10" + + # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py @@ -20,7 +26,6 @@ formats: # Optionally set the version of Python and requirements # required to build your docs python: - version: 3.7 install: - requirements: docs/requirements.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index b204dd839..8890f6a5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.1.0] - 2025-04-07 +- Switched away from distutils to Meson for build system +- Updated coupling to coveralls +- Updated package version for security issue in sphinx +- Updated online unit testing +- Updated to IGRF14 +- Updated documentation +- Updated unit tests to latest standards + ## [1.0.1] - 2022-01-04 - Added pyproject.toml to support systems without numpy. - Modified manifest.ini to include version.txt diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 4ef65bf96..f0cf632ce 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -4,10 +4,10 @@ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. +our community a harassment-free experience for everyone, regardless of age, +body size, disability, ethnicity, gender identity and expression, level of +experience, nationality, personal appearance, race, religion, or sexual +identity and orientation. ## Our Standards @@ -23,13 +23,13 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or - advances + advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic - address, without explicit permission + address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a - professional setting + professional setting ## Our Responsibilities @@ -48,18 +48,19 @@ threatening, offensive, or harmful. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. Representation of a +project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at pysat.developers@gmail.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +reported by contacting the project team at contact@cosmicstudio.io. The +pysat project team will review and investigate all complaints, and will respond +in a way that it deems appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an +incident. Further details of specific enforcement policies may be posted +separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other @@ -67,10 +68,15 @@ members of the project's leadership. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +[https://contributor-covenant.org/version/1/4][version] -[homepage]: https://www.contributor-covenant.org +## FAQ For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq +[https://www.contributor-covenant.org/faq][faq] + +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/4/ +[faq]: https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8836c85a8..4b99e203e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,87 +1,173 @@ Contributing ============ -Bug reports, feature suggestions and other contributions are greatly -appreciated! Pysat is a community-driven project and welcomes both feedback and -contributions. +Bug reports, feature suggestions, and other contributions are greatly +appreciated! Short version -============= +------------- + +* Submit bug reports, feature requests, and questions at + [GitHub](https://github.com/CosmicStudioSoftware/OMMBV/issues) -* Submit bug reports and feature requests at `GitHub `_ * Make pull requests to the ``develop`` branch +Issues +------ + +Bug reports, questions, and feature requests should all be made as GitHub +Issues. Templates are provided for each type of issue, to help you include +all the necessary information. + +Questions +^^^^^^^^^ + +Not sure how something works? Ask away! The more information you provide, the +easier the question will be to answer. + Bug reports -=========== +^^^^^^^^^^^ -When `reporting a bug `_ please +When [reporting a bug](https://github.com/CosmicStudioSoftware/OMMBV/issues) please include: * Your operating system name and version + * Any details about your local setup that might be helpful in troubleshooting + * Detailed steps to reproduce the bug Feature requests and feedback -============================= +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The best way to send feedback is to file an issue at -`GitHub `_. +The best way to send feedback is to file an +[issue](https://github.com/CosmicStudioSoftware/OMMBV/issues). -If you are proposing a feature: +If you are proposing a new feature or a change in something that already exists: * Explain in detail how it would work. + * Keep the scope as narrow as possible, to make it easier to implement. + * Remember that this is a volunteer-driven project, and that code contributions are welcome :) Development -=========== +----------- + +To set up `OMMBV` for local development: -To set up `pysat` for local development: +1. [Fork OMMBV on GitHub](https://github.com/CosmicStudioSoftware/OMMBV/fork). -1. `Fork pysat on GitHub `_. -2. Clone your fork locally:: +2. Clone your fork locally: - git clone git@github.com:your_name_here/pysatMagVect.git + ``` + git clone git@github.com:your_name_here/OMMBV.git + ``` -3. Create a branch for local development:: +3. Create a branch for local development: + ``` git checkout -b name-of-your-bugfix-or-feature + ``` + + Now you can make your changes locally. + - Now you can make your changes locally. Tests should be added to the - appropriately named file in ``OMMBV/tests``. - 4. When you're done making changes, run all the checks to ensure that nothing - is broken on your local system:: - - nosetests -vs pysatMagVect + is broken on your local system, as well as check for flake8 compliance: + + ``` + pytest + ``` + +5. You should also check for flake8 style compliance: + + ``` + flake8 . --count --select=D,E,F,H,W --show-source --statistics + ``` -5. Update/add documentation (in ``docs``), if relevant + Note that pysat uses the `flake-docstrings` and `hacking` packages to ensure + standards in docstring formatting. -5. Commit your changes and push your branch to GitHub:: +6. Update/add documentation (in ``docs``). Even if you don't think it's + relevant, check to see if any existing examples have changed. - git add . - git commit -m "Brief description of your changes" - git push origin name-of-your-bugfix-or-feature +7. Add your name to the .zenodo.json file as an author + +8. Commit your changes: + ``` + git add . + git commit -m "AAA: Brief description of your changes" + ``` + Where AAA is a standard shorthand for the type of change (e.g., BUG or DOC). + `pysat` follows the [numpy development workflow](https://numpy.org/doc/stable/dev/development_workflow.html), + see the discussion there for a full list of this shorthand notation. + +9. Once you are happy with the local changes, push to GitHub: + ``` + git push origin name-of-your-bugfix-or-feature + ``` + Note that each push will trigger the Continuous Integration workflow. + +10. Submit a pull request through the GitHub website. Pull requests should be + made to the ``develop`` branch. Note that automated tests will be run on + GitHub Actions, but these must be initialized by a member of the pysat team + for first time contributors. -6. Submit a pull request through the GitHub website. Pull requests should be - made to the ``develop`` branch. Pull Request Guidelines ----------------------- If you need some code review or feedback while you're developing the code, just -make a pull request. +make a pull request. Pull requests should be made to the ``develop`` branch. For merging, you should: 1. Include an example for use 2. Add a note to ``CHANGELOG.md`` about the changes -3. Ensure that all checks passed (current checks include Scrutinizer, Travis-CI, - and Coveralls) [1]_ - -.. [1] If you don't have all the necessary Python versions available locally or - have trouble building all the testing environments, you can rely on - Travis to run the tests for each change you add in the pull request. - Because testing here will delay tests by other developers, please ensure - that the code passes all tests on your local system first. +3. Update the author list in ``zenodo.json``, if applicable +4. Ensure that all checks passed (current checks include GitHub Actions, + Coveralls and ReadTheDocs) + +If you don't have all the necessary Python versions available locally or have +trouble building all the testing environments, you can rely on GitHub Actions to +run the tests for each change you add in the pull request. Because testing here +will delay tests by other developers, please ensure that the code passes all +tests on your local system first. + + +Project Style Guidelines +------------------------ + +In general, OMMBV follows PEP8 and numpydoc guidelines. Pytest runs the unit +and integration tests, flake8 checks for style, and sphinx-build performs +documentation tests. However, there are certain additional style elements that +have been adopted to ensure the project maintains a consistent coding style. +These include: + +* Line breaks should occur before a binary operator (ignoring flake8 W503) +* Combine long strings using `join` +* Preferably break long lines on open parentheses rather than using `\` +* Use no more than 80 characters per line +* Several dependent packages have common nicknames, including: + * `import datetime as dt` + * `import numpy as np` + * `import pandas as pds` + * `import xarray as xr` +* When incrementing a timestamp, use `dt.timedelta` instead of `pds.DateOffset` + when possible to reduce program runtime +* All classes should have `__repr__` and `__str__` functions +* Docstrings use `Note` instead of `Notes` +* Try to avoid creating a try/except statement where except passes +* Use setup_method (or setup_class) and teardown_method (or teardown_class) in + test classes +* Use pytest parametrize in test classes when appropriate +* Provide testing class methods with informative failure statements and + descriptive, one-line docstrings +* Block and inline comments should use proper English grammar and punctuation + with the exception of single sentences in a block, which may then omit the + final period +* When casting is necessary, use `np.int64` and `np.float64` to ensure operating + system agnosticism + diff --git a/MANIFEST.in b/MANIFEST.in index 356a2861d..c90dfe113 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ include LICENSE -include CONTRIBUTING.md +include CHANGELOG.md include OMMBV/version.txt +include meson.build +include README.md diff --git a/OMMBV/__init__.py b/OMMBV/__init__.py index 22d372e05..568e2059d 100644 --- a/OMMBV/__init__.py +++ b/OMMBV/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """init routine for OMMBV.""" -__version__ = '1.0.1' +__version__ = '1.1.0' try: from OMMBV import igrf @@ -22,4 +22,7 @@ from OMMBV import heritage -__all__ = ['heritage', 'satellite', 'trace', 'trans', 'utils', 'vector'] +__all__ = ['igrf', 'fortran_coords', 'sources', 'satellite', + 'trace', 'trans', 'utils', 'vector', 'heritage'] + +print("OMMBV brought to you by Cosmic Studio.") \ No newline at end of file diff --git a/OMMBV/_core.py b/OMMBV/_core.py index 494b76f43..471a39be3 100644 --- a/OMMBV/_core.py +++ b/OMMBV/_core.py @@ -10,7 +10,8 @@ from OMMBV import vector -def calculate_geomagnetic_basis(latitude, longitude, altitude, datetimes): +def calculate_geomagnetic_basis(latitude, longitude, altitude, datetimes, + **kwargs): """Calculate local geomagnetic basis vectors and mapping scalars. Parameters @@ -58,7 +59,8 @@ def calculate_geomagnetic_basis(latitude, longitude, altitude, datetimes): mx, my, mz, info) = calculate_mag_drift_unit_vectors_ecef(latitude, longitude, altitude, datetimes, - full_output=True) + full_output=True, + **kwargs) d_zon_mag = np.sqrt(info['d_zon_x']**2 + info['d_zon_y']**2 + info['d_zon_z']**2) @@ -239,7 +241,7 @@ def calculate_mag_drift_unit_vectors_ecef(latitude, longitude, altitude, for key in depd.keys(): if depd[key] is not None: wstr = " ".join([key, "is deprecated, non-functional,", - "and will be removed after OMMBV v1.0.0."]) + "and will be removed after OMMBV v1.2."]) warnings.warn(wstr, DeprecationWarning, stacklevel=2) # Account for potential alternate magnetic field and step functions. @@ -348,6 +350,7 @@ def calculate_mag_drift_unit_vectors_ecef(latitude, longitude, altitude, return_geodetic=True, ecef_input=True, **step_kwargs) + if centered_diff: # Negative step ecef_xz2, ecef_yz2, ecef_zz2 = (ecef_x - step_size * tzx, @@ -736,7 +739,7 @@ def scalars_for_mapping_ion_drifts(glats, glons, alts, dates, for key in depd.keys(): if depd[key] is not None: wstr = " ".join([key, "is deprecated, non-functional,", - "and will be removed after OMMBV v1.0.0."]) + "and will be removed after OMMBV v1.2."]) warnings.warn(wstr, DeprecationWarning, stacklevel=2) ecef_xs, ecef_ys, ecef_zs = trans.geodetic_to_ecef(glats, glons, alts) @@ -864,7 +867,7 @@ def geocentric_to_ecef(latitude, longitude, altitude): .. deprecated:: 1.0.0 Function moved to `OMMBV.trans.geocentric_to_ecef`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -883,7 +886,7 @@ def geocentric_to_ecef(latitude, longitude, altitude): """ warnings.warn("".join(["Function moved to `OMMBV.trans`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return trans.geocentric_to_ecef(latitude, longitude, altitude) @@ -894,7 +897,7 @@ def ecef_to_geocentric(x, y, z, ref_height=trans.earth_geo_radius): .. deprecated:: 1.0.0 Function moved to `OMMBV.trans.ecef_to_geocentric`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -916,7 +919,7 @@ def ecef_to_geocentric(x, y, z, ref_height=trans.earth_geo_radius): """ warnings.warn("".join(["Function moved to `OMMBV.trans`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return trans.ecef_to_geocentric(x, y, z, ref_height=ref_height) @@ -927,7 +930,7 @@ def geodetic_to_ecef(latitude, longitude, altitude): .. deprecated:: 1.0.0 Function moved to `OMMBV.trans.geodetic_to_ecef`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -946,7 +949,7 @@ def geodetic_to_ecef(latitude, longitude, altitude): """ warnings.warn("".join(["Function moved to `OMMBV.trans`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return trans.geodetic_to_ecef(latitude, longitude, altitude) @@ -957,12 +960,12 @@ def ecef_to_geodetic(*args, **kwargs): .. deprecated:: 1.0.0 Function moved to `OMMBV.trans.geodetic_to_ecef`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. """ warnings.warn("".join(["Function moved to `OMMBV.trans`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return trans.ecef_to_geodetic(*args, **kwargs) @@ -973,7 +976,7 @@ def python_ecef_to_geodetic(x, y, z, method='closed'): .. deprecated:: 1.0.0 Function moved to `OMMBV.trans.geodetic_to_ecef`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -998,7 +1001,7 @@ def python_ecef_to_geodetic(x, y, z, method='closed'): """ warnings.warn("".join(["Function moved to `OMMBV.trans`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) if method is None: @@ -1015,7 +1018,7 @@ def enu_to_ecef_vector(east, north, up, glat, glong): .. deprecated:: 1.0.0 Function moved to `OMMBV.vector.enu_to_ecef`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Position of vector in geospace may be specified in either geocentric or geodetic coordinates, with corresponding expression @@ -1042,7 +1045,7 @@ def enu_to_ecef_vector(east, north, up, glat, glong): """ warnings.warn("".join(["Function moved to `OMMBV.vector`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return vector.enu_to_ecef(east, north, up, glat, glong) @@ -1053,7 +1056,7 @@ def ecef_to_enu_vector(x, y, z, glat, glong): .. deprecated:: 1.0.0 Function moved to `OMMBV.vector.ecef_to_enu`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Position of vector in geospace may be specified in either geocentric or geodetic coordinates, with corresponding expression @@ -1080,7 +1083,7 @@ def ecef_to_enu_vector(x, y, z, glat, glong): """ warnings.warn("".join(["Function moved to `OMMBV.vector`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return vector.ecef_to_enu(x, y, z, glat, glong) @@ -1091,7 +1094,7 @@ def project_ECEF_vector_onto_basis(x, y, z, xx, xy, xz, yx, yy, yz, zx, zy, zz): .. deprecated:: 1.0.0 Function moved to `OMMBV.vector.project_onto_basis`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -1116,7 +1119,7 @@ def project_ECEF_vector_onto_basis(x, y, z, xx, xy, xz, yx, yy, yz, zx, zy, zz): """ warnings.warn("".join(["Function moved to `OMMBV.vector`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return vector.project_onto_basis(x, y, z, xx, xy, xz, yx, yy, yz, @@ -1128,7 +1131,7 @@ def normalize_vector(x, y, z): .. deprecated:: 1.0.0 Function moved to `OMMBV.vector.normalize`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -1147,7 +1150,7 @@ def normalize_vector(x, y, z): """ warnings.warn("".join(["Function moved to `OMMBV.vector`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return vector.normalize(x, y, z) @@ -1158,7 +1161,7 @@ def cross_product(x1, y1, z1, x2, y2, z2): .. deprecated:: 1.0.0 Function moved to `OMMBV.vector.cross_product`, this wrapper will - be removed after v1.0.0. + be removed after v1.2. Parameters ---------- @@ -1183,7 +1186,7 @@ def cross_product(x1, y1, z1, x2, y2, z2): """ warnings.warn("".join(["Function moved to `OMMBV.vector`, deprecated ", - "wrapper will be removed after OMMBV v1.0.0."]), + "wrapper will be removed after OMMBV v1.2."]), DeprecationWarning, stacklevel=2) return vector.cross_product(x1, y1, z1, x2, y2, z2) diff --git a/OMMBV/heritage.py b/OMMBV/heritage.py index b27137f3d..3d57036b5 100644 --- a/OMMBV/heritage.py +++ b/OMMBV/heritage.py @@ -184,12 +184,12 @@ def apex_edge_lengths_via_footpoint(*args, **kwargs): .. deprecated:: 1.0.0 Function moved to `apex_distance_after_footpoint_step`, - this wrapper will be removed after v1.0.0. + this wrapper will be removed after v1.2. """ estr = ''.join(['This method now called `apex_distance_after_', 'footpoint_step`. Wrapper will be removed after OMMBV ', - 'v1.0.0.']) + 'v1.2.']) warnings.warn(estr, DeprecationWarning, stacklevel=2) apex_distance_after_footpoint_step(*args, **kwargs) return diff --git a/OMMBV/tests/__init__.py b/OMMBV/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/OMMBV/trace.py b/OMMBV/trace.py index c3ce7398c..9ebc248db 100644 --- a/OMMBV/trace.py +++ b/OMMBV/trace.py @@ -17,7 +17,7 @@ def _stub_fcn(): # RTD doesn't support Fortran. from OMMBV import igrf from OMMBV import sources - ommbv_mag_fcn = igrf.igrf13syn + ommbv_mag_fcn = igrf.igrf14syn ommbv_step_fcn = sources.igrf_step except Exception: ommbv_mag_fcn, ommbv_step_fcn = _stub_fcn, _stub_fcn @@ -498,8 +498,8 @@ def magnetic_vector(x, y, z, dates, normalize=False, mag_fcn=ommbv_mag_fcn): If True, return unit vector. (default=False) mag_fcn : function Function that returns magnetic field from a model. - The call signature must match that of `igrf.igrf13syn`. - (default=OMMBV.igrf.igrf13syn) + The call signature must match that of `igrf.igrf14syn`. + (default=OMMBV.igrf.igrf14syn) Returns ------- diff --git a/OMMBV/version.txt b/OMMBV/version.txt index 7f207341d..1cc5f657e 100644 --- a/OMMBV/version.txt +++ b/OMMBV/version.txt @@ -1 +1 @@ -1.0.1 \ No newline at end of file +1.1.0 \ No newline at end of file diff --git a/README.md b/README.md index 512217c5c..6b2c0f707 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ # Orthogonal Multipole Magnetic Basis Vectors (OMMBV) -[![Build Status](https://github.com/rstoneback/OMMBV/actions/workflows/main.yml/badge.svg)](https://github.com/rstoneback/OMMBV/actions/workflows/main.yml/badge.svg) -[![Coverage Status](https://coveralls.io/repos/github/rstoneback/OMMBV/badge.svg?branch=main)](https://coveralls.io/github/rstoneback/OMMBV?branch=main) +[![Build Status](https://github.com/CosmicStudioSoftware/OMMBV/actions/workflows/main.yml/badge.svg)](https://github.com/CosmicStudioSoftware/OMMBV/actions/workflows/main.yml/badge.svg) +[![Coverage Status](https://coveralls.io/repos/github/CosmicStudioSoftware/OMMBV/badge.svg?branch=main)](https://coveralls.io/github/CosmicStudioSoftware/OMMBV?branch=main) [![Documentation Status](https://readthedocs.org/projects/ommbv/badge/?version=latest)](https://ommbv.readthedocs.io/en/latest/?badge=latest) [![DOI](https://zenodo.org/badge/138220240.svg)](https://zenodo.org/badge/latestdoi/138220240) @@ -45,7 +45,8 @@ and measurements from the Communications/Navigation Outage Forecasting System The development of the multipole software has been supported, in part, by multiple agencies under the following grants: -Naval Research Laboratory N00173-19-1-G016 and NASA 80NSSC18K1203. +Cosmic Studio, Naval Research Laboratory N00173-19-1-G016, +and NASA 80NSSC18K1203. Previous versions of this software that provided an 'average' basis were funded by: National Aeronautics and Space Agency (NASA NNG12FA45C), diff --git a/docs/api.rst b/docs/api.rst index 00a0f54b6..1889610f4 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -2,8 +2,44 @@ API === +Core +---- + .. automodule:: OMMBV._core :members: +Heritage +-------- + +.. automodule:: OMMBV.heritage + :members: + +Satellite +--------- + .. automodule:: OMMBV.satellite :members: + +Trace +----- + +.. automodule:: OMMBV.trace + :members: + +Trans +----- + +.. automodule:: OMMBV.trans + :members: + +Utils +----- + +.. automodule:: OMMBV.utils + :members: + +Vector +------ + +.. automodule:: OMMBV.vector + :members: diff --git a/docs/citing.rst b/docs/citing.rst index 457f8a2e7..a5dd60b78 100644 --- a/docs/citing.rst +++ b/docs/citing.rst @@ -11,16 +11,16 @@ reproducibility of your presented results. OMMBV ----- -* Stoneback, R. A., J. H. Klenzing, G. Iyer. (2021). rstoneback/OMMBV: -v0.5.5 (v0.5.5). Zenodo. https://doi.org/10.5281/zenodo.4960425 +* Stoneback, R. A., J. H. Klenzing, G. Iyer. (2025). Orthogonal Multipole Magnetic Basis Vectors (OMMBV) v1.1.0. Zenodo. https://doi.org/10.5281/zenodo.1299374 .. code-block:: latex - @Misc{pysatModels, + @Misc{OMMBV, author = {Stoneback, R. A. and Klenzing, J. H., and Iyer, G..}, - title = {rstoneback/OMMBV: v0.5.5 (v0.5.5)}, - year = {2021}, - date = {2021-06-15}, - url = {https://github.com/rstoneback/OMMBV}, + title = {Orthogonal Multipole Magnetic Basis Vectors (OMMBV) v1.1.0}, + year = {2025}, + date = {2025-04-07}, + doi = {10.5281/zenodo.1299374}, + url = {https://doi.org/10.5281/zenodo.1299374} } diff --git a/docs/conf.py b/docs/conf.py index 5d43d0c4c..66d586626 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,7 +53,8 @@ def __getattr__(cls, name): 'sphinx.ext.autosummary', 'sphinx.ext.napoleon', 'numpydoc', - 'IPython.sphinxext.ipython_console_highlighting' + 'IPython.sphinxext.ipython_console_highlighting', + 'm2r2' ] # added by RS @@ -75,7 +76,7 @@ def __getattr__(cls, name): # General information about the project. project = u'OMMBV' -copyright = u'2021, Russell Stoneback' +copyright = u'2025, Russell Stoneback' author = u'Russell Stoneback' # The version info for the project you're documenting, acts as replacement for @@ -252,7 +253,7 @@ def __getattr__(cls, name): # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'OMMBV.tex', u'Python Magnetic Vectors Documentation', + (master_doc, 'OMMBV.tex', u'Orthogonal Multipole Magnetic Basis Vectors Documentation', u'Russell Stoneback', 'manual'), ] diff --git a/docs/develop_guide/code_of_conduct.rst b/docs/develop_guide/code_of_conduct.rst index 1deed898b..f4ab40bad 100644 --- a/docs/develop_guide/code_of_conduct.rst +++ b/docs/develop_guide/code_of_conduct.rst @@ -1,4 +1 @@ -Code of Conduct -=============== - .. mdinclude:: ../../CODE_OF_CONDUCT.md diff --git a/docs/develop_guide/contributing.rst b/docs/develop_guide/contributing.rst index a4d4ac0bf..f2c987c71 100644 --- a/docs/develop_guide/contributing.rst +++ b/docs/develop_guide/contributing.rst @@ -1,4 +1 @@ -Contributing -============ - .. mdinclude:: ../../CONTRIBUTING.md diff --git a/docs/index.rst b/docs/index.rst index e90cdda0e..bc3df870f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,9 +6,9 @@ Welcome to OMMBV's documentation! ================================= -This documentation describes the Orthogonal Multi-pole Magnetic Basis Vectors -(OMMBV) module, which contains routines to derive a vector basis from any -magnetic field. These vectors may be used to organize electric field +This documentation describes the Orthogonal Multipole Magnetic Basis Vectors +(OMMBV) module, which contains routines to derive a vector basis from multipole +magnetic fields. These vectors may be used to organize electric field measurements as well as map those electric fields along magnetic field lines in a physically consistent manner. diff --git a/docs/installation.rst b/docs/installation.rst index 247b58f97..55fe55ff3 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -20,12 +20,12 @@ Prerequisites OMMBV uses common Python modules, as well as modules developed by and for the Space Physics community. pysat is an optional module, used by OMMBV to make it easy for satellite missions to add OMMBV results. -This module officially supports Python 3.6+. +This module officially supports Python 3.9+. ============== ================= Common modules Community modules ============== ================= - numpy pysat + numpy pysat (optional) scipy ============== ================= @@ -35,26 +35,21 @@ This module officially supports Python 3.6+. Installation Options -------------------- -1. Clone the git repository -:: +A. Using pypi :: + pip install OMMBV - git clone https://github.com/rstoneback/OMMBV.git +B. OMMBV may also be installed directly from the source repository on github: -2. Install OMMBV: - Change directories into the repository folder and run the setup.py file. - There are a few ways you can do this: + 1. Clone the git repository:: - A. Install on the system (root privileges required):: + git clone https://github.com/CosmicStudioSoftware/OMMBV.git - sudo python3 setup.py install - B. Install at the user level:: + 2. Install OMMBV: :: - python3 setup.py install --user - C. Install with the intent to develop locally:: + cd OMMBV + pip install --user . - - python3 setup.py develop --user diff --git a/docs/overview.rst b/docs/overview.rst index fd7f58e49..14b0e1d90 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -4,35 +4,25 @@ Overview ======== The derivation of an appropriate vector basis has been a long-term challenge -in space science. The vector basis in current use is non-orthogonal and as -such presents a number of challenges when attempting to apply it to space -science studies. This package provides for the calculation of an orthogonal -vector basis, consistent with the underlying physics, for general magnetic -fields. Further, OMMBV calculates scaling factors suitable for translating -an electric field at one location to any other location on the field line. +in space science. This package provides the first accurate orthogonal +vector basis that supports mapping electric fields or other parameters at one +location to any other location on the same field line. OMMBV retains these properties for non-spherical planets, such as the Earth, as well as for magnetic fields that are more complicated than a pure dipole, such as the Earth's. These features are fundamental for Space Science studies. Satellite measurements of plasma motions in-situ can now be accurately mapped along field lines -for comparison to ground based equipment. Forcings from the neutral atmosphere -(in say Earth's E-region Ionsophere) may now also be mapped to satellite -altitudes to accurately characterize both the magnitude and direction -of that forcing on plasma motion at satellite locations. Computer modelers -may use OMMBV to map electric fields calculated within a single plane through -the whole magnetosphere, significantly reducing computational resources. +for comparison to ground based equipment. Forcing from the neutral atmosphere +may now also be mapped to satellite altitudes to accurately characterize +both the magnitude and direction of that forcing on plasma motion at satellite +locations. Computer modelers may use OMMBV to map electric fields calculated +within a single plane through the whole magnetosphere, significantly reducing +computational resources. OMMBV has been validated using a variety of test magnetic sources as well as via application to the Earth's magnetic field using the `International Geomagnetic Reference Field (IGRF) `_. -Further, OMMBV includes two paths to determine the relevant vector basis. Both -paths will only result in the same answers if the underlying system is truly -orthogonal. The statistical performance of OMMBV between IGRF witha geodetic -Earth and a spherical Earth with a pure dipole magnetic field is the same. -OMMBV vectors are accurate up to 6-7 digits of precision at default calculation -settings. - .. image:: images/logo_high_res.png :width: 400px diff --git a/docs/requirements.txt b/docs/requirements.txt index 3122d86e1..d67f41e29 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,11 +1,11 @@ datetime +docutils<0.21 numpy numpydoc +m2r2 ipython -pandas -pysat -readthedocs-sphinx-search==0.1.1 +readthedocs-sphinx-search==0.3.2 scipy -sphinx_rtd_theme==1.0.0 -sphinx==4.2.0 +sphinx_rtd_theme >= 1.2.2, < 2.0.0 +sphinx diff --git a/meson.build b/meson.build new file mode 100644 index 000000000..10b9be4e6 --- /dev/null +++ b/meson.build @@ -0,0 +1,111 @@ +project('OMMBV', 'c', + version : '1.1.0', + license: 'BSD-3', + meson_version: '>=0.64.0', + default_options : [ + 'warning_level=2', + 'c_args=-Wno-unused-parameter -Wno-cast-function-type -Wno-missing-field-initializers', + 'fortran_args=-Wno-line-truncation -Wno-conversion -Wno-unused-variable -Wno-maybe-uninitialized -Wno-unused-dummy-argument -Wno-compare-reals', + 'fortran_std=legacy'], +) + +add_languages('fortran', native: false) + +py_mod = import('python') +py = py_mod.find_installation(pure: false) +py_dep = py.dependency() + +incdir_numpy = run_command(py, + ['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'], + check : true +).stdout().strip() + +incdir_f2py = run_command(py, + ['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'], + check : true +).stdout().strip() + +inc_np = include_directories(incdir_numpy, incdir_f2py) + +# Unlike distutils, meson doesn't yet include some of the f2py stuff +fortranobject_c = incdir_f2py / 'fortranobject.c' + +fortranobject_lib = static_library('_fortranobject', + fortranobject_c, + dependencies: py_dep, + include_directories: [incdir_numpy, incdir_f2py]) + +fortranobject_dep = declare_dependency( + link_with: fortranobject_lib, + include_directories: [incdir_numpy, incdir_f2py]) + + +igrf_source = custom_target('igrfmodule.c', + input : ['ommbvfortran/igrf14.f'], # .f so no F90 wrappers + output : ['igrfmodule.c', 'igrf-f2pywrappers.f'], + command : [py, '-m', 'numpy.f2py', '@INPUT@', '-m', 'igrf', '--lower'] +) +py.extension_module('igrf', + [ + 'ommbvfortran/igrf14.f', + igrf_source, + fortranobject_c + ], + include_directories: inc_np, + link_with: fortranobject_lib, + dependencies : [py_dep, fortranobject_dep], + subdir: 'OMMBV', + install : true +) + + +sources_source = custom_target('sourcesmodule.c', + input : ['ommbvfortran/sources.f', 'ommbvfortran/igrf14.f'], # .f so no F90 wrappers + output : ['sourcesmodule.c', 'sources-f2pywrappers.f'], + command : [py, '-m', 'numpy.f2py', '@INPUT@', '-m', 'sources', '--lower'] +) +py.extension_module('sources', + [ + 'ommbvfortran/sources.f', + 'ommbvfortran/igrf14.f', + sources_source, + fortranobject_c + ], + include_directories: inc_np, + link_with: fortranobject_lib, + dependencies : [py_dep, fortranobject_dep], + subdir: 'OMMBV', + install : true +) + + +fcoords_source = custom_target('fortran_coordsmodule.c', + input : ['ommbvfortran/_coords.f'], # .f so no F90 wrappers + output : ['fortran_coordsmodule.c', 'fortran_coords-f2pywrappers.f'], + command : [py, '-m', 'numpy.f2py', '@INPUT@', '-m', 'fortran_coords', '--lower'] +) +py.extension_module('fortran_coords', + [ + 'ommbvfortran/_coords.f', + fcoords_source, + fortranobject_c + ], + include_directories: inc_np, + link_with: fortranobject_lib, + dependencies : [py_dep, fortranobject_dep], + subdir: 'OMMBV', + install : true +) + +py.install_sources( + 'OMMBV/_core.py', + 'OMMBV/heritage.py', + 'OMMBV/satellite.py', + 'OMMBV/trace.py', + 'OMMBV/trans.py', + 'OMMBV/utils.py', + 'OMMBV/vector.py', + 'OMMBV/__init__.py', + pure: false, + subdir: 'OMMBV' +) \ No newline at end of file diff --git a/OMMBV/_coords.f b/ommbvfortran/_coords.f similarity index 100% rename from OMMBV/_coords.f rename to ommbvfortran/_coords.f diff --git a/OMMBV/igrf13.f b/ommbvfortran/igrf14.f similarity index 84% rename from OMMBV/igrf13.f rename to ommbvfortran/igrf14.f index 9c12f6391..093f37298 100644 --- a/OMMBV/igrf13.f +++ b/ommbvfortran/igrf14.f @@ -1,17 +1,15 @@ - - - subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) + subroutine igrf14syn (isv,date,itype,alt,colat,elong,x,y,z,f) c -c This is a synthesis routine for the 13th generation IGRF as agreed -c in December 2019 by IAGA Working Group V-MOD. It is valid 1900.0 to -c 2025.0 inclusive. Values for dates from 1945.0 to 2015.0 inclusive are +c This is a synthesis routine for the 14th generation IGRF as agreed +c in December 2024 by IAGA Working Group V-MOD. It is valid 1900.0 to +c 2030.0 inclusive. Values for dates from 1945.0 to 2020.0 inclusive are c definitive, otherwise they are non-definitive. c INPUT c isv = 0 if main-field values are required c isv = 1 if secular variation values are required c date = year A.D. Must be greater than or equal to 1900.0 and -c less than or equal to 2030.0. Warning message is given -c for dates greater than 2025.0. Must be double precision. +c less than or equal to 2035.0. Warning message is given +c for dates greater than 2030.0. Must be double precision. c itype = 1 if geodetic (spheroid) c itype = 2 if geocentric (sphere) c alt = height in km above sea level if itype = 1 @@ -35,18 +33,19 @@ subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) c radius (= 6371.0 km) but 6371.2 km is what is used in determining the c coefficients. Adaptation by Susan Macmillan, August 2003 (for c 9th generation), December 2004, December 2009 & December 2014; -c by William Brown, December 2019, February 2020. +c by William Brown, December 2019, February 2020. Updated by +c Ciaran Beggan, November 2024 c c Coefficients at 1995.0 incorrectly rounded (rounded up instead of c to even) included as these are the coefficients published in Excel c spreadsheet July 2005. c implicit double precision (a-h,o-z) - dimension gh(3645),g0(120),g1(120),g2(120),g3(120),g4(120), + dimension gh(3840),g0(120),g1(120),g2(120),g3(120),g4(120), 1 g5(120),g6(120),g7(120),g8(120),g9(120),ga(120), 2 gb(120),gc(120),gd(120),ge(120),gf(120),gg(120), 3 gi(120),gj(120),gk(195),gl(195),gm(195),gp(195), - 4 gq(195),gr(195),gs(195), + 4 gq(195),gr(195),gs(195),gt(195), 5 p(105),q(105),cl(13),sl(13) equivalence (g0,gh(1)),(g1,gh(121)),(g2,gh(241)),(g3,gh(361)), 1 (g4,gh(481)),(g5,gh(601)),(g6,gh(721)),(g7,gh(841)), @@ -55,7 +54,8 @@ subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) 4 (ge,gh(1681)),(gf,gh(1801)),(gg,gh(1921)), 5 (gi,gh(2041)),(gj,gh(2161)),(gk,gh(2281)), 6 (gl,gh(2476)),(gm,gh(2671)),(gp,gh(2866)), - 7 (gq,gh(3061)),(gr,gh(3256)),(gs,gh(3451)) + 7 (gq,gh(3061)),(gr,gh(3256)),(gs,gh(3451)), + 8 (gt,gh(3646)) c data g0/ -31543.,-2298., 5922., -677., 2905.,-1061., 924., 1121., 1900 1 1022.,-1469., -330., 1256., 3., 572., 523., 876., 1900 @@ -485,71 +485,104 @@ subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) u -0.10, 0.81, 0.42, -0.13, -0.04, 0.38, 2015 v 0.48, 0.08, 0.48, 0.46, -0.30, -0.35, 2015 w -0.43, -0.36, -0.71/ 2015 - data gr/ -29404.8, -1450.9, 4652.5, -2499.6, 2982.0, -2991.6, 2020 - 1 1677.0, -734.6, 1363.2, -2381.2, -82.1, 1236.2, 2020 - 2 241.9, 525.7, -543.4, 903.0, 809.5, 281.9, 2020 - 3 86.3, -158.4, -309.4, 199.7, 48.0, -349.7, 2020 - 4 -234.3, 363.2, 47.7, 187.8, 208.3, -140.7, 2020 - 5 -121.2, -151.2, 32.3, 13.5, 98.9, 66.0, 2020 - 6 65.5, -19.1, 72.9, 25.1, -121.5, 52.8, 2020 - 7 -36.2, -64.5, 13.5, 8.9, -64.7, 68.1, 2020 - 8 80.6, -76.7, -51.5, -8.2, -16.9, 56.5, 2020 - 9 2.2, 15.8, 23.5, 6.4, -2.2, -7.2, 2020 - a -27.2, 9.8, -1.8, 23.7, 9.7, 8.4, 2020 - b -17.6, -15.3, -0.5, 12.8, -21.1, -11.7, 2020 - c 15.3, 14.9, 13.7, 3.6, -16.5, -6.9, 2020 - d -0.3, 2.8, 5.0, 8.4, -23.4, 2.9, 2020 - e 11.0, -1.5, 9.8, -1.1, -5.1, -13.2, 2020 - f -6.3, 1.1, 7.8, 8.8, 0.4, -9.3, 2020 - g -1.4, -11.9, 9.6, -1.9, -6.2, 3.4, 2020 - h -0.1, -0.2, 1.7, 3.6, -0.9, 4.8, 2020 - i 0.7, -8.6, -0.9, -0.1, 1.9, -4.3, 2020 - j 1.4, -3.4, -2.4, -0.1, -3.8, -8.8, 2020 - k 3.0, -1.4, 0.0, -2.5, 2.5, 2.3, 2020 - l -0.6, -0.9, -0.4, 0.3, 0.6, -0.7, 2020 - m -0.2, -0.1, -1.7, 1.4, -1.6, -0.6, 2020 - n -3.0, 0.2, -2.0, 3.1, -2.6, -2.0, 2020 - o -0.1, -1.2, 0.5, 0.5, 1.3, 1.4, 2020 - p -1.2, -1.8, 0.7, 0.1, 0.3, 0.8, 2020 - q 0.5, -0.2, -0.3, 0.6, -0.5, 0.2, 2020 - r 0.1, -0.9, -1.1, 0.0, -0.3, 0.5, 2020 - s 0.1, -0.9, -0.9, 0.5, 0.6, 0.7, 2020 - t 1.4, -0.3, -0.4, 0.8, -1.3, 0.0, 2020 - u -0.1, 0.8, 0.3, 0.0, -0.1, 0.4, 2020 - v 0.5, 0.1, 0.5, 0.5, -0.4, -0.5, 2020 - w -0.4, -0.4, -0.6/ 2020 - data gs/ 5.7, 7.4, -25.9, -11.0, -7.0, -30.2, 2022 - 1 -2.1, -22.4, 2.2, -5.9, 6.0, 3.1, 2022 - 2 -1.1, -12.0, 0.5, -1.2, -1.6, -0.1, 2022 - 3 -5.9, 6.5, 5.2, 3.6, -5.1, -5.0, 2022 - 4 -0.3, 0.5, 0.0, -0.6, 2.5, 0.2, 2022 - 5 -0.6, 1.3, 3.0, 0.9, 0.3, -0.5, 2022 - 6 -0.3, 0.0, 0.4, -1.6, 1.3, -1.3, 2022 - 7 -1.4, 0.8, 0.0, 0.0, 0.9, 1.0, 2022 - 8 -0.1, -0.2, 0.6, 0.0, 0.6, 0.7, 2022 - 9 -0.8, 0.1, -0.2, -0.5, -1.1, -0.8, 2022 - a 0.1, 0.8, 0.3, 0.0, 0.1, -0.2, 2022 - b -0.1, 0.6, 0.4, -0.2, -0.1, 0.5, 2022 - c 0.4, -0.3, 0.3, -0.4, -0.1, 0.5, 2022 - d 0.4, 0.0, 115*0.0/ 2022 + data gr/-29403.41,-1451.37, 4653.35,-2499.78, 2981.96,-2991.72, 2020 + 1 1676.85, -734.62, 1363.00,-2380.80, -81.96, 1236.06, 2020 + 2 241.80, 525.60, -542.52, 902.82, 809.47, 282.10, 2020 + 3 86.18, -158.50, -309.47, 199.75, 47.44, -350.30, 2020 + 4 -234.42, 363.26, 47.52, 187.86, 208.36, -140.73, 2020 + 5 -121.43, -151.16, 32.09, 13.98, 99.14, 65.97, 2020 + 6 65.56, -19.22, 72.96, 25.02, -121.57, 52.76, 2020 + 7 -36.06, -64.40, 13.60, 8.96, -64.80, 68.04, 2020 + 8 80.54, -76.63, -51.50, -8.23, -16.85, 56.45, 2020 + 9 2.36, 15.80, 23.56, 6.30, -2.19, -7.21, 2020 + a -27.19, 9.77, -1.90, 23.66, 9.74, 8.43, 2020 + b -17.49, -15.23, -0.49, 12.83, -21.07, -11.76, 2020 + c 15.28, 14.94, 13.65, 3.62, -16.59, -6.90, 2020 + d -0.34, 2.90, 5.03, 8.36, -23.44, 2.84, 2020 + e 11.04, -1.48, 9.86, -1.14, -5.13, -13.22, 2020 + f -6.20, 1.08, 7.79, 8.82, 0.40, -9.23, 2020 + g -1.44, -11.86, 9.60, -1.84, -6.25, 3.38, 2020 + h -0.11, -0.18, 1.66, 3.50, -0.86, 4.86, 2020 + i 0.65, -8.62, -0.88, -0.11, 1.88, -4.26, 2020 + j 1.44, -3.43, -2.38, -0.10, -3.84, -8.84, 2020 + k 2.96, -1.36, -0.02, -2.51, 2.50, 2.31, 2020 + l -0.55, -0.85, -0.39, 0.28, 0.62, -0.66, 2020 + m -0.21, -0.07, -1.66, 1.44, -1.60, -0.59, 2020 + n -2.98, 0.18, -1.97, 3.09, -2.51, -2.00, 2020 + o -0.13, -1.15, 0.43, 0.52, 1.28, 1.37, 2020 + p -1.14, -1.81, 0.71, 0.08, 0.31, 0.71, 2020 + q 0.49, -0.15, -0.26, 0.55, -0.47, 0.16, 2020 + r 0.09, -0.93, -1.13, -0.04, -0.33, 0.52, 2020 + s 0.08, -0.93, -0.88, 0.53, 0.64, 0.72, 2020 + t 1.40, -0.30, -0.38, 0.75, -1.31, -0.01, 2020 + u -0.09, 0.76, 0.29, -0.05, -0.11, 0.37, 2020 + v 0.47, 0.13, 0.54, 0.45, -0.41, -0.46, 2020 + w -0.36, -0.40, -0.60/ 2020 + data gs/ -29350.0, -1410.3, 4545.5, -2556.2, 2950.9, -3133.6, 2025 + 1 1648.7, -814.2, 1360.9, -2404.2, -56.9, 1243.8, 2025 + 2 237.6, 453.4, -549.6, 894.7, 799.6, 278.6, 2025 + 3 55.8, -134.0, -281.1, 212.0, 12.0, -375.4, 2025 + 4 -232.9, 369.0, 45.3, 187.2, 220.0, -138.7, 2025 + 5 -122.9, -141.9, 42.9, 20.9, 106.2, 64.3, 2025 + 6 63.8, -18.4, 76.7, 16.8, -115.7, 48.9, 2025 + 7 -40.9, -59.8, 14.9, 10.9, -60.8, 72.8, 2025 + 8 79.6, -76.9, -48.9, -8.8, -14.4, 59.3, 2025 + 9 -1.0, 15.8, 23.5, 2.5, -7.4, -11.2, 2025 + a -25.1, 14.3, -2.2, 23.1, 10.9, 7.2, 2025 + b -17.5, -12.6, 2.0, 11.5, -21.8, -9.7, 2025 + c 16.9, 12.7, 14.9, 0.7, -16.8, -5.2, 2025 + d 1.0, 3.9, 4.7, 8.0, -24.8, 3.0, 2025 + e 12.1, -0.2, 8.3, -2.5, -3.4, -13.1, 2025 + f -5.3, 2.4, 7.2, 8.6, -0.6, -8.7, 2025 + g 0.8, -12.8, 9.8, -1.3, -6.4, 3.3, 2025 + h 0.2, 0.1, 2.0, 2.5, -1.0, 5.4, 2025 + i -0.5, -9.0, -0.9, 0.4, 1.5, -4.2, 2025 + j 0.9, -3.8, -2.6, 0.9, -3.9, -9.0, 2025 + k 3.0, -1.4, 0.0, -2.5, 2.8, 2.4, 2025 + l -0.6, -0.6, 0.1, 0.0, 0.5, -0.6, 2025 + m -0.3, -0.1, -1.2, 1.1, -1.7, -1.0, 2025 + n -2.9, -0.1, -1.8, 2.6, -2.3, -2.0, 2025 + o -0.1, -1.2, 0.4, 0.6, 1.2, 1.0, 2025 + p -1.2, -1.5, 0.6, 0.0, 0.5, 0.6, 2025 + q 0.5, -0.2, -0.1, 0.8, -0.5, 0.1, 2025 + r -0.2, -0.9, -1.2, 0.1, -0.7, 0.2, 2025 + s 0.2, -0.9, -0.9, 0.6, 0.7, 0.7, 2025 + t 1.2, -0.2, -0.3, 0.5, -1.3, 0.1, 2025 + u -0.1, 0.7, 0.2, 0.0, -0.2, 0.3, 2025 + v 0.5, 0.2, 0.6, 0.4, -0.6, -0.5, 2025 + w -0.3, -0.4, -0.5/ 2025 + data gt/ 12.6, 10.0, -21.5, -11.2, -5.3, -27.3, 2027 + 1 -8.3, -11.1, -1.5, -4.4, 3.8, 0.4, 2027 + 2 -0.2, -15.6, -3.9, -1.7, -2.3, -1.3, 2027 + 3 -5.8, 4.1, 5.4, 1.6, -6.8, -4.1, 2027 + 4 0.6, 1.3, -0.5, 0.0, 2.1, 0.7, 2027 + 5 0.5, 2.3, 1.7, 1.0, 1.9, -0.2, 2027 + 6 -0.3, 0.3, 0.8, -1.6, 1.2, -0.4, 2027 + 7 -0.8, 0.8, 0.4, 0.7, 0.9, 0.9, 2027 + 8 -0.1, -0.1, 0.6, -0.1, 0.5, 0.5, 2027 + 9 -0.7, -0.1, 0.0, -0.8, -0.9, -0.8, 2027 + a 0.5, 0.9, -0.3, -0.1, 0.2, -0.3, 2027 + b 0.0, 0.4, 0.4, -0.3, -0.1, 0.4, 2027 + c 0.3, -0.5, 0.1, -0.6, 0.0, 0.3, 2027 + d 0.3, 0.2, 115*0.0/ 2027 + C following added by RStoneback Cf2py intent(in) isv,date,itype,alt,colat,elong Cf2py intent(out) x,y,z,f - c c set initial values c x = 0.0 y = 0.0 z = 0.0 - if (date.lt.1900.0.or.date.gt.2030.0) go to 11 - if (date.gt.2025.0) write (6,960) date + if (date.lt.1900.0.or.date.gt.2035.0) go to 11 + if (date.gt.2030.0) write (6,960) date 960 format (/' This version of the IGRF is intended for use up', - 1 ' to 2025.0.'/' values for',f9.3,' will be computed', + 1 ' to 2030.0.'/' values for',f9.3,' will be computed', 2 ' but may be of reduced accuracy'/) - if (date.ge.2020.0) go to 1 + if (date.ge.2025.0) go to 1 t = 0.2*(date - 1900.0) ll = t one = ll @@ -579,7 +612,7 @@ subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) end if go to 2 c - 1 t = date - 2020.0 + 1 t = date - 2025.0 tc = 1.0 if (isv.eq.1) then t = 1.0 @@ -588,17 +621,15 @@ subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) c c pointer for last coefficient in pen-ultimate set of MF coefficients... c - ll = 3255 + ll = 3450 nmx = 13 nc = nmx*(nmx+2) kmx = (nmx+1)*(nmx+2)/2 2 r = alt - one = colat - !*0.017453292 + one = colat !*0.017453292 ct = cos(one) st = sin(one) - one = elong - !*0.017453292 + one = elong !*0.017453292 cl(1) = cos(one) sl(1) = sin(one) cd = 1.0 @@ -694,6 +725,6 @@ subroutine igrf13syn (isv,date,itype,alt,colat,elong,x,y,z,f) write (6,961) date 961 format (/' This subroutine will not work with a date of', 1 f9.3,'. Date must be in the range 1900.0.ge.date', - 2 '.le.2030.0. On return f = 1.0d8., x = y = z = 0.') + 2 '.le.2035.0. On return f = 1.0d8., x = y = z = 0.') return - end + end \ No newline at end of file diff --git a/OMMBV/sources.f b/ommbvfortran/sources.f similarity index 98% rename from OMMBV/sources.f rename to ommbvfortran/sources.f index 4d5d50cac..d285258b6 100644 --- a/OMMBV/sources.f +++ b/ommbvfortran/sources.f @@ -341,7 +341,7 @@ subroutine gen_step(mflag,gflag,out,pos,t,date,step,dir,height) ! Generalized integrand field-line step function for testing ! IGRF call - external :: igrf13syn + external :: igrf14syn ! pos is (x,y,z) in ECEF coordinates real*8, dimension(3) :: pos ! t is total time supplied by integration routine, ignored @@ -379,7 +379,7 @@ subroutine gen_step(mflag,gflag,out,pos,t,date,step,dir,height) if (mflag.eq.-1) then ! Use IGRF. Supported to ensure reults same as operational ! IGRF function. - call igrf13syn(0,date,2,r,colat,elong,bn,be,bd,bm) + call igrf14syn(0,date,2,r,colat,elong,bn,be,bd,bm) else ! Use a physically specified dipole + higher order poles call poles(mflag,0,date,2,r,colat,elong,bn,be,bd,bm) @@ -417,7 +417,7 @@ subroutine gen_step(mflag,gflag,out,pos,t,date,step,dir,height) subroutine igrf_step(out,pos,t,date,scalar,dir,height) ! IGRF call - external :: igrf13syn + external :: igrf14syn real*8, dimension(3) :: pos real*8 t, date @@ -449,7 +449,7 @@ subroutine igrf_step(out,pos,t,date,scalar,dir,height) ! altitude should be radial distance from center of earth call ecef_to_colat_long_r(pos,colat,elong,r) - call igrf13syn(0,date,2,r,colat,elong,bn,be,bd,bm) + call igrf14syn(0,date,2,r,colat,elong,bn,be,bd,bm) ! convert the mag field in spherical unit vectors to ECEF vectors call end_vector_to_ecef(be,bn,bd,colat,elong,bx,by,bz) diff --git a/pyproject.toml b/pyproject.toml index 83de03ad5..5247586ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,58 @@ [build-system] -requires = ["setuptools", "wheel", "Cython", "numpy"] +build-backend = 'mesonpy' +requires = [ + "wheel", + "meson-python>=0.12.0", + "setuptools<60.0", # Do not increase, 60.0 enables vendored distutils + "Cython>=0.29.21", + "ninja", + "numpy" +] + +[project] +name = "OMMBV" +version = "1.1.0" +license = {file = "LICENSE"} +description = "Orthogonal geomagnetic vector basis and field-line mapping for multipole magnetic fields." +maintainers = [ + {name = "Russell Stoneback", email = "contact@cosmicstudio.io"} +] +requires-python = ">=3.9" +dependencies = [ + "numpy", + "scipy" +] +readme = "README.md" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Topic :: Scientific/Engineering :: Physics", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: POSIX :: Linux", + "Operating System :: POSIX", + "Operating System :: MacOS" +] +keywords = [ + "vector-basis", + "geomagnetic-field", + "magnetic-fields", + "field-line-tracing", + "meridional", + "zonal", + "field-aligned", + "satellite", + "electric-field-mapping", + "ion-drift-mapping", + "multipole", + "electrodynamics", + "plasma" +] + + + diff --git a/requirements.txt b/requirements.txt index 702512066..1d6e52cdd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ numpy -pysat >= 3.0.0 +pysat scipy diff --git a/setup.cfg b/setup.cfg index b1a7bc206..1b094e17c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,9 @@ [metadata] name = OMMBV version = file: OMMBV/version.txt -url = https://github.com/rstoneback/OMMBV +url = https://github.com/CosmicStudioSoftware/OMMBV/ author = Russell A. Stoneback -author_email = github@stoneris.com +author_email = contact@cosmicstudio.io description = 'Orthogonal geomagnetic vector basis and field-line mapping for multipole magnetic fields.' long_description = file: README.md, CHANGELOG.md long_description_content_type = text/markdown @@ -61,11 +61,3 @@ exclude = conf.py tests __init__.py -[tool:pytest] -markers = - all_inst: tests all instruments - download: tests for downloadable instruments - no_download: tests for instruments without download support - load_options: tests for instruments including optional load kwargs - first: first tests to run - second: second tests to run diff --git a/setup.py b/setup.py index 8ad1550c6..295b4dac2 100644 --- a/setup.py +++ b/setup.py @@ -22,14 +22,15 @@ '-Wno-unused-variable', '-Wno-maybe-uninitialized', '-Wno-unused-dummy-argument'] extensions = [Extension(name='OMMBV.igrf', - sources=[os.path.join('OMMBV', 'igrf13.f')], + sources=[os.path.join('ommbvfortran', 'igrf14.f')], extra_f77_compile_args=extra_args), Extension(name='OMMBV.sources', - sources=[os.path.join('OMMBV', 'sources.f'), - os.path.join('OMMBV', 'igrf13.f')], + sources=[os.path.join('ommbvfortran', 'sources.f'), + os.path.join('ommbvfortran', 'igrf14.f')], extra_f77_compile_args=extra_args), Extension(name='OMMBV.fortran_coords', - sources=[os.path.join('OMMBV', '_coords.f')])] + sources=[os.path.join('ommbvfortran', + '_coords.f')])] setup_kwargs = {'ext_modules': extensions} setup(**setup_kwargs) diff --git a/test_requirements.txt b/test_requirements.txt index a1a17907b..6ee3c9931 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -4,6 +4,7 @@ flake8-docstrings hacking ipython m2r2 +docutils<0.21 numpydoc pytest-cov pytest-ordering diff --git a/OMMBV/tests/test_apex.py b/tests/test_apex.py similarity index 98% rename from OMMBV/tests/test_apex.py rename to tests/test_apex.py index 01999c3ce..6e456a8c0 100644 --- a/OMMBV/tests/test_apex.py +++ b/tests/test_apex.py @@ -59,7 +59,7 @@ def test_apex_heights(self): class TestApexAccuracy(object): - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.inst = pysat.Instrument('pysat', 'testing', num_samples=100) @@ -69,7 +69,7 @@ def setup(self): self.date = dt.datetime(2000, 1, 1) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.inst diff --git a/OMMBV/tests/test_core.py b/tests/test_core.py similarity index 98% rename from OMMBV/tests/test_core.py rename to tests/test_core.py index 33a16efa0..1ec29b376 100644 --- a/OMMBV/tests/test_core.py +++ b/tests/test_core.py @@ -8,9 +8,9 @@ import pytest import warnings +import pysat + import OMMBV -from OMMBV import tests -import OMMBV.tests.test_deprecation as testing import OMMBV.trace import OMMBV.trans import OMMBV.vector @@ -117,7 +117,7 @@ def gen_plot_grid_fixed_alt(alt): class TestUnitVectors(object): - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.date = dt.datetime(2000, 1, 1) @@ -134,7 +134,7 @@ def setup(self): return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.date, self.map_labels, self.lats, self.longs @@ -348,7 +348,7 @@ def test_nonconvergence_basis_ecef(self): assert len(war) >= len(self.warn_msgs) # Test the warning messages, ensuring each attribute is present. - testing.eval_warnings(war, self.warn_msgs, RuntimeWarning) + pysat.utils.testing.eval_warnings(war, self.warn_msgs, RuntimeWarning) return diff --git a/OMMBV/tests/test_deprecation.py b/tests/test_deprecation.py similarity index 96% rename from OMMBV/tests/test_deprecation.py rename to tests/test_deprecation.py index 0f71d1bce..876a324b1 100644 --- a/OMMBV/tests/test_deprecation.py +++ b/tests/test_deprecation.py @@ -50,7 +50,7 @@ def eval_warnings(warns, check_msgs, warn_type=DeprecationWarning): class TestDeprecations(object): """Unit tests for deprecated inputs and functions.""" - def setup(self): + def setup_method(self): """Setup test environment before each function.""" warnings.simplefilter("always", DeprecationWarning) @@ -58,7 +58,7 @@ def setup(self): self.warn_msgs = '' return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.warn_msgs, self.date return @@ -69,7 +69,7 @@ def test_core_geomagnetic_ecef(self, param): """Test deprecated inputs, `calculate_mag_drift_unit_vectors_ecef`.""" self.warn_msgs = [" ".join([param, "is deprecated, non-functional,", - "and will be removed after OMMBV v1.0.0."])] + "and will be removed after OMMBV v1.2."])] self.warn_msgs = np.array(self.warn_msgs) # Prep input @@ -94,7 +94,7 @@ def test_core_scalars_for_mapping(self, param): """Test deprecated inputs, `scalars_for_mapping_ion_drifts`.""" self.warn_msgs = [" ".join([param, "is deprecated, non-functional,", - "and will be removed after OMMBV v1.0.0."])] + "and will be removed after OMMBV v1.2."])] self.warn_msgs = np.array(self.warn_msgs) # Prep input @@ -117,7 +117,7 @@ def test_core_scalars_for_mapping(self, param): class TestCoreDeprecations(object): """Unit tests for deprecated core functions.""" - def setup(self): + def setup_method(self): """Setup test environment before each function.""" warnings.simplefilter("always", DeprecationWarning) @@ -126,7 +126,7 @@ def setup(self): return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.warn_msgs, self.date return @@ -141,7 +141,7 @@ def test_core_trans_functions_deprecated(self, func): self.warn_msgs = ["".join(["Function moved to `OMMBV.trans`, " "deprecated wrapper will be removed after ", - "OMMBV v1.0.0."])] + "OMMBV v1.2."])] self.warn_msgs = np.array(self.warn_msgs) # Catch the warnings. @@ -192,7 +192,7 @@ def test_core_vect_functions_deprecated(self, func, args): self.warn_msgs = ["".join(["Function moved to `OMMBV.vector`, ", "deprecated wrapper will be removed after ", - "OMMBV v1.0.0."])] + "OMMBV v1.2."])] self.warn_msgs = np.array(self.warn_msgs) # Catch the warnings. @@ -212,7 +212,7 @@ def test_heritage_functions_deprecated(self): self.warn_msgs = [''.join(['This method now called `apex_distance_', 'after_footpoint_step`. Wrapper will be ', - 'removed after OMMBV v1.0.0.'])] + 'removed after OMMBV v1.2.'])] self.warn_msgs = np.array(self.warn_msgs) # Catch the warnings. diff --git a/OMMBV/tests/test_former_methods.py b/tests/test_former_methods.py similarity index 98% rename from OMMBV/tests/test_former_methods.py rename to tests/test_former_methods.py index 239f71ea5..95ed6dbc8 100644 --- a/OMMBV/tests/test_former_methods.py +++ b/tests/test_former_methods.py @@ -4,19 +4,19 @@ import OMMBV import OMMBV.heritage -from OMMBV.tests.test_core import gen_plot_grid_fixed_alt +from test_core import gen_plot_grid_fixed_alt import OMMBV.vector class TestIntegratedMethods(object): - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.lats, self.longs, self.alts = gen_plot_grid_fixed_alt(550.) self.date = dt.datetime(2000, 1, 1) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.lats, self.longs, self.alts diff --git a/OMMBV/tests/test_satellite.py b/tests/test_satellite.py similarity index 99% rename from OMMBV/tests/test_satellite.py rename to tests/test_satellite.py index c454c1be8..54811a50b 100644 --- a/OMMBV/tests/test_satellite.py +++ b/tests/test_satellite.py @@ -10,13 +10,13 @@ class TestSatellite(object): - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.inst = pysat.Instrument('pysat', 'testing', num_samples=32) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.inst return diff --git a/OMMBV/tests/test_trace.py b/tests/test_trace.py similarity index 98% rename from OMMBV/tests/test_trace.py rename to tests/test_trace.py index 7b6a15be9..193984bbe 100644 --- a/OMMBV/tests/test_trace.py +++ b/tests/test_trace.py @@ -5,7 +5,7 @@ import numpy as np import pytest -from OMMBV.tests.test_core import gen_data_fixed_alt +from test_core import gen_data_fixed_alt import OMMBV.trans import OMMBV.trace as trace @@ -13,7 +13,7 @@ class TestTracing(object): """Test `OMMBV.trace` functions.""" - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.date = dt.datetime(2020, 1, 1) @@ -27,7 +27,7 @@ def setup(self): self.alts) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.lats, self.longs, self.alts diff --git a/OMMBV/tests/test_trans.py b/tests/test_trans.py similarity index 99% rename from OMMBV/tests/test_trans.py rename to tests/test_trans.py index 2dbd0515e..647130a77 100644 --- a/OMMBV/tests/test_trans.py +++ b/tests/test_trans.py @@ -6,7 +6,7 @@ from OMMBV import igrf from OMMBV import sources import OMMBV.trans -from OMMBV.tests.test_core import gen_data_fixed_alt +from test_core import gen_data_fixed_alt # ############## TRANSFORMATIONS ############## # @@ -32,14 +32,14 @@ def assert_difference_tol(data, data2, tol=1.E-5): class TestTransformations(object): - def setup(self): + def setup_method(self): """Setup test environment before each function.""" # Locations to perform tests at self.lats, self.longs, self.alts = gen_data_fixed_alt(550.) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.lats, self.longs, self.alts diff --git a/OMMBV/tests/test_utils.py b/tests/test_utils.py similarity index 97% rename from OMMBV/tests/test_utils.py rename to tests/test_utils.py index e11d418c0..082cf82fe 100644 --- a/OMMBV/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,7 +11,7 @@ class TestUtils(object): """Unit tests for utils.""" - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.start_date = dt.datetime(2000, 1, 1) @@ -20,7 +20,7 @@ def setup(self): self.end_date) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.start_date, self.end_date, self.dates diff --git a/OMMBV/tests/test_vector.py b/tests/test_vector.py similarity index 98% rename from OMMBV/tests/test_vector.py rename to tests/test_vector.py index bc184cba6..3ba13d464 100644 --- a/OMMBV/tests/test_vector.py +++ b/tests/test_vector.py @@ -5,20 +5,20 @@ import OMMBV from OMMBV import sources -from OMMBV.tests.test_core import gen_data_fixed_alt +from test_core import gen_data_fixed_alt class TestVector(object): """Unit tests for `OMMBV.vector`.""" - def setup(self): + def setup_method(self): """Setup test environment before each function.""" # Locations to perform tests at self.lats, self.longs, self.alts = gen_data_fixed_alt(550.) return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.lats, self.longs, self.alts diff --git a/OMMBV/tests/test_vitmo.py b/tests/test_vitmo.py similarity index 99% rename from OMMBV/tests/test_vitmo.py rename to tests/test_vitmo.py index 645bf8da2..6ebf93a10 100644 --- a/OMMBV/tests/test_vitmo.py +++ b/tests/test_vitmo.py @@ -65,7 +65,7 @@ class TestTracingVitmo(): """Test OMMBV tracing against public results hosted by NASA.""" - def setup(self): + def setup_method(self): """Setup test environment before each function.""" self.inst = pysat.Instrument('pysat', 'testing') @@ -74,7 +74,7 @@ def setup(self): return - def teardown(self): + def teardown_method(self): """Clean up test environment after each function.""" del self.inst