diff --git a/README.md b/README.md index f971999..c293939 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,78 @@ np.testing.assert_allclose(lcl_t, lcl_t_, rtol=1e-3) #### wet_bulb_temperature +#### CAPE CIN + +```python +isobaric = xr.open_dataset( + "hrrr.t00z.wrfprsf00.grib2", + engine="cfgrib", + backend_kwargs={"filter_by_keys": {"typeOfLevel": "isobaricInhPa"}}, +) +surface = xr.open_dataset( + "hrrr.t00z.wrfsfcf00.grib2", + engine="cfgrib", + backend_kwargs={"filter_by_keys": {"typeOfLevel": "surface", "stepType": "instant"}}, +) +T = isobaric["t"].to_numpy() # (K) (Z, Y, X) +Z, Y, X = T.shape +N = Y * X +T = T.reshape(Z, N).transpose() # (N, Z) + +P = isobaric["isobaricInhPa"].to_numpy().astype(np.float32) * 100.0 # (Pa) +Q = isobaric["q"].to_numpy() # (kg/kg) (Z, Y, X) +Q = Q.reshape(Z, N).transpose() # (N, Z) + +Td = nzt.dewpoint_from_specific_humidity(P[np.newaxis], Q) + +prof = nzt.parcel_profile(P, T[:, 0], Td[:, 0]) + +CAPE, CIN = nzt.cape_cin(P, T, Td, prof) + +CAPE = CAPE.reshape(Y, X) +CIN = CIN.reshape(Y, X) + + +lat = isobaric["latitude"].to_numpy() +lon = isobaric["longitude"].to_numpy() +lon = (lon + 180) % 360 - 180 +timestamp = datetime.datetime.fromisoformat(isobaric["time"].to_numpy().astype(str).item()) + +fig, axes = plt.subplots(2, 2, figsize=(24, 12), subplot_kw={"projection": ccrs.PlateCarree()}) +fig.suptitle(f"{timestamp:%Y-%m-%dT%H:%M:%SZ} | shape {Z, Y, X} | size {Z*Y*X:,}", fontsize=16, y=0.9) + +# I suspect that the difference between our cape calculations and the MRMS cape calculations is due +# to the fact we are not actually starting at the surface or accounting for surface elevation. +# leading to inflated cape values in areas of higher elevation. +cape = np.where(CAPE < 8000, CAPE, 8000) +cin = np.where(CIN > -1400, CIN, -1400) + +for ax, data, title, cmap in zip( + axes[0], [cape, cin], ["NZTHERMO CAPE", "NZTHERMO CIN"], ["inferno", "inferno_r"] +): + ax.coastlines(color="white", linewidth=0.25) + ax.set_title(title, fontsize=16) + ax.set_global() + ax.set_extent([lon.min(), lon.max(), lat.min(), lat.max()]) + cf = ax.contourf(lon, lat, data, transform=ccrs.PlateCarree(), cmap=cmap) + plt.colorbar(cf, ax=ax, orientation="vertical", pad=0.05, label="J/kg", shrink=0.75) + +MRMS_CAPE = surface["cape"].to_numpy() +MRMS_CIN = surface["cin"].to_numpy() +for ax, data, title, cmap in zip( + axes[1], [MRMS_CAPE, MRMS_CIN], ["MRMS CAPE", "MRMS CIN"], ["inferno", "inferno_r"] +): + ax.coastlines(color="white", linewidth=0.25) + ax.set_title(title, fontsize=16) + ax.set_global() + ax.set_extent([lon.min(), lon.max(), lat.min(), lat.max()]) + cf = ax.contourf(lon, lat, data, transform=ccrs.PlateCarree(), cmap=cmap) + plt.colorbar(cf, ax=ax, orientation="vertical", pad=0.05, label="J/kg", shrink=0.75) + +``` + +[![CAPE_CIN](assets/mrms_cape_cin.png)](assets/mrms_cape_cin.png) + #### dcape ```python @@ -156,7 +228,8 @@ for i, ax in enumerate(axes): ax.imshow(dcape[i], cmap="viridis") ``` -[![dcape](assets/dcape.png)](assets/dcape.png) +[![DCAPE](assets/dcape.png)](assets/dcape.png) + ### Testing diff --git a/assets/mrms_cape_cin.png b/assets/mrms_cape_cin.png new file mode 100644 index 0000000..42539d3 Binary files /dev/null and b/assets/mrms_cape_cin.png differ diff --git a/c.ipynb b/c.ipynb deleted file mode 100644 index dccc067..0000000 --- a/c.ipynb +++ /dev/null @@ -1,971 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext cython" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ 0 31]\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - "\n", - "\n", - "\n", - " \n", - " Cython: _cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06.pyx\n", - " \n", - "\n", - "\n", - "

Generated by Cython 3.0.10

\n", - "

\n", - " Yellow lines hint at Python interaction.
\n", - " Click on a line that starts with a \"+\" to see the C code that Cython generated for it.\n", - "

\n", - "
+01: # distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION
\n", - "
  __pyx_t_7 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_7) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "
 02: #distutils: extra_compile_args = -fopenmp
\n", - "
 03: #distutils: extra_link_args = -fopenmp
\n", - "
 04: # cython: language_level=3
\n", - "
 05: # cython: boundscheck=False
\n", - "
 06: # cython: wraparound=False
\n", - "
 07: # cython: nonecheck=False
\n", - "
 08: # cython: cdivision=True
\n", - "
 09: cimport cython
\n", - "
 10: import cython
\n", - "
 11: cimport numpy as np
\n", - "
+12: import numpy as np
\n", - "
  __pyx_t_2 = __Pyx_ImportDottedModule(__pyx_n_s_numpy, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_2) < 0) __PYX_ERR(0, 12, __pyx_L1_error)\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "
+13: np.import_array()
\n", - "
  __pyx_t_3 = __pyx_f_5numpy_import_array(); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 13, __pyx_L1_error)\n",
-       "
 14: 
\n", - "
 15: 
\n", - "
+16: cdef class unixtime:
\n", - "
struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime {\n",
-       "  PyObject_HEAD\n",
-       "  struct __pyx_vtabstruct_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *__pyx_vtab;\n",
-       "  PyArrayObject *values;\n",
-       "};\n",
-       "\n",
-       "\n",
-       "\n",
-       "struct __pyx_vtabstruct_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime {\n",
-       "  PyObject *(*years)(struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *, int __pyx_skip_dispatch);\n",
-       "};\n",
-       "static struct __pyx_vtabstruct_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *__pyx_vtabptr_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime;\n",
-       "
 17: 
\n", - "
 18:     cdef np.ndarray values
\n", - "
 19: 
\n", - "
+20:     def __cinit__(unixtime self, np.ndarray[np.int_t, ndim=1] values):
\n", - "
/* Python wrapper */\n",
-       "static int __pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
-       "static int __pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
-       "  PyArrayObject *__pyx_v_values = 0;\n",
-       "  CYTHON_UNUSED Py_ssize_t __pyx_nargs;\n",
-       "  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;\n",
-       "  int __pyx_r;\n",
-       "  __Pyx_RefNannyDeclarations\n",
-       "  __Pyx_RefNannySetupContext(\"__cinit__ (wrapper)\", 0);\n",
-       "  #if CYTHON_ASSUME_SAFE_MACROS\n",
-       "  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);\n",
-       "  #else\n",
-       "  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;\n",
-       "  #endif\n",
-       "  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);\n",
-       "  {\n",
-       "    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_values,0};\n",
-       "  PyObject* values[1] = {0};\n",
-       "    if (__pyx_kwds) {\n",
-       "      Py_ssize_t kw_args;\n",
-       "      switch (__pyx_nargs) {\n",
-       "        case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);\n",
-       "        CYTHON_FALLTHROUGH;\n",
-       "        case  0: break;\n",
-       "        default: goto __pyx_L5_argtuple_error;\n",
-       "      }\n",
-       "      kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);\n",
-       "      switch (__pyx_nargs) {\n",
-       "        case  0:\n",
-       "        if (likely((values[0] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_values)) != 0)) {\n",
-       "          (void)__Pyx_Arg_NewRef_VARARGS(values[0]);\n",
-       "          kw_args--;\n",
-       "        }\n",
-       "        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n",
-       "        else goto __pyx_L5_argtuple_error;\n",
-       "      }\n",
-       "      if (unlikely(kw_args > 0)) {\n",
-       "        const Py_ssize_t kwd_pos_args = __pyx_nargs;\n",
-       "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, \"__cinit__\") < 0)) __PYX_ERR(0, 20, __pyx_L3_error)\n",
-       "      }\n",
-       "    } else if (unlikely(__pyx_nargs != 1)) {\n",
-       "      goto __pyx_L5_argtuple_error;\n",
-       "    } else {\n",
-       "      values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);\n",
-       "    }\n",
-       "    __pyx_v_values = ((PyArrayObject *)values[0]);\n",
-       "  }\n",
-       "  goto __pyx_L6_skip;\n",
-       "  __pyx_L5_argtuple_error:;\n",
-       "  __Pyx_RaiseArgtupleInvalid(\"__cinit__\", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 20, __pyx_L3_error)\n",
-       "  __pyx_L6_skip:;\n",
-       "  goto __pyx_L4_argument_unpacking_done;\n",
-       "  __pyx_L3_error:;\n",
-       "  {\n",
-       "    Py_ssize_t __pyx_temp;\n",
-       "    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {\n",
-       "      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);\n",
-       "    }\n",
-       "  }\n",
-       "  __Pyx_AddTraceback(\"_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06.unixtime.__cinit__\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
-       "  __Pyx_RefNannyFinishContext();\n",
-       "  return -1;\n",
-       "  __pyx_L4_argument_unpacking_done:;\n",
-       "  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_values), __pyx_ptype_5numpy_ndarray, 1, \"values\", 0))) __PYX_ERR(0, 20, __pyx_L1_error)\n",
-       "  __pyx_r = __pyx_pf_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime___cinit__(((struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *)__pyx_v_self), __pyx_v_values);\n",
-       "  int __pyx_lineno = 0;\n",
-       "  const char *__pyx_filename = NULL;\n",
-       "  int __pyx_clineno = 0;\n",
-       "\n",
-       "  /* function exit code */\n",
-       "  goto __pyx_L0;\n",
-       "  __pyx_L1_error:;\n",
-       "  __pyx_r = -1;\n",
-       "  __pyx_L0:;\n",
-       "  {\n",
-       "    Py_ssize_t __pyx_temp;\n",
-       "    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {\n",
-       "      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);\n",
-       "    }\n",
-       "  }\n",
-       "  __Pyx_RefNannyFinishContext();\n",
-       "  return __pyx_r;\n",
-       "}\n",
-       "\n",
-       "static int __pyx_pf_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime___cinit__(struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *__pyx_v_self, PyArrayObject *__pyx_v_values) {\n",
-       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_values;\n",
-       "  __Pyx_Buffer __pyx_pybuffer_values;\n",
-       "  int __pyx_r;\n",
-       "  __pyx_pybuffer_values.pybuffer.buf = NULL;\n",
-       "  __pyx_pybuffer_values.refcount = 0;\n",
-       "  __pyx_pybuffernd_values.data = NULL;\n",
-       "  __pyx_pybuffernd_values.rcbuffer = &__pyx_pybuffer_values;\n",
-       "  {\n",
-       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
-       "    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_values.rcbuffer->pybuffer, (PyObject*)__pyx_v_values, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 20, __pyx_L1_error)\n",
-       "  }\n",
-       "  __pyx_pybuffernd_values.diminfo[0].strides = __pyx_pybuffernd_values.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_values.diminfo[0].shape = __pyx_pybuffernd_values.rcbuffer->pybuffer.shape[0];\n",
-       "/* … */\n",
-       "  /* function exit code */\n",
-       "  __pyx_r = 0;\n",
-       "  goto __pyx_L0;\n",
-       "  __pyx_L1_error:;\n",
-       "  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;\n",
-       "    __Pyx_PyThreadState_declare\n",
-       "    __Pyx_PyThreadState_assign\n",
-       "    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);\n",
-       "    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_values.rcbuffer->pybuffer);\n",
-       "  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}\n",
-       "  __Pyx_AddTraceback(\"_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06.unixtime.__cinit__\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
-       "  __pyx_r = -1;\n",
-       "  goto __pyx_L2;\n",
-       "  __pyx_L0:;\n",
-       "  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_values.rcbuffer->pybuffer);\n",
-       "  __pyx_L2:;\n",
-       "  __Pyx_RefNannyFinishContext();\n",
-       "  return __pyx_r;\n",
-       "}\n",
-       "
+21:         self.values = values
\n", - "
  __Pyx_INCREF((PyObject *)__pyx_v_values);\n",
-       "  __Pyx_GIVEREF((PyObject *)__pyx_v_values);\n",
-       "  __Pyx_GOTREF((PyObject *)__pyx_v_self->values);\n",
-       "  __Pyx_DECREF((PyObject *)__pyx_v_self->values);\n",
-       "  __pyx_v_self->values = ((PyArrayObject *)__pyx_v_values);\n",
-       "
 22: 
\n", - "
+23:     cpdef years(unixtime self):
\n", - "
static PyObject *__pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years(PyObject *__pyx_v_self, \n",
-       "#if CYTHON_METH_FASTCALL\n",
-       "PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds\n",
-       "#else\n",
-       "PyObject *__pyx_args, PyObject *__pyx_kwds\n",
-       "#endif\n",
-       "); /*proto*/\n",
-       "static PyObject *__pyx_f_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_years(struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *__pyx_v_self, int __pyx_skip_dispatch) {\n",
-       "  PyObject *__pyx_r = NULL;\n",
-       "  /* Check if called by wrapper */\n",
-       "  if (unlikely(__pyx_skip_dispatch)) ;\n",
-       "  /* Check if overridden in Python */\n",
-       "  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || __Pyx_PyType_HasFeature(Py_TYPE(((PyObject *)__pyx_v_self)), (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {\n",
-       "    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS\n",
-       "    static PY_UINT64_T __pyx_tp_dict_version = __PYX_DICT_VERSION_INIT, __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;\n",
-       "    if (unlikely(!__Pyx_object_dict_version_matches(((PyObject *)__pyx_v_self), __pyx_tp_dict_version, __pyx_obj_dict_version))) {\n",
-       "      PY_UINT64_T __pyx_typedict_guard = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));\n",
-       "      #endif\n",
-       "      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_years); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "      __Pyx_GOTREF(__pyx_t_1);\n",
-       "      if (!__Pyx_IsSameCFunction(__pyx_t_1, (void*) __pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years)) {\n",
-       "        __Pyx_XDECREF(__pyx_r);\n",
-       "        __Pyx_INCREF(__pyx_t_1);\n",
-       "        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;\n",
-       "        __pyx_t_5 = 0;\n",
-       "        #if CYTHON_UNPACK_METHODS\n",
-       "        if (unlikely(PyMethod_Check(__pyx_t_3))) {\n",
-       "          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);\n",
-       "          if (likely(__pyx_t_4)) {\n",
-       "            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
-       "            __Pyx_INCREF(__pyx_t_4);\n",
-       "            __Pyx_INCREF(function);\n",
-       "            __Pyx_DECREF_SET(__pyx_t_3, function);\n",
-       "            __pyx_t_5 = 1;\n",
-       "          }\n",
-       "        }\n",
-       "        #endif\n",
-       "        {\n",
-       "          PyObject *__pyx_callargs[2] = {__pyx_t_4, NULL};\n",
-       "          __pyx_t_2 = __Pyx_PyObject_FastCall(__pyx_t_3, __pyx_callargs+1-__pyx_t_5, 0+__pyx_t_5);\n",
-       "          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
-       "          if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "          __Pyx_GOTREF(__pyx_t_2);\n",
-       "          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
-       "        }\n",
-       "        __pyx_r = __pyx_t_2;\n",
-       "        __pyx_t_2 = 0;\n",
-       "        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
-       "        goto __pyx_L0;\n",
-       "      }\n",
-       "      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS\n",
-       "      __pyx_tp_dict_version = __Pyx_get_tp_dict_version(((PyObject *)__pyx_v_self));\n",
-       "      __pyx_obj_dict_version = __Pyx_get_object_dict_version(((PyObject *)__pyx_v_self));\n",
-       "      if (unlikely(__pyx_typedict_guard != __pyx_tp_dict_version)) {\n",
-       "        __pyx_tp_dict_version = __pyx_obj_dict_version = __PYX_DICT_VERSION_INIT;\n",
-       "      }\n",
-       "      #endif\n",
-       "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
-       "      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS\n",
-       "    }\n",
-       "    #endif\n",
-       "  }\n",
-       "/* … */\n",
-       "  /* function exit code */\n",
-       "  __pyx_L1_error:;\n",
-       "  __Pyx_XDECREF(__pyx_t_1);\n",
-       "  __Pyx_XDECREF(__pyx_t_2);\n",
-       "  __Pyx_XDECREF(__pyx_t_3);\n",
-       "  __Pyx_XDECREF(__pyx_t_4);\n",
-       "  __Pyx_AddTraceback(\"_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06.unixtime.years\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
-       "  __pyx_r = 0;\n",
-       "  __pyx_L0:;\n",
-       "  __Pyx_XGIVEREF(__pyx_r);\n",
-       "  __Pyx_RefNannyFinishContext();\n",
-       "  return __pyx_r;\n",
-       "}\n",
-       "\n",
-       "/* Python wrapper */\n",
-       "static PyObject *__pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years(PyObject *__pyx_v_self, \n",
-       "#if CYTHON_METH_FASTCALL\n",
-       "PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds\n",
-       "#else\n",
-       "PyObject *__pyx_args, PyObject *__pyx_kwds\n",
-       "#endif\n",
-       "); /*proto*/\n",
-       "static PyMethodDef __pyx_mdef_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years = {\"years\", (PyCFunction)(void*)(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0};\n",
-       "static PyObject *__pyx_pw_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years(PyObject *__pyx_v_self, \n",
-       "#if CYTHON_METH_FASTCALL\n",
-       "PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds\n",
-       "#else\n",
-       "PyObject *__pyx_args, PyObject *__pyx_kwds\n",
-       "#endif\n",
-       ") {\n",
-       "  #if !CYTHON_METH_FASTCALL\n",
-       "  CYTHON_UNUSED Py_ssize_t __pyx_nargs;\n",
-       "  #endif\n",
-       "  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;\n",
-       "  PyObject *__pyx_r = 0;\n",
-       "  __Pyx_RefNannyDeclarations\n",
-       "  __Pyx_RefNannySetupContext(\"years (wrapper)\", 0);\n",
-       "  #if !CYTHON_METH_FASTCALL\n",
-       "  #if CYTHON_ASSUME_SAFE_MACROS\n",
-       "  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);\n",
-       "  #else\n",
-       "  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;\n",
-       "  #endif\n",
-       "  #endif\n",
-       "  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);\n",
-       "  if (unlikely(__pyx_nargs > 0)) {\n",
-       "    __Pyx_RaiseArgtupleInvalid(\"years\", 1, 0, 0, __pyx_nargs); return NULL;}\n",
-       "  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_FASTCALL(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, \"years\", 0))) return NULL;\n",
-       "  __pyx_r = __pyx_pf_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_2years(((struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *)__pyx_v_self));\n",
-       "\n",
-       "  /* function exit code */\n",
-       "  __Pyx_RefNannyFinishContext();\n",
-       "  return __pyx_r;\n",
-       "}\n",
-       "\n",
-       "static PyObject *__pyx_pf_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_2years(struct __pyx_obj_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime *__pyx_v_self) {\n",
-       "  PyObject *__pyx_r = NULL;\n",
-       "  __Pyx_XDECREF(__pyx_r);\n",
-       "  __pyx_t_1 = __pyx_f_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_years(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_1);\n",
-       "  __pyx_r = __pyx_t_1;\n",
-       "  __pyx_t_1 = 0;\n",
-       "  goto __pyx_L0;\n",
-       "\n",
-       "  /* function exit code */\n",
-       "  __pyx_L1_error:;\n",
-       "  __Pyx_XDECREF(__pyx_t_1);\n",
-       "  __Pyx_AddTraceback(\"_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06.unixtime.years\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
-       "  __pyx_r = NULL;\n",
-       "  __pyx_L0:;\n",
-       "  __Pyx_XGIVEREF(__pyx_r);\n",
-       "  __Pyx_RefNannyFinishContext();\n",
-       "  return __pyx_r;\n",
-       "}\n",
-       "/* … */\n",
-       "  __pyx_tuple__4 = PyTuple_Pack(1, __pyx_n_s_self); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_tuple__4);\n",
-       "  __Pyx_GIVEREF(__pyx_tuple__4);\n",
-       "/* … */\n",
-       "  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_8unixtime_3years, __Pyx_CYFUNCTION_CCLASS, __pyx_n_s_unixtime_years, NULL, __pyx_n_s_cython_magic_849b2be7ec3b5ecc6e, __pyx_d, ((PyObject *)__pyx_codeobj__5)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime, __pyx_n_s_years, __pyx_t_2) < 0) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "  PyType_Modified(__pyx_ptype_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime);\n",
-       "  __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(1, 0, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_leaver_cache_ipython_cytho, __pyx_n_s_years, 23, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
-       "
+24:         return self.values // 31556952
\n", - "
  __Pyx_XDECREF(__pyx_r);\n",
-       "  __pyx_t_1 = PyNumber_FloorDivide(((PyObject *)__pyx_v_self->values), __pyx_int_31556952); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_1);\n",
-       "  __pyx_r = __pyx_t_1;\n",
-       "  __pyx_t_1 = 0;\n",
-       "  goto __pyx_L0;\n",
-       "
 25: 
\n", - "
 26: 
\n", - "
 27: 
\n", - "
 28: 
\n", - "
 29: 
\n", - "
 30: 
\n", - "
 31: 
\n", - "
 32: 
\n", - "
 33:     # def __repr__(self):
\n", - "
 34:     #     return f"timeseries({self.dt})"
\n", - "
 35: 
\n", - "
+36: dt = np.array(["1970-01-01T00:00:00.000000000", "1970-01-01T00:00:01.000000000"], dtype=np.datetime64)
\n", - "
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_array); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_4);\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "  __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __Pyx_INCREF(__pyx_kp_u_1970_01_01T00_00_00_000000000);\n",
-       "  __Pyx_GIVEREF(__pyx_kp_u_1970_01_01T00_00_00_000000000);\n",
-       "  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_kp_u_1970_01_01T00_00_00_000000000)) __PYX_ERR(0, 36, __pyx_L1_error);\n",
-       "  __Pyx_INCREF(__pyx_kp_u_1970_01_01T00_00_01_000000000);\n",
-       "  __Pyx_GIVEREF(__pyx_kp_u_1970_01_01T00_00_01_000000000);\n",
-       "  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 1, __pyx_kp_u_1970_01_01T00_00_01_000000000)) __PYX_ERR(0, 36, __pyx_L1_error);\n",
-       "  __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_5);\n",
-       "  __Pyx_GIVEREF(__pyx_t_2);\n",
-       "  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2)) __PYX_ERR(0, 36, __pyx_L1_error);\n",
-       "  __pyx_t_2 = 0;\n",
-       "  __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_np); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_6);\n",
-       "  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_datetime64); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
-       "  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_7) < 0) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "  __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, __pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
-       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_dt, __pyx_t_7) < 0) __PYX_ERR(0, 36, __pyx_L1_error)\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "
+37: ts = unixtime(dt.astype('int64'))
\n", - "
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_dt); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 37, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_astype); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "  __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 37, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "  __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_54_cython_magic_849b2be7ec3b5ecc6e389fb8a681e42f5c86ed06_unixtime), __pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ts, __pyx_t_2) < 0) __PYX_ERR(0, 37, __pyx_L1_error)\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "
+38: print(ts.years())
\n", - "
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ts); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 38, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_years); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 38, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "  __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 38, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_2);\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "  __pyx_t_7 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 38, __pyx_L1_error)\n",
-       "  __Pyx_GOTREF(__pyx_t_7);\n",
-       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
-       "  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;\n",
-       "
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%cython --annotate\n", - "# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION\n", - "#distutils: extra_compile_args = -fopenmp\n", - "#distutils: extra_link_args = -fopenmp\n", - "# cython: language_level=3\n", - "# cython: boundscheck=False\n", - "# cython: wraparound=False\n", - "# cython: nonecheck=False\n", - "# cython: cdivision=True\n", - "cimport cython\n", - "import cython\n", - "cimport numpy as np\n", - "import numpy as np\n", - "np.import_array()\n", - "\n", - "\n", - "cdef class unixtime:\n", - " \n", - " cdef np.ndarray values\n", - " \n", - " def __cinit__(unixtime self, np.ndarray[np.int_t, ndim=1] values):\n", - " self.values = values\n", - " \n", - " cpdef years(unixtime self):\n", - " return self.values // 31556952\n", - "\n", - " \n", - "\n", - " \n", - "\n", - "\n", - "\n", - "\n", - " # def __repr__(self):\n", - " # return f\"timeseries({self.dt})\"\n", - "\n", - "dt = np.array([\"1970-01-01T00:00:00.000000000\", \"1970-01-01T00:00:01.000000000\"], dtype=np.datetime64)\n", - "ts = unixtime(dt.astype('int64'))\n", - "print(ts.years())" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Timeseries(years=array([1970, 2020, 2024, 2024], dtype=uint32), months=array([1, 2, 2, 2], dtype=uint32), days=array([ 1, 29, 29, 29], dtype=uint32), hours=array([0, 0, 0, 0], dtype=uint32), minutes=array([0, 0, 0, 0], dtype=uint32), seconds=array([0, 0, 1, 0], dtype=uint32), microseconds=array([0, 0, 0, 0], dtype=uint32))\n", - "years [1970 2020 2024 2024]\n", - "months [1 2 2 2]\n", - "days [ 1 29 29 29]\n", - "hours [0 0 0 0]\n", - "delta_t [40.23467888 71.66730358 73.94523658 73.94523658]\n", - "[[1970 2020 2024 2024]\n", - " [ 1 2 2 2]\n", - " [ 1 29 29 29]\n", - " [ 0 0 0 0]\n", - " [ 0 0 0 0]\n", - " [ 0 0 1 0]\n", - " [ 0 0 0 0]]\n", - "['1970-01-01T00:00:00.000000' '2020-02-29T00:00:00.000000'\n", - " '2024-02-29T00:00:01.000000' '2024-02-29T00:00:00.000000']\n", - "\n" - ] - }, - { - "data": { - "text/plain": [ - "(True, True)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import numpy as np\n", - "# np.array([\"1970-01-01T00:00:00.000000000\", \"1970-01-01T00:00:01.000000000\"], dtype=np.datetime64).astype(\"datetime64[Y]\").astype(np.int64) + 1970\n", - "from typing import Self\n", - "from typing import NamedTuple\n", - "\n", - "import nzthermo as nzt\n", - "\n", - "values = np.array([\n", - " \"1970-01-01T00:00:00.000000000\",\n", - " # a leap year\n", - " \"2020-02-29T00:00:00.000000000\",\n", - " \"2024-02-29T00:00:01.000000000\",\n", - " \"2024-02-29\",\n", - " \n", - " \n", - "], dtype=\"datetime64[ns]\")\n", - "\n", - "a = nzt.timeseries(values)\n", - " \n", - "print(\n", - "f\"\"\"\n", - "{a}\n", - "years {a.years}\n", - "months {a.months}\n", - "days {a.days}\n", - "hours {a.hours}\n", - "delta_t {a.delta_t}\n", - "{np.array(a)}\n", - "{a.to_datetime64()}\n", - "\"\"\"\n", - ")\n", - "\n", - "def degrees(x: float) -> float:\n", - " return x * 180 / np.pi\n", - "\n", - "def radians(x: float) -> float:\n", - " return x * np.pi / 180\n", - "\n", - "np.testing.assert_almost_equal(degrees(radians(1)), 1)\n", - "\n", - "np.deg2rad(1) == radians(1), np.rad2deg(1) == degrees(1)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1716201353.765075" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import datetime\n", - "nzt.timeseries(datetime.datetime.now().timestamp())" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebook.ipynb b/notebook.ipynb index d8622b7..345cba9 100644 --- a/notebook.ipynb +++ b/notebook.ipynb @@ -7102,7 +7102,7 @@ "Td0 = Td[:, 0]\n", "TIME, LAT, LON = (temperature.shape[0],) + temperature.shape[2:]\n", "prof = nzt.parcel_profile(P, T0, Td0) # (T, Y, X, Z)\n", - "CAPE, CIN = nzt.cape_cin(P, T, Td, prof, fast_approximate=True)\n", + "CAPE, CIN = nzt.cape_cin(P, T, Td, prof)\n", "CAPE, CIN = CAPE.reshape(TIME, LAT, LON), CIN.reshape(TIME, LAT, LON)\n", "\n", "cape = np.where(CAPE < 8000, CAPE, 8000)\n", @@ -7168,7 +7168,7 @@ "\n", " prof = nzt.parcel_profile(P, T[:, 0], Td[:, 0])\n", "\n", - " CAPE, CIN = nzt.cape_cin(P, T, Td, prof, fast_approximate=True)\n", + " CAPE, CIN = nzt.cape_cin(P, T, Td, prof)\n", "\n", " CAPE = CAPE.reshape(Y, X)\n", " CIN = CIN.reshape(Y, X)\n",