{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load Required Packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import os\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.patches import Ellipse\n",
    "from matplotlib.lines import Line2D\n",
    "from matplotlib.colors import to_rgba\n",
    "from matplotlib.colors import ListedColormap\n",
    "import matplotlib.transforms as transforms\n",
    "import matplotlib.patheffects as path_effects\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.decomposition import PCA"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PCA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function to draw confidence ellipse\n",
    "def confidence_ellipse(x, y, ax, n_std=1.96, facecolor='none', edgecolor='black', **kwargs):\n",
    "    if x.size != y.size:\n",
    "        raise ValueError(\"x and y must be the same size\")\n",
    "    \n",
    "    cov = np.cov(x, y)\n",
    "    pearson = cov[0, 1] / np.sqrt(cov[0, 0] * cov[1, 1])\n",
    "    ell_radius_x = np.sqrt(1 + pearson)\n",
    "    ell_radius_y = np.sqrt(1 - pearson)\n",
    "    ellipse = Ellipse((0, 0), width=ell_radius_x * 2, height=ell_radius_y * 2, facecolor=facecolor, edgecolor=edgecolor, **kwargs)\n",
    "    \n",
    "    scale_x, scale_y = np.sqrt(cov[0, 0]) * n_std, np.sqrt(cov[1, 1]) * n_std\n",
    "    transf = transforms.Affine2D().rotate_deg(45).scale(scale_x, scale_y).translate(np.mean(x), np.mean(y))\n",
    "    ellipse.set_transform(transf + ax.transData)\n",
    "    return ax.add_patch(ellipse)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load data and define colors for conditions\n",
    "data = pd.read_csv()\n",
    "color_pos = '#821200' \n",
    "color_neg = '#FF7F00' \n",
    "sample_cols = [col for col in data.columns if any(x in col for x in ['Neg', 'Pos'])]\n",
    "pca_data = data[sample_cols]\n",
    "\n",
    "# Select top 500 most variable genes and transpose for PCA\n",
    "top_genes = pca_data.var(axis=1).nlargest(500).index\n",
    "pca_data_t = pca_data.loc[top_genes].T\n",
    "\n",
    "# Perform PCA\n",
    "pca = PCA(n_components=2)\n",
    "pca_result = pca.fit_transform(pca_data_t)\n",
    "\n",
    "# Create DataFrame with PCA results and condition labels\n",
    "pca_df = pd.DataFrame(pca_result, columns=['PC1', 'PC2'], index=pca_data_t.index)\n",
    "pca_df['condition'] = ['NeuN-' if 'Neg' in s else 'NeuN+' for s in pca_df.index]\n",
    "pca_df['treatment'] = ['GFP' if 'GFP' in s else 'IRISIN' for s in pca_df.index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot PCA results\n",
    "plt.figure(figsize=(12, 10))\n",
    "ax = sns.scatterplot(data=pca_df, x='PC1', y='PC2', hue='condition', style='treatment', s=500,\n",
    "                     palette={'NeuN+': color_pos, 'NeuN-': color_neg})\n",
    "\n",
    "plt.title('NeuN- vs NeuN+', fontsize=22)\n",
    "plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.2%} variance explained)', fontsize=18)\n",
    "plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.2%} variance explained)', fontsize=18)\n",
    "plt.tick_params(axis='both', labelsize=14)\n",
    "plt.axhline(y=0, color='k', linestyle='--', linewidth=0.5)\n",
    "plt.axvline(x=0, color='k', linestyle='--', linewidth=0.5)\n",
    "\n",
    "# Draw confidence ellipses for each condition\n",
    "for condition in pca_df['condition'].unique():\n",
    "    subset = pca_df[pca_df['condition'] == condition]\n",
    "    color = color_pos if condition == 'NeuN+' else color_neg\n",
    "    confidence_ellipse(subset['PC1'], subset['PC2'], ax, facecolor=color, edgecolor=color, alpha=0.3)\n",
    "\n",
    "plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=16)\n",
    "plt.xlim(pca_df['PC1'].min() - 30, pca_df['PC1'].max() + 15)\n",
    "plt.ylim(pca_df['PC2'].min() - 5, pca_df['PC2'].max() + 10)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load Required Packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "library(clusterProfiler)\n",
    "library(ggplot2)\n",
    "library(org.Mm.eg.db)\n",
    "library(enrichplot)\n",
    "library(cowplot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GSEA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Load data from CSV and inspect 'padj' column\n",
    "df_NeuNpos <- read.csv()\n",
    "print('Total number of genes:')\n",
    "length(df_NeuNpos$padj)\n",
    "print('Number of genes with NA:')\n",
    "sum(is.na(df_NeuNpos$padj))\n",
    "print('Percentage of NA genes:')\n",
    "sum(is.na(df_NeuNpos$padj)) / length(df_NeuNpos$padj) * 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Sort genes by log2FoldChange in descending order and create gene list\n",
    "df_NeuNpos_sorted <- df_NeuNpos[order(df_NeuNpos$log2FoldChange, decreasing = TRUE), ]\n",
    "geneList_NeuNpos <- df_NeuNpos_sorted$log2FoldChange\n",
    "names(geneList_NeuNpos) <- df_NeuNpos_sorted$X\n",
    "geneList_NeuNpos <- geneList_NeuNpos[!is.na(names(geneList_NeuNpos))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Perform gene set enrichment analysis (GSEA) and simplify results\n",
    "gse_neun <- gseGO(\n",
    "  geneList = geneList_NeuNpos,\n",
    "  ont = \"ALL\", keyType = \"ENSEMBL\", minGSSize = 15, maxGSSize = 500, \n",
    "  pvalueCutoff = 0.05, verbose = TRUE, OrgDb = org.Mm.eg.db, pAdjustMethod = \"BH\", by = \"fgsea\"\n",
    ")\n",
    "gse_neun_simplified <- simplify(gse_neun, cutoff = 0.7, by = \"p.adjust\", select_fun = min)\n",
    "\n",
    "# Convert gene IDs to gene symbols for readability and create pairwise term similarity matrix\n",
    "gsex_neun_simplified <- setReadable(gse_neun_simplified, 'org.Mm.eg.db', 'ENSEMBL')\n",
    "gsex2_neun_simplified <- pairwise_termsim(gsex_neun_simplified)\n",
    "\n",
    "# Add a column with negative NES values for color coding in plot legend\n",
    "gsex2_neun_simplified_with_negNES <- gsex2_neun_simplified\n",
    "result_df_neun_simplified <- gsex2_neun_simplified_with_negNES@result\n",
    "result_df_neun_simplified$negNES <- -1 * result_df_neun_simplified$NES\n",
    "gsex2_neun_simplified_with_negNES@result <- result_df_neun_simplified"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Create enrichment map plot with customized layout and clustering\n",
    "set.seed(123)\n",
    "p <- emapplot(\n",
    "  gsex2_neun_simplified_with_negNES, layout = \"kk\", color = \"negNES\",\n",
    "  showCategory = 200, cex_category = 1, cex_label_category = 0.5, \n",
    "  group_category = TRUE, nCluster = 11\n",
    ")\n",
    "\n",
    "# Enhance plot appearance: add title, adjust legend, and arrange layout\n",
    "p <- p + ggtitle(\"Enrichment Map of Gene Sets\")\n",
    "legend <- get_legend(p)\n",
    "p_no_legend <- p + theme(legend.position = \"none\")\n",
    "p_large <- ggdraw() + draw_plot(p_no_legend, 0, 0, 1, 1) + theme(plot.margin = margin(10, 10, 10, 10))\n",
    "final_plot_neun_simplified_negNES <- plot_grid(p_large, legend, rel_widths = c(0.8, 0.2), ncol = 2)\n",
    "\n",
    "print(final_plot_neun_simplified_negNES)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Image Processing (ImageJ/Fiji)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This macro documents the preprocessing and quantification steps used for MFI GFAP, DAPI, NeuN, and Irisin imaging analysis.  \n",
    "All steps were performed in **ImageJ (Fiji)** using the following macro, provided below for reproducibility.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Irisin NeuN processing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Create Max Projections for DAPI and NeuN -------------\n",
    "selectWindow(\"DAPI\");\n",
    "run(\"Z Project...\", \"projection=[Max Intensity]\");\n",
    "rename(\"DAPI_Max\");\n",
    "\n",
    "selectWindow(\"NeuN\");\n",
    "run(\"Z Project...\", \"projection=[Max Intensity]\");\n",
    "rename(\"NeuN_Max\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Apply setMinAndMax for NeuN -------------\n",
    "selectWindow(\"NeuN_Max\");\n",
    "setMinAndMax(32, 12832);\n",
    "\n",
    "// ----------- Create Average Intensity Projection for Irisin -------------\n",
    "selectWindow(\"Irisin\");\n",
    "run(\"Z Project...\", \"projection=[Average Intensity]\");\n",
    "rename(\"Irisin_Avg\");\n",
    "\n",
    "// ----------- Apply setMinAndMax for Irisin -------------\n",
    "selectWindow(\"Irisin_Avg\");\n",
    "setMinAndMax(33, 3801);\n",
    "run(\"Subtract Background...\", \"rolling=100\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Threshold and Segment NeuN (to get candidate ROIs) -------------\n",
    "selectWindow(\"NeuN_Max\");\n",
    "run(\"Gaussian Blur...\", \"sigma=1.0\");\n",
    "run(\"Auto Threshold\", \"method=Otsu white\");\n",
    "setOption(\"BlackBackground\", false);\n",
    "run(\"Convert to Mask\");\n",
    "run(\"Watershed\");\n",
    "rename(\"NeuN_Segmented\");\n",
    "\n",
    "run(\"Analyze Particles...\", \"size=50-Infinity circularity=0.3-1.00 show=Nothing display clear add\");\n",
    "\n",
    "// Save NeuN ROIs temporarily\n",
    "roiManager(\"Select All\");\n",
    "roiManager(\"Combine\");\n",
    "run(\"Create Mask\");\n",
    "rename(\"All_NeuN_Mask\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Filter ROIs that overlap with DAPI -------------\n",
    "roiManager(\"Reset\");  // start fresh\n",
    "selectWindow(\"NeuN_Segmented\");\n",
    "run(\"Analyze Particles...\", \"size=50-Infinity circularity=0.3-1.00 show=Nothing clear add\");\n",
    "\n",
    "// Store original NeuN ROIs\n",
    "nROIs = roiManager(\"count\");\n",
    "\n",
    "// Prepare mask from DAPI\n",
    "selectWindow(\"DAPI_Max\");\n",
    "run(\"Gaussian Blur...\", \"sigma=1.0\");\n",
    "run(\"Auto Threshold\", \"method=Otsu white\");\n",
    "setOption(\"BlackBackground\", false);\n",
    "run(\"Convert to Mask\");\n",
    "rename(\"DAPI_Mask\");\n",
    "\n",
    "// Create a copy for pixel inspection\n",
    "selectWindow(\"DAPI_Mask\");\n",
    "run(\"Duplicate...\", \"title=DAPI_Mask_Copy\");\n",
    "selectWindow(\"DAPI_Mask_Copy\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Keep only NeuN ROIs that overlap DAPI -------------\n",
    "roiManager(\"deselect\");\n",
    "keptROIs = 0;\n",
    "for (i = 0; i < nROIs; i++) {\n",
    "    roiManager(\"select\", i);\n",
    "    run(\"Measure\");\n",
    "    getStatistics(area, mean);\n",
    "    \n",
    "    // Check if mean intensity inside DAPI mask is above 0\n",
    "    if (mean > 0) {\n",
    "        roiManager(\"select\", i);\n",
    "        roiManager(\"Add\");  // add again to new filtered set\n",
    "        keptROIs++;\n",
    "    }\n",
    "}\n",
    "\n",
    "// Remove original unfiltered ROIs\n",
    "for (j = 0; j < nROIs; j++) {\n",
    "    roiManager(\"Select\", 0);\n",
    "    roiManager(\"Delete\");\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Measure Irisin in Filtered NeuN ROIs -------------\n",
    "run(\"Clear Results\");\n",
    "selectWindow(\"Irisin_Avg\");\n",
    "roiManager(\"deselect\");\n",
    "roiManager(\"measure\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### MFI GFAP processing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Create Max Projections for DAPI and GFAP -------------\n",
    "selectWindow(\"DAPI\");\n",
    "run(\"Z Project...\", \"projection=[Max Intensity]\");\n",
    "rename(\"DAPI_Max\");\n",
    "print(\"DAPI Max Projection created.\");\n",
    "\n",
    "selectWindow(\"GFAP\");\n",
    "run(\"Z Project...\", \"projection=[Max Intensity]\");\n",
    "rename(\"GFAP_Max\");\n",
    "print(\"GFAP Max Projection created.\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Apply setMinAndMax for GFAP -------------\n",
    "selectWindow(\"GFAP_Max\");\n",
    "setMinAndMax(280, 3641);\n",
    "print(\"GFAP display range set.\");\n",
    "\n",
    "// ----------- Create Average Intensity Projection for Irisin -------------\n",
    "selectWindow(\"Irisin\");\n",
    "run(\"Z Project...\", \"projection=[Average Intensity]\");\n",
    "rename(\"Irisin_Avg\");\n",
    "print(\"Irisin Avg Projection created.\");\n",
    "\n",
    "// ----------- Apply setMinAndMax for Irisin -------------\n",
    "selectWindow(\"Irisin_Avg\");\n",
    "setMinAndMax(0, 2201);\n",
    "run(\"Subtract Background...\", \"rolling=100\");\n",
    "print(\"Irisin display range set.\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Threshold and Segment GFAP -------------\n",
    "selectWindow(\"GFAP_Max\");\n",
    "setAutoThreshold(\"Yen dark no-reset\");\n",
    "run(\"Convert to Mask\");\n",
    "run(\"Analyze Particles...\", \"size=20-Infinity show=Nothing add\");\n",
    "print(\"GFAP thresholded and initial ROIs added.\");\n",
    "\n",
    "// ----------- Combine and mask ROIs -------------\n",
    "roiManager(\"Select All\");\n",
    "roiManager(\"Combine\");\n",
    "run(\"Create Mask\");\n",
    "rename(\"All_GFAP_Mask\");\n",
    "print(\"GFAP ROIs combined into All_GFAP_Mask.\");\n",
    "\n",
    "// ----------- Prepare DAPI mask -------------\n",
    "selectWindow(\"DAPI_Max\");\n",
    "run(\"Gaussian Blur...\", \"sigma=1.0\");\n",
    "run(\"Auto Threshold\", \"method=Otsu white\");\n",
    "setOption(\"BlackBackground\", false);\n",
    "run(\"Convert to Mask\");\n",
    "rename(\"DAPI_Mask\");\n",
    "print(\"DAPI mask created.\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Filter GFAP ROIs that overlap with DAPI -------------\n",
    "roiManager(\"Reset\");\n",
    "selectWindow(\"All_GFAP_Mask\");\n",
    "run(\"Analyze Particles...\", \"size=20-Infinity show=Nothing clear add\");\n",
    "\n",
    "nROIs = roiManager(\"count\");\n",
    "print(\"ROIs to check for DAPI overlap: \" + nROIs);\n",
    "\n",
    "selectWindow(\"DAPI_Mask\");\n",
    "\n",
    "roiManager(\"deselect\");\n",
    "keptROIs = 0;\n",
    "for (i = 0; i < nROIs; i++) {\n",
    "    roiManager(\"select\", i);\n",
    "    run(\"Measure\");\n",
    "    getStatistics(area, mean);\n",
    "    if (mean > 0) {\n",
    "        roiManager(\"select\", i);\n",
    "        roiManager(\"Add\");\n",
    "        keptROIs++;\n",
    "    }\n",
    "}\n",
    "print(\"ROIs overlapping with DAPI: \" + keptROIs);\n",
    "\n",
    "// Remove original unfiltered ROIs\n",
    "for (j = 0; j < nROIs; j++) {\n",
    "    roiManager(\"Select\", 0);\n",
    "    roiManager(\"Delete\");\n",
    "}\n",
    "print(\"Original unfiltered ROIs removed.\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "javascript"
    }
   },
   "outputs": [],
   "source": [
    "// ----------- Measure Irisin average intensity -------------\n",
    "run(\"Clear Results\");\n",
    "selectWindow(\"Irisin_Avg\");\n",
    "run(\"Set Measurements...\", \"mean redirect=None decimal=3\");\n",
    "roiManager(\"deselect\");\n",
    "roiManager(\"measure\");\n",
    "print(\"Irisin intensity measured for filtered GFAP ROIs.\");"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "proj_eae",
   "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.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
