{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Search SWOT passes\n",
    "\n",
    "This notebook is similar to the notebook [main](main.ipynb) but it uses the the\n",
    "public API of the module to search for SWOT passes using the programmatic\n",
    "interface instead of the\n",
    "[voila](https://voila.readthedocs.io/en/stable/using.html) interface.\n",
    "\n",
    "First, we import the module and create the application object. It is not\n",
    "mandatory to create the application object but it is useful to have access to\n",
    "the GUI to create the bounding box."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from search_swot.widgets import MapSelection, compute_selected_passes\n",
    "from search_swot.orbit import get_selected_passes, get_pass_passage_time\n",
    "\n",
    "app = MapSelection()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Display the GUI to create the bounding box."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "app.display()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The easiest way to get the selected passes is to use the method provided by the application."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pyinterp\n",
    "import warnings\n",
    "\n",
    "if app.selection is None:\n",
    "    warnings.warn('No selection has been done with the GUI, '\n",
    "                  'a default selection is used')\n",
    "    app.selection = pyinterp.geodetic.Polygon.read_wkt(\n",
    "        'POLYGON((-48 -12,-48 42,0 42,0 -12,-48 -12))')\n",
    "df = compute_selected_passes(app.date_selection, app)\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To save the result in a CSV file execute: `df.to_csv(\"passes.csv\")`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## API\n",
    "\n",
    "An other way to get the selected passes is to use the function provided by the package.\n",
    "The following code computes the selected passes for the next 72 hours. The first\n",
    "parameter is the current time, the second parameter is the time interval.\n",
    "\n",
    "*Adjust the parameters as needed.*\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy\n",
    "\n",
    "df = get_selected_passes(numpy.datetime64('now'), numpy.timedelta64(3, 'D'))\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we compute the passage time for the selected passes for a given polygon.\n",
    "Here you have two options:\n",
    "\n",
    "1. Use the polygon defined in the app : `app.selection`\n",
    "2. Define your own polygon, using the\n",
    "   [WKT](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry)\n",
    "   format.\n",
    "3. Define your own polygon, using [GeoJSON](https://en.wikipedia.org/wiki/GeoJSON)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bbox = pyinterp.geodetic.Polygon.read_wkt(\n",
    "    'POLYGON((-6 36,-6 60,36 60,36 36,-6 36))')\n",
    "bbox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas\n",
    "\n",
    "df = pandas.DataFrame(get_pass_passage_time(selected_passes=df, polygon=bbox))\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## To display the SWATH with matplotlib\n",
    "\n",
    "The last section of this notebook shows how to plot the selected passes with\n",
    "matplotlib."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from search_swot.widgets import load_polygons"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "left_swath, right_swath = load_polygons(df['pass_number'].values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cartopy.crs\n",
    "import matplotlib.pyplot\n",
    "import matplotlib\n",
    "import matplotlib.patches\n",
    "import matplotlib.colors\n",
    "import matplotlib.cm\n",
    "\n",
    "color_norm = matplotlib.colors.Normalize(vmin=0,\n",
    "                                         vmax=df['pass_number'].values.max())\n",
    "color_map = matplotlib.cm.ScalarMappable(norm=color_norm, cmap='jet')\n",
    "\n",
    "fig = matplotlib.pyplot.figure(figsize=(10, 10))\n",
    "ax = fig.add_subplot(1, 1, 1, projection=cartopy.crs.PlateCarree())\n",
    "ax.coastlines()\n",
    "ax.gridlines()\n",
    "\n",
    "points = bbox.outer\n",
    "lons = numpy.array([p.lon for p in points])\n",
    "lats = numpy.array([p.lat for p in points])\n",
    "labels = {}\n",
    "\n",
    "ax.plot(lons, lats, transform=cartopy.crs.Geodetic(), color='red')\n",
    "for pass_number, item in left_swath:\n",
    "    item = item.intersection(bbox)\n",
    "    if len(item) == 0:\n",
    "        continue\n",
    "    outer = item[0].outer\n",
    "    poly = matplotlib.patches.Polygon([(p.lon, p.lat) for p in outer],\n",
    "                                      transform=cartopy.crs.PlateCarree(),\n",
    "                                      facecolor=color_map.to_rgba(pass_number),\n",
    "                                      alpha=0.5)\n",
    "    labels[pass_number] = True\n",
    "    poly.set_label(f'Pass {pass_number}')\n",
    "    ax.add_patch(poly)\n",
    "\n",
    "for pass_number, item in right_swath:\n",
    "    item = item.intersection(bbox)\n",
    "    if len(item) == 0:\n",
    "        continue\n",
    "    outer = item[0].outer\n",
    "    poly = matplotlib.patches.Polygon([(p.lon, p.lat) for p in outer],\n",
    "                                      transform=cartopy.crs.PlateCarree(),\n",
    "                                      facecolor=color_map.to_rgba(pass_number),\n",
    "                                      alpha=0.5)\n",
    "    if pass_number not in labels:\n",
    "        poly.set_label(f'Pass {pass_number}')\n",
    "    ax.add_patch(poly)\n",
    "handles, labels = ax.get_legend_handles_labels()\n",
    "ax.legend(handles, labels, loc='lower left')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}