{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ec10aab9-454d-4dc2-9059-665e60050d73",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ethoscopy as etho\n",
    "import pandas as pd\n",
    "from scipy.stats import mannwhitneyu\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import seaborn as sns\n",
    "from scipy.stats import wilcoxon, shapiro, ttest_rel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5289d86c-0107-4089-83e3-327b70168e08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2.1.0'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "etho.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3d32b423-cc70-43f2-a2cc-ed9bd08c2981",
   "metadata": {},
   "outputs": [],
   "source": [
    "meta = '/home/rdingjin/CantonS_2026-05-01/metadata_CantonS_2026-05-01_green.csv'\n",
    "local = '/mnt/ethoscope_results'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "df11ef6f-5475-45b0-95c3-2a8672a21219",
   "metadata": {},
   "outputs": [],
   "source": [
    "metadata = etho.link_meta_index(meta, local)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ebfbf3dc-d405-4f7b-a4a1-1eacff24f3a5",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loading ROI_1 from ETHOSCOPE_130\n",
      "Loading ROI_2 from ETHOSCOPE_130\n",
      "Loading ROI_3 from ETHOSCOPE_130\n",
      "Loading ROI_4 from ETHOSCOPE_130\n",
      "Loading ROI_5 from ETHOSCOPE_130\n",
      "Loading ROI_6 from ETHOSCOPE_130\n",
      "Loading ROI_7 from ETHOSCOPE_130\n",
      "Loading ROI_8 from ETHOSCOPE_130\n",
      "Loading ROI_9 from ETHOSCOPE_130\n",
      "Loading ROI_10 from ETHOSCOPE_130\n",
      "Loading ROI_11 from ETHOSCOPE_130\n",
      "Loading ROI_12 from ETHOSCOPE_130\n",
      "Loading ROI_13 from ETHOSCOPE_130\n",
      "Loading ROI_14 from ETHOSCOPE_130\n",
      "Loading ROI_15 from ETHOSCOPE_130\n",
      "Loading ROI_16 from ETHOSCOPE_130\n",
      "Loading ROI_17 from ETHOSCOPE_130\n",
      "Loading ROI_18 from ETHOSCOPE_130\n",
      "Loading ROI_19 from ETHOSCOPE_130\n",
      "Loading ROI_20 from ETHOSCOPE_130\n"
     ]
    }
   ],
   "source": [
    "#fetch data from ethoscope\n",
    "data = etho.load_ethoscope(metadata, reference_hour = 9.0, FUN = etho.sleep_annotation)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a32d69f8-e66c-47fc-9b9a-2273f2c5082b",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = etho.behavpy(data, metadata, check = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e633d7d9-99db-4815-900d-e79d11dd65b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.to_pickle('/home/rdingjin/CantonS_2026-05-01/phase3.pkl')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ae2ff7e0-2f6c-4cc0-9afd-a1c021140760",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ethoscopy as etho\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from scipy.stats import wilcoxon, shapiro, ttest_rel\n",
    "df = pd.read_pickle('/home/rdingjin/CantonS_2026-05-01/phase3.pkl')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "94a0854d-4b5a-475f-a856-c61ec01d080e",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = df.baseline(column = 'baseline')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "cae6a067-5fd7-493a-9f23-c75d63e6ae06",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " ==== METADATA ====\n",
      "\n",
      "                                     date   machine_name  region_id  \\\n",
      "id                                                                    \n",
      "2026-05-01_14-02-36_13005e|01  2026-05-01  ETHOSCOPE_130          1   \n",
      "2026-05-01_14-02-36_13005e|02  2026-05-01  ETHOSCOPE_130          2   \n",
      "2026-05-01_14-02-36_13005e|03  2026-05-01  ETHOSCOPE_130          3   \n",
      "2026-05-01_14-02-36_13005e|04  2026-05-01  ETHOSCOPE_130          4   \n",
      "2026-05-01_14-02-36_13005e|05  2026-05-01  ETHOSCOPE_130          5   \n",
      "2026-05-01_14-02-36_13005e|06  2026-05-01  ETHOSCOPE_130          6   \n",
      "2026-05-01_14-02-36_13005e|07  2026-05-01  ETHOSCOPE_130          7   \n",
      "2026-05-01_14-02-36_13005e|08  2026-05-01  ETHOSCOPE_130          8   \n",
      "2026-05-01_14-02-36_13005e|09  2026-05-01  ETHOSCOPE_130          9   \n",
      "2026-05-01_14-02-36_13005e|10  2026-05-01  ETHOSCOPE_130         10   \n",
      "2026-05-01_14-02-36_13005e|11  2026-05-01  ETHOSCOPE_130         11   \n",
      "2026-05-01_14-02-36_13005e|12  2026-05-01  ETHOSCOPE_130         12   \n",
      "2026-05-01_14-02-36_13005e|13  2026-05-01  ETHOSCOPE_130         13   \n",
      "2026-05-01_14-02-36_13005e|14  2026-05-01  ETHOSCOPE_130         14   \n",
      "2026-05-01_14-02-36_13005e|15  2026-05-01  ETHOSCOPE_130         15   \n",
      "2026-05-01_14-02-36_13005e|16  2026-05-01  ETHOSCOPE_130         16   \n",
      "2026-05-01_14-02-36_13005e|17  2026-05-01  ETHOSCOPE_130         17   \n",
      "2026-05-01_14-02-36_13005e|18  2026-05-01  ETHOSCOPE_130         18   \n",
      "2026-05-01_14-02-36_13005e|19  2026-05-01  ETHOSCOPE_130         19   \n",
      "2026-05-01_14-02-36_13005e|20  2026-05-01  ETHOSCOPE_130         20   \n",
      "\n",
      "                               sleep_deprived  species         food  baseline  \\\n",
      "id                                                                              \n",
      "2026-05-01_14-02-36_13005e|01            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|02           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|03            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|04           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|05            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|06           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|07            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|08           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|09            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|10           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|11           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|12            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|13           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|14            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|15           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|16            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|17           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|18            True  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|19           False  CantonS  normal_food         0   \n",
      "2026-05-01_14-02-36_13005e|20            True  CantonS  normal_food         0   \n",
      "\n",
      "                                sex      time  \n",
      "id                                             \n",
      "2026-05-01_14-02-36_13005e|01  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|02  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|03  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|04  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|05  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|06  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|07  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|08  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|09  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|10  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|11  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|12  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|13  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|14  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|15  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|16  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|17  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|18  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|19  male  14-02-36  \n",
      "2026-05-01_14-02-36_13005e|20  male  14-02-36  \n",
      " ====== DATA ======\n",
      "\n",
      "                                    t           x          y          w  \\\n",
      "id                                                                        \n",
      "2026-05-01_14-02-36_13005e|01   18180  159.250000  46.350000  27.100000   \n",
      "2026-05-01_14-02-36_13005e|01   18190  239.650000  43.200000  28.650000   \n",
      "2026-05-01_14-02-36_13005e|01   18200  249.578947  42.052632  28.526316   \n",
      "2026-05-01_14-02-36_13005e|01   18210  261.684211  44.684211  27.052632   \n",
      "2026-05-01_14-02-36_13005e|01   18220  321.666667  47.555556  25.500000   \n",
      "...                               ...         ...        ...        ...   \n",
      "2026-05-01_14-02-36_13005e|20  359410  269.000000  26.000000  27.111111   \n",
      "2026-05-01_14-02-36_13005e|20  359420  269.000000  26.000000  27.400000   \n",
      "2026-05-01_14-02-36_13005e|20  359430  269.000000  26.000000  27.117647   \n",
      "2026-05-01_14-02-36_13005e|20  359440  269.000000  26.000000  27.133333   \n",
      "2026-05-01_14-02-36_13005e|20  359450  269.000000  26.000000  27.000000   \n",
      "\n",
      "                                       h         phi  max_velocity  \\\n",
      "id                                                                   \n",
      "2026-05-01_14-02-36_13005e|01  12.600000  160.450000     10.324731   \n",
      "2026-05-01_14-02-36_13005e|01  12.150000   16.800000      3.082327   \n",
      "2026-05-01_14-02-36_13005e|01  12.105263  107.105263      7.996110   \n",
      "2026-05-01_14-02-36_13005e|01  11.210526   14.210526     13.548111   \n",
      "2026-05-01_14-02-36_13005e|01  11.444444  107.777778     10.253656   \n",
      "...                                  ...         ...           ...   \n",
      "2026-05-01_14-02-36_13005e|20  11.944444   10.333333      0.714297   \n",
      "2026-05-01_14-02-36_13005e|20  12.000000   13.000000      0.747961   \n",
      "2026-05-01_14-02-36_13005e|20  11.941176   10.941176      0.888953   \n",
      "2026-05-01_14-02-36_13005e|20  11.933333   12.400000      0.730935   \n",
      "2026-05-01_14-02-36_13005e|20  12.000000    0.000000      0.655962   \n",
      "\n",
      "                               mean_velocity      dist  has_interacted  \\\n",
      "id                                                                       \n",
      "2026-05-01_14-02-36_13005e|01       5.212167  0.312730             0.0   \n",
      "2026-05-01_14-02-36_13005e|01       0.983852  0.059031             0.0   \n",
      "2026-05-01_14-02-36_13005e|01       1.723054  0.098214             0.0   \n",
      "2026-05-01_14-02-36_13005e|01       2.109787  0.120258             0.0   \n",
      "2026-05-01_14-02-36_13005e|01       4.167080  0.225022             0.0   \n",
      "...                                      ...       ...             ...   \n",
      "2026-05-01_14-02-36_13005e|20       0.649865  0.035093             0.0   \n",
      "2026-05-01_14-02-36_13005e|20       0.653423  0.029404             0.0   \n",
      "2026-05-01_14-02-36_13005e|20       0.671835  0.034264             0.0   \n",
      "2026-05-01_14-02-36_13005e|20       0.644651  0.029009             0.0   \n",
      "2026-05-01_14-02-36_13005e|20       0.655962  0.001968             0.0   \n",
      "\n",
      "                               beam_cross moving  micro   walk  \\\n",
      "id                                                               \n",
      "2026-05-01_14-02-36_13005e|01         0.0   True  False   True   \n",
      "2026-05-01_14-02-36_13005e|01         0.0   True  False   True   \n",
      "2026-05-01_14-02-36_13005e|01         0.0   True  False   True   \n",
      "2026-05-01_14-02-36_13005e|01         0.0   True  False   True   \n",
      "2026-05-01_14-02-36_13005e|01         0.0   True  False   True   \n",
      "...                                   ...    ...    ...    ...   \n",
      "2026-05-01_14-02-36_13005e|20         0.0  False  False  False   \n",
      "2026-05-01_14-02-36_13005e|20         0.0  False  False  False   \n",
      "2026-05-01_14-02-36_13005e|20         0.0  False  False  False   \n",
      "2026-05-01_14-02-36_13005e|20         0.0  False  False  False   \n",
      "2026-05-01_14-02-36_13005e|20         0.0  False  False  False   \n",
      "\n",
      "                               is_interpolated  asleep  \n",
      "id                                                      \n",
      "2026-05-01_14-02-36_13005e|01            False   False  \n",
      "2026-05-01_14-02-36_13005e|01            False   False  \n",
      "2026-05-01_14-02-36_13005e|01            False   False  \n",
      "2026-05-01_14-02-36_13005e|01            False   False  \n",
      "2026-05-01_14-02-36_13005e|01            False   False  \n",
      "...                                        ...     ...  \n",
      "2026-05-01_14-02-36_13005e|20            False   False  \n",
      "2026-05-01_14-02-36_13005e|20            False   False  \n",
      "2026-05-01_14-02-36_13005e|20            False   False  \n",
      "2026-05-01_14-02-36_13005e|20            False   False  \n",
      "2026-05-01_14-02-36_13005e|20            False   False  \n",
      "\n",
      "[683112 rows x 16 columns]\n"
     ]
    }
   ],
   "source": [
    "df.display()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "76cd7456-6246-4665-a08a-d6f270a8567d",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/srv/venv/lib/python3.12/site-packages/ethoscopy/behavpy_core.py:1611: FutureWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
      "  tdf.groupby(\"id\", group_keys=False).apply(\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 80820 characters]",
      "text/plain": [
       "<Figure size 800x200 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#heatmap of CantonS sleep\n",
    "fig = df.heatmap(variable = 'asleep')\n",
    "fig.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "64a23e70-b06a-4c0e-8aad-0fee653d74b3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 186288 characters]",
      "text/plain": [
       "<Figure size 1200x475 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Generate plot from Ethoscopy\n",
    "fig = df.plot_overtime(variable='asleep', avg_window=30, grids=True)\n",
    "\n",
    "# Extract the main axis from the figure\n",
    "ax = fig.axes[0]\n",
    "\n",
    "# Add shading stimulus shading\n",
    "ax.axvspan(72, 96, color='#51ff4c', alpha=0.3, zorder=1)\n",
    "\n",
    "# Set custom labels\n",
    "ax.set_xlabel(\"Zeitgeber Time (Hours)\", fontsize=12)\n",
    "ax.set_ylabel(\"Fraction of Time Asleep\", fontsize=12)\n",
    "\n",
    "# Show plot\n",
    "fig.show()\n",
    "\n",
    "# Save as a high-resolution PNG\n",
    "plt.savefig(\"Figure_3A.png\", dpi=600, bbox_inches='tight')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "3a8d183b-f839-4168-b72f-53f1a05b5826",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 161516 characters]",
      "text/plain": [
       "<Figure size 1066.67x458.333 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "start_hour = 24\n",
    "\n",
    "# Generate plot from Ethoscopy\n",
    "fig = df.t_filter(start_time=start_hour).plot_overtime(variable='asleep', avg_window=30, grids=True)\n",
    "\n",
    "# Extract the main axis from the figure\n",
    "ax = fig.axes[0]\n",
    "\n",
    "# Add shading stimulus shading\n",
    "ax.axvspan(72, 96, color='#51ff4c', alpha=0.3, zorder=1)\n",
    "\n",
    "# Set custom labels\n",
    "ax.set_xlabel(\"Zeitgeber Time (Hours)\", fontsize=12)\n",
    "ax.set_ylabel(\"Fraction of Time Asleep\", fontsize=12)\n",
    "\n",
    "# Show plot\n",
    "fig.show()\n",
    "\n",
    "# Save as a high-resolution PNG\n",
    "plt.savefig(\"Figure_3A(start24h).png\", dpi=600, bbox_inches='tight')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "522d1ddd-247d-4f1f-b20f-fcd0e9516b41",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Individual Fly Sleep (Baseline: 0h to 72h, Averaged per day) ---\n",
      "             Fly_Label  Base_Sleep_24h  Base_Day_12h  Base_Night_12h\n",
      "ETHOSCOPE_130 - Fly 01       11.659259      4.414647        7.863889\n",
      "ETHOSCOPE_130 - Fly 02       12.112037      3.861450        8.791667\n",
      "ETHOSCOPE_130 - Fly 03       12.719444      5.493898        7.995370\n",
      "ETHOSCOPE_130 - Fly 04       13.904630      5.667265        9.031481\n",
      "ETHOSCOPE_130 - Fly 05       14.106481      5.855707        9.071296\n",
      "ETHOSCOPE_130 - Fly 06       12.323148      5.013640        8.012037\n",
      "ETHOSCOPE_130 - Fly 07       13.837963      5.827679        8.827778\n",
      "ETHOSCOPE_130 - Fly 08       12.409259      4.860732        8.229630\n",
      "ETHOSCOPE_130 - Fly 09       13.751852      6.071070        8.531481\n",
      "ETHOSCOPE_130 - Fly 10       12.789815      5.192246        8.325926\n",
      "ETHOSCOPE_130 - Fly 11        8.700926      4.479541        4.849074\n",
      "ETHOSCOPE_130 - Fly 12       11.645370      4.888729        7.441667\n",
      "ETHOSCOPE_130 - Fly 13       14.201852      6.862527        8.300926\n",
      "ETHOSCOPE_130 - Fly 14       12.330556      5.414214        7.675000\n",
      "ETHOSCOPE_130 - Fly 15       11.861111      4.684976        7.833333\n",
      "ETHOSCOPE_130 - Fly 16       12.712963      4.843503        8.548148\n",
      "ETHOSCOPE_130 - Fly 17       14.035185      5.260230        9.512037\n",
      "ETHOSCOPE_130 - Fly 18       12.533333      5.007450        8.228704\n",
      "ETHOSCOPE_130 - Fly 19       12.372222      5.780330        7.401852\n",
      "ETHOSCOPE_130 - Fly 20       12.086111      4.534458        8.187037\n",
      "... (Showing first 20 rows)\n",
      "\n",
      "--- Grand Summary Statistics (Baseline: 0h to 72h) ---\n",
      "Total Flies Analyzed: n = 20\n",
      "\n",
      "[ OVERALL SLEEP (Scaled to 24h Baseline Average) ]\n",
      "Mean ± SEM:   12.60 ± 0.28 hours\n",
      "Median:       12.47 hours\n",
      "\n",
      "[ DAY TIME (ZT 0-12, Averaged to 12h blocks) ]\n",
      "Mean ± SEM:   5.20 ± 0.15 hours\n",
      "Median:       5.10 hours\n",
      "\n",
      "[ NIGHT TIME (ZT 12-24, Averaged to 12h blocks) ]\n",
      "Mean ± SEM:   8.13 ± 0.21 hours\n",
      "Median:       8.23 hours\n"
     ]
    }
   ],
   "source": [
    "# BASELINE\n",
    "\n",
    "# Define baseline time period\n",
    "start_hour = 0\n",
    "end_hour = 72\n",
    "\n",
    "# Filter the dataset to ONLY include data within specific baseline window\n",
    "base_df = df.t_filter(start_time=start_hour, end_time=end_hour).copy()\n",
    "\n",
    "# Calculate Overall 24h Baseline Average\n",
    "sleep_hours = (base_df.groupby('id')['asleep'].sum() * 10) / 3600\n",
    "\n",
    "# (48 - 0) / 24 evaluates to exactly 2 days. \n",
    "# Dividing total sleep by 2 to average the 48 hours into a single 24-hour metric\n",
    "days_tracked = (end_hour - start_hour) / 24 \n",
    "base_overall = (sleep_hours / days_tracked).reset_index(name='Base_Sleep_24h')\n",
    "\n",
    "# Calculate Day/Night 12h Baseline Averages\n",
    "base_df['zt_hour'] = (base_df['t'] / 3600) % 24\n",
    "base_df['Phase'] = np.where(base_df['zt_hour'] < 12, 'Day', 'Night')\n",
    "\n",
    "base_phase = base_df.groupby(['id', 'Phase']).agg(\n",
    "    total_sleep_epochs=('asleep', 'sum'),\n",
    "    total_tracking_epochs=('t', 'count')\n",
    ").reset_index()\n",
    "\n",
    "# Tracking_Hours will be ~24 for Day and ~24 for Night \n",
    "# Dividing sleep by 24 and multiplying by 12 averages it to a single 12h block.\n",
    "base_phase['Sleep_Hours'] = (base_phase['total_sleep_epochs'] * 10) / 3600\n",
    "base_phase['Tracking_Hours'] = (base_phase['total_tracking_epochs'] * 10) / 3600\n",
    "base_phase['Base_Sleep_12h'] = (base_phase['Sleep_Hours'] / base_phase['Tracking_Hours']) * 12\n",
    "\n",
    "base_pivot = base_phase.pivot(index='id', columns='Phase', values='Base_Sleep_12h').reset_index()\n",
    "# Rename columns\n",
    "base_pivot.columns = ['id', 'Base_Day_12h', 'Base_Night_12h']\n",
    "\n",
    "# Merge and clean up data\n",
    "merged_df = pd.merge(base_overall, base_pivot, on='id')\n",
    "\n",
    "merged_df['Machine'] = merged_df['id'].map(df.meta['machine_name'])\n",
    "merged_df['Tube'] = merged_df['id'].apply(lambda x: str(x).split('|')[-1])\n",
    "merged_df['Fly_Label'] = merged_df['Machine'] + \" - Fly \" + merged_df['Tube']\n",
    "\n",
    "clean_table = merged_df.dropna(subset=['Machine']).sort_values(by=['Machine', 'Tube'])\n",
    "baseline_stats = clean_table[['Fly_Label', 'Base_Sleep_24h', 'Base_Day_12h', 'Base_Night_12h']]\n",
    "\n",
    "# PRINT RESULTS\n",
    "print(f\"--- Individual Fly Sleep (Baseline: {start_hour}h to {end_hour}h, Averaged per day) ---\")\n",
    "print(baseline_stats.head(20).to_string(index=False)) \n",
    "print(\"... (Showing first 20 rows)\\n\")\n",
    "\n",
    "print(f\"--- Grand Summary Statistics (Baseline: {start_hour}h to {end_hour}h) ---\")\n",
    "print(f\"Total Flies Analyzed: n = {len(baseline_stats)}\")\n",
    "\n",
    "# 1. OVERALL 24H STATS\n",
    "print(\"\\n[ OVERALL SLEEP (Scaled to 24h Baseline Average) ]\")\n",
    "print(f\"Mean ± SEM:   {baseline_stats['Base_Sleep_24h'].mean():.2f} ± {baseline_stats['Base_Sleep_24h'].sem():.2f} hours\")\n",
    "print(f\"Median:       {baseline_stats['Base_Sleep_24h'].median():.2f} hours\")\n",
    "\n",
    "# 2. DAY TIME STATS\n",
    "print(f\"\\n[ DAY TIME (ZT 0-12, Averaged to 12h blocks) ]\")\n",
    "print(f\"Mean ± SEM:   {baseline_stats['Base_Day_12h'].mean():.2f} ± {baseline_stats['Base_Day_12h'].sem():.2f} hours\")\n",
    "print(f\"Median:       {baseline_stats['Base_Day_12h'].median():.2f} hours\")\n",
    "\n",
    "# 3. NIGHT TIME STATS\n",
    "print(f\"\\n[ NIGHT TIME (ZT 12-24, Averaged to 12h blocks) ]\")\n",
    "print(f\"Mean ± SEM:   {baseline_stats['Base_Night_12h'].mean():.2f} ± {baseline_stats['Base_Night_12h'].sem():.2f} hours\")\n",
    "print(f\"Median:       {baseline_stats['Base_Night_12h'].median():.2f} hours\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "8c8013b6-ce63-4e0e-9963-67bd0e0c8f87",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Individual Fly Sleep (Stimulus: 72h to 96h) ---\n",
      "             Fly_Label  Stim_Sleep_24h  Stim_Day_12h  Stim_Night_12h\n",
      "ETHOSCOPE_130 - Fly 01        6.961111      3.391667        3.569444\n",
      "ETHOSCOPE_130 - Fly 02        3.258333      1.925000        1.333333\n",
      "ETHOSCOPE_130 - Fly 03        7.050000      3.061111        3.988889\n",
      "ETHOSCOPE_130 - Fly 04        7.122222      1.158333        5.963889\n",
      "ETHOSCOPE_130 - Fly 05       10.422222      4.269444        6.152778\n",
      "ETHOSCOPE_130 - Fly 06        7.719444      2.850000        4.869444\n",
      "ETHOSCOPE_130 - Fly 07        8.080556      2.966667        5.113889\n",
      "ETHOSCOPE_130 - Fly 08        3.063889      0.525000        2.538889\n",
      "ETHOSCOPE_130 - Fly 09        4.530556      2.419444        2.111111\n",
      "ETHOSCOPE_130 - Fly 10        6.758333      1.197222        5.561111\n",
      "ETHOSCOPE_130 - Fly 11        6.300000      2.147222        4.152778\n",
      "ETHOSCOPE_130 - Fly 12       11.144444      4.952778        6.191667\n",
      "ETHOSCOPE_130 - Fly 13       13.136111      5.805556        7.330556\n",
      "ETHOSCOPE_130 - Fly 14       13.988889      5.394444        8.594444\n",
      "ETHOSCOPE_130 - Fly 15       11.983333      5.033333        6.950000\n",
      "ETHOSCOPE_130 - Fly 16        9.280556      3.386111        5.894444\n",
      "ETHOSCOPE_130 - Fly 17       15.661111      7.102778        8.558333\n",
      "ETHOSCOPE_130 - Fly 18       10.841667      5.033333        5.808333\n",
      "ETHOSCOPE_130 - Fly 19        9.988889      4.502778        5.486111\n",
      "ETHOSCOPE_130 - Fly 20       10.294444      3.077778        7.216667\n",
      "... (Showing first 20 rows)\n",
      "\n",
      "--- Grand Summary Statistics (Stimulus: 72h to 96h) ---\n",
      "Total Flies Analyzed: n = 20\n",
      "\n",
      "[ OVERALL SLEEP (24h Stimulus Block) ]\n",
      "Mean ± SEM:   8.88 ± 0.76 hours\n",
      "Median:       8.68 hours\n",
      "\n",
      "[ DAY TIME (ZT 0-12 during Stimulus) ]\n",
      "Mean ± SEM:   3.51 ± 0.39 hours\n",
      "Median:       3.23 hours\n",
      "\n",
      "[ NIGHT TIME (ZT 12-24 during Stimulus) ]\n",
      "Mean ± SEM:   5.37 ± 0.44 hours\n",
      "Median:       5.68 hours\n"
     ]
    }
   ],
   "source": [
    "# Define stimulus time period\n",
    "start_hour = 72\n",
    "end_hour = 96\n",
    "\n",
    "# Filter the dataset to ONLY include data within specific stimulus window\n",
    "stim_df = df.t_filter(start_time=start_hour, end_time=end_hour).copy()\n",
    "\n",
    "# Calculate Overall 24h Stimulus Average\n",
    "sleep_hours = (stim_df.groupby('id')['asleep'].sum() * 10) / 3600\n",
    "days_tracked = (end_hour - start_hour) / 24 \n",
    "stim_overall = (sleep_hours / days_tracked).reset_index(name='Stim_Sleep_24h')\n",
    "\n",
    "# Calculate Day/Night 12h Stimulus Averages\n",
    "stim_df['zt_hour'] = (stim_df['t'] / 3600) % 24\n",
    "stim_df['Phase'] = np.where(stim_df['zt_hour'] < 12, 'Day', 'Night')\n",
    "\n",
    "stim_phase = stim_df.groupby(['id', 'Phase']).agg(\n",
    "    total_sleep_epochs=('asleep', 'sum'),\n",
    "    total_tracking_epochs=('t', 'count')\n",
    ").reset_index()\n",
    "\n",
    "# Tracking_Hours will now be ~12 for Day and ~12 for Night\n",
    "# Dividing sleep by tracking hours and multiplying by 12 averages it to a single 12h block.\n",
    "stim_phase['Sleep_Hours'] = (stim_phase['total_sleep_epochs'] * 10) / 3600\n",
    "stim_phase['Tracking_Hours'] = (stim_phase['total_tracking_epochs'] * 10) / 3600\n",
    "stim_phase['Stim_Sleep_12h'] = (stim_phase['Sleep_Hours'] / stim_phase['Tracking_Hours']) * 12\n",
    "\n",
    "stim_pivot = stim_phase.pivot(index='id', columns='Phase', values='Stim_Sleep_12h').reset_index()\n",
    "# Rename columns \n",
    "stim_pivot.columns = ['id', 'Stim_Day_12h', 'Stim_Night_12h']\n",
    "\n",
    "# Merge and clean up data\n",
    "merged_df = pd.merge(stim_overall, stim_pivot, on='id')\n",
    "\n",
    "merged_df['Machine'] = merged_df['id'].map(df.meta['machine_name'])\n",
    "merged_df['Tube'] = merged_df['id'].apply(lambda x: str(x).split('|')[-1])\n",
    "merged_df['Fly_Label'] = merged_df['Machine'] + \" - Fly \" + merged_df['Tube']\n",
    "\n",
    "clean_table = merged_df.dropna(subset=['Machine']).sort_values(by=['Machine', 'Tube'])\n",
    "stim_stats = clean_table[['Fly_Label', 'Stim_Sleep_24h', 'Stim_Day_12h', 'Stim_Night_12h']]\n",
    "\n",
    "# PRINT RESULTS\n",
    "print(f\"--- Individual Fly Sleep (Stimulus: {start_hour}h to {end_hour}h) ---\")\n",
    "print(stim_stats.head(20).to_string(index=False)) \n",
    "print(\"... (Showing first 20 rows)\\n\")\n",
    "\n",
    "print(f\"--- Grand Summary Statistics (Stimulus: {start_hour}h to {end_hour}h) ---\")\n",
    "print(f\"Total Flies Analyzed: n = {len(stim_stats)}\")\n",
    "\n",
    "# 1. OVERALL 24H STATS\n",
    "print(\"\\n[ OVERALL SLEEP (24h Stimulus Block) ]\")\n",
    "print(f\"Mean ± SEM:   {stim_stats['Stim_Sleep_24h'].mean():.2f} ± {stim_stats['Stim_Sleep_24h'].sem():.2f} hours\")\n",
    "print(f\"Median:       {stim_stats['Stim_Sleep_24h'].median():.2f} hours\")\n",
    "\n",
    "# 2. DAY TIME STATS\n",
    "print(f\"\\n[ DAY TIME (ZT 0-12 during Stimulus) ]\")\n",
    "print(f\"Mean ± SEM:   {stim_stats['Stim_Day_12h'].mean():.2f} ± {stim_stats['Stim_Day_12h'].sem():.2f} hours\")\n",
    "print(f\"Median:       {stim_stats['Stim_Day_12h'].median():.2f} hours\")\n",
    "\n",
    "# 3. NIGHT TIME STATS\n",
    "print(f\"\\n[ NIGHT TIME (ZT 12-24 during Stimulus) ]\")\n",
    "print(f\"Mean ± SEM:   {stim_stats['Stim_Night_12h'].mean():.2f} ± {stim_stats['Stim_Night_12h'].sem():.2f} hours\")\n",
    "print(f\"Median:       {stim_stats['Stim_Night_12h'].median():.2f} hours\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "4483ebc9-77bb-4624-86a6-01ccc201fb15",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "--- 24h Total Statistical Analysis ---\n",
      "Shapiro-Wilk P-value (Normality of differences): 0.5755\n",
      "Result: Data is normal. Used Paired T-test.\n",
      "P-value: 8.5647e-05\n",
      "Significance: ****\n",
      "\n",
      "--- Daytime Statistical Analysis ---\n",
      "Shapiro-Wilk P-value (Normality of differences): 0.8039\n",
      "Result: Data is normal. Used Paired T-test.\n",
      "P-value: 2.3748e-04\n",
      "Significance: ***\n",
      "\n",
      "--- Nighttime Statistical Analysis ---\n",
      "Shapiro-Wilk P-value (Normality of differences): 0.4164\n",
      "Result: Data is normal. Used Paired T-test.\n",
      "P-value: 1.1008e-05\n",
      "Significance: ****\n"
     ]
    }
   ],
   "source": [
    "# 1. Merge Baseline and Stimulus data on Fly_Label\n",
    "# This ensures comparing the SAME fly to itself\n",
    "paired_df = pd.merge(baseline_stats, stim_stats, on='Fly_Label')\n",
    "\n",
    "def run_paired_stats(df, base_col, stim_col, label):\n",
    "    # Calculate the differences for the paired test\n",
    "    diffs = df[stim_col] - df[base_col]\n",
    "    \n",
    "    # 2. Shapiro-Wilk Test for Normality\n",
    "    _, p_shapiro = shapiro(diffs)\n",
    "    \n",
    "    print(f\"\\n--- {label} Statistical Analysis ---\")\n",
    "    print(f\"Shapiro-Wilk P-value (Normality of differences): {p_shapiro:.4f}\")\n",
    "    \n",
    "    # 3. Determine Test: If P > 0.05, data is normal (use t-test). If P < 0.05, use Wilcoxon.\n",
    "    if p_shapiro > 0.05:\n",
    "        stat, p_val = ttest_rel(df[base_col], df[stim_col])\n",
    "        print(f\"Result: Data is normal. Used Paired T-test.\")\n",
    "    else:\n",
    "        stat, p_val = wilcoxon(df[base_col], df[stim_col])\n",
    "        print(f\"Result: Data is not normal. Used Wilcoxon Signed-Rank test.\")\n",
    "        \n",
    "    print(f\"P-value: {p_val:.4e}\")\n",
    "    if p_val < 0.0001: print(\"Significance: ****\")\n",
    "    elif p_val < 0.001: print(\"Significance: ***\")\n",
    "    elif p_val < 0.01: print(\"Significance: **\")\n",
    "    elif p_val < 0.05: print(\"Significance: *\")\n",
    "    else: print(\"Significance: ns\")\n",
    "\n",
    "# Run for all three metrics\n",
    "run_paired_stats(paired_df, 'Base_Sleep_24h', 'Stim_Sleep_24h', '24h Total')\n",
    "run_paired_stats(paired_df, 'Base_Day_12h', 'Stim_Day_12h', 'Daytime')\n",
    "run_paired_stats(paired_df, 'Base_Night_12h', 'Stim_Night_12h', 'Nighttime')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "45dd6526-92ed-4b4b-a924-1a33eda0d28b",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_42207/12866365.py:27: FutureWarning: \n",
      "\n",
      "Setting a gradient palette using color= is deprecated and will be removed in v0.14.0. Set `palette='dark:black'` for the same effect.\n",
      "\n",
      "  sns.stripplot(\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 50780 characters]",
      "text/plain": [
       "<Figure size 700x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 1. PREPARE DATA\n",
    "combined = pd.merge(baseline_stats, stim_stats, on='Fly_Label')\n",
    "plot_df = combined.melt(id_vars=['Fly_Label'], var_name='Variable', value_name='Hours')\n",
    "plot_df['Condition'] = plot_df['Variable'].apply(lambda x: '24h' if '24h' in x else ('Day' if 'Day' in x else 'Night'))\n",
    "plot_df['State'] = plot_df['Variable'].apply(lambda x: 'Baseline' if 'Base' in x else 'Stimulus')\n",
    "\n",
    "# 2. GENERATE PLOT\n",
    "plt.figure(figsize=(7, 6))\n",
    "sns.set_theme(style=\"ticks\")\n",
    "\n",
    "order = ['24h', 'Day', 'Night']\n",
    "hue_order = ['Baseline', 'Stimulus']\n",
    "palette = {'Baseline': '#cccccc', 'Stimulus': '#51ff4c'}\n",
    "\n",
    "# Boxplot\n",
    "sns.boxplot(\n",
    "    data=plot_df, x='Condition', y='Hours', hue='State', \n",
    "    order=order, hue_order=hue_order, palette=palette,\n",
    "    width=0.6, \n",
    "    gap=0.2, \n",
    "    boxprops={'edgecolor': 'black', 'alpha': 0.7},\n",
    "    medianprops={'color': 'black', 'linewidth': 1.5}, showfliers=False\n",
    ")\n",
    "\n",
    "# Stripplot \n",
    "sns.stripplot(\n",
    "    data=plot_df, x='Condition', y='Hours', hue='State', \n",
    "    order=order, hue_order=hue_order, dodge=True,\n",
    "    color='black', alpha=0.5, size=4, jitter=0.05,\n",
    "    legend=False\n",
    ")\n",
    "\n",
    "# 3. ADD MEDIAN LABELS\n",
    "ax = plt.gca()\n",
    "medians = plot_df.groupby(['Condition', 'State'], sort=False)['Hours'].median()\n",
    "offsets = {'Baseline': -0.4, 'Stimulus': 0.4}\n",
    "\n",
    "for i, cond in enumerate(order):\n",
    "    for state in hue_order:\n",
    "        val = medians[(cond, state)]\n",
    "        ax.text(i + offsets[state], val, f\"{val:.1f}h\", \n",
    "                ha='center', va='bottom', fontsize=10)\n",
    "\n",
    "# 4. FORMATTING\n",
    "sns.despine()\n",
    "plt.ylabel('Average time spent asleep (hours)', fontsize=12)\n",
    "plt.xlabel('')\n",
    "plt.ylim(0, 18) \n",
    "plt.legend(title='', frameon=False)\n",
    "plt.tight_layout()\n",
    "\n",
    "plt.savefig(\"CantonS_Green.png\", dpi=600, bbox_inches='tight')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "579fdddd-eb38-428c-8f44-fbccd3020ca6",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_42207/1824297848.py:45: FutureWarning: \n",
      "\n",
      "Setting a gradient palette using color= is deprecated and will be removed in v0.14.0. Set `palette='dark:black'` for the same effect.\n",
      "\n",
      "  sns.stripplot(\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 52708 characters]",
      "text/plain": [
       "<Figure size 700x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 1. PREPARE DATA & CALCULATE STATS\n",
    "combined = pd.merge(baseline_stats, stim_stats, on='Fly_Label')\n",
    "\n",
    "# Calculate the paired statistics for the brackets\n",
    "p_values = {}\n",
    "metrics = {\n",
    "    '24h': ('Base_Sleep_24h', 'Stim_Sleep_24h'),\n",
    "    'Day': ('Base_Day_12h', 'Stim_Day_12h'),\n",
    "    'Night': ('Base_Night_12h', 'Stim_Night_12h')\n",
    "}\n",
    "\n",
    "for phase, (base_col, stim_col) in metrics.items():\n",
    "    diffs = combined[stim_col] - combined[base_col]\n",
    "    _, p_shapiro = shapiro(diffs)\n",
    "    \n",
    "    # Use Paired T-Test if normal, Wilcoxon if not\n",
    "    if p_shapiro > 0.05:\n",
    "        _, p_val = ttest_rel(combined[base_col], combined[stim_col])\n",
    "    else:\n",
    "        _, p_val = wilcoxon(combined[base_col], combined[stim_col])\n",
    "    p_values[phase] = p_val\n",
    "\n",
    "# Melt the data for plotting\n",
    "plot_df = combined.melt(id_vars=['Fly_Label'], var_name='Variable', value_name='Hours')\n",
    "plot_df['Condition'] = plot_df['Variable'].apply(lambda x: '24h' if '24h' in x else ('Day' if 'Day' in x else 'Night'))\n",
    "plot_df['State'] = plot_df['Variable'].apply(lambda x: 'Baseline' if 'Base' in x else 'Stimulus')\n",
    "\n",
    "# 2. GENERATE PLOT\n",
    "plt.figure(figsize=(7, 6))\n",
    "sns.set_theme(style=\"ticks\")\n",
    "\n",
    "order = ['24h', 'Day', 'Night']\n",
    "hue_order = ['Baseline', 'Stimulus']\n",
    "palette = {'Baseline': '#cccccc', 'Stimulus': '#51ff4c'}\n",
    "\n",
    "# Boxplot\n",
    "sns.boxplot(\n",
    "    data=plot_df, x='Condition', y='Hours', hue='State', \n",
    "    order=order, hue_order=hue_order, palette=palette,\n",
    "    width=0.6, gap=0.2, boxprops={'edgecolor': 'black', 'alpha': 0.7},\n",
    "    medianprops={'color': 'black', 'linewidth': 1.5}, showfliers=False\n",
    ")\n",
    "\n",
    "# Stripplot\n",
    "sns.stripplot(\n",
    "    data=plot_df, x='Condition', y='Hours', hue='State', \n",
    "    order=order, hue_order=hue_order, dodge=True,\n",
    "    color='black', alpha=0.5, size=4, jitter=0.05,\n",
    "    legend=False\n",
    ")\n",
    "\n",
    "# 3. ADD MEDIAN LABELS\n",
    "ax = plt.gca()\n",
    "medians = plot_df.groupby(['Condition', 'State'], sort=False)['Hours'].median()\n",
    "\n",
    "offsets = {'Baseline': -0.4, 'Stimulus': 0.4}\n",
    "\n",
    "for i, cond in enumerate(order):\n",
    "    for state in hue_order:\n",
    "        val = medians[(cond, state)]\n",
    "        ax.text(i + offsets[state], val, f\"{val:.1f}h\", \n",
    "                ha='center', va='bottom', fontsize=10)\n",
    "\n",
    "# 4. ADD SIGNIFICANCE BRACKETS\n",
    "y_max = plot_df['Hours'].max()\n",
    "y_line = y_max + 1.0  # Float the bracket 1 hour above the highest data point\n",
    "h = 0.4               # Height of the bracket's downward ticks\n",
    "\n",
    "for i, cond in enumerate(order):\n",
    "    p = p_values[cond]\n",
    "    \n",
    "    # Determine the correct asterisk\n",
    "    if p < 0.0001: star = '****'\n",
    "    elif p < 0.001: star = '***'\n",
    "    elif p < 0.01: star = '**'\n",
    "    elif p < 0.05: star = '*'\n",
    "    else: star = 'ns'\n",
    "    \n",
    "    # Bracket coordinates (Centers of the Baseline and Stimulus boxes)\n",
    "    x1, x2 = i - 0.2, i + 0.2\n",
    "    \n",
    "    # Draw the bracket line\n",
    "    plt.plot([x1, x1, x2, x2], [y_line, y_line+h, y_line+h, y_line], lw=1.5, c='k')\n",
    "    \n",
    "    # Place the text above the bracket\n",
    "    plt.text((x1+x2)*.5, y_line+h, star, ha='center', va='bottom', fontsize=12)\n",
    "\n",
    "# 5. FORMATTING\n",
    "sns.despine()\n",
    "plt.ylabel('Average time spent asleep (hours)', fontsize=12)\n",
    "plt.xlabel('')\n",
    "\n",
    "plt.xlim(-0.6, 2.5) \n",
    "\n",
    "plt.legend(title='', frameon=False)\n",
    "plt.tight_layout()\n",
    "plt.ylim(0, max(18, y_line + h + 1.5))\n",
    "\n",
    "plt.legend(title='', frameon=False, loc='center left', bbox_to_anchor=(1, 0.5))\n",
    "plt.tight_layout()\n",
    "\n",
    "plt.savefig(\"CantonS_Green.png\", dpi=600, bbox_inches='tight')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "3cc80754-211a-4020-904a-85f00a2ccfc7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Delta Sleep (Stimulus - Baseline) per Fly ---\n",
      "             Fly_Label  Delta_24h  Delta_Day  Delta_Night\n",
      "ETHOSCOPE_130 - Fly 01  -4.698148  -1.022981    -4.294444\n",
      "ETHOSCOPE_130 - Fly 02  -8.853704  -1.936450    -7.458333\n",
      "ETHOSCOPE_130 - Fly 03  -5.669444  -2.432787    -4.006481\n",
      "ETHOSCOPE_130 - Fly 04  -6.782407  -4.508932    -3.067593\n",
      "ETHOSCOPE_130 - Fly 05  -3.684259  -1.586263    -2.918519\n",
      "ETHOSCOPE_130 - Fly 06  -4.603704  -2.163640    -3.142593\n",
      "ETHOSCOPE_130 - Fly 07  -5.757407  -2.861012    -3.713889\n",
      "ETHOSCOPE_130 - Fly 08  -9.345370  -4.335732    -5.690741\n",
      "ETHOSCOPE_130 - Fly 09  -9.221296  -3.651625    -6.420370\n",
      "ETHOSCOPE_130 - Fly 10  -6.031481  -3.995023    -2.764815\n",
      "ETHOSCOPE_130 - Fly 11  -2.400926  -2.332318    -0.696296\n",
      "ETHOSCOPE_130 - Fly 12  -0.500926   0.064048    -1.250000\n",
      "ETHOSCOPE_130 - Fly 13  -1.065741  -1.056971    -0.970370\n",
      "ETHOSCOPE_130 - Fly 14   1.658333  -0.019769     0.919444\n",
      "ETHOSCOPE_130 - Fly 15   0.122222   0.348358    -0.883333\n",
      "ETHOSCOPE_130 - Fly 16  -3.432407  -1.457392    -2.653704\n",
      "ETHOSCOPE_130 - Fly 17   1.625926   1.842548    -0.953704\n",
      "ETHOSCOPE_130 - Fly 18  -1.691667   0.025883    -2.420370\n",
      "ETHOSCOPE_130 - Fly 19  -2.383333  -1.277552    -1.915741\n",
      "ETHOSCOPE_130 - Fly 20  -1.791667  -1.456680    -0.970370\n",
      "\n",
      "==================================================\n",
      "\n",
      "--- Average Change (Delta) across all flies ---\n",
      "Delta_24h: -3.73 ± 0.75 hours\n",
      "Delta_Day: -1.69 ± 0.37 hours\n",
      "Delta_Night: -2.76 ± 0.47 hours\n"
     ]
    }
   ],
   "source": [
    "# 1. Ensure have the merged paired data\n",
    "combined = pd.merge(baseline_stats, stim_stats, on='Fly_Label')\n",
    "\n",
    "# 2. Calculate the Delta (Stimulus - Baseline) for each fly\n",
    "combined['Delta_24h'] = combined['Stim_Sleep_24h'] - combined['Base_Sleep_24h']\n",
    "combined['Delta_Day'] = combined['Stim_Day_12h'] - combined['Base_Day_12h']\n",
    "combined['Delta_Night'] = combined['Stim_Night_12h'] - combined['Base_Night_12h']\n",
    "\n",
    "# 3. Print the Delta for each individual fly\n",
    "print(\"--- Delta Sleep (Stimulus - Baseline) per Fly ---\")\n",
    "delta_table = combined[['Fly_Label', 'Delta_24h', 'Delta_Day', 'Delta_Night']]\n",
    "print(delta_table.to_string(index=False))\n",
    "print(\"\\n\" + \"=\"*50 + \"\\n\")\n",
    "\n",
    "# 4. Calculate and print the group averages\n",
    "print(\"--- Average Change (Delta) across all flies ---\")\n",
    "avg_delta = delta_table[['Delta_24h', 'Delta_Day', 'Delta_Night']].mean()\n",
    "sem_delta = delta_table[['Delta_24h', 'Delta_Day', 'Delta_Night']].sem()\n",
    "\n",
    "for metric in ['Delta_24h', 'Delta_Day', 'Delta_Night']:\n",
    "    print(f\"{metric}: {avg_delta[metric]:.2f} ± {sem_delta[metric]:.2f} hours\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "4515719c-4438-462c-a989-f2cff18003d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "#export to csv\n",
    "delta_table['Condition'] = 'Green'\n",
    "delta_table.to_csv('delta_green.csv', index=False)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
