{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "39d482f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "import matplotlib.colors as mcolors\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import plotly.graph_objects as go\n",
    "import scienceplots  # noqa: F401\n",
    "import seaborn as sns\n",
    "from matplotlib.patches import Patch\n",
    "from rich import pretty, traceback\n",
    "from scipy.cluster import hierarchy\n",
    "from scipy.spatial.distance import squareform\n",
    "from scipy.stats import spearmanr\n",
    "from sklearn.feature_selection import (\n",
    "    VarianceThreshold,\n",
    "    f_classif,\n",
    "    f_regression,\n",
    "    mutual_info_classif,\n",
    "    mutual_info_regression,\n",
    ")\n",
    "from sklearn.preprocessing import (\n",
    "    Normalizer,\n",
    "    StandardScaler,\n",
    ")\n",
    "\n",
    "from entropice.ml.dataset import DatasetEnsemble\n",
    "\n",
    "pretty.install()\n",
    "traceback.install()\n",
    "\n",
    "sns.set_theme(context=\"paper\", style=\"whitegrid\", palette=\"tab10\", font_scale=1.5)\n",
    "plt.style.use([\"science\", \"grid\", \"no-latex\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "70a62775",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reading grid took 2.10s\n",
      "Getting target labels (with task=density) took 2.25s\n",
      "Loading features from cache took 0.04s\n",
      "Row norms (should be close to 1): 1.0 1.0 1.0\n"
     ]
    }
   ],
   "source": [
    "grid = \"hex\"\n",
    "level = 6\n",
    "task = \"density\"\n",
    "dimension_filters = {\"ArcticDEM\": {\"aggregations\": [\"median\"]}}\n",
    "if (grid == \"hex\" and level in [3, 4]) or (grid == \"healpix\" and level in [6, 7]):\n",
    "    dimension_filters[\"ERA5-shoulder\"] = {\"aggregations\": [\"median\"]}\n",
    "dataset_ensemble = DatasetEnsemble(\n",
    "    grid=grid, level=level, members=[\"ArcticDEM\", \"ERA5-shoulder\"], dimension_filters=dimension_filters\n",
    ")\n",
    "training_data = dataset_ensemble.create_training_set(task, \"darts_mllabels\")\n",
    "\n",
    "X_train = training_data.X.train\n",
    "y_train = training_data.y.train\n",
    "\n",
    "X_train = StandardScaler().fit_transform(X_train)\n",
    "X_train = Normalizer().fit_transform(X_train)\n",
    "# Check if rows are unit vectors\n",
    "row_norms = np.linalg.norm(X_train, axis=1)\n",
    "print(\n",
    "    \"Row norms (should be close to 1):\", row_norms.max().round(2), row_norms.min().round(2), row_norms.mean().round(2)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "23d54807",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "top_features=array(['era5_sshf_OND', 'era5_freezing_days_OND', 'era5_thawing_days_OND',\n",
      "       'era5_sf_OND', 'era5_freezing_degree_days_trend_JFM',\n",
      "       'era5_t2m_skew_AMJ', 'era5_precipitation_occurrences_OND',\n",
      "       'era5_t2m_avg_OND', 'era5_t2m_max_trend_OND', 'era5_sf_trend_JAS',\n",
      "       'era5_t2m_max_AMJ', 'era5_snowfall_occurrences_JFM',\n",
      "       'era5_t2m_avg_trend_JFM', 'era5_sf_trend_OND',\n",
      "       'era5_effective_snow_depth_trend_AMJ',\n",
      "       'era5_precipitation_occurrences_AMJ',\n",
      "       'era5_thawing_days_trend_JFM', 'era5_freezing_days_trend_JFM',\n",
      "       'era5_snowc_mean_trend_AMJ', 'era5_sshf_JFM',\n",
      "       'era5_snowfall_occurrences_JAS', 'era5_sf_JAS',\n",
      "       'era5_t2m_skew_JFM', 'era5_freezing_degree_days_JFM',\n",
      "       'era5_tp_AMJ', 'era5_t2m_max_JFM', 'era5_freezing_degree_days_JAS',\n",
      "       'era5_t2m_max_JAS', 'era5_tp_JAS', 'era5_t2m_min_AMJ',\n",
      "       'era5_t2m_avg_trend_OND', 'era5_t2m_mean_JFM',\n",
      "       'era5_freezing_degree_days_trend_JAS', 'era5_t2m_range_JAS',\n",
      "       'era5_snowfall_occurrences_trend_JAS', 'era5_t2m_avg_JFM',\n",
      "       'era5_t2m_mean_trend_OND', 'era5_thawing_days_JAS',\n",
      "       'era5_freezing_days_JAS', 'era5_t2m_min_trend_JAS',\n",
      "       'era5_snowc_mean_trend_JAS', 'era5_t2m_skew_JAS',\n",
      "       'era5_t2m_max_OND', 'era5_t2m_mean_trend_JFM',\n",
      "       'era5_freezing_days_trend_JAS', 'era5_thawing_days_trend_JAS',\n",
      "       'era5_t2m_min_trend_JFM', 'era5_t2m_mean_JAS',\n",
      "       'era5_freezing_degree_days_AMJ', 'era5_freezing_days_AMJ',\n",
      "       'era5_thawing_days_AMJ', 'era5_t2m_range_AMJ',\n",
      "       'era5_freezing_degree_days_trend_OND',\n",
      "       'era5_thawing_degree_days_JAS', 'era5_t2m_avg_JAS',\n",
      "       'era5_t2m_mean_AMJ', 'era5_thawing_degree_days_AMJ', 'x',\n",
      "       'era5_t2m_avg_AMJ', 'y'], dtype='<U40')\n",
      "top_features_f=array(['era5_t2m_mean_OND', 'era5_t2m_mean_trend_AMJ',\n",
      "       'era5_sshf_trend_AMJ', 'era5_sf_trend_JAS',\n",
      "       'era5_snowfall_occurrences_OND', 'era5_t2m_range_JFM',\n",
      "       'era5_t2m_range_OND', 'era5_precipitation_occurrences_OND',\n",
      "       'era5_freezing_degree_days_JFM', 'era5_t2m_avg_JFM', 'land_ratio',\n",
      "       'era5_t2m_mean_JFM', 'era5_snowc_mean_AMJ',\n",
      "       'era5_snowfall_occurrences_trend_JAS', 'water_area',\n",
      "       'era5_precipitation_occurrences_JAS', 'era5_sf_JAS',\n",
      "       'era5_sshf_trend_JAS', 'era5_t2m_mean_trend_OND',\n",
      "       'era5_t2m_avg_trend_OND', 'era5_lblt_max_JAS', 'era5_t2m_min_AMJ',\n",
      "       'era5_t2m_min_JAS', 'era5_sshf_OND', 'era5_tp_JAS',\n",
      "       'era5_freezing_degree_days_JAS', 'era5_t2m_max_trend_OND',\n",
      "       'era5_sshf_JFM', 'era5_freezing_days_AMJ', 'era5_thawing_days_AMJ',\n",
      "       'era5_t2m_skew_trend_AMJ', 'era5_t2m_max_JFM',\n",
      "       'era5_snowfall_occurrences_JAS',\n",
      "       'era5_precipitation_occurrences_AMJ', 'era5_tp_AMJ',\n",
      "       'era5_t2m_max_OND', 'era5_t2m_avg_AMJ', 'era5_t2m_range_AMJ',\n",
      "       'era5_t2m_mean_AMJ', 'era5_freezing_degree_days_trend_JFM',\n",
      "       'era5_thawing_degree_days_AMJ', 'era5_freezing_days_JAS',\n",
      "       'era5_thawing_days_JAS', 'era5_freezing_degree_days_AMJ',\n",
      "       'era5_t2m_mean_trend_JFM', 'era5_t2m_skew_trend_JAS',\n",
      "       'era5_t2m_min_trend_JFM', 'era5_t2m_avg_trend_JFM',\n",
      "       'era5_t2m_max_JAS', 'era5_t2m_range_JAS',\n",
      "       'era5_freezing_degree_days_trend_OND', 'era5_t2m_max_AMJ',\n",
      "       'era5_snowc_mean_trend_JAS', 'era5_thawing_days_trend_JAS',\n",
      "       'era5_freezing_days_trend_JAS', 'era5_thawing_degree_days_JAS',\n",
      "       'era5_t2m_avg_JAS', 'era5_t2m_min_trend_JAS', 'era5_t2m_mean_JAS',\n",
      "       'era5_freezing_degree_days_trend_JAS'], dtype='<U40')\n",
      "top_features_combined=array(['era5_sf_trend_OND', 'era5_t2m_min_JAS', 'era5_snowc_mean_AMJ',\n",
      "       'era5_thawing_days_OND', 'era5_freezing_days_OND', 'era5_sf_OND',\n",
      "       'era5_freezing_days_trend_JFM', 'era5_thawing_days_trend_JFM',\n",
      "       'era5_t2m_skew_trend_JAS', 'era5_snowfall_occurrences_JFM',\n",
      "       'era5_t2m_avg_OND', 'era5_t2m_skew_JFM', 'era5_sf_trend_JAS',\n",
      "       'era5_precipitation_occurrences_OND', 'era5_sshf_OND',\n",
      "       'era5_sf_JAS', 'era5_t2m_max_trend_OND',\n",
      "       'era5_freezing_degree_days_JFM', 'era5_sshf_JFM',\n",
      "       'era5_precipitation_occurrences_AMJ',\n",
      "       'era5_snowfall_occurrences_JAS', 'era5_t2m_mean_JFM',\n",
      "       'era5_freezing_degree_days_trend_JFM', 'era5_t2m_avg_JFM',\n",
      "       'era5_snowfall_occurrences_trend_JAS', 'era5_t2m_avg_trend_OND',\n",
      "       'era5_t2m_min_AMJ', 'era5_freezing_degree_days_JAS', 'era5_tp_JAS',\n",
      "       'era5_t2m_skew_JAS', 'era5_t2m_mean_trend_OND', 'era5_t2m_max_JFM',\n",
      "       'era5_tp_AMJ', 'era5_t2m_avg_trend_JFM', 'era5_t2m_max_AMJ',\n",
      "       'era5_thawing_days_JAS', 'era5_freezing_days_JAS',\n",
      "       'era5_t2m_max_OND', 'era5_t2m_max_JAS', 'era5_t2m_mean_trend_JFM',\n",
      "       'era5_t2m_range_JAS', 'era5_t2m_min_trend_JFM',\n",
      "       'era5_freezing_days_AMJ', 'era5_thawing_days_AMJ',\n",
      "       'era5_freezing_degree_days_AMJ', 'era5_snowc_mean_trend_JAS',\n",
      "       'era5_t2m_range_AMJ', 'era5_freezing_days_trend_JAS',\n",
      "       'era5_thawing_days_trend_JAS', 'era5_t2m_min_trend_JAS',\n",
      "       'era5_t2m_mean_JAS', 'x', 'era5_freezing_degree_days_trend_OND',\n",
      "       'era5_t2m_mean_AMJ', 'era5_thawing_degree_days_JAS',\n",
      "       'era5_thawing_degree_days_AMJ', 'era5_t2m_avg_JAS',\n",
      "       'era5_t2m_avg_AMJ', 'era5_freezing_degree_days_trend_JAS', 'y'],\n",
      "      dtype='<U40')\n",
      "Selected features based on variance thresholding: ['cell_area' 'land_area' 'x' 'y' 'arcticdem_aspect_median'\n",
      " 'arcticdem_dem_median' 'arcticdem_slope_median'\n",
      " 'arcticdem_tpi_large_median' 'arcticdem_tri_large_median'\n",
      " 'arcticdem_tri_medium_median' 'arcticdem_tri_small_median'\n",
      " 'era5_freezing_days_AMJ' 'era5_freezing_days_trend_AMJ'\n",
      " 'era5_freezing_days_trend_JAS' 'era5_freezing_days_trend_OND'\n",
      " 'era5_freezing_degree_days_AMJ' 'era5_freezing_degree_days_JFM'\n",
      " 'era5_freezing_degree_days_OND' 'era5_freezing_degree_days_trend_AMJ'\n",
      " 'era5_freezing_degree_days_trend_JAS'\n",
      " 'era5_freezing_degree_days_trend_JFM'\n",
      " 'era5_freezing_degree_days_trend_OND' 'era5_lblt_max_AMJ'\n",
      " 'era5_lblt_max_JAS' 'era5_lblt_max_JFM' 'era5_lblt_max_OND'\n",
      " 'era5_lblt_max_trend_AMJ' 'era5_lblt_max_trend_JAS'\n",
      " 'era5_lblt_max_trend_JFM' 'era5_lblt_max_trend_OND'\n",
      " 'era5_precipitation_occurrences_AMJ' 'era5_precipitation_occurrences_JAS'\n",
      " 'era5_precipitation_occurrences_JFM' 'era5_precipitation_occurrences_OND'\n",
      " 'era5_precipitation_occurrences_trend_AMJ'\n",
      " 'era5_precipitation_occurrences_trend_JAS'\n",
      " 'era5_precipitation_occurrences_trend_JFM'\n",
      " 'era5_precipitation_occurrences_trend_OND' 'era5_sf_trend_AMJ'\n",
      " 'era5_sf_trend_JAS' 'era5_sf_trend_OND' 'era5_snowc_mean_AMJ'\n",
      " 'era5_snowc_mean_JFM' 'era5_snowc_mean_trend_AMJ'\n",
      " 'era5_snowfall_occurrences_AMJ' 'era5_snowfall_occurrences_JAS'\n",
      " 'era5_snowfall_occurrences_JFM' 'era5_snowfall_occurrences_OND'\n",
      " 'era5_snowfall_occurrences_trend_AMJ'\n",
      " 'era5_snowfall_occurrences_trend_JAS'\n",
      " 'era5_snowfall_occurrences_trend_JFM'\n",
      " 'era5_snowfall_occurrences_trend_OND' 'era5_sshf_AMJ' 'era5_sshf_JAS'\n",
      " 'era5_sshf_JFM' 'era5_sshf_OND' 'era5_sshf_trend_AMJ'\n",
      " 'era5_sshf_trend_JAS' 'era5_sshf_trend_JFM' 'era5_sshf_trend_OND'\n",
      " 'era5_t2m_avg_AMJ' 'era5_t2m_avg_JAS' 'era5_t2m_avg_JFM'\n",
      " 'era5_t2m_avg_OND' 'era5_t2m_avg_trend_AMJ' 'era5_t2m_avg_trend_JAS'\n",
      " 'era5_t2m_avg_trend_JFM' 'era5_t2m_avg_trend_OND' 'era5_t2m_max_AMJ'\n",
      " 'era5_t2m_max_JFM' 'era5_t2m_max_OND' 'era5_t2m_max_trend_AMJ'\n",
      " 'era5_t2m_max_trend_JAS' 'era5_t2m_max_trend_JFM'\n",
      " 'era5_t2m_max_trend_OND' 'era5_t2m_mean_AMJ' 'era5_t2m_mean_JAS'\n",
      " 'era5_t2m_mean_JFM' 'era5_t2m_mean_OND' 'era5_t2m_mean_trend_AMJ'\n",
      " 'era5_t2m_mean_trend_JAS' 'era5_t2m_mean_trend_JFM'\n",
      " 'era5_t2m_mean_trend_OND' 'era5_t2m_min_AMJ' 'era5_t2m_min_JAS'\n",
      " 'era5_t2m_min_trend_AMJ' 'era5_t2m_min_trend_JAS'\n",
      " 'era5_t2m_min_trend_JFM' 'era5_t2m_min_trend_OND' 'era5_t2m_range_AMJ'\n",
      " 'era5_t2m_range_JAS' 'era5_t2m_range_JFM' 'era5_t2m_range_OND'\n",
      " 'era5_t2m_range_trend_AMJ' 'era5_t2m_range_trend_JAS'\n",
      " 'era5_t2m_range_trend_JFM' 'era5_t2m_range_trend_OND' 'era5_t2m_skew_AMJ'\n",
      " 'era5_t2m_skew_JAS' 'era5_t2m_skew_JFM' 'era5_t2m_skew_OND'\n",
      " 'era5_t2m_skew_trend_AMJ' 'era5_t2m_skew_trend_JAS'\n",
      " 'era5_t2m_skew_trend_JFM' 'era5_t2m_skew_trend_OND'\n",
      " 'era5_thawing_days_AMJ' 'era5_thawing_days_trend_AMJ'\n",
      " 'era5_thawing_days_trend_JAS' 'era5_thawing_days_trend_OND'\n",
      " 'era5_thawing_degree_days_AMJ' 'era5_thawing_degree_days_JAS'\n",
      " 'era5_thawing_degree_days_trend_AMJ' 'era5_thawing_degree_days_trend_JAS'\n",
      " 'era5_tp_trend_AMJ' 'era5_tp_trend_JAS']\n",
      "Intersection of top features from MI and F-test: {np.str_('era5_t2m_mean_JAS'), np.str_('era5_t2m_min_AMJ'), np.str_('era5_freezing_degree_days_JFM'), np.str_('era5_snowc_mean_trend_JAS'), np.str_('era5_sshf_JFM'), np.str_('era5_thawing_degree_days_AMJ'), np.str_('era5_t2m_avg_JFM'), np.str_('era5_freezing_degree_days_JAS'), np.str_('era5_freezing_degree_days_AMJ'), np.str_('era5_thawing_days_JAS'), np.str_('era5_tp_AMJ'), np.str_('era5_thawing_degree_days_JAS'), np.str_('era5_freezing_days_AMJ'), np.str_('era5_freezing_days_trend_JAS'), np.str_('era5_t2m_mean_trend_JFM'), np.str_('era5_t2m_avg_trend_JFM'), np.str_('era5_t2m_range_JAS'), np.str_('era5_precipitation_occurrences_OND'), np.str_('era5_t2m_max_OND'), np.str_('era5_t2m_max_JFM'), np.str_('era5_sf_trend_JAS'), np.str_('era5_t2m_min_trend_JFM'), np.str_('era5_freezing_degree_days_trend_OND'), np.str_('era5_freezing_degree_days_trend_JAS'), np.str_('era5_freezing_degree_days_trend_JFM'), np.str_('era5_t2m_max_trend_OND'), np.str_('era5_t2m_mean_JFM'), np.str_('era5_snowfall_occurrences_trend_JAS'), np.str_('era5_t2m_mean_AMJ'), np.str_('era5_t2m_max_JAS'), np.str_('era5_thawing_days_AMJ'), np.str_('era5_t2m_max_AMJ'), np.str_('era5_t2m_avg_JAS'), np.str_('era5_thawing_days_trend_JAS'), np.str_('era5_t2m_mean_trend_OND'), np.str_('era5_sshf_OND'), np.str_('era5_t2m_avg_AMJ'), np.str_('era5_precipitation_occurrences_AMJ'), np.str_('era5_t2m_range_AMJ'), np.str_('era5_t2m_min_trend_JAS'), np.str_('era5_t2m_avg_trend_OND'), np.str_('era5_freezing_days_JAS'), np.str_('era5_snowfall_occurrences_JAS'), np.str_('era5_sf_JAS'), np.str_('era5_tp_JAS')}\n"
     ]
    }
   ],
   "source": [
    "if task == \"density\":\n",
    "    mi = mutual_info_regression(X_train, y_train)\n",
    "else:\n",
    "    mi = mutual_info_classif(X_train, y_train)\n",
    "mi /= np.max(mi)\n",
    "\n",
    "if task == \"density\":\n",
    "    f = f_regression(X_train, y_train)[0]\n",
    "else:\n",
    "    f = f_classif(X_train, y_train)[0]\n",
    "f /= np.max(f)\n",
    "\n",
    "combined_score = 1 - np.sqrt((1 - mi) * (1 - f))\n",
    "\n",
    "selector = VarianceThreshold(threshold=0.005)\n",
    "X_train_selected = selector.fit_transform(X_train)\n",
    "var = selector.variances_\n",
    "\n",
    "# Get the feature names with the most mi\n",
    "feature_names = np.array(training_data.feature_names)\n",
    "top_features = feature_names[np.argsort(mi)[-60:]]\n",
    "print(f\"{top_features=}\")\n",
    "\n",
    "# Get the feature names with the most f\n",
    "top_features_f = feature_names[np.argsort(f)[-60:]]\n",
    "print(f\"{top_features_f=}\")\n",
    "# Get the feature names with the most combined score\n",
    "top_features_combined = feature_names[np.argsort(combined_score)[-60:]]\n",
    "print(f\"{top_features_combined=}\")\n",
    "\n",
    "# Get the feature names with the most variance\n",
    "selected_feature_names = feature_names[selector.get_support()]\n",
    "print(f\"Selected features based on variance thresholding: {selected_feature_names}\")\n",
    "\n",
    "# Get the intersection of the top features from both methods\n",
    "top_features_intersection = set(top_features).intersection(set(top_features_f))\n",
    "print(f\"Intersection of top features from MI and F-test: {top_features_intersection}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "bd35579b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Feature</th>\n",
       "      <th>MI</th>\n",
       "      <th>F-test</th>\n",
       "      <th>Variance</th>\n",
       "      <th>Source</th>\n",
       "      <th>Variable</th>\n",
       "      <th>Season</th>\n",
       "      <th>Score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>cell_area</td>\n",
       "      <td>0.325049</td>\n",
       "      <td>0.006513</td>\n",
       "      <td>0.006654</td>\n",
       "      <td>General</td>\n",
       "      <td>Cell Area</td>\n",
       "      <td></td>\n",
       "      <td>0.181126</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>land_area</td>\n",
       "      <td>0.369872</td>\n",
       "      <td>0.059173</td>\n",
       "      <td>0.005008</td>\n",
       "      <td>General</td>\n",
       "      <td>Land Area</td>\n",
       "      <td></td>\n",
       "      <td>0.230038</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>water_area</td>\n",
       "      <td>0.155818</td>\n",
       "      <td>0.206797</td>\n",
       "      <td>0.003999</td>\n",
       "      <td>General</td>\n",
       "      <td>Water Area</td>\n",
       "      <td></td>\n",
       "      <td>0.181705</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>land_ratio</td>\n",
       "      <td>0.178655</td>\n",
       "      <td>0.195779</td>\n",
       "      <td>0.003874</td>\n",
       "      <td>General</td>\n",
       "      <td>Land Ratio</td>\n",
       "      <td></td>\n",
       "      <td>0.187262</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>x</td>\n",
       "      <td>0.958702</td>\n",
       "      <td>0.019901</td>\n",
       "      <td>0.008507</td>\n",
       "      <td>General</td>\n",
       "      <td>X</td>\n",
       "      <td></td>\n",
       "      <td>0.798812</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>174</th>\n",
       "      <td>era5_tp_OND</td>\n",
       "      <td>0.476412</td>\n",
       "      <td>0.116201</td>\n",
       "      <td>0.002354</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>OND</td>\n",
       "      <td>0.319745</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>175</th>\n",
       "      <td>era5_tp_trend_AMJ</td>\n",
       "      <td>0.329276</td>\n",
       "      <td>0.073498</td>\n",
       "      <td>0.006428</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>AMJ Trend</td>\n",
       "      <td>0.211694</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>176</th>\n",
       "      <td>era5_tp_trend_JAS</td>\n",
       "      <td>0.477281</td>\n",
       "      <td>0.015266</td>\n",
       "      <td>0.005601</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.282547</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>177</th>\n",
       "      <td>era5_tp_trend_JFM</td>\n",
       "      <td>0.209480</td>\n",
       "      <td>0.007929</td>\n",
       "      <td>0.001945</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>JFM Trend</td>\n",
       "      <td>0.114420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>178</th>\n",
       "      <td>era5_tp_trend_OND</td>\n",
       "      <td>0.308995</td>\n",
       "      <td>0.006398</td>\n",
       "      <td>0.003441</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>OND Trend</td>\n",
       "      <td>0.171396</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>179 rows × 8 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "\n",
       "               Feature        MI    F-test  Variance   Source    Variable  \\\n",
       "\u001b[1;36m0\u001b[0m            cell_area  \u001b[1;36m0.325049\u001b[0m  \u001b[1;36m0.006513\u001b[0m  \u001b[1;36m0.006654\u001b[0m  General   Cell Area   \n",
       "\u001b[1;36m1\u001b[0m            land_area  \u001b[1;36m0.369872\u001b[0m  \u001b[1;36m0.059173\u001b[0m  \u001b[1;36m0.005008\u001b[0m  General   Land Area   \n",
       "\u001b[1;36m2\u001b[0m           water_area  \u001b[1;36m0.155818\u001b[0m  \u001b[1;36m0.206797\u001b[0m  \u001b[1;36m0.003999\u001b[0m  General  Water Area   \n",
       "\u001b[1;36m3\u001b[0m           land_ratio  \u001b[1;36m0.178655\u001b[0m  \u001b[1;36m0.195779\u001b[0m  \u001b[1;36m0.003874\u001b[0m  General  Land Ratio   \n",
       "\u001b[1;36m4\u001b[0m                    x  \u001b[1;36m0.958702\u001b[0m  \u001b[1;36m0.019901\u001b[0m  \u001b[1;36m0.008507\u001b[0m  General           X   \n",
       "..                 \u001b[33m...\u001b[0m       \u001b[33m...\u001b[0m       \u001b[33m...\u001b[0m       \u001b[33m...\u001b[0m      \u001b[33m...\u001b[0m         \u001b[33m...\u001b[0m   \n",
       "\u001b[1;36m174\u001b[0m        era5_tp_OND  \u001b[1;36m0.476412\u001b[0m  \u001b[1;36m0.116201\u001b[0m  \u001b[1;36m0.002354\u001b[0m     ERA5          Tp   \n",
       "\u001b[1;36m175\u001b[0m  era5_tp_trend_AMJ  \u001b[1;36m0.329276\u001b[0m  \u001b[1;36m0.073498\u001b[0m  \u001b[1;36m0.006428\u001b[0m     ERA5         Tp    \n",
       "\u001b[1;36m176\u001b[0m  era5_tp_trend_JAS  \u001b[1;36m0.477281\u001b[0m  \u001b[1;36m0.015266\u001b[0m  \u001b[1;36m0.005601\u001b[0m     ERA5         Tp    \n",
       "\u001b[1;36m177\u001b[0m  era5_tp_trend_JFM  \u001b[1;36m0.209480\u001b[0m  \u001b[1;36m0.007929\u001b[0m  \u001b[1;36m0.001945\u001b[0m     ERA5         Tp    \n",
       "\u001b[1;36m178\u001b[0m  era5_tp_trend_OND  \u001b[1;36m0.308995\u001b[0m  \u001b[1;36m0.006398\u001b[0m  \u001b[1;36m0.003441\u001b[0m     ERA5         Tp    \n",
       "\n",
       "        Season     Score  \n",
       "\u001b[1;36m0\u001b[0m               \u001b[1;36m0.181126\u001b[0m  \n",
       "\u001b[1;36m1\u001b[0m               \u001b[1;36m0.230038\u001b[0m  \n",
       "\u001b[1;36m2\u001b[0m               \u001b[1;36m0.181705\u001b[0m  \n",
       "\u001b[1;36m3\u001b[0m               \u001b[1;36m0.187262\u001b[0m  \n",
       "\u001b[1;36m4\u001b[0m               \u001b[1;36m0.798812\u001b[0m  \n",
       "..         \u001b[33m...\u001b[0m       \u001b[33m...\u001b[0m  \n",
       "\u001b[1;36m174\u001b[0m        OND  \u001b[1;36m0.319745\u001b[0m  \n",
       "\u001b[1;36m175\u001b[0m  AMJ Trend  \u001b[1;36m0.211694\u001b[0m  \n",
       "\u001b[1;36m176\u001b[0m  JAS Trend  \u001b[1;36m0.282547\u001b[0m  \n",
       "\u001b[1;36m177\u001b[0m  JFM Trend  \u001b[1;36m0.114420\u001b[0m  \n",
       "\u001b[1;36m178\u001b[0m  OND Trend  \u001b[1;36m0.171396\u001b[0m  \n",
       "\n",
       "\u001b[1m[\u001b[0m\u001b[1;36m179\u001b[0m rows x \u001b[1;36m8\u001b[0m columns\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Parse the variables of the feature name\n",
    "# A feature name looks like this: \"source_variable_season\"\n",
    "def parse_feature_name(feature_name):\n",
    "    parts = feature_name.split(\"_\")\n",
    "    match parts[0]:\n",
    "        case \"arcticdem\":\n",
    "            source = \"ArcticDEM\"\n",
    "            variable = \" \".join(parts[1:]).replace(\"median\", \"\").title()\n",
    "            season = \"\"\n",
    "        case \"era5\":\n",
    "            source = \"ERA5\"\n",
    "            variable = \" \".join(parts[1:-1]).replace(\"trend\", \"\").title()\n",
    "            season = parts[-1]\n",
    "            if \"trend\" in feature_name:\n",
    "                season += \" Trend\"\n",
    "        case _:\n",
    "            return \"General\", feature_name.replace(\"_\", \" \").title(), \"\"\n",
    "    return source, variable, season\n",
    "\n",
    "\n",
    "# Make a dataframe of the feature names, their scores and their parsed components\n",
    "feature_similarities = pd.DataFrame({\"Feature\": feature_names, \"MI\": mi, \"F-test\": f, \"Variance\": var})\n",
    "feature_similarities[[\"Source\", \"Variable\", \"Season\"]] = (\n",
    "    feature_similarities[\"Feature\"].apply(parse_feature_name).apply(pd.Series)\n",
    ")\n",
    "feature_similarities[\"Score\"] = combined_score\n",
    "feature_similarities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "177395e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 293264 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size \u001b[0m\u001b[1;36m1152.\u001b[0m\u001b[39m62x1000 with \u001b[0m\u001b[1;36m20\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "g = sns.PairGrid(\n",
    "    feature_similarities.sort_index(ascending=False),\n",
    "    vars=[\"MI\", \"F-test\", \"Variance\", \"Score\"],\n",
    "    hue=\"Source\",\n",
    "    palette=\"Set2\",\n",
    ")\n",
    "g.map_upper(sns.scatterplot)\n",
    "g.map_lower(sns.kdeplot, fill=True, alpha=0.5)\n",
    "g.map_diag(sns.histplot, kde=True)\n",
    "g.add_legend()\n",
    "plt.suptitle(\"Feature importance based on variance, MI and F-test\", y=1.02)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "07067d18",
   "metadata": {},
   "outputs": [],
   "source": [
    "def _parse_feature_name(feature_name: str) -> str:\n",
    "    feature_name = (\n",
    "        feature_name.replace(\"_median\", \"_\")\n",
    "        .replace(\"_mean\", \"_\")\n",
    "        .replace(\"era5_\", \"\")\n",
    "        .replace(\"arcticdem_\", \"\")\n",
    "        .replace(\"JFM\", \"Winter\")\n",
    "        .replace(\"AMJ\", \"Spring\")\n",
    "        .replace(\"JAS\", \"Summer\")\n",
    "        .replace(\"OND\", \"Fall\")\n",
    "        .replace(\"embeddings_embeddings\", \"embeddings\")\n",
    "        .replace(\"_\", \" \")\n",
    "        .title()\n",
    "    )\n",
    "    # Remove duplicate spaces\n",
    "    feature_name = \" \".join(feature_name.split())\n",
    "    return feature_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "76485283",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 157088 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 100\u001b[0m\u001b[1;36m0x800\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m2\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(figsize=(10, 8))\n",
    "\n",
    "scatter = ax.scatter(\n",
    "    mi,\n",
    "    f,\n",
    "    c=combined_score,\n",
    "    s=64,  # size=8 in plotly roughly corresponds to s=64 in matplotlib\n",
    "    cmap=\"viridis\",\n",
    "    alpha=0.7,\n",
    "    edgecolors=\"white\",\n",
    "    linewidths=0.5,\n",
    ")\n",
    "\n",
    "# Add colorbar\n",
    "cbar = plt.colorbar(scatter, ax=ax)\n",
    "cbar.set_label(\"Combined Score\", fontsize=12)\n",
    "\n",
    "# Set labels and title\n",
    "ax.set_xlabel(\"Mutual Information\", fontsize=12)\n",
    "ax.set_ylabel(\"F-test p-value\", fontsize=12)\n",
    "# ax.set_title(\"Feature importance based on Mutual Information and F-test\", fontsize=14, fontweight=\"bold\")\n",
    "\n",
    "# Add dashed line where combined score = 0.4\n",
    "# combined_score = 1 - sqrt((1 - mi) * (1 - f))\n",
    "# Solving for f when combined_score = 0.4:\n",
    "# 0.4 = 1 - sqrt((1 - mi) * (1 - f))\n",
    "# sqrt((1 - mi) * (1 - f)) = 0.6\n",
    "# (1 - mi) * (1 - f) = 0.36\n",
    "# f = 1 - 0.36 / (1 - mi)\n",
    "threshold = 0.425\n",
    "mi_range = np.linspace(0, 1, 1000)\n",
    "# Avoid division by zero\n",
    "mi_range = mi_range[mi_range < 0.9999]\n",
    "f_threshold = 1 - (1 - threshold) ** 2 / (1 - mi_range)\n",
    "# Only plot valid f values (between 0 and 1)\n",
    "valid_mask = (f_threshold >= 0) & (f_threshold <= 1)\n",
    "ax.plot(\n",
    "    mi_range[valid_mask],\n",
    "    f_threshold[valid_mask],\n",
    "    \"--\",\n",
    "    color=\"red\",\n",
    "    linewidth=2,\n",
    "    label=f\"Combined Score = {threshold}\",\n",
    "    alpha=0.8,\n",
    ")\n",
    "ax.legend(fontsize=10, loc=\"lower right\")\n",
    "\n",
    "# Optional: Add feature name annotations for top features (prevents overcrowding)\n",
    "# Annotate top 10 features by combined score\n",
    "top_n = 10\n",
    "top_indices = np.argsort(combined_score)[-top_n:]\n",
    "for idx in top_indices:\n",
    "    xytext = (-5, 5)\n",
    "    ha = \"right\"\n",
    "    ax.annotate(\n",
    "        _parse_feature_name(feature_names[idx]),\n",
    "        (mi[idx], f[idx]),\n",
    "        xytext=xytext,\n",
    "        textcoords=\"offset points\",\n",
    "        fontsize=10,\n",
    "        alpha=0.8,\n",
    "        ha=ha,\n",
    "        bbox=dict(boxstyle=\"round,pad=0.3\", facecolor=\"white\", edgecolor=\"gray\", alpha=0.7),\n",
    "    )\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60aa4192",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.plotly.v1+json": {
       "config": {
        "plotlyServerURL": "https://plot.ly"
       },
       "data": [
        {
         "hovertemplate": "<b>%{text}</b><br>MI: %{x:.3f}<br>F-test: %{y:.3f}<br>Combined: %{marker.color:.3f}}<extra></extra>",
         "marker": {
          "color": {
           "bdata": "1KvnXCAvxz88jr8C4nHNP7gbuNkXQsc/RLwTYjX4xz+RRbNQ3o/pPwAAAAAAAPA/wOfigMUblD/Ulp7Ba1PAP66zMyPeOdA/6NKNpgkMvT/APvFR99OoP6C/ggzmP6w/qLZEf7DVvj/IjlmD8NDHP+x0nrjxDMQ/oEPvloEyvT/QyezXVQnHP9hw5ZxtA80/VDj66OkLzj/Q+4PUBNu0P7wy5HMpI8U/OMX5aa1FwD9IfkbTiW21P8YgYYTQjNY/TL78ZRQfzT+kMy76TDbIP7AFDVQcmsA/d1coVNlW5j98nBiPtInjP2z6vIwb18s/CMnEBvXX1z/8Kl3WUr/MP87PiY0Tc+c/KpNwTpb21z+4liGJmFfOP9i1hO1h4eY/F+3pq8W54D9cauP3yMbdP3K9nJZPk9Y/jK3GxPCQyD8AAAAAAADwP2ggLYSrJOA/hjVFm2/+6T+yhzepnKLQP3b05PpUANM/lJ2uU1OowT/O27jrF+XQP/hJ4nKpB7M//AdjgIDbwD8AAFiHo6S2PpChM1UmRaI/YBIhT/9Luz8o0GOxOO+/PzB0hoWhjrA/gBOdf5gDrj+geocg7V7IPzh9QA8Tcbg/tGW7SbPrxz/0hazllnbEP0hzqocZv98/hGqS8zdf0D/qgy9rZSTWP+DHvXuh1tk/dIPo+58Lwz+mz4nIU4PQP8CVceVyw8A/2HSUyftizD9AxY9ReF27P4BnnPZha8I/XIc+qXOpwT8YeuF76JG7PzyP3bqU9MQ/IFdHMC04oD9E6sJlVzfGP9DfuHbmL8c/IH/qdM5/wD+eBpUf+sncP6RycIIGtNE/Xh999zXm1z+0u91seKvAP3IGPUqA1tk/KOJ1eZuSyz+2XXiB81jXP4AWeWl81dc/cGGb8khIvj+oZ6eT17a1P4TGW3Dp9sI/2vYPAoBP1z/K3auemhznP8BPMnAXUpg/+ryVhdAs0T9EcaOVNl7DP+2/jDZbE+A/0vWjEFou2T9Us+FHF5nTP8jl8oaFWrY//6mo7ENT4D+caw8e3hTHP7ZXlJcMjNQ/3glb96Ai1T+SO/DreV7SP4ok11+BpN4/pg3FPqrX2z/0ZMvVmq3VP+Sdi7BkC9c/7qJfH1w50z/gPfQRTbPNP8qASnfKyOw/a0MgWA0l7D/MK47OZEngP6ZuquuGP9k/7o6tu9Mm1j+khIBXVZvTPxgi0Yeh6+E/iIMgaR9W4D9WwMldT3fjP96NZ9weAeQ/Kiyvv1wv4T8XLJAjNdPjP5zE8NB678U/bMwqgfKzyT8Aj606+szTP4RGBGDGud0/VBKT9reZ6j/dD1MxegfpP6j+QijcIOA/xOItz7sD1T/a56IjGdTRP1onIqG3K9A/G285ywmb5D8QqNRorgPhP92VeN1ChOA/3MH9N+531z9YNR8tC+jJP7BYmaoMls4/hBrt9mqWzT9SuBUNJYbnP/rlierCFOY/VB4Tz9vQ0j8CBQn7QE3nP3z+o3kPFOU/xv+kjyhd1T+wxs0fUlTGP2hvW2BnYr4/jEJ+EwLpyD/qWLnYMfjSP9zlxyo6t8E/rpY7/Hho1j+7scbwXtDgP+BjCqgWstk/GON5M+lDyz/UCROlcNfTP4owC0QlANk//OT8/xmhwD8AGV0Io6q3P8muL1TZVuY/RfoXwvF94z/c2gHVmPbLP2JU0gP119c//Cpd1lK/zD/Oz4mNE3PnP8gjiE6W9tc/RPMEiphXzj9q6kHb4yPrP9pNhsAUIus/8N5zCtblzD8yR99JC4nTP9YPXjJHM9Q/fPqp1ezmzj8gSU5W+bHFP3aQ7Vma8tM/fLnfD2Zj4T/sX22/WcPgP4gWAbsbjM4/yO2+8rR21D/ESiWjxxjLP9AqzNk+FdI/4LkzD6JKvT9kYrDLTvDFPw==",
           "dtype": "f8"
          },
          "colorbar": {
           "title": {
            "text": "Combined Score"
           }
          },
          "colorscale": [
           [
            0,
            "#440154"
           ],
           [
            0.1111111111111111,
            "#482878"
           ],
           [
            0.2222222222222222,
            "#3e4989"
           ],
           [
            0.3333333333333333,
            "#31688e"
           ],
           [
            0.4444444444444444,
            "#26828e"
           ],
           [
            0.5555555555555556,
            "#1f9e89"
           ],
           [
            0.6666666666666666,
            "#35b779"
           ],
           [
            0.7777777777777778,
            "#6ece58"
           ],
           [
            0.8888888888888888,
            "#b5de2b"
           ],
           [
            1,
            "#fde725"
           ]
          ],
          "line": {
           "color": "white",
           "width": 0.5
          },
          "opacity": 0.7,
          "showscale": true,
          "size": 8
         },
         "mode": "markers",
         "text": [
          "cell_area",
          "land_area",
          "water_area",
          "land_ratio",
          "x",
          "y",
          "arcticdem_aspect_median",
          "arcticdem_curvature_median",
          "arcticdem_dem_median",
          "arcticdem_slope_median",
          "arcticdem_tpi_large_median",
          "arcticdem_tpi_medium_median",
          "arcticdem_tpi_small_median",
          "arcticdem_tri_large_median",
          "arcticdem_tri_medium_median",
          "arcticdem_tri_small_median",
          "arcticdem_vrm_large_median",
          "arcticdem_vrm_medium_median",
          "arcticdem_vrm_small_median",
          "era5_effective_snow_depth_AMJ",
          "era5_effective_snow_depth_JAS",
          "era5_effective_snow_depth_JFM",
          "era5_effective_snow_depth_OND",
          "era5_effective_snow_depth_trend_AMJ",
          "era5_effective_snow_depth_trend_JAS",
          "era5_effective_snow_depth_trend_JFM",
          "era5_effective_snow_depth_trend_OND",
          "era5_freezing_days_AMJ",
          "era5_freezing_days_JAS",
          "era5_freezing_days_JFM",
          "era5_freezing_days_OND",
          "era5_freezing_days_trend_AMJ",
          "era5_freezing_days_trend_JAS",
          "era5_freezing_days_trend_JFM",
          "era5_freezing_days_trend_OND",
          "era5_freezing_degree_days_AMJ",
          "era5_freezing_degree_days_JAS",
          "era5_freezing_degree_days_JFM",
          "era5_freezing_degree_days_OND",
          "era5_freezing_degree_days_trend_AMJ",
          "era5_freezing_degree_days_trend_JAS",
          "era5_freezing_degree_days_trend_JFM",
          "era5_freezing_degree_days_trend_OND",
          "era5_lblt_max_AMJ",
          "era5_lblt_max_JAS",
          "era5_lblt_max_JFM",
          "era5_lblt_max_OND",
          "era5_lblt_max_trend_AMJ",
          "era5_lblt_max_trend_JAS",
          "era5_lblt_max_trend_JFM",
          "era5_lblt_max_trend_OND",
          "era5_naive_snow_isolation_AMJ",
          "era5_naive_snow_isolation_JAS",
          "era5_naive_snow_isolation_JFM",
          "era5_naive_snow_isolation_OND",
          "era5_naive_snow_isolation_trend_AMJ",
          "era5_naive_snow_isolation_trend_JAS",
          "era5_naive_snow_isolation_trend_JFM",
          "era5_naive_snow_isolation_trend_OND",
          "era5_precipitation_occurrences_AMJ",
          "era5_precipitation_occurrences_JAS",
          "era5_precipitation_occurrences_JFM",
          "era5_precipitation_occurrences_OND",
          "era5_precipitation_occurrences_trend_AMJ",
          "era5_precipitation_occurrences_trend_JAS",
          "era5_precipitation_occurrences_trend_JFM",
          "era5_precipitation_occurrences_trend_OND",
          "era5_sde_mean_AMJ",
          "era5_sde_mean_JAS",
          "era5_sde_mean_JFM",
          "era5_sde_mean_OND",
          "era5_sde_mean_trend_AMJ",
          "era5_sde_mean_trend_JAS",
          "era5_sde_mean_trend_JFM",
          "era5_sde_mean_trend_OND",
          "era5_sf_AMJ",
          "era5_sf_JAS",
          "era5_sf_JFM",
          "era5_sf_OND",
          "era5_sf_trend_AMJ",
          "era5_sf_trend_JAS",
          "era5_sf_trend_JFM",
          "era5_sf_trend_OND",
          "era5_snowc_mean_AMJ",
          "era5_snowc_mean_JAS",
          "era5_snowc_mean_JFM",
          "era5_snowc_mean_OND",
          "era5_snowc_mean_trend_AMJ",
          "era5_snowc_mean_trend_JAS",
          "era5_snowc_mean_trend_JFM",
          "era5_snowc_mean_trend_OND",
          "era5_snowfall_occurrences_AMJ",
          "era5_snowfall_occurrences_JAS",
          "era5_snowfall_occurrences_JFM",
          "era5_snowfall_occurrences_OND",
          "era5_snowfall_occurrences_trend_AMJ",
          "era5_snowfall_occurrences_trend_JAS",
          "era5_snowfall_occurrences_trend_JFM",
          "era5_snowfall_occurrences_trend_OND",
          "era5_sshf_AMJ",
          "era5_sshf_JAS",
          "era5_sshf_JFM",
          "era5_sshf_OND",
          "era5_sshf_trend_AMJ",
          "era5_sshf_trend_JAS",
          "era5_sshf_trend_JFM",
          "era5_sshf_trend_OND",
          "era5_t2m_avg_AMJ",
          "era5_t2m_avg_JAS",
          "era5_t2m_avg_JFM",
          "era5_t2m_avg_OND",
          "era5_t2m_avg_trend_AMJ",
          "era5_t2m_avg_trend_JAS",
          "era5_t2m_avg_trend_JFM",
          "era5_t2m_avg_trend_OND",
          "era5_t2m_max_AMJ",
          "era5_t2m_max_JAS",
          "era5_t2m_max_JFM",
          "era5_t2m_max_OND",
          "era5_t2m_max_trend_AMJ",
          "era5_t2m_max_trend_JAS",
          "era5_t2m_max_trend_JFM",
          "era5_t2m_max_trend_OND",
          "era5_t2m_mean_AMJ",
          "era5_t2m_mean_JAS",
          "era5_t2m_mean_JFM",
          "era5_t2m_mean_OND",
          "era5_t2m_mean_trend_AMJ",
          "era5_t2m_mean_trend_JAS",
          "era5_t2m_mean_trend_JFM",
          "era5_t2m_mean_trend_OND",
          "era5_t2m_min_AMJ",
          "era5_t2m_min_JAS",
          "era5_t2m_min_JFM",
          "era5_t2m_min_OND",
          "era5_t2m_min_trend_AMJ",
          "era5_t2m_min_trend_JAS",
          "era5_t2m_min_trend_JFM",
          "era5_t2m_min_trend_OND",
          "era5_t2m_range_AMJ",
          "era5_t2m_range_JAS",
          "era5_t2m_range_JFM",
          "era5_t2m_range_OND",
          "era5_t2m_range_trend_AMJ",
          "era5_t2m_range_trend_JAS",
          "era5_t2m_range_trend_JFM",
          "era5_t2m_range_trend_OND",
          "era5_t2m_skew_AMJ",
          "era5_t2m_skew_JAS",
          "era5_t2m_skew_JFM",
          "era5_t2m_skew_OND",
          "era5_t2m_skew_trend_AMJ",
          "era5_t2m_skew_trend_JAS",
          "era5_t2m_skew_trend_JFM",
          "era5_t2m_skew_trend_OND",
          "era5_thawing_days_AMJ",
          "era5_thawing_days_JAS",
          "era5_thawing_days_JFM",
          "era5_thawing_days_OND",
          "era5_thawing_days_trend_AMJ",
          "era5_thawing_days_trend_JAS",
          "era5_thawing_days_trend_JFM",
          "era5_thawing_days_trend_OND",
          "era5_thawing_degree_days_AMJ",
          "era5_thawing_degree_days_JAS",
          "era5_thawing_degree_days_JFM",
          "era5_thawing_degree_days_OND",
          "era5_thawing_degree_days_trend_AMJ",
          "era5_thawing_degree_days_trend_JAS",
          "era5_thawing_degree_days_trend_JFM",
          "era5_thawing_degree_days_trend_OND",
          "era5_tp_AMJ",
          "era5_tp_JAS",
          "era5_tp_JFM",
          "era5_tp_OND",
          "era5_tp_trend_AMJ",
          "era5_tp_trend_JAS",
          "era5_tp_trend_JFM",
          "era5_tp_trend_OND"
         ],
         "type": "scatter",
         "x": {
          "bdata": "HNLjgZrN1D+SvRWr+6vXP6rRFhrW8cM/GbTImy7exj9vYSHMrq3uPwAAAAAAAPA/uaZEU50EoD/bEo0Mc/nEP6mKGkoGo9Y/o1iqzqTYyD9lLzM4kt6jP41dHCUCTKY/n364tFKhxD8+7zksO4LUP/jLQR91LdE/apZTK1ZjyD98P1BJz5DTPzus6Qx+ZNg/SWDKzknY2D9bfbyJJQfDP1EO2YTy3tI/QAx3QucozT9At6iEGWbDPxl7e0Xwi+I/hOrOhJZf2T+lNfoLOZ3VP1bxMTJd1s0//uKcg3Vt6z+Jb+38OS3nP5awR9cS29Y/iVIdZdd94T8CimF2ucbWP56UOD8wSOg/ZBPYi1S14j9yotCB4vjWP827eFTg/+o/2UpLUw0P5T9H1jTRL6fkP2sgWH3VGeA/gef0/G8t0j9nBRoB/TTmPxqkRquUwuE/Tkt41GXf7D9npBFnpFrWPx7Wjz9qNtQ/lhcRcLeVzT/kYzjRjB3aP7PnheOYBKc/SIVJ/nhpxj8AAAAAAAAAAD5QDP1uYZY/GVSs/MYzyT+YRJRT4LnMP6i0rpufJb0/+UIB0P6ruj8woOEJZdzUPzln+L2iJMc/GsJqnA9H1T8cPCdHFEjSP/XWxFWRpOI/nc78OlW00j82S4pTZArgP9L0f6RQ7OE/zlJ9uzMl0D+82u/OJ/XaPzZDkAbfccs/ahYcHMWN1D+lgespej7JPzoaEVhoitA/Fyb3BIygzz/4E2+pWfbIP+mQZI+h+tE/GCRfIqhdrj8tx99ruuDTP32tgtFJi9Q/B+yS7UO/zj+UQvaHxJPjPxfaOVYi5Ns/F44pYOWP4T/ownx2qyTPP9yLVKMQNeI/mpntnbs82D+KTbAy6nDiP6il79f4QeA/+7FkTYJbzD/po8n0ztzCP400XKu5Ss8/Pu2msebE4j8QXjArf9LnP5Etnj361Kc/NxcefyBr3T8qA5nsrrXRPyPTtv3sHuM/BgZRB4RJ4j/HLP/iNI/aPy4cfgCRZcQ/2a/ob1xa5j8KxBqMLPrSP0acPj/FGt4/v/ZJpRwU4D845h25IDLfP/Jx6s0L3uI/qLxTdWM34T/+AqtEEjHeP82tZ3aY390/rLFJpNd93z/RWMFisp7YP8UxYrkUce8/1UebmmY97j8U6MYL42jmP8Q+ex/TCuI/9nFVB/X03z8iRqfubobgP+KXdGgIT+I/WPJi8mDI5T+fl9q2xT3iP7QUIfQdVeU/WblPdyb/5D/lYwgLHQDoP+iYMfKijtM/GgJri9Bb1j9JMZUAZhvdPzPeLXijKeI/lPr59PVZ7j8UvDB8p/rpP/DhFkhOM+Y/kMwcw6GZ3T8oOjciGOHXP3uJcoC5F9w/20fFLrow6D/Iu3kwmNrmPw/dw8aDfuU/3hwQEFzj2z98Ah7jQQjXP+eg4yVu69o/fhA9bfdq2T+jsg6oDTfnP0Uf0FboP+k/bf8BfHq93j/rtaaA7+DrPzJdEtJ3N+Y/cwWv9xd03T88oo6Wt5LEPzCA9wH9vcI/wVqCyhcF1T8DKZCWRo/dP8UcxXYhLs0/+a1/cZ7Z4T88TuItbfjnP6YyXFj7VeQ/Kh+AqtAv2D87oy/ICn3PP1bIUPHkrdE/p7AUDn8Bzj8aOgfdkmTFP/7inIN1bes/wYzruIoc5z9wQKGZ7fTWP4lSHWXXfeE/AophdrnG1j+elDg/MEjoP2QT2ItUteI/cqLQgeL41j92Nf317KjuP3WhQJm0R+0/zbR3lO6H2D8fGWzKAI7dP+O0VriAqd4/VZfbvbnj2j8AQjL26SzRPxZFyA9EXN4/hzQng0O25D9ipMJYjHXlP1r1SAyaR9g/B2FA7Yd93j8p7uhf3RLVP+c+mlTFi94/5JTs6EDQyj8LfI54kcbTPw==",
          "dtype": "f8"
         },
         "y": {
          "bdata": "73UVXiatej9YoLFw40uuP2UVLZtWeMo/gUqQmEcPyT+qtbAXDGGUP3AeB0VKVKs/G0s1cTITgD+Yn2vUaPO2P2S6zGy0pME/4rk09IlXmT9JfyApkrytP2bEzuehELE/bs8Ypifnsz9fRNp6xrSZP1EiDkTCfJw/j8K2MSITnz/OFpRVVRugP6jw8BodOqE/rlspE3rnpT/Zmxre4WGCPxP/UWIJp4c/RwD03lZEiz+CMGEUNVqFP5dq/vWntWI/lAl07FsUhz/gWXbc5MN9P+iIDYNAUIk/2SaEMVEt1z8DPWQJDMzcPw/DT2vhWag/2zmlgunawD+rhC33mQixP0Y8PVj6huY/kxFJzC+crT/0tovP64u3P5m/TzODvN4/JgY6IFpa1T+IFC2iRsfIP5eNYkXREcQ/1jb4wJWFtj8AAAAAAADwP+Lh+H6Gr9w/pdteDBh35D+Zt14mFEPEP73hlNerwdE/d24kiYcjoT/cLvyEjLi1P8Eyoz7MUbo/ma5YM3QFtj/uF/uGoqTGPtL+hff1P6k/+VPTPxh5eT+vJGnY8hiJP6qF4qQoJoo/TeDHNKf9hT+P6PUrPD6cP2LBZ5v7l1Q/9lwG6YqOgz90pL4U83SIP8i3GfAID9k/EKfWR7bWyz++HKjtczfCP4BwuLLWi8g/dYI/M8O8nz+PUjbXlvyoP8IMjr9DyqM/KBiLG1ibuz+WYBuvXD96P6yt6mms4oc/sRRrCL3Eij8EB58ZjFKGP5rP5zACD5w/w/FSiTyFaj/uwyxcRwyDPzFkIstmlYk/LXYMNrX9VD9nstkwuzLMP7sdm6w1kLI/U+g6kCifwD+vPl1rQDIxP06NDrhzacY/r/ztBAXWgj8JNCel2XWoP9ykZjFthMk/wy5zdSYCVj/bgjMxqR2SP0fEZlBOQ6Q/4jmve0rtlj+O945W6FbmP2A48TJ61jo/4k+KOhkagz+tTpRpBRRxP3DG4zLtntg/W8czswYcwj/F1sJaP6/GP//RCKZpq4I/mNUHkwIgyj80+xRF/wGnP3uyjaDZlsA/e98SNY0xuT/2Vy/VS9yAP7PjWqusotU/NRJ3yILI0z+UNiBxngrGP3SQRoe7ss0/4mwZ3i2eoj8Tn4ReAUGlP/WT8g+v9No/iQkOgEmO5z+aN6fMeATJPxaJWyQNacQ/h3yA8TGxwj9aTImjvbp0P6GD7PhoheE/pEbM2aLyzz/m1VcF8JTkP4aDSlrLguI/1W7t5Rkb2D+aPuWzwvDaPz2YPauj+4Y/PP5x7FjHkj/0mC8+RwbAP8DmBwhgjdU/Khsl+2Gh3D96MyM/7+3nP3r2fe/4LMk/UYIYv5CSxD+a5bnX+7rFP80P/kS8mHI/OZp9Lj3A3j+dYw/pQMnNP7K6gUyOXNI/nLfOUgeC0j+KgrjdJD95PxH5dGrFdDU/YWz0Sovokz+zsaphdNLnP7wojm3fbOE/4NKG3IbupD9q85Y8xEjbP+u5sTi/zuM/aqmRiJDCxj9LL/X5kg7IP2a71YHGDbc/cihSuut3oT/0wgOn5n20PwJGrT5Wr6M/a81uYM37pj8j1uIuyDu6P56ZdhGer5E/am+DMs72cT9btfHpS5fXP+Mvw70oKt8/h1PdrT3Uhj9pGVhK1qmGP5ExwjFRLdc/kSh3JgzM3D+KPfCh4lmoPwDdVHLp2sA/q4Qt95kIsT9GPD1Y+obmP7HrgM4vnK0/uRXG0+uLtz/YYJr308DcP8FVG3SbSuc/0aWSLaKpnD+JNHyH+2e6P+vyjpFh0rk/F4UxLOEnfz8wuglTJ1GtP2u1e1tCP7k/H/AZ2wAs2j9WUyVLHfPTP1JzLsQE57A/m4+dc2G/vT+W5Q2xwtCyP7OkFxrQQ48/Yo4CLOk8gD9y8/5jozR6Pw==",
          "dtype": "f8"
         }
        }
       ],
       "layout": {
        "height": 600,
        "hovermode": "closest",
        "template": {
         "data": {
          "bar": [
           {
            "error_x": {
             "color": "#2a3f5f"
            },
            "error_y": {
             "color": "#2a3f5f"
            },
            "marker": {
             "line": {
              "color": "white",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "bar"
           }
          ],
          "barpolar": [
           {
            "marker": {
             "line": {
              "color": "white",
              "width": 0.5
             },
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "barpolar"
           }
          ],
          "carpet": [
           {
            "aaxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "#C8D4E3",
             "linecolor": "#C8D4E3",
             "minorgridcolor": "#C8D4E3",
             "startlinecolor": "#2a3f5f"
            },
            "baxis": {
             "endlinecolor": "#2a3f5f",
             "gridcolor": "#C8D4E3",
             "linecolor": "#C8D4E3",
             "minorgridcolor": "#C8D4E3",
             "startlinecolor": "#2a3f5f"
            },
            "type": "carpet"
           }
          ],
          "choropleth": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "choropleth"
           }
          ],
          "contour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "contour"
           }
          ],
          "contourcarpet": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "contourcarpet"
           }
          ],
          "heatmap": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "heatmap"
           }
          ],
          "histogram": [
           {
            "marker": {
             "pattern": {
              "fillmode": "overlay",
              "size": 10,
              "solidity": 0.2
             }
            },
            "type": "histogram"
           }
          ],
          "histogram2d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2d"
           }
          ],
          "histogram2dcontour": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "histogram2dcontour"
           }
          ],
          "mesh3d": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "type": "mesh3d"
           }
          ],
          "parcoords": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "parcoords"
           }
          ],
          "pie": [
           {
            "automargin": true,
            "type": "pie"
           }
          ],
          "scatter": [
           {
            "fillpattern": {
             "fillmode": "overlay",
             "size": 10,
             "solidity": 0.2
            },
            "type": "scatter"
           }
          ],
          "scatter3d": [
           {
            "line": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatter3d"
           }
          ],
          "scattercarpet": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattercarpet"
           }
          ],
          "scattergeo": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergeo"
           }
          ],
          "scattergl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattergl"
           }
          ],
          "scattermap": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermap"
           }
          ],
          "scattermapbox": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scattermapbox"
           }
          ],
          "scatterpolar": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolar"
           }
          ],
          "scatterpolargl": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterpolargl"
           }
          ],
          "scatterternary": [
           {
            "marker": {
             "colorbar": {
              "outlinewidth": 0,
              "ticks": ""
             }
            },
            "type": "scatterternary"
           }
          ],
          "surface": [
           {
            "colorbar": {
             "outlinewidth": 0,
             "ticks": ""
            },
            "colorscale": [
             [
              0,
              "#0d0887"
             ],
             [
              0.1111111111111111,
              "#46039f"
             ],
             [
              0.2222222222222222,
              "#7201a8"
             ],
             [
              0.3333333333333333,
              "#9c179e"
             ],
             [
              0.4444444444444444,
              "#bd3786"
             ],
             [
              0.5555555555555556,
              "#d8576b"
             ],
             [
              0.6666666666666666,
              "#ed7953"
             ],
             [
              0.7777777777777778,
              "#fb9f3a"
             ],
             [
              0.8888888888888888,
              "#fdca26"
             ],
             [
              1,
              "#f0f921"
             ]
            ],
            "type": "surface"
           }
          ],
          "table": [
           {
            "cells": {
             "fill": {
              "color": "#EBF0F8"
             },
             "line": {
              "color": "white"
             }
            },
            "header": {
             "fill": {
              "color": "#C8D4E3"
             },
             "line": {
              "color": "white"
             }
            },
            "type": "table"
           }
          ]
         },
         "layout": {
          "annotationdefaults": {
           "arrowcolor": "#2a3f5f",
           "arrowhead": 0,
           "arrowwidth": 1
          },
          "autotypenumbers": "strict",
          "coloraxis": {
           "colorbar": {
            "outlinewidth": 0,
            "ticks": ""
           }
          },
          "colorscale": {
           "diverging": [
            [
             0,
             "#8e0152"
            ],
            [
             0.1,
             "#c51b7d"
            ],
            [
             0.2,
             "#de77ae"
            ],
            [
             0.3,
             "#f1b6da"
            ],
            [
             0.4,
             "#fde0ef"
            ],
            [
             0.5,
             "#f7f7f7"
            ],
            [
             0.6,
             "#e6f5d0"
            ],
            [
             0.7,
             "#b8e186"
            ],
            [
             0.8,
             "#7fbc41"
            ],
            [
             0.9,
             "#4d9221"
            ],
            [
             1,
             "#276419"
            ]
           ],
           "sequential": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ],
           "sequentialminus": [
            [
             0,
             "#0d0887"
            ],
            [
             0.1111111111111111,
             "#46039f"
            ],
            [
             0.2222222222222222,
             "#7201a8"
            ],
            [
             0.3333333333333333,
             "#9c179e"
            ],
            [
             0.4444444444444444,
             "#bd3786"
            ],
            [
             0.5555555555555556,
             "#d8576b"
            ],
            [
             0.6666666666666666,
             "#ed7953"
            ],
            [
             0.7777777777777778,
             "#fb9f3a"
            ],
            [
             0.8888888888888888,
             "#fdca26"
            ],
            [
             1,
             "#f0f921"
            ]
           ]
          },
          "colorway": [
           "#636efa",
           "#EF553B",
           "#00cc96",
           "#ab63fa",
           "#FFA15A",
           "#19d3f3",
           "#FF6692",
           "#B6E880",
           "#FF97FF",
           "#FECB52"
          ],
          "font": {
           "color": "#2a3f5f"
          },
          "geo": {
           "bgcolor": "white",
           "lakecolor": "white",
           "landcolor": "white",
           "showlakes": true,
           "showland": true,
           "subunitcolor": "#C8D4E3"
          },
          "hoverlabel": {
           "align": "left"
          },
          "hovermode": "closest",
          "mapbox": {
           "style": "light"
          },
          "paper_bgcolor": "white",
          "plot_bgcolor": "white",
          "polar": {
           "angularaxis": {
            "gridcolor": "#EBF0F8",
            "linecolor": "#EBF0F8",
            "ticks": ""
           },
           "bgcolor": "white",
           "radialaxis": {
            "gridcolor": "#EBF0F8",
            "linecolor": "#EBF0F8",
            "ticks": ""
           }
          },
          "scene": {
           "xaxis": {
            "backgroundcolor": "white",
            "gridcolor": "#DFE8F3",
            "gridwidth": 2,
            "linecolor": "#EBF0F8",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "#EBF0F8"
           },
           "yaxis": {
            "backgroundcolor": "white",
            "gridcolor": "#DFE8F3",
            "gridwidth": 2,
            "linecolor": "#EBF0F8",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "#EBF0F8"
           },
           "zaxis": {
            "backgroundcolor": "white",
            "gridcolor": "#DFE8F3",
            "gridwidth": 2,
            "linecolor": "#EBF0F8",
            "showbackground": true,
            "ticks": "",
            "zerolinecolor": "#EBF0F8"
           }
          },
          "shapedefaults": {
           "line": {
            "color": "#2a3f5f"
           }
          },
          "ternary": {
           "aaxis": {
            "gridcolor": "#DFE8F3",
            "linecolor": "#A2B1C6",
            "ticks": ""
           },
           "baxis": {
            "gridcolor": "#DFE8F3",
            "linecolor": "#A2B1C6",
            "ticks": ""
           },
           "bgcolor": "white",
           "caxis": {
            "gridcolor": "#DFE8F3",
            "linecolor": "#A2B1C6",
            "ticks": ""
           }
          },
          "title": {
           "x": 0.05
          },
          "xaxis": {
           "automargin": true,
           "gridcolor": "#EBF0F8",
           "linecolor": "#EBF0F8",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "#EBF0F8",
           "zerolinewidth": 2
          },
          "yaxis": {
           "automargin": true,
           "gridcolor": "#EBF0F8",
           "linecolor": "#EBF0F8",
           "ticks": "",
           "title": {
            "standoff": 15
           },
           "zerolinecolor": "#EBF0F8",
           "zerolinewidth": 2
          }
         }
        },
        "title": {
         "text": "Feature importance based on Mututal Information and F-test"
        },
        "width": 900,
        "xaxis": {
         "title": {
          "text": "Mutual Information"
         }
        },
        "yaxis": {
         "title": {
          "text": "F-test p-value"
         }
        }
       }
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "tplt = \"<b>%{text}</b><br>MI: %{x:.3f}<br>F-test: %{y:.3f}<br>F-test: %{y:.3f}<br>Variance: %{marker.color:.3f}<extra></extra>\"\n",
    "fig = go.Figure(\n",
    "    data=go.Scatter(\n",
    "        x=mi,\n",
    "        y=f,\n",
    "        mode=\"markers\",\n",
    "        text=feature_names,\n",
    "        marker={\n",
    "            \"size\": 8,\n",
    "            \"color\": combined_score,\n",
    "            \"colorscale\": \"Viridis\",\n",
    "            \"showscale\": True,\n",
    "            \"colorbar\": {\"title\": \"Combined Score\"},\n",
    "            \"opacity\": 0.7,\n",
    "            \"line\": {\"width\": 0.5, \"color\": \"white\"},\n",
    "        },\n",
    "        hovertemplate=(\n",
    "            \"<b>%{text}</b><br>MI: %{x:.3f}<br>F-test: %{y:.3f}<br>Combined: %{marker.color:.3f}}<extra></extra>\"\n",
    "        ),\n",
    "    )\n",
    ")\n",
    "\n",
    "fig.update_layout(\n",
    "    title=\"Feature importance based on Mututal Information and F-test\",\n",
    "    xaxis_title=\"Mutual Information\",\n",
    "    yaxis_title=\"F-test p-value\",\n",
    "    hovermode=\"closest\",\n",
    "    height=600,\n",
    "    width=900,\n",
    "    template=\"plotly_white\",\n",
    ")\n",
    "fig.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d93aa493",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mmatplotlib.legend.Legend\u001b[0m\u001b[39m object at \u001b[0m\u001b[1;36m0x7f1d2842ac10\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 76228 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 60\u001b[0m\u001b[1;36m0x600\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(figsize=(6, 6))\n",
    "\n",
    "seasonal_colors = {\n",
    "    \"JFM\": \"#5BA3D0\",  # Cool blue\n",
    "    \"AMJ\": \"#7BC96F\",  # Fresh green\n",
    "    \"JAS\": \"#FFD166\",  # Warm yellow\n",
    "    \"OND\": \"#E07A5F\",  # Earthy orange-red\n",
    "    \"JFM Trend\": \"#2C5F7F\",  # Deep blue\n",
    "    \"AMJ Trend\": \"#4A7C59\",  # Forest green\n",
    "    \"JAS Trend\": \"#D4A142\",  # Golden amber\n",
    "    \"OND Trend\": \"#A0503C\",  # Rich terracotta\n",
    "    \"\": \"#888888\",  # Gray for features without a season\n",
    "}\n",
    "\n",
    "sns.swarmplot(\n",
    "    data=feature_similarities, x=\"Score\", y=\"Source\", hue=\"Season\", ax=ax, palette=seasonal_colors, dodge=True\n",
    ")\n",
    "# Add a dashed line where combined score = 0.4\n",
    "ax.axvline(x=threshold, color=\"red\", linestyle=\"--\", label=f\"Combined Score = {threshold}\")\n",
    "ax.legend(fontsize=10, loc=\"upper right\", bbox_to_anchor=(1.35, 0.7))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "893a7e15",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mseaborn.axisgrid.FacetGrid\u001b[0m\u001b[39m object at \u001b[0m\u001b[1;36m0x7ef914157380\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 198732 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 1137x1000 with \u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sns.catplot(data=feature_similarities, x=\"Score\", y=\"Variable\", hue=\"Season\", height=10, aspect=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f7c3c43d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1;36m47\u001b[0m"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(feature_similarities[feature_similarities[\"Score\"] > 0.4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "5a025f30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Feature</th>\n",
       "      <th>MI</th>\n",
       "      <th>F-test</th>\n",
       "      <th>Variance</th>\n",
       "      <th>Source</th>\n",
       "      <th>Variable</th>\n",
       "      <th>Season</th>\n",
       "      <th>Score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>y</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.053377</td>\n",
       "      <td>0.007329</td>\n",
       "      <td>General</td>\n",
       "      <td>Y</td>\n",
       "      <td></td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>40</th>\n",
       "      <td>era5_freezing_degree_days_trend_JAS</td>\n",
       "      <td>0.693968</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.005918</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Degree Days</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>107</th>\n",
       "      <td>era5_t2m_avg_AMJ</td>\n",
       "      <td>0.982554</td>\n",
       "      <td>0.421184</td>\n",
       "      <td>0.006320</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Avg</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.899511</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>108</th>\n",
       "      <td>era5_t2m_avg_JAS</td>\n",
       "      <td>0.944995</td>\n",
       "      <td>0.736119</td>\n",
       "      <td>0.005625</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Avg</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.879523</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>163</th>\n",
       "      <td>era5_thawing_degree_days_AMJ</td>\n",
       "      <td>0.958121</td>\n",
       "      <td>0.449269</td>\n",
       "      <td>0.006484</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Thawing Degree Days</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.848131</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>164</th>\n",
       "      <td>era5_thawing_degree_days_JAS</td>\n",
       "      <td>0.915003</td>\n",
       "      <td>0.727857</td>\n",
       "      <td>0.005626</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Thawing Degree Days</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.847910</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>123</th>\n",
       "      <td>era5_t2m_mean_AMJ</td>\n",
       "      <td>0.948482</td>\n",
       "      <td>0.447350</td>\n",
       "      <td>0.006278</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Mean</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.831264</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>42</th>\n",
       "      <td>era5_freezing_degree_days_trend_OND</td>\n",
       "      <td>0.902270</td>\n",
       "      <td>0.639538</td>\n",
       "      <td>0.006551</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Degree Days</td>\n",
       "      <td>OND Trend</td>\n",
       "      <td>0.812309</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>x</td>\n",
       "      <td>0.958702</td>\n",
       "      <td>0.019901</td>\n",
       "      <td>0.008507</td>\n",
       "      <td>General</td>\n",
       "      <td>X</td>\n",
       "      <td></td>\n",
       "      <td>0.798812</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>124</th>\n",
       "      <td>era5_t2m_mean_JAS</td>\n",
       "      <td>0.811847</td>\n",
       "      <td>0.747795</td>\n",
       "      <td>0.005750</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Mean</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.782163</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>136</th>\n",
       "      <td>era5_t2m_min_trend_JAS</td>\n",
       "      <td>0.725470</td>\n",
       "      <td>0.744440</td>\n",
       "      <td>0.007912</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Min</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.735125</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>160</th>\n",
       "      <td>era5_thawing_days_trend_JAS</td>\n",
       "      <td>0.758812</td>\n",
       "      <td>0.703977</td>\n",
       "      <td>0.005935</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Thawing Days</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.732797</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>32</th>\n",
       "      <td>era5_freezing_days_trend_JAS</td>\n",
       "      <td>0.758812</td>\n",
       "      <td>0.703977</td>\n",
       "      <td>0.005935</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Days</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.732797</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>139</th>\n",
       "      <td>era5_t2m_range_AMJ</td>\n",
       "      <td>0.871208</td>\n",
       "      <td>0.426316</td>\n",
       "      <td>0.007174</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Range</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.728180</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>88</th>\n",
       "      <td>era5_snowc_mean_trend_JAS</td>\n",
       "      <td>0.744445</td>\n",
       "      <td>0.698109</td>\n",
       "      <td>0.004649</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Snowc Mean</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.722242</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35</th>\n",
       "      <td>era5_freezing_degree_days_AMJ</td>\n",
       "      <td>0.843735</td>\n",
       "      <td>0.480256</td>\n",
       "      <td>0.006077</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Degree Days</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.715013</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>155</th>\n",
       "      <td>era5_thawing_days_AMJ</td>\n",
       "      <td>0.857112</td>\n",
       "      <td>0.362141</td>\n",
       "      <td>0.006062</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Thawing Days</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.698102</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>era5_freezing_days_AMJ</td>\n",
       "      <td>0.857112</td>\n",
       "      <td>0.362141</td>\n",
       "      <td>0.006062</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Days</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.698102</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>137</th>\n",
       "      <td>era5_t2m_min_trend_JFM</td>\n",
       "      <td>0.789051</td>\n",
       "      <td>0.544540</td>\n",
       "      <td>0.006993</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Min</td>\n",
       "      <td>JFM Trend</td>\n",
       "      <td>0.690034</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>140</th>\n",
       "      <td>era5_t2m_range_JAS</td>\n",
       "      <td>0.694271</td>\n",
       "      <td>0.618988</td>\n",
       "      <td>0.006164</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Range</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.658699</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>129</th>\n",
       "      <td>era5_t2m_mean_trend_JFM</td>\n",
       "      <td>0.755948</td>\n",
       "      <td>0.480483</td>\n",
       "      <td>0.006620</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Mean</td>\n",
       "      <td>JFM Trend</td>\n",
       "      <td>0.643926</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>116</th>\n",
       "      <td>era5_t2m_max_JAS</td>\n",
       "      <td>0.666640</td>\n",
       "      <td>0.578466</td>\n",
       "      <td>0.004727</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Max</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.625137</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>118</th>\n",
       "      <td>era5_t2m_max_OND</td>\n",
       "      <td>0.750014</td>\n",
       "      <td>0.420945</td>\n",
       "      <td>0.005769</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Max</td>\n",
       "      <td>OND</td>\n",
       "      <td>0.619532</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>era5_freezing_days_JAS</td>\n",
       "      <td>0.724271</td>\n",
       "      <td>0.449954</td>\n",
       "      <td>0.003554</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Days</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.610560</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>156</th>\n",
       "      <td>era5_thawing_days_JAS</td>\n",
       "      <td>0.722234</td>\n",
       "      <td>0.449954</td>\n",
       "      <td>0.003554</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Thawing Days</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.609124</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>115</th>\n",
       "      <td>era5_t2m_max_AMJ</td>\n",
       "      <td>0.570041</td>\n",
       "      <td>0.643181</td>\n",
       "      <td>0.005506</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Max</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.608314</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>113</th>\n",
       "      <td>era5_t2m_avg_trend_JFM</td>\n",
       "      <td>0.572148</td>\n",
       "      <td>0.547535</td>\n",
       "      <td>0.006607</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Avg</td>\n",
       "      <td>JFM Trend</td>\n",
       "      <td>0.560014</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>171</th>\n",
       "      <td>era5_tp_AMJ</td>\n",
       "      <td>0.647249</td>\n",
       "      <td>0.408936</td>\n",
       "      <td>0.004515</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.543384</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>117</th>\n",
       "      <td>era5_t2m_max_JFM</td>\n",
       "      <td>0.656146</td>\n",
       "      <td>0.376654</td>\n",
       "      <td>0.006591</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Max</td>\n",
       "      <td>JFM</td>\n",
       "      <td>0.537032</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>130</th>\n",
       "      <td>era5_t2m_mean_trend_OND</td>\n",
       "      <td>0.714184</td>\n",
       "      <td>0.232704</td>\n",
       "      <td>0.007430</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Mean</td>\n",
       "      <td>OND Trend</td>\n",
       "      <td>0.531699</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>148</th>\n",
       "      <td>era5_t2m_skew_JAS</td>\n",
       "      <td>0.749075</td>\n",
       "      <td>0.102475</td>\n",
       "      <td>0.009218</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Skew</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.525436</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>172</th>\n",
       "      <td>era5_tp_JAS</td>\n",
       "      <td>0.670599</td>\n",
       "      <td>0.311714</td>\n",
       "      <td>0.004316</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Tp</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.523847</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>36</th>\n",
       "      <td>era5_freezing_degree_days_JAS</td>\n",
       "      <td>0.658087</td>\n",
       "      <td>0.333640</td>\n",
       "      <td>0.002855</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Degree Days</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.522677</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>131</th>\n",
       "      <td>era5_t2m_min_AMJ</td>\n",
       "      <td>0.671694</td>\n",
       "      <td>0.286899</td>\n",
       "      <td>0.005750</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Min</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.516145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>114</th>\n",
       "      <td>era5_t2m_avg_trend_OND</td>\n",
       "      <td>0.680710</td>\n",
       "      <td>0.249592</td>\n",
       "      <td>0.007352</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Avg</td>\n",
       "      <td>OND Trend</td>\n",
       "      <td>0.510513</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>96</th>\n",
       "      <td>era5_snowfall_occurrences_trend_JAS</td>\n",
       "      <td>0.698530</td>\n",
       "      <td>0.204102</td>\n",
       "      <td>0.005778</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Snowfall Occurrences</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.510164</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>109</th>\n",
       "      <td>era5_t2m_avg_JFM</td>\n",
       "      <td>0.700304</td>\n",
       "      <td>0.195449</td>\n",
       "      <td>0.005759</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Avg</td>\n",
       "      <td>JFM</td>\n",
       "      <td>0.508959</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>41</th>\n",
       "      <td>era5_freezing_degree_days_trend_JFM</td>\n",
       "      <td>0.555003</td>\n",
       "      <td>0.448213</td>\n",
       "      <td>0.006358</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Degree Days</td>\n",
       "      <td>JFM Trend</td>\n",
       "      <td>0.504476</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>125</th>\n",
       "      <td>era5_t2m_mean_JFM</td>\n",
       "      <td>0.693763</td>\n",
       "      <td>0.196685</td>\n",
       "      <td>0.005783</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Mean</td>\n",
       "      <td>JFM</td>\n",
       "      <td>0.504011</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>92</th>\n",
       "      <td>era5_snowfall_occurrences_JAS</td>\n",
       "      <td>0.597525</td>\n",
       "      <td>0.384700</td>\n",
       "      <td>0.005357</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Snowfall Occurrences</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.502363</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>era5_precipitation_occurrences_AMJ</td>\n",
       "      <td>0.582589</td>\n",
       "      <td>0.391543</td>\n",
       "      <td>0.007040</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Precipitation Occurrences</td>\n",
       "      <td>AMJ</td>\n",
       "      <td>0.496039</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>101</th>\n",
       "      <td>era5_sshf_JFM</td>\n",
       "      <td>0.589605</td>\n",
       "      <td>0.338054</td>\n",
       "      <td>0.007279</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Sshf</td>\n",
       "      <td>JFM</td>\n",
       "      <td>0.478791</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>37</th>\n",
       "      <td>era5_freezing_degree_days_JFM</td>\n",
       "      <td>0.645409</td>\n",
       "      <td>0.193581</td>\n",
       "      <td>0.005620</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Freezing Degree Days</td>\n",
       "      <td>JFM</td>\n",
       "      <td>0.465258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>122</th>\n",
       "      <td>era5_t2m_max_trend_OND</td>\n",
       "      <td>0.567583</td>\n",
       "      <td>0.336754</td>\n",
       "      <td>0.008155</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Max</td>\n",
       "      <td>OND Trend</td>\n",
       "      <td>0.464464</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>76</th>\n",
       "      <td>era5_sf_JAS</td>\n",
       "      <td>0.611788</td>\n",
       "      <td>0.220298</td>\n",
       "      <td>0.004595</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Sf</td>\n",
       "      <td>JAS</td>\n",
       "      <td>0.449828</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>102</th>\n",
       "      <td>era5_sshf_OND</td>\n",
       "      <td>0.538011</td>\n",
       "      <td>0.309113</td>\n",
       "      <td>0.005727</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Sshf</td>\n",
       "      <td>OND</td>\n",
       "      <td>0.435038</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>62</th>\n",
       "      <td>era5_precipitation_occurrences_OND</td>\n",
       "      <td>0.560097</td>\n",
       "      <td>0.191768</td>\n",
       "      <td>0.006104</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Precipitation Occurrences</td>\n",
       "      <td>OND</td>\n",
       "      <td>0.403725</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>80</th>\n",
       "      <td>era5_sf_trend_JAS</td>\n",
       "      <td>0.568978</td>\n",
       "      <td>0.175093</td>\n",
       "      <td>0.005544</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>Sf</td>\n",
       "      <td>JAS Trend</td>\n",
       "      <td>0.403717</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>149</th>\n",
       "      <td>era5_t2m_skew_JFM</td>\n",
       "      <td>0.635496</td>\n",
       "      <td>0.017271</td>\n",
       "      <td>0.009543</td>\n",
       "      <td>ERA5</td>\n",
       "      <td>T2M Skew</td>\n",
       "      <td>JFM</td>\n",
       "      <td>0.401495</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "\n",
       "                                 Feature        MI    F-test  Variance  \\\n",
       "\u001b[1;36m5\u001b[0m                                      y  \u001b[1;36m1.000000\u001b[0m  \u001b[1;36m0.053377\u001b[0m  \u001b[1;36m0.007329\u001b[0m   \n",
       "\u001b[1;36m40\u001b[0m   era5_freezing_degree_days_trend_JAS  \u001b[1;36m0.693968\u001b[0m  \u001b[1;36m1.000000\u001b[0m  \u001b[1;36m0.005918\u001b[0m   \n",
       "\u001b[1;36m107\u001b[0m                     era5_t2m_avg_AMJ  \u001b[1;36m0.982554\u001b[0m  \u001b[1;36m0.421184\u001b[0m  \u001b[1;36m0.006320\u001b[0m   \n",
       "\u001b[1;36m108\u001b[0m                     era5_t2m_avg_JAS  \u001b[1;36m0.944995\u001b[0m  \u001b[1;36m0.736119\u001b[0m  \u001b[1;36m0.005625\u001b[0m   \n",
       "\u001b[1;36m163\u001b[0m         era5_thawing_degree_days_AMJ  \u001b[1;36m0.958121\u001b[0m  \u001b[1;36m0.449269\u001b[0m  \u001b[1;36m0.006484\u001b[0m   \n",
       "\u001b[1;36m164\u001b[0m         era5_thawing_degree_days_JAS  \u001b[1;36m0.915003\u001b[0m  \u001b[1;36m0.727857\u001b[0m  \u001b[1;36m0.005626\u001b[0m   \n",
       "\u001b[1;36m123\u001b[0m                    era5_t2m_mean_AMJ  \u001b[1;36m0.948482\u001b[0m  \u001b[1;36m0.447350\u001b[0m  \u001b[1;36m0.006278\u001b[0m   \n",
       "\u001b[1;36m42\u001b[0m   era5_freezing_degree_days_trend_OND  \u001b[1;36m0.902270\u001b[0m  \u001b[1;36m0.639538\u001b[0m  \u001b[1;36m0.006551\u001b[0m   \n",
       "\u001b[1;36m4\u001b[0m                                      x  \u001b[1;36m0.958702\u001b[0m  \u001b[1;36m0.019901\u001b[0m  \u001b[1;36m0.008507\u001b[0m   \n",
       "\u001b[1;36m124\u001b[0m                    era5_t2m_mean_JAS  \u001b[1;36m0.811847\u001b[0m  \u001b[1;36m0.747795\u001b[0m  \u001b[1;36m0.005750\u001b[0m   \n",
       "\u001b[1;36m136\u001b[0m               era5_t2m_min_trend_JAS  \u001b[1;36m0.725470\u001b[0m  \u001b[1;36m0.744440\u001b[0m  \u001b[1;36m0.007912\u001b[0m   \n",
       "\u001b[1;36m160\u001b[0m          era5_thawing_days_trend_JAS  \u001b[1;36m0.758812\u001b[0m  \u001b[1;36m0.703977\u001b[0m  \u001b[1;36m0.005935\u001b[0m   \n",
       "\u001b[1;36m32\u001b[0m          era5_freezing_days_trend_JAS  \u001b[1;36m0.758812\u001b[0m  \u001b[1;36m0.703977\u001b[0m  \u001b[1;36m0.005935\u001b[0m   \n",
       "\u001b[1;36m139\u001b[0m                   era5_t2m_range_AMJ  \u001b[1;36m0.871208\u001b[0m  \u001b[1;36m0.426316\u001b[0m  \u001b[1;36m0.007174\u001b[0m   \n",
       "\u001b[1;36m88\u001b[0m             era5_snowc_mean_trend_JAS  \u001b[1;36m0.744445\u001b[0m  \u001b[1;36m0.698109\u001b[0m  \u001b[1;36m0.004649\u001b[0m   \n",
       "\u001b[1;36m35\u001b[0m         era5_freezing_degree_days_AMJ  \u001b[1;36m0.843735\u001b[0m  \u001b[1;36m0.480256\u001b[0m  \u001b[1;36m0.006077\u001b[0m   \n",
       "\u001b[1;36m155\u001b[0m                era5_thawing_days_AMJ  \u001b[1;36m0.857112\u001b[0m  \u001b[1;36m0.362141\u001b[0m  \u001b[1;36m0.006062\u001b[0m   \n",
       "\u001b[1;36m27\u001b[0m                era5_freezing_days_AMJ  \u001b[1;36m0.857112\u001b[0m  \u001b[1;36m0.362141\u001b[0m  \u001b[1;36m0.006062\u001b[0m   \n",
       "\u001b[1;36m137\u001b[0m               era5_t2m_min_trend_JFM  \u001b[1;36m0.789051\u001b[0m  \u001b[1;36m0.544540\u001b[0m  \u001b[1;36m0.006993\u001b[0m   \n",
       "\u001b[1;36m140\u001b[0m                   era5_t2m_range_JAS  \u001b[1;36m0.694271\u001b[0m  \u001b[1;36m0.618988\u001b[0m  \u001b[1;36m0.006164\u001b[0m   \n",
       "\u001b[1;36m129\u001b[0m              era5_t2m_mean_trend_JFM  \u001b[1;36m0.755948\u001b[0m  \u001b[1;36m0.480483\u001b[0m  \u001b[1;36m0.006620\u001b[0m   \n",
       "\u001b[1;36m116\u001b[0m                     era5_t2m_max_JAS  \u001b[1;36m0.666640\u001b[0m  \u001b[1;36m0.578466\u001b[0m  \u001b[1;36m0.004727\u001b[0m   \n",
       "\u001b[1;36m118\u001b[0m                     era5_t2m_max_OND  \u001b[1;36m0.750014\u001b[0m  \u001b[1;36m0.420945\u001b[0m  \u001b[1;36m0.005769\u001b[0m   \n",
       "\u001b[1;36m28\u001b[0m                era5_freezing_days_JAS  \u001b[1;36m0.724271\u001b[0m  \u001b[1;36m0.449954\u001b[0m  \u001b[1;36m0.003554\u001b[0m   \n",
       "\u001b[1;36m156\u001b[0m                era5_thawing_days_JAS  \u001b[1;36m0.722234\u001b[0m  \u001b[1;36m0.449954\u001b[0m  \u001b[1;36m0.003554\u001b[0m   \n",
       "\u001b[1;36m115\u001b[0m                     era5_t2m_max_AMJ  \u001b[1;36m0.570041\u001b[0m  \u001b[1;36m0.643181\u001b[0m  \u001b[1;36m0.005506\u001b[0m   \n",
       "\u001b[1;36m113\u001b[0m               era5_t2m_avg_trend_JFM  \u001b[1;36m0.572148\u001b[0m  \u001b[1;36m0.547535\u001b[0m  \u001b[1;36m0.006607\u001b[0m   \n",
       "\u001b[1;36m171\u001b[0m                          era5_tp_AMJ  \u001b[1;36m0.647249\u001b[0m  \u001b[1;36m0.408936\u001b[0m  \u001b[1;36m0.004515\u001b[0m   \n",
       "\u001b[1;36m117\u001b[0m                     era5_t2m_max_JFM  \u001b[1;36m0.656146\u001b[0m  \u001b[1;36m0.376654\u001b[0m  \u001b[1;36m0.006591\u001b[0m   \n",
       "\u001b[1;36m130\u001b[0m              era5_t2m_mean_trend_OND  \u001b[1;36m0.714184\u001b[0m  \u001b[1;36m0.232704\u001b[0m  \u001b[1;36m0.007430\u001b[0m   \n",
       "\u001b[1;36m148\u001b[0m                    era5_t2m_skew_JAS  \u001b[1;36m0.749075\u001b[0m  \u001b[1;36m0.102475\u001b[0m  \u001b[1;36m0.009218\u001b[0m   \n",
       "\u001b[1;36m172\u001b[0m                          era5_tp_JAS  \u001b[1;36m0.670599\u001b[0m  \u001b[1;36m0.311714\u001b[0m  \u001b[1;36m0.004316\u001b[0m   \n",
       "\u001b[1;36m36\u001b[0m         era5_freezing_degree_days_JAS  \u001b[1;36m0.658087\u001b[0m  \u001b[1;36m0.333640\u001b[0m  \u001b[1;36m0.002855\u001b[0m   \n",
       "\u001b[1;36m131\u001b[0m                     era5_t2m_min_AMJ  \u001b[1;36m0.671694\u001b[0m  \u001b[1;36m0.286899\u001b[0m  \u001b[1;36m0.005750\u001b[0m   \n",
       "\u001b[1;36m114\u001b[0m               era5_t2m_avg_trend_OND  \u001b[1;36m0.680710\u001b[0m  \u001b[1;36m0.249592\u001b[0m  \u001b[1;36m0.007352\u001b[0m   \n",
       "\u001b[1;36m96\u001b[0m   era5_snowfall_occurrences_trend_JAS  \u001b[1;36m0.698530\u001b[0m  \u001b[1;36m0.204102\u001b[0m  \u001b[1;36m0.005778\u001b[0m   \n",
       "\u001b[1;36m109\u001b[0m                     era5_t2m_avg_JFM  \u001b[1;36m0.700304\u001b[0m  \u001b[1;36m0.195449\u001b[0m  \u001b[1;36m0.005759\u001b[0m   \n",
       "\u001b[1;36m41\u001b[0m   era5_freezing_degree_days_trend_JFM  \u001b[1;36m0.555003\u001b[0m  \u001b[1;36m0.448213\u001b[0m  \u001b[1;36m0.006358\u001b[0m   \n",
       "\u001b[1;36m125\u001b[0m                    era5_t2m_mean_JFM  \u001b[1;36m0.693763\u001b[0m  \u001b[1;36m0.196685\u001b[0m  \u001b[1;36m0.005783\u001b[0m   \n",
       "\u001b[1;36m92\u001b[0m         era5_snowfall_occurrences_JAS  \u001b[1;36m0.597525\u001b[0m  \u001b[1;36m0.384700\u001b[0m  \u001b[1;36m0.005357\u001b[0m   \n",
       "\u001b[1;36m59\u001b[0m    era5_precipitation_occurrences_AMJ  \u001b[1;36m0.582589\u001b[0m  \u001b[1;36m0.391543\u001b[0m  \u001b[1;36m0.007040\u001b[0m   \n",
       "\u001b[1;36m101\u001b[0m                        era5_sshf_JFM  \u001b[1;36m0.589605\u001b[0m  \u001b[1;36m0.338054\u001b[0m  \u001b[1;36m0.007279\u001b[0m   \n",
       "\u001b[1;36m37\u001b[0m         era5_freezing_degree_days_JFM  \u001b[1;36m0.645409\u001b[0m  \u001b[1;36m0.193581\u001b[0m  \u001b[1;36m0.005620\u001b[0m   \n",
       "\u001b[1;36m122\u001b[0m               era5_t2m_max_trend_OND  \u001b[1;36m0.567583\u001b[0m  \u001b[1;36m0.336754\u001b[0m  \u001b[1;36m0.008155\u001b[0m   \n",
       "\u001b[1;36m76\u001b[0m                           era5_sf_JAS  \u001b[1;36m0.611788\u001b[0m  \u001b[1;36m0.220298\u001b[0m  \u001b[1;36m0.004595\u001b[0m   \n",
       "\u001b[1;36m102\u001b[0m                        era5_sshf_OND  \u001b[1;36m0.538011\u001b[0m  \u001b[1;36m0.309113\u001b[0m  \u001b[1;36m0.005727\u001b[0m   \n",
       "\u001b[1;36m62\u001b[0m    era5_precipitation_occurrences_OND  \u001b[1;36m0.560097\u001b[0m  \u001b[1;36m0.191768\u001b[0m  \u001b[1;36m0.006104\u001b[0m   \n",
       "\u001b[1;36m80\u001b[0m                     era5_sf_trend_JAS  \u001b[1;36m0.568978\u001b[0m  \u001b[1;36m0.175093\u001b[0m  \u001b[1;36m0.005544\u001b[0m   \n",
       "\u001b[1;36m149\u001b[0m                    era5_t2m_skew_JFM  \u001b[1;36m0.635496\u001b[0m  \u001b[1;36m0.017271\u001b[0m  \u001b[1;36m0.009543\u001b[0m   \n",
       "\n",
       "      Source                   Variable     Season     Score  \n",
       "\u001b[1;36m5\u001b[0m    General                          Y             \u001b[1;36m1.000000\u001b[0m  \n",
       "\u001b[1;36m40\u001b[0m      ERA5      Freezing Degree Days   JAS Trend  \u001b[1;36m1.000000\u001b[0m  \n",
       "\u001b[1;36m107\u001b[0m     ERA5                    T2M Avg        AMJ  \u001b[1;36m0.899511\u001b[0m  \n",
       "\u001b[1;36m108\u001b[0m     ERA5                    T2M Avg        JAS  \u001b[1;36m0.879523\u001b[0m  \n",
       "\u001b[1;36m163\u001b[0m     ERA5        Thawing Degree Days        AMJ  \u001b[1;36m0.848131\u001b[0m  \n",
       "\u001b[1;36m164\u001b[0m     ERA5        Thawing Degree Days        JAS  \u001b[1;36m0.847910\u001b[0m  \n",
       "\u001b[1;36m123\u001b[0m     ERA5                   T2M Mean        AMJ  \u001b[1;36m0.831264\u001b[0m  \n",
       "\u001b[1;36m42\u001b[0m      ERA5      Freezing Degree Days   OND Trend  \u001b[1;36m0.812309\u001b[0m  \n",
       "\u001b[1;36m4\u001b[0m    General                          X             \u001b[1;36m0.798812\u001b[0m  \n",
       "\u001b[1;36m124\u001b[0m     ERA5                   T2M Mean        JAS  \u001b[1;36m0.782163\u001b[0m  \n",
       "\u001b[1;36m136\u001b[0m     ERA5                   T2M Min   JAS Trend  \u001b[1;36m0.735125\u001b[0m  \n",
       "\u001b[1;36m160\u001b[0m     ERA5              Thawing Days   JAS Trend  \u001b[1;36m0.732797\u001b[0m  \n",
       "\u001b[1;36m32\u001b[0m      ERA5             Freezing Days   JAS Trend  \u001b[1;36m0.732797\u001b[0m  \n",
       "\u001b[1;36m139\u001b[0m     ERA5                  T2M Range        AMJ  \u001b[1;36m0.728180\u001b[0m  \n",
       "\u001b[1;36m88\u001b[0m      ERA5                Snowc Mean   JAS Trend  \u001b[1;36m0.722242\u001b[0m  \n",
       "\u001b[1;36m35\u001b[0m      ERA5       Freezing Degree Days        AMJ  \u001b[1;36m0.715013\u001b[0m  \n",
       "\u001b[1;36m155\u001b[0m     ERA5               Thawing Days        AMJ  \u001b[1;36m0.698102\u001b[0m  \n",
       "\u001b[1;36m27\u001b[0m      ERA5              Freezing Days        AMJ  \u001b[1;36m0.698102\u001b[0m  \n",
       "\u001b[1;36m137\u001b[0m     ERA5                   T2M Min   JFM Trend  \u001b[1;36m0.690034\u001b[0m  \n",
       "\u001b[1;36m140\u001b[0m     ERA5                  T2M Range        JAS  \u001b[1;36m0.658699\u001b[0m  \n",
       "\u001b[1;36m129\u001b[0m     ERA5                  T2M Mean   JFM Trend  \u001b[1;36m0.643926\u001b[0m  \n",
       "\u001b[1;36m116\u001b[0m     ERA5                    T2M Max        JAS  \u001b[1;36m0.625137\u001b[0m  \n",
       "\u001b[1;36m118\u001b[0m     ERA5                    T2M Max        OND  \u001b[1;36m0.619532\u001b[0m  \n",
       "\u001b[1;36m28\u001b[0m      ERA5              Freezing Days        JAS  \u001b[1;36m0.610560\u001b[0m  \n",
       "\u001b[1;36m156\u001b[0m     ERA5               Thawing Days        JAS  \u001b[1;36m0.609124\u001b[0m  \n",
       "\u001b[1;36m115\u001b[0m     ERA5                    T2M Max        AMJ  \u001b[1;36m0.608314\u001b[0m  \n",
       "\u001b[1;36m113\u001b[0m     ERA5                   T2M Avg   JFM Trend  \u001b[1;36m0.560014\u001b[0m  \n",
       "\u001b[1;36m171\u001b[0m     ERA5                         Tp        AMJ  \u001b[1;36m0.543384\u001b[0m  \n",
       "\u001b[1;36m117\u001b[0m     ERA5                    T2M Max        JFM  \u001b[1;36m0.537032\u001b[0m  \n",
       "\u001b[1;36m130\u001b[0m     ERA5                  T2M Mean   OND Trend  \u001b[1;36m0.531699\u001b[0m  \n",
       "\u001b[1;36m148\u001b[0m     ERA5                   T2M Skew        JAS  \u001b[1;36m0.525436\u001b[0m  \n",
       "\u001b[1;36m172\u001b[0m     ERA5                         Tp        JAS  \u001b[1;36m0.523847\u001b[0m  \n",
       "\u001b[1;36m36\u001b[0m      ERA5       Freezing Degree Days        JAS  \u001b[1;36m0.522677\u001b[0m  \n",
       "\u001b[1;36m131\u001b[0m     ERA5                    T2M Min        AMJ  \u001b[1;36m0.516145\u001b[0m  \n",
       "\u001b[1;36m114\u001b[0m     ERA5                   T2M Avg   OND Trend  \u001b[1;36m0.510513\u001b[0m  \n",
       "\u001b[1;36m96\u001b[0m      ERA5      Snowfall Occurrences   JAS Trend  \u001b[1;36m0.510164\u001b[0m  \n",
       "\u001b[1;36m109\u001b[0m     ERA5                    T2M Avg        JFM  \u001b[1;36m0.508959\u001b[0m  \n",
       "\u001b[1;36m41\u001b[0m      ERA5      Freezing Degree Days   JFM Trend  \u001b[1;36m0.504476\u001b[0m  \n",
       "\u001b[1;36m125\u001b[0m     ERA5                   T2M Mean        JFM  \u001b[1;36m0.504011\u001b[0m  \n",
       "\u001b[1;36m92\u001b[0m      ERA5       Snowfall Occurrences        JAS  \u001b[1;36m0.502363\u001b[0m  \n",
       "\u001b[1;36m59\u001b[0m      ERA5  Precipitation Occurrences        AMJ  \u001b[1;36m0.496039\u001b[0m  \n",
       "\u001b[1;36m101\u001b[0m     ERA5                       Sshf        JFM  \u001b[1;36m0.478791\u001b[0m  \n",
       "\u001b[1;36m37\u001b[0m      ERA5       Freezing Degree Days        JFM  \u001b[1;36m0.465258\u001b[0m  \n",
       "\u001b[1;36m122\u001b[0m     ERA5                   T2M Max   OND Trend  \u001b[1;36m0.464464\u001b[0m  \n",
       "\u001b[1;36m76\u001b[0m      ERA5                         Sf        JAS  \u001b[1;36m0.449828\u001b[0m  \n",
       "\u001b[1;36m102\u001b[0m     ERA5                       Sshf        OND  \u001b[1;36m0.435038\u001b[0m  \n",
       "\u001b[1;36m62\u001b[0m      ERA5  Precipitation Occurrences        OND  \u001b[1;36m0.403725\u001b[0m  \n",
       "\u001b[1;36m80\u001b[0m      ERA5                        Sf   JAS Trend  \u001b[1;36m0.403717\u001b[0m  \n",
       "\u001b[1;36m149\u001b[0m     ERA5                   T2M Skew        JFM  \u001b[1;36m0.401495\u001b[0m  "
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature_similarities[feature_similarities[\"Score\"] > 0.4].sort_values(\"Score\", ascending=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "368b06a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\n",
       "\u001b[1m[\u001b[0m\n",
       "    \u001b[32m'x'\u001b[0m,\n",
       "    \u001b[32m'y'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_sf_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_sf_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_snowc_mean_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_snowfall_occurrences_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_snowfall_occurrences_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_sshf_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_sshf_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_mean_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_mean_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_mean_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_mean_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_mean_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_min_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_min_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_min_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_range_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_range_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_skew_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_skew_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_thawing_days_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_thawing_days_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_thawing_days_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_thawing_degree_days_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_thawing_degree_days_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_tp_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_tp_JAS'\u001b[0m\n",
       "\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "univariate_features = feature_similarities[feature_similarities[\"Score\"] > 0.4][\"Feature\"].to_list()\n",
    "univariate_features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "6d061187",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mmatplotlib.legend.Legend\u001b[0m\u001b[39m object at \u001b[0m\u001b[1;36m0x7f1e94ae0a50\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 1423480 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 480\u001b[0m\u001b[1;36m0x5200\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m5\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "corr = spearmanr(X_train).correlation\n",
    "\n",
    "# Ensure the correlation matrix is symmetric\n",
    "corr = (corr + corr.T) / 2\n",
    "np.fill_diagonal(corr, 1)\n",
    "\n",
    "corr_df = pd.DataFrame(corr, index=training_data.feature_names, columns=training_data.feature_names)\n",
    "\n",
    "\n",
    "parsed_feature_names = [parse_feature_name(name) for name in training_data.feature_names]\n",
    "feature_info_df = pd.DataFrame(\n",
    "    parsed_feature_names, columns=[\"Source\", \"Variable\", \"Season\"], index=training_data.feature_names\n",
    ")\n",
    "source_pal = sns.husl_palette(3, s=0.45)\n",
    "source_lut = dict(zip(feature_info_df[\"Source\"].unique(), source_pal))\n",
    "variable_pal = sns.husl_palette(feature_info_df[\"Season\"].nunique(), s=0.45)\n",
    "variable_lut = dict(zip(feature_info_df[\"Season\"].unique(), variable_pal))\n",
    "seasonal_colors = {\n",
    "    \"JFM\": \"#5BA3D0\",  # Cool blue\n",
    "    \"AMJ\": \"#7BC96F\",  # Fresh green\n",
    "    \"JAS\": \"#FFD166\",  # Warm yellow\n",
    "    \"OND\": \"#E07A5F\",  # Earthy orange-red\n",
    "    \"JFM Trend\": \"#2C5F7F\",  # Deep blue\n",
    "    \"AMJ Trend\": \"#4A7C59\",  # Forest green\n",
    "    \"JAS Trend\": \"#D4A142\",  # Golden amber\n",
    "    \"OND Trend\": \"#A0503C\",  # Rich terracotta\n",
    "    \"\": \"#888888\",  # Gray for features without a season\n",
    "}\n",
    "season_lut = {season: mcolors.hex2color(color) for season, color in seasonal_colors.items()}\n",
    "row_colors = feature_info_df[\"Source\"].map(source_lut)\n",
    "col_colors = feature_info_df[\"Season\"].map(season_lut)\n",
    "\n",
    "g = sns.clustermap(\n",
    "    corr_df,\n",
    "    row_colors=row_colors,\n",
    "    col_colors=col_colors,\n",
    "    dendrogram_ratio=(0.1, 0.2),\n",
    "    cbar_pos=(0.02, 0.32, 0.03, 0.2),\n",
    "    center=0,\n",
    "    cmap=\"vlag\",\n",
    "    linewidths=0.9,\n",
    "    figsize=(48, 52),\n",
    ")\n",
    "g.ax_row_dendrogram.remove()\n",
    "\n",
    "# Customize colorbar\n",
    "cbar = g.ax_cbar\n",
    "cbar.set_ylabel(\"Spearman Correlation\", fontsize=16, rotation=90, labelpad=25)\n",
    "cbar.tick_params(labelsize=14)\n",
    "\n",
    "# Add legend for sources (row colors)\n",
    "source_handles = [\n",
    "    Patch(facecolor=source_lut[source], label=source, linewidth=2, edgecolor=\"black\")\n",
    "    for source in sorted(source_lut.keys())\n",
    "]\n",
    "source_legend = g.ax_heatmap.legend(\n",
    "    handles=source_handles,\n",
    "    title=\"Source\",\n",
    "    bbox_to_anchor=(-0.13, 0.95),\n",
    "    loc=\"upper left\",\n",
    "    frameon=True,\n",
    "    fontsize=14,\n",
    "    title_fontsize=16,\n",
    "    handlelength=2.5,\n",
    "    handleheight=2.0,\n",
    ")\n",
    "\n",
    "# Increase font size for row and column color ticks\n",
    "g.ax_row_colors.set_xticklabels(g.ax_row_colors.get_xticklabels(), fontsize=16)\n",
    "g.ax_col_colors.set_yticklabels(g.ax_col_colors.get_yticklabels(), fontsize=16)\n",
    "\n",
    "# Add legend for seasons (column colors)\n",
    "season_handles = [\n",
    "    Patch(facecolor=season_lut[season], label=season if season else \"No Season\", linewidth=2, edgecolor=\"black\")\n",
    "    for season in sorted(season_lut.keys(), key=lambda x: (x == \"\", x))\n",
    "]\n",
    "season_legend = g.ax_heatmap.legend(\n",
    "    handles=season_handles,\n",
    "    title=\"Season\",\n",
    "    bbox_to_anchor=(-0.13, 0.85),\n",
    "    loc=\"upper left\",\n",
    "    frameon=True,\n",
    "    fontsize=14,\n",
    "    title_fontsize=16,\n",
    "    handlelength=2.5,\n",
    "    handleheight=2.0,\n",
    ")\n",
    "\n",
    "# Add the source legend back since the second legend() call replaces it\n",
    "g.ax_heatmap.add_artist(source_legend)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "5ad120e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# We convert the correlation matrix to a distance matrix before performing\n",
    "# hierarchical clustering using Ward's linkage.\n",
    "distance_matrix = 1 - np.abs(corr)\n",
    "dist_linkage = hierarchy.ward(squareform(distance_matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "68d5c2d5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 157312 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 130\u001b[0m\u001b[1;36m0x700\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m2\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Show how the feature-selection threshold effects the absolute correlation\n",
    "# (min, mean, max, 1std) between the selected features\n",
    "thresholds = np.linspace(0, 3, 125)\n",
    "max_abs_correlations = []\n",
    "median_abs_correlations = []\n",
    "q75_abs_correlations = []\n",
    "q25_abs_correlations = []\n",
    "q95_abs_correlations = []\n",
    "q05_abs_correlations = []\n",
    "num_selected_features = []\n",
    "\n",
    "for threshold in thresholds:\n",
    "    cluster_ids = hierarchy.fcluster(dist_linkage, threshold, criterion=\"distance\")\n",
    "    cluster_id_to_feature_ids = defaultdict(list)\n",
    "    for idx, cluster_id in enumerate(cluster_ids):\n",
    "        cluster_id_to_feature_ids[cluster_id].append(idx)\n",
    "    selected_features = [v[0] for v in cluster_id_to_feature_ids.values()]\n",
    "    num_selected_features.append(len(selected_features))\n",
    "    selected_corr = corr[np.ix_(selected_features, selected_features)]\n",
    "    abs_corr_values = np.abs(selected_corr - np.eye(len(selected_features)))\n",
    "    max_abs_correlation = np.max(abs_corr_values)\n",
    "    max_abs_correlations.append(max_abs_correlation)\n",
    "    median_abs_correlation = np.median(abs_corr_values)\n",
    "    median_abs_correlations.append(median_abs_correlation)\n",
    "    q75_abs_correlation = np.quantile(abs_corr_values, 0.75)\n",
    "    q75_abs_correlations.append(q75_abs_correlation)\n",
    "    q25_abs_correlation = np.quantile(abs_corr_values, 0.25)\n",
    "    q25_abs_correlations.append(q25_abs_correlation)\n",
    "    q95_abs_correlation = np.quantile(abs_corr_values, 0.95)\n",
    "    q95_abs_correlations.append(q95_abs_correlation)\n",
    "    q05_abs_correlation = np.quantile(abs_corr_values, 0.05)\n",
    "    q05_abs_correlations.append(q05_abs_correlation)\n",
    "\n",
    "fig, ax1 = plt.subplots(figsize=(13, 7))\n",
    "\n",
    "# Left y-axis: Absolute correlation metrics\n",
    "ax1.plot(\n",
    "    thresholds,\n",
    "    median_abs_correlations,\n",
    "    label=\"Median Abs Correlation\",\n",
    "    linewidth=3,\n",
    "    color=\"#1f77b4\",\n",
    "    zorder=3,\n",
    ")\n",
    "ax1.fill_between(\n",
    "    thresholds,\n",
    "    np.array(q25_abs_correlations),\n",
    "    np.array(q75_abs_correlations),\n",
    "    alpha=0.2,\n",
    "    color=\"#1f77b4\",\n",
    "    label=\"25th-75th Percentile\",\n",
    "    zorder=2,\n",
    ")\n",
    "ax1.fill_between(\n",
    "    thresholds,\n",
    "    np.array(q05_abs_correlations),\n",
    "    np.array(q95_abs_correlations),\n",
    "    alpha=0.1,\n",
    "    color=\"#1f77b4\",\n",
    "    label=\"5th-95th Percentile\",\n",
    "    zorder=1,\n",
    ")\n",
    "\n",
    "# Plot max as dashed lines (min is always 0)\n",
    "ax1.plot(\n",
    "    thresholds,\n",
    "    max_abs_correlations,\n",
    "    label=\"Max Abs Correlation\",\n",
    "    linewidth=2,\n",
    "    linestyle=\"--\",\n",
    "    color=\"#1f77b4\",\n",
    "    alpha=0.7,\n",
    "    zorder=1,\n",
    ")\n",
    "\n",
    "ax1.set_xlabel(\"Clustering Threshold\", fontsize=12, fontweight=\"bold\")\n",
    "ax1.set_ylabel(\"Absolute Correlation\", fontsize=12, fontweight=\"bold\", color=\"#1f77b4\")\n",
    "ax1.tick_params(axis=\"y\", labelcolor=\"#1f77b4\")\n",
    "ax1.grid(True, alpha=0.3, linestyle=\"--\")\n",
    "ax1.set_ylim(bottom=0)\n",
    "\n",
    "# Right y-axis: Number of selected features\n",
    "ax2 = ax1.twinx()\n",
    "ax2.plot(\n",
    "    thresholds,\n",
    "    num_selected_features,\n",
    "    label=\"Number of Selected Features\",\n",
    "    linewidth=2.5,\n",
    "    color=\"#C41E3A\",\n",
    "    marker=\"o\",\n",
    "    markersize=6,\n",
    "    alpha=0.6,\n",
    ")\n",
    "# ax2.set_yscale(\"log\")\n",
    "ax2.grid(False)\n",
    "ax2.set_ylabel(\"Number of Selected Features\", fontsize=12, fontweight=\"bold\", color=\"#C41E3A\")\n",
    "ax2.tick_params(axis=\"y\", labelcolor=\"#C41E3A\")\n",
    "\n",
    "# Combine legends\n",
    "lines1, labels1 = ax1.get_legend_handles_labels()\n",
    "lines2, labels2 = ax2.get_legend_handles_labels()\n",
    "legend = ax1.legend(lines1 + lines2, labels1 + labels2, fontsize=11, loc=\"upper right\", framealpha=0.95, fancybox=True)\n",
    "legend.get_frame().set_zorder(4)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "c3d1000b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 382624 characters]",
      "text/plain": [
       "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 180\u001b[0m\u001b[1;36m0x1900\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m5\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cluster_ids = hierarchy.fcluster(dist_linkage, 0.5, criterion=\"distance\")\n",
    "# Get the feature names of the clusters\n",
    "cluster_id_to_feature_ids = defaultdict(list)\n",
    "for idx, cluster_id in enumerate(cluster_ids):\n",
    "    cluster_id_to_feature_ids[cluster_id].append(idx)\n",
    "selected_features = [v[0] for v in cluster_id_to_feature_ids.values()]\n",
    "X_train = pd.DataFrame(X_train, columns=feature_names)\n",
    "selected_features_names = X_train.columns[selected_features]\n",
    "\n",
    "X_train_selected = X_train[selected_features_names]\n",
    "corr_selected = spearmanr(X_train_selected).correlation\n",
    "# Ensure the correlation matrix is symmetric\n",
    "corr_selected = (corr_selected + corr_selected.T) / 2\n",
    "np.fill_diagonal(corr_selected, 1)\n",
    "corr_selected_df = pd.DataFrame(corr_selected, index=selected_features_names, columns=selected_features_names)\n",
    "\n",
    "parsed_feature_names = [parse_feature_name(name) for name in selected_features_names]\n",
    "feature_info_df = pd.DataFrame(\n",
    "    parsed_feature_names, columns=[\"Source\", \"Variable\", \"Season\"], index=selected_features_names\n",
    ")\n",
    "source_pal = sns.husl_palette(3, s=0.45)\n",
    "source_lut = dict(zip(feature_info_df[\"Source\"].unique(), source_pal))\n",
    "variable_pal = sns.husl_palette(feature_info_df[\"Season\"].nunique(), s=0.45)\n",
    "variable_lut = dict(zip(feature_info_df[\"Season\"].unique(), variable_pal))\n",
    "row_colors = feature_info_df[\"Source\"].map(source_lut)\n",
    "col_colors = feature_info_df[\"Season\"].map(variable_lut)\n",
    "\n",
    "g = sns.clustermap(\n",
    "    corr_selected_df,\n",
    "    row_colors=row_colors,\n",
    "    col_colors=col_colors,\n",
    "    dendrogram_ratio=(0.1, 0.2),\n",
    "    cbar_pos=(0.02, 0.32, 0.03, 0.2),\n",
    "    center=0,\n",
    "    cmap=\"vlag\",\n",
    "    linewidths=0.75,\n",
    "    figsize=(18, 19),\n",
    ")\n",
    "g.ax_row_dendrogram.remove()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7bf6ba52",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Selected Feature], [Other Features in Cluster], \n",
      "[Slope], [Tri Large, Tri Medium, Tri Small, Vrm Large, Vrm Medium, Vrm Small],\n",
      "[Dem], [—],\n",
      "[Water Area], [Land Ratio, Effective Snow Depth Spring, Effective Snow Depth Summer, Effective Snow Depth Winter, Effective Snow Depth Fall, Naive Snow Isolation Spring, Naive Snow Isolation Summer, Naive Snow Isolation Winter, Naive Snow Isolation Fall, Naive Snow Isolation Trend Summer, Sde Spring, Sde Summer, Sde Winter, Sde Fall, Sde Trend Summer, Snowc Summer, Snowc Trend Winter],\n",
      "[Snowc Winter], [Snowc Fall],\n",
      "[Freezing Days Winter], [Freezing Days Trend Winter, Thawing Days Winter, Thawing Days Trend Winter, Thawing Degree Days Winter, Thawing Degree Days Trend Winter],\n",
      "[Snowc Trend Fall], [—],\n",
      "[Effective Snow Depth Trend Spring], [Naive Snow Isolation Trend Spring, Sde Trend Spring],\n",
      "[Precipitation Occurrences Trend Fall], [Snowfall Occurrences Trend Fall, Tp Trend Fall],\n",
      "[Freezing Days Trend Fall], [Thawing Days Trend Fall, Thawing Degree Days Trend Fall],\n",
      "[Lblt Max Trend Fall], [—],\n",
      "[Effective Snow Depth Trend Fall], [Naive Snow Isolation Trend Fall, Sde Trend Fall],\n",
      "[Effective Snow Depth Trend Winter], [Naive Snow Isolation Trend Winter, Sde Trend Winter, Sf Trend Fall],\n",
      "[Precipitation Occurrences Trend Winter], [Sf Trend Winter, Snowfall Occurrences Trend Winter, Tp Trend Winter],\n",
      "[Curvature], [Tpi Large, Tpi Medium, Tpi Small],\n",
      "[Sf Trend Spring], [Snowfall Occurrences Trend Spring],\n",
      "[T2M Range Trend Spring], [—],\n",
      "[Precipitation Occurrences Trend Spring], [Tp Trend Spring],\n",
      "[T2M Skew Trend Spring], [—],\n",
      "[T2M Avg Trend Spring], [T2M Trend Spring],\n",
      "[Freezing Days Trend Spring], [T2M Max Trend Spring, Thawing Days Trend Spring, Thawing Degree Days Trend Spring],\n",
      "[Sshf Trend Winter], [Sshf Trend Fall],\n",
      "[T2M Max Trend Summer], [—],\n",
      "[Cell Area], [Land Area],\n",
      "[T2M Max Trend Winter], [—],\n",
      "[T2M Skew Trend Winter], [—],\n",
      "[Aspect], [—],\n",
      "[Lblt Max Trend Winter], [—],\n",
      "[Lblt Max Summer], [Lblt Max Winter],\n",
      "[Lblt Max Trend Spring], [—],\n",
      "[Lblt Max Trend Summer], [—],\n",
      "[T2M Avg Trend Summer], [T2M Trend Summer, Thawing Degree Days Trend Summer],\n",
      "[T2M Range Trend Winter], [—],\n",
      "[Precipitation Occurrences Trend Summer], [Sshf Trend Summer, Tp Trend Summer],\n",
      "[Freezing Degree Days Trend Spring], [T2M Min Trend Spring],\n",
      "[X], [T2M Range Trend Summer, T2M Range Trend Fall, T2M Skew Spring, T2M Skew Summer, T2M Skew Winter, T2M Skew Fall],\n",
      "[T2M Min Winter], [T2M Min Fall],\n",
      "[Freezing Days Fall], [Freezing Degree Days Winter, Freezing Degree Days Fall, Lblt Max Fall, T2M Avg Winter, T2M Avg Fall, T2M Winter, T2M Fall, Thawing Days Fall, Thawing Degree Days Fall],\n",
      "[Precipitation Occurrences Winter], [Precipitation Occurrences Fall, Sf Winter, Sf Fall, Snowfall Occurrences Winter, Snowfall Occurrences Fall, Tp Winter, Tp Fall],\n",
      "[Precipitation Occurrences Spring], [Precipitation Occurrences Summer, Tp Spring, Tp Summer],\n",
      "[Freezing Days Spring], [Freezing Days Trend Summer, Freezing Degree Days Spring, Lblt Max Spring, Snowc Spring, T2M Avg Spring, T2M Avg Summer, T2M Max Winter, T2M Max Fall, T2M Spring, T2M Summer, T2M Min Spring, Thawing Days Spring, Thawing Days Trend Summer, Thawing Degree Days Spring, Thawing Degree Days Summer],\n",
      "[Freezing Days Summer], [Freezing Degree Days Summer, Freezing Degree Days Trend Summer, Sf Summer, Snowfall Occurrences Summer, T2M Min Summer, Thawing Days Summer],\n",
      "[Effective Snow Depth Trend Summer], [Snowc Trend Summer],\n",
      "[Sf Spring], [Snowfall Occurrences Spring],\n",
      "[T2M Range Winter], [T2M Range Fall],\n",
      "[T2M Max Spring], [T2M Max Summer, T2M Range Spring, T2M Range Summer],\n",
      "[Sshf Spring], [Sshf Summer],\n",
      "[Y], [—],\n",
      "[T2M Max Trend Fall], [T2M Min Trend Summer],\n",
      "[T2M Skew Trend Summer], [—],\n",
      "[Snowc Trend Spring], [—],\n",
      "[Sf Trend Summer], [Snowfall Occurrences Trend Summer],\n",
      "[T2M Skew Trend Fall], [—],\n",
      "[Freezing Degree Days Trend Winter], [T2M Avg Trend Winter, T2M Trend Winter],\n",
      "[Freezing Degree Days Trend Fall], [T2M Avg Trend Fall, T2M Trend Fall, T2M Min Trend Winter],\n",
      "[Sshf Winter], [Sshf Fall],\n",
      "[Sshf Trend Spring], [—],\n",
      "[T2M Min Trend Fall], [—],\n",
      "\n"
     ]
    }
   ],
   "source": [
    "def create_cluster_comparison_typst_table(\n",
    "    cluster_features: list[str],\n",
    "    univariate_features: list[str],\n",
    "    dist_linkage,\n",
    "    feature_names: list[str],\n",
    ") -> str:\n",
    "    \"\"\"Generate a typst table comparing selected cluster features with non-selected features.\n",
    "\n",
    "    Args:\n",
    "        cluster_features: List of features selected by clustering method\n",
    "        univariate_features: List of univariate features for reference\n",
    "        dist_linkage: Hierarchical clustering linkage from scipy\n",
    "        feature_names: All available feature names\n",
    "\n",
    "    Returns:\n",
    "        Formatted typst table string\n",
    "\n",
    "    \"\"\"\n",
    "    from collections import defaultdict\n",
    "\n",
    "    from scipy.cluster import hierarchy\n",
    "\n",
    "    # Perform clustering to get feature groups\n",
    "    cluster_ids = hierarchy.fcluster(dist_linkage, 0.5, criterion=\"distance\")\n",
    "    cluster_id_to_feature_ids = defaultdict(list)\n",
    "\n",
    "    for idx, cluster_id in enumerate(cluster_ids):\n",
    "        cluster_id_to_feature_ids[cluster_id].append(idx)\n",
    "\n",
    "    # Get selected and non-selected features per cluster\n",
    "    cluster_analysis = {}\n",
    "    for cluster_id, feature_indices in cluster_id_to_feature_ids.items():\n",
    "        selected = feature_names[feature_indices[0]]  # Representative feature\n",
    "        non_selected = [feature_names[idx] for idx in feature_indices[1:]]\n",
    "        cluster_analysis[cluster_id] = {\n",
    "            \"selected\": selected,\n",
    "            \"non_selected\": non_selected,\n",
    "        }\n",
    "\n",
    "    # Build typst table\n",
    "    headings = [\"Selected Feature\", \"Other Features in Cluster\"]\n",
    "    typst_table = \"\"\n",
    "\n",
    "    for h in headings:\n",
    "        typst_table += f\"[{h}], \"\n",
    "\n",
    "    typst_table += \"\\n\"\n",
    "\n",
    "    for cluster_id in sorted(cluster_analysis.keys()):\n",
    "        info = cluster_analysis[cluster_id]\n",
    "        selected_name = _parse_feature_name(info[\"selected\"])\n",
    "        non_selected_names = \", \".join([_parse_feature_name(f) for f in info[\"non_selected\"]])\n",
    "\n",
    "        typst_table += f\"[{selected_name}], [{non_selected_names if non_selected_names else '—'}],\\n\"\n",
    "\n",
    "    return typst_table\n",
    "\n",
    "\n",
    "# After clustering in your feature_selection.ipynb\n",
    "typst_output = create_cluster_comparison_typst_table(\n",
    "    cluster_features=X_train_selected.columns.to_list(),\n",
    "    univariate_features=univariate_features,\n",
    "    dist_linkage=dist_linkage,\n",
    "    feature_names=training_data.feature_names,\n",
    ")\n",
    "print(typst_output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7a887dcb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\u001b[1;36m57\u001b[0m"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(X_train_selected.columns.to_list())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "cdcf584c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "\n",
       "\u001b[1m[\u001b[0m\n",
       "    \u001b[32m'cell_area'\u001b[0m,\n",
       "    \u001b[32m'water_area'\u001b[0m,\n",
       "    \u001b[32m'x'\u001b[0m,\n",
       "    \u001b[32m'y'\u001b[0m,\n",
       "    \u001b[32m'arcticdem_aspect_median'\u001b[0m,\n",
       "    \u001b[32m'arcticdem_curvature_median'\u001b[0m,\n",
       "    \u001b[32m'arcticdem_dem_median'\u001b[0m,\n",
       "    \u001b[32m'arcticdem_slope_median'\u001b[0m,\n",
       "    \u001b[32m'era5_effective_snow_depth_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_effective_snow_depth_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_effective_snow_depth_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_effective_snow_depth_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_days_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_freezing_degree_days_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_lblt_max_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_lblt_max_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_lblt_max_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_lblt_max_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_lblt_max_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_precipitation_occurrences_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_sf_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_sf_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_sf_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_snowc_mean_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_snowc_mean_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_snowc_mean_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_sshf_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_sshf_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_sshf_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_sshf_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_avg_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_max_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_min_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_min_trend_OND'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_range_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_range_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_range_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_skew_trend_AMJ'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_skew_trend_JAS'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_skew_trend_JFM'\u001b[0m,\n",
       "    \u001b[32m'era5_t2m_skew_trend_OND'\u001b[0m\n",
       "\u001b[1m]\u001b[0m"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train_selected.columns.to_list()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "default",
   "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.13.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
