Optogenetics-Sleep-Deprivation/2.CantonS_Red_Stimulus.ipynb

1015 lines
398 KiB
Text
Raw Permalink Normal View History

2026-05-26 14:00:21 +00:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 53,
"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": 4,
"id": "5289d86c-0107-4089-83e3-327b70168e08",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'2.1.0'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"etho.__version__"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3d32b423-cc70-43f2-a2cc-ed9bd08c2981",
"metadata": {},
"outputs": [],
"source": [
"meta = '/home/rdingjin/Optic_2026-04-01/metadata_CantonS_2026-04-01.csv'\n",
"local = '/mnt/ethoscope_results'"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "df11ef6f-5475-45b0-95c3-2a8672a21219",
"metadata": {},
"outputs": [],
"source": [
"metadata = etho.link_meta_index(meta, local)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "ebfbf3dc-d405-4f7b-a4a1-1eacff24f3a5",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading ROI_1 from ETHOSCOPE_278\n",
"Loading ROI_2 from ETHOSCOPE_278\n",
"Loading ROI_3 from ETHOSCOPE_278\n",
"Loading ROI_4 from ETHOSCOPE_278\n",
"Loading ROI_5 from ETHOSCOPE_278\n",
"Loading ROI_6 from ETHOSCOPE_278\n",
"Loading ROI_7 from ETHOSCOPE_278\n",
"Loading ROI_8 from ETHOSCOPE_278\n",
"Loading ROI_9 from ETHOSCOPE_278\n",
"Loading ROI_10 from ETHOSCOPE_278\n",
"Loading ROI_11 from ETHOSCOPE_278\n",
"Loading ROI_12 from ETHOSCOPE_278\n",
"Loading ROI_13 from ETHOSCOPE_278\n",
"Loading ROI_14 from ETHOSCOPE_278\n",
"Loading ROI_15 from ETHOSCOPE_278\n",
"Loading ROI_16 from ETHOSCOPE_278\n",
"Loading ROI_17 from ETHOSCOPE_278\n",
"Loading ROI_18 from ETHOSCOPE_278\n",
"Loading ROI_19 from ETHOSCOPE_278\n",
"Loading ROI_20 from ETHOSCOPE_278\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": 8,
"id": "a32d69f8-e66c-47fc-9b9a-2273f2c5082b",
"metadata": {},
"outputs": [],
"source": [
"df = etho.behavpy(data, metadata, check = True)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "e633d7d9-99db-4815-900d-e79d11dd65b1",
"metadata": {},
"outputs": [],
"source": [
"df.to_pickle('/home/rdingjin/Optic_2026-04-01/phase2.pkl')"
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "ae2ff7e0-2f6c-4cc0-9afd-a1c021140760",
"metadata": {},
"outputs": [],
"source": [
"import ethoscopy as etho\n",
"import pandas as pd\n",
"from scipy.stats import wilcoxon, shapiro, ttest_rel\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import seaborn as sns\n",
"df = pd.read_pickle('/home/rdingjin/Optic_2026-04-01/phase2.pkl')"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "94a0854d-4b5a-475f-a856-c61ec01d080e",
"metadata": {},
"outputs": [],
"source": [
"df = df.baseline(column = 'baseline')"
]
},
{
"cell_type": "code",
"execution_count": 12,
"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-04-01_11-20-57_278441|01 2026-04-01 ETHOSCOPE_278 1 \n",
"2026-04-01_11-20-57_278441|02 2026-04-01 ETHOSCOPE_278 2 \n",
"2026-04-01_11-20-57_278441|03 2026-04-01 ETHOSCOPE_278 3 \n",
"2026-04-01_11-20-57_278441|04 2026-04-01 ETHOSCOPE_278 4 \n",
"2026-04-01_11-20-57_278441|05 2026-04-01 ETHOSCOPE_278 5 \n",
"2026-04-01_11-20-57_278441|06 2026-04-01 ETHOSCOPE_278 6 \n",
"2026-04-01_11-20-57_278441|07 2026-04-01 ETHOSCOPE_278 7 \n",
"2026-04-01_11-20-57_278441|08 2026-04-01 ETHOSCOPE_278 8 \n",
"2026-04-01_11-20-57_278441|09 2026-04-01 ETHOSCOPE_278 9 \n",
"2026-04-01_11-20-57_278441|10 2026-04-01 ETHOSCOPE_278 10 \n",
"2026-04-01_11-20-57_278441|11 2026-04-01 ETHOSCOPE_278 11 \n",
"2026-04-01_11-20-57_278441|12 2026-04-01 ETHOSCOPE_278 12 \n",
"2026-04-01_11-20-57_278441|13 2026-04-01 ETHOSCOPE_278 13 \n",
"2026-04-01_11-20-57_278441|14 2026-04-01 ETHOSCOPE_278 14 \n",
"2026-04-01_11-20-57_278441|15 2026-04-01 ETHOSCOPE_278 15 \n",
"2026-04-01_11-20-57_278441|16 2026-04-01 ETHOSCOPE_278 16 \n",
"2026-04-01_11-20-57_278441|17 2026-04-01 ETHOSCOPE_278 17 \n",
"2026-04-01_11-20-57_278441|18 2026-04-01 ETHOSCOPE_278 18 \n",
"2026-04-01_11-20-57_278441|19 2026-04-01 ETHOSCOPE_278 19 \n",
"2026-04-01_11-20-57_278441|20 2026-04-01 ETHOSCOPE_278 20 \n",
"\n",
" sleep_deprived species food baseline \\\n",
"id \n",
"2026-04-01_11-20-57_278441|01 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|02 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|03 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|04 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|05 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|06 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|07 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|08 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|09 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|10 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|11 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|12 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|13 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|14 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|15 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|16 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|17 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|18 True CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|19 False CantonS normal_food 0 \n",
"2026-04-01_11-20-57_278441|20 True CantonS normal_food 0 \n",
"\n",
" sex time \n",
"id \n",
"2026-04-01_11-20-57_278441|01 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|02 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|03 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|04 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|05 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|06 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|07 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|08 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|09 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|10 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|11 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|12 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|13 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|14 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|15 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|16 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|17 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|18 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|19 male 11-20-57 \n",
"2026-04-01_11-20-57_278441|20 male 11-20-57 \n",
" ====== DATA ======\n",
"\n",
" t x y w \\\n",
"id \n",
"2026-04-01_11-20-57_278441|01 8460 248.739130 41.782609 20.130435 \n",
"2026-04-01_11-20-57_278441|01 8470 116.657143 44.885714 19.542857 \n",
"2026-04-01_11-20-57_278441|01 8480 27.581395 45.488372 11.744186 \n",
"2026-04-01_11-20-57_278441|01 8490 21.000000 45.000000 11.000000 \n",
"2026-04-01_11-20-57_278441|01 8500 21.000000 45.000000 11.000000 \n",
"... ... ... ... ... \n",
"2026-04-01_11-20-57_278441|20 701770 161.700000 22.000000 20.800000 \n",
"2026-04-01_11-20-57_278441|20 701780 160.571429 21.714286 21.428571 \n",
"2026-04-01_11-20-57_278441|20 701790 162.904762 22.761905 21.476190 \n",
"2026-04-01_11-20-57_278441|20 701800 161.227273 21.863636 21.818182 \n",
"2026-04-01_11-20-57_278441|20 701810 160.952381 22.095238 21.714286 \n",
"\n",
" h phi max_velocity \\\n",
"id \n",
"2026-04-01_11-20-57_278441|01 9.217391 90.782609 56.218434 \n",
"2026-04-01_11-20-57_278441|01 7.171429 35.171429 17.818812 \n",
"2026-04-01_11-20-57_278441|01 6.604651 15.534884 16.439127 \n",
"2026-04-01_11-20-57_278441|01 7.000000 18.000000 3.033044 \n",
"2026-04-01_11-20-57_278441|01 7.000000 18.000000 3.033044 \n",
"... ... ... ... \n",
"2026-04-01_11-20-57_278441|20 9.050000 163.750000 1.386369 \n",
"2026-04-01_11-20-57_278441|20 8.714286 169.142857 2.300799 \n",
"2026-04-01_11-20-57_278441|20 8.380952 156.000000 1.255679 \n",
"2026-04-01_11-20-57_278441|20 8.681818 164.954545 1.249910 \n",
"2026-04-01_11-20-57_278441|20 8.476190 165.047619 1.224274 \n",
"\n",
" mean_velocity dist has_interacted \\\n",
"id \n",
"2026-04-01_11-20-57_278441|01 10.761196 0.742523 0.0 \n",
"2026-04-01_11-20-57_278441|01 4.753718 0.499140 0.0 \n",
"2026-04-01_11-20-57_278441|01 3.349548 0.432092 0.0 \n",
"2026-04-01_11-20-57_278441|01 3.033044 0.345767 0.0 \n",
"2026-04-01_11-20-57_278441|01 3.033044 0.354866 0.0 \n",
"... ... ... ... \n",
"2026-04-01_11-20-57_278441|20 0.836259 0.050176 0.0 \n",
"2026-04-01_11-20-57_278441|20 0.926716 0.058383 0.0 \n",
"2026-04-01_11-20-57_278441|20 0.869378 0.054771 0.0 \n",
"2026-04-01_11-20-57_278441|20 0.845312 0.055791 0.0 \n",
"2026-04-01_11-20-57_278441|20 0.885445 0.055783 0.0 \n",
"\n",
" beam_cross moving micro walk \\\n",
"id \n",
"2026-04-01_11-20-57_278441|01 0.0 True False True \n",
"2026-04-01_11-20-57_278441|01 0.0 True False True \n",
"2026-04-01_11-20-57_278441|01 0.0 True False True \n",
"2026-04-01_11-20-57_278441|01 0.0 True False True \n",
"2026-04-01_11-20-57_278441|01 0.0 True False True \n",
"... ... ... ... ... \n",
"2026-04-01_11-20-57_278441|20 0.0 True True False \n",
"2026-04-01_11-20-57_278441|20 0.0 True True False \n",
"2026-04-01_11-20-57_278441|20 0.0 True True False \n",
"2026-04-01_11-20-57_278441|20 0.0 True True False \n",
"2026-04-01_11-20-57_278441|20 0.0 True True False \n",
"\n",
" is_interpolated asleep \n",
"id \n",
"2026-04-01_11-20-57_278441|01 False False \n",
"2026-04-01_11-20-57_278441|01 False False \n",
"2026-04-01_11-20-57_278441|01 False False \n",
"2026-04-01_11-20-57_278441|01 False False \n",
"2026-04-01_11-20-57_278441|01 False False \n",
"... ... ... \n",
"2026-04-01_11-20-57_278441|20 False False \n",
"2026-04-01_11-20-57_278441|20 False False \n",
"2026-04-01_11-20-57_278441|20 False False \n",
"2026-04-01_11-20-57_278441|20 False False \n",
"2026-04-01_11-20-57_278441|20 False False \n",
"\n",
"[1386538 rows x 16 columns]\n"
]
}
],
"source": [
"#display metadata\n",
"df.display()"
]
},
{
"cell_type": "code",
"execution_count": 41,
"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": "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
"text/plain": [
"<Figure size 800x200 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#heatmap of CantonS sleep\n",
"start_hour = 0\n",
"end_hour = 96\n",
"fig = df.t_filter(start_time=start_hour, end_time=end_hour).heatmap(variable = 'asleep')\n",
"fig.show()"
]
},
{
"cell_type": "code",
"execution_count": 112,
"id": "e97cc949-01e2-4ad2-8a06-fd5b6c36b089",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1133.33x466.667 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"start_hour = 0\n",
"end_hour = 96\n",
"\n",
"# Generate plot from Ethoscopy\n",
"fig = df.t_filter(start_time=start_hour, end_time=end_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",
"# Draw a vertical span from ZT 48 to ZT 72\n",
"ax.axvspan(48, 72, color='#ff4c4c', 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_2A.png\", dpi=600, bbox_inches='tight')"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "81bb4b3e-0d14-4e1b-86af-b304eb557f24",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Individual Fly Sleep (Baseline: 0h to 48h, Averaged per day) ---\n",
" Fly_Label Base_Sleep_24h Base_Day_12h Base_Night_12h\n",
"ETHOSCOPE_278 - Fly 01 11.508333 6.030793 6.068056\n",
"ETHOSCOPE_278 - Fly 02 10.863889 4.857583 6.481944\n",
"ETHOSCOPE_278 - Fly 03 10.951389 5.397998 6.081944\n",
"ETHOSCOPE_278 - Fly 04 12.305556 5.017706 7.779167\n",
"ETHOSCOPE_278 - Fly 05 12.623611 4.623557 8.452778\n",
"ETHOSCOPE_278 - Fly 06 9.318056 3.846035 5.848611\n",
"ETHOSCOPE_278 - Fly 07 10.198611 3.513472 7.029167\n",
"ETHOSCOPE_278 - Fly 08 10.611111 3.398871 7.545833\n",
"ETHOSCOPE_278 - Fly 09 9.495833 3.040801 6.752778\n",
"ETHOSCOPE_278 - Fly 10 7.136111 1.992302 5.338889\n",
"ETHOSCOPE_278 - Fly 11 7.872222 2.909931 5.247222\n",
"ETHOSCOPE_278 - Fly 12 11.048611 4.259011 7.219444\n",
"ETHOSCOPE_278 - Fly 13 9.591667 3.630485 6.316667\n",
"ETHOSCOPE_278 - Fly 14 8.198611 4.460354 4.175000\n",
"ETHOSCOPE_278 - Fly 15 10.927778 3.765974 7.530556\n",
"ETHOSCOPE_278 - Fly 16 10.326389 4.676505 6.108333\n",
"ETHOSCOPE_278 - Fly 17 8.308333 3.885214 4.813889\n",
"ETHOSCOPE_278 - Fly 18 7.506944 2.677444 5.091667\n",
"ETHOSCOPE_278 - Fly 19 12.595833 3.788501 9.179167\n",
"ETHOSCOPE_278 - Fly 20 8.979167 3.086990 6.194444\n",
"... (Showing first 20 rows)\n",
"\n",
"--- Grand Summary Statistics (Baseline: 0h to 48h) ---\n",
"Total Flies Analyzed: n = 20\n",
"\n",
"[ OVERALL SLEEP (Scaled to 24h Baseline Average) ]\n",
"Mean ± SEM: 10.02 ± 0.37 hours\n",
"Median: 10.26 hours\n",
"\n",
"[ DAY TIME (ZT 0-12, Averaged to 12h blocks) ]\n",
"Mean ± SEM: 3.94 ± 0.22 hours\n",
"Median: 3.82 hours\n",
"\n",
"[ NIGHT TIME (ZT 12-24, Averaged to 12h blocks) ]\n",
"Mean ± SEM: 6.46 ± 0.28 hours\n",
"Median: 6.26 hours\n"
]
}
],
"source": [
"# BASELINE\n",
"\n",
"# Define baseline time period\n",
"start_hour = 0\n",
"end_hour = 48\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": 68,
"id": "6aa39f19-25f6-48cc-aceb-dc7accbc6a58",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Individual Fly Sleep (Stimulus: 48h to 72h) ---\n",
" Fly_Label Stim_Sleep_24h Stim_Day_12h Stim_Night_12h\n",
"ETHOSCOPE_278 - Fly 01 11.947222 4.252778 7.694444\n",
"ETHOSCOPE_278 - Fly 02 11.638889 6.025000 5.613889\n",
"ETHOSCOPE_278 - Fly 03 12.650000 5.280556 7.369444\n",
"ETHOSCOPE_278 - Fly 04 10.319444 5.800000 4.519444\n",
"ETHOSCOPE_278 - Fly 05 15.816667 7.772222 8.044444\n",
"ETHOSCOPE_278 - Fly 06 11.011111 2.513889 8.497222\n",
"ETHOSCOPE_278 - Fly 07 12.352778 4.850000 7.502778\n",
"ETHOSCOPE_278 - Fly 08 10.591667 4.247222 6.344444\n",
"ETHOSCOPE_278 - Fly 09 9.761111 6.705556 3.055556\n",
"ETHOSCOPE_278 - Fly 10 5.716667 2.472222 3.244444\n",
"ETHOSCOPE_278 - Fly 11 10.008333 4.850000 5.158333\n",
"ETHOSCOPE_278 - Fly 12 10.355556 4.730556 5.625000\n",
"ETHOSCOPE_278 - Fly 13 11.650000 5.130556 6.519444\n",
"ETHOSCOPE_278 - Fly 14 13.888889 6.200000 7.688889\n",
"ETHOSCOPE_278 - Fly 15 13.050000 5.519444 7.530556\n",
"ETHOSCOPE_278 - Fly 16 12.097222 4.641667 7.455556\n",
"ETHOSCOPE_278 - Fly 17 11.394444 5.036111 6.358333\n",
"ETHOSCOPE_278 - Fly 18 10.991667 4.991667 6.000000\n",
"ETHOSCOPE_278 - Fly 19 15.338889 6.291667 9.047222\n",
"ETHOSCOPE_278 - Fly 20 11.936111 4.061111 7.875000\n",
"... (Showing first 20 rows)\n",
"\n",
"--- Grand Summary Statistics (Stimulus: 48h to 72h) ---\n",
"Total Flies Analyzed: n = 20\n",
"\n",
"[ OVERALL SLEEP (24h Stimulus Block) ]\n",
"Mean ± SEM: 11.63 ± 0.48 hours\n",
"Median: 11.64 hours\n",
"\n",
"[ DAY TIME (ZT 0-12 during Stimulus) ]\n",
"Mean ± SEM: 5.07 ± 0.28 hours\n",
"Median: 5.01 hours\n",
"\n",
"[ NIGHT TIME (ZT 12-24 during Stimulus) ]\n",
"Mean ± SEM: 6.56 ± 0.37 hours\n",
"Median: 6.94 hours\n"
]
}
],
"source": [
"# Define stimulus time period\n",
"start_hour = 48\n",
"end_hour = 72\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": 101,
"id": "6449454d-1195-451f-b5d2-77887dae0cdc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- 24h Total Statistical Analysis ---\n",
"Shapiro-Wilk P-value (Normality of differences): 0.7122\n",
"Result: Data is normal. Used Paired T-test.\n",
"P-value: 8.6132e-04\n",
"Significance: ***\n",
"\n",
"--- Daytime Statistical Analysis ---\n",
"Shapiro-Wilk P-value (Normality of differences): 0.8870\n",
"Result: Data is normal. Used Paired T-test.\n",
"P-value: 1.2991e-03\n",
"Significance: **\n",
"\n",
"--- Nighttime Statistical Analysis ---\n",
"Shapiro-Wilk P-value (Normality of differences): 0.8906\n",
"Result: Data is normal. Used Paired T-test.\n",
"P-value: 8.2210e-01\n",
"Significance: ns\n"
]
}
],
"source": [
"from scipy.stats import shapiro, wilcoxon, ttest_rel\n",
"\n",
"# 1. Merge Baseline and Stimulus data on Fly_Label\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": 115,
"id": "f4bf7cde-117c-4ce5-a591-e595f0ac297b",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_38794/1708898274.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": "iVBORw0KGgoAAAANSUhEUgAAAqwAAAJICAYAAACkF7akAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAl4dJREFUeJzs3XlcVPX+P/DXzMAAw77JvggoiIiK+5KImrumllumWVqZ2mJpmbdvVjeXLCsLy0zT1DTNysw9tbjmngtuqCzKJsuwDsuwzPL7Q5mfI6AwzDADvJ6Px31cz+ecOec13K69+ZzPIlCr1WoQEREREZkoobEDEBERERE9DAtWIiIiIjJpLFiJiIiIyKSxYCUiIiIik8aClYiIiIhMGgtWIiIiIjJpLFiJiIiIyKSxYCUiIiIik8aClYiIiIhMmpmxA9wvOTkZ69evR2xsLOLj4xEQEIA9e/ZoXSOXy/H1119j3759yMnJgbu7O8aOHYuZM2fCzMykvg4RERER6YFJVXjx8fGIiYlBx44doVKpUNOusR9++CEOHTqEN954A4GBgbh48SK+/PJLyOVyzJs3zwipiYiIiMiQBOqaqkIjUalUEArvjlJYuHAhrly5otXDqlKpEBERgRkzZuCVV17RtL/99ts4d+4cDh8+3OiZiYiIiMiwTGoMa1WxWhu1Wg2FQgFbW1utdltb2xp7Y4mIiIio6TOpgvVRRCIRxo0bhy1btuDSpUsoKSnBiRMn8Pvvv+OZZ54xdjwiIiIiMgCTGsNaF4sXL8bixYsxfvx4TdtLL72E55577qGfGzhwYK3nsrOz0bFjR2zZskVvOYmIiIhIP5pcwfrpp5/i77//xkcffQR/f39cvHgRq1evhp2dHWbOnKnTPZVKJTIyMvSclIiIiIj0oUkVrDdv3sT333+Pb775BgMGDAAAdOvWDQqFAqtWrcKkSZNgY2NT42ePHDlS630f1vtKRERERMbVpMawJiQkAADatWun1R4aGoqKigpkZWUZIxYRERERGVCTKli9vLwAAFevXtVqv3LlCgQCATw9PY0Ri4iIiIgMyKSGBMjlcsTExAAA0tPTUVxcjAMHDgAAunfvjrCwMISFhWHx4sXIzc2Fr68vLl26hLVr1+LJJ5+ElZWVMeMTERERkQGY1MYBaWlptY4n3bRpE3r06AGpVIpVq1bhxIkTyM3Nhbu7O0aOHIkXXngBlpaWOj236pkPG+dKRERERMZhUgWrsbBgJSIiIjJdTWoMKxERERG1PCxYiYiIiMiksWAlIiIiIpPGgpWIiIiITBoLViIiIiIyaSxYiYiIiMiksWAlIiIiIpNmUjtdEREREUmlUshkMqM8287ODq6urvX6zFdffYXo6GjNsVgshre3N8aNG4cZM2ZAKGzc/sHTp09j2rRp2LlzJzp06AAACA4OxltvvYUZM2Y0ahZ9YcFKREREJkMqleLFF1+EXC43yvOtrKywdu3aehetlpaW+OGHHwAAZWVlOH36NFauXAm1Wo0XX3zREFHrZfv27fD09DR2DJ2xYCUiIiKTIZPJIJfLMXXqVLi7uzfqszMzM7F582bIZLJ6F6xCoRCdOnXSHPfs2RM3b97EoUOHTKJgvT9bU8SClYiIiEyOu7s7/Pz8jB2jQaytraFQKDTHn376KWJiYpCWlgYbGxt069YNCxcuRKtWrTTXnDt3Dp999hmuX78OlUoFb29vPP/88xg7dqzmmr///hurV6/GjRs3IJFIMGTIELz99tuQSCS1ZnlwSMDUqVMhkUgwduxYfP7558jOzkaHDh3w0UcfwdfXV/O5iooKREdH448//oBUKoWPjw9mz56NUaNG6fNH9UgsWImIiIj0oKo4rRoScOjQIbz00kua87m5uXjppZfQqlUr5OXlYcOGDZg6dSr27t0LMzMzFBcX46WXXkKXLl3w2WefQSwWIyEhQWs874EDBzBv3jyMGzcOr7zyCqRSKVauXAmZTIbPP/+8Xnnj4uKQl5eH+fPnQ6lUYvny5ViwYAG2b9+uuea1117D+fPnMWfOHAQGBiImJgYLFiyAnZ0dIiMjG/gTqzsWrEREREQNVFpaivbt22u1DR8+XGs4wLJlyzR/ViqV6Ny5M/r164dTp06hb9++uHXrFoqKivDGG28gODgYANCrVy/NZ9RqNVasWIHhw4djyZIlmnZXV1e8+OKLmD17Ntq0aVPnzEVFRdi1axecnJw03+Gdd95BZmYm3N3dcerUKRw9ehTr169H3759AQB9+vSBVCrFV1991agFK5e1IiIiImogS0tL7Ny5Ezt37sTWrVvxn//8B8eOHcO7776ruSYmJgaTJk1Cly5dEBoain79+gEAbt++DQDw9fWFjY0N3n//fezbtw95eXlaz7h16xbS09MxbNgwKBQKzX+6d+8OoVCIK1eu1CtzSEiIplgFgKCgIAB3x/ICwPHjx+Hg4ICePXtqPa93796Ii4uDUqms989JV+xhJSIiImogoVCoWUIKALp06aJ5zf7cc8+hrKwMs2fPxsCBA/HCCy/A2dkZAoEAEyZMQHl5OQDA3t4eGzZswJdffom33noLSqUSXbt2xbvvvovg4GDk5+cDAObMmVNjhoyMjHpltrOz0zo2NzcHAE2e/Px8FBQUVOs5riKVShttYhwLViIiIiIDCAgIAAAkJCTg+vXrsLGxwRdffKFZlzU9Pb3aZ8LDw7Fu3TrNONiPP/4Yc+bMweHDh+Hg4AAAeO+99xAeHl7ts/dP3tIHe3t7ODk5Ye3atTWev7931tBYsBIREREZQHx8PADA0dERZWVlMDc3h0Ag0Jz/448/av2spaUlIiMjkZKSgiVLlqC8vBwBAQFwd3dHamoqpkyZYvD8vXv3xrp162Bubo6QkBCDP+9hWLASERERNZBKpcLFixcBAJWVlbh69Sq++eYbBAUFoWvXrqioqMAPP/yA//73v3j88cdx4cIF/P7771r3+Pvvv7Fz504MGjQInp6eyMnJwZYtWxAREQELCwsAwMKFCzF//nyUlpaif//+sLKywp07dxATE4N58+ahdevWevtOffr0QVRUFGbOnImZM2ciODgYcrkcCQkJSE5O1pr4ZWgsWImIiMjkVE38aSrPLCsrw8SJEwEAZmZmcHd3x+jRozF37lyYm5sjMjIS8+fPx5YtW/Drr78iIiIC3377LYYMGaK5h6+vL4RCIb744gvk5ubCwcEBffv2xRtvvKG5ZtiwYbCzs8OaNWs0PbReXl547LHH4OLionP+2nz55ZdYu3Yttm3bhvT0dNja2qJNmzYYN26c3p/1MAK1Wq1u1CeaoIEDBwIAjhw5YuQkRERELVtT3ZqVDIs9rERERGQyXF1dsXbtWq3F8huTnZ0di1UTxIKViIiITIqrqyuLRtLCjQOIiIiIyKSxYCUiIiIik8aClYiIiIhMGgtWIiIiIjJpLFiJiIiIyKSxYCUiIiIik8aClYiIiIhMGgtWIiIiogbavXs3nnrqKXTp0gUREREYNmwY/vOf/yA3N1dzzcaNGxETE1PtswMGDMCHH37YaFnT0tIQHByMAwcONNozG4obBxAREZFJkUqlTWqnq++++w4rV67E9OnT8eqrr0KtViM+Ph5//PEHsrOz4ezsDADYtGkT+vfvj8jISK3PR0dHw87OTm/foTliwUpEREQmQyqVYtb06SgrLDTK8y3t7bFm48Z6Fa2bN2/G2LFjsXDhQk1bZGQkZs6cCZVK9cjPh4aG6pS1JWHBSkRERCZDJpOhrLAQL3fuDC9Hx0Z9dnp+Pr65cAEymaxeBatMJkOrVq1qPCcU3h19OWDAAKSnp+PHH3/Ejz/+CABYtmwZxo0bhwEDBqB///547733AAALFy7ElStXsGjRIixbtgzJyckIDw/H8uXLYWNjg8WLF+PYsWNwcnLCG2+8geHDh2ue9+C9AODw4cOYM2cOjhw5Am9v7xpzBgcH46233sKMGTM0bRs3bsSyZctw48YNAEBlZSU+++wz7N+/Hzk5OXBwcEBYWBg++eQT2Nra1vnnpQsWrERERGRyvBwd0drFxdgx6qR9+/b
"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': '#ff4c4c'}\n",
"\n",
"# Boxplot (This will generate the legend)\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",
"\n",
"# Offsets remain at 0.4 to match the new box centers with gap=0.2\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_Red.png\", dpi=600, bbox_inches='tight')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 133,
"id": "606952df-3087-480a-8a76-71cbd659c0a7",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_38794/2013331516.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": "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nj17GjoeUaPSaL+XKCkpwV9//YWYmBid/1KNiYkBgEqTu4iIiOqioKCgUltwcDCA8qXWiOjJNNoe1j///BNlZWUYMWKEoaMQERFpWb16Nc6dO4eoqCh4eXkhNzcXP/30E9zd3dGpUydDxyNqdBptwbp79260atWqxokTj7Nnzx4A4DJXRESkV/369UN6ejp+/fVX5Ofnw9HREV27dsWcOXNga2tr6HhEjY5R7XRVWlqK2NhYAMCPP/6I1NRULFq0CADQtWtXzVp2eXl56N27N15++WXMnTu30n3S09MxcOBAzJw5E7NnzwYALFiwAD4+PggJCdFMutq4cSOioqKwevVqnTNzpysiIiKi+mVUPay5ubl4/fXXtdoqjn/44QfNDN99+/ZBoVBUOxxArVZDqVRq7ZTVunVr7Nq1C+vXr4dcLoeXlxdeeeUVTJ8+vZ5eTdOjVqtRWlpq6BgNysrKijsf1TO+r6g+8H1F1LQYVQ9rY9RceljVajVGjRqFc+fOGTpKg+rSpQt+//13fgjUE76v+L6qD3xf8X1FTU+jXSWAGlZpaWmz++UPAGfPnm12vTQNie8rqg98XxE1PUY1JIAah4SEBIhEIkPHqFdSqbROE/royfF9RfWB7yuipoEFKz0xkUjU5D8AqOHxfUX1ge8roqaBQwKIiIiIyKixYCUiIiIio8aClYiIiIiMGgtWIiIiIjJqLFiJiIiIyKixYCUiIiIio8aClYiIiIiMGgtWIiIiIjJq3DiAasXKygpdunTR/Lupa26v11Ca28+5ub1eQ2luP+fm9nqpeRKo1Wq1oUM0Zv379wcAHD582MBJ6l/FW0UgEBg4ScNobq/XUJrbz7m5vV5DaW4/5+b2eqn5YQ8r1Vpz+0XY3F6voTS3n3Nze72G0tx+zs3t9VLzwzGsRERERGTUWLASERERkVFjwUpERERERo0FKxEREREZNRasRERERGTUWLASERERkVFjwUpERERERo0FKxEREREZNRasRERERGTUWLASERERkVFjwUpERERERo0FKxEREREZNRasRERERGTUWLASERERkVFjwUpERERERo0FKxEREREZNRasRERERGTUWLASERERkVFjwUpERERERo0FKxEREREZNRasRERERGTUWLASERERkVFjwUpERERERs3U0AGIjEVCQgIuXrwIS0tLdO/eHd7e3oaORERERGDBSgQAOH36NPbt26c5vnbtGl5++WW4ubkZMBUREREBHBJABAA4e/as1rFCocCFCxcMlIaIiIgexoKVCIBara5VGxERETU8FqxEADp16qR1LBQKER4ebqA0RERE9DCOYSUC0LNnT1hYWCAxMRGWlpbo2bMnPDw8DB2LiIiIwIKVSKNTp06VelqJiIjI8DgkgIiIiIiMGgtWIiIiIjJqLFiJiIiIyKixYCUiIiIio8aClYiIiIiMGgtWIiIiIjJqLFiJHiGTyaBUKg0dg4iIiB7gOqxED0ilUuzYsQNJSUkwNzdHr1690KdPH0PHIiIiavbYw0r0wP79+3Hjxg2o1Wrcv38fR44cwY0bNwwdi4iIqNljwUr0QFJSUqW2mzdvGiAJERERPYwFK9EDjo6OldocHBwaPggRERFpYcFK9ED//v0hFAo1xy4uLoiIiDBgIiIiIgI46YpIIyAgAHP
"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': '#ff4c4c'}\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",
"plt.savefig(\"CantonS_Red.png\", dpi=600, bbox_inches='tight')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 116,
"id": "5f77fc74-7bea-4c2c-a498-791a4656f46f",
"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_278 - Fly 01 0.438889 -1.778015 1.626389\n",
"ETHOSCOPE_278 - Fly 02 0.775000 1.167417 -0.868056\n",
"ETHOSCOPE_278 - Fly 03 1.698611 -0.117443 1.287500\n",
"ETHOSCOPE_278 - Fly 04 -1.986111 0.782294 -3.259722\n",
"ETHOSCOPE_278 - Fly 05 3.193056 3.148666 -0.408333\n",
"ETHOSCOPE_278 - Fly 06 1.693056 -1.332147 2.648611\n",
"ETHOSCOPE_278 - Fly 07 2.154167 1.336528 0.473611\n",
"ETHOSCOPE_278 - Fly 08 -0.019444 0.848352 -1.201389\n",
"ETHOSCOPE_278 - Fly 09 0.265278 3.664755 -3.697222\n",
"ETHOSCOPE_278 - Fly 10 -1.419444 0.479920 -2.094444\n",
"ETHOSCOPE_278 - Fly 11 2.136111 1.940069 -0.088889\n",
"ETHOSCOPE_278 - Fly 12 -0.693056 0.471544 -1.594444\n",
"ETHOSCOPE_278 - Fly 13 2.058333 1.500071 0.202778\n",
"ETHOSCOPE_278 - Fly 14 5.690278 1.739646 3.513889\n",
"ETHOSCOPE_278 - Fly 15 2.122222 1.753471 0.000000\n",
"ETHOSCOPE_278 - Fly 16 1.770833 -0.034838 1.347222\n",
"ETHOSCOPE_278 - Fly 17 3.086111 1.150897 1.544444\n",
"ETHOSCOPE_278 - Fly 18 3.484722 2.314222 0.908333\n",
"ETHOSCOPE_278 - Fly 19 2.743056 2.503166 -0.131944\n",
"ETHOSCOPE_278 - Fly 20 2.956944 0.974121 1.680556\n",
"\n",
"==================================================\n",
"\n",
"--- Average Change (Delta) across all flies ---\n",
"Delta_24h: 1.61 ± 0.41 hours\n",
"Delta_Day: 1.13 ± 0.30 hours\n",
"Delta_Night: 0.09 ± 0.41 hours\n"
]
}
],
"source": [
"#DELTA\n",
"\n",
"# 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": 117,
"id": "673c571d-ec35-4f87-b58f-127bd6b9c379",
"metadata": {},
"outputs": [],
"source": [
"#export to csv\n",
"delta_table['Condition'] = 'Red'\n",
"delta_table.to_csv('delta_red.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
}