diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..bad6ba3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + # Check for updates once a week + interval: 'weekly' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f51670..aca255d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,56 +1,58 @@ name: CI on: push: + branches: + - main + - develop pull_request: workflow_dispatch: - # schedule: - # - cron: '0 0 * * *' # Daily “At 00:00” + schedule: + - cron: '0 0 * * *' # Daily “At 00:00” + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: test: - # if: | - # github.repository == 'NCAR/wrf-python' - name: Python (${{ matrix.python-version }}, ${{ matrix.os }}) + name: Python ${{ matrix.python-version }}, ${{ matrix.os }} runs-on: ${{ matrix.os }} defaults: run: shell: bash -l {0} - strategy: fail-fast: false matrix: - os: [ "ubuntu-latest", "macos-latest"] - python-version: [ "3.6", "3.7", "3.8", "3.9" ] - + os: [ "ubuntu-latest", "macos-latest", "macos-14" ] + python-version: [ "3.9", "3.10", "3.11", "3.12" ] steps: - - name: Cancel previous runs - uses: styfle/cancel-workflow-action@0.9.0 - with: - access_token: ${{ github.token }} - - name: Checkout - uses: actions/checkout@v2 + - name: checkout + uses: actions/checkout@v4 + - name: environment setup + uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 with: - token: ${{ github.token }} - - name: Conda setup - uses: conda-incubator/setup-miniconda@v2 - with: - activate-environment: wrf_python_build python-version: ${{ matrix.python-version }} - channels: conda-forge, ncar - - name: Conda install (Darwin) - if: matrix.os == 'macos-latest' - run: | - conda env update --file build_envs/Darwin.yml --prune - - name: Conda install (Linux) - if: matrix.os == 'ubuntu-latest' + channels: conda-forge + environment-file: build_envs/environment.yml + - name: build WRF-Python run: | - conda env update --file build_envs/Linux.yml --prune - - name: Build WRF-Python - run: | - cd build_scripts - ./gnu_omp.sh - cd .. - - name: Run tests + python -m pip install build + python -m build . + python -m pip install dist/wrf*.whl + - name: run tests run: | cd test/ci_tests python utests.py + - name: check import + if: failure() + run: | + python -m pip show wrf-python + python -m pip show --files wrf-python + prefix="$(python -m pip show --files wrf-python | grep Location: | cut -f2 -d" ")" + echo "Site-packages directory is ${prefix}" + cd "${prefix}" + installed_files="$(python -m pip show --files wrf-python | grep -v -E -e '^[-a-zA-Z]+:')" + ls -l ${installed_files} + file ${installed_files} + python -vvv -dd -c "import wrf" + ldd $(echo ${installed_files} | grep -F -v -e ".py" -e ".dist-info") diff --git a/.github/workflows/pypi.yaml b/.github/workflows/pypi.yaml new file mode 100644 index 0000000..b79509f --- /dev/null +++ b/.github/workflows/pypi.yaml @@ -0,0 +1,52 @@ +name: Upload wrf-python to PyPI +on: + release: + types: + - published +jobs: + test-build: + if: github.repository == 'NCAR/wrf-python' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install build twine + - name: Build tarball and wheels + run: | + python -m build + - name: Test the artifacts + run: | + python -m twine check dist/* + publish: + needs: test-build + if: startsWith(github.ref, 'refs/tags') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install build twine + - name: Build tarball and wheels + run: | + python -m build + - name: Test the artifacts + run: | + python -m twine check dist/* + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 + with: + user: __token__ + password: ${{ secrets.PYPI_WRF_PYTHON }} + skip_existing: true + verbose: true diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..8cb6480 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,21 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "mambaforge-4.10" + jobs: + post_create_environment: + - python -m pip install --no-cache-dir --no-deps . + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: doc/source/conf.py + +conda: + environment: build_envs/environment.yml diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..08f040d --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,7 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +authors: + - given-names: "Visualization & Analysis Systems Technologies" +title: "Geoscience Community Analysis Toolkit: WRF-Python" +doi: 10.5065/D6W094P1 +url: "https://github.com/NCAR/wrf-python" diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..265c22c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,209 @@ +### setup project ### +# https://numpy.org/doc/stable/f2py/buildtools/skbuild.html +cmake_minimum_required(VERSION 3.18) + +project(${SKBUILD_PROJECT_NAME} + VERSION ${SKBUILD_PROJECT_VERSION} + DESCRIPTION "Utilities for reading WRF output" + LANGUAGES C Fortran + ) + +# Safety net +if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) + message( + FATAL_ERROR + "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there.\n" + ) +endif() + +find_package(Python COMPONENTS Interpreter Development.Module NumPy REQUIRED) + +# Ensure scikit-build modules +if (NOT SKBUILD) + # Kanged --> https://github.com/Kitware/torch_liberator/blob/master/CMakeLists.txt + # If skbuild is not the driver; include its utilities in CMAKE_MODULE_PATH + execute_process( + COMMAND "${Python_EXECUTABLE}" + -c "import os, skbuild; print(os.path.dirname(skbuild.__file__))" + OUTPUT_VARIABLE SKBLD_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + list(APPEND CMAKE_MODULE_PATH "${SKBLD_DIR}/resources/cmake") + message(STATUS "Looking in ${SKBLD_DIR}/resources/cmake for CMake modules") +endif() + +# Grab the variables from a local Python installation +# NumPy headers +# F2PY headers +execute_process( + COMMAND "${Python_EXECUTABLE}" + -c "import numpy.f2py; print(numpy.f2py.get_include())" + OUTPUT_VARIABLE F2PY_INCLUDE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +find_package(OpenMP COMPONENTS Fortran) +set_source_files_properties(fortran/ompgen.F90 PROPERTIES Fortran_PREPROCESS ON) +# TODO: Figure out the conditionals for running the C Preprocessor on Fortran files +# I think the main thing to be changed is -E -cpp +# Intel is -fpp -save-temps or /fpp on Windows +# or call fpp instead of the fortran compiler to get it to stop after preprocessing +if (${OpenMP_Fortran_FOUND}) + # This would probably be cleaner if I shoved it in the subdirectory + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/fortran") + add_executable(sizes "${CMAKE_SOURCE_DIR}/fortran/build_help/omp_sizes.f90") + target_link_libraries(sizes PUBLIC OpenMP::OpenMP_Fortran) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/fortran/ompgen.F90" + DEPENDS "${CMAKE_SOURCE_DIR}/fortran/ompgen.F90.template" + ${CMAKE_SOURCE_DIR}/fortran/build_help/sub_sizes.py + sizes + COMMAND + ${Python_EXECUTABLE} ${CMAKE_SOURCE_DIR}/fortran/build_help/sub_sizes.py + ${CMAKE_SOURCE_DIR}/fortran/ompgen.F90.template + ${CMAKE_CURRENT_BINARY_DIR}/fortran/ompgen.F90 + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/fortran/omp.f90" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/fortran/ompgen.F90" + COMMAND ${CMAKE_Fortran_COMPILER} -E "${CMAKE_CURRENT_BINARY_DIR}/fortran/ompgen.F90" + -o "${CMAKE_CURRENT_BINARY_DIR}/fortran/omp.f90" ${OpenMP_Fortran_FLAGS} -cpp + ) +else() + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/fortran/omp.f90" + DEPENDS "${CMAKE_SOURCE_DIR}/fortran/ompgen.F90" + COMMAND ${CMAKE_Fortran_COMPILER} -E fortran/ompgen.F90 -o fortran/omp.f90 -cpp + ) +endif() + +# Prepping the module +set(f2py_module_name "_wrffortran") +set(fortran_src_files + "${CMAKE_SOURCE_DIR}/fortran/wrf_constants.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_testfunc.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_user.f90" + "${CMAKE_SOURCE_DIR}/fortran/rip_cape.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_cloud_fracf.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_fctt.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_user_dbz.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_relhl.f90" + "${CMAKE_SOURCE_DIR}/fortran/calc_uh.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_user_latlon_routines.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_pvo.f90" + "${CMAKE_SOURCE_DIR}/fortran/eqthecalc.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_rip_phys_routines.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_pw.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_vinterp.f90" + "${CMAKE_SOURCE_DIR}/fortran/wrf_wind.f90" + "${CMAKE_CURRENT_BINARY_DIR}/fortran/omp.f90") +set(python_src_files + "${CMAKE_SOURCE_DIR}/src/wrf/__init__.py" + "${CMAKE_SOURCE_DIR}/src/wrf/api.py" + "${CMAKE_SOURCE_DIR}/src/wrf/cache.py" + "${CMAKE_SOURCE_DIR}/src/wrf/computation.py" + "${CMAKE_SOURCE_DIR}/src/wrf/config.py" + "${CMAKE_SOURCE_DIR}/src/wrf/constants.py" + "${CMAKE_SOURCE_DIR}/src/wrf/contrib.py" + "${CMAKE_SOURCE_DIR}/src/wrf/coordpair.py" + "${CMAKE_SOURCE_DIR}/src/wrf/decorators.py" + "${CMAKE_SOURCE_DIR}/src/wrf/destag.py" + "${CMAKE_SOURCE_DIR}/src/wrf/extension.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_cape.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_cloudfrac.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_ctt.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_dbz.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_dewpoint.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_geoht.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_helicity.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_latlon.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_omega.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_precip.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_pressure.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_pw.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_rh.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_slp.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_temp.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_terrain.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_times.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_uvmet.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_vorticity.py" + "${CMAKE_SOURCE_DIR}/src/wrf/g_wind.py" + "${CMAKE_SOURCE_DIR}/src/wrf/geobnds.py" + "${CMAKE_SOURCE_DIR}/src/wrf/interp.py" + "${CMAKE_SOURCE_DIR}/src/wrf/interputils.py" + "${CMAKE_SOURCE_DIR}/src/wrf/latlonutils.py" + "${CMAKE_SOURCE_DIR}/src/wrf/metadecorators.py" + "${CMAKE_SOURCE_DIR}/src/wrf/projection.py" + "${CMAKE_SOURCE_DIR}/src/wrf/projutils.py" + "${CMAKE_SOURCE_DIR}/src/wrf/py3compat.py" + "${CMAKE_SOURCE_DIR}/src/wrf/routines.py" + "${CMAKE_SOURCE_DIR}/src/wrf/specialdec.py" + "${CMAKE_SOURCE_DIR}/src/wrf/units.py" + "${CMAKE_SOURCE_DIR}/src/wrf/util.py" + "${CMAKE_SOURCE_DIR}/src/wrf/version.py" +) +set(f2py_module_c "${f2py_module_name}module.c") + +# Target for enforcing dependencies +add_custom_target(genpyf + DEPENDS "${fortran_src_files}" +) +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_c}" + "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_name}-f2pywrappers.f" + "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_name}-f2pywrappers2.f90" + COMMAND ${Python_EXECUTABLE} -m "numpy.f2py" + -m "${f2py_module_name}" + --lower # Important + ${fortran_src_files} + DEPENDS "${fortran_src_files}" # Fortran source +) + +Python_add_library(${f2py_module_name} MODULE + "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_c}" + "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_name}-f2pywrappers.f" + "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_name}-f2pywrappers2.f90" + "${F2PY_INCLUDE_DIR}/fortranobject.c" + "${fortran_src_files}") + +target_include_directories(${f2py_module_name} PUBLIC + ${F2PY_INCLUDE_DIR} + ${Python_NumPy_INCLUDE_DIRS} + ${Python_INCLUDE_DIRS}) +set_target_properties(${f2py_module_name} PROPERTIES SUFFIX ".${Python_SOABI}${CMAKE_SHARED_MODULE_SUFFIX}") +set_target_properties(${f2py_module_name} PROPERTIES PREFIX "") + +# https://scikit-build-core.readthedocs.io/en/latest/getting_started.html +target_link_libraries(${f2py_module_name} PRIVATE Python::NumPy) +if (${OpenMP_Fortran_FOUND}) + target_link_libraries(${f2py_module_name} PUBLIC OpenMP::OpenMP_Fortran) +endif() + +# Linker fixes +if (UNIX) + if (APPLE) + set_target_properties(${f2py_module_name} PROPERTIES + LINK_FLAGS '-Wl,-dylib,-undefined,dynamic_lookup') + else() + set_target_properties(${f2py_module_name} PROPERTIES + LINK_FLAGS '-Wl,--allow-shlib-undefined') + endif() +endif() + +add_dependencies(${f2py_module_name} genpyf) + +if (NOT SKBUILD) + string(REGEX REPLACE "^/(usr/(local/)?)?" "" Python_SITEARCH_INSTALL ${Python_SITEARCH}) + string(REGEX REPLACE "^/(usr/(local/)?)?" "" Python_SITELIB_INSTALL ${Python_SITELIB}) + # string(SUBSTRING ${Python_SITEARCH} 1 -1 Python_SITEARCH_INSTALL) + # string(SUBSTRING ${Python_SITELIB} 1 -1 Python_SITELIB_INSTALL) + + install(TARGETS ${f2py_module_name} DESTINATION "${Python_SITEARCH_INSTALL}/wrf/") + install(FILES ${python_src_files} DESTINATION "${Python_SITELIB_INSTALL}/wrf/") + install(FILES src/wrf/data/psadilookup.dat DESTINATION "${Python_SITELIB_INSTALL}/wrf") +else() + # https://scikit-build-core.readthedocs.io/en/latest/cmakelists.html#install-directories + install(TARGETS ${f2py_module_name} DESTINATION "${SKBUILD_PLATLIB_DIR}/wrf/") +endif() diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b132591..fb043f2 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,182 +1,75 @@ -# Contributor Code of Conduct - -## Related Code of Conduct - -Participant Code of Conduct -[https://www2.fin.ucar.edu/ethics/participant-code-conduct](https://www2.fin.ucar.edu/ethics/participant-code-conduct) +# Code of Conduct ## Our Pledge -We, as contributors and maintainers (participants), of WRF-Python pledge to -make participation in our software project and community a safe, productive, -welcoming and inclusive experience for everyone. All participants are required -to abide by this Code of Conduct. This includes respectful treatment of -everyone regardless of age, body size, disability, ethnicity, gender identity -or expression, level of experience, nationality, political affiliation, -veteran status, pregnancy, genetic information, physical appearance, race, -religion, or sexual orientation, as well as any other characteristic protected -under applicable US federal or state law. +We, as contributors, creators, stewards, and maintainers (collectively referred to as "contributors" below), of WRF-Python pledge to make participation in our software, system or hardware project and community a safe, productive, and welcoming experience for everyone. All contributors are required to abide by this Code of Conduct. This includes respectful treatment of everyone regardless of age, body size, disability, ethnicity, gender identity or expression, level of experience, nationality, political affiliation, veteran status, pregnancy, genetic information, physical appearance, race, religion, or sexual orientation, as well as any other characteristic protected under applicable US federal or state law. ## Our Standards Examples of behaviors that contribute to a positive environment include: -* Using welcoming and inclusive language -* Respectful when offering and gracefully accepting constructive criticism -* Acknowledging the contributions of others -* Focusing on what is best for the community -* Showing empathy towards other community members -* Treating everyone with respect and consideration, valuing a diversity of - views and opinions -* Communicating openly with respect for others, critiquing ideas rather than - individuals +- All contributors are treated with respect and consideration +- Be considerate, respectful, and collaborative +- Communicate openly with respect for others, critiquing ideas rather than individuals and gracefully accepting criticism +- Acknowledging the contributions of others +- Avoid personal attacks directed toward other contributors +- Be mindful of your surroundings and of your fellow contributors +- Alert UCAR staff and suppliers/vendors if you notice a dangerous situation or someone in distress +- Respect the rules and policies of the project and venue Examples of unacceptable behavior include, but are not limited to: -* Harassment, intimidation, or discrimination in any form -* Personal attacks directed toward other participants -* Unwelcome sexual attention or advances -* Inappropriate, negative, derogatory comments and/or attacks on personal - beliefs -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Refusing to use the pronouns that someone requests -* Alarming, intimidating, threatening, or hostile comments or conduct -* Physical or verbal abuse by anyone to anyone, including but not limited to a - participant, member of the public, guest, member of any institution or - sponsor -* Comments related to characteristics given in the pledge at the top -* Inappropriate use of nudity and/or sexual images -* Threatening or stalking other participants -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- Harassment, intimidation, or discrimination in any form +- Physical, verbal, or written abuse by anyone to anyone +- Unwelcome sexual attention or advances +- Personal attacks directed at other guests, members, contributors, etc. +- Publishing others’ private information, such as a physical or electronic address, without explicit permission +- Alarming, intimidating, threatening, or hostile comments or conduct +- Inappropriate use of nudity and/or sexual images +- Threatening or stalking anyone, including a contributor +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Scope -This Code of Conduct applies to all spaces managed by the Project whether it -be online or face-to-face. This includes project code, code repository, -associated web pages, documentation, mailing lists, project websites and -wiki pages, issue tracker, meetings, telecons, events, project social media -accounts, and any other forums created by the project team which the community -uses for communication. In addition, violations of this Code of Conduct -outside these spaces may affect a person's ability to participate within them. -Representation of a project may be further defined and clarified by project -maintainers. +This Code of Conduct applies to all spaces managed by the Project whether they be physical, online or face-to-face. This includes project code, code repository, associated web pages, documentation, mailing lists, project websites and wiki pages, issue tracker, meetings, telecons, events, project social media accounts, and any other forums created by the project team which the community uses for communication. In addition, violations of this Code of Conduct outside these spaces may affect a person's ability to participate within them. Representation of a project may be further defined and clarified by project maintainers. ## Community Responsibilities -Everyone in the community is empowered to respond to people who are showing -unacceptable behavior. They can talk to them privately or publicly. Anyone -requested to stop unacceptable behavior is expected to comply immediately. -If the behavior continues concerns may be brought to the project -administrators or to any other party listed in the Reporting section below. +Everyone in the community is empowered to respond to people who are showing unacceptable behavior. They can talk to them privately or publicly. Anyone requested to stop unacceptable behavior is expected to comply immediately. If the behavior continues concerns may be brought to the project administrators or to any other party listed in the Reporting section below. ## Project Administrator Responsibilities -Project Administrators are responsible for clarifying the standards of -acceptable behavior and are encouraged to model appropriate behavior and -provide support when people in the community point out inappropriate behavior. -Project administrator(s) are normally the ones that would be tasked to carry -out the actions in the Consequences section below. +Project administrators are responsible for clarifying the standards of acceptable behavior and are encouraged to model appropriate behavior and provide support when people in the community point out inappropriate behavior. Project administrator(s) are normally the ones that would be tasked to carry out the actions in the Consequences section below. -Project Administrators are also expected to keep this Code of Conduct updated -with the main one housed at UCAR as listed below in the Attribution section. +Project administrators are also expected to keep this Code of Conduct updated with the main one housed at UCAR, as listed below in the Attribution section. ## Reporting -Instances of unacceptable behavior can be brought to the attention of the -project administrator(s) who may take any action as outlined in the -Consequences section below. However, making a report to a project -administrator is not considered an 'official report' to UCAR. +Instances of unacceptable behavior can be brought to the attention of the project administrator(s) who may take any reasonable and necessary action to address and stop the behavior. However, making a report to a project administrator is not considered an ‘official report’ to UCAR. + +Instances of unacceptable behavior may also be reported: +- To [The Chief Human Resources Officer](chro@ucar.edu) who serves as UCAR’s Section 504, Title VI, VII and IX Coordinator; +- Through [UCAR’s Reporting a Concern website](https://www.ucar.edu/who-we-are/ethics); or +- Anonymously through [UCAR’s EthicsPoint Hotline](https://www.ucar.edu/who-we-are/ethics). -Instances of unacceptable behavior may also be reported directly to UCAR via -UCAR's Harassment Reporting and Complaint Procedure at [https://www2.fin.ucar.edu/procedures/hr/harassment-reporting-and-complaint-procedure](https://www2.fin.ucar.edu/procedures/hr/harassment-reporting-and-complaint-procedure), -or anonymously through UCAR's EthicsPoint Hotline at [https://www2.fin.ucar.edu/ethics/anonymous-reporting](https://www2.fin.ucar.edu/ethics/anonymous-reporting). +Complaints received by UCAR will be handled pursuant to the procedures outlined in [UCAR’s Complaint and Investigations Procedures](https://sundog.ucar.edu/Interact/Pages/Content/Document.aspx?id=5140). Complaints to UCAR will be held as confidential as practicable under the circumstances, and retaliation against a person who initiates a complaint or an inquiry about inappropriate behavior will not be tolerated. -Complaints received by UCAR will be handled pursuant to the procedures -outlined in UCAR's Harassment Reporting and Complaint Procedure. Complaints -to UCAR will be held as confidential as practicable under the circumstances, -and retaliation against a person who initiates a complaint or an inquiry about -inappropriate behavior will not be tolerated. +If you require a reasonable accommodation due to a disability or for assistance as an individual with Limited English Proficiency (LEP), please contact UCAR's [Chief Human Resources Officer](chro@ucar.edu). -Any Contributor can use these reporting methods even if they are not directly -affiliated with UCAR. The Frequently Asked Questions (FAQ) page for reporting -is here: [https://www2.fin.ucar.edu/procedures/hr/reporting-faqs](https://www2.fin.ucar.edu/procedures/hr/reporting-faqs). +Any Contributor can use these reporting methods even if they are not directly affiliated with UCAR. The Frequently Asked Questions (FAQ) page for reporting is [here](https://www.ucar.edu/who-we-are/ethics). ## Consequences -Upon receipt of a complaint, the project administrator(s) may take any action -deemed necessary and appropriate under the circumstances. Such action can -include things such as: removing, editing, or rejecting comments, commits, -code, wiki edits, email, issues, and other contributions that are not aligned -to this Code of Conduct, or banning temporarily or permanently any contributor -for other behaviors that are deemed inappropriate, threatening, offensive, or -harmful. Project Administrators also have the right to report violations to -UCAR HR and/or UCAR's Office of Diversity, Equity and Inclusion (ODEI) as -well as a participant's home institution and/or law enforcement. In the event -an incident is reported to UCAR, UCAR will follow its Harassment Reporting -and Complaint Procedure. +Upon receipt of a complaint, the project administrator(s) may take any action deemed necessary and appropriate under the circumstances. Such action can include things such as: removing, editing, or rejecting comments, commits, code, wiki edits, email, issues, and other contributions that are not aligned to this Code of Conduct, or banning temporarily or permanently any contributor for other behaviors that are deemed inappropriate, threatening, offensive, or harmful. Project administrators also have the right to report violations to UCAR HR as well as to a contributor’s home institution and/or law enforcement. In the event an incident is reported to UCAR, UCAR will follow its Complaint and Investigations Procedure. ## Process for Changes -All UCAR managed projects are required to adopt this Contributor Code of -Conduct. Adoption is assumed even if not expressly stated in the repository. -Projects should fill in sections where prompted with project-specific -information, including, project name, email addresses, adoption date, etc. -There is one section below marked "optional" that may not apply to a given -project. +All UCAR managed projects are required to adopt this Contributor Code of Conduct. Adoption is assumed even if not expressly stated in the repository. Projects should fill in sections where prompted with project-specific information, including, project name and adoption date. -Projects that adopt this Code of Conduct need to stay up to date with -UCAR's Contributor Code of Conduct, linked with a DOI in the "Attribution" -section below. Projects can make limited substantive changes to the Code of -Conduct, however, the changes must be limited in scope and may not contradict -the UCAR Contributor Code of Conduct. +Projects that adopt this Code of Conduct need to stay up to date with UCAR's Contributor Code of Conduct, linked with a DOI in the Attribution section below. Projects can make limited substantive changes to the Code of Conduct, however, the changes must be limited in scope and may not contradict the UCAR Contributor Code of Conduct. ## Attribution -This Code of Conduct was originally adapted from the Contributor Covenant, -version 1.4, available at [Contributor-Covenant](http://contributor-covenant.org/version/1/4). -We then aligned it with the UCAR Participant Code of Conduct, which also -borrows from the American Geophysical Union (AGU) Code of Conduct. The UCAR -Participant Code of Conduct applies to both UCAR employees as well as -participants in activities run by UCAR. We modified the "scope" section with -the django project description, and we added "Publication Ethics" from -the NGEET/FATES project. The original version of this for all software -projects that have strong management from UCAR or UCAR staff is available -on the UCAR website at [*Enter DOI link name*] (the date that it was adopted -by this project was [*Enter date adopted*]). When responding to complaints -UCAR HR and ODEI will do so based on the latest published version. Therefore, -any project-specific changes should follow the Process for Changes section -above. - -## Publication Ethics (optional) - -We aim to create an open development environment where developers can be -confident that all members of the community are publishing any research -on the project in an ethical manner. In particular, writing code is a form of -intellectual contribution, and one should expect that all such intellectual -contributions are respected and given credit in any resulting published work. -To support the community and avoid issues of misconduct related to the above -principle, please respect the following rules: - -* Document the version of the code used in any publication, preferably by - either using a release tag (existing or newly created) if possible, or a - commit hash if not. - -* Do not use code from anywhere other than the central project's development - repository main development branch without discussing with the author(s) of - the modified code your intentions for using the code and receiving their - permission to do so. - -* When using project features that have recently been integrated into the - central Project development repository, be mindful of the contributions - of others and, where the novel features qualitatively affect the results, - involve the author(s) of these features in any resulting manuscripts. - Be particularly aware of the concerns of early career researchers, and - ensure they have sufficient time to lead publications using their - developments. - -* When discussing results arising from older project features that have been -described in the literature or releases, accurately cite the publications -describing those features or releases. +This Code of Conduct was originally adapted from the [Contributor Covenant](http://contributor-covenant.org/version/1/4), version 1.4. We then aligned it with the UCAR Participant Code of Conduct, which also borrows from the American Geophysical Union (AGU) Code of Conduct. The UCAR Participant Code of Conduct applies to both UCAR employees as well as participants in activities run by UCAR. The original version of this for all software projects that have strong management from UCAR or UCAR staff is available on the UCAR website at [https://doi.org/10.5065/6w2c-a132](https://doi.org/10.5065/6w2c-a132). The date that it was adopted by this project was April 2, 2025. When responding to complaints, UCAR HR will do so based on the latest published version. Therefore, any project-specific changes should follow the Process for Changes section above. +As an Equal Employment Opportunity Employer and recipient of federal funds, UCAR complies with Title VI, Title VII, and Title IX of the Civil Rights Act; the Rehabilitation Act of 1973, as amended, and the Age Discrimination in Employment Act of 1975, as amended. See [UCAR’s Nondiscrimination Statement](https://www.ucar.edu/who-we-are/ethics-integrity/nondiscrimination). diff --git a/LICENSE b/LICENSE index 525a044..18c9b18 100644 --- a/LICENSE +++ b/LICENSE @@ -1,14 +1,202 @@ -Copyright 2016 University Corporation for Atmospheric Research +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 University Corporation for Atmospheric Research + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MANIFEST.in b/MANIFEST.in index 79b786b..44c6fbd 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include README.md include LICENSE -include requirements.txt include fortran/*.f90 include fortran/*.pyf diff --git a/README.md b/README.md index 3a40651..13f6420 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,8 @@ http://wrf-python.rtfd.org Citation ------------------ - Ladwig, W. (2017). wrf-python (Version x.x.x) [Software]. Boulder, Colorado: UCAR/NCAR. https://doi.org/10.5065/D6W094P1 - -Note: The version number x.x.x should be set to the version of wrf-python that you are using. +If you use this software, please cite it as described at the [WRF-Python - Citation]( +https://wrf-python.readthedocs.io/en/latest/citation.html) page. -------------------- diff --git a/build_envs/environment.yml b/build_envs/environment.yml new file mode 100644 index 0000000..4c646a3 --- /dev/null +++ b/build_envs/environment.yml @@ -0,0 +1,22 @@ +# Create full conda environment for development, including some useful tools +name: wrf_python_build +channels: + - conda-forge +dependencies: + - python>=3.9, <3.13 + - compilers + - basemap + - cartopy + - jupyter + - matplotlib + - netcdf4 + - numpy + - pycodestyle + - setuptools + - sphinx + - sphinx_rtd_theme + - sphinxcontrib-googleanalytics + - wrapt + - xarray + - python-build + - pip diff --git a/build_envs/platform-specific/README.md b/build_envs/platform-specific/README.md new file mode 100644 index 0000000..de69662 --- /dev/null +++ b/build_envs/platform-specific/README.md @@ -0,0 +1,3 @@ +These platform specific environment files are included here for reference only and not actively tested or maintained. + +We have moved to a single environment file (../environment.yml) for all platforms. diff --git a/build_envs/Linux.yml b/build_envs/platform-specific/linux.yml similarity index 95% rename from build_envs/Linux.yml rename to build_envs/platform-specific/linux.yml index 60af2aa..c348960 100644 --- a/build_envs/Linux.yml +++ b/build_envs/platform-specific/linux.yml @@ -3,7 +3,7 @@ name: wrf_python_build channels: - conda-forge dependencies: - - python=3 + - python<3.12 - basemap - cartopy - gcc_linux-64 diff --git a/build_envs/platform-specific/macos_arm64.yml b/build_envs/platform-specific/macos_arm64.yml new file mode 100644 index 0000000..2e475f0 --- /dev/null +++ b/build_envs/platform-specific/macos_arm64.yml @@ -0,0 +1,21 @@ +# Create full conda environment for development, including some useful tools +name: wrf_python_build +channels: + - conda-forge +dependencies: + - python<3.12 + - basemap + - cartopy + - clang_osx-arm64 + - gfortran_osx-arm64 + - jupyter + - matplotlib + - netcdf4 + - numpy + - pycodestyle + - setuptools + - sphinx + - sphinx_rtd_theme + - wrapt + - xarray + diff --git a/build_envs/Darwin.yml b/build_envs/platform-specific/macos_x64.yml similarity index 95% rename from build_envs/Darwin.yml rename to build_envs/platform-specific/macos_x64.yml index 044292e..2415ebe 100644 --- a/build_envs/Darwin.yml +++ b/build_envs/platform-specific/macos_x64.yml @@ -3,7 +3,7 @@ name: wrf_python_build channels: - conda-forge dependencies: - - python=3 + - python<3.12 - basemap - cartopy - clang_osx-64 diff --git a/build_envs/Win64.yml b/build_envs/platform-specific/windows.yml similarity index 95% rename from build_envs/Win64.yml rename to build_envs/platform-specific/windows.yml index e9bb70a..1053db0 100644 --- a/build_envs/Win64.yml +++ b/build_envs/platform-specific/windows.yml @@ -4,7 +4,7 @@ channels: - conda-forge - msys2 dependencies: - - python=3 + - python<3.12 - basemap - cartopy - jupyter diff --git a/build_scripts/gnu_omp.sh b/build_scripts/gnu_omp.sh index 03faa1b..46dded6 100755 --- a/build_scripts/gnu_omp.sh +++ b/build_scripts/gnu_omp.sh @@ -11,6 +11,7 @@ $FC -E ompgen.F90 -fopenmp -cpp -o omp.f90 cd .. python setup.py clean --all +export LDFLAGS=" -fopenmp " python setup.py config_fc --f90flags="-mtune=generic -fopenmp" build_ext --libraries="gomp" build pip install . diff --git a/conda_recipe/LICENSE b/conda_recipe/LICENSE deleted file mode 100644 index 376dd79..0000000 --- a/conda_recipe/LICENSE +++ /dev/null @@ -1,32 +0,0 @@ -PLEASE READ THIS SOFTWARE LICENSE ("LICENSE") CAREFULLY BEFORE USING THE -SOFTWARE. BY USING THE SOFTWARE, YOU ARE AGREEING TO BE BOUND BY ALL OF THE -TERMS OF THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE, -DO NOT USE THE SOFTWARE. - -Copyright © 2016 the University Corporation for Atmospheric Research ("UCAR"). -All rights reserved. Developed by NCAR's Computational and Information Systems -Laboratory, UCAR, www2.cisl.ucar.edu. - -Redistribution and use of the Software in source and binary forms, with or -without modification, is permitted provided that the following conditions -are met: - -- Neither the names of NCAR's Computational and Information Systems Laboratory, - the University Corporation for Atmospheric Research, nor the names of its - sponsors or contributors may be used to endorse or promote products derived - from this Software without specific prior written permission. - -- Redistributions of source code must retain the above copyright notices, this - list of conditions, and the disclaimer below. - -- Redistributions in binary form must reproduce the above copyright notice, this - list of conditions, and the disclaimer below in the documentation and/or other - materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. diff --git a/conda_recipe/bld.bat b/conda_recipe/bld.bat deleted file mode 100644 index d4a4a3f..0000000 --- a/conda_recipe/bld.bat +++ /dev/null @@ -1,19 +0,0 @@ -cd fortran\build_help -CALL gfortran -o sizes -fopenmp omp_sizes.f90 -CALL python sub_sizes.py - -cd .. -CALL gfortran -E ompgen.F90 -cpp -fopenmp -o omp.f90 -REM Wildcards not working on Windows for some reason -CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90 -cd .. - -IF %ARCH% == 64 ( - CALL %PYTHON% setup.py config_fc --f90flags="-O2 -mtune=generic -fopenmp" build_ext --libraries="gomp" build --compiler=msvc --fcompiler=gnu95 -) ELSE ( - CALL %PYTHON% setup.py config_fc --f90flags="-O2 -mtune=generic -fopenmp -mincoming-stack-boundary=2" build_ext --libraries="gomp" build --compiler=msvc --fcompiler=gnu95 -) - -CALL %PYTHON% setup.py install --single-version-externally-managed --record=record.txt - - diff --git a/conda_recipe/build.sh b/conda_recipe/build.sh deleted file mode 100644 index feace2b..0000000 --- a/conda_recipe/build.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -cd fortran/build_help -if [ `uname` == Darwin ]; then - gfortran -o sizes -fopenmp omp_sizes.f90 -Wl,-rpath,${CONDA_PREFIX}/lib -else - gfortran -o sizes -fopenmp omp_sizes.f90 -fi -python sub_sizes.py - -cd .. -gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90 -f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature -cd .. - -if [ `uname` == Darwin ]; then - LDFLAGS="$LDFLAGS -undefined dynamic_lookup -bundle" -fi - -$PYTHON setup.py config_fc --f90flags="-mtune=generic -fopenmp" build_ext --libraries="gomp" build - -$PYTHON setup.py install --single-version-externally-managed --record=record.txt diff --git a/conda_recipe/meta.yaml b/conda_recipe/meta.yaml deleted file mode 100644 index 060b824..0000000 --- a/conda_recipe/meta.yaml +++ /dev/null @@ -1,62 +0,0 @@ -{% set version = "1.3.2.6" %} - -package: - name: wrf-python - version: {{ version }} - -source: -# for develop - git_url: https://github.com/NCAR/wrf-python - git_branch: develop -# for release -# fn: wrf-python-{{ version }}.tar.gz -# url: https://github.com/NCAR/wrf-python/archive/{{ version }}.tar.gz -# sha256: 9ca11366ed9a0d5e83e576ac80ce36be4748ba8a06752dac077277acec5e46d9 - -build: - number: 0 - detect_binary_files_with_prefix: true - -requirements: - build: - - setuptools - - python - - numpy 1.11.* # [unix] - - numpy 1.14.* # [win] - - wrapt - - m2w64-toolchain # [win] - - gcc # [unix] - run: - - setuptools - - numpy >=1.11 # [unix] - - numpy >=1.14 # [win] - - python - - wrapt - - m2w64-gcc-libs # [win] - - libgfortran # [unix] - - libgcc # [unix] - - xarray - -test: - requires: - - setuptools - - netcdf4 - - xarray - source_files: - - test/ci_tests - imports: - - wrf - commands: - - cd test/ci_tests && python utests.py - -about: - home: https://github.com/NCAR/wrf-python - license: "UCAR" - license_file: '{{ environ["RECIPE_DIR"] }}/LICENSE' - summary: "Diagnostic and interpolation routines for WRF-ARW data." - -extra: - recipe-maintainers: - - michaelavs - - erogluorhan - diff --git a/doc/source/citation.rst b/doc/source/citation.rst index 89c35c4..1ad5317 100644 --- a/doc/source/citation.rst +++ b/doc/source/citation.rst @@ -1,26 +1,49 @@ .. _citation: Citation -================= +========== -WRF-Python has a Digital Object Identifier (DOI), which is a persistent -identifier for web-based resources. The wrf-python DOI, when used in URL form, -https://doi.org/10.5065/D6W094P1, provides a persistent link to the wrf-python -Github page. The benefit of DOIs is that they are widely accepted by academic -publishers as citable locators for scholarly objects. +How to cite WRF-Python +----------------------- -If you author a paper that involves data analysis with wrf-python, or -visualizations created with wrf-python, we would like to ask you to please -cite wrf-python. This helps us better understand the impact of the software on -the scientific community, which in turns helps us maintain support for the -effort. +If you use this software, please cite it as described below: -You can cite wrf-python using the following citation: +WRF-Python has a Digital Object Identifier (DOI), which is a persistent identifier for +web-based resources. The benefit of DOIs is that they are widely accepted by academic publishers +as citable locators for scholarly objects. The WRF-Python DOI, when used in URL form, +`https://doi.org/10.5065/D6W094P1 `_, provides a persistent link +to the WRF-Python GitHub repository, and can be used to cite the WRF-Python project as a whole. -.. code-block:: none +In addition, each WRF-Python version is assigned a separate DOI to allow users to access older +releases. This ensures that users are not only able to cite the specific software version through +DOIs but are also able to download & use the corresponding release for reproducibility purposes. - Ladwig, W. (2017). wrf-python (Version x.x.x) [Software]. Boulder, Colorado: UCAR/NCAR. https://doi.org/10.5065/D6W094P1 - -.. note:: +If you would like to cite WRF-Python as a whole (without referring to a specific version), use +the following text: - The version number x.x.x should be set to the version of wrf-python that you are using. \ No newline at end of file +**Visualization & Analysis Systems Technologies. (2017). +Geoscience Community Analysis Toolkit: WRF-Python [Software]. +Boulder, CO: UCAR/NCAR - Computational and Informational System Lab. doi:10.5065/D6W094P1.** + +Instead, if you would like to cite a specific version of WRF-Python, use the following text: + +**Visualization & Analysis Systems Technologies. (Year). +Geoscience Community Analysis Toolkit: WRF-Python (v\) [Software]. +Boulder, CO, USA: UCAR/NCAR - Computational and Informational System Lab. doi:\.** + +In the above citation text, update the year, WRF-Python version, and DOI as appropriate. For +example: + +**Visualization & Analysis Systems Technologies. (2022). +Geoscience Community Analysis Toolkit: WRF-Python (v1.3.4.1) [Software]. +Boulder, CO, USA: UCAR/NCAR - Computational and Informational System Lab. doi:10.5281/zenodo.6685115.** + +Please find DOIs for all the WRF-Python versions `here +`_. + +Please note: The DOI minting service, Zenodo, might be suggesting their own citation text (as +they are the publisher of such DOIs) in their website. We prefer the text we recommend here to be used; +however, either way is acceptable. + +For further information, please refer to +`GeoCAT homepage - Citation `_. diff --git a/doc/source/conf.py b/doc/source/conf.py index 26a6073..3c89989 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -75,9 +75,12 @@ def mock_asscalar(val): 'sphinx.ext.napoleon', 'sphinx.ext.autosummary', 'sphinx.ext.intersphinx', - 'sphinx.ext.mathjax' + 'sphinx.ext.mathjax', + 'sphinxcontrib.googleanalytics' ] +googleanalytics_id = 'G-6WSSSBGTH8' + #mathjax_path = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" intersphinx_mapping = { diff --git a/doc/source/contrib.rst b/doc/source/contrib.rst index 0f96d18..d11fa76 100644 --- a/doc/source/contrib.rst +++ b/doc/source/contrib.rst @@ -294,28 +294,13 @@ contributing is: git remote add ncar https://github.com/ncar/wrf-python.git -- To create the development environment, you'll need to run the appropriate - command below for your operating system. - - OSX: - - .. code:: - - conda env create -f build_envs/Darwin.yml - - Linux: - - .. code:: - - conda env create -f build_envs/Linux.yml - - Win64: +- To create the development environment, you'll need to run the command below: .. code:: - conda env create -f build_envs/Win64.yml + conda env create -f build_envs/environment.yml - Note: For Win64, you will also need VS2015 installed on your system. + Note: For Windows, you will also need Visual Studio installed on your system. - Activate your conda environment. diff --git a/doc/source/installation.rst b/doc/source/installation.rst index 4088af2..c35c7fc 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -4,7 +4,7 @@ Installation Required Dependencies ---------------------- - - Python 2.7, 3.4, or 3.5+ + - Python 3.9+ - numpy (1.11 or later; 1.14 required to build on Windows) - wrapt (1.10 or later) - setuptools (38.0 or later) diff --git a/doc/source/new.rst b/doc/source/new.rst index 6e8719d..364af0b 100644 --- a/doc/source/new.rst +++ b/doc/source/new.rst @@ -4,6 +4,15 @@ What's New Releases ------------- +v1.4.0 (May 2025) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Release 1.4.0 +- Transition to CMake build using scikit-build-core +- Packaging updates and adoption of pyproject.toml +- Support for Python 3.12 +- Support for macOS ARM architecture + v1.3.2 (February 2019) ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/source/tutorials/wrf_workshop_2019.rst b/doc/source/tutorials/wrf_workshop_2019.rst index d2a1925..7f697e7 100644 --- a/doc/source/tutorials/wrf_workshop_2019.rst +++ b/doc/source/tutorials/wrf_workshop_2019.rst @@ -82,7 +82,7 @@ Step 2: Download Miniconda ---------------------------- For this tutorial, you will need to download and install Miniconda. We are -going to use Python 3.7, but it will also work with Python 2.7. +going to use Python 3.7, but it will also work with Python 2.7. Please use the appropriate link below to download Miniconda for your operating system. diff --git a/fortran/build_help/sub_sizes.py b/fortran/build_help/sub_sizes.py index d69b6e8..bb91eb6 100644 --- a/fortran/build_help/sub_sizes.py +++ b/fortran/build_help/sub_sizes.py @@ -41,6 +41,9 @@ def main(): ompgen_temp_path = os.path.join("..", "ompgen.F90.template") ompgen_out_path = os.path.join("..", "ompgen.F90") + if len(sys.argv) == 3: + ompgen_temp_path = sys.argv[1] + ompgen_out_path = sys.argv[2] with open(ompgen_temp_path, "r") as ompgen_in: ompgen_template = Template(ompgen_in.read()) diff --git a/fortran/omp.f90 b/fortran/omp.f90 index dce6b1d..0480fe6 100644 --- a/fortran/omp.f90 +++ b/fortran/omp.f90 @@ -7,6 +7,9 @@ MODULE omp_constants INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_dynamic = 2 INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_guided = 3 INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_auto = 4 +contains + subroutine have_omp_constants() + end subroutine have_omp_constants END MODULE omp_constants diff --git a/fortran/ompgen.F90 b/fortran/ompgen.F90 index 14fa7d4..4b2920b 100644 --- a/fortran/ompgen.F90 +++ b/fortran/ompgen.F90 @@ -20,6 +20,10 @@ MODULE omp_constants INTEGER(KIND=4), PARAMETER :: fomp_sched_auto = 4 #endif +contains + subroutine have_omp_constants() + end subroutine have_omp_constants + END MODULE omp_constants diff --git a/fortran/ompgen.F90.template b/fortran/ompgen.F90.template index 00a50d5..92be74b 100644 --- a/fortran/ompgen.F90.template +++ b/fortran/ompgen.F90.template @@ -20,6 +20,10 @@ MODULE omp_constants INTEGER(KIND=4), PARAMETER :: fomp_sched_auto = 4 #endif +contains + subroutine have_omp_constants() + end subroutine have_omp_constants + END MODULE omp_constants diff --git a/fortran/wrf_constants.f90 b/fortran/wrf_constants.f90 index 0864502..ebc5667 100644 --- a/fortran/wrf_constants.f90 +++ b/fortran/wrf_constants.f90 @@ -69,6 +69,9 @@ MODULE wrf_constants REAL(KIND=8), PARAMETER :: EXPON = RD*USSALR/G REAL(KIND=8), PARAMETER :: EXPONI = 1./EXPON + contains + subroutine have_wrf_constants() + end subroutine have_wrf_constants END MODULE wrf_constants diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..5047e19 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,78 @@ +[build-system] +requires = ["scikit-build-core", "numpy"] +build-backend = "scikit_build_core.build" + +[project] +name = "wrf-python" +authors = [ + { name = "Bill Ladwig" } +] +maintainers = [ + { name = "GeoCAT", email = "geocat@ucar.edu" }, +] +description = "Diagnostic and interpolation routines for WRF-ARW data." +readme = "README.md" +requires-python = ">=3.9, <3.13" +keywords = [ + "python", "wrf-python", "wrf", "forecast", "model", + "weather research and forecasting", "interpolation", + "plotting", "plots", "meteorology", "nwp", + "numerical weather prediction", "diagnostic", + "science", "numpy" +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Fortran", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Atmospheric Science", + "Topic :: Software Development", + "Operating System :: POSIX", + "Operating System :: Unix", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows" +] +license = { text = "Apache-2.0" } +dynamic = [ "version" ] +dependencies = [ + "basemap", + "numpy >=1.11, !=1.24.3", + "setuptools>=61", + "wrapt", + "xarray" +] + +[project.urls] +Repository = "https://github.com/NCAR/wrf-python" +Documentation = "https://wrf-python.rtfd.org" + +[tool.setuptools] +package-data = { "wrf" = ["data/psadilookup.dat"]} +platforms = ["any"] + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools.dynamic] +version = { attr = "wrf.version.__version__" } + +[tool.scikit-build] +cmake.verbose = true +logging.level = "INFO" +minimum-version = "0.8" +cmake.version = ">=3.18" +wheel.packages = ["src/wrf"] + +# To avoid stripping installed libraries +# Packages often want to do their own stripping +# SKBUILD_INSTALL_STRIP: "false" +# install.strip = false + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "src/wrf/version.py" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 67027d4..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -numpy>=1.11 -wrapt -setuptools diff --git a/setup.py b/setup.py deleted file mode 100755 index 9304ff4..0000000 --- a/setup.py +++ /dev/null @@ -1,119 +0,0 @@ -import os -import sys -import setuptools -import socket - -# Bootstrap a numpy installation before trying to import it. -import imp -try: - imp.find_module('numpy') -except ImportError: - import subprocess - subprocess.call([sys.executable, '-m', 'pip', 'install', 'numpy']) - -if not socket.gethostname().startswith("cheyenne"): - import numpy.distutils.core -else: - import chey_intel - import numpy.distutils.core - import numpy.distutils.fcompiler.intel - - numpy.distutils.fcompiler.intel.IntelFCompiler = chey_intel.IntelFCompiler - numpy.distutils.fcompiler.intel.IntelVisualFCompiler = ( - chey_intel.IntelVisualFCompiler) - numpy.distutils.fcompiler.intel.IntelItaniumFCompiler = ( - chey_intel.IntelItaniumFCompiler) - numpy.distutils.fcompiler.intel.IntelItaniumVisualFCompiler = ( - chey_intel.IntelItaniumVisualFCompiler) - numpy.distutils.fcompiler.intel.IntelEM64VisualFCompiler = ( - chey_intel.IntelEM64VisualFCompiler) - numpy.distutils.fcompiler.intel.IntelEM64TFCompiler = ( - chey_intel.IntelEM64TFCompiler) - -ext1 = numpy.distutils.core.Extension( - name="wrf._wrffortran", - sources=["fortran/wrf_constants.f90", - "fortran/wrf_testfunc.f90", - "fortran/wrf_user.f90", - "fortran/rip_cape.f90", - "fortran/wrf_cloud_fracf.f90", - "fortran/wrf_fctt.f90", - "fortran/wrf_user_dbz.f90", - "fortran/wrf_relhl.f90", - "fortran/calc_uh.f90", - "fortran/wrf_user_latlon_routines.f90", - "fortran/wrf_pvo.f90", - "fortran/eqthecalc.f90", - "fortran/wrf_rip_phys_routines.f90", - "fortran/wrf_pw.f90", - "fortran/wrf_vinterp.f90", - "fortran/wrf_wind.f90", - "fortran/omp.f90"] - ) - -with open("src/wrf/version.py") as f: - exec(f.read()) - -on_rtd = os.environ.get("READTHEDOCS", None) == "True" -# on_rtd=True -if on_rtd: - if sys.version_info < (3, 3): - requirements = ["mock"] # for python2 and python < 3.3 - else: - requirements = [] # for >= python3.3 - ext_modules = [] - -else: - # Place install_requires into the text file "requirements.txt" - with open("requirements.txt") as f2: - requirements = f2.read().strip().splitlines() - - # if sys.version_info < (3,3): - # requirements.append("mock") - ext_modules = [ext1] - - -numpy.distutils.core.setup( - author="Bill Ladwig", - author_email="ladwig@ucar.edu", - description="Diagnostic and interpolation routines for WRF-ARW data.", - long_description=("A collection of diagnostic and interpolation " - "routines to be used with WRF-ARW data.\n\n" - "GitHub Repository:\n\n" - "https://github.com/NCAR/wrf-python\n\n" - "Documentation:\n\n" - "http://wrf-python.rtfd.org\n"), - url="https://github.com/NCAR/wrf-python", - keywords=["python", "wrf-python", "wrf", "forecast", "model", - "weather research and forecasting", "interpolation", - "plotting", "plots", "meteorology", "nwp", - "numerical weather prediction", "diagnostic", - "science", "numpy"], - install_requires=requirements, - classifiers=["Development Status :: 5 - Production/Stable", - "Intended Audience :: Science/Research", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Fortran", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Topic :: Scientific/Engineering :: Atmospheric Science", - "Topic :: Software Development", - "Operating System :: POSIX", - "Operating System :: Unix", - "Operating System :: MacOS", - "Operating System :: Microsoft :: Windows"], - name="wrf-python", - platforms=["any"], - license="Apache License 2.0", - version=__version__, - packages=setuptools.find_packages("src"), - ext_modules=ext_modules, - package_dir={"": "src"}, - download_url="http://python.org/pypi/wrf-python", - package_data={"wrf": ["data/psadilookup.dat"]}, - scripts=[] -) diff --git a/src/wrf/__init__.py b/src/wrf/__init__.py old mode 100755 new mode 100644 diff --git a/src/wrf/config.py b/src/wrf/config.py index fa20201..e133304 100644 --- a/src/wrf/config.py +++ b/src/wrf/config.py @@ -10,37 +10,54 @@ _local_config = local() -def _init_local(): +def _try_enable_xarray(): global _local_config - _local_config.xarray_enabled = True - _local_config.cartopy_enabled = True - _local_config.basemap_enabled = True - _local_config.pyngl_enabled = True - _local_config.cache_size = 20 - _local_config.initialized = True - try: from xarray import DataArray except ImportError: _local_config.xarray_enabled = False + +def _try_enable_cartopy(): + global _local_config + _local_config.cartopy_enabled = True try: from cartopy import crs except ImportError: _local_config.cartopy_enabled = False + +def _try_enable_basemap(): + global _local_config + _local_config.basemap_enabled = True try: from mpl_toolkits.basemap import Basemap except ImportError: _local_config.basemap_enabled = False + +def _try_enable_pyngl(): + global _local_config + _local_config.pyngl_enabled = True try: from Ngl import Resources except ImportError: _local_config.pyngl_enabled = False +def _init_local(): + global _local_config + + _try_enable_xarray() + _try_enable_cartopy() + _try_enable_basemap() + _try_enable_pyngl() + + _local_config.cache_size = 20 + _local_config.initialized = True + + # Initialize the main thread's configuration _init_local() @@ -51,11 +68,11 @@ def init_local(): def func_wrapper(wrapped, instance, args, kwargs): global _local_config try: - init = _local_config.init + initialized = _local_config.initialized except AttributeError: _init_local() else: - if not init: + if not initialized: _init_local() return wrapped(*args, **kwargs) @@ -77,17 +94,16 @@ def xarray_enabled(): @init_local() -def disable_xarray(): - """Disable xarray.""" - global _local_config - _local_config.xarray_enabled = False +def enable_xarray(): + """Enable xarray if it is installed.""" + _try_enable_xarray() @init_local() -def enable_xarray(): - """Enable xarray.""" +def disable_xarray(): + """Disable xarray.""" global _local_config - _local_config.xarray_enabled = True + _local_config.xarray_enabled = False @init_local() @@ -105,16 +121,15 @@ def cartopy_enabled(): @init_local() def enable_cartopy(): - """Enable cartopy.""" - global _local_config - _local_config.cartopy_enabled = True + """Enable cartopy if it is installed.""" + _try_enable_cartopy() @init_local() def disable_cartopy(): """Disable cartopy.""" global _local_config - _local_config.cartopy_enabled = True + _local_config.cartopy_enabled = False @init_local() @@ -132,16 +147,15 @@ def basemap_enabled(): @init_local() def enable_basemap(): - """Enable basemap.""" - global _local_config - _local_config.basemap_enabled = True + """Enable basemap if it is installed.""" + _try_enable_basemap() @init_local() def disable_basemap(): """Disable basemap.""" global _local_config - _local_config.basemap_enabled = True + _local_config.basemap_enabled = False @init_local() @@ -159,16 +173,15 @@ def pyngl_enabled(): @init_local() def enable_pyngl(): - """Enable pyngl.""" - global _local_config - _local_config.pyngl_enabled = True + """Enable pyngl if it is installed.""" + _try_enable_pyngl() @init_local() def disable_pyngl(): """Disable pyngl.""" global _local_config - _local_config.pyngl_enabled = True + _local_config.pyngl_enabled = False @init_local() diff --git a/src/wrf/constants.py b/src/wrf/constants.py old mode 100755 new mode 100644 diff --git a/src/wrf/destag.py b/src/wrf/destag.py old mode 100755 new mode 100644 diff --git a/src/wrf/extension.py b/src/wrf/extension.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_cape.py b/src/wrf/g_cape.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_dbz.py b/src/wrf/g_dbz.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_dewpoint.py b/src/wrf/g_dewpoint.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_geoht.py b/src/wrf/g_geoht.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_helicity.py b/src/wrf/g_helicity.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_latlon.py b/src/wrf/g_latlon.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_omega.py b/src/wrf/g_omega.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_precip.py b/src/wrf/g_precip.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_pressure.py b/src/wrf/g_pressure.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_pw.py b/src/wrf/g_pw.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_rh.py b/src/wrf/g_rh.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_slp.py b/src/wrf/g_slp.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_temp.py b/src/wrf/g_temp.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_terrain.py b/src/wrf/g_terrain.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_times.py b/src/wrf/g_times.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_uvmet.py b/src/wrf/g_uvmet.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_vorticity.py b/src/wrf/g_vorticity.py old mode 100755 new mode 100644 diff --git a/src/wrf/g_wind.py b/src/wrf/g_wind.py old mode 100755 new mode 100644 diff --git a/src/wrf/interp.py b/src/wrf/interp.py old mode 100755 new mode 100644 diff --git a/src/wrf/projection.py b/src/wrf/projection.py index b2aca20..f4d55cd 100644 --- a/src/wrf/projection.py +++ b/src/wrf/projection.py @@ -18,6 +18,7 @@ from Ngl import Resources + if cartopy_enabled(): class MercatorWithLatTS(crs.Mercator): """A :class:`cartopy.crs.Mercator` subclass that adds support for @@ -60,6 +61,10 @@ def __init__(self, central_longitude=0.0, ("units", "m")] super(crs.Mercator, self).__init__(proj4_params, globe=globe) + # Need to have x/y limits defined for the initial hash which + # gets used within transform_points for caching + self._x_limits = self._y_limits = None + # Calculate limits. limits = self.transform_points( crs.Geodetic(), @@ -76,14 +81,12 @@ def __init__(self, central_longitude=0.0, else: xlimits[0] = -xlimits[0] - self._xlimits = tuple(xlimits) - self._ylimits = tuple(limits[..., 1]) - # Compatibility with cartopy >= 0.17 - self._x_limits = self._xlimits - self._y_limits = self._ylimits + self._x_limits = tuple(xlimits) + self._y_limits = tuple(limits[..., 1]) - self._threshold = np.diff(self.x_limits)[0] / 720 + self._threshold = min(np.diff(self.x_limits)[0] / 720, + np.diff(self.y_limits)[0] / 360) def _ismissing(val, islat=True): diff --git a/src/wrf/routines.py b/src/wrf/routines.py index 3998209..d40b72d 100644 --- a/src/wrf/routines.py +++ b/src/wrf/routines.py @@ -196,6 +196,8 @@ "wdir_uvmet": "uvmet_wdir", "wspd_uvmet10": "uvmet10_wspd", "wdir_uvmet10": "uvmet10_wdir", + "mcape": "cape2d_only", + "mcin": "cin2d_only" } diff --git a/src/wrf/units.py b/src/wrf/units.py old mode 100755 new mode 100644 diff --git a/src/wrf/version.py b/src/wrf/version.py index f708a9b..3e8d9f9 100644 --- a/src/wrf/version.py +++ b/src/wrf/version.py @@ -1 +1 @@ -__version__ = "1.3.2" +__version__ = "1.4.0"