{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Dubois surface inversion tutorial\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook shows how to run the Dubois surface inversion on the UAVSAR multilooked GRD covariance product for `winnip_09002_12060_004_120714_L090_CX_02`, together with a matching incidence-angle raster.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How the input product was prepared\n",
    "\n",
    "The example data used here were prepared in three steps:\n",
    "\n",
    "- Download the free UAVSAR multilooked GRD covariance product for `winnip_09002_12060_004_120714_L090_CX_02` from the [UAVSAR website](https://uavsar.jpl.nasa.gov/).\n",
    "- Import the covariance product into ESA SNAP and export it to NetCDF-BEAM format.\n",
    "- Download the matching incidence-angle file for the same scene and use the annotation file (`.ann`) to retrieve the original incidence-angle raster dimensions.\n",
    "\n",
    "In the notebook below we read the NetCDF-BEAM covariance product with `open_netcdf_beam`, load the incidence-angle raster, downsample it to match the multilooked grid, and then pass both inputs to `dubois_surface_inversion`.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Import packages and set directories\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "from pathlib import Path\n",
    "\n",
    "import numpy as np\n",
    "import xarray as xr\n",
    "from dask.diagnostics import ProgressBar\n",
    "\n",
    "from polsarpro.io import open_netcdf_beam\n",
    "from polsarpro.physical_inversion import dubois_surface_inversion\n",
    "\n",
    "# change these paths to match your local files\n",
    "product_id = \"winnip_09002_12060_004_120714_L090_CX_02\"\n",
    "\n",
    "input_uavsar_nc = Path(f\"/data/psp/test_files/{product_id}_ML5X5.nc\")\n",
    "incidence_angle_file = Path(f\"/data/psp/test_files/{product_id}.inc\")\n",
    "output_dir = Path(\"/data/psp/res\")\n",
    "output_dir.mkdir(parents=True, exist_ok=True)\n",
    "file_out = output_dir / 'dubois_surface_inversion_winnip_python.nc'\n",
    "\n",
    "# Dubois expects GHz; UAVSAR metadata stores the center wavelength in cm.\n",
    "with xr.open_dataset(input_uavsar_nc) as raw_ds:\n",
    "    center_wavelength_cm = raw_ds[\"metadata\"].attrs[\"Annotation:CenterWavelength\"]\n",
    "\n",
    "freq_ghz = 29.9792458 / float(center_wavelength_cm)\n",
    "\n",
    "# Same parameter values used in the comparison notebook.\n",
    "thresh1_db = 0.0\n",
    "thresh2_db = 0.0\n",
    "calibration_coeff = 1.0\n",
    "\n",
    "print(f\"Derived radar frequency: {freq_ghz:.6f} GHz\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load the input product\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "C3 = open_netcdf_beam(input_uavsar_nc)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load and resample the incidence angle\n",
    "\n",
    "We first open the incidence-angle raster at its original dimensions, then downsample it so it matches the 5x5 geocoded image used by the C3 product.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "row_dim, col_dim = C3.dims\n",
    "\n",
    "# use lines from .ann file (infer from auxiliary file)\n",
    "# hgt.set_rows                         (pixels)        = 3767                   ; HGT Lines\n",
    "# hgt.set_cols                         (pixels)        = 11636                  ; HGT Samples\n",
    "nlines = 3767\n",
    "ncols = 11636\n",
    "\n",
    "# The incidence-angle file is a little-endian float32 stream in radians.\n",
    "# Read only the raster-sized prefix and reshape it to the UAVSAR grid.\n",
    "incidence_angle_values = np.fromfile(\n",
    "    incidence_angle_file,\n",
    "    dtype=\"<f4\",\n",
    "    count=nlines * ncols,\n",
    ")\n",
    "\n",
    "# Reduce to the same dimensions as multilooked 5x5 image.\n",
    "incidence_angle_values[incidence_angle_values == -10000] = np.nan\n",
    "incidence_angle = xr.DataArray(\n",
    "    incidence_angle_values.reshape(nlines, ncols),\n",
    "    dims=(row_dim, col_dim),\n",
    "    name=\"incidence_angle\",\n",
    ").coarsen(y=5, x=5, boundary=\"trim\").mean()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Apply the inversion\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if file_out.exists():\n",
    "    file_out.unlink()\n",
    "with ProgressBar():\n",
    "    dubois_surface_inversion(\n",
    "        C3,\n",
    "        incidence_angle=incidence_angle,\n",
    "        freq_ghz=freq_ghz,\n",
    "        thresh1=thresh1_db,\n",
    "        thresh2=thresh2_db,\n",
    "        calibration_coeff=calibration_coeff,\n",
    "    ).to_netcdf(file_out)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load the output file\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = xr.open_dataset(file_out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also plot the main Dubois outputs directly:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "res.dubois_ks.plot.imshow(cmap='viridis', vmax=0.5, interpolation='bilinear', figsize=(7,7))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "res.dubois_er.plot.imshow(cmap='viridis', vmax=20, interpolation='bilinear', figsize=(7,7))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "res.dubois_mv.plot.imshow(cmap='viridis', vmax=100, interpolation='bilinear', figsize=(7,7))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "res.dubois_mask_valid_in_out.plot.imshow(cmap='viridis', interpolation='bilinear', figsize=(7,7))\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 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.12.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
