{ "cells": [ { "cell_type": "markdown", "id": "eda45022-441d-4c7d-88f2-6ed58dbc41bf", "metadata": {}, "source": [ "## Function to convert IRGASON sonic horizontal wind components to zonal and meridional wind components\n", "\n", "### $u_{sonic\\_x},\\ u_{sonic\\_y} \\ \\rightarrow \\ u_{zonal},\\ u_{meridional}$\n", "\n", "Manda Chasteen | Leidos, Inc.
\n", "April 2026\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "b4920441-c577-450f-a7b4-dd608597a49a", "metadata": {}, "source": [ "### Background:" ] }, { "cell_type": "markdown", "id": "e5810204-873a-4f8d-ab80-fcf14997af1d", "metadata": {}, "source": [ "The Dozier Snow Site at Mammoth Mountain, CA, has two Campbell Scientific IRGASON eddy covariance systems. IRGASON #1 is mounted to the wind mast on the southwest corner of the instrument platform. IRGASON #2 is mounted to the adjustable boom that is manually raised/lowered to stay approximately 1 m above the snow surface. Both systems are oriented toward the south (i.e., `sonic_azimuth` $\\approx$ 180°) and collect measurements at 10 Hz. \n", "\n", "As of April 2026, the logger program for the IRGASONs does not include any coordinate transformations for the wind measurements. Thus, the $Ux$, $Uy$, and $Uz$ wind components are in the instruments' sonic coordinate system, which is defined such that the instrument is pointed into $-x$, which is by default oriented toward the north (i.e., `sonic_azimuth` is assumed to be 0°). At the Dozier Site, the instruments' $-x$ axis is directed toward 180° in earth-relative coordinates.\n", "\n", "The main function contained in this notebook transforms the horizontal wind components into earth-relative coordinates for analysis. If processing the IRGASON data with another program (e.g., EddyFlux), `sonic_azimuth` should be set to 180°.\n", "\n", "Site webpage: https://snow.ucsb.edu/index.php/site-description/
\n", "IRGASON manual: https://s.campbellsci.com/documents/us/manuals/irgason.pdf" ] }, { "cell_type": "markdown", "id": "f47461cc-b963-478b-96cb-82a26367fa3e", "metadata": {}, "source": [ "### Equations:\n", "\n", "#### $u_{zonal}\\quad\\quad =\\ -u_{sonic\\_x}\\, *\\, sin(\\theta)\\; +\\; u_{sonic\\_y}\\, *\\, cos(\\theta)$\n", "\n", "#### $v_{meridional}\\ =\\ -u_{sonic\\_x}\\, *\\, cos(\\theta)\\; -\\; u_{sonic\\_y}\\, *\\, sin(\\theta)$\n", "
\n", "\n", "$\\theta\\; \\rightarrow\\;$ `sonic_azimuth` [direction instrument is pointing in meteorological coordinate system]
\n", "– *Default setting = 0°; assumes that IRGASON is pointed toward the north*" ] }, { "cell_type": "markdown", "id": "60d5663c-cc63-4b3e-8087-fec9f3fb6d4b", "metadata": {}, "source": [ "### Functions:" ] }, { "cell_type": "code", "execution_count": 1, "id": "4346850d-f187-48e6-9bce-0932c9d1af39", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "def convert_sonic_winds_to_uv(u_x, u_y, sonic_azimuth=180):\n", " \"\"\"\n", " Convert IRGASON sonic horizontal wind components to earth-relative zonal and meridional wind components\n", "\n", " Parameters\n", " ----------\n", " u_x : float or array-like\n", " Sonic x-component of wind. Positive along the +x axis of the instrument.\n", " u_y : float or array-like\n", " Sonic y-component of wind. Positive 90° counterclockwise from +x.\n", " sonic_azimuth : float, optional\n", " Azimuth (degrees) of the sonic's -x axis measured clockwise from true north.\n", " Default is 180° for the IRGASONs at the Dozier Site (-x points south).\n", "\n", " Returns\n", " -------\n", " u_zonal : float or array-like\n", " Zonal wind component, where positive values indicate westerly (eastward) flow.\n", " u_meridional : float or array-like\n", " Meridional wind component, where positive values indicate southerly (northward) flow.\n", "\n", " Notes\n", " -----\n", " * The default sonic_azimuth in Campbell Scientific logger software is 0°, which assumes \n", " that the instrument's -x axis points toward the north. \n", "\n", " * Here we adopt the meteorological coordinate convention for sonic_azimuth angle, where\n", " the angle increases moving clockwise from north (e.g., IRGASON pointing toward the east\n", " has a sonic_azimuth angle of 90°, toward the south = 180°, toward the west = 270°, etc.).\n", " This *may not* be the same convention that is used in the Campbell Scientific programs but\n", " it forms the basis of the equations used here to derive the earth-relative wind components. \n", " \n", " * For the Dozier Site IRGASONs, a sonic_azimuth of 0° was assumed in the datalogger program,\n", " so the u and v wind components in earth-relative coordinates must be derived.\n", " \n", " * The orientation and true sonic_azimuth angle of IRGASON #1 and IRGASON #2 is 180° (i.e.,\n", " both instruments point toward the south)\n", "\n", " Reference: https://s.campbellsci.com/documents/us/manuals/irgason.pdf \n", " \n", " \"\"\"\n", " \n", " # Convert angle to radians:\n", " sonic_azimuth_rad = np.deg2rad(sonic_azimuth)\n", "\n", " # Zonal wind component:\n", " u_zonal = -u_x * np.sin(sonic_azimuth_rad) + u_y * np.cos(sonic_azimuth_rad)\n", "\n", " # Meridional wind component:\n", " u_meridional = -u_x * np.cos(sonic_azimuth_rad) - u_y * np.sin(sonic_azimuth_rad)\n", " \n", " return u_zonal, u_meridional \n", "\n", "\n", "def calc_wind_direction(u, v):\n", " \"\"\"\n", " Compute meteorological wind direction from zonal and meridional wind components\n", "\n", " Parameters\n", " ----------\n", " u : float or array-like\n", " Zonal wind component, where positive values indicate westerly (eastward) flow.\n", " v : float or array-like\n", " Meridional wind component, where positive values indicate southerly (northward) flow.\n", "\n", " Returns\n", " -------\n", " winddir : float or array-like\n", " Wind direction (degrees), defined as the direction *from which* the wind\n", " is blowing, measured clockwise from true north (0–360°).\n", "\n", " Notes\n", " -----\n", " - Output is normalized to the range [0, 360).\n", " \"\"\"\n", "\n", " # Calculate wind direction:\n", " winddir = 90.0 - np.rad2deg(np.arctan2(-v, -u))\n", "\n", " # Normalize to 0-360°:\n", " mask = np.array(winddir < 0)\n", " if np.any(mask):\n", " winddir[mask] += 360\n", " \n", " return winddir\n", "\n", "\n", "def calc_wind_speed(u, v):\n", " \"\"\"\n", " Compute horizontal wind speed from wind components.\n", "\n", " Parameters\n", " ----------\n", " u : float or array-like\n", " x-wind component \n", " v : float or array-like\n", " y-wind component \n", "\n", " Returns\n", " -------\n", " windspeed : float or array-like\n", " Wind speed, computed as the magnitude of the horizontal wind vector.\n", " \"\"\"\n", " return np.sqrt(u**2 + v**2)" ] }, { "cell_type": "code", "execution_count": null, "id": "24cea9ba-7c73-4a21-bfc7-d770ad472a8f", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "point_clouds", "language": "python", "name": "point_clouds" }, "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.12" } }, "nbformat": 4, "nbformat_minor": 5 }