{ "cells": [ { "cell_type": "markdown", "id": "1c6be7d5", "metadata": {}, "source": [ "# Usage of torchMWRT\n", "\n", "`torchMWRT` is a PyTorch translation of the radiative transfer calculation core of `PyRTlib`. It is designed to be faster than the original `PyRTlib` while still producing the same results.\n", "\n", "This is achieved by vectorizing all calculations over frequencies, angles, height levels, and any leading dimensions such as time or location. The calculations can be further accelerated using GPU support provided by PyTorch, although this is not necessary in most cases.\n", "\n", "The following code demonstrates how to use torchMWRT to calculate brightness temperatures." ] }, { "cell_type": "code", "execution_count": 1, "id": "8bd5280f", "metadata": {}, "outputs": [], "source": [ "%config InlineBackend.figure_format = 'svg'\n", "\n", "import numpy as np\n", "import xarray as xr\n", "import time\n", "import matplotlib.pyplot as plt\n", "\n", "from torchMWRT import AtmProfile, RTModel\n", "\n", "FREQS = np.array([22.24,23.04,23.84,25.44,26.24,27.84,31.40,51.26,52.28,53.86,54.94,56.66,57.30,58.00])\n", "ANGLES = np.array([90.0], dtype=float)\n", "\n", "DATA_DIR = '../../../../data'" ] }, { "cell_type": "markdown", "id": "feb58ec5", "metadata": {}, "source": [ "Let's start by loading the radiosonde data set created in the [Create a Retrieval](#create_retrieval) Section." ] }, { "cell_type": "code", "execution_count": 2, "id": "fece5f1f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 147MB\n",
       "Dimensions:  (synop: 22040, height: 208)\n",
       "Coordinates:\n",
       "  * synop    (synop) datetime64[ns] 176kB 1990-01-01 ... 2026-02-21\n",
       "  * height   (height) int64 2kB 0 10 25 50 75 ... 28000 28500 29000 29500 30000\n",
       "Data variables:\n",
       "    T        (synop, height) float64 37MB 267.1 267.1 267.1 ... 219.6 220.5\n",
       "    p        (synop, height) float64 37MB 963.2 962.0 960.2 ... 10.73 9.947\n",
       "    rh       (synop, height) float64 37MB 96.6 95.27 93.27 ... 2.035 2.066 2.088\n",
       "    lwc      (synop, height) float64 37MB 0.0 0.007414 0.01853 ... 0.0 0.0 0.0\n",
       "Attributes:\n",
       "    station_id:      03715\n",
       "    station_name:    Oberschleißheim (Lustheim)\n",
       "    station_height:  484\n",
       "    station_lat:     48.2446\n",
       "    station_lon:     11.5525
" ], "text/plain": [ " Size: 147MB\n", "Dimensions: (synop: 22040, height: 208)\n", "Coordinates:\n", " * synop (synop) datetime64[ns] 176kB 1990-01-01 ... 2026-02-21\n", " * height (height) int64 2kB 0 10 25 50 75 ... 28000 28500 29000 29500 30000\n", "Data variables:\n", " T (synop, height) float64 37MB 267.1 267.1 267.1 ... 219.6 220.5\n", " p (synop, height) float64 37MB 963.2 962.0 960.2 ... 10.73 9.947\n", " rh (synop, height) float64 37MB 96.6 95.27 93.27 ... 2.035 2.066 2.088\n", " lwc (synop, height) float64 37MB 0.0 0.007414 0.01853 ... 0.0 0.0 0.0\n", "Attributes:\n", " station_id: 03715\n", " station_name: Oberschleißheim (Lustheim)\n", " station_height: 484\n", " station_lat: 48.2446\n", " station_lon: 11.5525" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds = xr.load_dataset(f\"{DATA_DIR}/sites/munich_G5/radiosonde/radiosonde_data_03715.nc\")[['T', 'p', 'rh', 'lwc']]\n", "ds" ] }, { "cell_type": "markdown", "id": "97d061c4", "metadata": {}, "source": [ "## Run torchMWRT for a Single Profile" ] }, { "cell_type": "code", "execution_count": 3, "id": "19ee0aab", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", " \n", " 2026-02-26T14:02:55.282119\n", " image/svg+xml\n", " \n", " \n", " Matplotlib v3.10.8, https://matplotlib.org/\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 8kB\n",
       "Dimensions:  (height: 208)\n",
       "Coordinates:\n",
       "  * height   (height) int64 2kB 0 10 25 50 75 ... 28000 28500 29000 29500 30000\n",
       "    synop    datetime64[ns] 8B 2026-02-21\n",
       "Data variables:\n",
       "    T        (height) float64 2kB 274.9 275.3 275.6 275.9 ... 218.5 219.6 220.5\n",
       "    p        (height) float64 2kB 966.6 965.4 963.6 960.7 ... 11.59 10.73 9.947\n",
       "    rh       (height) float64 2kB 87.0 92.0 94.73 90.0 ... 2.035 2.066 2.088\n",
       "    lwc      (height) float64 2kB 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0\n",
       "Attributes:\n",
       "    station_id:      03715\n",
       "    station_name:    Oberschleißheim (Lustheim)\n",
       "    station_height:  484\n",
       "    station_lat:     48.2446\n",
       "    station_lon:     11.5525
" ], "text/plain": [ " Size: 8kB\n", "Dimensions: (height: 208)\n", "Coordinates:\n", " * height (height) int64 2kB 0 10 25 50 75 ... 28000 28500 29000 29500 30000\n", " synop datetime64[ns] 8B 2026-02-21\n", "Data variables:\n", " T (height) float64 2kB 274.9 275.3 275.6 275.9 ... 218.5 219.6 220.5\n", " p (height) float64 2kB 966.6 965.4 963.6 960.7 ... 11.59 10.73 9.947\n", " rh (height) float64 2kB 87.0 92.0 94.73 90.0 ... 2.035 2.066 2.088\n", " lwc (height) float64 2kB 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0\n", "Attributes:\n", " station_id: 03715\n", " station_name: Oberschleißheim (Lustheim)\n", " station_height: 484\n", " station_lat: 48.2446\n", " station_lon: 11.5525" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds_date = ds.isel(synop= -1)\n", "\n", "fig, axs = plt.subplots(ncols=3, sharey=True, figsize=(8, 4), constrained_layout=True)\n", "\n", "ds_date['T'].sel(height=slice(0,10000)).plot(y='height', ax=axs[0])\n", "ds_date['rh'].sel(height=slice(0,10000)).plot(y='height', ax=axs[1])\n", "ds_date['lwc'].sel(height=slice(0,10000)).plot(y='height', ax=axs[2])\n", "\n", "for i, ax in enumerate(axs):\n", " ax.set_ylabel(\"\" if i > 0 else \"Height [m]\")\n", " ax.set_title('')\n", "fig.suptitle('Single Radiosonde Profile')\n", "\n", "plt.show()\n", "\n", "ds_date" ] }, { "cell_type": "markdown", "id": "465d12f1", "metadata": {}, "source": [ "The first step is to create an instance of the `RTModel` class, which owns the radiative transfer code. In the initialization, all the settings are defined, such as the frequencies and angles for which the calculations should be performed, the absorption model to use, whether to simulate measurements from the surface or from a satellite." ] }, { "cell_type": "code", "execution_count": 4, "id": "6186cf64", "metadata": {}, "outputs": [], "source": [ "rtmodel = RTModel(freqs=FREQS, angles=ANGLES, absmdl=\"R17\")" ] }, { "cell_type": "markdown", "id": "9774b6a5", "metadata": {}, "source": [ "The next step is to create an `AtmProfile` object, which holds the atmospheric profile data. The `AtmProfile` class is designed to be flexible and can handle different input types, like numpy arrays, xarray DataArrays, or PyTorch tensors. The only requirement is that they all share the same height dimension / coordinate. To run a clear sky simulation just omit the lwc and the iwc variables." ] }, { "cell_type": "code", "execution_count": 5, "id": "1a14699f", "metadata": {}, "outputs": [], "source": [ "atm_profile = AtmProfile(\n", " temperature=ds_date[\"T\"],\n", " height=ds_date[\"height\"],\n", " pressure=ds_date[\"p\"],\n", " rh=ds_date[\"rh\"] / 100.0,\n", " lwc=ds_date[\"lwc\"],\n", ")" ] }, { "cell_type": "markdown", "id": "0981d38c", "metadata": {}, "source": [ "Finally, the `execute` method of the `RTModel` instance is called to perform the radiative transfer calculations. The results can be returned as an xarray Dataset." ] }, { "cell_type": "code", "execution_count": 6, "id": "2970850c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'tbtotal' (frq: 14, ang: 1)> Size: 112B\n",
       "array([[ 28.81278599],\n",
       "       [ 27.64180941],\n",
       "       [ 24.29956104],\n",
       "       [ 19.07339972],\n",
       "       [ 17.68918404],\n",
       "       [ 16.42028042],\n",
       "       [ 16.89313523],\n",
       "       [104.27898408],\n",
       "       [142.87996218],\n",
       "       [239.04810181],\n",
       "       [269.35150176],\n",
       "       [274.62096968],\n",
       "       [275.0700758 ],\n",
       "       [275.33194293]])\n",
       "Coordinates:\n",
       "  * frq      (frq) float64 112B 22.24 23.04 23.84 25.44 ... 56.66 57.3 58.0\n",
       "  * ang      (ang) float64 8B 90.0
" ], "text/plain": [ " Size: 112B\n", "array([[ 28.81278599],\n", " [ 27.64180941],\n", " [ 24.29956104],\n", " [ 19.07339972],\n", " [ 17.68918404],\n", " [ 16.42028042],\n", " [ 16.89313523],\n", " [104.27898408],\n", " [142.87996218],\n", " [239.04810181],\n", " [269.35150176],\n", " [274.62096968],\n", " [275.0700758 ],\n", " [275.33194293]])\n", "Coordinates:\n", " * frq (frq) float64 112B 22.24 23.04 23.84 25.44 ... 56.66 57.3 58.0\n", " * ang (ang) float64 8B 90.0" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_ds = rtmodel.execute(atm_profile, return_ds=True)\n", "result_ds[\"tbtotal\"]" ] }, { "cell_type": "markdown", "id": "7c74c790", "metadata": {}, "source": [ "## Run torchMWRT for Multiple Profiles\n", "\n", "The `RTModel` and `AtmProfile` classes are designed to be run on multiple profiles in parallel / vectorized. To do this, simply add leading dimensions to the profile variables, for example by stacking multiple profiles along a new \"time\" dimension. The `execute` method will automatically perform the calculations for all profiles in parallel and return the results with the same leading dimensions. \n", "\n", "In this example, the code is executed on 1000 profiles. Note that the `RTModel` instance can be reused for different profiles, so the initialization overhead is incurred only once." ] }, { "cell_type": "code", "execution_count": 7, "id": "27f03b17", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 7MB\n",
       "Dimensions:  (synop: 1000, height: 208)\n",
       "Coordinates:\n",
       "  * synop    (synop) datetime64[ns] 8kB 2024-10-20T12:00:00 ... 2026-02-20T18...\n",
       "  * height   (height) int64 2kB 0 10 25 50 75 ... 28000 28500 29000 29500 30000\n",
       "Data variables:\n",
       "    T        (synop, height) float64 2MB 288.3 287.3 286.2 ... 203.6 206.2 208.4\n",
       "    p        (synop, height) float64 2MB 967.0 965.8 964.1 ... 10.14 9.334 8.595\n",
       "    rh       (synop, height) float64 2MB 80.14 85.86 92.2 92.58 ... 2.0 2.0 2.0\n",
       "    lwc      (synop, height) float64 2MB 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0\n",
       "Attributes:\n",
       "    station_id:      03715\n",
       "    station_name:    Oberschleißheim (Lustheim)\n",
       "    station_height:  484\n",
       "    station_lat:     48.2446\n",
       "    station_lon:     11.5525
" ], "text/plain": [ " Size: 7MB\n", "Dimensions: (synop: 1000, height: 208)\n", "Coordinates:\n", " * synop (synop) datetime64[ns] 8kB 2024-10-20T12:00:00 ... 2026-02-20T18...\n", " * height (height) int64 2kB 0 10 25 50 75 ... 28000 28500 29000 29500 30000\n", "Data variables:\n", " T (synop, height) float64 2MB 288.3 287.3 286.2 ... 203.6 206.2 208.4\n", " p (synop, height) float64 2MB 967.0 965.8 964.1 ... 10.14 9.334 8.595\n", " rh (synop, height) float64 2MB 80.14 85.86 92.2 92.58 ... 2.0 2.0 2.0\n", " lwc (synop, height) float64 2MB 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0\n", "Attributes:\n", " station_id: 03715\n", " station_name: Oberschleißheim (Lustheim)\n", " station_height: 484\n", " station_lat: 48.2446\n", " station_lon: 11.5525" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds_1000 = ds.isel(synop=slice(-1001, -1))\n", "ds_1000" ] }, { "cell_type": "code", "execution_count": 8, "id": "46f32134", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Elapsed time: 1.658 seconds\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'tbtotal' (synop: 1000, frq: 14, ang: 1)> Size: 112kB\n",
       "array([[[ 52.05499361],\n",
       "        [ 49.30037352],\n",
       "        [ 41.6287104 ],\n",
       "        ...,\n",
       "        [284.93592111],\n",
       "        [284.95471599],\n",
       "        [284.93810103]],\n",
       "\n",
       "       [[ 50.32336476],\n",
       "        [ 47.43428159],\n",
       "        [ 39.85995939],\n",
       "        ...,\n",
       "        [285.606027  ],\n",
       "        [285.5579183 ],\n",
       "        [285.45227132]],\n",
       "\n",
       "       [[ 46.84885243],\n",
       "        [ 44.088421  ],\n",
       "        [ 37.03379201],\n",
       "        ...,\n",
       "...\n",
       "        ...,\n",
       "        [270.06910101],\n",
       "        [270.4867661 ],\n",
       "        [270.76314251]],\n",
       "\n",
       "       [[ 24.26275865],\n",
       "        [ 23.2799833 ],\n",
       "        [ 20.28705312],\n",
       "        ...,\n",
       "        [270.77442228],\n",
       "        [271.1585723 ],\n",
       "        [271.41547469]],\n",
       "\n",
       "       [[ 28.77178129],\n",
       "        [ 28.1277405 ],\n",
       "        [ 25.38258218],\n",
       "        ...,\n",
       "        [272.39975957],\n",
       "        [272.7973637 ],\n",
       "        [273.05728277]]], shape=(1000, 14, 1))\n",
       "Coordinates:\n",
       "  * synop    (synop) datetime64[ns] 8kB 2024-10-20T12:00:00 ... 2026-02-20T18...\n",
       "  * frq      (frq) float64 112B 22.24 23.04 23.84 25.44 ... 56.66 57.3 58.0\n",
       "  * ang      (ang) float64 8B 90.0
" ], "text/plain": [ " Size: 112kB\n", "array([[[ 52.05499361],\n", " [ 49.30037352],\n", " [ 41.6287104 ],\n", " ...,\n", " [284.93592111],\n", " [284.95471599],\n", " [284.93810103]],\n", "\n", " [[ 50.32336476],\n", " [ 47.43428159],\n", " [ 39.85995939],\n", " ...,\n", " [285.606027 ],\n", " [285.5579183 ],\n", " [285.45227132]],\n", "\n", " [[ 46.84885243],\n", " [ 44.088421 ],\n", " [ 37.03379201],\n", " ...,\n", "...\n", " ...,\n", " [270.06910101],\n", " [270.4867661 ],\n", " [270.76314251]],\n", "\n", " [[ 24.26275865],\n", " [ 23.2799833 ],\n", " [ 20.28705312],\n", " ...,\n", " [270.77442228],\n", " [271.1585723 ],\n", " [271.41547469]],\n", "\n", " [[ 28.77178129],\n", " [ 28.1277405 ],\n", " [ 25.38258218],\n", " ...,\n", " [272.39975957],\n", " [272.7973637 ],\n", " [273.05728277]]], shape=(1000, 14, 1))\n", "Coordinates:\n", " * synop (synop) datetime64[ns] 8kB 2024-10-20T12:00:00 ... 2026-02-20T18...\n", " * frq (frq) float64 112B 22.24 23.04 23.84 25.44 ... 56.66 57.3 58.0\n", " * ang (ang) float64 8B 90.0" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "start = time.perf_counter()\n", "\n", "atm_profile = AtmProfile(\n", " temperature=ds_1000[\"T\"],\n", " height=ds_1000[\"height\"],\n", " pressure=ds_1000[\"p\"],\n", " rh=ds_1000[\"rh\"] / 100.0,\n", " lwc=ds_1000[\"lwc\"],\n", ")\n", "result_ds = rtmodel.execute(atm_profile, return_ds=True)\n", "\n", "end = time.perf_counter()\n", "\n", "print(f\"Elapsed time: {end - start:.3f} seconds\")\n", "\n", "result_ds[\"tbtotal\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "8739b42b", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "venv (3.14.3)", "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.14.3" } }, "nbformat": 4, "nbformat_minor": 5 }