From 2438d060656d80516281304f550ed3e744d17798 Mon Sep 17 00:00:00 2001 From: wyq Date: Wed, 27 Jul 2022 15:43:19 +0800 Subject: [PATCH] add wrf sub-package --- meteoinfo-lab/milconfig.xml | 32 +-- meteoinfo-lab/pylib/__init__.py | 0 .../mipylib/dataset/dimdatafile$py.class | Bin 50732 -> 50777 bytes .../pylib/mipylib/dataset/dimdatafile.py | 6 +- .../pylib/mipylib/imagelib/filters$py.class | Bin 31996 -> 31997 bytes .../pylib/mipylib/imagelib/filters.py | 4 +- .../pylib/mipylib/meteolib/__init__$py.class | Bin 3104 -> 3076 bytes .../pylib/mipylib/meteolib/__init__.py | 2 +- .../pylib/mipylib/meteolib/wrf/__init__.py | 11 + .../pylib/mipylib/meteolib/wrf/destag.py | 42 ++++ .../pylib/mipylib/meteolib/wrf/g_geoht.py | 209 ++++++++++++++++++ .../pylib/mipylib/meteolib/wrf/g_pressure.py | 19 ++ .../pylib/mipylib/meteolib/wrf/g_rh.py | 48 ++++ .../pylib/mipylib/meteolib/wrf/g_slp.py | 37 ++++ .../pylib/mipylib/meteolib/wrf/util.py | 39 ++++ .../pylib/mipylib/meteolib/{ => wrf}/wrf.py | 2 +- 16 files changed, 429 insertions(+), 22 deletions(-) create mode 100644 meteoinfo-lab/pylib/__init__.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/__init__.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/destag.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_geoht.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_pressure.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_rh.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_slp.py create mode 100644 meteoinfo-lab/pylib/mipylib/meteolib/wrf/util.py rename meteoinfo-lab/pylib/mipylib/meteolib/{ => wrf}/wrf.py (97%) diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml index d8d52335..aa54fe06 100644 --- a/meteoinfo-lab/milconfig.xml +++ b/meteoinfo-lab/milconfig.xml @@ -1,32 +1,32 @@ - - - - - - - - - + - - + + + + + + + + + + - - + + - - + + @@ -34,5 +34,5 @@
- + diff --git a/meteoinfo-lab/pylib/__init__.py b/meteoinfo-lab/pylib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/meteoinfo-lab/pylib/mipylib/dataset/dimdatafile$py.class b/meteoinfo-lab/pylib/mipylib/dataset/dimdatafile$py.class index 60754340fe538b0378fb4bceee2012b61c816e17..10d4dd780bd31cb691f7e8764b60d76b6699c81b 100644 GIT binary patch literal 50777 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%0ARS|0ZzU102=v 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 EAAz{4RR910 literal 50732 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 L*fJ{QVh8*`C&8Jp diff --git a/meteoinfo-lab/pylib/mipylib/dataset/dimdatafile.py b/meteoinfo-lab/pylib/mipylib/dataset/dimdatafile.py index e9aa5337..ab0fd649 100644 --- a/meteoinfo-lab/pylib/mipylib/dataset/dimdatafile.py +++ b/meteoinfo-lab/pylib/mipylib/dataset/dimdatafile.py @@ -119,13 +119,15 @@ class DimDataFile(object): return None v = np.array(attr.getValues()) return v - + + @property def variables(self): """ Get all variables. """ return self._variables - + + @property def varnames(self): """ Get all variable names. diff --git a/meteoinfo-lab/pylib/mipylib/imagelib/filters$py.class b/meteoinfo-lab/pylib/mipylib/imagelib/filters$py.class index b19e9c9d342aa36398d4388cc4f480fee9e7d50d..ca19e97a8ff3e3c075bb5442110a6089dfe887a6 100644 GIT binary patch delta 28 kcmezKlkx9Q#tj9WOlw2 diff --git a/meteoinfo-lab/pylib/mipylib/imagelib/filters.py b/meteoinfo-lab/pylib/mipylib/imagelib/filters.py index d8b8a0e7..e0655b33 100644 --- a/meteoinfo-lab/pylib/mipylib/imagelib/filters.py +++ b/meteoinfo-lab/pylib/mipylib/imagelib/filters.py @@ -30,7 +30,7 @@ def __getimage(src): elif isinstance(src, Graphic): return src.getShape().getImage() elif isinstance(src, MILayer): - return src.layer.getImage() + return src._layer.getImage() elif isinstance(src, NDArray): return ImageUtil.createImage(src.asarray()) return None @@ -40,7 +40,7 @@ def __getreturn(src, dst): src.getShape().setImage(dst) return src elif isinstance(src, MILayer): - src.layer.setImage(dst) + src._layer.setImage(dst) return src elif isinstance(src, NDArray): r = ImageUtil.imageRead(dst) diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/__init__$py.class b/meteoinfo-lab/pylib/mipylib/meteolib/__init__$py.class index 2a0d759abce534da24ece55530523cdb26f4819f..ed5111b99e20c4e80fce382c5eaa8eec6ba1bc0a 100644 GIT binary patch delta 202 zcmZ1=(IT;dn~|5fyeN%>L6DJwfrCMKGC!lJfG8saXL5dCaYw<)3fNUcx7HuI3NuWN3$!9rrIE8jF=mkfz i2uVz4;!{2i}iz}K@Z1XoREk*z|eJ4}^ delta 246 zcmZpXSRk>1n^Bp8gF%pyK_Dx!EKxrvF)v*|xTGjEFP)u1n2~|GyeN%>L3FY$V;+Y% zg9H}?4};|7&5ZV<(hM?O3@i+?j0~K~`FX`9iFqZ(9GibI2D7o&tG3+yw>f}AnlUMz zfsKKcfq_w9n`IjVhY*)G%MJzsZB`Ilh-EK>h@URAkXW!TNLUKUHnL*T77~*Ls+D5| zGTBhnDWIuS0IQq4kyD3LYzKp0a3qV6!sKV1YK(G|dAUHO36~0xj0BT)T+xgon{RPx GF#-TEQ!`2c diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/__init__.py b/meteoinfo-lab/pylib/mipylib/meteolib/__init__.py index 19f36d46..8c3b3e41 100644 --- a/meteoinfo-lab/pylib/mipylib/meteolib/__init__.py +++ b/meteoinfo-lab/pylib/mipylib/meteolib/__init__.py @@ -1,5 +1,5 @@ from .meteo import * -from . import wrf +from .wrf import * from . import constants from .calc import * from .interpolate import * diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/__init__.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/__init__.py new file mode 100644 index 00000000..74bb9851 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/__init__.py @@ -0,0 +1,11 @@ +from destag import * +from g_slp import * +from g_rh import * +from g_pressure import * +from g_geoht import * + +__all__ = destag.__all__ +__all__ += g_slp.__all__ +__all__ += g_rh.__all__ +__all__ += g_pressure.__all__ +__all__ += g_geoht.__all__ \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/destag.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/destag.py new file mode 100644 index 00000000..8c50f162 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/destag.py @@ -0,0 +1,42 @@ + +__all__ = ['destagger'] + +def destagger(var, stagger_dim): + """ + Return the variable data array on the unstaggered grid. + + This function destaggers the variable by taking the average of the + values located on either side of the grid box. + + :param var: (*array*) A variable on a staggered grid. + :param stagger_dim: (*int*) The dimension index to destagger. + Negative values can be used to choose dimensions referenced + from the right hand side (-1 is the rightmost dimension). + + :returns: (*array*) The destaggered variable data array. + """ + var_shape = var.shape + num_dims = var.ndim + stagger_dim_size = var_shape[stagger_dim] + # Dynamically building the range slices to create the appropriate + # number of ':'s in the array accessor lists. + # For example, for a 3D array, the calculation would be + # result = .5 * (var[:,:,0:stagger_dim_size-2] + # + var[:,:,1:stagger_dim_size-1]) + # for stagger_dim=2. So, full slices would be used for dims 0 and 1, but + # dim 2 needs the special slice. + full_slice = slice(None) + slice1 = slice(0, stagger_dim_size - 1, 1) + slice2 = slice(1, stagger_dim_size, 1) + + # default to full slices + dim_ranges_1 = [full_slice] * num_dims + dim_ranges_2 = [full_slice] * num_dims + + # for the stagger dim, insert the appropriate slice range + dim_ranges_1[stagger_dim] = slice1 + dim_ranges_2[stagger_dim] = slice2 + + result = .5*(var[tuple(dim_ranges_1)] + var[tuple(dim_ranges_2)]) + + return result \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_geoht.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_geoht.py new file mode 100644 index 00000000..b018fd69 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_geoht.py @@ -0,0 +1,209 @@ +from util import either +from destag import destagger +from .. import constants +import warnings + +__all__ = ['get_geopt', 'get_stag_geopt', 'get_height', 'get_stag_height', 'get_height_agl'] + +def _get_geoht(wrfin, timeidx, height=True, msl=True, stag=False): + """Return the geopotential or geopotential height. + + If *height* is False, then geopotential is returned in units of + [m2 s-2]. If *height* is True, then geopotential height is + returned in units of [m]. If *msl* is True, then geopotential height + is return as Mean Sea Level (MSL). If *msl* is False, then geopotential + height is returned as Above Ground Level (AGL). + 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. + height (:obj:`bool`, optional): Set to True to return geopotential + height instead of geopotential. Default is True. + msl (:obj:`bool`, optional): Set to True to return geopotential height + as Mean Sea Level (MSL). Set to False to return the + geopotential height as Above Ground Level (AGL) by subtracting + the terrain height. Default is True. + stag (:obj:`bool`, optional): Set to True to use the vertical + staggered grid, rather than the mass grid. Default is False. + + Returns: + :class:`DimArray` + """ + + varname = either("PH", "GHT")(wrfin) + if varname == "PH": + ph = wrfin["PH"][timeidx] + phb = wrfin["PHB"][timeidx] + hgt = wrfin["HGT"][timeidx] + geopt = ph + phb + if not stag: + geopt_unstag = destagger(geopt, -3) + else: + geopt_unstag = geopt + else: + geopt_unstag = wrfin["GHT"][timeidx] * constants.g + hgt = wrfin["HGT_M"][timeidx] + + if stag: + warnings.warn("file contains no vertically staggered geopotential " + "height variable, returning unstaggered result " + "instead") + if height: + if msl: + return geopt_unstag / constants.g + else: + # Due to broadcasting with multifile/multitime, the 2D terrain + # 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) + hgt = hgt.reshape(new_dims) + + return (geopt_unstag / constants.g) - hgt + else: + return geopt_unstag + +def get_geopt(wrfin, timeidx=0): + """Return the geopotential. + + The geopotential is returned in units of [m2 s-2]. + 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. + + Returns: + :class:`DimArray` + """ + return _get_geoht(wrfin, timeidx, False, True) + +def get_height(wrfin, timeidx=0, msl=True): + """Return the geopotential height. + + If *msl* is True, then geopotential height is returned as Mean Sea Level + (MSL). If *msl* is False, then 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. + msl (:obj:`bool`, optional): Set to True to return geopotential height + as Mean Sea Level (MSL). Set to False to return the + geopotential height as Above Ground Level (AGL) by subtracting + the terrain height. Default is True. + + Returns: + :class:`DimArray` or :class:`numpy.ndarray`: The + geopotential height (m). + """ + return _get_geoht(wrfin, timeidx, True, msl) + +def get_stag_geopt(wrfin, timeidx=0): + """Return the geopotential for the vertically staggered grid. + + The geopotential is returned in units of [m2 s-2]. + 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. + + Returns: + :class:`DimArray` or :class:`numpy.ndarray`: The + geopotential (m). + """ + return _get_geoht(wrfin, timeidx, False, True, stag=True) + + +def get_stag_height(wrfin, timeidx=0, msl=True): + """Return the geopotential height for the vertically staggered grid. + + If *msl* is True, then geopotential height is returned as Mean Sea Level + (MSL). If *msl* is False, then 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. + msl (:obj:`bool`, optional): Set to True to return geopotential height + as Mean Sea Level (MSL). Set to False to return the + geopotential height as Above Ground Level (AGL) by subtracting + the terrain height. Default is True. + + Returns: + :class:`DimArray` or :class:`numpy.ndarray`: The + geopotential height (m). + """ + + return _get_geoht(wrfin, timeidx, True, msl, stag=True) + + +def get_height_agl(wrfin, timeidx=0): + """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. + + Returns: + :class:`DimArray` or :class:`numpy.ndarray`: The + geopotential height (m). + """ + + return _get_geoht(wrfin, timeidx, True, False) \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_pressure.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_pressure.py new file mode 100644 index 00000000..15a58752 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_pressure.py @@ -0,0 +1,19 @@ +__all__ = ['get_pressure'] + +def get_pressure(wrfin, timeidx=0): + """ + Return the pressure in the specified units. + + This function extracts the necessary variables from the NetCDF file + object in order to perform the calculation. + + :param wrfin: (*DimDataFile*) Data file. + :param timeidx: (*int*) Time index. + + :returns: (*array*) Pressure (hPa). + """ + p = wrfin['P'][timeidx] + pb = wrfin['PB'][timeidx] + pres = (p + pb) * 0.01 + + return pres \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_rh.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_rh.py new file mode 100644 index 00000000..ba6ffb2a --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_rh.py @@ -0,0 +1,48 @@ +from .. import constants +from ..calc.thermo import relative_humidity_from_specific_humidity, temperature_from_potential_temperature + +__all__ = ['get_rh', 'get_rh2m'] + +def get_rh(wrfin, timeidx=0): + """ + Return the relative humidity. + + This functions extracts the necessary variables from the NetCDF file + object in order to perform the calculation. + + :param wrfin: (*DimDataFile*) Data file. + :param timeidx: (*int*) Time index. + + :returns: (*array*) Relative humidity. + """ + t = wrfin['T'][timeidx,:,:,:] + p = wrfin['P'][timeidx,:,:,:] + pb = wrfin['PB'][timeidx,:,:,:] + qvapor = wrfin['QVAPOR'][timeidx,:,:,:] + full_t = t + constants.T_BASE + full_p = p + pb + qvapor[qvapor < 0] = 0. + tk = temperature_from_potential_temperature(full_p * 0.01, full_t) + rh = relative_humidity_from_specific_humidity(full_p * 0.01, tk, qvapor) + + return rh + +def get_rh2m(wrfin, timeidx=0): + """ + Return the 2m relative humidity. + + This functions extracts the necessary variables from the NetCDF file + object in order to perform the calculation. + + :param wrfin: (*DimDataFile*) Data file. + :param timeidx: (*int*) Time index. + + :returns: (*array*) Relative humidity. + """ + t2 = wrfin['T2'][timeidx,:,:] + psfc = wrfin['PSFC'][timeidx,:,:] + q2 = wrfin['Q2'][timeidx,:,:] + q2[q2 < 0] = 0. + rh = relative_humidity_from_specific_humidity(psfc * 0.01, t2, q2) + + return rh \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_slp.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_slp.py new file mode 100644 index 00000000..56c18a72 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/g_slp.py @@ -0,0 +1,37 @@ +from org.meteoinfo.math.meteo import MeteoMath +from mipylib.numeric.core import DimArray +from .. import constants +from ..calc.thermo import temperature_from_potential_temperature +from destag import destagger + +__all__ = ['get_slp'] + +def get_slp(wrfin, timeidx=0, units='hPa'): + """ + Return the sea level pressure in the specified units. + + This function extracts the necessary variables from the NetCDF file + object in order to perform the calculation. + + :param wrfin: (*DimDataFile*) Data file. + :param timeidx: (*int*) Time index. + :param units: (*string*) The desired units. + + :returns: (*array*) Sea level pressure. + """ + t = wrfin['T'][timeidx,:,:,:] + p = wrfin['P'][timeidx,:,:,:] + pb = wrfin['PB'][timeidx,:,:,:] + qvapor = wrfin['QVAPOR'][timeidx,:,:,:] + ph = wrfin['PH'][timeidx,:,:,:] + phb = wrfin['PHB'][timeidx,:,:,:] + full_t = t + constants.T_BASE + full_p = p + pb + qvapor[qvapor < 0] = 0. + + full_ph = (ph + phb) / constants.g + destag_ph = destagger(full_ph, -3) + tk = temperature_from_potential_temperature(full_p * 0.01, full_t) + slp = MeteoMath.calSeaPrs(destag_ph._array, tk._array, full_p._array, qvapor._array) + + return DimArray(slp, dims=t.dims[1:]) \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf/util.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/util.py new file mode 100644 index 00000000..67d4b5d7 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/util.py @@ -0,0 +1,39 @@ + +# Helper utilities for metadata +class either(object): + """A callable class that determines which variable is present in the + file. + + This is used in situations where the same variable type has different names + depending on the type of file used. For example, in a WRF output file, + 'P' is used for pressure, whereas in a met_em file, pressure is named + 'PRES'. + + Methods: + __call__(wrfin): Return the variable that is present in the file. + 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. + Returns: + :obj:`str`: The variable name that is present in the file. + + Attributes: + varnames (sequence): A sequence of possible variable names. + """ + def __init__(self, *varnames): + """Initialize an :class:`either` object. + + Args: + *varnames (sequence): A sequence of possible variable names. + """ + self.varnames = varnames + + def __call__(self, wrfin): + for varname in self.varnames: + if varname in wrfin.varnames: + return varname + + raise ValueError("{} are not valid variable names".format( + self.varnames)) \ No newline at end of file diff --git a/meteoinfo-lab/pylib/mipylib/meteolib/wrf.py b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/wrf.py similarity index 97% rename from meteoinfo-lab/pylib/mipylib/meteolib/wrf.py rename to meteoinfo-lab/pylib/mipylib/meteolib/wrf/wrf.py index 17dd33fe..2f874ecf 100644 --- a/meteoinfo-lab/pylib/mipylib/meteolib/wrf.py +++ b/meteoinfo-lab/pylib/mipylib/meteolib/wrf/wrf.py @@ -8,7 +8,7 @@ from org.meteoinfo.math.meteo import MeteoMath from mipylib.numeric.core import NDArray, DimArray import constants as constants -from .calc.thermo import relative_humidity_from_specific_humidity, temperature_from_potential_temperature +from pylib.mipylib.meteolib.calc.thermo import relative_humidity_from_specific_humidity, temperature_from_potential_temperature __all__ = [ 'destagger','get_slp','get_rh','get_rh2m'