Browse Source

Merge branch 'release/1.3.2'

main 1.3.2
Bill Ladwig 6 years ago
parent
commit
5682aa5007
  1. 3
      .circleci/conda_env.yml
  2. 7
      .circleci/config.yml
  3. 10
      README.md
  4. 5
      build_scripts/gnu_no_omp.sh
  5. 7
      build_scripts/gnu_omp.sh
  6. 2
      build_scripts/win_msvc_mingw_no_omp.bat
  7. 2
      build_scripts/win_msvc_mingw_omp.bat
  8. 79
      chey_intel.py
  9. 10
      doc/source/_templates/product_table.txt
  10. 63
      doc/source/contrib.rst
  11. 10
      doc/source/index.rst
  12. 3
      doc/source/internal_api/index.rst
  13. 12
      doc/source/new.rst
  14. 38
      fortran/build_help/sub_sizes.py
  15. 8
      fortran/rip_cape.f90
  16. 36
      fortran/wrf_wind.f90
  17. 54
      setup.py
  18. 19
      src/wrf/__init__.py
  19. 1
      src/wrf/api.py
  20. 5
      src/wrf/cache.py
  21. 27
      src/wrf/computation.py
  22. 4
      src/wrf/config.py
  23. 37
      src/wrf/constants.py
  24. 31
      src/wrf/coordpair.py
  25. 60
      src/wrf/decorators.py
  26. 2
      src/wrf/destag.py
  27. 203
      src/wrf/extension.py
  28. 27
      src/wrf/g_cape.py
  29. 24
      src/wrf/g_cloudfrac.py
  30. 5
      src/wrf/g_ctt.py
  31. 2
      src/wrf/g_dbz.py
  32. 7
      src/wrf/g_dewpoint.py
  33. 75
      src/wrf/g_geoht.py
  34. 13
      src/wrf/g_helicity.py
  35. 36
      src/wrf/g_latlon.py
  36. 3
      src/wrf/g_omega.py
  37. 2
      src/wrf/g_precip.py
  38. 5
      src/wrf/g_pressure.py
  39. 7
      src/wrf/g_pw.py
  40. 6
      src/wrf/g_rh.py
  41. 4
      src/wrf/g_slp.py
  42. 13
      src/wrf/g_temp.py
  43. 3
      src/wrf/g_terrain.py
  44. 1
      src/wrf/g_times.py
  45. 33
      src/wrf/g_uvmet.py
  46. 1
      src/wrf/g_vorticity.py
  47. 21
      src/wrf/g_wind.py
  48. 9
      src/wrf/geobnds.py
  49. 127
      src/wrf/interp.py
  50. 50
      src/wrf/interputils.py
  51. 35
      src/wrf/latlonutils.py
  52. 155
      src/wrf/metadecorators.py
  53. 198
      src/wrf/projection.py
  54. 3
      src/wrf/projutils.py
  55. 4
      src/wrf/py3compat.py
  56. 308
      src/wrf/routines.py
  57. 49
      src/wrf/specialdec.py
  58. 276
      src/wrf/units.py
  59. 219
      src/wrf/util.py
  60. 3
      src/wrf/version.py
  61. 3
      test/ci_tests/make_test_file.py
  62. 38
      test/ci_tests/utests.py
  63. 158
      test/comp_utest.py
  64. 17
      test/ctt_test.py
  65. 8
      test/generator_test.py
  66. 40
      test/misc/extract_one_time.py
  67. 70
      test/misc/loop_and_fill_meta.py
  68. 35
      test/misc/mocktest.py
  69. 124
      test/misc/projtest.py
  70. 58
      test/misc/quiver_test.py
  71. 0
      test/misc/reduce_file.py
  72. 29
      test/misc/snippet.py
  73. 18
      test/misc/varcache.py
  74. 19
      test/misc/viewtest.py
  75. 230
      test/misc/wps.py
  76. 0
      test/ncl/listBug.ncl
  77. 30
      test/ncl/ncl_get_var.ncl
  78. 92
      test/ncl/ncl_vertcross.ncl
  79. 81
      test/ncl/refl10_cross.ncl
  80. 26
      test/ncl/rotated_test.ncl
  81. 21
      test/ncl/test_this.ncl
  82. 0
      test/ncl/test_vinterp.ncl
  83. 416
      test/ncl/wrf_user_vertcross.ncl
  84. 30
      test/snippet.py
  85. 52
      test/test_filevars.py
  86. 41
      test/test_inputs.py
  87. 42
      test/test_multi_cache.py
  88. 29
      test/test_omp.py
  89. 120
      test/test_proj_params.py
  90. 1
      test/test_units.py
  91. 580
      test/utests.py

3
.circleci/conda_env.yml

@ -2,7 +2,8 @@ name: wrf-python @@ -2,7 +2,8 @@ name: wrf-python
channels:
- conda-forge
dependencies:
- gcc
- gcc_linux-64
- gfortran_linux-64
- setuptools
- python
- numpy

7
.circleci/config.yml

@ -46,11 +46,14 @@ jobs: @@ -46,11 +46,14 @@ jobs:
name: build wrf-python
command: |
source ~/miniconda3/bin/activate wrf-python
unset FFLAGS
unset LDFLAGS
unset CFLAGS
cd fortran/build_help
gfortran -o sizes -fopenmp omp_sizes.f90
$FC -o sizes -fopenmp omp_sizes.f90
LD_LIBRARY_PATH=~/miniconda3/envs/wrf-python/lib python sub_sizes.py
cd ..
gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90
$FC -E ompgen.F90 -fopenmp -cpp -o omp.f90
cd ..
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

10
README.md

@ -23,3 +23,13 @@ Citation @@ -23,3 +23,13 @@ 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.
--------------------
*The National Center for Atmospheric Research is sponsored by the National
Science Foundation. Any opinions, findings and conclusions or recommendations
expressed in this material do not necessarily reflect the views of the
National Science Foundation.*

5
build_scripts/gnu_no_omp.sh

@ -1,8 +1,9 @@ @@ -1,8 +1,9 @@
#!/bin/bash
unset LDFLAGS
cd ../fortran
gfortran -E ompgen.F90 -cpp -o omp.f90
#f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature
$FC -E ompgen.F90 -cpp -o omp.f90
cd ..
python setup.py clean --all

7
build_scripts/gnu_omp.sh

@ -1,12 +1,13 @@ @@ -1,12 +1,13 @@
#!/bin/bash
unset LDFLAGS
cd ../fortran/build_help
gfortran -o sizes -fopenmp omp_sizes.f90
$FC -o sizes -fopenmp omp_sizes.f90
python sub_sizes.py
cd ..
gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90
#f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature
$FC -E ompgen.F90 -fopenmp -cpp -o omp.f90
cd ..
python setup.py clean --all

2
build_scripts/win_msvc_mingw_no_omp.bat

@ -1,7 +1,5 @@ @@ -1,7 +1,5 @@
cd ../fortran
CALL gfortran -E ompgen.F90 -cpp -o omp.f90
REM Wildcards not working on Windows for some reason
REM 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 ..
CALL python setup.py clean --all

2
build_scripts/win_msvc_mingw_omp.bat

@ -4,8 +4,6 @@ CALL python sub_sizes.py @@ -4,8 +4,6 @@ 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
REM 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 ..
CALL python setup.py clean --all

79
chey_intel.py

@ -13,7 +13,8 @@ compilers = ['IntelFCompiler', 'IntelVisualFCompiler', @@ -13,7 +13,8 @@ compilers = ['IntelFCompiler', 'IntelVisualFCompiler',
def intel_version_match(type):
# Match against the important stuff in the version string
return simple_version_match(start=r'Intel.*?Fortran.*?(?:%s).*?Version' % (type,))
return simple_version_match(
start=r'Intel.*?Fortran.*?(?:%s).*?Version'.format(type,))
class BaseIntelFCompiler(FCompiler):
@ -36,13 +37,13 @@ class IntelFCompiler(BaseIntelFCompiler): @@ -36,13 +37,13 @@ class IntelFCompiler(BaseIntelFCompiler):
possible_executables = ['ifort', 'ifc']
executables = {
'version_cmd' : None, # set by update_executables
'compiler_f77' : [None, "-72", "-w90", "-w95"],
'compiler_f90' : [None],
'compiler_fix' : [None, "-FI"],
'linker_so' : ["<F90>", "-shared"],
'archiver' : ["ar", "-cr"],
'ranlib' : ["ranlib"]
'version_cmd': None, # set by update_executables
'compiler_f77': [None, "-72", "-w90", "-w95"],
'compiler_f90': [None],
'compiler_fix': [None, "-FI"],
'linker_so': ["<F90>", "-shared"],
'archiver': ["ar", "-cr"],
'ranlib': ["ranlib"]
}
pic_flags = ['-fPIC']
@ -89,13 +90,13 @@ class IntelItaniumFCompiler(IntelFCompiler): @@ -89,13 +90,13 @@ class IntelItaniumFCompiler(IntelFCompiler):
possible_executables = ['ifort', 'efort', 'efc']
executables = {
'version_cmd' : None,
'compiler_f77' : [None, "-FI", "-w90", "-w95"],
'compiler_fix' : [None, "-FI"],
'compiler_f90' : [None],
'linker_so' : ['<F90>', "-shared"],
'archiver' : ["ar", "-cr"],
'ranlib' : ["ranlib"]
'version_cmd': None,
'compiler_f77': [None, "-FI", "-w90", "-w95"],
'compiler_fix': [None, "-FI"],
'compiler_f90': [None],
'linker_so': ['<F90>', "-shared"],
'archiver': ["ar", "-cr"],
'ranlib': ["ranlib"]
}
@ -104,18 +105,19 @@ class IntelEM64TFCompiler(IntelFCompiler): @@ -104,18 +105,19 @@ class IntelEM64TFCompiler(IntelFCompiler):
compiler_aliases = ()
description = 'Intel Fortran Compiler for 64-bit apps'
version_match = intel_version_match('EM64T-based|Intel\\(R\\) 64|64|IA-64|64-bit')
version_match = intel_version_match(
'EM64T-based|Intel\\(R\\) 64|64|IA-64|64-bit')
possible_executables = ['ifort', 'efort', 'efc']
executables = {
'version_cmd' : None,
'compiler_f77' : [None, "-FI"],
'compiler_fix' : [None, "-FI"],
'compiler_f90' : [None],
'linker_so' : ['<F90>', "-shared"],
'archiver' : ["ar", "-cr"],
'ranlib' : ["ranlib"]
'version_cmd': None,
'compiler_f77': [None, "-FI"],
'compiler_fix': [None, "-FI"],
'compiler_f90': [None],
'linker_so': ['<F90>', "-shared"],
'archiver': ["ar", "-cr"],
'ranlib': ["ranlib"]
}
def get_flags(self):
@ -147,13 +149,13 @@ class IntelVisualFCompiler(BaseIntelFCompiler): @@ -147,13 +149,13 @@ class IntelVisualFCompiler(BaseIntelFCompiler):
possible_executables = ['ifort', 'ifl']
executables = {
'version_cmd' : None,
'compiler_f77' : [None],
'compiler_fix' : [None],
'compiler_f90' : [None],
'linker_so' : [None],
'archiver' : [ar_exe, "/verbose", "/OUT:"],
'ranlib' : None
'version_cmd': None,
'compiler_f77': [None],
'compiler_fix': [None],
'compiler_f90': [None],
'linker_so': [None],
'archiver': [ar_exe, "/verbose", "/OUT:"],
'ranlib': None
}
compile_switch = '/c '
@ -163,7 +165,8 @@ class IntelVisualFCompiler(BaseIntelFCompiler): @@ -163,7 +165,8 @@ class IntelVisualFCompiler(BaseIntelFCompiler):
module_include_switch = '/I'
def get_flags(self):
opt = ['/nologo', '/MD', '/nbs', '/names:lowercase', '/assume:underscore']
opt = ['/nologo', '/MD', '/nbs', '/names:lowercase',
'/assume:underscore']
return opt
def get_flags_free(self):
@ -192,13 +195,13 @@ class IntelItaniumVisualFCompiler(IntelVisualFCompiler): @@ -192,13 +195,13 @@ class IntelItaniumVisualFCompiler(IntelVisualFCompiler):
ar_exe = IntelVisualFCompiler.ar_exe
executables = {
'version_cmd' : None,
'compiler_f77' : [None, "-FI", "-w90", "-w95"],
'compiler_fix' : [None, "-FI", "-4L72", "-w"],
'compiler_f90' : [None],
'linker_so' : ['<F90>', "-shared"],
'archiver' : [ar_exe, "/verbose", "/OUT:"],
'ranlib' : None
'version_cmd': None,
'compiler_f77': [None, "-FI", "-w90", "-w95"],
'compiler_fix': [None, "-FI", "-4L72", "-w"],
'compiler_f90': [None],
'linker_so': ['<F90>', "-shared"],
'archiver': [ar_exe, "/verbose", "/OUT:"],
'ranlib': None
}

10
doc/source/_templates/product_table.txt

@ -245,6 +245,16 @@ @@ -245,6 +245,16 @@
| | | | |
| | | mi | |
+--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| height_agl | Model Height for Mass Grid (AGL) | m | **units** (str) : Set to desired units. Default is *'m'*. |
| | | | |
| | | km | |
| | | | |
| | | dm | |
| | | | |
| | | ft | |
| | | | |
| | | mi | |
+--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| zstag | Model Height for Vertically Staggered Grid | m | **msl** (boolean): Set to False to return AGL values. True is for MSL. Default is *True*. |
| | | | |
| | | km | **units** (str) : Set to desired units. Default is *'m'*. |

63
doc/source/contrib.rst

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
.. _contrib_guide:
Contributor Guide
=================================
.. note::
This contributor guide is written for wrf-python v1.3.x. In the
not-too-distant future, wrf-python will undergo a significant refactoring
to remove the wrapt decorators (which don't serialize for dask), but the
concepts will remain the same as described below.
Ways to Contribute
-----------------------------
Users are encouraged to contribute various ways. This includes:
- Submitting a bug report
- Submitting bug fixes
- Submitting new Fortran computational routines
- Submitting new Python computational routines
- Submitting fully wrapped computational routines
Getting the source code
------------------------------
The source code is available on GitHub:
https://github.com/NCAR/wrf-python
To checkout the code::
git clone https://github.com/NCAR/wrf-python
Git Flow
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This project follows the GitFlow Workflow, which you can read about here if it
is new to you:
https://leanpub.com/git-flow/read
When you first clone the repository, by default you will be on the 'develop'
branch, which is what you should use for your development.
Pull Requests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order to submit changes, you must use GitHub to issue a pull request.
Overview of WRF-Python Internals
----------------------------------
WRF-Python is a collection of diagnostic and interpolation routines for WRF-ARW
data. The API consists of a handful of functions

10
doc/source/index.rst

@ -13,6 +13,14 @@ @@ -13,6 +13,14 @@
university corporation for atmospheric research,
pynio, pyngl, interpolation
.. .. image:: _static/images/nsf.png
.. :scale: 100%
.. :align: right
.. |
.. |
wrf-python
===========
@ -57,6 +65,7 @@ Indices and tables @@ -57,6 +65,7 @@ Indices and tables
* :ref:`modindex`
* :ref:`search`
--------------------
*The National Center for Atmospheric Research is sponsored by the National
@ -64,4 +73,3 @@ Science Foundation. Any opinions, findings and conclusions or recommendations @@ -64,4 +73,3 @@ Science Foundation. Any opinions, findings and conclusions or recommendations
expressed in this material do not necessarily reflect the views of the
National Science Foundation.*

3
doc/source/internal_api/index.rst

@ -23,6 +23,9 @@ The routines below are called internally by :meth:`wrf.getvar`. @@ -23,6 +23,9 @@ The routines below are called internally by :meth:`wrf.getvar`.
wrf.g_dewpoint.get_dp_2m
wrf.g_geoht.get_geopt
wrf.g_geoht.get_height
wrf.g_geoht.get_height_agl
wrf.g_geoht.get_stag_geopt
wrf.g_geoht.get_stag_height
wrf.g_helicity.get_srh
wrf.g_helicity.get_uh
wrf.g_omega.get_omega

12
doc/source/new.rst

@ -4,6 +4,18 @@ What's New @@ -4,6 +4,18 @@ What's New
Releases
-------------
v1.3.2 (February 2019)
^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.3.2
- Coordinate name index positions are no longer assumed and are searched
instead. Some users use xarray to rewrite WRF output files, and xarray
might reorder the coordinate name positions.
- Fixed a segfault issue with CAPE when more than 150 vertical levels are
used (e.g. LES runs).
- setup.py will now bootstrap the numpy installation (thanks bbonenfant!).
v1.3.1 (January 2019)
^^^^^^^^^^^^^^^^^^^^^^^^^

38
fortran/build_help/sub_sizes.py

@ -3,12 +3,13 @@ import os @@ -3,12 +3,13 @@ import os
from string import Template
import sys
def main():
print("Running sub_sizes")
print ("Running sub_sizes")
try:
result = subprocess.check_output(["./sizes"])
except:
except OSError:
result = subprocess.check_output(["sizes.exe"])
split_result = result.split()
@ -17,28 +18,27 @@ def main(): @@ -17,28 +18,27 @@ def main():
if split_result[0].strip().decode() != "SIZES":
raise ValueError("First line is not SIZES")
subs = {"FOMP_SCHED_KIND" : split_result[1].strip().decode(),
"FOMP_LOCK_KIND" : split_result[2].strip().decode(),
"FOMP_NEST_LOCK_KIND" : split_result[3].strip().decode(),
"FOMP_SCHED_STATIC" : split_result[4].strip().decode(),
"FOMP_SCHED_DYNAMIC" : split_result[5].strip().decode(),
"FOMP_SCHED_GUIDED" : split_result[6].strip().decode(),
"FOMP_SCHED_AUTO" : split_result[7].strip().decode()
subs = {"FOMP_SCHED_KIND": split_result[1].strip().decode(),
"FOMP_LOCK_KIND": split_result[2].strip().decode(),
"FOMP_NEST_LOCK_KIND": split_result[3].strip().decode(),
"FOMP_SCHED_STATIC": split_result[4].strip().decode(),
"FOMP_SCHED_DYNAMIC": split_result[5].strip().decode(),
"FOMP_SCHED_GUIDED": split_result[6].strip().decode(),
"FOMP_SCHED_AUTO": split_result[7].strip().decode()
}
else:
if split_result[0].strip() != "SIZES":
raise ValueError("First line is not SIZES")
subs = {"FOMP_SCHED_KIND" : split_result[1].strip(),
"FOMP_LOCK_KIND" : split_result[2].strip(),
"FOMP_NEST_LOCK_KIND" : split_result[3].strip(),
"FOMP_SCHED_STATIC" : split_result[4].strip(),
"FOMP_SCHED_DYNAMIC" : split_result[5].strip(),
"FOMP_SCHED_GUIDED" : split_result[6].strip(),
"FOMP_SCHED_AUTO" : split_result[7].strip()
subs = {"FOMP_SCHED_KIND": split_result[1].strip(),
"FOMP_LOCK_KIND": split_result[2].strip(),
"FOMP_NEST_LOCK_KIND": split_result[3].strip(),
"FOMP_SCHED_STATIC": split_result[4].strip(),
"FOMP_SCHED_DYNAMIC": split_result[5].strip(),
"FOMP_SCHED_GUIDED": split_result[6].strip(),
"FOMP_SCHED_AUTO": split_result[7].strip()
}
ompgen_temp_path = os.path.join("..", "ompgen.F90.template")
ompgen_out_path = os.path.join("..", "ompgen.F90")
@ -47,11 +47,11 @@ def main(): @@ -47,11 +47,11 @@ def main():
ompgen_string = ompgen_template.substitute(subs)
with open(ompgen_out_path, "w") as ompgen_out:
ompgen_out.write(ompgen_string)
print("End sub_sizes")
print ("End sub_sizes")
if __name__ == "__main__":
main()

8
fortran/rip_cape.f90

@ -316,7 +316,9 @@ SUBROUTINE DCAPECALC3D(prs,tmk,qvp,ght,ter,sfp,cape,cin,& @@ -316,7 +316,9 @@ SUBROUTINE DCAPECALC3D(prs,tmk,qvp,ght,ter,sfp,cape,cin,&
REAL(KIND=8) :: facden, qvplift, tmklift, tvenv, tvlift, ghtlift
REAL(KIND=8) :: eslift, tmkenv, qvpenv, tonpsadiabat
REAL(KIND=8) :: benamin, dz
REAL(KIND=8), DIMENSION(150) :: buoy, zrel, benaccum
! Set a safety factor of 2*mkzh + 1 instead of previously chosen
! 150 levels
REAL(KIND=8), DIMENSION(2*mkzh + 1) :: buoy, zrel, benaccum
REAL(KIND=8), DIMENSION(150) :: psadithte, psadiprs
REAL(KIND=8), DIMENSION(150,150) :: psaditmk
LOGICAL :: elfound
@ -646,7 +648,9 @@ SUBROUTINE DCAPECALC2D(prs,tmk,qvp,ght,ter,sfp,cape,cin,& @@ -646,7 +648,9 @@ SUBROUTINE DCAPECALC2D(prs,tmk,qvp,ght,ter,sfp,cape,cin,&
REAL(KIND=8) :: facden, qvplift, tmklift, tvenv, tvlift, ghtlift
REAL(KIND=8) :: eslift, tmkenv, qvpenv, tonpsadiabat
REAL(KIND=8) :: benamin, dz, pup, pdn
REAL(KIND=8), DIMENSION(150) :: buoy, zrel, benaccum
! Set a safety factor of 2*mkzh + 1 instead of previously chosen
! 150 levels
REAL(KIND=8), DIMENSION(2*mkzh + 1) :: buoy, zrel, benaccum
REAL(KIND=8), DIMENSION(150) :: psadithte, psadiprs
REAL(KIND=8), DIMENSION(150,150) :: psaditmk
LOGICAL :: elfound

36
fortran/wrf_wind.f90

@ -1,23 +1,21 @@ @@ -1,23 +1,21 @@
! NCLFORTSTART
SUBROUTINE DCOMPUTEWSPD(wspd, u, v, nx, ny)
SUBROUTINE DCOMPUTEWSPD(wspd, u, v, n)
IMPLICIT NONE
!f2py threadsafe
!f2py intent(in,out) :: wspd
INTEGER, INTENT(IN) :: nx, ny
REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: wspd
REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: u, v
INTEGER, INTENT(IN) :: n
REAL(KIND=8), DIMENSION(n), INTENT(OUT) :: wspd
REAL(KIND=8), DIMENSION(n), INTENT(IN) :: u, v
! NCLEND
INTEGER i, j
INTEGER i
!$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime)
DO j = 1,ny
DO i = 1,nx
wspd(i,j) = SQRT(u(i,j)*u(i,j) + v(i,j)*v(i,j))
END DO
!$OMP PARALLEL DO SCHEDULE(runtime)
DO i = 1,n
wspd(i) = SQRT(u(i)*u(i) + v(i)*v(i))
END DO
!$OMP END PARALLEL DO
@ -25,7 +23,7 @@ END SUBROUTINE DCOMPUTEWSPD @@ -25,7 +23,7 @@ END SUBROUTINE DCOMPUTEWSPD
! NCLFORTSTART
SUBROUTINE DCOMPUTEWDIR(wdir, u, v, nx, ny)
SUBROUTINE DCOMPUTEWDIR(wdir, u, v, n)
USE wrf_constants, ONLY : DEG_PER_RAD
IMPLICIT NONE
@ -33,18 +31,16 @@ SUBROUTINE DCOMPUTEWDIR(wdir, u, v, nx, ny) @@ -33,18 +31,16 @@ SUBROUTINE DCOMPUTEWDIR(wdir, u, v, nx, ny)
!f2py threadsafe
!f2py intent(in,out) :: wdir
INTEGER, INTENT(IN) :: nx, ny
REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: wdir
REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: u, v
INTEGER, INTENT(IN) :: n
REAL(KIND=8), DIMENSION(n), INTENT(OUT) :: wdir
REAL(KIND=8), DIMENSION(n), INTENT(IN) :: u, v
! NCLEND
INTEGER i, j
INTEGER i
!$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime)
DO j = 1,ny
DO i = 1,nx
wdir(i,j) = MOD(270.0 - ATAN2(v(i,j), u(i,j)) * DEG_PER_RAD, 360.)
END DO
!$OMP PARALLEL DO SCHEDULE(runtime)
DO i = 1,n
wdir(i) = MOD(270.0 - ATAN2(v(i), u(i)) * DEG_PER_RAD, 360.)
END DO
!$OMP END PARALLEL DO

54
setup.py

@ -3,6 +3,14 @@ import sys @@ -3,6 +3,14 @@ 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:
@ -23,8 +31,8 @@ else: @@ -23,8 +31,8 @@ else:
chey_intel.IntelEM64TFCompiler)
ext1 = numpy.distutils.core.Extension(
name = "wrf._wrffortran",
sources = ["fortran/wrf_constants.f90",
name="wrf._wrffortran",
sources=["fortran/wrf_constants.f90",
"fortran/wrf_testfunc.f90",
"fortran/wrf_user.f90",
"fortran/rip_cape.f90",
@ -47,9 +55,9 @@ with open("src/wrf/version.py") as f: @@ -47,9 +55,9 @@ with open("src/wrf/version.py") as f:
exec(f.read())
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
#on_rtd=True
# on_rtd=True
if on_rtd:
if sys.version_info < (3,3):
if sys.version_info < (3, 3):
requirements = ["mock"] # for python2 and python < 3.3
else:
requirements = [] # for >= python3.3
@ -60,29 +68,29 @@ else: @@ -60,29 +68,29 @@ else:
with open("requirements.txt") as f2:
requirements = f2.read().strip().splitlines()
#if sys.version_info < (3,3):
# 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"
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",
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",
install_requires=requirements,
classifiers=["Development Status :: 5 - Production/Stable",
"Intended Audience :: Science/Research",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
@ -98,14 +106,14 @@ numpy.distutils.core.setup( @@ -98,14 +106,14 @@ numpy.distutils.core.setup(
"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"]},
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=[]
)

19
src/wrf/__init__.py

@ -2,19 +2,24 @@ from __future__ import (absolute_import, division, print_function) @@ -2,19 +2,24 @@ from __future__ import (absolute_import, division, print_function)
import os
import pkg_resources
# For gfortran+msvc combination, extra shared libraries may exist (stored by numpy.distutils)
if os.name == "nt":
try:
try:
from . import api
from .api import *
except ImportError:
# For gfortran+msvc combination, extra shared libraries may exist
# (stored by numpy.distutils)
if os.name == "nt":
req = pkg_resources.Requirement.parse("wrf-python")
extra_dll_dir = pkg_resources.resource_filename(req,
"wrf-python/.libs")
if os.path.isdir(extra_dll_dir):
os.environ["PATH"] += os.pathsep + extra_dll_dir
except ImportError:
pass
from . import api
from .api import *
from . import api
from .api import *
else:
raise
__all__ = []
__all__.extend(api.__all__)

1
src/wrf/api.py

@ -110,4 +110,3 @@ __all__ += ["CoordPair"] @@ -110,4 +110,3 @@ __all__ += ["CoordPair"]
__all__ += ["to_xy_coords"]
__all__ += ["cache_item", "get_cached_item"]
__all__ += ["__version__"]

5
src/wrf/cache.py

@ -161,8 +161,3 @@ def _get_cache(): @@ -161,8 +161,3 @@ def _get_cache():
_shrink_cache()
return getattr(_local_storage, "cache", None)

27
src/wrf/computation.py

@ -15,6 +15,7 @@ from .metadecorators import (set_alg_metadata, set_uvmet_alg_metadata, @@ -15,6 +15,7 @@ from .metadecorators import (set_alg_metadata, set_uvmet_alg_metadata,
set_smooth_metdata)
from .interputils import get_xy
@set_interp_metadata("xy")
def xy(field, pivot_point=None, angle=None, start_point=None, end_point=None,
meta=True):
@ -601,8 +602,8 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"): @@ -601,8 +602,8 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"):
and *v*, but with rightmost dimensions south_north x
west_east and the same leftmost dimensions as *u* and *v*
- multi-dimensional with one fewer dimensions as *u* and *v*,
with rightmost dimensions south_north x west_east and the same
leftmost dimensions as *u* and *v*, minus the
with rightmost dimensions south_north x west_east and the
same leftmost dimensions as *u* and *v*, minus the
third-from-the-right dimension of *u* and *v*.
Note:
@ -622,8 +623,8 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"): @@ -622,8 +623,8 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"):
and *v*, but with rightmost dimensions south_north x
west_east and the same leftmost dimensions as *u* and *v*
- multi-dimensional with one fewer dimensions as *u* and *v*,
with rightmost dimensions south_north x west_east and the same
leftmost dimensions as *u* and *v*, minus the
with rightmost dimensions south_north x west_east and the
same leftmost dimensions as *u* and *v*, minus the
third-from-the-right dimension of *u* and *v*.
@ -870,10 +871,10 @@ def cape_2d(pres_hpa, tkel, qv, height, terrain, psfc_hpa, ter_follow, @@ -870,10 +871,10 @@ def cape_2d(pres_hpa, tkel, qv, height, terrain, psfc_hpa, ter_follow,
# Cape 2D output is not flipped in the vertical, so index from the
# end
result[0,...,:,:] = cape_cin[0,...,-1,:,:]
result[1,...,:,:] = cape_cin[1,...,-1,:,:]
result[2,...,:,:] = cape_cin[1,...,-2,:,:]
result[3,...,:,:] = cape_cin[1,...,-3,:,:]
result[0, ..., :, :] = cape_cin[0, ..., -1, :, :]
result[1, ..., :, :] = cape_cin[1, ..., -1, :, :]
result[2, ..., :, :] = cape_cin[1, ..., -2, :, :]
result[3, ..., :, :] = cape_cin[1, ..., -3, :, :]
return ma.masked_values(result, missing)
@ -1201,7 +1202,6 @@ def ctt(pres_hpa, tkel, qv, qcld, height, terrain, qice=None, @@ -1201,7 +1202,6 @@ def ctt(pres_hpa, tkel, qv, qcld, height, terrain, qice=None,
return ma.masked_values(ctt, missing)
@set_alg_metadata(3, "pres", units="dBZ",
description="radar reflectivity")
def dbz(pres, tkel, qv, qr, qs=None, qg=None, use_varint=False,
@ -1374,9 +1374,9 @@ def srhel(u, v, height, terrain, top=3000.0, lats=None, meta=True): @@ -1374,9 +1374,9 @@ def srhel(u, v, height, terrain, top=3000.0, lats=None, meta=True):
"""
# u, v get swapped in vertical
_u = np.ascontiguousarray(u[...,::-1,:,:])
_v = np.ascontiguousarray(v[...,::-1,:,:])
_height = np.ascontiguousarray(height[...,::-1,:,:])
_u = np.ascontiguousarray(u[..., ::-1, :, :])
_v = np.ascontiguousarray(v[..., ::-1, :, :])
_height = np.ascontiguousarray(height[..., ::-1, :, :])
if lats is None:
_lats = np.ones_like(terrain)
@ -1955,6 +1955,3 @@ def pw(pres, tkel, qv, height, meta=True): @@ -1955,6 +1955,3 @@ def pw(pres, tkel, qv, height, meta=True):
tv = _tv(tkel, qv)
return _pw(pres, tv, qv, height)

4
src/wrf/config.py

@ -9,6 +9,7 @@ from ._wrffortran import (fomp_enabled, fomp_set_num_threads, @@ -9,6 +9,7 @@ from ._wrffortran import (fomp_enabled, fomp_set_num_threads,
_local_config = local()
def _init_local():
global _local_config
@ -191,7 +192,8 @@ def set_cache_size(size): @@ -191,7 +192,8 @@ def set_cache_size(size):
@init_local()
def get_cache_size():
"""Return the maximum number of items that the threadlocal cache can retain.
"""Return the maximum number of items that the threadlocal cache can
retain.
Returns:

37
src/wrf/constants.py

@ -10,10 +10,12 @@ from ._wrffortran import wrf_constants, omp_constants @@ -10,10 +10,12 @@ from ._wrffortran import wrf_constants, omp_constants
#: Indicates that all times should be used in a diagnostic routine.
ALL_TIMES = None
class Constants(object):
pass
for key,val in viewitems(wrf_constants.__dict__):
for key, val in viewitems(wrf_constants.__dict__):
setattr(Constants, key.upper(), np.asscalar(val))
OMP_SCHED_STATIC = omp_constants.fomp_sched_static
@ -44,21 +46,22 @@ class ProjectionTypes(object): @@ -44,21 +46,22 @@ class ProjectionTypes(object):
MERCATOR = 3
LAT_LON = 6
# Create the default fill mapping based on type.
_DEFAULT_FILL_MAP = {None: Constants.DEFAULT_FILL,
np.dtype(np.bool_) : False,
np.dtype(np.intc) : Constants.DEFAULT_FILL_INT32, # Usually true
np.dtype(np.int8) : Constants.DEFAULT_FILL_INT8,
np.dtype(np.uint8) : 255,
np.dtype(np.int16) : Constants.DEFAULT_FILL_INT16,
np.dtype(np.uint16) : 65535,
np.dtype(np.int32) : Constants.DEFAULT_FILL_INT32,
np.dtype(np.uint32) : 4294967295,
np.dtype(np.int64) : Constants.DEFAULT_FILL_INT64,
np.dtype(np.uint64) : 18446744073709551614,
np.dtype(np.float_) : Constants.DEFAULT_FILL_DOUBLE,
np.dtype(np.float32) : Constants.DEFAULT_FILL_FLOAT,
np.dtype(np.float64) : Constants.DEFAULT_FILL_DOUBLE
np.dtype(np.bool_): False,
np.dtype(np.intc): Constants.DEFAULT_FILL_INT32,
np.dtype(np.int8): Constants.DEFAULT_FILL_INT8,
np.dtype(np.uint8): 255,
np.dtype(np.int16): Constants.DEFAULT_FILL_INT16,
np.dtype(np.uint16): 65535,
np.dtype(np.int32): Constants.DEFAULT_FILL_INT32,
np.dtype(np.uint32): 4294967295,
np.dtype(np.int64): Constants.DEFAULT_FILL_INT64,
np.dtype(np.uint64): 18446744073709551614,
np.dtype(np.float_): Constants.DEFAULT_FILL_DOUBLE,
np.dtype(np.float32): Constants.DEFAULT_FILL_FLOAT,
np.dtype(np.float64): Constants.DEFAULT_FILL_DOUBLE
}
if version_info >= (3, ):
@ -76,9 +79,3 @@ else: @@ -76,9 +79,3 @@ else:
def default_fill(dtype=None):
dt = np.dtype(dtype) if dtype is not None else None
return _DEFAULT_FILL_MAP.get(dt, Constants.DEFAULT_FILL)

31
src/wrf/coordpair.py

@ -35,13 +35,13 @@ def _binary_operator(operator): @@ -35,13 +35,13 @@ def _binary_operator(operator):
"""
if isinstance(other, CoordPair):
args = [
None if getattr(self, attr) is None or getattr(other, attr) is None
else getattr(getattr(self, attr), operator)(getattr(other, attr))
args = [None if getattr(self, attr) is None or
getattr(other, attr) is None else
getattr(getattr(self, attr), operator)(getattr(other,
attr))
for attr in ("x", "y", "lat", "lon")]
else:
args = [
None if getattr(self, attr) is None
args = [None if getattr(self, attr) is None
else getattr(getattr(self, attr), operator)(other)
for attr in ("x", "y", "lat", "lon")]
@ -151,7 +151,6 @@ class CoordPair(object): @@ -151,7 +151,6 @@ class CoordPair(object):
self.lat = lat
self.lon = lon
def __repr__(self):
args = []
if self.x is not None:
@ -166,11 +165,9 @@ class CoordPair(object): @@ -166,11 +165,9 @@ class CoordPair(object):
return "{}({})".format(self.__class__.__name__, argstr)
def __str__(self):
return self.__repr__()
def xy_str(self, fmt="{:.4f}, {:.4f}"):
"""Return a :obj:`str` for the (x,y) coordinate pair.
@ -188,7 +185,6 @@ class CoordPair(object): @@ -188,7 +185,6 @@ class CoordPair(object):
return fmt.format(self.x, self.y)
def latlon_str(self, fmt="{:.4f}, {:.4f}"):
"""Return a :obj:`str` for the (latitude, longitude) coordinate pair.
@ -206,7 +202,6 @@ class CoordPair(object): @@ -206,7 +202,6 @@ class CoordPair(object):
return fmt.format(self.lat, self.lon)
def __round__(self, ndigits=None):
"""Return a new :class:`CoordPair` object with all coordinate values
rounded to the nearest integer.
@ -226,23 +221,20 @@ class CoordPair(object): @@ -226,23 +221,20 @@ class CoordPair(object):
return CoordPair(*args)
def __pow__(self, other, modulo=None):
if isinstance(other, CoordPair):
args = [
None if getattr(self, attr) is None or getattr(other, attr) is None
else getattr(getattr(self, attr), "__pow__")(getattr(other, attr),
modulo)
args = [None if getattr(self, attr) is None or
getattr(other, attr) is None
else getattr(getattr(self, attr), "__pow__")(
getattr(other, attr), modulo)
for attr in ("x", "y", "lat", "lon")]
else:
args = [
None if getattr(self, attr) is None
args = [None if getattr(self, attr) is None
else getattr(getattr(self, attr), "__pow__")(other, modulo)
for attr in ("x", "y", "lat", "lon")]
return CoordPair(*args)
def __rpow__(self, other):
return self.__pow__(other)
@ -260,6 +252,3 @@ for operator in ("__neg__", "__pos__", "__abs__", "__invert__"): @@ -260,6 +252,3 @@ for operator in ("__neg__", "__pos__", "__abs__", "__invert__"):
for operator in ("__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"):
setattr(CoordPair, operator, _cmp_operator(operator))

60
src/wrf/decorators.py

@ -15,6 +15,7 @@ from .constants import default_fill @@ -15,6 +15,7 @@ from .constants import default_fill
if xarray_enabled():
from xarray import DataArray
def convert_units(unit_type, alg_unit):
"""A decorator that converts the units from the wrapped function's output.
@ -47,17 +48,6 @@ def convert_units(unit_type, alg_unit): @@ -47,17 +48,6 @@ def convert_units(unit_type, alg_unit):
return func_wrapper
#def _calc_out_dims(outvar, left_dims):
# """
#
# """
# #left_dims = [x for x in left_dims]
# #right_dims = [x for x in outvar.shape]
# #return left_dims + right_dims
#
# return left_dims + outvar.shape
def left_iteration(ref_var_expected_dims,
ref_var_right_ndims,
insert_dims=None,
@ -171,16 +161,15 @@ def left_iteration(ref_var_expected_dims, @@ -171,16 +161,15 @@ def left_iteration(ref_var_expected_dims,
# the right (e.g. [1,1,:])
left_and_slice_idxs = left_idxs + (slice(None), )
# Slice the args if applicable
new_args = [arg[left_and_slice_idxs]
if i not in _ignore_args else arg
for i,arg in enumerate(args)]
for i, arg in enumerate(args)]
# Slice the kwargs if applicable
new_kargs = {key:(val[left_and_slice_idxs]
new_kargs = {key: (val[left_and_slice_idxs]
if key not in _ignore_kargs else val)
for key,val in viewitems(kwargs)}
for key, val in viewitems(kwargs)}
# Skip the possible empty/missing arrays for the join method
skip_missing = False
@ -210,7 +199,7 @@ def left_iteration(ref_var_expected_dims, @@ -210,7 +199,7 @@ def left_iteration(ref_var_expected_dims,
# Insert the output views if one hasn't been provided
if "outview" not in new_kargs:
for outkey,output in viewitems(outd):
for outkey, output in viewitems(outd):
outview = output[left_and_slice_idxs]
new_kargs[outkey] = outview
@ -222,14 +211,11 @@ def left_iteration(ref_var_expected_dims, @@ -222,14 +211,11 @@ def left_iteration(ref_var_expected_dims,
outview.__array_interface__["data"][0]):
raise RuntimeError("output array was copied")
if len(outd) == 1:
output = next(iter(viewvalues(outd)))
else:
output = tuple(arr for arr in viewvalues(outd))
if cast_output:
if isinstance(output, np.ndarray):
output = output.astype(ref_var_dtype)
@ -262,8 +248,8 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None, @@ -262,8 +248,8 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None,
positional arguments to be used as the reference variable for
determining the :class:`numpy.dtype` to return. Default is 0.
arg_idxs (sequence of :obj:`int`, optional): A sequence of indexes in the
wrapped function's positional arguments that indicate which
arg_idxs (sequence of :obj:`int`, optional): A sequence of indexes in
the wrapped function's positional arguments that indicate which
arguments to cast. Must be specified if *karg_names* is None.
Default is None.
@ -272,8 +258,8 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None, @@ -272,8 +258,8 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None,
arguments to cast. Must be specified if *arg_idxs* is None.
Default is None.
alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type used
in the wrapped function.
alg_dtype (:class:`numpy.dtype` or :obj:`str`): The numpy data type
used in the wrapped function.
outviews (:obj:`str` or a sequence): A single key or sequence of keys
that indicate the wrapped function's keyword argument to use
@ -300,16 +286,15 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None, @@ -300,16 +286,15 @@ def cast_type(ref_idx=0, arg_idxs=None, karg_names=None,
if _outview is not None:
has_outview = True
orig_type = args[ref_idx].dtype
new_args = [arg.astype(alg_dtype)
if i in _arg_idxs else arg
for i,arg in enumerate(args)]
for i, arg in enumerate(args)]
new_kargs = {key:(val.astype(alg_dtype)
new_kargs = {key: (val.astype(alg_dtype)
if key in _karg_names else val)
for key,val in viewitems(kwargs)}
for key, val in viewitems(kwargs)}
result = wrapped(*new_args, **new_kargs)
@ -401,8 +386,8 @@ def extract_and_transpose(do_transpose=True, outviews="outview"): @@ -401,8 +386,8 @@ def extract_and_transpose(do_transpose=True, outviews="outview"):
new_args = [_extract_and_transpose(arg, do_transpose) for arg in args]
new_kargs = {key:_extract_and_transpose(val, do_transpose)
for key,val in viewitems(kwargs)}
new_kargs = {key: _extract_and_transpose(val, do_transpose)
for key, val in viewitems(kwargs)}
result = wrapped(*new_args, **new_kargs)
@ -481,7 +466,7 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None, @@ -481,7 +466,7 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None,
else:
_stagger = stagger
for i,ndim in enumerate(rightdims):
for i, ndim in enumerate(rightdims):
if ndim is None:
continue
@ -498,7 +483,8 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None, @@ -498,7 +483,8 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None,
# Check that the number of dims is correct
if (var.ndim - extra_dims != right_var_ndims):
raise ValueError("invalid number of dimensions for argument "
"{} (got {}, expected {}).".format(i,
"{} (got {}, expected {}).".format(
i,
var.ndim,
right_var_ndims + extra_dims))
@ -517,19 +503,11 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None, @@ -517,19 +503,11 @@ def check_args(refvaridx, refvarndim, rightdims, stagger=None,
ref_right_sizes[-right_var_ndims:]):
raise ValueError("invalid shape for argument "
"{} (got {}, expected {})".format(i,
"{} (got {}, expected {})".format(
i,
var.shape[-right_var_ndims:],
ref_right_sizes[-right_var_ndims:]))
return wrapped(*args, **kwargs)
return func_wrapper

2
src/wrf/destag.py

@ -60,5 +60,3 @@ def destagger(var, stagger_dim, meta=False): @@ -60,5 +60,3 @@ def destagger(var, stagger_dim, meta=False):
result = .5*(var[tuple(dim_ranges_1)] + var[tuple(dim_ranges_2)])
return result

203
src/wrf/extension.py

@ -5,20 +5,21 @@ import numpy as np @@ -5,20 +5,21 @@ import numpy as np
from .constants import Constants, default_fill
from wrf._wrffortran import (dcomputetk, dinterp3dz, dinterp2dxy, dinterp1d,
dcomputeseaprs, dfilter2d, dcomputerh, dcomputeuvmet,
dcomputetd, dcapecalc2d, dcapecalc3d, dcloudfrac2,
wrfcttcalc, calcdbz, dcalrelhl, dcalcuh, dcomputepv,
dcomputeabsvort, dlltoij, dijtoll, deqthecalc,
omgcalc, virtual_temp, wetbulbcalc, dcomputepw,
dcomputeseaprs, dfilter2d, dcomputerh,
dcomputeuvmet, dcomputetd, dcapecalc2d,
dcapecalc3d, dcloudfrac2, wrfcttcalc, calcdbz,
dcalrelhl, dcalcuh, dcomputepv, dcomputeabsvort,
dlltoij, dijtoll, deqthecalc, omgcalc,
virtual_temp, wetbulbcalc, dcomputepw,
wrf_monotonic, wrf_vintrp, dcomputewspd,
dcomputewdir, dinterp3dz_2dlev,
fomp_set_num_threads, fomp_get_num_threads,
fomp_get_max_threads, fomp_get_thread_num,
fomp_get_num_procs, fomp_in_parallel,
fomp_set_dynamic, fomp_get_dynamic, fomp_set_nested,
fomp_get_nested, fomp_set_schedule,
fomp_get_schedule, fomp_get_thread_limit,
fomp_set_max_active_levels,
fomp_set_dynamic, fomp_get_dynamic,
fomp_set_nested, fomp_get_nested,
fomp_set_schedule, fomp_get_schedule,
fomp_get_thread_limit, fomp_set_max_active_levels,
fomp_get_max_active_levels, fomp_get_level,
fomp_get_ancestor_thread_num, fomp_get_team_size,
fomp_get_active_level, fomp_in_final,
@ -37,6 +38,7 @@ from .specialdec import (uvmet_left_iter, cape_left_iter, @@ -37,6 +38,7 @@ from .specialdec import (uvmet_left_iter, cape_left_iter,
cloudfrac_left_iter, check_cape_args,
interplevel_left_iter, check_interplevel_args)
class DiagnosticError(Exception):
"""Raised when an error occurs in a diagnostic routine."""
def __init__(self, message=None):
@ -66,6 +68,7 @@ class DiagnosticError(Exception): @@ -66,6 +68,7 @@ class DiagnosticError(Exception):
"""
raise self.__class__(message)
# The routines below are thin wrappers around the Fortran functions. These
# are not meant to be called by end users. Use the public API instead for
# that purpose.
@ -73,10 +76,9 @@ class DiagnosticError(Exception): @@ -73,10 +76,9 @@ class DiagnosticError(Exception):
# IMPORTANT! Unless otherwise noted, all variables used in the routines
# below assume that Fortran-ordered views are being used. This allows
# f2py to pass the array pointers directly to the Fortran routine.
@check_interplevel_args(is2dlev=False)
@interplevel_left_iter(is2dlev=False)
@cast_type(arg_idxs=(0,1,2))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
"""Wrapper for dinterp3dz.
@ -98,7 +100,7 @@ def _interpz3d(field3d, z, desiredloc, missingval, outview=None): @@ -98,7 +100,7 @@ def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
@check_interplevel_args(is2dlev=True)
@interplevel_left_iter(is2dlev=True)
@cast_type(arg_idxs=(0,1,2))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _interpz3d_lev2d(field3d, z, lev2d, missingval, outview=None):
"""Wrapper for dinterp3dz.
@ -117,10 +119,10 @@ def _interpz3d_lev2d(field3d, z, lev2d, missingval, outview=None): @@ -117,10 +119,10 @@ def _interpz3d_lev2d(field3d, z, lev2d, missingval, outview=None):
return result
@check_args(0, 3, (3,))
@left_iteration(3, combine_dims([(0,-3),(1,-2)]), ref_var_idx=0,
ignore_args=(1,))
@cast_type(arg_idxs=(0,1))
@check_args(0, 3, (3, ))
@left_iteration(3, combine_dims([(0, -3), (1, -2)]), ref_var_idx=0,
ignore_args=(1, ))
@cast_type(arg_idxs=(0, 1))
@extract_and_transpose()
def _interp2dxy(field3d, xy, outview=None):
"""Wrapper for dinterp2dxy.
@ -138,9 +140,9 @@ def _interp2dxy(field3d, xy, outview=None): @@ -138,9 +140,9 @@ def _interp2dxy(field3d, xy, outview=None):
return result
@check_args(0, 1, (1,1,None,None))
@left_iteration(1, combine_dims([(2,0)]), ref_var_idx=0, ignore_args=(2,3))
@cast_type(arg_idxs=(0,1,2))
@check_args(0, 1, (1, 1, None, None))
@left_iteration(1, combine_dims([(2, 0)]), ref_var_idx=0, ignore_args=(2, 3))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _interp1d(v_in, z_in, z_out, missingval, outview=None):
"""Wrapper for dinterp1d.
@ -160,9 +162,9 @@ def _interp1d(v_in, z_in, z_out, missingval, outview=None): @@ -160,9 +162,9 @@ def _interp1d(v_in, z_in, z_out, missingval, outview=None):
return result
@left_iteration(3, combine_dims([(3,0), (1,0)]),
ref_var_idx=0, ignore_args=(1,3,4))
@cast_type(arg_idxs=(0,))
@left_iteration(3, combine_dims([(3, 0), (1, 0)]),
ref_var_idx=0, ignore_args=(1, 3, 4))
@cast_type(arg_idxs=(0, ))
@extract_and_transpose(do_transpose=False)
def _vertcross(field3d, xy, var2dz, z_var2d, missingval, outview=None):
"""Return the vertical cross section.
@ -180,14 +182,14 @@ def _vertcross(field3d, xy, var2dz, z_var2d, missingval, outview=None): @@ -180,14 +182,14 @@ def _vertcross(field3d, xy, var2dz, z_var2d, missingval, outview=None):
var2dtmp = _interp2dxy(field3d, xy)
for i in py3range(xy.shape[0]):
outview[:,i] = _interp1d(var2dtmp[:,i], var2dz[:,i], z_var2d,
outview[:, i] = _interp1d(var2dtmp[:, i], var2dz[:, i], z_var2d,
missingval)
return outview
@left_iteration(2, combine_dims([(1,0)]), ref_var_idx=0, ignore_args=(1,))
@cast_type(arg_idxs=(0,))
@left_iteration(2, combine_dims([(1, 0)]), ref_var_idx=0, ignore_args=(1, ))
@cast_type(arg_idxs=(0, ))
@extract_and_transpose(do_transpose=False)
def _interpline(field2d, xy, outview=None):
"""Return the two-dimensional field interpolated to a line.
@ -204,7 +206,7 @@ def _interpline(field2d, xy, outview=None): @@ -204,7 +206,7 @@ def _interpline(field2d, xy, outview=None):
tmp_shape = (1,) + field2d.shape
var2dtmp = np.empty(tmp_shape, field2d.dtype)
var2dtmp[0,:,:] = field2d[:,:]
var2dtmp[0, :, :] = field2d[:, :]
var1dtmp = _interp2dxy(var2dtmp, xy)
@ -213,9 +215,9 @@ def _interpline(field2d, xy, outview=None): @@ -213,9 +215,9 @@ def _interpline(field2d, xy, outview=None):
return outview
@check_args(0, 3, (3,3,3,3))
@check_args(0, 3, (3, 3, 3, 3))
@left_iteration(3, 2, ref_var_idx=0)
@cast_type(arg_idxs=(0,1,2,3))
@cast_type(arg_idxs=(0, 1, 2, 3))
@extract_and_transpose()
def _slp(z, t, p, q, outview=None):
"""Wrapper for dcomputeseaprs.
@ -250,9 +252,9 @@ def _slp(z, t, p, q, outview=None): @@ -250,9 +252,9 @@ def _slp(z, t, p, q, outview=None):
return result
@check_args(0, 3, (3,3))
@check_args(0, 3, (3, 3))
@left_iteration(3, 3, ref_var_idx=0)
@cast_type(arg_idxs=(0,1))
@cast_type(arg_idxs=(0, 1))
@extract_and_transpose()
def _tk(pressure, theta, outview=None):
"""Wrapper for dcomputetk.
@ -272,9 +274,9 @@ def _tk(pressure, theta, outview=None): @@ -272,9 +274,9 @@ def _tk(pressure, theta, outview=None):
return result
@check_args(0, 2, (2,2))
@check_args(0, 2, (2, 2))
@left_iteration(2, 2, ref_var_idx=0)
@cast_type(arg_idxs=(0,1))
@cast_type(arg_idxs=(0, 1))
@extract_and_transpose()
def _td(pressure, qv_in, outview=None):
"""Wrapper for dcomputetd.
@ -294,9 +296,9 @@ def _td(pressure, qv_in, outview=None): @@ -294,9 +296,9 @@ def _td(pressure, qv_in, outview=None):
return result
@check_args(0, 2, (2,2,2))
@check_args(0, 2, (2, 2, 2))
@left_iteration(2, 2, ref_var_idx=0)
@cast_type(arg_idxs=(0,1,2))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _rh(qv, q, t, outview=None):
"""Wrapper for dcomputerh.
@ -318,12 +320,12 @@ def _rh(qv, q, t, outview=None): @@ -318,12 +320,12 @@ def _rh(qv, q, t, outview=None):
# Note: combining the -3 and -2 dimensions from u, then the -1 dimension
# from v
@check_args(0, 3, (3,3,2,2,2,2), stagger=(-1,-2,-1,-2,None,None),
@check_args(0, 3, (3, 3, 2, 2, 2, 2), stagger=(-1, -2, -1, -2, None, None),
refstagdim=-1)
@left_iteration(3, combine_dims([(0, (-3,-2)),
(1, (-1,))]),
ref_var_idx=0, ignore_args=(6,7))
@cast_type(arg_idxs=(0,1,2,3,4,5))
@left_iteration(3, combine_dims([(0, (-3, -2)),
(1, (-1, ))]),
ref_var_idx=0, ignore_args=(6, 7))
@cast_type(arg_idxs=(0, 1, 2, 3, 4, 5))
@extract_and_transpose()
def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None):
"""Wrapper for dcomputeabsvort.
@ -332,7 +334,7 @@ def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None): @@ -332,7 +334,7 @@ def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None):
"""
if outview is None:
outshape = (v.shape[0],) + u.shape[1:]
outshape = (v.shape[0], ) + u.shape[1:]
outview = np.empty(outshape, np.float64, order="F")
result = dcomputeabsvort(outview,
@ -348,11 +350,10 @@ def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None): @@ -348,11 +350,10 @@ def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None):
return result
@check_args(0, 3, (3,3,3,3,2,2,2,2), stagger=(-1,-2,None,None,-1,-2,None,
None),
refstagdim=-1)
@left_iteration(3, 3, ref_var_idx=2, ignore_args=(8,9))
@cast_type(arg_idxs=(0,1,2,3,4,5,6,7))
@check_args(0, 3, (3, 3, 3, 3, 2, 2, 2, 2),
stagger=(-1, -2, None, None, -1, -2, None, None), refstagdim=-1)
@left_iteration(3, 3, ref_var_idx=2, ignore_args=(8, 9))
@cast_type(arg_idxs=(0, 1, 2, 3, 4, 5, 6, 7))
@extract_and_transpose()
def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None):
"""Wrapper for dcomputepv.
@ -378,9 +379,9 @@ def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None): @@ -378,9 +379,9 @@ def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None):
return result
@check_args(0, 3, (3,3,3))
@check_args(0, 3, (3, 3, 3))
@left_iteration(3, 3, ref_var_idx=0)
@cast_type(arg_idxs=(0,1,2))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _eth(qv, tk, p, outview=None):
"""Wrapper for deqthecalc.
@ -400,11 +401,13 @@ def _eth(qv, tk, p, outview=None): @@ -400,11 +401,13 @@ def _eth(qv, tk, p, outview=None):
@uvmet_left_iter()
@cast_type(arg_idxs=(0,1,2,3))
@cast_type(arg_idxs=(0, 1, 2, 3))
@extract_and_transpose()
def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False,
umissing=default_fill(np.float64), vmissing=default_fill(np.float64),
uvmetmissing=default_fill(np.float64), outview=None):
umissing=default_fill(np.float64),
vmissing=default_fill(np.float64),
uvmetmissing=default_fill(np.float64),
outview=None):
"""Wrapper for dcomputeuvmet.
Located in wrf_user.f90.
@ -437,9 +440,9 @@ def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False, @@ -437,9 +440,9 @@ def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False,
return result
@check_args(0, 3, (3,3,3,3))
@check_args(0, 3, (3, 3, 3, 3))
@left_iteration(3, 3, ref_var_idx=0)
@cast_type(arg_idxs=(0,1,2,3))
@cast_type(arg_idxs=(0, 1, 2, 3))
@extract_and_transpose()
def _omega(qv, tk, w, p, outview=None):
"""Wrapper for omgcalc.
@ -459,9 +462,9 @@ def _omega(qv, tk, w, p, outview=None): @@ -459,9 +462,9 @@ def _omega(qv, tk, w, p, outview=None):
return result
@check_args(0, 3, (3,3))
@check_args(0, 3, (3, 3))
@left_iteration(3, 3, ref_var_idx=0)
@cast_type(arg_idxs=(0,1))
@cast_type(arg_idxs=(0, 1))
@extract_and_transpose()
def _tv(tk, qv, outview=None):
"""Wrapper for virtual_temp.
@ -479,9 +482,9 @@ def _tv(tk, qv, outview=None): @@ -479,9 +482,9 @@ def _tv(tk, qv, outview=None):
return result
@check_args(0, 3, (3,3,3))
@check_args(0, 3, (3, 3, 3))
@left_iteration(3, 3, ref_var_idx=0, ignore_args=(3,))
@cast_type(arg_idxs=(0,1,2))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None):
"""Wrapper for wetbulbcalc.
@ -509,9 +512,9 @@ def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None): @@ -509,9 +512,9 @@ def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None):
return result
@check_args(0, 3, (3,3,3,2,2))
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(5,))
@cast_type(arg_idxs=(0,1,2,3,4))
@check_args(0, 3, (3, 3, 3, 2, 2))
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(5, ))
@cast_type(arg_idxs=(0, 1, 2, 3, 4))
@extract_and_transpose()
def _srhel(u, v, z, ter, lats, top, outview=None):
"""Wrapper for dcalrelhl.
@ -533,9 +536,9 @@ def _srhel(u, v, z, ter, lats, top, outview=None): @@ -533,9 +536,9 @@ def _srhel(u, v, z, ter, lats, top, outview=None):
return result
@check_args(2, 3, (3,2,3,3,3), stagger=(-3,None,None,None,-3))
@left_iteration(3, 2, ref_var_idx=2, ignore_args=(5,6,7,8))
@cast_type(arg_idxs=(0,1,2,3,4))
@check_args(2, 3, (3, 2, 3, 3, 3), stagger=(-3, None, None, None, -3))
@left_iteration(3, 2, ref_var_idx=2, ignore_args=(5, 6, 7, 8))
@cast_type(arg_idxs=(0, 1, 2, 3, 4))
@extract_and_transpose()
def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None):
"""Wrapper for dcalcuh.
@ -567,9 +570,9 @@ def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None): @@ -567,9 +570,9 @@ def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None):
return result
@check_args(0, 3, (3,3,3,3), stagger=(None, None, None, -3))
@check_args(0, 3, (3, 3, 3, 3), stagger=(None, None, None, -3))
@left_iteration(3, 2, ref_var_idx=0)
@cast_type(arg_idxs=(0,1,2,3))
@cast_type(arg_idxs=(0, 1, 2, 3))
@extract_and_transpose()
def _pw(p, tv, qv, ht, outview=None):
"""Wrapper for dcomputepw.
@ -589,9 +592,9 @@ def _pw(p, tv, qv, ht, outview=None): @@ -589,9 +592,9 @@ def _pw(p, tv, qv, ht, outview=None):
return result
@check_args(0, 3, (3,3,3,3,3,3))
@left_iteration(3, 3, ref_var_idx=0, ignore_args=(6,7,8))
@cast_type(arg_idxs=(0,1,2,3,4,5))
@check_args(0, 3, (3, 3, 3, 3, 3, 3))
@left_iteration(3, 3, ref_var_idx=0, ignore_args=(6, 7, 8))
@cast_type(arg_idxs=(0, 1, 2, 3, 4, 5))
@extract_and_transpose()
def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None):
"""Wrapper for calcdbz.
@ -618,7 +621,7 @@ def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None): @@ -618,7 +621,7 @@ def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None):
@check_cape_args()
@cape_left_iter()
@cast_type(arg_idxs=(0,1,2,3,4,5), outviews=("capeview", "cinview"))
@cast_type(arg_idxs=(0, 1, 2, 3, 4, 5), outviews=("capeview", "cinview"))
@extract_and_transpose(outviews=("capeview", "cinview"))
def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow,
psafile=psafilepath(), capeview=None, cinview=None):
@ -674,12 +677,14 @@ def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow, @@ -674,12 +677,14 @@ def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow,
return result
@check_args(0, 3, (3,3))
@check_args(0, 3, (3, 3))
@cloudfrac_left_iter()
@cast_type(arg_idxs=(0, 1), outviews=("lowview", "midview", "highview"))
@extract_and_transpose(outviews=("lowview", "midview", "highview"))
def _cloudfrac(vert, rh, vert_inc_w_height, low_thresh, mid_thresh,
high_thresh, missing, lowview=None, midview=None, highview=None):
high_thresh, missing, lowview=None, midview=None,
highview=None):
"""Wrapper for dcloudfrac2.
Located in wrf_cloud_fracf.f90.
@ -789,9 +794,9 @@ def _xytoll(map_proj, truelat1, truelat2, stdlon, lat1, lon1, @@ -789,9 +794,9 @@ def _xytoll(map_proj, truelat1, truelat2, stdlon, lat1, lon1,
return result
@check_args(0, 3, (3,3,3,3,3,3,2))
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(7,8,9,10))
@cast_type(arg_idxs=(0,1,2,3,4,5,6))
@check_args(0, 3, (3, 3, 3, 3, 3, 3, 2))
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(7, 8, 9, 10))
@cast_type(arg_idxs=(0, 1, 2, 3, 4, 5, 6))
@extract_and_transpose()
def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, fill_nocloud,
missing, opt_thresh, outview=None):
@ -822,9 +827,9 @@ def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, fill_nocloud, @@ -822,9 +827,9 @@ def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, fill_nocloud,
return result
@check_args(0, 2, (2,))
@left_iteration(2, 2, ref_var_idx=0, ignore_args=(1,2))
@cast_type(arg_idxs=(0,))
@check_args(0, 2, (2, ))
@left_iteration(2, 2, ref_var_idx=0, ignore_args=(1, 2))
@cast_type(arg_idxs=(0, ))
@extract_and_transpose()
def _smooth2d(field, passes, cenweight, outview=None):
"""Wrapper for dfilter2d.
@ -856,9 +861,9 @@ def _smooth2d(field, passes, cenweight, outview=None): @@ -856,9 +861,9 @@ def _smooth2d(field, passes, cenweight, outview=None):
return outview
@check_args(0, 3, (3,3,2))
@left_iteration(3, 3, ref_var_idx=0, ignore_args=(3,4,5))
@cast_type(arg_idxs=(0,1,2))
@check_args(0, 3, (3, 3, 2))
@left_iteration(3, 3, ref_var_idx=0, ignore_args=(3, 4, 5))
@cast_type(arg_idxs=(0, 1, 2))
@extract_and_transpose()
def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None):
"""Wrapper for wrf_monotonic.
@ -885,11 +890,11 @@ def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None): @@ -885,11 +890,11 @@ def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None):
# Output shape is interp_levels.shape + field.shape[-2:]
@check_args(0, 3, (3,3,3,3,3,2,2,2,3))
@left_iteration(3, combine_dims([(9, (-1,)),
(0, (-2,-1))]),
ref_var_idx=0, ignore_args=(9,10,11,12,13,14))
@cast_type(arg_idxs=(0,1,2,3,4,5,6,7,8,9))
@check_args(0, 3, (3, 3, 3, 3, 3, 2, 2, 2, 3))
@left_iteration(3, combine_dims([(9, (-1, )),
(0, (-2, -1))]),
ref_var_idx=0, ignore_args=(9, 10, 11, 12, 13, 14))
@cast_type(arg_idxs=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
@extract_and_transpose()
def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp,
vcarray, interp_levels, icase, extrap, vcor, logp,
@ -933,9 +938,10 @@ def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp, @@ -933,9 +938,10 @@ def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp,
return result
@check_args(0, 2, (2,2))
@check_args(0, 2, (2, 2))
@left_iteration(2, 2, ref_var_idx=0)
@cast_type(arg_idxs=(0,1))
@cast_type(arg_idxs=(0, 1))
@extract_and_transpose()
def _wspd(u, v, outview=None):
"""Wrapper for dcomputewspd.
@ -943,19 +949,22 @@ def _wspd(u, v, outview=None): @@ -943,19 +949,22 @@ def _wspd(u, v, outview=None):
Located in wrf_wind.f90.
"""
shape = u.shape
if outview is None:
outview = np.empty_like(u)
result = dcomputewspd(outview,
u,
v)
result = dcomputewspd(outview.ravel(order="A"),
u.ravel(order="A"),
v.ravel(order="A"))
result = np.reshape(result, shape, order="F")
return result
@check_args(0, 2, (2,2))
@check_args(0, 2, (2, 2))
@left_iteration(2, 2, ref_var_idx=0)
@cast_type(arg_idxs=(0,1))
@cast_type(arg_idxs=(0, 1))
@extract_and_transpose()
def _wdir(u, v, outview=None):
"""Wrapper for dcomputewdir.
@ -963,12 +972,15 @@ def _wdir(u, v, outview=None): @@ -963,12 +972,15 @@ def _wdir(u, v, outview=None):
Located in wrf_wind.f90.
"""
shape = u.shape
if outview is None:
outview = np.empty_like(u)
result = dcomputewdir(outview,
u,
v)
result = dcomputewdir(outview.ravel(order="A"),
u.ravel(order="A"),
v.ravel(order="A"))
result = np.reshape(result, shape, order="F")
return result
@ -1651,6 +1663,3 @@ def omp_get_wtick(): @@ -1651,6 +1663,3 @@ def omp_get_wtick():
"""
return fomp_get_wtick()

27
src/wrf/g_cape.py

@ -9,6 +9,7 @@ from .constants import default_fill, Constants, ConversionFactors @@ -9,6 +9,7 @@ from .constants import default_fill, Constants, ConversionFactors
from .util import extract_vars
from .metadecorators import set_cape_metadata
@set_cape_metadata(is2d=True)
def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=default_fill(np.float64)):
@ -77,7 +78,7 @@ def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -77,7 +78,7 @@ def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
varnames = ("T", "P", "PB", "QVAPOR", "PH","PHB", "HGT", "PSFC")
varnames = ("T", "P", "PB", "QVAPOR", "PH", "PHB", "HGT", "PSFC")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -118,10 +119,10 @@ def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -118,10 +119,10 @@ def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
# Cape 2D output is not flipped in the vertical, so index from the
# end
result[0,...,:,:] = cape_cin[0,...,-1,:,:]
result[1,...,:,:] = cape_cin[1,...,-1,:,:]
result[2,...,:,:] = cape_cin[1,...,-2,:,:]
result[3,...,:,:] = cape_cin[1,...,-3,:,:]
result[0, ..., :, :] = cape_cin[0, ..., -1, :, :]
result[1, ..., :, :] = cape_cin[1, ..., -1, :, :]
result[2, ..., :, :] = cape_cin[1, ..., -2, :, :]
result[3, ..., :, :] = cape_cin[1, ..., -3, :, :]
return ma.masked_values(result, missing)
@ -221,7 +222,6 @@ def get_3dcape(wrfin, timeidx=0, method="cat", @@ -221,7 +222,6 @@ def get_3dcape(wrfin, timeidx=0, method="cat",
cape_cin = _cape(p_hpa, tk, qv, z, ter, psfc_hpa, missing, i3dflag,
ter_follow)
return ma.masked_values(cape_cin, missing)
@ -284,7 +284,7 @@ def get_cape2d_only(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -284,7 +284,7 @@ def get_cape2d_only(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[0,:]
meta, _key, missing)[0, :]
if meta:
result.attrs["description"] = "mcape"
@ -351,7 +351,7 @@ def get_cin2d_only(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -351,7 +351,7 @@ def get_cin2d_only(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[1,:]
meta, _key, missing)[1, :]
if meta:
result.attrs["description"] = "mcin"
@ -418,7 +418,7 @@ def get_lcl(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -418,7 +418,7 @@ def get_lcl(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[2,:]
meta, _key, missing)[2, :]
if meta:
result.attrs["description"] = "lcl"
@ -485,7 +485,7 @@ def get_lfc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -485,7 +485,7 @@ def get_lfc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[3,:]
meta, _key, missing)[3, :]
if meta:
result.attrs["description"] = "lfc"
@ -554,7 +554,7 @@ def get_3dcape_only(wrfin, timeidx=0, method="cat", @@ -554,7 +554,7 @@ def get_3dcape_only(wrfin, timeidx=0, method="cat",
"""
result = get_3dcape(wrfin, timeidx, method, squeeze, cache, meta,
_key, missing)[0,:]
_key, missing)[0, :]
if meta:
result.attrs["description"] = "cape"
@ -622,13 +622,10 @@ def get_3dcin_only(wrfin, timeidx=0, method="cat", @@ -622,13 +622,10 @@ def get_3dcin_only(wrfin, timeidx=0, method="cat",
"""
result = get_3dcape(wrfin, timeidx, method, squeeze, cache, meta,
_key, missing)[1,:]
_key, missing)[1, :]
if meta:
result.attrs["description"] = "cin"
result.attrs["units"] = "J kg-1"
return result

24
src/wrf/g_cloudfrac.py

@ -164,8 +164,9 @@ def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -164,8 +164,9 @@ def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
vert_type="height_agl", low_thresh=None,
mid_thresh=None, high_thresh=None,
missing=default_fill(np.float64)):
"""Return the cloud fraction for the low level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
@ -264,9 +265,8 @@ def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -264,9 +265,8 @@ def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[0,:]
cache, meta, _key, vert_type, low_thresh,
mid_thresh, high_thresh, missing)[0, :]
if meta:
result.attrs["description"] = "low clouds"
@ -276,8 +276,9 @@ def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -276,8 +276,9 @@ def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
vert_type="height_agl", low_thresh=None,
mid_thresh=None, high_thresh=None,
missing=default_fill(np.float64)):
"""Return the cloud fraction for the mid level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
@ -378,7 +379,7 @@ def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -378,7 +379,7 @@ def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[1,:]
high_thresh, missing)[1, :]
if meta:
result.attrs["description"] = "mid clouds"
@ -388,8 +389,9 @@ def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -388,8 +389,9 @@ def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
def get_high_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
vert_type="height_agl", low_thresh=None,
mid_thresh=None, high_thresh=None,
missing=default_fill(np.float64)):
"""Return the cloud fraction for the high level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
@ -490,7 +492,7 @@ def get_high_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True, @@ -490,7 +492,7 @@ def get_high_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[2,:]
high_thresh, missing)[2, :]
if meta:
result.attrs["description"] = "high clouds"

5
src/wrf/g_ctt.py

@ -3,7 +3,6 @@ from __future__ import (absolute_import, division, print_function) @@ -3,7 +3,6 @@ from __future__ import (absolute_import, division, print_function)
import numpy as np
import numpy.ma as ma
#from .extension import computectt, computetk
from .extension import _ctt, _tk
from .constants import Constants, ConversionFactors, default_fill
from .destag import destagger
@ -118,7 +117,7 @@ def get_ctt(wrfin, timeidx=0, method="cat", @@ -118,7 +117,7 @@ def get_ctt(wrfin, timeidx=0, method="cat",
qice = np.zeros(qv.shape, qv.dtype)
haveqci = 0
else:
qice = icevars["QICE"] * 1000.0 #g/kg
qice = icevars["QICE"] * 1000.0 # g/kg
try:
cldvars = extract_vars(wrfin, timeidx, "QCLOUD",
@ -127,7 +126,7 @@ def get_ctt(wrfin, timeidx=0, method="cat", @@ -127,7 +126,7 @@ def get_ctt(wrfin, timeidx=0, method="cat",
except KeyError:
raise RuntimeError("'QCLOUD' not found in NetCDF file")
else:
qcld = cldvars["QCLOUD"] * 1000.0 #g/kg
qcld = cldvars["QCLOUD"] * 1000.0 # g/kg
full_p = p + pb
p_hpa = full_p * ConversionFactors.PA_TO_HPA

2
src/wrf/g_dbz.py

@ -2,7 +2,6 @@ from __future__ import (absolute_import, division, print_function) @@ -2,7 +2,6 @@ from __future__ import (absolute_import, division, print_function)
import numpy as np
#from .extension import computedbz,computetk
from .extension import _dbz, _tk
from .constants import Constants
from .util import extract_vars, to_np
@ -196,4 +195,3 @@ def get_max_dbz(wrfin, timeidx=0, method="cat", @@ -196,4 +195,3 @@ def get_max_dbz(wrfin, timeidx=0, method="cat",
return np.amax(to_np(get_dbz(wrfin, timeidx, method, squeeze, cache, meta,
_key, use_varint, use_liqskin)),
axis=-3)

7
src/wrf/g_dewpoint.py

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
from __future__ import (absolute_import, division, print_function)
#from .extension import computetd
from .extension import _td
from .decorators import convert_units
from .metadecorators import copy_and_set_metadata
@ -69,7 +68,7 @@ def get_dp(wrfin, timeidx=0, method="cat", squeeze=True, @@ -69,7 +68,7 @@ def get_dp(wrfin, timeidx=0, method="cat", squeeze=True,
"""
varnames=("P", "PB", "QVAPOR")
varnames = ("P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -86,6 +85,7 @@ def get_dp(wrfin, timeidx=0, method="cat", squeeze=True, @@ -86,6 +85,7 @@ def get_dp(wrfin, timeidx=0, method="cat", squeeze=True,
td = _td(full_p, qvapor)
return td
@copy_and_set_metadata(copy_varname="Q2", name="td2",
description="2m dew point temperature")
@convert_units("temp", "c")
@ -147,7 +147,7 @@ def get_dp_2m(wrfin, timeidx=0, method="cat", squeeze=True, @@ -147,7 +147,7 @@ def get_dp_2m(wrfin, timeidx=0, method="cat", squeeze=True,
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames=("PSFC", "Q2")
varnames = ("PSFC", "Q2")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -161,4 +161,3 @@ def get_dp_2m(wrfin, timeidx=0, method="cat", squeeze=True, @@ -161,4 +161,3 @@ def get_dp_2m(wrfin, timeidx=0, method="cat", squeeze=True,
td = _td(psfc, q2)
return td

75
src/wrf/g_geoht.py

@ -8,6 +8,7 @@ from .decorators import convert_units @@ -8,6 +8,7 @@ from .decorators import convert_units
from .metadecorators import set_height_metadata
from .util import extract_vars, either
def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
height=True, msl=True, stag=False):
@ -104,7 +105,7 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True, @@ -104,7 +105,7 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
if stag:
warnings.warn("file contains no vertically staggered geopotential "
"height variable, returning unstaggered result "
"instead" )
"instead")
if height:
if msl:
return geopt_unstag / Constants.G
@ -113,7 +114,7 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True, @@ -113,7 +114,7 @@ def _get_geoht(wrfin, timeidx, method="cat", squeeze=True,
# array needs to be reshaped to a 3D array so the right dims
# line up
new_dims = list(hgt.shape)
new_dims.insert(-2,1)
new_dims.insert(-2, 1)
hgt = hgt.reshape(new_dims)
return (geopt_unstag / Constants.G) - hgt
@ -321,8 +322,7 @@ def get_stag_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -321,8 +322,7 @@ def get_stag_geopt(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
@set_height_metadata(geopt=False, stag=True)
@convert_units("height", "m")
def get_stag_height(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
msl=True, units="m"):
cache=None, meta=True, _key=None, msl=True, units="m"):
"""Return the geopotential height for the vertically staggered grid.
If *msl* is True, then geopotential height is returned as Mean Sea Level
@ -392,3 +392,70 @@ def get_stag_height(wrfin, timeidx=0, method="cat", squeeze=True, @@ -392,3 +392,70 @@ def get_stag_height(wrfin, timeidx=0, method="cat", squeeze=True,
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, msl, stag=True)
@set_height_metadata(geopt=False, stag=False)
@convert_units("height", "m")
def get_height_agl(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, units="m"):
"""Return the geopotential height (AGL).
The geopotential height is returned as Above Ground Level (AGL) by
subtracting the terrain height.
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'height_agl'.
Default is 'm'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
geopotential height.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
return _get_geoht(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, False)

13
src/wrf/g_helicity.py

@ -9,6 +9,7 @@ from .util import extract_vars, extract_global_attrs, either @@ -9,6 +9,7 @@ from .util import extract_vars, extract_global_attrs, either
from .metadecorators import copy_and_set_metadata
from .g_latlon import get_lat
@copy_and_set_metadata(copy_varname="HGT", name="srh",
description="storm relative helicity",
units="m2 s-2")
@ -101,14 +102,15 @@ def get_srh(wrfin, timeidx=0, method="cat", squeeze=True, @@ -101,14 +102,15 @@ def get_srh(wrfin, timeidx=0, method="cat", squeeze=True,
z = geopt_unstag / Constants.G
# Re-ordering from high to low
u1 = np.ascontiguousarray(u[...,::-1,:,:])
v1 = np.ascontiguousarray(v[...,::-1,:,:])
z1 = np.ascontiguousarray(z[...,::-1,:,:])
u1 = np.ascontiguousarray(u[..., ::-1, :, :])
v1 = np.ascontiguousarray(v[..., ::-1, :, :])
z1 = np.ascontiguousarray(z[..., ::-1, :, :])
srh = _srhel(u1, v1, z1, ter, lats, top)
return srh
@copy_and_set_metadata(copy_varname="MAPFAC_M", name="updraft_helicity",
description="updraft helicity",
units="m2 s-2")
@ -206,8 +208,3 @@ def get_uh(wrfin, timeidx=0, method="cat", squeeze=True, @@ -206,8 +208,3 @@ def get_uh(wrfin, timeidx=0, method="cat", squeeze=True,
uh = _udhel(zp, mapfct, u, v, wstag, dx, dy, bottom, top)
return uh

36
src/wrf/g_latlon.py

@ -244,7 +244,7 @@ def _llxy_mapping(wrfin, x_or_lat, y_or_lon, func, timeidx, stagger, @@ -244,7 +244,7 @@ def _llxy_mapping(wrfin, x_or_lat, y_or_lon, func, timeidx, stagger,
outdims = [numkeys]
outdims += first_array.shape
outdata = np.empty(outdims, first_array.dtype)
outdata[0,:] = first_array[:]
outdata[0, :] = first_array[:]
idx = 1
while True:
@ -265,7 +265,7 @@ def _llxy_mapping(wrfin, x_or_lat, y_or_lon, func, timeidx, stagger, @@ -265,7 +265,7 @@ def _llxy_mapping(wrfin, x_or_lat, y_or_lon, func, timeidx, stagger,
if outdata.shape[1:] != result_array.shape:
raise ValueError("data sequences must have the "
"same size for all dictionary keys")
outdata[idx,:] = to_np(result_array)[:]
outdata[idx, :] = to_np(result_array)[:]
idx += 1
if xarray_enabled() and meta:
@ -301,12 +301,10 @@ def _llxy_mapping(wrfin, x_or_lat, y_or_lon, func, timeidx, stagger, @@ -301,12 +301,10 @@ def _llxy_mapping(wrfin, x_or_lat, y_or_lon, func, timeidx, stagger,
# make it so that key_0 is leftmost
outdims = key_coordnames + list(first_array.dims[existing_cnt:])
# Create the new 'key_n', value pairs
for coordname, coordval in zip(key_coordnames, coord_vals):
outcoords[coordname] = coordval
outattrs = OrderedDict(first_array.attrs)
outarr = DataArray(outdata, name=outname, coords=outcoords,
@ -604,11 +602,12 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True, @@ -604,11 +602,12 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True,
"""
loc = locals()
_projparams = {name : loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon", "ref_lat",
"ref_lon", "pole_lat", "pole_lon",
"known_x", "known_y", "dx", "dy",
"latinc", "loninc")}
_projparams = {name: loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon",
"ref_lat", "ref_lon",
"pole_lat", "pole_lon",
"known_x", "known_y", "dx",
"dy", "latinc", "loninc")}
projparams = _set_defaults(_projparams)
@ -772,20 +771,13 @@ def xy_to_ll_proj(x, y, meta=True, squeeze=True, map_proj=None, truelat1=None, @@ -772,20 +771,13 @@ def xy_to_ll_proj(x, y, meta=True, squeeze=True, map_proj=None, truelat1=None,
be a :class:`numpy.ndarray` object with no metadata.
"""
loc = locals()
_projparams = {name : loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon", "ref_lat",
"ref_lon", "pole_lat", "pole_lon",
"known_x", "known_y", "dx", "dy",
"latinc", "loninc")}
_projparams = {name: loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon",
"ref_lat", "ref_lon",
"pole_lat", "pole_lon",
"known_x", "known_y", "dx",
"dy", "latinc", "loninc")}
projparams = _set_defaults(_projparams)
return _xy_to_ll(x, y, None, 0, None, "cat", squeeze, None, None,
**projparams)

3
src/wrf/g_omega.py

@ -64,7 +64,7 @@ def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -64,7 +64,7 @@ def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "W", "PB", "QVAPOR")
varnames = ("T", "P", "W", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -81,4 +81,3 @@ def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -81,4 +81,3 @@ def get_omega(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
omega = _omega(qv, tk, wa, full_p)
return omega

2
src/wrf/g_precip.py

@ -2,7 +2,6 @@ from __future__ import (absolute_import, division, print_function) @@ -2,7 +2,6 @@ from __future__ import (absolute_import, division, print_function)
from .util import extract_vars
__all__ = ["get_accum_precip", "get_precip_diff"]
def get_accum_precip(wrfin, timeidx=0):
ncvars = extract_vars(wrfin, timeidx, varnames=("RAINC", "RAINNC"))
@ -13,6 +12,7 @@ def get_accum_precip(wrfin, timeidx=0): @@ -13,6 +12,7 @@ def get_accum_precip(wrfin, timeidx=0):
return rainsum
def get_precip_diff(wrfin1, wrfin2, timeidx=0):
vars1 = extract_vars(wrfin1, timeidx, varnames=("RAINC", "RAINNC"))
vars2 = extract_vars(wrfin2, timeidx, varnames=("RAINC", "RAINNC"))

5
src/wrf/g_pressure.py

@ -85,6 +85,7 @@ def get_pressure(wrfin, timeidx=0, method="cat", squeeze=True, @@ -85,6 +85,7 @@ def get_pressure(wrfin, timeidx=0, method="cat", squeeze=True,
return pres
def get_pressure_hpa(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None):
"""Return the pressure in [hPa].
@ -142,7 +143,3 @@ def get_pressure_hpa(wrfin, timeidx=0, method="cat", squeeze=True, @@ -142,7 +143,3 @@ def get_pressure_hpa(wrfin, timeidx=0, method="cat", squeeze=True,
"""
return get_pressure(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="hPa")

7
src/wrf/g_pw.py

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
from __future__ import (absolute_import, division, print_function)
#from .extension import computepw,computetv,computetk
from .extension import _pw, _tv, _tk
from .constants import Constants
from .util import extract_vars
@ -66,7 +65,7 @@ def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -66,7 +65,7 @@ def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "PH", "PHB", "QVAPOR")
varnames = ("T", "P", "PB", "PH", "PHB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -85,7 +84,3 @@ def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -85,7 +84,3 @@ def get_pw(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
tv = _tv(tk, qv)
return _pw(full_p, tv, qv, ht)

6
src/wrf/g_rh.py

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
from __future__ import (absolute_import, division, print_function)
from .constants import Constants
#from .extension import computerh, computetk
from .extension import _rh, _tk
from .util import extract_vars
from .metadecorators import copy_and_set_metadata
@ -64,7 +63,7 @@ def get_rh(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -64,7 +63,7 @@ def get_rh(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -140,7 +139,7 @@ def get_rh_2m(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -140,7 +139,7 @@ def get_rh_2m(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T2", "PSFC", "Q2")
varnames = ("T2", "PSFC", "Q2")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t2 = ncvars["T2"]
@ -153,4 +152,3 @@ def get_rh_2m(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -153,4 +152,3 @@ def get_rh_2m(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
rh = _rh(q2, psfc, t2)
return rh

4
src/wrf/g_slp.py

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
from __future__ import (absolute_import, division, print_function)
#from .extension import computeslp, computetk
from .extension import _slp, _tk
from .constants import Constants
from .destag import destagger
@ -75,7 +74,7 @@ def get_slp(wrfin, timeidx=0, method="cat", squeeze=True, @@ -75,7 +74,7 @@ def get_slp(wrfin, timeidx=0, method="cat", squeeze=True,
:class:`numpy.ndarray` object with no metadata.
"""
varnames=("T", "P", "PB", "QVAPOR", "PH", "PHB")
varnames = ("T", "P", "PB", "QVAPOR", "PH", "PHB")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -100,4 +99,3 @@ def get_slp(wrfin, timeidx=0, method="cat", squeeze=True, @@ -100,4 +99,3 @@ def get_slp(wrfin, timeidx=0, method="cat", squeeze=True,
slp = _slp(destag_ph, tk, full_p, qvapor)
return slp

13
src/wrf/g_temp.py

@ -69,7 +69,7 @@ def get_theta(wrfin, timeidx=0, method="cat", squeeze=True, @@ -69,7 +69,7 @@ def get_theta(wrfin, timeidx=0, method="cat", squeeze=True,
be a :class:`numpy.ndarray` object with no metadata.
"""
varnames = ("T",)
varnames = ("T", )
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -142,7 +142,7 @@ def get_temp(wrfin, timeidx=0, method="cat", squeeze=True, @@ -142,7 +142,7 @@ def get_temp(wrfin, timeidx=0, method="cat", squeeze=True,
"""
varnames=("T", "P", "PB")
varnames = ("T", "P", "PB")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -219,7 +219,7 @@ def get_eth(wrfin, timeidx=0, method="cat", squeeze=True, @@ -219,7 +219,7 @@ def get_eth(wrfin, timeidx=0, method="cat", squeeze=True,
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -299,7 +299,7 @@ def get_tv(wrfin, timeidx=0, method="cat", squeeze=True, @@ -299,7 +299,7 @@ def get_tv(wrfin, timeidx=0, method="cat", squeeze=True,
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
@ -380,7 +380,7 @@ def get_tw(wrfin, timeidx=0, method="cat", squeeze=True, @@ -380,7 +380,7 @@ def get_tw(wrfin, timeidx=0, method="cat", squeeze=True,
"""
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfin, timeidx, varnames, method, squeeze, cache,
meta=False, _key=_key)
t = ncvars["T"]
@ -511,6 +511,3 @@ def get_tc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -511,6 +511,3 @@ def get_tc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
return get_temp(wrfin, timeidx, method, squeeze, cache, meta, _key,
units="degC")

3
src/wrf/g_terrain.py

@ -73,6 +73,3 @@ def get_terrain(wrfin, timeidx=0, method="cat", squeeze=True, @@ -73,6 +73,3 @@ def get_terrain(wrfin, timeidx=0, method="cat", squeeze=True,
return extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta=False,
_key=_key)[varname]

1
src/wrf/g_times.py

@ -118,4 +118,3 @@ def get_xtimes(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -118,4 +118,3 @@ def get_xtimes(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
"""
return extract_times(wrfin, timeidx, method, squeeze, cache,
meta=meta, do_xtime=True)

33
src/wrf/g_uvmet.py

@ -4,7 +4,6 @@ from math import fabs, log, tan, sin, cos @@ -4,7 +4,6 @@ from math import fabs, log, tan, sin, cos
import numpy as np
#from .extension import computeuvmet
from .extension import _uvmet
from .destag import destagger
from .constants import Constants
@ -101,13 +100,13 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True, @@ -101,13 +100,13 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
u = (u_vars[varname] if varname == "U10" else
destagger(u_vars[varname][...,0,:,:], -1))
destagger(u_vars[varname][..., 0, :, :], -1))
varname = either("V10", "VV")(wrfin)
v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
v = (v_vars[varname] if varname == "V10" else
destagger(v_vars[varname][...,0,:,:], -2))
destagger(v_vars[varname][..., 0, :, :], -2))
map_proj_attrs = extract_global_attrs(wrfin, attrs="MAP_PROJ")
map_proj = map_proj_attrs["MAP_PROJ"]
@ -119,7 +118,7 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True, @@ -119,7 +118,7 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
# Note: NCL has no code to handle other projections (0,4,5) as they
# don't appear to be supported any longer
if map_proj in (0,3,6):
if map_proj in (0, 3, 6):
# No rotation needed for Mercator and Lat/Lon, but still need
# u,v aggregated in to one array
@ -145,7 +144,7 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True, @@ -145,7 +144,7 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
result = np.ma.masked_values(result, fill)
return result
elif map_proj in (1,2):
elif map_proj in (1, 2):
lat_attrs = extract_global_attrs(wrfin, attrs=("TRUELAT1",
"TRUELAT2"))
radians_per_degree = Constants.PI/180.0
@ -165,7 +164,6 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True, @@ -165,7 +164,6 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
else:
cen_lon = lon_attrs["STAND_LON"]
varname = either("XLAT_M", "XLAT")(wrfin)
xlat_var = extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta=False,
@ -181,11 +179,12 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True, @@ -181,11 +179,12 @@ def _get_uvmet(wrfin, timeidx=0, method="cat", squeeze=True,
if map_proj == 1:
if((fabs(true_lat1 - true_lat2) > 0.1) and
(fabs(true_lat2 - 90.) > 0.1)):
cone = (log(cos(true_lat1*radians_per_degree))
- log(cos(true_lat2*radians_per_degree)))
cone = (log(cos(true_lat1*radians_per_degree)) -
log(cos(true_lat2*radians_per_degree)))
cone = (cone /
(log(tan((45.-fabs(true_lat1/2.))*radians_per_degree))
- log(tan((45.-fabs(true_lat2/2.))*radians_per_degree))))
- log(tan((45.-fabs(true_lat2/2.)) *
radians_per_degree))))
else:
cone = sin(fabs(true_lat1)*radians_per_degree)
else:
@ -434,7 +433,7 @@ def get_uvmet_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True, @@ -434,7 +433,7 @@ def get_uvmet_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
uvmet = _get_uvmet(wrfin, timeidx, method, squeeze,
cache, meta, _key, False, units="m s-1")
return _calc_wspd_wdir(uvmet[0,...,:,:,:], uvmet[1,...,:,:,:],
return _calc_wspd_wdir(uvmet[0, ..., :, :, :], uvmet[1, ..., :, :, :],
False, units)
@ -517,7 +516,8 @@ def get_uvmet10_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True, @@ -517,7 +516,8 @@ def get_uvmet10_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
uvmet10 = _get_uvmet(wrfin, timeidx, method, squeeze, cache, meta, _key,
True, units="m s-1")
return _calc_wspd_wdir(uvmet10[0,...,:,:], uvmet10[1,...,:,:], True, units)
return _calc_wspd_wdir(uvmet10[0, ..., :, :], uvmet10[1, ..., :, :],
True, units)
def get_uvmet_wspd(wrfin, timeidx=0, method="cat", squeeze=True,
@ -583,7 +583,7 @@ def get_uvmet_wspd(wrfin, timeidx=0, method="cat", squeeze=True, @@ -583,7 +583,7 @@ def get_uvmet_wspd(wrfin, timeidx=0, method="cat", squeeze=True,
"""
result = get_uvmet_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[0,:]
cache, meta, _key, units)[0, :]
if meta:
result.attrs["description"] = "earth rotated wspd"
@ -654,7 +654,7 @@ def get_uvmet_wdir(wrfin, timeidx=0, method="cat", squeeze=True, @@ -654,7 +654,7 @@ def get_uvmet_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
"""
result = get_uvmet_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[1,:]
cache, meta, _key, units)[1, :]
if meta:
result.attrs["description"] = "earth rotated wdir"
@ -725,7 +725,7 @@ def get_uvmet10_wspd(wrfin, timeidx=0, method="cat", squeeze=True, @@ -725,7 +725,7 @@ def get_uvmet10_wspd(wrfin, timeidx=0, method="cat", squeeze=True,
"""
result = get_uvmet10_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[0,:]
cache, meta, _key, units)[0, :]
if meta:
result.attrs["description"] = "10m earth rotated wspd"
@ -795,12 +795,9 @@ def get_uvmet10_wdir(wrfin, timeidx=0, method="cat", squeeze=True, @@ -795,12 +795,9 @@ def get_uvmet10_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
"""
result = get_uvmet10_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[1,:]
cache, meta, _key, units)[1, :]
if meta:
result.attrs["description"] = "10m earth rotated wdir"
return result

1
src/wrf/g_vorticity.py

@ -164,4 +164,3 @@ def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, @@ -164,4 +164,3 @@ def get_pvo(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
full_p = p + pb
return _pvo(u, v, full_t, full_p, msfu, msfv, msfm, cor, dx, dy)

21
src/wrf/g_wind.py

@ -92,13 +92,11 @@ def _calc_wspd_wdir(u, v, two_d, units): @@ -92,13 +92,11 @@ def _calc_wspd_wdir(u, v, two_d, units):
result = np.zeros(outdims, wspd.dtype)
idxs0 = ((0,Ellipsis, slice(None), slice(None), slice(None))
if not two_d else
(0, Ellipsis, slice(None), slice(None)))
idxs0 = ((0, Ellipsis, slice(None), slice(None), slice(None))
if not two_d else (0, Ellipsis, slice(None), slice(None)))
idxs1 = ((1, Ellipsis, slice(None), slice(None), slice(None))
if not two_d else
(1, Ellipsis, slice(None), slice(None)))
if not two_d else (1, Ellipsis, slice(None), slice(None)))
result[idxs0] = wspd[:]
result[idxs1] = wdir[:]
@ -497,13 +495,13 @@ def get_destag_wspd_wdir10(wrfin, timeidx=0, method="cat", @@ -497,13 +495,13 @@ def get_destag_wspd_wdir10(wrfin, timeidx=0, method="cat",
u_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
u = (u_vars[varname] if varname == "U10" else
destagger(u_vars[varname][...,0,:,:], -1))
destagger(u_vars[varname][..., 0, :, :], -1))
varname = either("V10", "VV")(wrfin)
v_vars = extract_vars(wrfin, timeidx, varname, method, squeeze, cache,
meta=False, _key=_key)
v = (v_vars[varname] if varname == "V10" else
destagger(v_vars[varname][...,0,:,:], -2))
destagger(v_vars[varname][..., 0, :, :], -2))
return _calc_wspd_wdir(u, v, True, units)
@ -569,7 +567,7 @@ def get_destag_wspd(wrfin, timeidx=0, method="cat", @@ -569,7 +567,7 @@ def get_destag_wspd(wrfin, timeidx=0, method="cat",
"""
result = get_destag_wspd_wdir(wrfin, timeidx, method, squeeze, cache,
meta, _key, units)[0,:]
meta, _key, units)[0, :]
if meta:
result.attrs["description"] = "wspd in projection space"
@ -638,7 +636,7 @@ def get_destag_wdir(wrfin, timeidx=0, method="cat", @@ -638,7 +636,7 @@ def get_destag_wdir(wrfin, timeidx=0, method="cat",
"""
result = get_destag_wspd_wdir(wrfin, timeidx, method, squeeze, cache,
meta, _key, units)[1,:]
meta, _key, units)[1, :]
if meta:
result.attrs["description"] = "wdir in projection space"
@ -708,7 +706,7 @@ def get_destag_wspd10(wrfin, timeidx=0, method="cat", @@ -708,7 +706,7 @@ def get_destag_wspd10(wrfin, timeidx=0, method="cat",
"""
result = get_destag_wspd_wdir10(wrfin, timeidx, method,
squeeze, cache, meta, _key, units)[0,:]
squeeze, cache, meta, _key, units)[0, :]
if meta:
result.attrs["description"] = "10m wspd in projection space"
@ -778,10 +776,9 @@ def get_destag_wdir10(wrfin, timeidx=0, method="cat", @@ -778,10 +776,9 @@ def get_destag_wdir10(wrfin, timeidx=0, method="cat",
"""
result = get_destag_wspd_wdir10(wrfin, timeidx, method,
squeeze, cache, meta, _key, units)[1,:]
squeeze, cache, meta, _key, units)[1, :]
if meta:
result.attrs["description"] = "10m wdir in projection space"
return result

9
src/wrf/geobnds.py

@ -2,6 +2,7 @@ from __future__ import (absolute_import, division, print_function) @@ -2,6 +2,7 @@ from __future__ import (absolute_import, division, print_function)
from .coordpair import CoordPair
class GeoBounds(object):
"""A class that stores the geographic boundaries.
@ -56,8 +57,8 @@ class GeoBounds(object): @@ -56,8 +57,8 @@ class GeoBounds(object):
raise ValueError("'top_right' parameter does not contain a"
"'lon' attribute")
elif lats is not None and lons is not None:
self.bottom_left = CoordPair(lat=lats[0,0], lon=lons[0,0])
self.top_right = CoordPair(lat=lats[-1,-1], lon=lons[-1,-1])
self.bottom_left = CoordPair(lat=lats[0, 0], lon=lons[0, 0])
self.top_right = CoordPair(lat=lats[-1, -1], lon=lons[-1, -1])
else:
raise ValueError("must specify either 'bottom_top' and "
"'top_right' parameters "
@ -84,7 +85,3 @@ class NullGeoBounds(GeoBounds): @@ -84,7 +85,3 @@ class NullGeoBounds(GeoBounds):
def __repr__(self):
return "{}()".format(self.__class__.__name__)

127
src/wrf/interp.py

@ -76,11 +76,24 @@ def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64), @@ -76,11 +76,24 @@ def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64),
p = getvar(wrfin, "pressure")
ht = getvar(wrfin, "z", units="dm")
pblh = getvar(wrfin, "PBLH")
ht_500 = interplevel(ht, p, 500.0)
Interpolate Relative Humidity to Boundary Layer Heights
.. code-block:: python
from netCDF4 import Dataset
from wrf import getvar, interplevel
wrfin = Dataset("wrfout_d02_2010-06-13_21:00:00")
rh = getvar(wrfin, "rh")
z = getvar(wrfin, "z")
pblh = getvar(wrfin, "PBLH")
rh_pblh = interplevel(rh, p, pblh)
"""
@ -97,7 +110,7 @@ def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64), @@ -97,7 +110,7 @@ def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64),
else:
result = _interpz3d_lev2d(field3d, vert, _desiredlev, missing)
masked = ma.masked_values (result, missing)
masked = ma.masked_values(result, missing)
if not meta:
if squeeze:
@ -162,9 +175,9 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64), @@ -162,9 +175,9 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
timeidx (:obj:`int`, optional): The
desired time index when obtaining map boundary information
from moving nests. This value can be a positive or negative integer.
Only required when *wrfin* is specified and the nest is moving.
Currently, :data:`wrf.ALL_TIMES` is not supported.
from moving nests. This value can be a positive or negative
integer. Only required when *wrfin* is specified and the nest is
moving. Currently, :data:`wrf.ALL_TIMES` is not supported.
Default is 0.
stagger (:obj:`str`): If using latitude, longitude coordinate pairs
@ -286,12 +299,12 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64), @@ -286,12 +299,12 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using lat/lon "
"cross sections because the domain could "
"move outside of the cross section. "
"You must request each time "
"individually.")
raise ValueError("Requesting all times with a moving "
"nest is not supported when using "
"lat/lon cross sections because the "
"domain could move outside of the "
"cross section. You must request "
"each time individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
@ -343,7 +356,7 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64), @@ -343,7 +356,7 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
result = np.empty(outshape, dtype=field3d.dtype)
for i in py3range(field3d.shape[0]):
result[i,:] = _vertcross(field3d[i,:], xy, var2dz, z_var2d,
result[i, :] = _vertcross(field3d[i, :], xy, var2dz, z_var2d,
missing)[:]
return ma.masked_values(result, missing)
@ -379,9 +392,9 @@ def interpline(field2d, wrfin=None, timeidx=0, stagger=None, projection=None, @@ -379,9 +392,9 @@ def interpline(field2d, wrfin=None, timeidx=0, stagger=None, projection=None,
timeidx (:obj:`int`, optional): The
desired time index when obtaining map boundary information
from moving nests. This value can be a positive or negative integer.
Only required when *wrfin* is specified and the nest is moving.
Currently, :data:`wrf.ALL_TIMES` is not supported.
from moving nests. This value can be a positive or negative
integer. Only required when *wrfin* is specified and the nest is
moving. Currently, :data:`wrf.ALL_TIMES` is not supported.
Default is 0.
stagger (:obj:`str`): If using latitude, longitude coordinate pairs
@ -496,10 +509,10 @@ def interpline(field2d, wrfin=None, timeidx=0, stagger=None, projection=None, @@ -496,10 +509,10 @@ def interpline(field2d, wrfin=None, timeidx=0, stagger=None, projection=None,
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using a lat/lon "
"line because the domain could "
"move outside of line. "
raise ValueError("Requesting all times with a moving "
"nest is not supported when using a "
"lat/lon line because the domain "
"could move outside of line. "
"You must request each time "
"individually.")
else:
@ -572,8 +585,8 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False, @@ -572,8 +585,8 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
* 'ght_msl': grid point height msl [km]
* 'ght_agl': grid point height agl [km]
* 'theta', 'th': potential temperature [K]
* 'theta-e', 'thetae', 'eth': equivalent potential temperature \
[K]
* 'theta-e', 'thetae', 'eth': equivalent potential \
temperature [K]
interp_levels (sequence): A 1D sequence of vertical levels to
interpolate to. Values must be in the same units as specified
@ -662,39 +675,37 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False, @@ -662,39 +675,37 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
"tc", "tk", "theta", "th", "theta-e", "thetae",
"eth", "ght", 'z_km', 'ght_km')
icase_lookup = {"none" : 0,
"p" : 1,
"pres" : 1,
"pressure" : 1,
"p_hpa" : 1,
"pres_hpa" : 1,
"pressure_hpa" : 1,
"z" : 2,
"ght" : 2,
"z_km" : 2,
"ght_km" : 2,
"tc" : 3,
"tk" : 4,
"theta" : 5,
"th" : 5,
"theta-e" : 6,
"thetae" : 6,
"eth" : 6}
in_unitmap = {"p_hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"pres_hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"pressure_hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"z_km" : 1.0/ConversionFactors.M_TO_KM,
"ght_km" : 1.0/ConversionFactors.M_TO_KM,
icase_lookup = {"none": 0,
"p": 1,
"pres": 1,
"pressure": 1,
"p_hpa": 1,
"pres_hpa": 1,
"pressure_hpa": 1,
"z": 2,
"ght": 2,
"z_km": 2,
"ght_km": 2,
"tc": 3,
"tk": 4,
"theta": 5,
"th": 5,
"theta-e": 6,
"thetae": 6,
"eth": 6}
in_unitmap = {"p_hpa": 1.0/ConversionFactors.PA_TO_HPA,
"pres_hpa": 1.0/ConversionFactors.PA_TO_HPA,
"pressure_hpa": 1.0/ConversionFactors.PA_TO_HPA,
"z_km": 1.0/ConversionFactors.M_TO_KM,
"ght_km": 1.0/ConversionFactors.M_TO_KM,
}
out_unitmap = {"p_hpa" : ConversionFactors.PA_TO_HPA,
"pres_hpa" : ConversionFactors.PA_TO_HPA,
"pressure_hpa" : ConversionFactors.PA_TO_HPA,
"z_km" : ConversionFactors.M_TO_KM,
"ght_km" : ConversionFactors.M_TO_KM,
out_unitmap = {"p_hpa": ConversionFactors.PA_TO_HPA,
"pres_hpa": ConversionFactors.PA_TO_HPA,
"pressure_hpa": ConversionFactors.PA_TO_HPA,
"z_km": ConversionFactors.M_TO_KM,
"ght_km": ConversionFactors.M_TO_KM,
}
# These constants match what's in the fortran code.
@ -715,12 +726,12 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False, @@ -715,12 +726,12 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
# Check for valid coord
if vert_coord not in valid_coords:
raise ValueError("'%s' is not a valid vertical "
"coordinate type" % vert_coord)
raise ValueError("'{}' is not a valid vertical "
"coordinate type".format(vert_coord))
# Check for valid field type
if field_type not in valid_field_types:
raise ValueError("'%s' is not a valid field type" % field_type)
raise ValueError("'{}' is not a valid field type".format(field_type))
log_p_int = 1 if log_p else 0
@ -848,9 +859,3 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False, @@ -848,9 +859,3 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
res_ = res
return ma.masked_values(res_, missing)

50
src/wrf/interputils.py

@ -31,7 +31,7 @@ def to_positive_idxs(shape, coord): @@ -31,7 +31,7 @@ def to_positive_idxs(shape, coord):
if (coord[-2] >= 0 and coord[-1] >= 0):
return coord
return [x if (x >= 0) else shape[-i-1]+x for (i,x) in enumerate(coord)]
return [x if (x >= 0) else shape[-i-1]+x for (i, x) in enumerate(coord)]
def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
@ -85,11 +85,10 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None, @@ -85,11 +85,10 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
if (angle > 315.0 or angle < 45.0
or ((angle > 135.0) and (angle < 225.0))):
#x = y*slope + intercept
slope = -(360.-angle)/45.
if( angle < 45. ):
if(angle < 45.):
slope = angle/45.
if( angle > 135.):
if(angle > 135.):
slope = (angle-180.)/45.
intercept = xp - yp*slope
@ -98,49 +97,49 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None, @@ -98,49 +97,49 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
y0 = 0.
x0 = y0*slope + intercept
if( x0 < 0.): # intersect outside of left boundary
if(x0 < 0.): # intersect outside of left boundary
x0 = 0.
y0 = (x0 - intercept)/slope
if( x0 > xdim-1): #intersect outside of right boundary
if(x0 > xdim-1): # intersect outside of right boundary
x0 = xdim-1
y0 = (x0 - intercept)/slope
y1 = ydim-1. #need to make sure this will be a float?
y1 = ydim-1. # need to make sure this will be a float?
x1 = y1*slope + intercept
if( x1 < 0.): # intersect outside of left boundary
if(x1 < 0.): # intersect outside of left boundary
x1 = 0.
y1 = (x1 - intercept)/slope
if( x1 > xdim-1): # intersect outside of right boundary
if(x1 > xdim-1): # intersect outside of right boundary
x1 = xdim-1
y1 = (x1 - intercept)/slope
else:
# y = x*slope + intercept
slope = (90.-angle)/45.
if( angle > 225. ):
if (angle > 225.):
slope = (270.-angle)/45.
intercept = yp - xp*slope
#find intersections with domain boundaries
# Find intersections with domain boundaries
x0 = 0.
y0 = x0*slope + intercept
if( y0 < 0.): # intersect outside of bottom boundary
if (y0 < 0.): # intersect outside of bottom boundary
y0 = 0.
x0 = (y0 - intercept)/slope
if( y0 > ydim-1): # intersect outside of top boundary
if (y0 > ydim-1): # intersect outside of top boundary
y0 = ydim-1
x0 = (y0 - intercept)/slope
x1 = xdim-1. # need to make sure this will be a float?
y1 = x1*slope + intercept
if( y1 < 0.): # intersect outside of bottom boundary
if (y1 < 0.): # intersect outside of bottom boundary
y1 = 0.
x1 = (y1 - intercept)/slope
if( y1 > ydim-1):# intersect outside of top boundary
if (y1 > ydim-1): # intersect outside of top boundary
y1 = ydim-1
x1 = (y1 - intercept)/slope
elif start_point is not None and end_point is not None:
@ -164,14 +163,14 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None, @@ -164,14 +163,14 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
distance = (dx*dx + dy*dy)**0.5
npts = int(distance) + 1
xy = np.zeros((npts,2), "float")
xy = np.zeros((npts, 2), "float")
dx = dx/(npts-1)
dy = dy/(npts-1)
for i in py3range(npts):
xy[i,0] = x0 + i*dx
xy[i,1] = y0 + i*dy
xy[i, 0] = x0 + i*dx
xy[i, 1] = y0 + i*dy
return xy
@ -237,8 +236,8 @@ def get_xy_z_params(z, pivot_point=None, angle=None, @@ -237,8 +236,8 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
var2dz = _interp2dxy(z, xy)
extra_dim_num = z.ndim - 3
idx1 = tuple([0]*extra_dim_num + [0,0])
idx2 = tuple([0]*extra_dim_num + [-1,0])
idx1 = tuple([0]*extra_dim_num + [0, 0])
idx2 = tuple([0]*extra_dim_num + [-1, 0])
if levels is None:
# interp to constant z grid
@ -256,7 +255,7 @@ def get_xy_z_params(z, pivot_point=None, angle=None, @@ -256,7 +255,7 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
z_var2d = np.zeros((autolevels), dtype=z.dtype)
z_var2d[0] = z_min
for i in py3range(1,autolevels):
for i in py3range(1, autolevels):
z_var2d[i] = z_var2d[0] + i*dz
else:
z_var2d = np.asarray(levels, z.dtype)
@ -323,6 +322,7 @@ def get_xy(var, pivot_point=None, angle=None, @@ -323,6 +322,7 @@ def get_xy(var, pivot_point=None, angle=None,
return xy
def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None,
ll_point=None):
"""Return the coordinate pairs in grid space.
@ -381,7 +381,7 @@ def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None, @@ -381,7 +381,7 @@ def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None,
"""
if (wrfin is None and (projection is None or ll_point is None)):
raise ValueError ("'wrfin' parameter or "
raise ValueError("'wrfin' parameter or "
"'projection' and 'll_point' parameters "
"are required")
@ -389,7 +389,8 @@ def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None, @@ -389,7 +389,8 @@ def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None,
if wrfin is not None:
xy_vals = _ll_to_xy(lat, lon, wrfin=wrfin, timeidx=timeidx,
squeeze=True, meta=False, stagger=stagger, as_int=True)
squeeze=True, meta=False, stagger=stagger,
as_int=True)
else:
map_proj = projection.map_proj
@ -427,9 +428,8 @@ def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None, @@ -427,9 +428,8 @@ def to_xy_coords(pairs, wrfin=None, timeidx=0, stagger=None, projection=None,
xy_vals = xy_vals.squeeze()
if xy_vals.ndim == 1:
return CoordPair(x=xy_vals[0], y=xy_vals[1])
else:
return [CoordPair(x=xy_vals[0,i], y=xy_vals[1,i])
return [CoordPair(x=xy_vals[0, i], y=xy_vals[1, i])
for i in py3range(xy_vals.shape[1])]

35
src/wrf/latlonutils.py

@ -7,8 +7,8 @@ import numpy as np @@ -7,8 +7,8 @@ import numpy as np
from .constants import Constants, ProjectionTypes
from .extension import _lltoxy, _xytoll
from .util import (extract_vars, extract_global_attrs,
either, is_moving_domain, is_multi_time_req,
iter_left_indexes, is_mapping, is_multi_file)
either, is_moving_domain, iter_left_indexes,
is_mapping, is_multi_file)
from .py3compat import viewkeys, viewitems
from .projutils import dict_keys_to_upper
@ -46,6 +46,7 @@ def _lat_varname(wrfin, stagger): @@ -46,6 +46,7 @@ def _lat_varname(wrfin, stagger):
return varname
def _lon_varname(wrfin, stagger):
"""Return the longitude variable name for the specified stagger type.
@ -79,6 +80,7 @@ def _lon_varname(wrfin, stagger): @@ -79,6 +80,7 @@ def _lon_varname(wrfin, stagger):
return varname
def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
"""Return the map projection parameters.
@ -232,12 +234,12 @@ def _kwarg_proj_params(**projparams): @@ -232,12 +234,12 @@ def _kwarg_proj_params(**projparams):
# Sanity checks
# Required args for all projections
for name, var in viewitems({"MAP_PROJ" : map_proj,
"REF_LAT" : ref_lat,
"REF_LON" : ref_lon,
"KNOWN_X" : known_x,
"KNOWN_Y" : known_y,
"DX" : dx}):
for name, var in viewitems({"MAP_PROJ": map_proj,
"REF_LAT": ref_lat,
"REF_LON": ref_lon,
"KNOWN_X": known_x,
"KNOWN_Y": known_y,
"DX": dx}):
if var is None:
raise ValueError("'{}' argument required".format(name))
@ -391,7 +393,6 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0, @@ -391,7 +393,6 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
result = np.empty(outdim, np.float64)
for left_idxs in iter_left_indexes(extra_dims):
#left_and_slice_idxs = left_idxs + (slice(None), )
# Left indexes is a misnomer, since these will be on the right
x_idxs = (0,) + left_idxs
y_idxs = (1,) + left_idxs
@ -426,7 +427,6 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0, @@ -426,7 +427,6 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
result[0] = fort_out[1]
result[1] = fort_out[0]
# Make indexes 0-based
result = result - 1
@ -435,6 +435,7 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0, @@ -435,6 +435,7 @@ def _ll_to_xy(latitude, longitude, wrfin=None, timeidx=0,
return result
# X and Y should be 0-based
def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
method="cat", squeeze=True, cache=None, _key=None,
@ -528,7 +529,6 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None, @@ -528,7 +529,6 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc) = _kwarg_proj_params(**projparams)
if isinstance(x, Iterable):
x_arr = np.asarray(x)
y_arr = np.asarray(y)
@ -555,7 +555,6 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None, @@ -555,7 +555,6 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
result = np.empty(outdim, np.float64)
for left_idxs in iter_left_indexes(extra_dims):
#left_and_slice_idxs = left_idxs + (slice(None), )
lat_idxs = (0,) + left_idxs
lon_idxs = (1,) + left_idxs
@ -573,7 +572,6 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None, @@ -573,7 +572,6 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
ref_lon_val, pole_lat, pole_lon, known_x, known_y,
dx, dy, latinc, loninc, x_val, y_val)
#result[left_and_slice_idxs] = ll[:]
result[lat_idxs] = ll[0]
result[lon_idxs] = ll[1]
@ -582,13 +580,8 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None, @@ -582,13 +580,8 @@ def _xy_to_ll(x, y, wrfin=None, timeidx=0, stagger=None,
x_val = x + 1
y_val = y + 1
result = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon,
pole_lat, pole_lon, known_x, known_y, dx, dy, latinc,
loninc, x_val, y_val)
result = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat,
ref_lon, pole_lat, pole_lon, known_x, known_y,
dx, dy, latinc, loninc, x_val, y_val)
return result

155
src/wrf/metadecorators.py

@ -112,7 +112,6 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None, @@ -112,7 +112,6 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
var_to_copy = None if cache is None else cache.get(_copy_varname,
None)
if var_to_copy is None:
var_to_copy = extract_vars(wrfin, timeidx, (_copy_varname,),
method, squeeze, cache,
@ -155,7 +154,6 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None, @@ -155,7 +154,6 @@ def copy_and_set_metadata(copy_varname=None, delete_attrs=None, name=None,
except KeyError:
pass
if name is not None:
outname = name
@ -277,10 +275,8 @@ def set_wind_metadata(copy_varname, name, description, @@ -277,10 +275,8 @@ def set_wind_metadata(copy_varname, name, description,
outattrs = OrderedDict()
outdimnames = list(copy_var.dims)
#outcoords.update(copy_var.coords)
outattrs.update(copy_var.attrs)
if wind_ncvar:
outcoords.update(copy_var.coords)
elif not wspd_wdir:
@ -307,7 +303,7 @@ def set_wind_metadata(copy_varname, name, description, @@ -307,7 +303,7 @@ def set_wind_metadata(copy_varname, name, description,
# So, need to rebuild the XLAT, XLONG, coordinates again since the
# leftmost index changed.
if not wind_ncvar:
for key,dataarray in viewitems(copy_var.coords):
for key, dataarray in viewitems(copy_var.coords):
if is_coordvar(key):
outcoords[key] = dataarray.dims, to_np(dataarray)
elif key == "XTIME":
@ -414,13 +410,12 @@ def set_cape_metadata(is2d): @@ -414,13 +410,12 @@ def set_cape_metadata(is2d):
outattrs["_FillValue"] = missing
outattrs["missing_value"] = missing
# xarray doesn't line up coordinate dimensions based on
# names, it just remembers the index it originally mapped to.
# So, need to rebuild the XLAT, XLONG, coordinates again since the
# leftmost index changed.
for key,dataarray in viewitems(copy_var.coords):
for key, dataarray in viewitems(copy_var.coords):
if is_coordvar(key):
outcoords[key] = dataarray.dims, to_np(dataarray)
elif key == "XTIME":
@ -433,7 +428,6 @@ def set_cape_metadata(is2d): @@ -433,7 +428,6 @@ def set_cape_metadata(is2d):
else:
outcoords["cape_cin"] = ["cape", "cin"]
return DataArray(result, name=outname, coords=outcoords,
dims=outdimnames, attrs=outattrs)
@ -543,7 +537,7 @@ def set_cloudfrac_metadata(): @@ -543,7 +537,7 @@ def set_cloudfrac_metadata():
# So, need to rebuild the XLAT, XLONG, coordinates again since the
# leftmost index changed.
for key,dataarray in viewitems(copy_var.coords):
for key, dataarray in viewitems(copy_var.coords):
if is_coordvar(key):
outcoords[key] = dataarray.dims, to_np(dataarray)
elif key == "XTIME":
@ -632,8 +626,8 @@ def set_latlon_metadata(xy=False): @@ -632,8 +626,8 @@ def set_latlon_metadata(xy=False):
for x in zip(arr1, arr2)])
coords[dimnames[0]] = ["lat", "lon"]
else:
coords["latlon_coord"] = (dimnames[-1], [CoordPair(lat=x[0],
lon=x[1])
coords["latlon_coord"] = (dimnames[-1],
[CoordPair(lat=x[0], lon=x[1])
for x in zip(arr1, arr2)])
coords[dimnames[0]] = ["x", "y"]
@ -750,11 +744,12 @@ def set_height_metadata(geopt=False, stag=False): @@ -750,11 +744,12 @@ def set_height_metadata(geopt=False, stag=False):
"(mass grid)".format(height_type))
else:
outattrs["description"] = ("model height - [{}] (vertically "
"staggered grid)".format(height_type))
"staggered grid)".format(
height_type))
return DataArray(result, name=outname, dims=outdimnames,
coords=outcoords, attrs=outattrs)
return DataArray(result, name=outname,
dims=outdimnames, coords=outcoords, attrs=outattrs)
return func_wrapper
@ -819,7 +814,6 @@ def _set_horiz_meta(wrapped, instance, args, kwargs): @@ -819,7 +814,6 @@ def _set_horiz_meta(wrapped, instance, args, kwargs):
if isinstance(z, DataArray):
vert_units = z.attrs.get("units", None)
if isinstance(field3d, DataArray):
outcoords = OrderedDict()
outdimnames = list(field3d.dims)
@ -993,7 +987,8 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -993,7 +987,8 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
end_point_xy = (end_point.x, end_point.y)
xy, var2dz, z_var2d = get_xy_z_params(to_np(z), pivot_point_xy, angle,
start_point_xy, end_point_xy, levels, autolevels)
start_point_xy, end_point_xy,
levels, autolevels)
# Make a copy so we don't modify a user supplied cache
if cache is not None:
@ -1018,10 +1013,10 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -1018,10 +1013,10 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
outattrs = OrderedDict()
# Use XY to set the cross-section metadata
st_x = xy[0,0]
st_y = xy[0,1]
ed_x = xy[-1,0]
ed_y = xy[-1,1]
st_x = xy[0, 0]
st_y = xy[0, 1]
ed_x = xy[-1, 0]
ed_y = xy[-1, 1]
cross_str = "({0}, {1}) to ({2}, {3})".format(st_x, st_y, ed_x, ed_y)
if angle is not None:
@ -1032,14 +1027,13 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -1032,14 +1027,13 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
outcoords = OrderedDict()
outdimnames = list(field3d.dims)
outcoords.update(field3d.coords)
for i in py3range(-3,0,1):
for i in py3range(-3, 0, 1):
outdimnames.remove(field3d.dims[i])
try:
del outcoords[field3d.dims[i]]
except KeyError:
pass # Xarray 0.9
# Delete any lat,lon coords
delkeys = [key for key in viewkeys(outcoords) if is_coordvar(key)]
for key in delkeys:
@ -1069,12 +1063,10 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -1069,12 +1063,10 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
lats = _interpline(latcoord, xy)
lons = _interpline(loncoord, xy)
outcoords["xy_loc"] = ("cross_line_idx",
np.asarray(tuple(
CoordPair(x=xy[i,0], y=xy[i,1],
outcoords["xy_loc"] = ("cross_line_idx", np.asarray(tuple(
CoordPair(x=xy[i, 0], y=xy[i, 1],
lat=lats[i], lon=lons[i])
for i in py3range(xy.shape[-2])))
)
for i in py3range(xy.shape[-2]))))
# Moving domain
else:
extra_dims = latcoord.shape[0:-2]
@ -1086,12 +1078,11 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -1086,12 +1078,11 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
lats = _interpline(latcoord[idxs], xy)
lons = _interpline(loncoord[idxs], xy)
latlon_loc[idxs] = np.asarray(tuple(
CoordPair(x=xy[i,0], y=xy[i,1],
latlon_loc[idxs] = np.asarray(
tuple(CoordPair(
x=xy[i, 0], y=xy[i, 1],
lat=lats[i], lon=lons[i])
for i in py3range(xy.shape[-2]))
)[:]
for i in py3range(xy.shape[-2])))[:]
extra_dimnames = latcoord.dims[0:-2]
loc_dimnames = extra_dimnames + ("cross_line_idx",)
@ -1099,14 +1090,16 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -1099,14 +1090,16 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
else:
warnings.warn("'latlon' is set to True, but 'field3d' "
" contains no coordinate information")
outcoords["xy_loc"] = ("cross_line_idx", np.asarray(tuple(
CoordPair(xy[i,0], xy[i,1])
"contains no coordinate information")
outcoords["xy_loc"] = ("cross_line_idx",
np.asarray(tuple(
CoordPair(xy[i, 0], xy[i, 1])
for i in py3range(xy.shape[-2]))))
else:
outcoords["xy_loc"] = ("cross_line_idx", np.asarray(tuple(
CoordPair(xy[i,0], xy[i,1])
outcoords["xy_loc"] = ("cross_line_idx",
np.asarray(tuple(
CoordPair(xy[i, 0], xy[i, 1])
for i in py3range(xy.shape[-2]))))
outcoords["vertical"] = z_var2d[:]
@ -1160,11 +1153,10 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1160,11 +1153,10 @@ def _set_line_meta(wrapped, instance, args, kwargs):
:mod:`wrapt`
"""
argvars = from_args(wrapped, ("field2d",
"wrfin", "timeidx", "stagger", "projection",
"ll_point", "pivot_point", "angle",
"start_point", "end_point", "latlon",
"cache"),
argvars = from_args(wrapped, ("field2d", "wrfin", "timeidx", "stagger",
"projection", "ll_point", "pivot_point",
"angle", "start_point", "end_point",
"latlon", "cache"),
*args, **kwargs)
field2d = argvars["field2d"]
@ -1223,7 +1215,6 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1223,7 +1215,6 @@ def _set_line_meta(wrapped, instance, args, kwargs):
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None:
xy_coords = to_xy_coords(pivot_point, wrfin, _timeidx,
@ -1232,7 +1223,6 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1232,7 +1223,6 @@ def _set_line_meta(wrapped, instance, args, kwargs):
else:
pivot_point_xy = (pivot_point.x, pivot_point.y)
if start_point is not None and end_point is not None:
if start_point.lat is not None and start_point.lon is not None:
xy_coords = to_xy_coords(start_point, wrfin, _timeidx,
@ -1248,7 +1238,6 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1248,7 +1238,6 @@ def _set_line_meta(wrapped, instance, args, kwargs):
else:
end_point_xy = (end_point.x, end_point.y)
xy = get_xy(field2d, pivot_point_xy, angle, start_point_xy, end_point_xy)
# Make a copy so we don't modify a user supplied cache
@ -1269,21 +1258,20 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1269,21 +1258,20 @@ def _set_line_meta(wrapped, instance, args, kwargs):
outattrs = OrderedDict()
# Use XY to set the cross-section metadata
st_x = xy[0,0]
st_y = xy[0,1]
ed_x = xy[-1,0]
ed_y = xy[-1,1]
st_x = xy[0, 0]
st_y = xy[0, 1]
ed_x = xy[-1, 0]
ed_y = xy[-1, 1]
cross_str = "({0}, {1}) to ({2}, {3})".format(st_x, st_y, ed_x, ed_y)
if angle is not None:
cross_str += " ; center={0} ; angle={1}".format(pivot_point,
angle)
cross_str += " ; center={0} ; angle={1}".format(pivot_point, angle)
if isinstance(field2d, DataArray):
outcoords = OrderedDict()
outdimnames = list(field2d.dims)
outcoords.update(field2d.coords)
for i in py3range(-2,0,1):
for i in py3range(-2, 0, 1):
outdimnames.remove(field2d.dims[i])
try:
del outcoords[field2d.dims[i]]
@ -1318,12 +1306,10 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1318,12 +1306,10 @@ def _set_line_meta(wrapped, instance, args, kwargs):
lats = _interpline(latcoord, xy)
lons = _interpline(loncoord, xy)
outcoords["xy_loc"] = ("line_idx",
np.asarray(tuple(
CoordPair(x=xy[i,0], y=xy[i,1],
outcoords["xy_loc"] = ("line_idx", np.asarray(tuple(
CoordPair(x=xy[i, 0], y=xy[i, 1],
lat=lats[i], lon=lons[i])
for i in py3range(xy.shape[-2])))
)
for i in py3range(xy.shape[-2]))))
# Moving domain
else:
@ -1337,11 +1323,9 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1337,11 +1323,9 @@ def _set_line_meta(wrapped, instance, args, kwargs):
lons = _interpline(loncoord[idxs], xy)
latlon_loc[idxs] = np.asarray(tuple(
CoordPair(x=xy[i,0], y=xy[i,1],
CoordPair(x=xy[i, 0], y=xy[i, 1],
lat=lats[i], lon=lons[i])
for i in py3range(xy.shape[-2]))
)[:]
for i in py3range(xy.shape[-2])))[:]
extra_dimnames = latcoord.dims[0:-2]
loc_dimnames = extra_dimnames + ("line_idx",)
@ -1350,15 +1334,13 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1350,15 +1334,13 @@ def _set_line_meta(wrapped, instance, args, kwargs):
else:
warnings.warn("'latlon' is set to True, but 'field2d' "
"contains no coordinate information")
outcoords["xy_loc"] = ("line_idx", np.asarray(tuple(
CoordPair(xy[i,0], xy[i,1])
outcoords["xy_loc"] = ("line_idx", np.asarray(
tuple(CoordPair(xy[i, 0], xy[i, 1])
for i in py3range(xy.shape[-2]))))
else:
outcoords["xy_loc"] = ("line_idx", np.asarray(tuple(
CoordPair(xy[i,0], xy[i,1])
outcoords["xy_loc"] = ("line_idx", np.asarray(
tuple(CoordPair(xy[i, 0], xy[i, 1])
for i in py3range(xy.shape[-2]))))
else:
if inc_latlon:
warnings.warn("'latlon' is set to True, but 'field2d' is "
@ -1427,7 +1409,6 @@ def _set_vinterp_meta(wrapped, instance, args, kwargs): @@ -1427,7 +1409,6 @@ def _set_vinterp_meta(wrapped, instance, args, kwargs):
outcoords = None
outattrs = OrderedDict()
if isinstance(field, DataArray):
outcoords = OrderedDict()
outdimnames = list(field.dims)
@ -1443,7 +1424,6 @@ def _set_vinterp_meta(wrapped, instance, args, kwargs): @@ -1443,7 +1424,6 @@ def _set_vinterp_meta(wrapped, instance, args, kwargs):
outcoords["interp_level"] = interp_levels
outattrs.update(field.attrs)
outname = field.name
else:
@ -1498,13 +1478,12 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): @@ -1498,13 +1478,12 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
result = wrapped(*args, **kwargs)
# Use XY to set the cross-section metadata
st_x = xy[0,0]
st_y = xy[0,1]
ed_x = xy[-1,0]
ed_y = xy[-1,1]
st_x = xy[0, 0]
st_y = xy[0, 1]
ed_x = xy[-1, 0]
ed_y = xy[-1, 1]
cross_str = "({0},{1}) to ({2},{3})".format(st_x, st_y,
ed_x, ed_y)
cross_str = "({0},{1}) to ({2},{3})".format(st_x, st_y, ed_x, ed_y)
outname = None
outdimnames = None
@ -1517,7 +1496,7 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): @@ -1517,7 +1496,7 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
outdimnames = list(field3d.dims)
outcoords.update(field3d.coords)
for i in py3range(-2,0,1):
for i in py3range(-2, 0, 1):
try:
del outcoords[field3d.dims[i]]
except KeyError:
@ -1525,14 +1504,13 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): @@ -1525,14 +1504,13 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
outdimnames.remove(field3d.dims[i])
# Need to remove XLAT, XLONG...
delkeys = (key for key,arr in viewitems(field3d.coords)
delkeys = (key for key, arr in viewitems(field3d.coords)
if arr.ndim > 1)
for key in delkeys:
del outcoords[key]
outdimnames.append("line_idx")
#outattrs.update(field3d.attrs)
desc = field3d.attrs.get("description", None)
if desc is not None:
@ -1544,7 +1522,8 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs): @@ -1544,7 +1522,8 @@ def _set_2dxy_meta(wrapped, instance, args, kwargs):
outname = "{0}_2dxy".format(field3d.name)
outcoords["xy_loc"] = ("line_idx", [CoordPair(xy[i,0], xy[i,1])
outcoords["xy_loc"] = ("line_idx",
[CoordPair(xy[i, 0], xy[i, 1])
for i in py3range(xy.shape[-2])])
for key in ("MemoryOrder",):
@ -1611,7 +1590,7 @@ def _set_1d_meta(wrapped, instance, args, kwargs): @@ -1611,7 +1590,7 @@ def _set_1d_meta(wrapped, instance, args, kwargs):
outcoords = None
outattrs = OrderedDict()
# Dims are (...,xy,z)
# Dims are (..., xy, z)
if isinstance(field, DataArray):
outcoords = OrderedDict()
outdimnames = list(field.dims)
@ -1824,7 +1803,6 @@ def set_alg_metadata(alg_ndims, refvarname, @@ -1824,7 +1803,6 @@ def set_alg_metadata(alg_ndims, refvarname,
if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs)
result = wrapped(*args, **kwargs)
outname = wrapped.__name__
@ -1858,7 +1836,6 @@ def set_alg_metadata(alg_ndims, refvarname, @@ -1858,7 +1836,6 @@ def set_alg_metadata(alg_ndims, refvarname,
if _units is not None:
outattrs["units"] = _units
if description is not None:
if isinstance(description, from_var):
desc = description(wrapped, *args, **kwargs)
@ -1867,7 +1844,6 @@ def set_alg_metadata(alg_ndims, refvarname, @@ -1867,7 +1844,6 @@ def set_alg_metadata(alg_ndims, refvarname,
else:
outattrs["description"] = description
# Copy the dimnames from the reference variable, otherwise, use
# the supplied dimnames
if refvarname is not None:
@ -1909,7 +1885,7 @@ def set_alg_metadata(alg_ndims, refvarname, @@ -1909,7 +1885,7 @@ def set_alg_metadata(alg_ndims, refvarname,
ref_extra = refvar.ndim - refvarndims
ref_left_dimnames = refvar.dims[0:ref_extra]
for i,dimname in enumerate(ref_left_dimnames[::-1], 1):
for i, dimname in enumerate(ref_left_dimnames[::-1], 1):
if i <= result.ndim:
outdims[-alg_ndims - i] = dimname
else:
@ -2078,7 +2054,7 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"): @@ -2078,7 +2054,7 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
result = wrapped(*args, **kwargs)
argvals = from_args(wrapped, (copyarg,"missing"), *args, **kwargs)
argvals = from_args(wrapped, (copyarg, "missing"), *args, **kwargs)
p = argvals[copyarg]
missing = argvals["missing"]
@ -2094,7 +2070,6 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"): @@ -2094,7 +2070,6 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
outattrs = OrderedDict()
if is2d:
if is1d:
outname = "cape_2d"
@ -2114,7 +2089,6 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"): @@ -2114,7 +2089,6 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
outattrs["description"] = "cape; cin"
outattrs["units"] = "J kg-1 ; J kg-1"
if isinstance(p, DataArray):
if is2d:
if not is1d:
@ -2131,7 +2105,6 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"): @@ -2131,7 +2105,6 @@ def set_cape_alg_metadata(is2d, copyarg="pres_hpa"):
else:
outdims[1] = p.dims[0]
outcoords = {}
# Left-most is always cape_cin or cape_cin_lcl_lfc
if is2d:
@ -2214,7 +2187,6 @@ def set_cloudfrac_alg_metadata(copyarg="vert"): @@ -2214,7 +2187,6 @@ def set_cloudfrac_alg_metadata(copyarg="vert"):
# Left dims
outdims[1:-2] = cp.dims[0:-3]
outcoords = {}
# Left-most is always low_mid_high
outdims[0] = "low_mid_high"
@ -2294,8 +2266,3 @@ def set_destag_metadata(): @@ -2294,8 +2266,3 @@ def set_destag_metadata():
return out
return func_wrapper

198
src/wrf/projection.py

@ -61,7 +61,8 @@ if cartopy_enabled(): @@ -61,7 +61,8 @@ if cartopy_enabled():
super(crs.Mercator, self).__init__(proj4_params, globe=globe)
# Calculate limits.
limits = self.transform_points(crs.Geodetic(),
limits = self.transform_points(
crs.Geodetic(),
np.array([-180, 180]) + central_longitude,
np.array([min_latitude, max_latitude]))
@ -195,7 +196,6 @@ class WrfProj(object): @@ -195,7 +196,6 @@ class WrfProj(object):
if self.stand_lon is None:
self.stand_lon = self._cen_lon
@staticmethod
def _context_equal(x, y, ctx):
"""Return True if both objects are equal based on the provided context.
@ -230,7 +230,6 @@ class WrfProj(object): @@ -230,7 +230,6 @@ class WrfProj(object):
return True
def __eq__(self, other):
"""Return True if this projection object is the same as *other*.
@ -262,7 +261,6 @@ class WrfProj(object): @@ -262,7 +261,6 @@ class WrfProj(object):
WrfProj._context_equal(self.dx, other.dx, ctx) and
WrfProj._context_equal(self.dy, other.dy, ctx))
def _basemap(self, geobounds, **kwargs):
return None
@ -275,17 +273,15 @@ class WrfProj(object): @@ -275,17 +273,15 @@ class WrfProj(object):
def _calc_extents(self, geobounds):
# Need to modify the extents for the new projection
pc = crs.PlateCarree()
xs, ys, _ = self._cartopy().transform_points(pc,
np.array([geobounds.bottom_left.lon,
geobounds.top_right.lon]),
np.array([geobounds.bottom_left.lat,
geobounds.top_right.lat])).T
xs, ys, _ = self._cartopy().transform_points(
pc,
np.array([geobounds.bottom_left.lon, geobounds.top_right.lon]),
np.array([geobounds.bottom_left.lat, geobounds.top_right.lat])).T
_xlimits = xs.tolist()
_ylimits = ys.tolist()
return (_xlimits, _ylimits)
def _cart_extents(self, geobounds):
try:
_ = len(geobounds)
@ -327,7 +323,7 @@ class WrfProj(object): @@ -327,7 +323,7 @@ class WrfProj(object):
try:
_ = len(geobounds)
except TypeError:
x_extents= self._cart_extents(geobounds)[0]
x_extents = self._cart_extents(geobounds)[0]
else:
extents = self._cart_extents(geobounds)
x_extents = np.empty(extents.shape, np.object)
@ -352,7 +348,7 @@ class WrfProj(object): @@ -352,7 +348,7 @@ class WrfProj(object):
try:
_ = len(geobounds)
except TypeError:
y_extents= self._cart_extents(geobounds)[1]
y_extents = self._cart_extents(geobounds)[1]
else:
extents = self._cart_extents(geobounds)
y_extents = np.empty(extents.shape, np.object)
@ -529,10 +525,9 @@ class LambertConformal(WrfProj): @@ -529,10 +525,9 @@ class LambertConformal(WrfProj):
if self.truelat2 is not None:
self._std_parallels.append(self.truelat2)
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "lambert_conformal_conic";
_cf_params["grid_mapping_name"] = "lambert_conformal_conic"
_cf_params["standard_parallel"] = self._std_parallels
_cf_params["longitude_of_central_meridian"] = self.stand_lon
_cf_params["latitude_of_projection_origin"] = self.moad_cen_lat
@ -540,13 +535,11 @@ class LambertConformal(WrfProj): @@ -540,13 +535,11 @@ class LambertConformal(WrfProj):
return _cf_params
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
truelat2 = (self.truelat1
if _ismissing(self.truelat2)
truelat2 = (self.truelat1 if _ismissing(self.truelat2)
else self.truelat2)
_pyngl = Resources()
@ -567,22 +560,21 @@ class LambertConformal(WrfProj): @@ -567,22 +560,21 @@ class LambertConformal(WrfProj):
return _pyngl
def _basemap(self, geobounds, **kwargs):
if not basemap_enabled():
return None
local_kwargs = dict(projection = "lcc",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
lat_1 = self.truelat1,
lat_2 = self.truelat2,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = 'l')
local_kwargs = dict(projection="lcc",
lon_0=self.stand_lon,
lat_0=self.moad_cen_lat,
lat_1=self.truelat1,
lat_2=self.truelat2,
llcrnrlat=geobounds.bottom_left.lat,
urcrnrlat=geobounds.top_right.lat,
llcrnrlon=geobounds.bottom_left.lon,
urcrnrlon=geobounds.top_right.lon,
rsphere=Constants.WRF_EARTH_RADIUS,
resolution='l')
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
@ -597,11 +589,11 @@ class LambertConformal(WrfProj): @@ -597,11 +589,11 @@ class LambertConformal(WrfProj):
cutoff = -30.0 if self.moad_cen_lat >= 0 else 30.0
_cartopy = crs.LambertConformal(
central_longitude = self.stand_lon,
central_latitude = self.moad_cen_lat,
standard_parallels = self._std_parallels,
globe = self._globe(),
cutoff = cutoff)
central_longitude=self.stand_lon,
central_latitude=self.moad_cen_lat,
standard_parallels=self._std_parallels,
globe=self._globe(),
cutoff=cutoff)
return _cartopy
@ -650,16 +642,14 @@ class Mercator(WrfProj): @@ -650,16 +642,14 @@ class Mercator(WrfProj):
"""
super(Mercator, self).__init__(**proj_params)
self._lat_ts = (None
if self.truelat1 == 0. or _ismissing(self.truelat1)
self._lat_ts = (
None if self.truelat1 == 0. or _ismissing(self.truelat1)
else self.truelat1)
self._stand_lon = (0. if _ismissing(self.stand_lon, islat=False)
else self.stand_lon)
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "mercator"
_cf_params["longitude_of_projection_origin"] = self.stand_lon
@ -667,7 +657,6 @@ class Mercator(WrfProj): @@ -667,7 +657,6 @@ class Mercator(WrfProj):
return _cf_params
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
@ -689,46 +678,40 @@ class Mercator(WrfProj): @@ -689,46 +678,40 @@ class Mercator(WrfProj):
return _pyngl
def _basemap(self, geobounds, **kwargs):
if not basemap_enabled():
return None
local_kwargs = dict(projection = "merc",
lon_0 = self._stand_lon,
lat_0 = self.moad_cen_lat,
lat_ts = self._lat_ts,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs = dict(projection="merc",
lon_0=self._stand_lon,
lat_0=self.moad_cen_lat,
lat_ts=self._lat_ts,
llcrnrlat=geobounds.bottom_left.lat,
urcrnrlat=geobounds.top_right.lat,
llcrnrlon=geobounds.bottom_left.lon,
urcrnrlon=geobounds.top_right.lon,
rsphere=Constants.WRF_EARTH_RADIUS,
resolution="l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
def _cartopy(self):
if not cartopy_enabled():
return None
if self._lat_ts == 0.0:
_cartopy = crs.Mercator(
central_longitude = self._stand_lon,
globe = self._globe())
_cartopy = crs.Mercator(central_longitude=self._stand_lon,
globe=self._globe())
else:
_cartopy = MercatorWithLatTS(
central_longitude = self._stand_lon,
latitude_true_scale = self._lat_ts,
globe = self._globe())
_cartopy = MercatorWithLatTS(central_longitude=self._stand_lon,
latitude_true_scale=self._lat_ts,
globe=self._globe())
return _cartopy
def _proj4(self):
_proj4 = ("+proj=merc +units=meters +a={} +b={} "
@ -740,6 +723,7 @@ class Mercator(WrfProj): @@ -740,6 +723,7 @@ class Mercator(WrfProj):
return _proj4
class PolarStereographic(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Polar Stereographic projections.
@ -750,7 +734,6 @@ class PolarStereographic(WrfProj): @@ -750,7 +734,6 @@ class PolarStereographic(WrfProj):
:class:`Mercator`, :class:`LambertConformal`
"""
def __init__(self, **proj_params):
"""Initialize a :class:`wrf.PolarStereographic` object.
@ -770,10 +753,7 @@ class PolarStereographic(WrfProj): @@ -770,10 +753,7 @@ class PolarStereographic(WrfProj):
"""
super(PolarStereographic, self).__init__(**proj_params)
self._hemi = -90. if self.truelat1 < 0 else 90.
self._lat_ts = (None
if _ismissing(self.truelat1)
else self.truelat1)
self._lat_ts = (None if _ismissing(self.truelat1) else self.truelat1)
def _cf_params(self):
_cf_params = {}
@ -785,7 +765,6 @@ class PolarStereographic(WrfProj): @@ -785,7 +765,6 @@ class PolarStereographic(WrfProj):
return _cf_params
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
@ -811,28 +790,26 @@ class PolarStereographic(WrfProj): @@ -811,28 +790,26 @@ class PolarStereographic(WrfProj):
return _pyngl
def _basemap(self, geobounds, **kwargs):
if not basemap_enabled():
return None
local_kwargs = dict(projection = "stere",
lon_0 = self.stand_lon,
lat_0 = self._hemi,
lat_ts = self._lat_ts,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs = dict(projection="stere",
lon_0=self.stand_lon,
lat_0=self._hemi,
lat_ts=self._lat_ts,
llcrnrlat=geobounds.bottom_left.lat,
urcrnrlat=geobounds.top_right.lat,
llcrnrlon=geobounds.bottom_left.lon,
urcrnrlon=geobounds.top_right.lon,
rsphere=Constants.WRF_EARTH_RADIUS,
resolution="l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
def _cartopy(self):
if not cartopy_enabled():
return None
@ -843,7 +820,6 @@ class PolarStereographic(WrfProj): @@ -843,7 +820,6 @@ class PolarStereographic(WrfProj):
globe=self._globe())
return _cartopy
def _proj4(self):
_proj4 = ("+proj=stere +units=meters +a={} +b={} "
"+lat0={} +lon_0={} +lat_ts={} +nadgrids=@null".format(
@ -856,7 +832,6 @@ class PolarStereographic(WrfProj): @@ -856,7 +832,6 @@ class PolarStereographic(WrfProj):
return _proj4
class LatLon(WrfProj):
"""A :class:`wrf.WrfProj` subclass for Lat Lon projections.
@ -886,13 +861,11 @@ class LatLon(WrfProj): @@ -886,13 +861,11 @@ class LatLon(WrfProj):
"""
super(LatLon, self).__init__(**proj_params)
def _cf_params(self):
_cf_params = {}
_cf_params["grid_mapping_name"] = "latitude_longitude"
return _cf_params
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
@ -914,27 +887,25 @@ class LatLon(WrfProj): @@ -914,27 +887,25 @@ class LatLon(WrfProj):
return _pyngl
def _basemap(self, geobounds, **kwargs):
if not basemap_enabled():
return None
local_kwargs = dict(projection = "cyl",
lon_0 = self.stand_lon,
lat_0 = self.moad_cen_lat,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs = dict(projection="cyl",
lon_0=self.stand_lon,
lat_0=self.moad_cen_lat,
llcrnrlat=geobounds.bottom_left.lat,
urcrnrlat=geobounds.top_right.lat,
llcrnrlon=geobounds.bottom_left.lon,
urcrnrlon=geobounds.top_right.lon,
rsphere=Constants.WRF_EARTH_RADIUS,
resolution="l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
def _cartopy(self):
if not cartopy_enabled():
return None
@ -944,19 +915,19 @@ class LatLon(WrfProj): @@ -944,19 +915,19 @@ class LatLon(WrfProj):
return _cartopy
def _cart_extents(self, geobounds):
return ([geobounds.bottom_left.lon, geobounds.top_right.lon],
[geobounds.bottom_left.lat, geobounds.top_right.lat])
def _proj4(self):
_proj4 = ("+proj=eqc +units=meters +a={} +b={} "
"+lon_0={} +nadgrids=@null".format(Constants.WRF_EARTH_RADIUS,
"+lon_0={} +nadgrids=@null".format(
Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS,
self.stand_lon))
return _proj4
# Notes (may not be correct since this projection confuses me):
# Each projection system handles this differently.
# 1) In WRF, if following the WPS instructions, POLE_LON is mainly used to
@ -1042,7 +1013,7 @@ class RotatedLatLon(WrfProj): @@ -1042,7 +1013,7 @@ class RotatedLatLon(WrfProj):
self._bm_lon_0 = (-self.stand_lon if self._north
else 180.0 - self.stand_lon)
self._bm_cart_pole_lat = (self.pole_lat if self._north
else -self.pole_lat )
else -self.pole_lat)
# The important point is that pole longitude is the position
# of the dateline of the new projection, not its central
# longitude (per the creator of cartopy). This is based on
@ -1059,7 +1030,6 @@ class RotatedLatLon(WrfProj): @@ -1059,7 +1030,6 @@ class RotatedLatLon(WrfProj):
self._cart_pole_lon = (-self.stand_lon - 180.0 if self._north
else -self.stand_lon)
def _cf_params(self):
_cf_params = {}
# Assuming this follows the same guidelines as cartopy
@ -1070,7 +1040,6 @@ class RotatedLatLon(WrfProj): @@ -1070,7 +1040,6 @@ class RotatedLatLon(WrfProj):
return _cf_params
def _pyngl(self, geobounds, **kwargs):
if not pyngl_enabled():
return None
@ -1092,38 +1061,35 @@ class RotatedLatLon(WrfProj): @@ -1092,38 +1061,35 @@ class RotatedLatLon(WrfProj):
return _pyngl
def _basemap(self, geobounds, **kwargs):
if not basemap_enabled():
return None
local_kwargs = dict(projection = "rotpole",
o_lat_p = self._bm_cart_pole_lat,
o_lon_p = self.pole_lon,
llcrnrlat = geobounds.bottom_left.lat,
urcrnrlat = geobounds.top_right.lat,
llcrnrlon = geobounds.bottom_left.lon,
urcrnrlon = geobounds.top_right.lon,
lon_0 = self._bm_lon_0,
rsphere = Constants.WRF_EARTH_RADIUS,
resolution = "l")
local_kwargs = dict(projection="rotpole",
o_lat_p=self._bm_cart_pole_lat,
o_lon_p=self.pole_lon,
llcrnrlat=geobounds.bottom_left.lat,
urcrnrlat=geobounds.top_right.lat,
llcrnrlon=geobounds.bottom_left.lon,
urcrnrlon=geobounds.top_right.lon,
lon_0=self._bm_lon_0,
rsphere=Constants.WRF_EARTH_RADIUS,
resolution="l")
local_kwargs.update(kwargs)
_basemap = Basemap(**local_kwargs)
return _basemap
def _cartopy(self):
if not cartopy_enabled():
return None
_cartopy = crs.RotatedPole(
pole_longitude=self._cart_pole_lon,
_cartopy = crs.RotatedPole(pole_longitude=self._cart_pole_lon,
pole_latitude=self._bm_cart_pole_lat,
central_rotated_longitude=(
180.0 - self.pole_lon), # Probably
globe = self._globe())
globe=self._globe())
return _cartopy
def _proj4(self):
@ -1138,6 +1104,7 @@ class RotatedLatLon(WrfProj): @@ -1138,6 +1104,7 @@ class RotatedLatLon(WrfProj):
return _proj4
def getproj(**proj_params):
"""Return a :class:`wrf.WrfProj` subclass.
@ -1164,7 +1131,6 @@ def getproj(**proj_params): @@ -1164,7 +1131,6 @@ def getproj(**proj_params):
specified map projection parameters.
"""
up_proj_params = dict_keys_to_upper(proj_params)
proj_type = up_proj_params.get("MAP_PROJ", 0)
@ -1184,5 +1150,3 @@ def getproj(**proj_params): @@ -1184,5 +1150,3 @@ def getproj(**proj_params):
else:
# Unknown projection
return WrfProj(**proj_params)

3
src/wrf/projutils.py

@ -2,6 +2,7 @@ from __future__ import (absolute_import, division, print_function) @@ -2,6 +2,7 @@ from __future__ import (absolute_import, division, print_function)
from .py3compat import viewitems
def dict_keys_to_upper(d):
"""Return a dictionary with the keys changed to uppercase.
@ -14,4 +15,4 @@ def dict_keys_to_upper(d): @@ -14,4 +15,4 @@ def dict_keys_to_upper(d):
:obj:`dict`: A dictionary with uppercase keys.
"""
return {key.upper() : val for key, val in viewitems(d)}
return {key.upper(): val for key, val in viewitems(d)}

4
src/wrf/py3compat.py

@ -3,6 +3,7 @@ from __future__ import (absolute_import, division, print_function) @@ -3,6 +3,7 @@ from __future__ import (absolute_import, division, print_function)
from sys import version_info
from math import floor, copysign
# Dictionary python 2-3 compatibility stuff
def viewitems(d):
"""Return either the items or viewitems method for a dictionary.
@ -57,6 +58,7 @@ def viewvalues(d): @@ -57,6 +58,7 @@ def viewvalues(d):
func = d.values
return func()
def isstr(s):
"""Return True if the object is a string type.
@ -165,5 +167,3 @@ def ucode(*args, **kwargs): @@ -165,5 +167,3 @@ def ucode(*args, **kwargs):
return str(*args, **kwargs)
return unicode(*args, **kwargs)

308
src/wrf/routines.py

@ -8,7 +8,8 @@ from .g_cape import (get_2dcape, get_3dcape, get_cape2d_only, @@ -8,7 +8,8 @@ from .g_cape import (get_2dcape, get_3dcape, get_cape2d_only,
from .g_ctt import get_ctt
from .g_dbz import get_dbz, get_max_dbz
from .g_dewpoint import get_dp, get_dp_2m
from .g_geoht import get_geopt, get_height, get_stag_geopt, get_stag_height
from .g_geoht import (get_geopt, get_height, get_stag_geopt, get_stag_height,
get_height_agl)
from .g_helicity import get_srh, get_uh
from .g_latlon import get_lat, get_lon
from .g_omega import get_omega
@ -16,7 +17,8 @@ from .g_pressure import get_pressure, get_pressure_hpa @@ -16,7 +17,8 @@ from .g_pressure import get_pressure, get_pressure_hpa
from .g_pw import get_pw
from .g_rh import get_rh, get_rh_2m
from .g_slp import get_slp
from .g_temp import get_tc, get_eth, get_temp, get_theta, get_tk, get_tv, get_tw
from .g_temp import (get_tc, get_eth, get_temp, get_theta, get_tk, get_tv,
get_tw)
from .g_terrain import get_terrain
from .g_uvmet import (get_uvmet, get_uvmet10, get_uvmet10_wspd_wdir,
get_uvmet_wspd_wdir, get_uvmet_wspd, get_uvmet_wdir,
@ -33,167 +35,170 @@ from .g_cloudfrac import (get_cloudfrac, get_low_cloudfrac, get_mid_cloudfrac, @@ -33,167 +35,170 @@ from .g_cloudfrac import (get_cloudfrac, get_low_cloudfrac, get_mid_cloudfrac,
# func is the function to call. kargs are required arguments that should
# not be altered by the user
_FUNC_MAP = {"cape2d" : get_2dcape,
"cape3d" : get_3dcape,
"dbz" : get_dbz,
"maxdbz" : get_max_dbz,
"dp" : get_dp,
"dp2m" : get_dp_2m,
"height" : get_height,
"geopt" : get_geopt,
"srh" : get_srh,
"uhel" : get_uh,
"omega" : get_omega,
"pw" : get_pw,
"rh" : get_rh,
"rh2m" : get_rh_2m,
"slp" : get_slp,
"theta" : get_theta,
"temp" : get_temp,
"tk" : get_tk,
"tc" : get_tc,
"theta_e" : get_eth,
"tv" : get_tv,
"twb" : get_tw,
"terrain" : get_terrain,
"times" : get_times,
"xtimes" : get_xtimes,
"uvmet" : get_uvmet,
"uvmet10" : get_uvmet10,
"avo" : get_avo,
"pvo" : get_pvo,
"ua" : get_u_destag,
"va" : get_v_destag,
"wa" : get_w_destag,
"lat" : get_lat,
"lon" : get_lon,
"pressure" : get_pressure_hpa,
"pres" : get_pressure,
"wspd_wdir" : get_destag_wspd_wdir,
"wspd_wdir10" : get_destag_wspd_wdir10,
"uvmet_wspd_wdir" : get_uvmet_wspd_wdir,
"uvmet10_wspd_wdir" : get_uvmet10_wspd_wdir,
"ctt" : get_ctt,
"cloudfrac" : get_cloudfrac,
"geopt_stag" : get_stag_geopt,
"zstag" : get_stag_height,
_FUNC_MAP = {"cape2d": get_2dcape,
"cape3d": get_3dcape,
"dbz": get_dbz,
"maxdbz": get_max_dbz,
"dp": get_dp,
"dp2m": get_dp_2m,
"height": get_height,
"geopt": get_geopt,
"srh": get_srh,
"uhel": get_uh,
"omega": get_omega,
"pw": get_pw,
"rh": get_rh,
"rh2m": get_rh_2m,
"slp": get_slp,
"theta": get_theta,
"temp": get_temp,
"tk": get_tk,
"tc": get_tc,
"theta_e": get_eth,
"tv": get_tv,
"twb": get_tw,
"terrain": get_terrain,
"times": get_times,
"xtimes": get_xtimes,
"uvmet": get_uvmet,
"uvmet10": get_uvmet10,
"avo": get_avo,
"pvo": get_pvo,
"ua": get_u_destag,
"va": get_v_destag,
"wa": get_w_destag,
"lat": get_lat,
"lon": get_lon,
"pressure": get_pressure_hpa,
"pres": get_pressure,
"wspd_wdir": get_destag_wspd_wdir,
"wspd_wdir10": get_destag_wspd_wdir10,
"uvmet_wspd_wdir": get_uvmet_wspd_wdir,
"uvmet10_wspd_wdir": get_uvmet10_wspd_wdir,
"ctt": get_ctt,
"cloudfrac": get_cloudfrac,
"geopt_stag": get_stag_geopt,
"zstag": get_stag_height,
"height_agl": get_height_agl,
# Diagnostics below are extracted from multi-product diagnostics
"cape2d_only" : get_cape2d_only,
"cin2d_only" : get_cin2d_only,
"lcl" : get_lcl,
"lfc" : get_lfc,
"cape3d_only" : get_3dcape_only,
"cape2d_only": get_cape2d_only,
"cin2d_only": get_cin2d_only,
"lcl": get_lcl,
"lfc": get_lfc,
"cape3d_only": get_3dcape_only,
"cin3d_only": get_3dcin_only,
"uvmet_wspd" : get_uvmet_wspd,
"uvmet_wdir" : get_uvmet_wdir,
"uvmet10_wspd" : get_uvmet10_wspd,
"uvmet10_wdir" : get_uvmet10_wdir,
"wspd" : get_destag_wspd,
"wdir" : get_destag_wdir,
"wspd10" : get_destag_wspd10,
"wdir10" : get_destag_wdir10,
"low_cloudfrac" : get_low_cloudfrac,
"mid_cloudfrac" : get_mid_cloudfrac,
"high_cloudfrac" : get_high_cloudfrac
"uvmet_wspd": get_uvmet_wspd,
"uvmet_wdir": get_uvmet_wdir,
"uvmet10_wspd": get_uvmet10_wspd,
"uvmet10_wdir": get_uvmet10_wdir,
"wspd": get_destag_wspd,
"wdir": get_destag_wdir,
"wspd10": get_destag_wspd10,
"wdir10": get_destag_wdir10,
"low_cloudfrac": get_low_cloudfrac,
"mid_cloudfrac": get_mid_cloudfrac,
"high_cloudfrac": get_high_cloudfrac
}
_VALID_KARGS = {"cape2d" : ["missing"],
"cape3d" : ["missing"],
"dbz" : ["do_variant", "do_liqskin"],
"maxdbz" : ["do_variant", "do_liqskin"],
"dp" : ["units"],
"dp2m" : ["units"],
"height" : ["msl", "units"],
"geopt" : [],
"srh" : ["top"],
"uhel" : ["bottom", "top"],
"omega" : [],
"pw" : [],
"rh" : [],
"rh2m" : [],
"slp" : ["units"],
"temp" : ["units"],
"tk" : [],
"tc" : [],
"theta" : ["units"],
"theta_e" : ["units"],
"tv" : ["units"],
"twb" : ["units"],
"terrain" : ["units"],
"times" : [],
"xtimes" : [],
"uvmet" : ["units"],
"uvmet10" : ["units"],
"avo" : [],
"pvo" : [],
"ua" : ["units"],
"va" : ["units"],
"wa" : ["units"],
"lat" : [],
"lon" : [],
"pres" : ["units"],
"pressure" : ["units"],
"wspd_wdir" : ["units"],
"wspd_wdir10" : ["units"],
"uvmet_wspd_wdir" : ["units"],
"uvmet10_wspd_wdir" : ["units"],
"ctt" : ["fill_nocloud", "missing", "opt_thresh", "units"],
"cloudfrac" : ["vert_type", "low_thresh",
_VALID_KARGS = {"cape2d": ["missing"],
"cape3d": ["missing"],
"dbz": ["do_variant", "do_liqskin"],
"maxdbz": ["do_variant", "do_liqskin"],
"dp": ["units"],
"dp2m": ["units"],
"height": ["msl", "units"],
"geopt": [],
"srh": ["top"],
"uhel": ["bottom", "top"],
"omega": [],
"pw": [],
"rh": [],
"rh2m": [],
"slp": ["units"],
"temp": ["units"],
"tk": [],
"tc": [],
"theta": ["units"],
"theta_e": ["units"],
"tv": ["units"],
"twb": ["units"],
"terrain": ["units"],
"times": [],
"xtimes": [],
"uvmet": ["units"],
"uvmet10": ["units"],
"avo": [],
"pvo": [],
"ua": ["units"],
"va": ["units"],
"wa": ["units"],
"lat": [],
"lon": [],
"pres": ["units"],
"pressure": ["units"],
"wspd_wdir": ["units"],
"wspd_wdir10": ["units"],
"uvmet_wspd_wdir": ["units"],
"uvmet10_wspd_wdir": ["units"],
"ctt": ["fill_nocloud", "missing", "opt_thresh", "units"],
"cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"geopt_stag" : [],
"zstag" : ["msl", "units"],
"cape2d_only" : ["missing"],
"cin2d_only" : ["missing"],
"lcl" : ["missing"],
"lfc" : ["missing"],
"cape3d_only" : ["missing"],
"geopt_stag": [],
"zstag": ["msl", "units"],
"height_agl": ["units"],
"cape2d_only": ["missing"],
"cin2d_only": ["missing"],
"lcl": ["missing"],
"lfc": ["missing"],
"cape3d_only": ["missing"],
"cin3d_only": ["missing"],
"uvmet_wspd" : ["units"],
"uvmet_wdir" : ["units"],
"uvmet10_wspd" : ["units"],
"uvmet10_wdir" : ["units"],
"wspd" : ["units"],
"wdir" : ["units"],
"wspd10" : ["units"],
"wdir10" : ["units"],
"low_cloudfrac" : ["vert_type", "low_thresh",
"uvmet_wspd": ["units"],
"uvmet_wdir": ["units"],
"uvmet10_wspd": ["units"],
"uvmet10_wdir": ["units"],
"wspd": ["units"],
"wdir": ["units"],
"wspd10": ["units"],
"wdir10": ["units"],
"low_cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"mid_cloudfrac" : ["vert_type", "low_thresh",
"mid_cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"high_cloudfrac" : ["vert_type", "low_thresh",
"high_cloudfrac": ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"default" : []
"default": []
}
_ALIASES = {"cape_2d" : "cape2d",
"cape_3d" : "cape3d",
"eth" : "theta_e",
"mdbz" : "maxdbz",
"geopotential" : "geopt",
"helicity" : "srh",
"latitude" : "lat",
"longitude" : "lon",
"omg" : "omega",
"p" : "pres",
"rh2" : "rh2m",
_ALIASES = {"cape_2d": "cape2d",
"cape_3d": "cape3d",
"eth": "theta_e",
"mdbz": "maxdbz",
"geopotential": "geopt",
"helicity": "srh",
"latitude": "lat",
"longitude": "lon",
"omg": "omega",
"p": "pres",
"rh2": "rh2m",
"z": "height",
"ter" : "terrain",
"updraft_helicity" : "uhel",
"td" : "dp",
"td2" : "dp2m",
"cfrac" : "cloudfrac",
"wspd_wdir_uvmet" : "uvmet_wspd_wdir",
"wspd_wdir_uvmet10" : "uvmet10_wspd_wdir",
"th" : "theta",
"low_cfrac" : "low_cloudfrac",
"mid_cfrac" : "mid_cloudfrac",
"high_cfrac" : "high_cloudfrac",
"wspd_uvmet" : "uvmet_wspd" ,
"wdir_uvmet" : "uvmet_wdir" ,
"wspd_uvmet10" : "uvmet10_wspd" ,
"wdir_uvmet10" : "uvmet10_wdir" ,
"ter": "terrain",
"updraft_helicity": "uhel",
"td": "dp",
"td2": "dp2m",
"cfrac": "cloudfrac",
"wspd_wdir_uvmet": "uvmet_wspd_wdir",
"wspd_wdir_uvmet10": "uvmet10_wspd_wdir",
"th": "theta",
"low_cfrac": "low_cloudfrac",
"mid_cfrac": "mid_cloudfrac",
"high_cfrac": "high_cloudfrac",
"wspd_uvmet": "uvmet_wspd",
"wdir_uvmet": "uvmet_wdir",
"wspd_uvmet10": "uvmet10_wspd",
"wdir_uvmet10": "uvmet10_wdir",
}
class ArgumentError(Exception):
def __init__(self, msg):
self.msg = msg
@ -201,6 +206,7 @@ class ArgumentError(Exception): @@ -201,6 +206,7 @@ class ArgumentError(Exception):
def __str__(self):
return self.msg
def _undo_alias(alias):
actual = _ALIASES.get(alias, None)
if actual is None:
@ -208,6 +214,7 @@ def _undo_alias(alias): @@ -208,6 +214,7 @@ def _undo_alias(alias):
else:
return actual
def _check_kargs(var, kargs):
for arg in viewkeys(kargs):
if arg not in _VALID_KARGS[var]:
@ -340,10 +347,9 @@ def getvar(wrfin, varname, timeidx=0, @@ -340,10 +347,9 @@ def getvar(wrfin, varname, timeidx=0,
actual_var = _undo_alias(varname)
if actual_var not in _VALID_KARGS:
raise ValueError("'%s' is not a valid variable name" % (varname))
raise ValueError("'{}' is not a valid variable name".format(varname))
_check_kargs(actual_var, kwargs)
return _FUNC_MAP[actual_var](wrfin, timeidx, method, squeeze, cache,
meta, _key, **kwargs)

49
src/wrf/specialdec.py

@ -99,8 +99,6 @@ def uvmet_left_iter(alg_dtype=np.float64): @@ -99,8 +99,6 @@ def uvmet_left_iter(alg_dtype=np.float64):
if (u.shape[-1] == lat.shape[-1] or u.shape[-2] == lat.shape[-2]):
raise ValueError("v is staggered but u is not")
# No special left side iteration, return the function result
if (num_left_dims_u == 0):
return wrapped(u, v, lat, lon, cen_long, cone, isstag=is_stag,
@ -132,15 +130,14 @@ def uvmet_left_iter(alg_dtype=np.float64): @@ -132,15 +130,14 @@ def uvmet_left_iter(alg_dtype=np.float64):
lat_left_and_slice = left_and_slice_idxs
elif mode == 2:
# Only need the left-most
lat_left_and_slice = tuple(left_idx
for left_idx in left_idxs[0:num_left_dims_lat])
lat_left_and_slice = tuple(
left_idx for left_idx in left_idxs[0:num_left_dims_lat])
u_output_idxs = (0,) + left_idxs + (slice(None),)
v_output_idxs = (1,) + left_idxs + (slice(None),)
u_view_idxs = left_idxs + (0, slice(None))
v_view_idxs = left_idxs + (1, slice(None))
new_u = u[left_and_slice_idxs]
new_v = v[left_and_slice_idxs]
new_lat = lat[lat_left_and_slice]
@ -186,7 +183,6 @@ def uvmet_left_iter(alg_dtype=np.float64): @@ -186,7 +183,6 @@ def uvmet_left_iter(alg_dtype=np.float64):
return func_wrapper
def cape_left_iter(alg_dtype=np.float64):
"""A decorator to handle iterating over the leftmost dimensions for the
cape diagnostic.
@ -250,10 +246,10 @@ def cape_left_iter(alg_dtype=np.float64): @@ -250,10 +246,10 @@ def cape_left_iter(alg_dtype=np.float64):
if p_hpa[bot_idxs] > p_hpa[top_idxs]:
flip = True
p_hpa = np.ascontiguousarray(p_hpa[...,::-1,:,:])
tk = np.ascontiguousarray(tk[...,::-1,:,:])
qv = np.ascontiguousarray(qv[...,::-1,:,:])
ht = np.ascontiguousarray(ht[...,::-1,:,:])
p_hpa = np.ascontiguousarray(p_hpa[..., ::-1, :, :])
tk = np.ascontiguousarray(tk[..., ::-1, :, :])
qv = np.ascontiguousarray(qv[..., ::-1, :, :])
ht = np.ascontiguousarray(ht[..., ::-1, :, :])
new_args[0] = p_hpa
new_args[1] = tk
new_args[2] = qv
@ -279,8 +275,8 @@ def cape_left_iter(alg_dtype=np.float64): @@ -279,8 +275,8 @@ def cape_left_iter(alg_dtype=np.float64):
new_args[1] = tk.reshape((1, 1, tk.shape[0]), order='F')
new_args[2] = qv.reshape((1, 1, qv.shape[0]), order='F')
new_args[3] = ht.reshape((1, 1, ht.shape[0]), order='F')
new_args[4] = np.full((1,1), ter, orig_dtype)
new_args[5] = np.full((1,1), sfp, orig_dtype)
new_args[4] = np.full((1, 1), ter, orig_dtype)
new_args[5] = np.full((1, 1), sfp, orig_dtype)
num_left_dims = 0
@ -298,11 +294,11 @@ def cape_left_iter(alg_dtype=np.float64): @@ -298,11 +294,11 @@ def cape_left_iter(alg_dtype=np.float64):
output = np.empty(output_dims, orig_dtype)
if flip and not is2d:
output[0,:] = cape[::-1,:,:]
output[1,:] = cin[::-1,:,:]
output[0, :] = cape[::-1, :, :]
output[1, :] = cin[::-1, :, :]
else:
output[0,:] = cape[:]
output[1,:] = cin[:]
output[0, :] = cape[:]
output[1, :] = cin[:]
return output
@ -329,9 +325,9 @@ def cape_left_iter(alg_dtype=np.float64): @@ -329,9 +325,9 @@ def cape_left_iter(alg_dtype=np.float64):
cape_output_idxs = (0,) + left_idxs + (slice(None),)
cin_output_idxs = (1,) + left_idxs + (slice(None),)
view_cape_reverse_idxs = left_idxs + (0, slice(None,None,-1),
view_cape_reverse_idxs = left_idxs + (0, slice(None, None, -1),
slice(None))
view_cin_reverse_idxs = left_idxs + (1, slice(None,None,-1),
view_cin_reverse_idxs = left_idxs + (1, slice(None, None, -1),
slice(None))
new_args[0] = p_hpa[left_and_slice_idxs]
@ -374,7 +370,6 @@ def cape_left_iter(alg_dtype=np.float64): @@ -374,7 +370,6 @@ def cape_left_iter(alg_dtype=np.float64):
capeview.__array_interface__["data"][0]):
raise RuntimeError("output array was copied")
if flip and not is2d:
output[cape_output_idxs] = (
outview_array[view_cape_reverse_idxs].astype(orig_dtype))
@ -435,14 +430,14 @@ def cloudfrac_left_iter(alg_dtype=np.float64): @@ -435,14 +430,14 @@ def cloudfrac_left_iter(alg_dtype=np.float64):
output_dims += vert.shape[-2:]
output = np.empty(output_dims, orig_dtype)
output[0,:] = low[:]
output[1,:] = mid[:]
output[2,:] = high[:]
output[0, :] = low[:]
output[1, :] = mid[:]
output[2, :] = high[:]
return output
# Initial output is ...,low_mid_high,nz,ny,nx to create contiguous views
# Initial output is ...,low_mid_high,nz,ny,nx to create contiguous
# views
outdims = vert.shape[0:num_left_dims]
extra_dims = tuple(outdims) # Copy the left-most dims for iteration
@ -548,8 +543,8 @@ def interplevel_left_iter(is2dlev, alg_dtype=np.float64): @@ -548,8 +543,8 @@ def interplevel_left_iter(is2dlev, alg_dtype=np.float64):
output = np.empty(outshape, dtype=alg_dtype)
for i in py3range(field3d.shape[0]):
new_args[0] = field3d[i,:]
new_kwargs["outview"] = output[i,:]
new_args[0] = field3d[i, :]
new_kwargs["outview"] = output[i, :]
_ = wrapped(*new_args, **new_kwargs)
else:
output = wrapped(*args, **kwargs)
@ -579,7 +574,6 @@ def interplevel_left_iter(is2dlev, alg_dtype=np.float64): @@ -579,7 +574,6 @@ def interplevel_left_iter(is2dlev, alg_dtype=np.float64):
else:
z_slice_idxs = left_idxs + (slice(None),)
new_args[0] = field3d[field_out_slice_idxs]
new_args[1] = z[z_slice_idxs]
@ -695,4 +689,3 @@ def check_interplevel_args(is2dlev): @@ -695,4 +689,3 @@ def check_interplevel_args(is2dlev):
return wrapped(*args, **kwargs)
return func_wrapper

276
src/wrf/units.py

@ -129,175 +129,170 @@ def _apply_temp_conv(var, var_unit, dest_unit): @@ -129,175 +129,170 @@ def _apply_temp_conv(var, var_unit, dest_unit):
# A mapping of unit names to their dictionary key names
_UNIT_ALIASES = {"mps" : "m s-1",
"m/s" : "m s-1",
"ms-1" : "m s-1",
"meters_per_second" : "m s-1",
"metres_per_second" : "m s-1",
"knots" : "kt",
"knot" : "kt",
"kts" : "kt",
"kn" : "kt",
"miles_per_hour" : "mi h-1",
"mih-1" : "mi h-1",
"mph" : "mi h-1",
"mi/h" : "mi h-1",
"kmph" : "km h-1",
"kmh-1" : "km h-1",
"km/h" : "km h-1",
"kilometers_per_hour" : "km h-1",
"kilometres_per_hour" : "km h-1",
"ft/s" : "ft s-1",
"ft/sec" : "ft s-1",
"fps" : "ft s-1",
"fs-1" : "ft s-1",
"feet_per_second" : "ft s-1",
"pascal" : "pa",
"pascals" : "pa",
"hecto_pascal" : "hpa",
"hecto_pascals" : "hpa",
"millibar" : "mb",
"millibars" : "mb",
"mbar" : "mb",
"kelvin" : "k",
"degree_kelvin" : "k",
"degrees_kelvin" : "k",
"degree_k" : "k",
"degrees_k" : "k",
"degreek" : "k",
"degreesk" : "k",
"degk" : "k",
"degsk" : "k",
"deg_k" : "k",
"degs_k" : "k",
"deg k" : "k",
"degs k" : "k",
"celsius" : "c",
"degree_celsius" : "c",
"degrees_celsius" : "c",
"degree_c" : "c",
"degrees_c" : "c",
"degreec" : "c",
"degreesc" : "c",
"degc" : "c",
"degsc" : "c",
"deg_c" : "c",
"degs_c" : "c",
"deg c" : "c",
"degs c" : "c",
"fahrenheit" : "f",
"degree_fahrenheit" : "f",
"degrees_fahrenheit" : "f",
"degree_f" : "f",
"degrees_f" : "f",
"degreef" : "f",
"degreesf" : "f",
"degf" : "f",
"degsf" : "f",
"deg_f" : "f",
"degs_f" : "f",
"deg f" : "f",
"degs f" : "f",
"meter" : "m",
"meters" : "m",
"metre" : "m",
"metres" : "m",
"kilometer" : "km",
"kilometers" : "km",
"dekameter" : "dm",
"dekameters" : "dm",
"decameter" : "dm",
"decameters" : "dm",
"dekametre" : "dm",
"dekametres" : "dm",
"decametre" : "dm",
"decametres" : "dm",
"dam" : "dm",
"dkm" : "dm",
"feet" : "ft",
"foot" : "ft",
"mile" : "mi",
"miles" : "mi"
_UNIT_ALIASES = {"mps": "m s-1",
"m/s": "m s-1",
"ms-1": "m s-1",
"meters_per_second": "m s-1",
"metres_per_second": "m s-1",
"knots": "kt",
"knot": "kt",
"kts": "kt",
"kn": "kt",
"miles_per_hour": "mi h-1",
"mih-1": "mi h-1",
"mph": "mi h-1",
"mi/h": "mi h-1",
"kmph": "km h-1",
"kmh-1": "km h-1",
"km/h": "km h-1",
"kilometers_per_hour": "km h-1",
"kilometres_per_hour": "km h-1",
"ft/s": "ft s-1",
"ft/sec": "ft s-1",
"fps": "ft s-1",
"fs-1": "ft s-1",
"feet_per_second": "ft s-1",
"pascal": "pa",
"pascals": "pa",
"hecto_pascal": "hpa",
"hecto_pascals": "hpa",
"millibar": "mb",
"millibars": "mb",
"mbar": "mb",
"kelvin": "k",
"degree_kelvin": "k",
"degrees_kelvin": "k",
"degree_k": "k",
"degrees_k": "k",
"degreek": "k",
"degreesk": "k",
"degk": "k",
"degsk": "k",
"deg_k": "k",
"degs_k": "k",
"deg k": "k",
"degs k": "k",
"celsius": "c",
"degree_celsius": "c",
"degrees_celsius": "c",
"degree_c": "c",
"degrees_c": "c",
"degreec": "c",
"degreesc": "c",
"degc": "c",
"degsc": "c",
"deg_c": "c",
"degs_c": "c",
"deg c": "c",
"degs c": "c",
"fahrenheit": "f",
"degree_fahrenheit": "f",
"degrees_fahrenheit": "f",
"degree_f": "f",
"degrees_f": "f",
"degreef": "f",
"degreesf": "f",
"degf": "f",
"degsf": "f",
"deg_f": "f",
"degs_f": "f",
"deg f": "f",
"degs f": "f",
"meter": "m",
"meters": "m",
"metre": "m",
"metres": "m",
"kilometer": "km",
"kilometers": "km",
"dekameter": "dm",
"dekameters": "dm",
"decameter": "dm",
"decameters": "dm",
"dekametre": "dm",
"dekametres": "dm",
"decametre": "dm",
"decametres": "dm",
"dam": "dm",
"dkm": "dm",
"feet": "ft",
"foot": "ft",
"mile": "mi",
"miles": "mi"
}
# A mapping of unit types to the avaible units
_VALID_UNITS = {"wind" : ["m s-1", "kt", "mi h-1", "km h-1", "ft s-1"],
"pressure" : ["pa", "hpa", "mb", "torr", "mmhg", "atm"],
"temp" : ["k", "f", "c"],
"height" : ["m", "km", "dm", "ft", "mi"]
_VALID_UNITS = {"wind": ["m s-1", "kt", "mi h-1", "km h-1", "ft s-1"],
"pressure": ["pa", "hpa", "mb", "torr", "mmhg", "atm"],
"temp": ["k", "f", "c"],
"height": ["m", "km", "dm", "ft", "mi"]
}
# Conversion factor map for wind from base units
_WIND_BASE_FACTORS = {"kt" : ConversionFactors.MPS_TO_KTS,
"km h-1" : ConversionFactors.MPS_TO_KMPH,
"mi h-1" : ConversionFactors.MPS_TO_MPH,
"ft s-1" : ConversionFactors.MPS_TO_FPS
_WIND_BASE_FACTORS = {"kt": ConversionFactors.MPS_TO_KTS,
"km h-1": ConversionFactors.MPS_TO_KMPH,
"mi h-1": ConversionFactors.MPS_TO_MPH,
"ft s-1": ConversionFactors.MPS_TO_FPS
}
# Conversion factor map to base units
_WIND_TOBASE_FACTORS = {"kt" : 1.0/ConversionFactors.MPS_TO_KTS,
"km h-1" : 1.0/ConversionFactors.MPS_TO_KMPH,
"mi h-1" : 1.0/ConversionFactors.MPS_TO_MPH,
"ft s-1" : 1.0/ConversionFactors.MPS_TO_FPS
_WIND_TOBASE_FACTORS = {"kt": 1.0/ConversionFactors.MPS_TO_KTS,
"km h-1": 1.0/ConversionFactors.MPS_TO_KMPH,
"mi h-1": 1.0/ConversionFactors.MPS_TO_MPH,
"ft s-1": 1.0/ConversionFactors.MPS_TO_FPS
}
# Conversion factor map for pressure from base units
_PRES_BASE_FACTORS = {"hpa" : ConversionFactors.PA_TO_HPA,
"mb" : ConversionFactors.PA_TO_HPA,
"torr" : ConversionFactors.PA_TO_TORR,
"mmhg" : ConversionFactors.PA_TO_MMHG,
"atm" : ConversionFactors.PA_TO_ATM
_PRES_BASE_FACTORS = {"hpa": ConversionFactors.PA_TO_HPA,
"mb": ConversionFactors.PA_TO_HPA,
"torr": ConversionFactors.PA_TO_TORR,
"mmhg": ConversionFactors.PA_TO_MMHG,
"atm": ConversionFactors.PA_TO_ATM
}
# Conversion factor map for pressure to base units
_PRES_TOBASE_FACTORS = {"hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"mb" : 1.0/ConversionFactors.PA_TO_HPA,
"torr" : 1.0/ConversionFactors.PA_TO_TORR,
"mmhg" : 1.0/ConversionFactors.PA_TO_MMHG,
"atm" : 1.0/ConversionFactors.PA_TO_ATM
_PRES_TOBASE_FACTORS = {"hpa": 1.0/ConversionFactors.PA_TO_HPA,
"mb": 1.0/ConversionFactors.PA_TO_HPA,
"torr": 1.0/ConversionFactors.PA_TO_TORR,
"mmhg": 1.0/ConversionFactors.PA_TO_MMHG,
"atm": 1.0/ConversionFactors.PA_TO_ATM
}
# Conversion factor map for height from base units
_HEIGHT_BASE_FACTORS = {"km" : ConversionFactors.M_TO_KM,
"dm" : ConversionFactors.M_TO_DM,
"ft" : ConversionFactors.M_TO_FT,
"mi" : ConversionFactors.M_TO_MILES
_HEIGHT_BASE_FACTORS = {"km": ConversionFactors.M_TO_KM,
"dm": ConversionFactors.M_TO_DM,
"ft": ConversionFactors.M_TO_FT,
"mi": ConversionFactors.M_TO_MILES
}
# Conversion factor map for height to base units
_HEIGHT_TOBASE_FACTORS = {"km" : 1.0/ConversionFactors.M_TO_KM,
"dm" : 1.0/ConversionFactors.M_TO_DM,
"ft" : 1.0/ConversionFactors.M_TO_FT,
"mi" : 1.0/ConversionFactors.M_TO_MILES
_HEIGHT_TOBASE_FACTORS = {"km": 1.0/ConversionFactors.M_TO_KM,
"dm": 1.0/ConversionFactors.M_TO_DM,
"ft": 1.0/ConversionFactors.M_TO_FT,
"mi": 1.0/ConversionFactors.M_TO_MILES
}
# Mapping of unit type to base unit type
_BASE_UNITS = {"wind" : "m s-1",
"pressure" : "pa",
"temp" : "k",
"height" : "m"
_BASE_UNITS = {"wind": "m s-1",
"pressure": "pa",
"temp": "k",
"height": "m"
}
# A mapping of unit type to a mapping of to/from base conversion factors
_CONV_FACTORS = {"wind" : {"to_dest" : _WIND_BASE_FACTORS,
"to_base" : _WIND_TOBASE_FACTORS},
"pressure" : {"to_dest" : _PRES_BASE_FACTORS,
"to_base" : _PRES_TOBASE_FACTORS},
"height" : {"to_dest" : _HEIGHT_BASE_FACTORS,
"to_base" : _HEIGHT_TOBASE_FACTORS}
_CONV_FACTORS = {"wind": {"to_dest": _WIND_BASE_FACTORS,
"to_base": _WIND_TOBASE_FACTORS},
"pressure": {"to_dest": _PRES_BASE_FACTORS,
"to_base": _PRES_TOBASE_FACTORS},
"height": {"to_dest": _HEIGHT_BASE_FACTORS,
"to_base": _HEIGHT_TOBASE_FACTORS}
}
# A mapping of temperature type to the conversion function
_TEMP_CONV_METHODS = {"c" : _k_to_c,
"f" : _k_to_f
_TEMP_CONV_METHODS = {"c": _k_to_c,
"f": _k_to_f
}
def dealias_and_clean_unit(unit):
"""Return the properly cleaned and dealiased unit name.
@ -336,7 +331,7 @@ def check_units(unit, unit_type): @@ -336,7 +331,7 @@ def check_units(unit, unit_type):
"""
u_cleaned = dealias_and_clean_unit(unit)
if u_cleaned not in _VALID_UNITS[unit_type]:
raise ValueError("invalid unit type '%s'" % unit)
raise ValueError("invalid unit type '{}'".format(unit))
def do_conversion(var, vartype, var_unit, dest_unit):
@ -365,8 +360,3 @@ def do_conversion(var, vartype, var_unit, dest_unit): @@ -365,8 +360,3 @@ def do_conversion(var, vartype, var_unit, dest_unit):
return _apply_conv_fact(var, vartype, var_unit.lower(), u_cleaned)
else:
return _apply_temp_conv(var, var_unit.lower(), u_cleaned)

219
src/wrf/util.py

@ -41,16 +41,16 @@ if xarray_enabled(): @@ -41,16 +41,16 @@ if xarray_enabled():
from xarray import DataArray
_COORD_PAIR_MAP = {"XLAT" : ("XLAT", "XLONG"),
"XLONG" : ("XLAT", "XLONG"),
"XLAT_M" : ("XLAT_M", "XLONG_M"),
"XLONG_M" : ("XLAT_M", "XLONG_M"),
"XLAT_U" : ("XLAT_U", "XLONG_U"),
"XLONG_U" : ("XLAT_U", "XLONG_U"),
"XLAT_V" : ("XLAT_V", "XLONG_V"),
"XLONG_V" : ("XLAT_V", "XLONG_V"),
"CLAT" : ("CLAT", "CLONG"),
"CLONG" : ("CLAT", "CLONG")}
_COORD_PAIR_MAP = {"XLAT": ("XLAT", "XLONG"),
"XLONG": ("XLAT", "XLONG"),
"XLAT_M": ("XLAT_M", "XLONG_M"),
"XLONG_M": ("XLAT_M", "XLONG_M"),
"XLAT_U": ("XLAT_U", "XLONG_U"),
"XLONG_U": ("XLAT_U", "XLONG_U"),
"XLAT_V": ("XLAT_V", "XLONG_V"),
"XLONG_V": ("XLAT_V", "XLONG_V"),
"CLAT": ("CLAT", "CLONG"),
"CLONG": ("CLAT", "CLONG")}
_COORD_VARS = ("XLAT", "XLONG", "XLAT_M", "XLONG_M", "XLAT_U", "XLONG_U",
@ -58,7 +58,7 @@ _COORD_VARS = ("XLAT", "XLONG", "XLAT_M", "XLONG_M", "XLAT_U", "XLONG_U", @@ -58,7 +58,7 @@ _COORD_VARS = ("XLAT", "XLONG", "XLAT_M", "XLONG_M", "XLAT_U", "XLONG_U",
_LAT_COORDS = ("XLAT", "XLAT_M", "XLAT_U", "XLAT_V", "CLAT")
_LON_COORDS = ("XLONG", "XLONG_M", "XLONG_U","XLONG_V", "CLONG")
_LON_COORDS = ("XLONG", "XLONG_M", "XLONG_U", "XLONG_V", "CLONG")
_TIME_COORD_VARS = ("XTIME",)
@ -210,11 +210,11 @@ def _generator_copy(gen): @@ -210,11 +210,11 @@ def _generator_copy(gen):
if module is not None:
try:
try:
argd = {key:argvals.locals[key] for key in argvals.args}
argd = {key: argvals.locals[key] for key in argvals.args}
res = module.get(funcname)(**argd)
except AttributeError:
res = getattr(module, funcname)(**argd)
except:
except Exception:
# This is the old way it used to work, but it looks like this was
# fixed by Python.
try:
@ -226,9 +226,9 @@ def _generator_copy(gen): @@ -226,9 +226,9 @@ def _generator_copy(gen):
import __main__
try:
argd = {key:argvals.locals[key] for key in argvals.args}
argd = {key: argvals.locals[key] for key in argvals.args}
res = getattr(__main__, funcname)(**argd)
except:
except Exception:
# This was the old way it used to work, but appears to have
# been fixed by Python.
res = getattr(__main__, funcname)(**argvals.locals)
@ -237,7 +237,7 @@ def _generator_copy(gen): @@ -237,7 +237,7 @@ def _generator_copy(gen):
def test():
q = [1,2,3]
q = [1, 2, 3]
for i in q:
yield i
@ -661,18 +661,18 @@ def _corners_moved(wrfnc, first_ll_corner, first_ur_corner, latvar, lonvar): @@ -661,18 +661,18 @@ def _corners_moved(wrfnc, first_ll_corner, first_ur_corner, latvar, lonvar):
# Need to check all times
for i in py3range(lats.shape[-3]):
start_idxs = [0]*len(lats.shape) # PyNIO does not support ndim
start_idxs = [0] * len(lats.shape) # PyNIO does not support ndim
start_idxs[-3] = i
start_idxs = tuple(start_idxs)
end_idxs = [-1]*len(lats.shape)
end_idxs = [-1] * len(lats.shape)
end_idxs[-3] = i
end_idxs = tuple(end_idxs)
if (first_ll_corner[0] != lats[start_idxs] or
first_ll_corner[1] != lons[start_idxs] or
first_ur_corner[0] != lats[end_idxs] or
first_ur_corner[1] != lons[end_idxs]):
if (first_ll_corner[0] != lats[start_idxs]
or first_ll_corner[1] != lons[start_idxs]
or first_ur_corner[0] != lats[end_idxs]
or first_ur_corner[1] != lons[end_idxs]):
return True
return False
@ -757,8 +757,14 @@ def is_moving_domain(wrfin, varname=None, latvar=either("XLAT", "XLAT_M"), @@ -757,8 +757,14 @@ def is_moving_domain(wrfin, varname=None, latvar=either("XLAT", "XLAT_M"),
lon_coord = lonvar
lat_coord = latvar
else:
lon_coord = coord_names[0]
lat_coord = coord_names[1]
for name in coord_names:
if name in _LAT_COORDS:
lat_coord = name
continue
if name in _LON_COORDS:
lon_coord = name
continue
else:
lon_coord = lonvar
lat_coord = latvar
@ -871,7 +877,7 @@ def extract_global_attrs(wrfin, attrs): @@ -871,7 +877,7 @@ def extract_global_attrs(wrfin, attrs):
entry = wrfin[next(iter(viewkeys(wrfin)))]
return extract_global_attrs(entry, attrs)
return {attr:_get_global_attr(wrfin, attr) for attr in attrlist}
return {attr: _get_global_attr(wrfin, attr) for attr in attrlist}
def extract_dim(wrfin, dim):
@ -901,15 +907,16 @@ def extract_dim(wrfin, dim): @@ -901,15 +907,16 @@ def extract_dim(wrfin, dim):
d = wrfin.dimensions[dim]
if not isinstance(d, int):
try:
return len(d) #netCDF4
except TypeError: #scipy.io.netcdf
return len(d) # netCDF4
except TypeError: # scipy.io.netcdf
# Scipy can't handled unlimited dimensions, so now we have to
# figure it out
try:
s = wrfin.variables["P"].shape
return s[-4]
except:
except Exception:
raise ValueError("unsupported NetCDF reader")
else:
return s[-4]
return d # PyNIO
@ -983,7 +990,7 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta, _key): @@ -983,7 +990,7 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta, _key):
outdims = [numkeys]
outdims += first_array.shape
outdata = np.empty(outdims, first_array.dtype)
outdata[0,:] = first_array[:]
outdata[0, :] = first_array[:]
idx = 1
while True:
@ -1002,7 +1009,7 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta, _key): @@ -1002,7 +1009,7 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta, _key):
if outdata.shape[1:] != vardata.shape:
raise ValueError("data sequences must have the "
"same size for all dictionary keys")
outdata[idx,:] = to_np(vardata)[:]
outdata[idx, :] = to_np(vardata)[:]
idx += 1
if xarray_enabled() and meta:
@ -1038,12 +1045,10 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta, _key): @@ -1038,12 +1045,10 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta, _key):
# make it so that key_0 is leftmost
outdims = key_coordnames + list(first_array.dims[existing_cnt:])
# Create the new 'key_n', value pairs
for coordname, coordval in zip(key_coordnames, coord_vals):
outcoords[coordname] = coordval
outattrs = OrderedDict(first_array.attrs)
outarr = DataArray(outdata, name=outname, coords=outcoords,
@ -1181,15 +1186,22 @@ def _get_coord_names(wrfin, varname): @@ -1181,15 +1186,22 @@ def _get_coord_names(wrfin, varname):
coord_names = coord_attr.split()
else:
coord_names = coord_attr.decode().split()
lon_coord = coord_names[0]
lat_coord = coord_names[1]
try:
time_coord = coord_names[2]
except IndexError:
time_coord = None
else:
# Make sure they time variable wasn't removed
for name in coord_names:
if name in _LAT_COORDS:
lat_coord = name
continue
if name in _LON_COORDS:
lon_coord = name
continue
if name in _TIME_COORD_VARS:
time_coord = name
continue
if time_coord is not None:
# Make sure the time variable wasn't removed
try:
_ = wrfnc.variables[time_coord]
except KeyError:
@ -1279,7 +1291,6 @@ def _build_data_array(wrfnc, varname, timeidx, is_moving_domain, is_multifile, @@ -1279,7 +1291,6 @@ def _build_data_array(wrfnc, varname, timeidx, is_moving_domain, is_multifile,
except IndexError:
pass
coords = OrderedDict()
# Handle lat/lon coordinates and projection information if available
@ -1341,17 +1352,17 @@ def _build_data_array(wrfnc, varname, timeidx, is_moving_domain, is_multifile, @@ -1341,17 +1352,17 @@ def _build_data_array(wrfnc, varname, timeidx, is_moving_domain, is_multifile,
else:
coords[lon_coord] = (lon_coord_dims[1:],
lon_coord_vals[0,:])
lon_coord_vals[0, :])
coords[lat_coord] = (lat_coord_dims[1:],
lat_coord_vals[0,:])
lat_coord_vals[0, :])
if time_coord is not None:
coords[time_coord] = (lon_coord_dims[0], time_coord_vals)
else:
coords[lon_coord] = (lon_coord_dims[1:],
lon_coord_vals[timeidx,:])
lon_coord_vals[timeidx, :])
coords[lat_coord] = (lat_coord_dims[1:],
lat_coord_vals[timeidx,:])
lat_coord_vals[timeidx, :])
if time_coord is not None:
coords[time_coord] = (lon_coord_dims[0],
@ -1605,8 +1616,6 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key): @@ -1605,8 +1616,6 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key):
return _find_arr_for_time(wrfseq, varname, timeidx, is_moving, meta,
_key)
#time_idx_or_slice = timeidx if not multitime else slice(None)
# If all times are requested, need to build a new array and cat together
# all of the arrays in the sequence
wrf_iter = iter(wrfseq)
@ -1652,7 +1661,8 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key): @@ -1652,7 +1661,8 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key):
outxtimes = get_cached_item(_key, timekey)
if outxtimes is None:
outxtimes = np.empty(outdims[0])
outxtimes[startidx:endidx] = to_np(first_var.coords[timename][:])
outxtimes[startidx:endidx] = to_np(
first_var.coords[timename][:])
else:
timecached = True
@ -1664,7 +1674,8 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key): @@ -1664,7 +1674,8 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key):
outlats = get_cached_item(_key, latkey)
if outlats is None:
outlats = np.empty(outcoorddims, first_var.dtype)
outlats[startidx:endidx, :] = to_np(first_var.coords[latname][:])
outlats[startidx:endidx, :] = to_np(
first_var.coords[latname][:])
else:
latcached = True
@ -1672,11 +1683,11 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key): @@ -1672,11 +1683,11 @@ def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta, _key):
outlons = get_cached_item(_key, lonkey)
if outlons is None:
outlons = np.empty(outcoorddims, first_var.dtype)
outlons[startidx:endidx, :] = to_np(first_var.coords[lonname][:])
outlons[startidx:endidx, :] = to_np(
first_var.coords[lonname][:])
else:
loncached = True
startidx = endidx
while True:
try:
@ -1927,7 +1938,7 @@ def _join_files(wrfseq, varname, timeidx, is_moving, meta, _key): @@ -1927,7 +1938,7 @@ def _join_files(wrfseq, varname, timeidx, is_moving, meta, _key):
else:
loncached = True
file_idx=1
file_idx = 1
while True:
try:
wrfnc = next(wrf_iter)
@ -1951,8 +1962,8 @@ def _join_files(wrfseq, varname, timeidx, is_moving, meta, _key): @@ -1951,8 +1962,8 @@ def _join_files(wrfseq, varname, timeidx, is_moving, meta, _key):
# For join, the times are a function of fileidx
file_times = extract_times(wrfnc, ALL_TIMES, meta=False,
do_xtime=False)
time_coord[file_idx, 0:numtimes] = np.asarray(file_times,
"datetime64[ns]")[:]
time_coord[file_idx, 0:numtimes] = np.asarray(
file_times, "datetime64[ns]")[:]
if timename is not None and not timecached:
xtimedata = wrfnc.variables[timename][:]
@ -2206,7 +2217,7 @@ def _extract_var(wrfin, varname, timeidx, is_moving, @@ -2206,7 +2217,7 @@ def _extract_var(wrfin, varname, timeidx, is_moving,
multifile, _key)
else:
if not multitime:
result = wrfin.variables[varname][timeidx,:]
result = wrfin.variables[varname][timeidx, :]
result = result[np.newaxis, :] # So that no squeeze works
else:
result = wrfin.variables[varname][:]
@ -2275,7 +2286,7 @@ def extract_vars(wrfin, timeidx, varnames, method="cat", squeeze=True, @@ -2275,7 +2286,7 @@ def extract_vars(wrfin, timeidx, varnames, method="cat", squeeze=True,
else:
varlist = varnames
return {var:_extract_var(wrfin, var, timeidx, None,
return {var: _extract_var(wrfin, var, timeidx, None,
method, squeeze, cache, meta, _key)
for var in varlist}
@ -2338,9 +2349,9 @@ def _file_times(wrfin, do_xtime): @@ -2338,9 +2349,9 @@ def _file_times(wrfin, do_xtime):
"""
if not do_xtime:
times = wrfin.variables["Times"][:,:]
times = wrfin.variables["Times"][:, :]
for i in py3range(times.shape[0]):
yield _make_time(times[i,:])
yield _make_time(times[i, :])
else:
xtimes = wrfin.variables["XTIME"][:]
for i in py3range(xtimes.shape[0]):
@ -2377,7 +2388,7 @@ def _extract_time_map(wrfin, timeidx, do_xtime, meta=False): @@ -2377,7 +2388,7 @@ def _extract_time_map(wrfin, timeidx, do_xtime, meta=False):
otherwise the sequence is :class:`numpy.ndarray`.
"""
return {key : extract_times(wrfseq, timeidx, do_xtime, meta)
return {key: extract_times(wrfseq, timeidx, do_xtime, meta)
for key, wrfseq in viewitems(wrfin)}
@ -2465,12 +2476,12 @@ def extract_times(wrfin, timeidx, method="cat", squeeze=True, cache=None, @@ -2465,12 +2476,12 @@ def extract_times(wrfin, timeidx, method="cat", squeeze=True, cache=None,
num_cols = len(time_list[0])
time_arr = np.full((num_rows, num_cols), fill_value, dtype=dt)
for i,row in enumerate(time_list):
for i, row in enumerate(time_list):
if len(row) == num_cols:
time_arr[i,:] = row[:]
time_arr[i, :] = row[:]
else:
for j,val in enumerate(row):
time_arr[i,j] = val
for j, val in enumerate(row):
time_arr[i, j] = val
time_arr = ma.masked_values(time_arr, fill_value)
@ -2501,10 +2512,8 @@ def extract_times(wrfin, timeidx, method="cat", squeeze=True, cache=None, @@ -2501,10 +2512,8 @@ def extract_times(wrfin, timeidx, method="cat", squeeze=True, cache=None,
outname = "XTIME"
outarr = DataArray(time_arr, name=outname, coords=outcoords,
dims=outdimnames, attrs=outattrs)
else:
outarr = time_arr
@ -2657,7 +2666,7 @@ def get_right_slices(var, right_ndims, fixed_val=0): @@ -2657,7 +2666,7 @@ def get_right_slices(var, right_ndims, fixed_val=0):
[slice(None)]*right_ndims)
def get_proj_params(wrfin):#, timeidx=0, varname=None):
def get_proj_params(wrfin):
"""Return a tuple of latitude, longitude, and projection parameters from
a WRF output file object or a sequence of WRF output file objects.
@ -2684,7 +2693,8 @@ def get_proj_params(wrfin):#, timeidx=0, varname=None): @@ -2684,7 +2693,8 @@ def get_proj_params(wrfin):#, timeidx=0, varname=None):
longitude coordinate, and global projection attributes.
"""
proj_params = extract_global_attrs(wrfin, attrs=("MAP_PROJ",
proj_params = extract_global_attrs(wrfin,
attrs=("MAP_PROJ",
"CEN_LAT", "CEN_LON",
"TRUELAT1", "TRUELAT2",
"MOAD_CEN_LAT", "STAND_LON",
@ -2697,7 +2707,7 @@ def get_proj_params(wrfin):#, timeidx=0, varname=None): @@ -2697,7 +2707,7 @@ def get_proj_params(wrfin):#, timeidx=0, varname=None):
def from_args(func, argnames, *args, **kwargs):
"""Return a mapping of argument name to value for the called function.
This function parses the function \*args and \*\*kwargs to obtain the \
This function parses the function args and kwargs to obtain the
desired argument value. If the argument has not been passed in, the value
is taken from the default keyword argument value.
@ -2706,7 +2716,7 @@ def from_args(func, argnames, *args, **kwargs): @@ -2706,7 +2716,7 @@ def from_args(func, argnames, *args, **kwargs):
Note:
This function currently does not work with functions that contain
\*args or \*\*kwargs arguments.
variable length args or kwargs arguments.
Args:
@ -2750,7 +2760,7 @@ def _args_to_list2(func, args, kwargs): @@ -2750,7 +2760,7 @@ def _args_to_list2(func, args, kwargs):
Note:
This function currently does not work with functions that contain
*args or **kwargs arguments.
variable length args or kwargs arguments.
Args:
@ -2771,15 +2781,15 @@ def _args_to_list2(func, args, kwargs): @@ -2771,15 +2781,15 @@ def _args_to_list2(func, args, kwargs):
# Build the full tuple with defaults filled in
outargs = [None]*len(argspec.args)
if argspec.defaults is not None:
for i,default in enumerate(argspec.defaults[::-1], 1):
for i, default in enumerate(argspec.defaults[::-1], 1):
outargs[-i] = default
# Add the supplied args
for i,arg in enumerate(args):
for i, arg in enumerate(args):
outargs[i] = arg
# Fill in the supplied kargs
for argname,val in viewitems(kwargs):
for argname, val in viewitems(kwargs):
argidx = argspec.args.index(argname)
outargs[argidx] = val
@ -2837,7 +2847,7 @@ def _args_to_list3(func, args, kwargs): @@ -2837,7 +2847,7 @@ def _args_to_list3(func, args, kwargs):
Note:
This function currently does not work with functions that contain
*args or **kwargs arguments.
variable length args or kwargs arguments.
Args:
@ -2872,7 +2882,7 @@ def args_to_list(func, args, kwargs): @@ -2872,7 +2882,7 @@ def args_to_list(func, args, kwargs):
Note:
This function currently does not work with functions that contain
\*args or \*\*kwargs arguments.
variable length args or kwargs arguments.
Args:
@ -3026,13 +3036,27 @@ def psafilepath(): @@ -3026,13 +3036,27 @@ def psafilepath():
def get_filepath(obj):
"""Return the file path for the specified object.
This is used to return the file path for a netcdf object. If the
particular object does not have the appropriate file path information,
then one is created based on the timestep in the file.
Args:
obj: An object.
Returns:
:obj:`str`: A string for a file path.
"""
try:
path = obj.filepath()
except AttributeError:
try:
path = obj.file.path
except:
except AttributeError:
# Let's make up a filename from the first file time
found = False
times = extract_times(obj, None, meta=False, do_xtime=False)
@ -3046,6 +3070,7 @@ def get_filepath(obj): @@ -3046,6 +3070,7 @@ def get_filepath(obj):
return path
def get_id(obj, prefix=''):
"""Return the cache id.
@ -3078,7 +3103,7 @@ def get_id(obj, prefix=''): @@ -3078,7 +3103,7 @@ def get_id(obj, prefix=''):
# For each key in the mapping, recursively call get_id until
# until a non-mapping is found
return {key : get_id(val, prefix) for key,val in viewitems(obj)}
return {key: get_id(val, prefix) for key, val in viewitems(obj)}
def geo_bounds(var=None, wrfin=None, varname=None, timeidx=0, method="cat",
@ -3221,6 +3246,7 @@ def geo_bounds(var=None, wrfin=None, varname=None, timeidx=0, method="cat", @@ -3221,6 +3246,7 @@ def geo_bounds(var=None, wrfin=None, varname=None, timeidx=0, method="cat",
# Non-moving domains
return GeoBounds(lats=lats, lons=lons)
def _get_wrf_proj_geobnds(var, wrfin, varname, timeidx, method, squeeze,
cache):
"""Return the :class:`wrf.WrfProj` subclass and :class:`wrf.GeoBounds`.
@ -3724,7 +3750,8 @@ def cartopy_xlim(var=None, geobounds=None, wrfin=None, varname=None, timeidx=0, @@ -3724,7 +3750,8 @@ def cartopy_xlim(var=None, geobounds=None, wrfin=None, varname=None, timeidx=0,
"""
wrf_proj, native_geobnds = _get_wrf_proj_geobnds(var, wrfin, varname,
timeidx, method, squeeze, cache)
timeidx, method, squeeze,
cache)
if geobounds is not None:
return wrf_proj.cartopy_xlim(geobounds)
@ -3810,7 +3837,8 @@ def cartopy_ylim(var=None, geobounds=None, wrfin=None, varname=None, timeidx=0, @@ -3810,7 +3837,8 @@ def cartopy_ylim(var=None, geobounds=None, wrfin=None, varname=None, timeidx=0,
"""
wrf_proj, native_geobnds = _get_wrf_proj_geobnds(var, wrfin, varname,
timeidx, method, squeeze, cache)
timeidx, method, squeeze,
cache)
if geobounds is not None:
return wrf_proj.cartopy_ylim(geobounds)
@ -3841,8 +3869,8 @@ def ll_points(lat, lon): @@ -3841,8 +3869,8 @@ def ll_points(lat, lon):
object or a list of :class:`wrf.CoordPair` objects.
"""
latvals = np.ravel(to_np(lat)[...,0,0])
lonvals = np.ravel(to_np(lon)[...,0,0])
latvals = np.ravel(to_np(lat)[..., 0, 0])
lonvals = np.ravel(to_np(lon)[..., 0, 0])
if latvals.shape[0] == 1:
return CoordPair(lat=float(latvals), lon=float(lonvals))
@ -3897,30 +3925,3 @@ def is_latlon_pair(pair): @@ -3897,30 +3925,3 @@ def is_latlon_pair(pair):
return (pair.lat is not None and pair.lon is not None)
else:
return False

3
src/wrf/version.py

@ -1,2 +1 @@ @@ -1,2 +1 @@
__version__ = "1.3.1"
__version__ = "1.3.2"

3
test/ci_tests/make_test_file.py

@ -131,7 +131,7 @@ def make_result_file(opts): @@ -131,7 +131,7 @@ def make_result_file(opts):
tk = getvar(infile, "temp", units="k")
interp_levels = [200,300,500,1000]
interp_levels = [200, 300, 500, 1000]
field = vinterp(infile,
field=tk,
@ -159,6 +159,7 @@ def make_result_file(opts): @@ -159,6 +159,7 @@ def make_result_file(opts):
ll = xy_to_ll(infile, x_s[0], y_s[0])
add_to_ncfile(outfile, ll, "ll")
def main(opts):
copy_and_reduce(opts)
make_result_file(opts)

38
test/ci_tests/utests.py

@ -2,7 +2,8 @@ import unittest as ut @@ -2,7 +2,8 @@ import unittest as ut
import numpy.testing as nt
import numpy as np
import numpy.ma as ma
import os, sys
import os
import sys
import subprocess
from wrf import (getvar, interplevel, interpline, vertcross, vinterp,
@ -20,6 +21,7 @@ REF_FILE = "ci_result_file.nc" @@ -20,6 +21,7 @@ REF_FILE = "ci_result_file.nc"
if sys.version_info > (3,):
xrange = range
# Using helpful information at:
# http://eli.thegreenplace.net/2014/04/02/dynamically-generating-python-test-cases
def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False):
@ -34,7 +36,6 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): @@ -34,7 +36,6 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False):
multiproduct = varname in ("uvmet", "uvmet10", "cape_2d", "cape_3d",
"cfrac")
ref_vals = refnc.variables[varname][:]
if (varname == "tc"):
@ -45,8 +46,7 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): @@ -45,8 +46,7 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False):
elif (varname == "pw"):
my_vals = getvar(in_wrfnc, "pw", timeidx=timeidx)
tol = .5/100.0
atol = 0 # NCL uses different constants and doesn't use same
# handrolled virtual temp in method
atol = 0
nt.assert_allclose(to_np(my_vals), ref_vals, tol, atol)
elif (varname == "cape_2d"):
cape_2d = getvar(in_wrfnc, varname, timeidx=timeidx)
@ -56,7 +56,7 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): @@ -56,7 +56,7 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False):
# merged back in to NCL. The modifications to the R and CP
# changes TK enough that non-lifting parcels could lift, thus
# causing wildly different values in LCL
nt.assert_allclose(to_np(cape_2d[0,:]), ref_vals[0,:], tol, atol)
nt.assert_allclose(to_np(cape_2d[0, :]), ref_vals[0, :], tol, atol)
elif (varname == "cape_3d"):
cape_3d = getvar(in_wrfnc, varname, timeidx=timeidx)
# Changing the R and CP constants, while keeping TK within
@ -67,18 +67,18 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): @@ -67,18 +67,18 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False):
tol = 0/100.
atol = 200.0
#print np.amax(np.abs(to_np(cape_3d[0,:]) - ref_vals[0,:]))
# print np.amax(np.abs(to_np(cape_3d[0,:]) - ref_vals[0,:]))
nt.assert_allclose(to_np(cape_3d), ref_vals, tol, atol)
else:
my_vals = getvar(in_wrfnc, varname, timeidx=timeidx)
tol = 2/100.
atol = 0.1
#print (np.amax(np.abs(to_np(my_vals) - ref_vals)))
# print (np.amax(np.abs(to_np(my_vals) - ref_vals)))
nt.assert_allclose(to_np(my_vals), ref_vals, tol, atol)
return test
def _get_refvals(referent, varname, repeat, multi):
from netCDF4 import Dataset as NetCDF
@ -88,6 +88,7 @@ def _get_refvals(referent, varname, repeat, multi): @@ -88,6 +88,7 @@ def _get_refvals(referent, varname, repeat, multi):
return ref_vals
def make_interp_test(varname, wrf_in, referent, multi=False,
repeat=3, pynio=False):
def test(self):
@ -103,7 +104,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, @@ -103,7 +104,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False,
# Check that it works with numpy arrays
hts_850 = interplevel(to_np(hts), p, 850)
#print (hts_850)
# print (hts_850)
hts_850 = interplevel(hts, p, 850)
nt.assert_allclose(to_np(hts_850), ref_ht_850)
@ -118,12 +119,11 @@ def make_interp_test(varname, wrf_in, referent, multi=False, @@ -118,12 +119,11 @@ def make_interp_test(varname, wrf_in, referent, multi=False,
# Check that it works with numpy arrays
ht_cross = vertcross(to_np(hts), to_np(p),
pivot_point=pivot_point, angle=90.)
#print (ht_cross)
# print (ht_cross)
ht_cross = vertcross(hts, p, pivot_point=pivot_point, angle=90.)
nt.assert_allclose(to_np(ht_cross), ref_ht_cross, rtol=.01)
elif (varname == "interpline"):
ref_t2_line = _get_refvals(referent, "interpline", repeat, multi)
@ -134,7 +134,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, @@ -134,7 +134,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False,
# Check that it works with numpy arrays
t2_line1 = interpline(to_np(t2), pivot_point=pivot_point,
angle=90.0)
#print (t2_line1)
# print (t2_line1)
t2_line1 = interpline(t2, pivot_point=pivot_point, angle=90.0)
nt.assert_allclose(to_np(t2_line1), ref_t2_line)
@ -146,7 +146,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, @@ -146,7 +146,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False,
tk = getvar(in_wrfnc, "temp", timeidx=timeidx, units="k")
interp_levels = [200,300,500,1000]
interp_levels = [200, 300, 500, 1000]
# Check that it works with numpy arrays
field = vinterp(in_wrfnc,
@ -157,7 +157,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, @@ -157,7 +157,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False,
field_type="tk",
timeidx=timeidx,
log_p=True)
#print (field)
# print (field)
field = vinterp(in_wrfnc,
field=tk,
@ -200,7 +200,6 @@ def make_latlon_test(testid, wrf_in, referent, single, multi=False, repeat=3, @@ -200,7 +200,6 @@ def make_latlon_test(testid, wrf_in, referent, single, multi=False, repeat=3,
nt.assert_allclose(to_np(xy), ref_vals)
else:
# Since this domain is not moving, the reference values are the
# same whether there are multiple or single files
@ -215,15 +214,17 @@ def make_latlon_test(testid, wrf_in, referent, single, multi=False, repeat=3, @@ -215,15 +214,17 @@ def make_latlon_test(testid, wrf_in, referent, single, multi=False, repeat=3,
nt.assert_allclose(to_np(ll), ref_vals)
return test
class WRFVarsTest(ut.TestCase):
longMessage = True
class WRFInterpTest(ut.TestCase):
longMessage = True
class WRFLatLonTest(ut.TestCase):
longMessage = True
@ -261,10 +262,7 @@ if __name__ == "__main__": @@ -261,10 +262,7 @@ if __name__ == "__main__":
repeat=3, pynio=False)
multistr = "" if not multi else "_multi"
singlestr = "_nosingle" if not single else "_single"
test_name = "test_{}{}{}".format(testid, singlestr,
multistr)
test_name = "test_{}{}{}".format(testid, singlestr, multistr)
setattr(WRFLatLonTest, test_name, test_ll_func)
ut.main()

158
test/comp_utest.py

@ -4,53 +4,64 @@ import unittest as ut @@ -4,53 +4,64 @@ import unittest as ut
import numpy.testing as nt
import numpy as np
import numpy.ma as ma
import os, sys
import os
import sys
import subprocess
from netCDF4 import Dataset as nc
from wrf import *
NCL_EXE = "/Users/ladwig/nclbuild/6.3.0/bin/ncl"
TEST_FILE = "/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00"
TEST_FILE = ("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-28_00:00:00")
OUT_NC_FILE = "/tmp/wrftest.nc"
NCFILE = nc(TEST_FILE)
NCGROUP = [NCFILE, NCFILE, NCFILE]
GROUP_FILES = [
("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-28_00:00:00"),
("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-28_12:00:00"),
("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-29_00:00:00")]
NCGROUP = [nc(file) for file in GROUP_FILES]
# Python 3
if sys.version_info > (3,):
xrange = range
ROUTINE_MAP = {"avo": avo,
"eth": eth,
"cape_2d": cape_2d,
"cape_3d": cape_3d,
"ctt": ctt,
"dbz": dbz,
"helicity": srhel,
"omg": omega,
"pvo": pvo,
"pw": pw,
"rh": rh,
"slp": slp,
"td": td,
"tk": tk,
"tv": tvirtual,
"twb": wetbulb,
"updraft_helicity": udhel,
"uvmet": uvmet,
"cloudfrac": cloudfrac}
ROUTINE_MAP = {"avo" : avo,
"eth" : eth,
"cape_2d" : cape_2d,
"cape_3d" : cape_3d,
"ctt" : ctt,
"dbz" : dbz,
"helicity" : srhel,
"omg" : omega,
"pvo" : pvo,
"pw" : pw,
"rh" : rh,
"slp" : slp,
"td" : td,
"tk" : tk,
"tv" : tvirtual,
"twb" : wetbulb,
"updraft_helicity" : udhel,
"uvmet" : uvmet,
"cloudfrac" : cloudfrac}
class ProjectionError(RuntimeError):
pass
def get_args(varname, wrfnc, timeidx, method, squeeze):
if varname == "avo":
ncvars = extract_vars(wrfnc, timeidx, ("U", "V", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M",
"F"),
method, squeeze, cache=None, meta=True)
varnames = ("U", "V", "MAPFAC_U", "MAPFAC_V", "MAPFAC_M", "F")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
attrs = extract_global_attrs(wrfnc, attrs=("DX", "DY"))
u = ncvars["U"]
@ -66,10 +77,10 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -66,10 +77,10 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (u, v, msfu, msfv, msfm, cor, dx, dy)
if varname == "pvo":
ncvars = extract_vars(wrfnc, timeidx, ("U", "V", "T", "P",
"PB", "MAPFAC_U",
"MAPFAC_V", "MAPFAC_M",
"F"),
varnames = ("U", "V", "T", "P", "PB", "MAPFAC_U", "MAPFAC_V",
"MAPFAC_M", "F")
ncvars = extract_vars(wrfnc, timeidx,
varnames,
method, squeeze, cache=None, meta=True)
attrs = extract_global_attrs(wrfnc, attrs=("DX", "DY"))
@ -92,7 +103,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -92,7 +103,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (u, v, full_t, full_p, msfu, msfv, msfm, cor, dx, dy)
if varname == "eth":
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
t = ncvars["T"]
@ -107,7 +118,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -107,7 +118,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (qv, tkel, full_p)
if varname == "cape_2d":
varnames = ("T", "P", "PB", "QVAPOR", "PH","PHB", "HGT", "PSFC")
varnames = ("T", "P", "PB", "QVAPOR", "PH", "PHB", "HGT", "PSFC")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
@ -187,7 +198,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -187,7 +198,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
qice = np.zeros(qv.shape, qv.dtype)
haveqci = 0
else:
qice = icevars["QICE"] * 1000.0 #g/kg
qice = icevars["QICE"] * 1000.0 # g/kg
try:
cldvars = extract_vars(wrfnc, timeidx, "QCLOUD",
@ -195,7 +206,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -195,7 +206,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
except KeyError:
raise RuntimeError("'QCLOUD' not found in NetCDF file")
else:
qcld = cldvars["QCLOUD"] * 1000.0 #g/kg
qcld = cldvars["QCLOUD"] * 1000.0 # g/kg
full_p = p + pb
p_hpa = full_p * ConversionFactors.PA_TO_HPA
@ -269,8 +280,9 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -269,8 +280,9 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (u, v, z, ter)
if varname == "updraft_helicity":
ncvars = extract_vars(wrfnc, timeidx, ("W", "PH", "PHB", "MAPFAC_M"),
method, squeeze, cache=None, meta=True)
varnames = ("W", "PH", "PHB", "MAPFAC_M")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
wstag = ncvars["W"]
ph = ncvars["PH"]
@ -292,12 +304,12 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -292,12 +304,12 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
cache=None, meta=True)
v = destagger(v_vars[varname], -2, meta=True)
zstag = ph + phb
zstag = (ph + phb) / Constants.G
return (zstag, mapfct, u, v, wstag, dx, dy)
if varname == "omg":
varnames=("T", "P", "W", "PB", "QVAPOR")
varnames = ("T", "P", "W", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
t = ncvars["T"]
@ -314,7 +326,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -314,7 +326,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (qv, tkel, wa, full_p)
if varname == "pw":
varnames=("T", "P", "PB", "PH", "PHB", "QVAPOR")
varnames = ("T", "P", "PB", "PH", "PHB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
@ -335,7 +347,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -335,7 +347,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (full_p, tkel, qv, ht)
if varname == "rh":
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
t = ncvars["T"]
@ -351,7 +363,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -351,7 +363,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (qvapor, full_p, tkel)
if varname == "slp":
varnames=("T", "P", "PB", "QVAPOR", "PH", "PHB")
varnames = ("T", "P", "PB", "QVAPOR", "PH", "PHB")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
@ -375,7 +387,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -375,7 +387,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (destag_ph, tkel, full_p, qvapor)
if varname == "td":
varnames=("P", "PB", "QVAPOR")
varnames = ("P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
@ -390,7 +402,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -390,7 +402,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (full_p, qvapor)
if varname == "tk":
varnames=("T", "P", "PB")
varnames = ("T", "P", "PB")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
t = ncvars["T"]
@ -403,7 +415,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -403,7 +415,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (full_p, full_t)
if varname == "tv":
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
@ -419,7 +431,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -419,7 +431,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
return (tkel, qv)
if varname == "twb":
varnames=("T", "P", "PB", "QVAPOR")
varnames = ("T", "P", "PB", "QVAPOR")
ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
t = ncvars["T"]
@ -449,9 +461,9 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -449,9 +461,9 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
map_proj_attrs = extract_global_attrs(wrfnc, attrs="MAP_PROJ")
map_proj = map_proj_attrs["MAP_PROJ"]
if map_proj in (0,3,6):
if map_proj in (0, 3, 6):
raise ProjectionError("Map projection does not need rotation")
elif map_proj in (1,2):
elif map_proj in (1, 2):
lat_attrs = extract_global_attrs(wrfnc, attrs=("TRUELAT1",
"TRUELAT2"))
radians_per_degree = Constants.PI/180.0
@ -463,15 +475,16 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -463,15 +475,16 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
lon_attrs = extract_global_attrs(wrfnc, attrs="STAND_LON")
except AttributeError:
try:
cen_lon_attrs = extract_global_attrs(wrfnc, attrs="CEN_LON")
cen_lon_attrs = extract_global_attrs(wrfnc,
attrs="CEN_LON")
except AttributeError:
raise RuntimeError("longitude attributes not found in NetCDF")
raise RuntimeError("longitude attributes not found in "
"NetCDF")
else:
cen_lon = cen_lon_attrs["CEN_LON"]
else:
cen_lon = lon_attrs["STAND_LON"]
varname = "XLAT"
xlat_var = extract_vars(wrfnc, timeidx, varname,
method, squeeze, cache=None, meta=True)
@ -485,13 +498,15 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -485,13 +498,15 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
if map_proj == 1:
if((fabs(true_lat1 - true_lat2) > 0.1) and
(fabs(true_lat2 - 90.) > 0.1)):
cone = (log(cos(true_lat1*radians_per_degree))
- log(cos(true_lat2*radians_per_degree)))
cone = (log(cos(true_lat1 * radians_per_degree))
- log(cos(true_lat2 * radians_per_degree)))
cone = (cone /
(log(tan((45.-fabs(true_lat1/2.))*radians_per_degree))
- log(tan((45.-fabs(true_lat2/2.))*radians_per_degree))))
(log(tan((45.-fabs(true_lat1/2.)) *
radians_per_degree))
- log(tan((45.-fabs(true_lat2/2.)) *
radians_per_degree))))
else:
cone = sin(fabs(true_lat1)*radians_per_degree)
cone = sin(fabs(true_lat1) * radians_per_degree)
else:
cone = 1
@ -499,8 +514,10 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -499,8 +514,10 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
if varname == "cloudfrac":
from wrf.g_geoht import get_height
vars = extract_vars(wrfnc, timeidx, ("P", "PB", "QVAPOR", "T"),
method, squeeze, cache=None, meta=True)
varnames = ("P", "PB", "QVAPOR", "T")
vars = extract_vars(wrfnc, timeidx, varnames, method, squeeze,
cache=None, meta=True)
p = vars["P"]
pb = vars["PB"]
@ -522,6 +539,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze): @@ -522,6 +539,7 @@ def get_args(varname, wrfnc, timeidx, method, squeeze):
class WRFVarsTest(ut.TestCase):
longMessage = True
def make_func(varname, wrfnc, timeidx, method, squeeze, meta):
def func(self):
@ -532,7 +550,7 @@ def make_func(varname, wrfnc, timeidx, method, squeeze, meta): @@ -532,7 +550,7 @@ def make_func(varname, wrfnc, timeidx, method, squeeze, meta):
routine = ROUTINE_MAP[varname]
kwargs = {"meta" : meta}
kwargs = {"meta": meta}
result = routine(*args, **kwargs)
ref = getvar(wrfnc, varname, timeidx, method, squeeze, cache=None,
@ -651,6 +669,7 @@ def test_cape2d_1d(wrfnc): @@ -651,6 +669,7 @@ def test_cape2d_1d(wrfnc):
return func
if __name__ == "__main__":
from wrf import (omp_set_num_threads, omp_set_schedule, omp_get_schedule,
omp_set_dynamic, omp_get_num_procs, OMP_SCHED_STATIC)
@ -658,13 +677,6 @@ if __name__ == "__main__": @@ -658,13 +677,6 @@ if __name__ == "__main__":
omp_set_schedule(OMP_SCHED_STATIC, 0)
omp_set_dynamic(False)
varnames = ["avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz",
"geopt", "helicity", "lat", "lon", "omg", "p", "pressure",
"pvo", "pw", "rh2", "rh", "slp", "ter", "td2", "td", "tc",
"theta", "tk", "tv", "twb", "updraft_helicity", "ua", "va",
"wa", "uvmet10", "uvmet", "z", "cloudfrac"]
#varnames = ["helicity"]
varnames=["avo", "pvo", "eth", "dbz", "helicity", "updraft_helicity",
"omg", "pw", "rh", "slp", "td", "tk", "tv", "twb", "uvmet",
"cloudfrac", "ctt"]
@ -677,8 +689,8 @@ if __name__ == "__main__": @@ -677,8 +689,8 @@ if __name__ == "__main__":
varnames += ["cape_2d", "cape_3d"]
for varname in varnames:
for i,wrfnc in enumerate((NCFILE, NCGROUP)):
for j,timeidx in enumerate((0, ALL_TIMES)):
for i, wrfnc in enumerate((NCFILE, NCGROUP)):
for j, timeidx in enumerate((0, ALL_TIMES)):
for method in ("cat", "join"):
for squeeze in (True, False):
for meta in (True, False):
@ -686,10 +698,11 @@ if __name__ == "__main__": @@ -686,10 +698,11 @@ if __name__ == "__main__":
squeeze, meta)
ncname = "single" if i == 0 else "multi"
timename = "t0" if j == 0 else "all"
squeeze_name = "squeeze" if squeeze else "nosqueeze"
squeeze_name = ("squeeze" if squeeze
else "nosqueeze")
meta_name = "meta" if meta else "nometa"
test_name = "test_{}_{}_{}_{}_{}_{}".format(varname,
ncname, timename, method,
test_name = "test_{}_{}_{}_{}_{}_{}".format(
varname, ncname, timename, method,
squeeze_name, meta_name)
setattr(WRFVarsTest, test_name, func)
@ -700,7 +713,4 @@ if __name__ == "__main__": @@ -700,7 +713,4 @@ if __name__ == "__main__":
func = test_cape2d_1d(wrfnc)
setattr(WRFVarsTest, "test_cape2d_1d", func)
ut.main()

17
test/ctt_test.py

@ -4,10 +4,12 @@ from matplotlib.cm import get_cmap @@ -4,10 +4,12 @@ from matplotlib.cm import get_cmap
import cartopy.crs as crs
from cartopy.feature import NaturalEarthFeature
from wrf import to_np, getvar, smooth2d, get_cartopy, cartopy_xlim, cartopy_ylim, latlon_coords
from wrf import (to_np, getvar, smooth2d, get_cartopy, cartopy_xlim,
cartopy_ylim, latlon_coords)
# Open the NetCDF file
ncfile = Dataset("/Users/ladwig/Documents/wrf_files/problem_files/cfrac_bug/wrfout_d02_1987-10-01_00:00:00")
ncfile = Dataset("/Users/ladwig/Documents/wrf_files/"
"problem_files/cfrac_bug/wrfout_d02_1987-10-01_00:00:00")
# Get the sea level pressure
ctt = getvar(ncfile, "ctt")
@ -19,20 +21,23 @@ lats, lons = latlon_coords(ctt) @@ -19,20 +21,23 @@ lats, lons = latlon_coords(ctt)
cart_proj = get_cartopy(ctt)
# Create a figure
fig = plt.figure(figsize=(12,9))
fig = plt.figure(figsize=(12, 9))
# Set the GeoAxes to the projection used by WRF
ax = plt.axes(projection=cart_proj)
# Download and add the states and coastlines
states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none',
states = NaturalEarthFeature(category='cultural', scale='50m',
facecolor='none',
name='admin_1_states_provinces_shp')
ax.add_feature(states, linewidth=.5)
ax.coastlines('50m', linewidth=0.8)
# Make the contour outlines and filled contours for the smoothed sea level pressure.
# Make the contour outlines and filled contours for the smoothed sea level
# pressure.
plt.contour(to_np(lons), to_np(lats), to_np(ctt), 10, colors="black",
transform=crs.PlateCarree())
plt.contourf(to_np(lons), to_np(lats), to_np(ctt), 10, transform=crs.PlateCarree(),
plt.contourf(to_np(lons), to_np(lats), to_np(ctt), 10,
transform=crs.PlateCarree(),
cmap=get_cmap("jet"))
# Add a color bar

8
test/generator_test.py

@ -1,17 +1,19 @@ @@ -1,17 +1,19 @@
from __future__ import (absolute_import, division, print_function, unicode_literals)
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from wrf import getvar
from netCDF4 import Dataset as nc
#ncfile = nc("/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00")
ncfile = nc("/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-10-07_00_00_00")
def gen_seq():
wrfseq = [ncfile, ncfile, ncfile]
for wrf in wrfseq:
yield wrf
p_gen = getvar(gen_seq(), "P", method="join")
print(p_gen)
del p_gen

40
test/misc/extract_one_time.py

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
from netCDF4 import Dataset
VARS_TO_KEEP = ("Times", "XLAT", "XLONG", "XLAT_U", "XLAT_V", "XLONG_U",
"XLONG_V", "U", "V", "W", "PH", "PHB", "T", "P", "PB", "Q2",
"T2", "PSFC", "U10", "V10", "XTIME", "QVAPOR", "QCLOUD",
"QGRAUP", "QRAIN", "QSNOW", "QICE", "MAPFAC_M", "MAPFAC_U",
"MAPFAC_V", "F", "HGT", "RAINC", "RAINSH", "RAINNC",
"I_RAINC", "I_RAINNC")
INPUT_FILE = "wrfout_d02_2005-08-28_00:00:00"
OUTPUT_FILE = "wrfout_problem_file"
DESIRED_TIME_INDEX = 0
with Dataset(INPUT_FILE) as infile, Dataset(OUTPUT_FILE, mode="w") as outfile:
# Copy the global attributes
outfile.setncatts(infile.__dict__)
# Copy Dimensions
for name, dimension in infile.dimensions.items():
if name != "Time":
dimsize = len(dimension)
outfile.createDimension(name, dimsize)
else:
outfile.createDimension(name, 1)
# Copy Variables
for name, variable in infile.variables.iteritems():
if name not in VARS_TO_KEEP:
continue
outvar = outfile.createVariable(name, variable.datatype,
variable.dimensions, zlib=True)
if len(variable.dimensions) > 1:
outvar[:] = variable[DESIRED_TIME_INDEX, :]
else:
outvar[:] = variable[DESIRED_TIME_INDEX]
outvar.setncatts(variable.__dict__)

70
test/misc/loop_and_fill_meta.py

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
from __future__ import print_function, division
import os
import numpy as np
from netCDF4 import Dataset
from wrf import getvar, ALL_TIMES, to_np
import xarray
filename_list = ["/Users/ladwig/Documents/wrf_files/"
"wrf_vortex_single/wrfout_d02_2005-08-28_00:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_single/"
"wrfout_d02_2005-08-28_03:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_single/"
"wrfout_d02_2005-08-28_06:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_single/"
"wrfout_d02_2005-08-28_09:00:00"]
result_shape = (4, 1, 96, 96)
# Let's get the first time so we can copy the metadata later
f = Dataset(filename_list[0])
# By setting squeeze to False, you'll get all the dimension names.
z1 = getvar(f, "T2", 0, squeeze=False)
xlat = getvar(f, "XLAT", 0)
xlong = getvar(f, "XLONG", 0)
z_final = np.empty(result_shape, np.float32)
# Modify this number if using more than 1 time per file
times_per_file = 1
data_times = []
xtimes = []
for timeidx in range(result_shape[0]):
# Compute the file index and the time index inside the file
fileidx = timeidx // times_per_file
file_timeidx = timeidx % times_per_file
f = Dataset(filename_list[fileidx])
z = getvar(f, "T2", file_timeidx)
t = getvar(f, "Times", file_timeidx)
xt = getvar(f, "xtimes", file_timeidx)
data_times.append(to_np(t))
xtimes.append(to_np(xt))
z_final[timeidx, :] = z[:]
f.close()
# Let's make the metadata. Dimension names should copy easily if you set
# sqeeze to False, otherwise you can just set them yourself is a tuple of
# dimension names. Since you wanted
# to keep the bottom_top dimension for this 2D variable (which is normally
# removed), I'm doing this manually.
z_dims = ["Time", "bottom_top", "south_north", "west_east"]
# Xarray doesn't copy coordinates easily (it always complains about shape
# mismatches), so do this manually
z_coords = {}
z_coords["Time"] = data_times
z_coords["XTIME"] = ("Time",), xtimes
z_coords["XLAT"] = ("south_north", "west_east"), xlat
z_coords["XLONG"] = ("south_north", "west_east"), xlong
z_name = "T2"
# Attributes copy nicely
z_attrs = {}
z_attrs.update(z1.attrs)
z_with_meta = xarray.DataArray(z_final, coords=z_coords, dims=z_dims,
attrs=z_attrs, name=z_name)

35
test/mocktest.py → test/misc/mocktest.py

@ -6,39 +6,48 @@ try: @@ -6,39 +6,48 @@ try:
except ImportError:
from mock import Mock as MagicMock
class Mock(MagicMock):
@classmethod
def __getattr__(cls, name):
return Mock()
MOCK_MODULES = ["numpy", "numpy.ma", "xarray", "cartopy",
"pandas", "matplotlib", "netCDF4", "mpl_toolkits.basemap",
"wrf._wrffortran"]
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
consts = {"DEFAULT_FILL" : 9.9692099683868690E36,
"DEFAULT_FILL_INT8" : -127,
"DEFAULT_FILL_INT16" : -32767,
"DEFAULT_FILL_INT32" : -2147483647,
"DEFAULT_FILL_INT64" : -9223372036854775806,
"DEFAULT_FILL_FLOAT" : 9.9692099683868690E36,
"DEFAULT_FILL_DOUBLE" : 9.9692099683868690E36,
"fomp_sched_static" : 1,
"fomp_sched_dynamic" : 2,
"fomp_sched_guided" : 3,
"fomp_sched_auto" : 4}
consts = {"DEFAULT_FILL": 9.9692099683868690E36,
"DEFAULT_FILL_INT8": -127,
"DEFAULT_FILL_INT16": -32767,
"DEFAULT_FILL_INT32": -2147483647,
"DEFAULT_FILL_INT64": -9223372036854775806,
"DEFAULT_FILL_FLOAT": 9.9692099683868690E36,
"DEFAULT_FILL_DOUBLE": 9.9692099683868690E36,
"fomp_sched_static": 1,
"fomp_sched_dynamic": 2,
"fomp_sched_guided": 3,
"fomp_sched_auto": 4}
class MockWrfConstants(object):
def __init__(self):
self.__dict__ = consts
def mock_asscalar(val):
return float(val)
sys.modules["wrf._wrffortran"].wrf_constants = MockWrfConstants()
sys.modules["wrf._wrffortran"].omp_constants = MockWrfConstants()
sys.modules["numpy"].asscalar = mock_asscalar
import wrf
print (wrf.get_coord_pairs.__doc__)
try:
import wrf
except ImportError:
pass
print(wrf.get_coord_pairs.__doc__)

124
test/projtest.py → test/misc/projtest.py

@ -7,6 +7,8 @@ import matplotlib.cm as cm @@ -7,6 +7,8 @@ import matplotlib.cm as cm
from netCDF4 import Dataset as NetCDF
from wrf import get_proj_params
from wrf.projection import getproj, RotatedLatLon, PolarStereographic
PYNGL = True
try:
@ -27,15 +29,11 @@ except ImportError: @@ -27,15 +29,11 @@ except ImportError:
CARTOPY = False
from wrf import get_proj_params
from wrf.projection import getproj, RotatedLatLon, PolarStereographic
FILE_DIR = "/Users/ladwig/Documents/wrf_files/"
WRF_FILES = [
join(FILE_DIR, "norway", "geo_em.d01.nc"),
WRF_FILES = [join(FILE_DIR, "norway", "geo_em.d01.nc"),
join(FILE_DIR, "rotated_pole", "EAS_geo_em.d01.nc"),
join(FILE_DIR, "rotated_pole", "EUR_geo_em.d01.nc"),
join(FILE_DIR,"wrfout_d01_2016-02-25_18_00_00"),
join(FILE_DIR, "wrfout_d01_2016-02-25_18_00_00"),
join(FILE_DIR, "wrfout_d01_2008-09-29_23-30-00"),
join(FILE_DIR, "wrfout_d01_2010-06-13_21:00:00")]
@ -46,63 +44,66 @@ def nz_proj(): @@ -46,63 +44,66 @@ def nz_proj():
lons = np.array([[163.839595, -179.693502],
[163.839595, -179.693502]])
params = {"MAP_PROJ" : 6,
"CEN_LAT" : -41.814869,
"CEN_LON" : 179.693502,
"TRUELAT1" : 0,
params = {"MAP_PROJ": 6,
"CEN_LAT": -41.814869,
"CEN_LON": 179.693502,
"TRUELAT1": 0,
"TRUELAT2": 0,
"MOAD_CEN_LAT" : -41.814869,
"STAND_LON" : 180.0 - 179.693502,
"POLE_LAT" : 48.185131,
"POLE_LON" : 0.0}
"MOAD_CEN_LAT": -41.814869,
"STAND_LON": 180.0 - 179.693502,
"POLE_LAT": 48.185131,
"POLE_LON": 0.0}
return lats, lons, RotatedLatLon(lats=lats, lons=lons, **params)
def argentina_proj():
lats = np.array([[-57.144064, -57.144064],
[-21.154470, -21.154470]])
lons = np.array([[-86.893797, -37.089724],
[-86.893797, -37.089724]])
params = {"MAP_PROJ" : 6,
"CEN_LAT" : -39.222954,
"CEN_LON" : -65.980109,
"TRUELAT1" : 0,
params = {"MAP_PROJ": 6,
"CEN_LAT": -39.222954,
"CEN_LON": -65.980109,
"TRUELAT1": 0,
"TRUELAT2": 0,
"MOAD_CEN_LAT" : -39.222954,
"STAND_LON" : 180.0 - -65.980109,
"POLE_LAT" : 90 + -39.222954,
"POLE_LON" : 0.0}
"MOAD_CEN_LAT": -39.222954,
"STAND_LON": 180.0 - -65.980109,
"POLE_LAT": 90 + -39.222954,
"POLE_LON": 0.0}
return lats, lons, RotatedLatLon(lats=lats, lons=lons, **params)
def south_polar_proj():
lats = np.array([[-30.0,-30.0],
[-30.0,-30.0]])
lats = np.array([[-30.0, -30.0],
[-30.0, -30.0]])
lons = np.array([[-120, 60],
[-120, 60]])
params = {"MAP_PROJ" : 2,
"CEN_LAT" : -90.0,
"CEN_LON" : 0,
"TRUELAT1" : -10.0,
"MOAD_CEN_LAT" : -90.0,
"STAND_LON" : 0}
params = {"MAP_PROJ": 2,
"CEN_LAT": -90.0,
"CEN_LON": 0,
"TRUELAT1": -10.0,
"MOAD_CEN_LAT": -90.0,
"STAND_LON": 0}
return lats, lons, PolarStereographic(lats=lats, lons=lons, **params)
def north_polar_proj():
lats = np.array([[30.0,30.0],
[30.0,30.0]])
lats = np.array([[30.0, 30.0],
[30.0, 30.0]])
lons = np.array([[-45, 140],
[-45, 140]])
params = {"MAP_PROJ" : 2,
"CEN_LAT" : 90.0,
"CEN_LON" : 10,
"TRUELAT1" : 10.0,
"MOAD_CEN_LAT" : 90.0,
"STAND_LON" : 10}
params = {"MAP_PROJ": 2,
"CEN_LAT": 90.0,
"CEN_LON": 10,
"TRUELAT1": 10.0,
"MOAD_CEN_LAT": 90.0,
"STAND_LON": 10}
return lats, lons, PolarStereographic(lats=lats, lons=lons, **params)
@ -113,20 +114,22 @@ def dateline_rot_proj(): @@ -113,20 +114,22 @@ def dateline_rot_proj():
lons = np.array([[170.332771, -153.456292],
[170.332771, -153.456292]])
params = {"MAP_PROJ" : 6,
"CEN_LAT" : 66.335764,
"CEN_LON" : -173.143792,
"TRUELAT1" : 0,
params = {"MAP_PROJ": 6,
"CEN_LAT": 66.335764,
"CEN_LON": -173.143792,
"TRUELAT1": 0,
"TRUELAT2": 0,
"MOAD_CEN_LAT" : 66.335764,
"STAND_LON" : 173.143792,
"POLE_LAT" : 90.0 - 66.335764,
"POLE_LON" : 180.0}
"MOAD_CEN_LAT": 66.335764,
"STAND_LON": 173.143792,
"POLE_LAT": 90.0 - 66.335764,
"POLE_LON": 180.0}
return lats, lons, RotatedLatLon(lats=lats, lons=lons, **params)
class WRFProjTest(ut.TestCase):
longMessage = True
def make_test(wrf_file=None, fixed_case=None):
if wrf_file is not None:
ncfile = NetCDF(wrf_file)
@ -144,22 +147,22 @@ def make_test(wrf_file=None, fixed_case=None): @@ -144,22 +147,22 @@ def make_test(wrf_file=None, fixed_case=None):
elif fixed_case == "north_polar":
lats, lons, proj = north_polar_proj()
elif fixed_case == "dateline_rot":
lats,lons,proj = dateline_rot_proj()
lats, lons, proj = dateline_rot_proj()
print ("wrf proj4: {}".format(proj.proj4()))
print("wrf proj4: {}".format(proj.proj4()))
if PYNGL:
# PyNGL plotting
wks_type = bytes("png")
wks = Ngl.open_wks(wks_type,bytes("pyngl_{}".format(name_suffix)))
wks = Ngl.open_wks(wks_type, bytes("pyngl_{}".format(name_suffix)))
mpres = proj.pyngl()
map = Ngl.map(wks,mpres)
map = Ngl.map(wks, mpres)
Ngl.delete_wks(wks)
if BASEMAP:
# Basemap plotting
fig = plt.figure(figsize=(10,10))
ax = fig.add_axes([0.1,0.1,0.8,0.8])
fig = plt.figure(figsize=(10, 10))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
# Define and plot the meridians and parallels
min_lat = np.amin(lats)
@ -174,27 +177,28 @@ def make_test(wrf_file=None, fixed_case=None): @@ -174,27 +177,28 @@ def make_test(wrf_file=None, fixed_case=None):
bm = proj.basemap()
bm.drawcoastlines(linewidth=.5)
#bm.drawparallels(parallels,labels=[1,1,1,1],fontsize=10)
#bm.drawmeridians(meridians,labels=[1,1,1,1],fontsize=10)
print ("basemap proj4: {}".format(bm.proj4string))
# bm.drawparallels(parallels,labels=[1,1,1,1],fontsize=10)
# bm.drawmeridians(meridians,labels=[1,1,1,1],fontsize=10)
print("basemap proj4: {}".format(bm.proj4string))
plt.savefig("basemap_{}.png".format(name_suffix))
plt.close(fig)
if CARTOPY:
# Cartopy plotting
fig = plt.figure(figsize=(10,10))
ax = plt.axes([0.1,0.1,0.8,0.8], projection=proj.cartopy())
print ("cartopy proj4: {}".format(proj.cartopy().proj4_params))
fig = plt.figure(figsize=(10, 10))
ax = plt.axes([0.1, 0.1, 0.8, 0.8], projection=proj.cartopy())
print("cartopy proj4: {}".format(proj.cartopy().proj4_params))
ax.coastlines('50m', linewidth=0.8)
#print proj.x_extents()
#print proj.y_extents()
# print proj.x_extents()
# print proj.y_extents()
ax.set_xlim(proj.cartopy_xlim())
ax.set_ylim(proj.cartopy_ylim())
ax.gridlines()
plt.savefig("cartopy_{}.png".format(name_suffix))
plt.close(fig)
if __name__ == "__main__":
for wrf_file in WRF_FILES:
test_func = make_test(wrf_file=wrf_file)

58
test/misc/quiver_test.py

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
from netCDF4 import Dataset
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.cm import get_cmap
import cartopy.crs as crs
from cartopy.feature import NaturalEarthFeature
from wrf import (getvar, interplevel, to_np, latlon_coords, get_cartopy,
cartopy_xlim, cartopy_ylim)
# Open the NetCDF file
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00")
# Extract the pressure and wind variables
p = getvar(ncfile, "pressure")
# Note: This is m/s.
ua = getvar(ncfile, "ua")
va = getvar(ncfile, "va")
# Interpolate u, and v winds to 950 hPa
u_950 = interplevel(ua, p, 950)
v_950 = interplevel(va, p, 950)
# Get the lat/lon coordinates
lats, lons = latlon_coords(u_950)
# Get the map projection information
cart_proj = get_cartopy(u_950)
# Create the figure
fig = plt.figure(figsize=(12, 9))
ax = plt.axes(projection=cart_proj)
# Download and add the states and coastlines
states = NaturalEarthFeature(category='cultural', scale='50m',
facecolor='none',
name='admin_1_states_provinces_shp')
ax.add_feature(states, linewidth=0.5)
ax.coastlines('50m', linewidth=0.8)
# Add the 950 hPa wind barbs, only plotting every 'thin'ed barb. Adjust thin
# as needed. Also, no scaling is done for the arrows, so you might need to
# mess with the scale argument.
thin = 50
plt.quiver(to_np(lons[::thin, ::thin]), to_np(lats[::thin, ::thin]),
to_np(u_950[::thin, ::thin]), to_np(v_950[::thin, ::thin]),
transform=crs.PlateCarree())
# Set the map bounds
ax.set_xlim(cartopy_xlim(u_950))
ax.set_ylim(cartopy_ylim(v_950))
ax.gridlines()
plt.title("Arrows")
plt.show()

0
test/reduce_file.py → test/misc/reduce_file.py

29
test/misc/snippet.py

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
def main():
bm = Basemap(projection="rotpole",
o_lat_p=36.0,
o_lon_p=180.0,
llcrnrlat=-10.590603,
urcrnrlat=46.591976,
llcrnrlon=-139.08585,
urcrnrlon=22.661009,
lon_0=-106.0,
rsphere=6370000,
resolution='l')
fig = plt.figure(figsize=(8, 8))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
bm.drawcoastlines(linewidth=.5)
print(bm.proj4string)
plt.savefig("basemap_map.png")
plt.close(fig)
if __name__ == "__main__":
main()

18
test/varcache.py → test/misc/varcache.py

@ -4,13 +4,18 @@ import time @@ -4,13 +4,18 @@ import time
from netCDF4 import Dataset
from wrf import getvar, ALL_TIMES, extract_vars
wrf_filenames = ["/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_2005-08-28_00:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_2005-08-28_12:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_2005-08-29_00:00:00"]
wrf_filenames = ["/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/"
"moving_nest/wrfout_d02_2005-08-28_00:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/"
"moving_nest/wrfout_d02_2005-08-28_12:00:00",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/"
"moving_nest/wrfout_d02_2005-08-29_00:00:00"]
wrfin = [Dataset(x) for x in wrf_filenames]
my_cache = extract_vars(wrfin, ALL_TIMES, ("P", "PB", "PH", "PHB", "T", "QVAPOR", "HGT", "U", "V", "W", "PSFC"))
my_cache = extract_vars(wrfin, ALL_TIMES,
("P", "PB", "PH", "PHB", "T", "QVAPOR", "HGT", "U",
"V", "W", "PSFC"))
start = time.time()
for var in ("avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz",
@ -21,7 +26,7 @@ for var in ("avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz", @@ -21,7 +26,7 @@ for var in ("avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz",
v = getvar(wrfin, var, ALL_TIMES)
end = time.time()
print ("Time taken without variable cache: ", (end-start))
print("Time taken without variable cache: ", (end-start))
start = time.time()
for var in ("avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz",
@ -32,5 +37,4 @@ for var in ("avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz", @@ -32,5 +37,4 @@ for var in ("avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz",
v = getvar(wrfin, var, ALL_TIMES, cache=my_cache)
end = time.time()
print ("Time taken with variable cache: ", (end-start))
print("Time taken with variable cache: ", (end-start))

19
test/viewtest.py → test/misc/viewtest.py

@ -1,26 +1,25 @@ @@ -1,26 +1,25 @@
# Test snippet for f2py
import numpy as np
import wrf._wrffortran
errlen = int(wrf._wrffortran.constants.errlen)
a = np.ones((3,3,3))
b = np.zeros((3,3,3,3))
a = np.ones((3, 3, 3))
b = np.zeros((3, 3, 3, 3))
c = np.zeros(errlen, "c")
errstat = np.array(0)
errmsg = np.zeros(errlen, "c")
c[:] = "Test String"
for i in xrange(2):
outview = b[i,:]
outview = b[i, :]
outview = outview.T
q = wrf._wrffortran.testfunc(a,outview,c,errstat=errstat,errmsg=errmsg)
print errstat
q = wrf._wrffortran.testfunc(a, outview, c, errstat=errstat,
errmsg=errmsg)
print(errstat)
str_bytes = (bytes(char).decode("utf-8") for char in errmsg[:])
print repr(errmsg)
print "".join(str_bytes).strip()
print(repr(errmsg))
print("".join(str_bytes).strip())

230
test/misc/wps.py

@ -0,0 +1,230 @@ @@ -0,0 +1,230 @@
# Hastily made script to read WPS intermediate files
from __future__ import print_function
import struct
import numpy as np
# Number of bytes used at the start and end of a fortran record to
# indicate the record size
SIZE_BYTES = 4
class WPSData(object):
def __init__(self, ifv=None, hdate=None, xfcst=None, map_source=None,
field=None, units=None, desc=None, xlvl=None, nx=None,
ny=None, iproj=None, startloc=None, startlat=None,
startlon=None, deltalat=None, deltalon=None, nlats=None,
dx=None, dy=None, xlonc=None, truelat1=None, truelat2=None,
earth_radius=None, is_wind_earth_rel=None, slab=None):
self.ifv = ifv
self.hdate = hdate
self.xfcst = xfcst
self.map_source = map_source
self.field = field
self.units = units
self.desc = desc
self.xlvl = xlvl
self.nx = nx
self.ny = ny
self.iproj = iproj
self.startloc = startloc
self.startlat = startlat
self.startlon = startlon
self.deltalat = deltalat
self.deltalon = deltalon
self.nlats = nlats
self.dx = dx
self.dy = dy
self.xlonc = xlonc
self.truelat1 = truelat1
self.truelat2 = truelat2
self.earth_radius = earth_radius
self.is_wind_earth_rel = is_wind_earth_rel
self.slab = slab
def _parse_record1(data):
result = {}
result["ifv"] = struct.unpack(">i", data)
return result
def _parse_record2(data):
result = {}
parsed = struct.unpack(">24sf32s9s25s46sfiii", data)
result["hdate"] = parsed[0]
result["xfcst"] = parsed[1]
result["map_source"] = parsed[2]
result["field"] = parsed[3]
result["units"] = parsed[4]
result["desc"] = parsed[5]
result["xlvl"] = parsed[6]
result["nx"] = parsed[7]
result["ny"] = parsed[8]
result["iproj"] = parsed[9]
return result
def _parse_record3(data, iproj):
result = {}
if iproj == 0:
fmt = ">8sfffff"
parsed = struct.unpack(fmt, data)
result["startloc"] = parsed[0]
result["startlat"] = parsed[1]
result["startlon"] = parsed[2]
result["deltalat"] = parsed[3]
result["deltalon"] = parsed[4]
result["earth_radius"] = parsed[5]
elif iproj == 1:
fmt = ">8sffffff"
parsed = struct.unpack(fmt, data)
result["startloc"] = parsed[0]
result["startlat"] = parsed[1]
result["startlon"] = parsed[2]
result["dx"] = parsed[3]
result["dy"] = parsed[4]
result["truelat1"] = parsed[5]
result["earth_radius"] = parsed[6]
elif iproj == 3:
fmt = ">8sffffffff"
parsed = struct.unpack(fmt, data)
result["startloc"] = parsed[0]
result["startlat"] = parsed[1]
result["startlon"] = parsed[2]
result["dx"] = parsed[3]
result["dy"] = parsed[4]
result["xlonc"] = parsed[5]
result["truelat1"] = parsed[6]
result["truelat2"] = parsed[7]
result["earth_radius"] = parsed[8]
elif iproj == 4:
fmt = ">8sfffff"
parsed = struct.unpack(fmt, data)
result["startloc"] = parsed[0]
result["startlat"] = parsed[1]
result["startlon"] = parsed[2]
result["nlats"] = parsed[3]
result["deltalon"] = parsed[4]
result["earth_radius"] = parsed[5]
elif iproj == 5:
fmt = ">8sfffffff"
parsed = struct.unpack(fmt, data)
result["startloc"] = parsed[0]
result["startlat"] = parsed[1]
result["startlon"] = parsed[2]
result["dx"] = parsed[3]
result["dy"] = parsed[4]
result["xlonc"] = parsed[5]
result["truelat1"] = parsed[6]
result["earth_radius"] = parsed[7]
return result
def _parse_record4(data):
result = {}
result["is_wind_earth_rel"] = struct.unpack(">i", data)
return result
def _parse_record5(data, nx, ny):
result = {}
size = nx * ny
fmt = ">{}f".format(size)
parsed = struct.unpack(fmt, data)
arr = np.array(parsed, dtype=np.float32)
result["slab"] = arr.reshape((nx, ny), order="F")
return result
_PARSE_MAP = {0: _parse_record1,
1: _parse_record2,
2: _parse_record3,
3: _parse_record4,
4: _parse_record5}
def parse_record(record_idx, data, iproj=None, nx=None, ny=None):
if record_idx == 0 or record_idx == 1 or record_idx == 3:
return _PARSE_MAP[record_idx](data)
elif record_idx == 2:
return _PARSE_MAP[record_idx](data, iproj)
elif record_idx == 4:
return _PARSE_MAP[record_idx](data, nx, ny)
def read_wps(wps_file, field=None):
with open(wps_file, "rb") as f:
wps_params = {}
record_list = []
raw_data = f.read()
record_size_idx = 0
end_of_file_idx = len(raw_data) - 1
while True:
iproj = None
nx = None
ny = None
keep_record = True
for record_idx in range(5):
# Each record has the size (in SIZE_BYTES bytes) at the
# start and end of each record. This might be compiler
# dependent though, so this might need to be modified.
# Also, the WPS files are stored big endian.
record_size = struct.unpack(
">i",
raw_data[record_size_idx: record_size_idx + SIZE_BYTES])
record_start = record_size_idx + SIZE_BYTES
record_end = record_start + record_size[0]
record_data = raw_data[record_start:record_end]
parsed_record = parse_record(record_idx, record_data, iproj,
nx, ny)
try:
field_name = parsed_record["field"].strip()
except KeyError:
pass
else:
if field is not None:
if field_name != field:
keep_record = False
try:
iproj = parsed_record["iproj"]
except KeyError:
pass
try:
nx = parsed_record["nx"]
except KeyError:
pass
try:
ny = parsed_record["ny"]
except KeyError:
pass
wps_params.update(parsed_record)
record_size_idx = record_end + SIZE_BYTES
if keep_record:
record_list.append(WPSData(**wps_params))
# Repeat for all record slabs
if record_end + SIZE_BYTES > end_of_file_idx:
break
return record_list

0
test/listBug.ncl → test/ncl/listBug.ncl

30
test/ncl_get_var.ncl → test/ncl/ncl_get_var.ncl

@ -32,7 +32,9 @@ @@ -32,7 +32,9 @@
"geopt", "helicity", "lat", "lon", "omg", "p", "pressure", \
"pvo", "pw", "rh2", "rh", "slp", "ter", "td2", "td", "tc", \
"theta", "tk", "tv", "twb", "updraft_helicity", "ua", "va", \
"wa", "uvmet10", "uvmet", "z", "cfrac", "height_agl" /]
"wa", "uvmet10", "uvmet", "z", "cfrac", "height_agl", \
"wspd_wdir", "wspd_wdir10", "uvmet_wspd_wdir", \
"uvmet10_wspd_wdir" /]
unique_dimname_list = NewList("fifo")
unique_dimsize_list = NewList("fifo")
@ -87,7 +89,7 @@ @@ -87,7 +89,7 @@
xopt@timeidx = time
xopt@linecoords = True
ht_vertcross1 = wrf_user_vertcross(z, p, pivot, xopt)
ht_vertcross1 = wrf_user_vert_cross(z, p, pivot, xopt)
fout->ht_vertcross1 = ht_vertcross1
@ -100,7 +102,7 @@ @@ -100,7 +102,7 @@
xopt@timeidx = time
xopt@linecoords = True
ht_vertcross2 = wrf_user_vertcross(z, p, pivot, xopt)
ht_vertcross2 = wrf_user_vert_cross(z, p, pivot, xopt)
ht_vertcross2!1 = "vertical2"
ht_vertcross2!2 = "cross_line_idx2"
@ -131,7 +133,7 @@ @@ -131,7 +133,7 @@
xopt@linecoords = True
xopt@autolevels = 1000
ht_vertcross3 = wrf_user_vertcross(z, p, start_end, xopt)
ht_vertcross3 = wrf_user_vert_cross(z, p, start_end, xopt)
ht_vertcross3!0 = "Time"
ht_vertcross3!1 = "vertical3"
@ -150,7 +152,7 @@ @@ -150,7 +152,7 @@
p_var := p(i,:,:,:)
z_var := z(i,:,:,:)
ht_vertcross := wrf_user_vertcross(z_var, p_var, start_end, xopt)
ht_vertcross := wrf_user_vert_cross(z_var, p_var, start_end, xopt)
dim0name = sprinti("vertical_t%i",i)
dim1name = sprinti("cross_line_idx_t%i",i)
@ -190,8 +192,8 @@ @@ -190,8 +192,8 @@
plev := 500. ; 500 MB
hlev := 5000 ; 5000 m
z2_500 = wrf_user_interplevel(z,p,plev,False)
p2_5000 = wrf_user_interplevel(p,z,hlev,False)
z2_500 = wrf_user_interp_level(z,p,plev,False)
p2_5000 = wrf_user_interp_level(p,z,hlev,False)
fout->z2_500 = z2_500
fout->p2_5000 = p2_5000
@ -199,8 +201,8 @@ @@ -199,8 +201,8 @@
plev := (/1000., 850., 500., 250./)
hlev := (/500., 2500., 5000., 10000. /)
z2_multi = wrf_user_interplevel(z,p,plev,False)
p2_multi = wrf_user_interplevel(p,z,hlev,False)
z2_multi = wrf_user_interp_level(z,p,plev,False)
p2_multi = wrf_user_interp_level(p,z,hlev,False)
fout->z2_multi = z2_multi
fout->p2_multi = p2_multi
@ -208,7 +210,7 @@ @@ -208,7 +210,7 @@
pblh = wrf_user_getvar(input_file, "PBLH", time)
opts := False
opts@inc2dlevs = True
p_lev2d = wrf_user_interplevel(p, z, pblh, opts)
p_lev2d = wrf_user_interp_level(p, z, pblh, opts)
fout->p_lev2d = p_lev2d
@ -234,7 +236,7 @@ @@ -234,7 +236,7 @@
xopt@timeidx = 0
xopt@linecoords = True
t2_line2 = wrf_user_interpline(t2, pivot, xopt)
t2_line2 = wrf_user_interp_line(t2, pivot, xopt)
fout->t2_line2 = t2_line2
@ -257,7 +259,7 @@ @@ -257,7 +259,7 @@
xopt@timeidx = 0
xopt@linecoords = True
t2_line3 = wrf_user_interpline(t2, start_end, xopt)
t2_line3 = wrf_user_interp_line(t2, start_end, xopt)
t2_line3!1 = "line_idx_t2_line3"
fout->t2_line3 = t2_line3
@ -270,7 +272,7 @@ @@ -270,7 +272,7 @@
name = sprinti("t2_line_t%i", i)
dim0name = sprinti("lineidx_t%i",i)
var := t2(i,:,:)
t2_line := wrf_user_interpline(var, start_end, xopt)
t2_line := wrf_user_interp_line(var, start_end, xopt)
t2_line!0 = dim0name
fout->$name$ = t2_line
end do
@ -286,7 +288,7 @@ @@ -286,7 +288,7 @@
xopt@timeidx = 0
xopt@linecoords = True
t2_line4 = wrf_user_interpline(t2, start_end, xopt)
t2_line4 = wrf_user_interp_line(t2, start_end, xopt)
t2_line4!0 = "t2_line4_idx"
fout->t2_line4 = t2_line4

92
test/ncl/ncl_vertcross.ncl

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
input_file = addfile("/Users/ladwig/Documents/wrf_files/wrfout_d02_2010-06-13_21:00:00.nc", "r")
z = wrf_user_getvar(input_file, "z", 0) ; grid point height
p = wrf_user_getvar(input_file, "pressure", 0) ; total pressure
dimsz = dimsizes(z)
pivot = (/ (dimsz(2)-1)/2, (dimsz(1)-1)/2 /) ; pivot point is center of domain
; For the new cross section routine
xopt = True
xopt@use_pivot = True
xopt@angle = 45.0
;xopt@levels =
;xopt@latlon =
xopt@file_handle = input_file
;xopt@timeidx =
xopt@linecoords = True
ht_vertcross = wrf_user_vertcross(z, p, pivot, xopt)
printVarSummary(ht_vertcross)
print(min(ht_vertcross@lats))
print(min(ht_vertcross@lons))
print(max(ht_vertcross@lats))
print(max(ht_vertcross@lons))
xopt@use_pivot = False
xopt@angle = 0.0
;xopt@levels =
xopt@latlon = True
xopt@file_handle = input_file
xopt@timeidx = 0
xopt@linecoords = True
loc_param = (/-104.3632, 32.8562, -95.15308, 40.06575 /) ; pivot point is center of domain
ht_vertcross2 = wrf_user_vertcross(z, p, loc_param, xopt)
printVarSummary(ht_vertcross2)
print(min(ht_vertcross2@lats))
print(min(ht_vertcross2@lons))
print(max(ht_vertcross2@lats))
print(max(ht_vertcross2@lons))
print(ht_vertcross2@lats(190))
print(ht_vertcross2@lons(190))
xopt@use_pivot = True
xopt@angle = 45.0
;xopt@levels =
xopt@latlon = True
xopt@file_handle = input_file
xopt@timeidx = 0
xopt@linecoords = True
loc_param := (/-99.98572, 36.54949 /) ; pivot point is center of domain
ht_vertcross3 = wrf_user_vertcross(z, p, loc_param, xopt)
printVarSummary(ht_vertcross3)
print(min(ht_vertcross3@lats))
print(min(ht_vertcross3@lons))
print(max(ht_vertcross3@lats))
print(max(ht_vertcross3@lons))
xopt@use_pivot = True
xopt@angle = 45.0
xopt@levels = (/1000., 850., 700., 500., 250. /)
xopt@latlon = True
xopt@file_handle = input_file
xopt@timeidx = 0
xopt@linecoords = True
loc_param := (/-99.98572, 36.54949 /) ; pivot point is center of domain
ht_vertcross4 = wrf_user_vertcross(z, p, loc_param, xopt)
printVarSummary(ht_vertcross4)
print(min(ht_vertcross4@lats))
print(min(ht_vertcross4@lons))
print(max(ht_vertcross4@lats))
print(max(ht_vertcross4@lons))
o = True
o@returnInt = False
o@useTime = 0
l = wrf_user_ll_to_xy(input_file, -99.98572, 36.54949, o)
print(l)
l1 = wrf_user_xy_to_ll(input_file, l(1), l(0), o)
print(l1)

81
test/ncl/refl10_cross.ncl

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
a = addfile("wrfout_d03_2017-04-03_06:00:00_ctrl","r")
time = 0
refl_10cm = wrf_user_getvar(a,"REFL_10CM",time)
z = wrf_user_getvar(a, "z", time)
lat = wrf_user_getvar(a, "lat", time)
lon = wrf_user_getvar(a, "lon", time)
; convert the lat/lon to x,y
start_lat = 20.9
start_lon = 92.5
end_lat = 29.2
end_lon = 92.5
opt = True
start_ij = wrf_user_ll_to_ij(a, start_lon, start_lat, opt)
start_ij = start_ij - 1
end_ij = wrf_user_ll_to_ij(a, end_lon, end_lat, opt)
end_ij = end_ij - 1
start_end = (/start_ij(0), start_ij(1), end_ij(0), end_ij(1)/)
lat_line = wrf_user_intrp2d(lat,start_end,0.0,True)
nlat = dimsizes(lat_line)
lon_line = wrf_user_intrp2d(lon,start_end,0.0,True)
refl_cross = wrf_user_intrp3d(refl_10cm,z,"v",start_end,0.,True)
; Need to make a vertical coordinate by using the same code as the
; cross section
; Currently, the vertical coordinate is not set, so let's do it
; manually. This will be fixed in the next version of NCL.
; If you want to set these levels yourself, you'll need to copy the
; code I sent before and manually set the levels in the cross section
; routine, then do it again here.
z_max = max(z)
z_min = 0.
dz = 0.01 * z_max
nlevels = tointeger( z_max/dz )
z_var2d = new( (/nlevels/), typeof(z))
z_var2d(0) = z_min
do i=1, nlevels-1
z_var2d(i) = z_var2d(0)+i*dz
end do
refl_cross&Vertical = z_var2d
wks = gsn_open_wks("png","cross")
cmap := read_colormap_file("BlAqGrYeOrReVi200")
cmap(0,:) = (/0,0,0,0/) ; make first color fully transparent
resx = True
resx@gsnMaximize = True
resx@lbLabelAutoStride = True ; default v6.1.0
resx@cnFillOn = True ; turn on color fill
resx@cnLinesOn = False ; turn lines on/off ; True is default
resx@cnLineLabelsOn = False ; turn line labels on/off ; True is default
resx@cnFillPalette = cmap
nLabels = 8 ; arbitrary
resx@tmXBLabels = new(nLabels,"string")
resx@tmXBMode = "Explicit"
resx@tmXBValues := toint(fspan(0,nlat-1,nLabels))
do i=0,nLabels-1
x = lon_line(i)
y = lat_line(i)
resx@tmXBLabels(i) = sprintf("%5.1f", y)+"~C~"+sprintf("%5.1f", x)
end do
resx@tiMainString = "Full South-North Grid Line X-Section"
plot1 = gsn_csm_contour(wks, refl_cross, resx )

26
test/ncl/rotated_test.ncl

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
;---Open file and calculate slp.
a = addfile("/Users/ladwig/Documents/wrf_files/rotated_pole_test.nc","r")
t2 = wrf_user_getvar(a,"T2",0)
;---Start the graphics
wks = gsn_open_wks("x11","wrf")
;---Set some graphical resources
res = True
res@gsnMaximize = True
res@cnFillOn = True
res@tfDoNDCOverlay = True ; This is necessary if you don't
; set sfXArray/sfYArray
;---Add additional map resources
res = wrf_map_resources(a,res)
;---Change some of the resources that were set (these were set to "gray")
res@mpGeophysicalLineColor = "black"
res@mpNationalLineColor = "black"
res@mpUSStateLineColor = "black"
plot = gsn_csm_contour_map(wks,t2,res)

21
test/ncl/test_this.ncl

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
ifils = systemfunc ("ls /Users/ladwig/Documents/wrf_files/wrf_vortex_single/wrfout_d02_*")
print(ifils)
a = addfiles(ifils, "r")
;a = addfile("/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00.nc", "r")
lats := (/22.0, 25.0, 27.0 /)
lons := (/-90.0, -87.5, -83.75 /)
opt = True
opt@useTime = -1
opt@returnI = False
xy = wrf_user_ll_to_xy(a, lons, lats, opt)
print(xy)
x_s = (/10, 50, 90 /)
y_s = (/10, 50, 90 /)
ll = wrf_user_xy_to_ll(a, x_s, y_s, opt)
print(ll)

0
test/test_vinterp.ncl → test/ncl/test_vinterp.ncl

416
test/ncl/wrf_user_vertcross.ncl

@ -0,0 +1,416 @@ @@ -0,0 +1,416 @@
;--------------------------------------------------------------------------------
undef("wrf_user_ll_to_xy")
function wrf_user_ll_to_xy( file_handle, longitude:numeric, latitude:numeric, \
opts_args:logical )
; This is the same as wrf_user_ll_to_ij, but returns 0-based indexes
begin
;
; As of NCL V6.0.0, wrf_user_ll_to_ij can now handle a file
; or a list of files.
;
if(typeof(file_handle).eq."file") then
ISFILE = True
nc_file = file_handle
elseif(typeof(file_handle).eq."list") then
ISFILE = False
nc_file = file_handle[0]
else
print("wrf_user_ll_to_xy: Error: the first argument must be a file or a list of files opened with addfile or addfiles")
return
end if
opts = opts_args
useT = get_res_value(opts,"useTime",0)
returnI= get_res_value(opts,"returnInt",True)
res = True
res@MAP_PROJ = nc_file@MAP_PROJ
res@TRUELAT1 = nc_file@TRUELAT1
res@TRUELAT2 = nc_file@TRUELAT2
res@STAND_LON = nc_file@STAND_LON
res@DX = nc_file@DX
res@DY = nc_file@DY
if (res@MAP_PROJ .eq. 6) then
res@POLE_LAT = nc_file@POLE_LAT
res@POLE_LON = nc_file@POLE_LON
res@LATINC = (res@DY*360.)/2.0/3.141592653589793/6370000.
res@LONINC = (res@DX*360.)/2.0/3.141592653589793/6370000.
else
res@POLE_LAT = 90.0
res@POLE_LON = 0.0
res@LATINC = 0.0
res@LONINC = 0.0
end if
if(isfilevar(nc_file,"XLAT"))
if(ISFILE) then
XLAT = nc_file->XLAT(useT,:,:)
XLONG = nc_file->XLONG(useT,:,:)
else
XLAT = file_handle[:]->XLAT
XLONG = file_handle[:]->XLONG
end if
else
if(ISFILE) then
XLAT = nc_file->XLAT_M(useT,:,:)
XLONG = nc_file->XLONG_M(useT,:,:)
else
XLAT = file_handle[:]->XLAT_M
XLONG = file_handle[:]->XLONG_M
end if
end if
if(dimsizes(dimsizes(XLAT)).eq.2) then
; Rank 2
res@REF_LAT = XLAT(0,0)
res@REF_LON = XLONG(0,0)
else
; Rank 3
res@REF_LAT = XLAT(useT,0,0)
res@REF_LON = XLONG(useT,0,0)
end if
res@KNOWNI = 1.0
res@KNOWNJ = 1.0
loc = wrf_ll_to_ij (longitude, latitude, res)
loc = loc - 1
if (dimsizes(dimsizes(loc)) .eq. 1) then
loc!0 = "x_y"
elseif (dimsizes(dimsizes(loc)) .eq. 2) then
loc!0 = "x_y"
loc!1 = "idx"
else ; Not currently supported
loc!0 = "x_y"
loc!1 = "domain_idx"
loc!2 = "idx"
end if
if ( returnI ) then
loci = new(dimsizes(loc),integer)
;loci@_FillValue = default_fillvalue("integer") ; was -999
loci = tointeger(loc + .5)
loci!0 = loc!0
return(loci)
else
return(loc)
end if
end
;--------------------------------------------------------------------------------
undef("wrf_user_xy_to_ll")
function wrf_user_xy_to_ll( file_handle, x:numeric, y:numeric, \
opts_args:logical )
begin
;
; As of NCL V6.0.0, wrf_user_ll_to_ij can now handle a file
; or a list of files.
;
if(typeof(file_handle).eq."file") then
ISFILE = True
nc_file = file_handle
elseif(typeof(file_handle).eq."list") then
ISFILE = False
nc_file = file_handle[0]
else
print("wrf_user_xy_to_ll: Error: the first argument must be a file or a list of files opened with addfile or addfiles")
return
end if
opts = opts_args
useT = get_res_value(opts,"useTime",0)
res = True
res@MAP_PROJ = nc_file@MAP_PROJ
res@TRUELAT1 = nc_file@TRUELAT1
res@TRUELAT2 = nc_file@TRUELAT2
res@STAND_LON = nc_file@STAND_LON
res@DX = nc_file@DX
res@DY = nc_file@DY
if (res@MAP_PROJ .eq. 6) then
res@POLE_LAT = nc_file@POLE_LAT
res@POLE_LON = nc_file@POLE_LON
res@LATINC = (res@DY*360.)/2.0/3.141592653589793/6370000.
res@LONINC = (res@DX*360.)/2.0/3.141592653589793/6370000.
else
res@POLE_LAT = 90.0
res@POLE_LON = 0.0
res@LATINC = 0.0
res@LONINC = 0.0
end if
if(isfilevar(nc_file,"XLAT")) then
if(ISFILE) then
XLAT = nc_file->XLAT(useT,:,:)
XLONG = nc_file->XLONG(useT,:,:)
else
XLAT = file_handle[:]->XLAT
XLONG = file_handle[:]->XLONG
end if
else
if(ISFILE) then
XLAT = nc_file->XLAT_M(useT,:,:)
XLONG = nc_file->XLONG_M(useT,:,:)
else
XLAT = file_handle[:]->XLAT_M
XLONG = file_handle[:]->XLONG_M
end if
end if
if(dimsizes(dimsizes(XLAT)).eq.2) then
; Rank 2
res@REF_LAT = XLAT(0,0)
res@REF_LON = XLONG(0,0)
else
; Rank 3
res@REF_LAT = XLAT(useT,0,0)
res@REF_LON = XLONG(useT,0,0)
end if
res@KNOWNI = 1.0
res@KNOWNJ = 1.0
; Convert to 1-based indexes for Fortran
new_x = x + 1
new_y = y + 1
loc = wrf_ij_to_ll (new_x,new_y,res)
if (dimsizes(dimsizes(loc)) .eq. 1) then
loc!0 = "lon_lat"
elseif (dimsizes(dimsizes(loc)) .eq. 2) then
loc!0 = "lon_lat"
loc!1 = "idx"
else ; Not currently supported
loc!0 = "lon_lat"
loc!1 = "domain_idx"
loc!2 = "idx"
end if
return(loc)
end
;--------------------------------------------------------------------------------
undef("wrf_user_vertcross")
function wrf_user_vertcross(var3d:numeric, z_in:numeric, \
loc_param:numeric, opts:logical )
; var3d - 3d field to interpolate (all input fields must be unstaggered)
; z_in - interpolate to this field (either p/z)
; loc_param - an array of 4 values representing the start point and end point
; for the cross section (start_x, start_y, end_x, end_y) OR a single
; point when opt@use_pivot is True representing the pivot point.
; The values can be in grid coordinates or lat/lon coordinates
; (start_x = start_lon, start_y = start_lat, ...). If using
; lat/lon coordinates, then opt@latlon must be True.
; opts - optional arguments
; use_pivot - set to True to indicate that loc_param and angle are used,
; otherwise loc_param is set to 4 values to indicate a start and
; end point
; angle - an angle for vertical plots - 90 represent a WE cross section,
; ignored if use_pivot is False.
; levels - the vertical levels to use in the same units as z_in. Set to
; False to automatically generate the number of levels specified
; by autolevels.
; latlon - set to True if the values in loc_param are latitude and longitude
; values rather than grid values
; file_handle - must be set to a file handle when latlon is True or
; linecoords is True, otherwise this is ignored.
; timeidx - the time index to use for moving nests when latlon is True. Set
; to 0 if the nest is not moving.
; linecoords - set to True to include the latitude and longitude coordinates
; for the cross section line in the output attributes.
; autolevels - set to the desired number of levels when levels are
; selected automatically (default 100).
begin
use_pivot = get_res_value(opts, "use_pivot", False)
angle = get_res_value(opts, "angle", 0.0)
levels = get_res_value(opts, "levels", new(1,integer))
latlon = get_res_value(opts, "latlon", False)
file_handle = get_res_value(opts, "file_handle", 0)
timeidx = get_res_value(opts, "timeidx", 0)
linecoords = get_res_value(opts, "linecoords", False)
nlevels = get_res_value(opts, "autolevels", 100)
dims = dimsizes(var3d)
nd = dimsizes(dims)
dimX = dims(nd-1)
dimY = dims(nd-2)
dimZ = dims(nd-3)
if ( nd .eq. 4 ) then
z = z_in(0,:,:,:)
else
z = z_in
end if
; Convert latlon to xy coordinates
if (use_pivot) then
if (latlon) then
opt = True
opt@returnInt = True
opt@useTime = timeidx
ij := wrf_user_ll_to_xy(file_handle, loc_param(0), loc_param(1), opt)
start_x = ij(0)
start_y = ij(1)
else
start_x = loc_param(0)
start_y = loc_param(1)
end if
else
if (latlon) then
opt = True
opt@returnInt = True
opt@useTime = timeidx
ij := wrf_user_ll_to_xy(file_handle, (/ loc_param(0), loc_param(2) /), (/ loc_param(1), loc_param(3) /), opt)
start_x = ij(0,0)
start_y = ij(1,0)
end_x = ij(0,1)
end_y = ij(1,1)
else
start_x = loc_param(0)
start_y = loc_param(1)
end_x = loc_param(2)
end_y = loc_param(3)
end if
end if
; get the lat/lons along the cross section line if requested
; set the cross section line coordinates if requested
if (linecoords) then
latname = "XLAT"
lonname = "XLONG"
if(.not. isfilevar(file_handle,"XLAT")) then
if(isfilevar(file_handle,"XLAT_M")) then
latname = "XLAT_M"
lonname = "XLONG_M"
end if
end if
latvar = _get_wrf_var(file_handle, latname, timeidx)
lonvar = _get_wrf_var(file_handle, lonname, timeidx)
if (use_pivot) then
loc := (/start_x, start_y/)
linelats = wrf_user_intrp2d(latvar, loc, angle, False)
linelons = wrf_user_intrp2d(lonvar, loc, angle, False)
else
loc := (/start_x, start_y, end_x, end_y /)
linelats = wrf_user_intrp2d(latvar, loc, angle, True)
linelons = wrf_user_intrp2d(lonvar, loc, angle, True)
end if
end if
; set vertical cross section
; Note for wrf_user_set_xy, opt is False when pivot and angle used.
if (use_pivot) then
xy = wrf_user_set_xy( z, start_x, start_y, \ ; assumes 0-based indexing in v6.5.0
0.0, 0.0, angle, False )
else
xy = wrf_user_set_xy( z, start_x, start_y, \ ; assumes 0-based indexing in v6.5.0
end_x, end_y, \
angle, True)
end if
xp = dimsizes(xy)
; first we interp z
var2dz = wrf_interp_2d_xy( z, xy)
; interp to constant z grid
if (all(ismissing(levels))) then
if(var2dz(0,0) .gt. var2dz(1,0) ) then ; monotonically decreasing coordinate
z_max = floor(max(z)/10)*10 ; bottom value
z_min = ceil(min(z)/10)*10 ; top value
dz = (1.0/nlevels) * (z_max - z_min)
;nlevels = tointeger( (z_max-z_min)/dz)
z_var2d = new( (/nlevels/), typeof(z))
z_var2d(0) = z_max
dz = -dz
else
z_max = max(z)
z_min = 0.
dz = (1.0/nlevels) * z_max
;nlevels = tointeger( z_max/dz )
z_var2d = new( (/nlevels/), typeof(z))
z_var2d(0) = z_min
end if
do i=1, nlevels-1
z_var2d(i) = z_var2d(0)+i*dz
end do
else
z_var2d = levels
nlevels = dimsizes(z_var2d)
end if
; interp the variable
if ( dimsizes(dims) .eq. 4 ) then
var2d = new( (/dims(0), nlevels, xp(0)/), typeof(var2dz))
do it = 0,dims(0)-1
var2dtmp = wrf_interp_2d_xy( var3d(it,:,:,:), xy)
do i=0,xp(0)-1
var2d(it,:,i) = wrf_interp_1d( var2dtmp(:,i), var2dz(:,i), z_var2d)
end do
end do
var2d!0 = var3d!0
var2d!1 = "vertical"
var2d!2 = "cross_line_idx"
else
var2d = new( (/nlevels, xp(0)/), typeof(var2dz))
var2dtmp = wrf_interp_2d_xy( var3d, xy)
do i=0,xp(0)-1
var2d(:,i) = wrf_interp_1d( var2dtmp(:,i), var2dz(:,i), z_var2d)
end do
var2d!0 = "vertical"
var2d!1 = "cross_line_idx"
end if
st_x = tointeger(xy(0,0)) ; + 1 (removed 1-based indexing in 6.5.0)
st_y = tointeger(xy(0,1)) ; + 1
ed_x = tointeger(xy(xp(0)-1,0)) ; + 1
ed_y = tointeger(xy(xp(0)-1,1)) ; + 1
if (.not. use_pivot) then
var2d@Orientation = "Cross-Section: (" + \
st_x + "," + st_y + ") to (" + \
ed_x + "," + ed_y + ")"
else
var2d@Orientation = "Cross-Section: (" + \
st_x + "," + st_y + ") to (" + \
ed_x + "," + ed_y + ") ; center=(" + \
start_x + "," + start_y + \
") ; angle=" + angle
end if
if (linecoords) then
var2d@lats = linelats
var2d@lons = linelons
end if
var2d&vertical = z_var2d
return(var2d)
end

30
test/snippet.py

@ -1,30 +0,0 @@ @@ -1,30 +0,0 @@
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
def main():
bm = Basemap(projection = "rotpole",
o_lat_p = 36.0,
o_lon_p = 180.0,
llcrnrlat = -10.590603,
urcrnrlat = 46.591976,
llcrnrlon = -139.08585,
urcrnrlon = 22.661009,
lon_0 = -106.0,
rsphere = 6370000,
resolution = 'l')
fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0.1,0.1,0.8,0.8])
bm.drawcoastlines(linewidth=.5)
print bm.proj4string
plt.savefig("basemap_map.png")
plt.close(fig)
if __name__ == "__main__":
main()

52
test/test_filevars.py

@ -2,7 +2,8 @@ import unittest as ut @@ -2,7 +2,8 @@ import unittest as ut
import numpy.testing as nt
import numpy as np
import numpy.ma as ma
import os, sys
import os
import sys
import subprocess
from wrf import getvar, ALL_TIMES
@ -21,38 +22,39 @@ if sys.version_info > (3,): @@ -21,38 +22,39 @@ if sys.version_info > (3,):
class WRFFileVarsTest(ut.TestCase):
longMessage = True
def make_test(ncfiles, varname):
def test(self):
#import time
#very_start = time.time()
#start = time.time()
# import time
# very_start = time.time()
# start = time.time()
t1 = getvar(ncfiles, varname, 0)
#end = time.time()
#print ("t1: ", start-end)
#start = time.time()
# end = time.time()
# print("t1: ", start-end)
# start = time.time()
t2 = getvar(ncfiles, varname, 0, meta=False)
#end = time.time()
#print ("t2: ", start-end)
#start = time.time()
# end = time.time()
# print("t2: ", start-end)
# start = time.time()
t3 = getvar(ncfiles, varname, ALL_TIMES)
#end = time.time()
#print ("t3: ", start-end)
#start = time.time()
# end = time.time()
# print("t3: ", start-end)
# start = time.time()
t4 = getvar(ncfiles, varname, ALL_TIMES, meta=False)
#end = time.time()
#print ("t4: ", start-end)
#start = time.time()
# end = time.time()
# print("t4: ", start-end)
# start = time.time()
t5 = getvar(ncfiles, varname, ALL_TIMES, method="join")
#end = time.time()
#print ("t5: ", start-end)
#start = time.time()
# end = time.time()
# print("t5: ", start-end)
# start = time.time()
t6 = getvar(ncfiles, varname, ALL_TIMES, method="join", meta=False)
#end = time.time()
#print ("t6: ", start-end)
#start = time.time()
# end = time.time()
# print("t6: ", start-end)
# start = time.time()
#print ("Total Time: ", (end-start))
# print("Total Time: ", (end-start))
return test
@ -60,8 +62,8 @@ if __name__ == "__main__": @@ -60,8 +62,8 @@ if __name__ == "__main__":
from netCDF4 import Dataset
ncfiles = [Dataset(x) for x in TEST_FILES]
#import scipy.io
#ncfiles = [scipy.io.netcdf.netcdf_file(x) for x in TEST_FILES]
# import scipy.io
# ncfiles = [scipy.io.netcdf.netcdf_file(x) for x in TEST_FILES]
file_vars = ncfiles[0].variables.keys()

41
test/test_inputs.py

@ -17,6 +17,7 @@ TEST_FILES = [os.path.join(IN_DIR, "wrfout_d02_2005-08-28_00:00:00"), @@ -17,6 +17,7 @@ TEST_FILES = [os.path.join(IN_DIR, "wrfout_d02_2005-08-28_00:00:00"),
os.path.join(IN_DIR, "wrfout_d02_2005-08-28_12:00:00"),
os.path.join(IN_DIR, "wrfout_d02_2005-08-29_00:00:00")]
def wrfin_gen(wrf_in):
for x in wrf_in:
yield x
@ -51,6 +52,7 @@ def make_test(varname, wrf_in): @@ -51,6 +52,7 @@ def make_test(varname, wrf_in):
return test
def make_interp_test(varname, wrf_in):
def test(self):
@ -58,7 +60,7 @@ def make_interp_test(varname, wrf_in): @@ -58,7 +60,7 @@ def make_interp_test(varname, wrf_in):
if (varname == "vinterp"):
for timeidx in (0, None):
eth = getvar(wrf_in, "eth", timeidx=timeidx)
interp_levels = [850,500,5]
interp_levels = [850, 500, 5]
field = vinterp(wrf_in,
field=eth,
vert_coord="pressure",
@ -70,7 +72,6 @@ def make_interp_test(varname, wrf_in): @@ -70,7 +72,6 @@ def make_interp_test(varname, wrf_in):
else:
pass
return test
@ -94,12 +95,15 @@ def make_latlon_test(testid, wrf_in): @@ -94,12 +95,15 @@ def make_latlon_test(testid, wrf_in):
class WRFVarsTest(ut.TestCase):
longMessage = True
class WRFInterpTest(ut.TestCase):
longMessage = True
class WRFLatLonTest(ut.TestCase):
longMessage = True
if __name__ == "__main__":
from wrf import (omp_set_num_threads, omp_set_schedule, omp_get_schedule,
omp_set_dynamic, omp_get_num_procs, OMP_SCHED_STATIC)
@ -116,13 +120,12 @@ if __name__ == "__main__": @@ -116,13 +120,12 @@ if __name__ == "__main__":
interp_methods = ["interplevel", "vertcross", "interpline", "vinterp"]
latlon_tests = ["xy_out", "ll_out"]
for nc_lib in ("netcdf4", "pynio", "scipy"):
if nc_lib == "netcdf4":
try:
from netCDF4 import Dataset
except ImportError:
print ("netcdf4-python not installed")
print("netcdf4-python not installed")
continue
else:
test_in = [Dataset(x) for x in TEST_FILES]
@ -130,15 +133,15 @@ if __name__ == "__main__": @@ -130,15 +133,15 @@ if __name__ == "__main__":
try:
from Nio import open_file
except ImportError:
print ("PyNIO not installed")
print("PyNIO not installed")
continue
else:
test_in = [open_file(x +".nc", "r") for x in TEST_FILES]
test_in = [open_file(x + ".nc", "r") for x in TEST_FILES]
elif nc_lib == "scipy":
try:
from scipy.io.netcdf import netcdf_file
except ImportError:
print ("scipy.io.netcdf not installed")
print("scipy.io.netcdf not installed")
else:
test_in = [netcdf_file(x, mmap=False) for x in TEST_FILES]
@ -147,29 +150,25 @@ if __name__ == "__main__": @@ -147,29 +150,25 @@ if __name__ == "__main__":
input2 = tuple(input1)
input3 = wrfin_gen(test_in)
input4 = wrf_in_iter_class(test_in)
input5 = {"A" : input1,
"B" : input2}
input6 = {"A" : {"AA" : input1},
"B" : {"BB" : input2}}
input5 = {"A": input1,
"B": input2}
input6 = {"A": {"AA": input1},
"B": {"BB": input2}}
for i,input in enumerate((input0, input1, input2,
for i, input in enumerate((input0, input1, input2,
input3, input4, input5, input6)):
for var in wrf_vars:
if var in ignore_vars:
continue
test_func1 = make_test(var, input)
setattr(WRFVarsTest, "test_{0}_input{1}_{2}".format(nc_lib,
i, var),
test_func1)
setattr(WRFVarsTest, "test_{0}_input{1}_{2}".format(
nc_lib, i, var), test_func1)
for method in interp_methods:
test_interp_func1 = make_interp_test(method, input)
setattr(WRFInterpTest,
"test_{0}_input{1}_{2}".format(nc_lib,
i, method),
test_interp_func1)
setattr(WRFInterpTest, "test_{0}_input{1}_{2}".format(
nc_lib, i, method), test_interp_func1)
for testid in latlon_tests:
test_ll_func = make_latlon_test(testid, input)
@ -177,5 +176,3 @@ if __name__ == "__main__": @@ -177,5 +176,3 @@ if __name__ == "__main__":
setattr(WRFLatLonTest, test_name, test_ll_func)
ut.main()

42
test/test_multi_cache.py

@ -3,56 +3,60 @@ from wrf.cache import _get_cache @@ -3,56 +3,60 @@ from wrf.cache import _get_cache
from wrf import getvar
from netCDF4 import Dataset as nc
#a = nc("/Users/ladwig/Documents/wrf_files/wrf_vortex_single/wrfout_d02_2005-08-28_00:00:00")
#b = nc("/Users/ladwig/Documents/wrf_files/wrf_vortex_single/wrfout_d02_2005-08-28_03:00:00")
a = nc("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_2005-08-28_00:00:00")
b = nc("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_2005-08-28_12:00:00")
q = {"outoutoutout" : {"outoutout" : {"outout" : {"out1" : {"blah" : [a,b], "blah2" : [a,b]}, "out2" : {"blah" : [a,b], "blah2" : [a,b]} } } } }
a = nc("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-28_00:00:00")
b = nc("/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-28_12:00:00")
q = {"outoutoutout":
{"outoutout":
{"outout":
{"out1": {"blah": [a, b], "blah2": [a, b]},
"out2": {"blah": [a, b], "blah2": [a, b]}}}}}
t1 = time.time()
c = getvar(q, "rh", method="cat", timeidx=None, squeeze=True)
t2 = time.time()
print (c)
print ("time taken: {}".format((t2-t1)*1000.))
print(c)
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="cat", timeidx=None, squeeze=False)
t2 = time.time()
print (c)
print ("time taken: {}".format((t2-t1)*1000.))
print(c)
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="cat", timeidx=1, squeeze=True)
t2 = time.time()
print (c)
print ("time taken: {}".format((t2-t1)*1000.))
print(c)
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="cat", timeidx=1, squeeze=False)
t2 = time.time()
print(c)
print ("time taken: {}".format((t2-t1)*1000.))
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="join", timeidx=None, squeeze=True)
t2 = time.time()
print (c)
print ("time taken: {}".format((t2-t1)*1000.))
print(c)
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="join", timeidx=None, squeeze=False)
t2 = time.time()
print(c)
print ("time taken: {}".format((t2-t1)*1000.))
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="join", timeidx=1, squeeze=True)
t2 = time.time()
print (c)
print ("time taken: {}".format((t2-t1)*1000.))
print(c)
print("time taken: {}".format((t2-t1)*1000.))
t1 = time.time()
c = getvar(q, "rh", method="join", timeidx=1, squeeze=False)
t2 = time.time()
print (c)
print ("time taken: {}".format((t2-t1)*1000.))
print(c)
print("time taken: {}".format((t2-t1)*1000.))

29
test/test_omp.py

@ -28,11 +28,11 @@ class OmpTest(ut.TestCase): @@ -28,11 +28,11 @@ class OmpTest(ut.TestCase):
longMessage = True
def test_locks(self):
l = omp_init_lock()
omp_set_lock(l)
omp_unset_lock(l)
omp_test_lock(l)
omp_destroy_lock(l)
lk = omp_init_lock()
omp_set_lock(lk)
omp_unset_lock(lk)
omp_test_lock(lk)
omp_destroy_lock(lk)
nl = omp_init_nest_lock()
omp_set_nest_lock(nl)
@ -40,24 +40,25 @@ class OmpTest(ut.TestCase): @@ -40,24 +40,25 @@ class OmpTest(ut.TestCase):
omp_test_nest_lock(nl)
omp_destroy_nest_lock(nl)
def test_thread_set(self):
omp_set_num_threads(4)
max_threads = omp_get_max_threads()
self.assertEqual(max_threads, 4)
num_threads = omp_get_num_threads()
self.assertEqual(num_threads, 1) # Always 1 outside of parallel region
# Always 1 outside of parallel region
self.assertEqual(num_threads, 1)
thread_num = omp_get_thread_num()
self.assertEqual(thread_num, 0) # Always 0 outside of parallel region
# Always 0 outside of parallel region
self.assertEqual(thread_num, 0)
num_procs = omp_get_num_procs()
in_parallel = omp_in_parallel()
self.assertFalse(in_parallel) # Always False outside of parallel region
# Always False outside of parallel region
self.assertFalse(in_parallel)
limit = omp_get_thread_limit()
def test_dynamic(self):
omp_set_dynamic(True)
dynamic = omp_get_dynamic()
@ -76,7 +77,6 @@ class OmpTest(ut.TestCase): @@ -76,7 +77,6 @@ class OmpTest(ut.TestCase):
nested = omp_get_nested()
self.assertFalse(nested)
def test_schedule(self):
omp_set_schedule(OMP_SCHED_STATIC, 100000)
kind, modifier = omp_get_schedule()
@ -96,10 +96,10 @@ class OmpTest(ut.TestCase): @@ -96,10 +96,10 @@ class OmpTest(ut.TestCase):
omp_set_schedule(OMP_SCHED_AUTO, 10)
kind, modifier = omp_get_schedule()
self.assertEqual(kind, OMP_SCHED_AUTO)
self.assertNotEqual(modifier, 10) # The modifier argument is ignored,
# The modifier argument is ignored,
# so it will be set to the previous
# value of 100.
self.assertNotEqual(modifier, 10)
def test_team_level(self):
omp_set_max_active_levels(10)
@ -112,11 +112,10 @@ class OmpTest(ut.TestCase): @@ -112,11 +112,10 @@ class OmpTest(ut.TestCase):
active_level = omp_get_active_level()
in_final = omp_in_final()
def test_time(self):
wtime = omp_get_wtime()
wtick = omp_get_wtick()
if __name__ == "__main__":
ut.main()

120
test/test_proj_params.py

@ -2,7 +2,8 @@ import unittest as ut @@ -2,7 +2,8 @@ import unittest as ut
import numpy.testing as nt
import numpy as np
import numpy.ma as ma
import os, sys
import os
import sys
import subprocess
from wrf import xy_to_ll_proj, ll_to_xy_proj, to_np
@ -11,11 +12,12 @@ from wrf import xy_to_ll_proj, ll_to_xy_proj, to_np @@ -11,11 +12,12 @@ from wrf import xy_to_ll_proj, ll_to_xy_proj, to_np
class WRFLatLonProjTest(ut.TestCase):
longMessage = True
def make_test(xy_or_ll_out):
def test(self):
# Python 3
if sys.version_info > (3,):
if sys.version_info > (3, ):
assert_raises_regex = self.assertRaisesRegex
xrange = range
else:
@ -23,37 +25,37 @@ def make_test(xy_or_ll_out): @@ -23,37 +25,37 @@ def make_test(xy_or_ll_out):
if xy_or_ll_out == "xy":
# Test the required failures
with assert_raises_regex(ValueError, ".*map_proj.*" ):
ll_to_xy_proj(30,-110)
with assert_raises_regex(ValueError, ".*map_proj.*"):
ll_to_xy_proj(30, -110)
with assert_raises_regex(ValueError, ".*ref_lat.*" ):
ll_to_xy_proj(30,-110, map_proj=1)
with assert_raises_regex(ValueError, ".*ref_lat.*"):
ll_to_xy_proj(30, -110, map_proj=1)
with assert_raises_regex(ValueError, ".*ref_lon.*" ):
ll_to_xy_proj(30,-110, map_proj=1, ref_lat=45)
with assert_raises_regex(ValueError, ".*ref_lon.*"):
ll_to_xy_proj(30, -110, map_proj=1, ref_lat=45)
with assert_raises_regex(ValueError, ".*known_x.*" ):
ll_to_xy_proj(30,-110, map_proj=1, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*known_x.*"):
ll_to_xy_proj(30, -110, map_proj=1, ref_lat=45.0,
ref_lon=-120.)
with assert_raises_regex(ValueError, ".*known_y.*" ):
ll_to_xy_proj(30,-110, map_proj=1, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*known_y.*"):
ll_to_xy_proj(30, -110, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=1)
with assert_raises_regex(ValueError, ".*dx.*" ):
ll_to_xy_proj(30,-110, map_proj=1, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*dx.*"):
ll_to_xy_proj(30, -110, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0)
####### Now test the projections
# Now test the projections
# Lambert Conformal - truelat1, stand_lon required
with assert_raises_regex(ValueError, ".*truelat1.*" ):
ll_to_xy_proj(30,-110, map_proj=1, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*truelat1.*"):
ll_to_xy_proj(30, -110, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.)
with assert_raises_regex(ValueError, ".*stand_lon.*" ):
ll_to_xy_proj(30,-110, map_proj=1, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*stand_lon.*"):
ll_to_xy_proj(30, -110, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.,
truelat1=60.)
@ -64,23 +66,21 @@ def make_test(xy_or_ll_out): @@ -64,23 +66,21 @@ def make_test(xy_or_ll_out):
dx=30000., truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=90., pole_lon=0.)
p_def = ll_to_xy_proj(28., -89., map_proj=1, ref_lat=17.803,
ref_lon=-100.7747, known_x=0, known_y=0,
dx=30000., truelat1=30.,
stand_lon=-89.)
dx=30000., truelat1=30., stand_lon=-89.)
nt.assert_allclose(to_np(p_all), to_np(p_def))
# Polar Stereographic - truelat1, stand_lon
with assert_raises_regex(ValueError, ".*truelat1.*" ):
ll_to_xy_proj(30,-110, map_proj=2, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*truelat1.*"):
ll_to_xy_proj(30, -110, map_proj=2, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.)
with assert_raises_regex(ValueError, ".*stand_lon.*" ):
ll_to_xy_proj(30,-110, map_proj=2, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*stand_lon.*"):
ll_to_xy_proj(30, -110, map_proj=2, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.,
truelat1=60.)
@ -90,19 +90,16 @@ def make_test(xy_or_ll_out): @@ -90,19 +90,16 @@ def make_test(xy_or_ll_out):
dx=30000., truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=90., pole_lon=0.)
p_def = ll_to_xy_proj(28., -89., map_proj=2, ref_lat=17.933,
ref_lon=-100.0735, known_x=0, known_y=0,
dx=30000., truelat1=30.,
stand_lon=-89.)
dx=30000., truelat1=30., stand_lon=-89.)
nt.assert_allclose(to_np(p_all), to_np(p_def))
# Mercator - truelat1
with assert_raises_regex(ValueError, ".*truelat1.*" ):
ll_to_xy_proj(30,-110, map_proj=2, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*truelat1.*"):
ll_to_xy_proj(30, -110, map_proj=2, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.)
@ -111,7 +108,6 @@ def make_test(xy_or_ll_out): @@ -111,7 +108,6 @@ def make_test(xy_or_ll_out):
dx=30000., truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=90., pole_lon=0.)
p_def = ll_to_xy_proj(28., -89., map_proj=3, ref_lat=19.1075,
ref_lon=-101.008, known_x=0, known_y=0,
dx=30000., truelat1=30.)
@ -120,38 +116,37 @@ def make_test(xy_or_ll_out): @@ -120,38 +116,37 @@ def make_test(xy_or_ll_out):
# Lat/lon - stand_lon, dy, pole_lat, pole_lon
with assert_raises_regex(ValueError, ".*stand_lon.*" ):
ll_to_xy_proj(30,-110, map_proj=6, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*stand_lon.*"):
ll_to_xy_proj(30, -110, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=.2698388)
with assert_raises_regex(ValueError, ".*dy.*" ):
ll_to_xy_proj(30,-110, map_proj=6, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*dy.*"):
ll_to_xy_proj(30, -110, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
stand_lon=89.0,
dx=.2698388)
with assert_raises_regex(ValueError, ".*pole_lat.*" ):
ll_to_xy_proj(30,-110, map_proj=6, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*pole_lat.*"):
ll_to_xy_proj(30, -110, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
stand_lon=89.0,
dx=.2698388, dy=.2698388)
with assert_raises_regex(ValueError, ".*pole_lon.*" ):
ll_to_xy_proj(30,-110, map_proj=6, ref_lat=45.0,
with assert_raises_regex(ValueError, ".*pole_lon.*"):
ll_to_xy_proj(30, -110, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
stand_lon=89.0,
dx=.2698388, dy=.2698388,
pole_lat=62.0)
p_all = ll_to_xy_proj(28.,-89., map_proj=6, ref_lat=17.6759,
p_all = ll_to_xy_proj(28., -89., map_proj=6, ref_lat=17.6759,
ref_lon=-101.4286, known_x=0, known_y=0,
dx=30000, dy=30000,
truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=62.0,
pole_lon=180.)
p_def = ll_to_xy_proj(28., -89., map_proj=6, ref_lat=17.6759,
ref_lon=-101.4286, known_x=0, known_y=0,
stand_lon=-89.,
@ -160,40 +155,39 @@ def make_test(xy_or_ll_out): @@ -160,40 +155,39 @@ def make_test(xy_or_ll_out):
nt.assert_allclose(to_np(p_all), to_np(p_def))
if xy_or_ll_out == "ll":
# Test the required failures
with assert_raises_regex(ValueError, ".*map_proj.*" ):
with assert_raises_regex(ValueError, ".*map_proj.*"):
xy_to_ll_proj(45, 50)
with assert_raises_regex(ValueError, ".*ref_lat.*" ):
with assert_raises_regex(ValueError, ".*ref_lat.*"):
xy_to_ll_proj(45, 50, map_proj=1)
with assert_raises_regex(ValueError, ".*ref_lon.*" ):
with assert_raises_regex(ValueError, ".*ref_lon.*"):
xy_to_ll_proj(45, 50, map_proj=1, ref_lat=45)
with assert_raises_regex(ValueError, ".*known_x.*" ):
with assert_raises_regex(ValueError, ".*known_x.*"):
xy_to_ll_proj(45, 50, map_proj=1, ref_lat=45.0,
ref_lon=-120.)
with assert_raises_regex(ValueError, ".*known_y.*" ):
with assert_raises_regex(ValueError, ".*known_y.*"):
xy_to_ll_proj(45, 50, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=1)
with assert_raises_regex(ValueError, ".*dx.*" ):
with assert_raises_regex(ValueError, ".*dx.*"):
xy_to_ll_proj(45, 50, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0)
####### Now test the projections
# Now test the projections
# Lambert Conformal - truelat1, stand_lon required
with assert_raises_regex(ValueError, ".*truelat1.*" ):
with assert_raises_regex(ValueError, ".*truelat1.*"):
xy_to_ll_proj(45, 50, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.)
with assert_raises_regex(ValueError, ".*stand_lon.*" ):
with assert_raises_regex(ValueError, ".*stand_lon.*"):
xy_to_ll_proj(45, 50, map_proj=1, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.,
@ -205,7 +199,6 @@ def make_test(xy_or_ll_out): @@ -205,7 +199,6 @@ def make_test(xy_or_ll_out):
dx=30000., truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=90., pole_lon=0.)
p_def = xy_to_ll_proj(45, 50, map_proj=1, ref_lat=17.803,
ref_lon=-100.7747, known_x=0, known_y=0,
dx=30000., truelat1=30.,
@ -215,12 +208,12 @@ def make_test(xy_or_ll_out): @@ -215,12 +208,12 @@ def make_test(xy_or_ll_out):
# Polar Stereographic - truelat1, stand_lon
with assert_raises_regex(ValueError, ".*truelat1.*" ):
with assert_raises_regex(ValueError, ".*truelat1.*"):
xy_to_ll_proj(45, 50, map_proj=2, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.)
with assert_raises_regex(ValueError, ".*stand_lon.*" ):
with assert_raises_regex(ValueError, ".*stand_lon.*"):
xy_to_ll_proj(45, 50, map_proj=2, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.,
@ -231,7 +224,6 @@ def make_test(xy_or_ll_out): @@ -231,7 +224,6 @@ def make_test(xy_or_ll_out):
dx=30000., truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=90., pole_lon=0.)
p_def = xy_to_ll_proj(45, 50, map_proj=2, ref_lat=17.933,
ref_lon=-100.0735, known_x=0, known_y=0,
dx=30000., truelat1=30.,
@ -239,10 +231,9 @@ def make_test(xy_or_ll_out): @@ -239,10 +231,9 @@ def make_test(xy_or_ll_out):
nt.assert_allclose(to_np(p_all), to_np(p_def))
# Mercator - truelat1
with assert_raises_regex(ValueError, ".*truelat1.*" ):
with assert_raises_regex(ValueError, ".*truelat1.*"):
xy_to_ll_proj(45, 50, map_proj=2, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=3000.)
@ -252,7 +243,6 @@ def make_test(xy_or_ll_out): @@ -252,7 +243,6 @@ def make_test(xy_or_ll_out):
dx=30000., truelat1=30., truelat2=30.,
stand_lon=-89., pole_lat=90., pole_lon=0.)
p_def = xy_to_ll_proj(45, 50, map_proj=3, ref_lat=19.1075,
ref_lon=-101.008, known_x=0, known_y=0,
dx=30000., truelat1=30.)
@ -261,24 +251,24 @@ def make_test(xy_or_ll_out): @@ -261,24 +251,24 @@ def make_test(xy_or_ll_out):
# Lat/lon - stand_lon, dy, pole_lat, pole_lon
with assert_raises_regex(ValueError, ".*stand_lon.*" ):
with assert_raises_regex(ValueError, ".*stand_lon.*"):
xy_to_ll_proj(45, 50, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
dx=.2698388)
with assert_raises_regex(ValueError, ".*dy.*" ):
with assert_raises_regex(ValueError, ".*dy.*"):
xy_to_ll_proj(45, 50, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
stand_lon=89.0,
dx=.2698388)
with assert_raises_regex(ValueError, ".*pole_lat.*" ):
with assert_raises_regex(ValueError, ".*pole_lat.*"):
xy_to_ll_proj(45, 50, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
stand_lon=89.0,
dx=.2698388, dy=.2698388)
with assert_raises_regex(ValueError, ".*pole_lon.*" ):
with assert_raises_regex(ValueError, ".*pole_lon.*"):
xy_to_ll_proj(45, 50, map_proj=6, ref_lat=45.0,
ref_lon=-120., known_x=0, known_y=0,
stand_lon=89.0,
@ -292,7 +282,6 @@ def make_test(xy_or_ll_out): @@ -292,7 +282,6 @@ def make_test(xy_or_ll_out):
stand_lon=-89., pole_lat=62.0,
pole_lon=180.)
p_def = xy_to_ll_proj(64, 40, map_proj=6, ref_lat=17.6759,
ref_lon=-101.4286, known_x=0, known_y=0,
stand_lon=-89.,
@ -311,4 +300,3 @@ if __name__ == "__main__": @@ -311,4 +300,3 @@ if __name__ == "__main__":
setattr(WRFLatLonProjTest, 'test_{0}'.format(v), test_func)
ut.main()

1
test/test_units.py

@ -51,6 +51,5 @@ class TestUnits(ut.TestCase): @@ -51,6 +51,5 @@ class TestUnits(ut.TestCase):
self.assertEqual(var.attrs["units"], units)
if __name__ == "__main__":
ut.main()

580
test/utests.py

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save