{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "0cb477d3", "metadata": { "ExecuteTime": { "end_time": "2023-01-30T06:09:49.902813Z", "start_time": "2023-01-30T06:09:49.080321Z" } }, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from multiprocessing import Pool\n", "import shapely.geometry as sgeom\n", "import cartopy as ctp\n", "import cartopy.crs as ccrs\n", "import matplotlib.cm as cm\n", "import matplotlib.pyplot as plt\n", "import matplotlib.ticker as mticker\n", "import matplotlib.patches as mpatches\n", "import matplotlib.transforms as mtransforms\n", "\n", "\n", "# Define the URL of the MJO LPT list\n", "MAIN_URL = 'https://orca.atmos.washington.edu/data/lpt/kc2020/20_72h/thresh12/systems/'\n", "\n", "def filter_lpt(years_to_filter, lon_begin_min, lon_begin_max):\n", " \"\"\"\n", " Filters MJO-C and MJO-B from MJO LPT list, returns mjo_c and mjo_b\n", " Predefined variables:\n", " mc_left, mc_right\n", " \"\"\"\n", " lpt_data = pd.read_csv(MAIN_URL + 'mjo_lpt_list.txt', skiprows=0, delim_whitespace=True)\n", " lpt_data[\"eprop_begin\"] = lpt_data[\"eprop_begin\"].astype(str)\n", " \n", " years = None\n", " if isinstance(years_to_filter, list):\n", " years = years_to_filter\n", " elif isinstance(years_to_filter, range):\n", " years = [str(year) for year in range(years_to_filter.start, years_to_filter.stop + 1)]\n", " elif isinstance(years_to_filter, int) or isinstance(years_to_filter, str):\n", " years = [str(years_to_filter)]\n", " else:\n", " raise ValueError(\"years_to_filter must be a list, range, int, or str.\")\n", " \n", " eprop_data = lpt_data[lpt_data[\"eprop_begin\"].str[:4].isin(years)]\n", " \n", " # More filter definition can be added here\n", " mc_left = 95\n", " mc_right = 150\n", " mjo_c = eprop_data[(eprop_data.eprop_lon_begin >= lon_begin_min) \n", " & (eprop_data.eprop_lon_begin <= lon_begin_max) \n", " & (eprop_data.eprop_lon_end >= mc_right)]\n", " mjo_b = eprop_data[(eprop_data.eprop_lon_begin >= lon_begin_min) \n", " & (eprop_data.eprop_lon_begin <= lon_begin_max) \n", " & (eprop_data.eprop_lon_end >= mc_left) \n", " & (eprop_data.eprop_lon_end <= mc_right)]\n", " return mjo_c, mjo_b\n", "\n", "def download_track(args):\n", " \"\"\"\n", " Download tracks for the given lpt index and begin year\n", " \"\"\"\n", " begin_year, eprop_begin = args\n", " end_year = begin_year + 1\n", " url_track = f'{MAIN_URL}lpt_systems_tmpa_{begin_year}060100_{end_year}063021.txt'\n", " lpt_track = pd.read_csv(url_track, skiprows=1, delim_whitespace=True)\n", " start_index = lpt_track.index[(lpt_track[\"YYYYMMDDHH\"] == eprop_begin) & (lpt_track[\"cen_lon.__\"] == eprop_lon_begin)][0]\n", " end_index = lpt_track.index[(lpt_track[\"_A_[km2]\"] > lpt_index) & (lpt_track[\"YYYYMMDDHH\"] == \"LPT\")][0]\n", " selected_track_lpt = lpt_track.loc[start_index+1:end_index-1]\n", " selected_track_lpt.insert(0, 'lpt_index', value=lpt_index)\n", " selected_track_lpt.insert(0, 'begin_year', value=begin_year)\n", " return selected_track_lpt # input for track_list_lpt \n", "\n", "def process_mjo_track(mjo_filtered):\n", " with Pool() as p:\n", " track_list_lpt = pd.concat(p.map(download_track, zip(lpt_filtered[\"begin_year\"],\n", " lpt_filtered[\"eprop_begin\"])), ignore_index=True)\n", " track_list_lpt['mjo_id'] = track_list_lpt.groupby([\"begin_year\", \"lpt_index\"]).ngroup() + 1\n", " new_cols = track_list_lpt.columns.tolist()\n", " for i, col in enumerate(new_cols):\n", " new_cols[i] = col.replace(\".\", \"\").replace(\"[\", \"\").replace(\"]\", \"\").replace(\"__\", \"\")\n", " track_list_lpt.columns = new_cols\n", " return track_list_lpt\n", "\n", "def subset_mjo_from_lpt(track_list_lpt, lpt_filtered):\n", " \n", " start_index = track_list_lpt.index[(track_list_lpt[\"YYYYMMDDHH\"] == )]\n", " end_index\n", " \n", " return track_list_mjo\n", "\n", "def group_tracks_by_mjo_id(track_list_mjo, mjo_id=None):\n", " if mjo_id is None:\n", " tracks_grouped = track_list_mjo.groupby('mjo_id')\n", " else:\n", " tracks_grouped = track_list_mjo[track_list_mjo[\"mjo_id\"]==mjo_id].groupby('mjo_id')\n", " return tracks_grouped\n", "\n", "def plot_maps_add_rectangle(axs, fig):\n", " for label, ax in axs.items():\n", " # Add label to the top-left corner of the axes\n", " trans = mtransforms.ScaledTranslation(5/72, -5/72, fig.dpi_scale_trans)\n", " ax.text(0.0, 1.0, label, transform=ax.transAxes + trans,\n", " fontsize=\"large\", verticalalignment=\"top\", fontfamily=\"serif\",\n", " bbox=dict(facecolor=\"0.8\", edgecolor=\"none\", pad=3.0))\n", "\n", " # Add coastlines and gridlines\n", " ax.coastlines(resolution='50m', linewidth=1, color='dimgrey', zorder=0)\n", " ax.set_extent([40, 40+180, -30, 30], ccrs.PlateCarree())\n", " gridlines = ax.gridlines(crs=ccrs.PlateCarree(), alpha=0.5, \n", " linestyle='--', linewidth=.75, zorder=0,\n", " xlocs=[40, 70, 100, 130, 160, -170, -140], \n", " ylocs=[30, 15, 0, -15, -30])\n", " gridlines.left_labels = True\n", " gridlines.bottom_labels = True\n", "\n", " # Add rectangle patch\n", " ax.add_patch(mpatches.Rectangle(xy=[95, -10], width=55, height=17,\n", " facecolor='green', alpha=0.2, transform=ccrs.PlateCarree()))\n", "\n", "def plot_grouped_tracks(grouped, ax):\n", " \"\"\"\n", " Plot grouped tracks (mjo_c vs mjo_b) on the given axis (subplot a or b).\n", " \n", " Parameters:\n", " grouped (DataFrameGroupBy): Grouped data.\n", " ax (Matplotlib Axes): Axis to plot the grouped tracks.\n", " \"\"\"\n", " # Get a color map and colors for each group\n", " color_map = cm.get_cmap(\"tab10\")\n", " colors = color_map(np.linspace(0,1,len(grouped)))\n", " \n", " for i, (group_name, group) in enumerate(grouped):\n", " # Get the tracks\n", " tracks = sgeom.LineString(zip(group['cen_lon'], group['cen_lat']))\n", " face_color = colors[i,:]\n", " \n", " # Plot the tracks and their buffers\n", " ax.add_geometries([tracks], ccrs.PlateCarree(), facecolor='none')\n", " ax.add_geometries([tracks.buffer(1.5)], ccrs.PlateCarree(), facecolor=face_color, alpha=0.3)\n", " \n", " # Get information from the first and last point of the track \n", " first_row = group.iloc[0]\n", " end_row = group.iloc[-1]\n", " origin_lon = first_row['cen_lon']\n", " origin_lat = first_row['cen_lat']\n", " end_lon = end_row['cen_lon']\n", " end_lat = end_row['cen_lat']\n", " origin_mon = first_row['YYYYMMDDHH'][4:6]\n", " end_mon = end_row['YYYYMMDDHH'][4:6]\n", " \n", " # Plot a circle (or a cross) to mark the origin (end point) of the line\n", " ax.scatter(origin_lon, origin_lat, transform=ccrs.PlateCarree(), \n", " s=150, color='blue', marker='o', facecolor='none', zorder=3)\n", " ax.scatter(end_lon, end_lat, transform=ccrs.PlateCarree(), \n", " s=150, color='red', marker='x', zorder=3)\n", " \n", " # Add text showing month for each MJO event\n", " ax.text(origin_lon, origin_lat, origin_mon, transform=ccrs.PlateCarree(), ha='center', va='center', \n", " fontsize=7, color='black', zorder=4)\n", " ax.text(end_lon, end_lat, end_mon, transform=ccrs.PlateCarree(), ha='center', va='center', \n", " fontsize=7, color='black', zorder=4)" ] }, { "cell_type": "code", "execution_count": 2, "id": "cadde1a9", "metadata": { "ExecuteTime": { "end_time": "2023-01-30T06:09:52.222925Z", "start_time": "2023-01-30T06:09:51.920131Z" } }, "outputs": [], "source": [ "# Filter MJO LPT list based on years, begin_lon_min, and begin_lon_max \n", "lpt_c, lpt_b = filter_lpt(range(1998,1999), 40, 95)" ] }, { "cell_type": "code", "execution_count": 8, "id": "ea60ffe1", "metadata": { "ExecuteTime": { "end_time": "2023-01-30T06:21:27.449709Z", "start_time": "2023-01-30T06:21:27.436108Z" } }, "outputs": [ { "data": { "text/html": [ "
| \n", " | begin_year | \n", "lpt_index | \n", "lptgroup | \n", "duration | \n", "mean_zonal_spd | \n", "begin | \n", "end | \n", "volrain | \n", "eprop_begin_idx | \n", "eprop_end_idx | \n", "eprop_spd | \n", "eprop_dur | \n", "eprop_begin | \n", "eprop_end | \n", "eprop_lon_begin | \n", "eprop_lon_end | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "1998 | \n", "26.03 | \n", "26 | \n", "37.38 | \n", "0.0 | \n", "1999011815 | \n", "1999022500 | \n", "0.0 | \n", "33 | \n", "266 | \n", "4.63 | \n", "29.12 | \n", "1999012215 | \n", "1999022018 | \n", "85.2 | \n", "188.1 | \n", "
| 1 | \n", "1998 | \n", "30.01 | \n", "30 | \n", "16.75 | \n", "0.0 | \n", "1999031303 | \n", "1999032921 | \n", "0.0 | \n", "59 | \n", "135 | \n", "9.79 | \n", "9.50 | \n", "1999032009 | \n", "1999032921 | \n", "93.7 | \n", "167.1 | \n", "
| \n", " | begin_year | \n", "lpt_index | \n", "YYYYMMDDHH | \n", "_A_km2 | \n", "cen_lat | \n", "cen_lon | \n", "Nobj | \n", "mjo_id | \n", "
|---|---|---|---|---|---|---|---|---|
| 0 | \n", "1998 | \n", "26.03 | \n", "1999011815 | \n", "357440.0 | \n", "-2.04 | \n", "99.10 | \n", "1.0 | \n", "1 | \n", "
| 1 | \n", "1998 | \n", "26.03 | \n", "1999011818 | \n", "450715.0 | \n", "-2.35 | \n", "99.19 | \n", "1.0 | \n", "1 | \n", "
| 2 | \n", "1998 | \n", "26.03 | \n", "1999011821 | \n", "637167.0 | \n", "-2.74 | \n", "99.35 | \n", "1.0 | \n", "1 | \n", "
| 3 | \n", "1998 | \n", "26.03 | \n", "1999011900 | \n", "826500.0 | \n", "-3.11 | \n", "99.57 | \n", "1.0 | \n", "1 | \n", "
| 4 | \n", "1998 | \n", "26.03 | \n", "1999011903 | \n", "898833.0 | \n", "-3.19 | \n", "99.66 | \n", "1.0 | \n", "1 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 430 | \n", "1998 | \n", "30.01 | \n", "1999032909 | \n", "1083796.0 | \n", "4.61 | \n", "166.00 | \n", "1.0 | \n", "2 | \n", "
| 431 | \n", "1998 | \n", "30.01 | \n", "1999032912 | \n", "1028297.0 | \n", "4.67 | \n", "166.20 | \n", "1.0 | \n", "2 | \n", "
| 432 | \n", "1998 | \n", "30.01 | \n", "1999032915 | \n", "948971.0 | \n", "4.74 | \n", "166.34 | \n", "1.0 | \n", "2 | \n", "
| 433 | \n", "1998 | \n", "30.01 | \n", "1999032918 | \n", "737148.0 | \n", "5.00 | \n", "166.61 | \n", "1.0 | \n", "2 | \n", "
| 434 | \n", "1998 | \n", "30.01 | \n", "1999032921 | \n", "384565.0 | \n", "5.42 | \n", "167.08 | \n", "1.0 | \n", "2 | \n", "
435 rows × 8 columns
\n", "