diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index fea5745..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..57272af --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,32 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # nodejs: "19" + # rust: "1.64" + # golang: "1.19" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/source/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +# formats: +# - pdf +# - epub + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - method: pip + path: . + - requirements: docs/source/requirements.txt diff --git a/README.md b/README.md index 3bb230a..f05efc4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,56 @@ -# pipeline_vsdi +

+ +
Pipeline VSDI +


+ Preprocessing tools for voltage sensitive dye imaging data ## Structure -- vsdi will contain classes for handling sessions and full datasets -- preprocessing contains functionality to clean and reshape data -- dim_reduction contains functionality to reduce the dimensionality of the data with different models +- **vsdi** - Contains classes for handling sessions and full datasets. +- **preprocessing** - Contains functionality to clean and reshape data. +- **dim_reduction** - Contains functionality to reduce the dimensionality of the data with different models. + +## Installation + +### Prerequisites + +- Python 3.7 or higher +- [Poetry](https://python-poetry.org/docs/#installation) Python packaging and dependency management tool. + +### Steps + +#### 1. Clone the repository + +```bash +git clone https://github.com/dabadav/pipeline_vsdi.git +cd pipeline_vsdi +``` + +#### 2. Install the package using Poetry + +Ensure you're in the `pipeline_vsdi` directory (or the directory where you cloned your repository) and run: + +```bash +poetry install +``` + +This command installs all the dependencies specified in the `pyproject.toml` file in a new virtual environment. If you want to use the virtual environment for other tasks, you can activate it using: + +```bash +poetry shell +``` + +After this, you should have all the necessary dependencies installed and be able to use the functionality provided by the Pipeline VSDI. + +## Usage + +After installation, you can import and use the tools in the Python interpreter or your scripts like: + +```python +from vsdi import Session +from preprocessing import clean_data +from dim_reduction import reduce_dimension + +# Use the tools as per your requirement. +``` \ No newline at end of file diff --git a/dim_reduction/clustering.py b/dim_reduction/clustering.py deleted file mode 100644 index e138467..0000000 --- a/dim_reduction/clustering.py +++ /dev/null @@ -1,46 +0,0 @@ -import numpy as np -from scipy.spatial.distance import pdist, squareform -from sklearn.cluster import KMeans -from sklearn.manifold import TSNE -import matplotlib.pyplot as plt - -def compute_distance_matrix(arr_list): - """ - Given a list of 2D arrays, compute the pairwise distance matrix using Pearson correlation. - """ - # Get the number of arrays in the list - n_arrays = len(arr_list) - # Create an empty distance matrix with shape (n_arrays, n_arrays) - dist_mat = np.zeros((n_arrays, n_arrays)) - # Compute the pairwise distance between all pairs of arrays using Pearson correlation - for i in range(n_arrays): - for j in range(i+1, n_arrays): - corr = np.corrcoef(arr_list[i], arr_list[j])[0, 1] - dist = 1 - np.abs(corr) - dist_mat[i, j] = dist - dist_mat[j, i] = dist - # Return the distance matrix - return dist_mat - -def cluster_and_plot(arr_list, kind='betas'): - """ - Given a list of 2D arrays, compute the pairwise distance matrix, cluster it using k-means, - and plot the t-SNE projection of the distance matrix, colored by the cluster labels. - """ - # Compute the distance matrix using Pearson correlation - dist_mat = compute_distance_matrix(arr_list) - # Set the number of clusters for k-means - n_clusters = 10 - # Apply k-means clustering to the distance matrix - kmeans = KMeans(n_clusters=n_clusters) - labels = kmeans.fit_predict(dist_mat) - # Compute the t-SNE projection of the distance matrix - tsne = TSNE(n_components=2, perplexity=30, random_state=42) - emb = tsne.fit_transform(dist_mat) - # Plot the t-SNE projection, coloring each point by its cluster label - fig, ax = plt.subplots(figsize=(8, 8)) - scatter = ax.scatter(emb[:,0], emb[:,1], c=labels, cmap='viridis') - legend = ax.legend(*scatter.legend_elements(), loc="lower left", title="Clusters") - ax.add_artist(legend) - ax.set_title(f"t-SNE projection of {kind} distance matrix") - plt.show() diff --git a/dim_reduction/pca_ica.ipynb b/dim_reduction/pca_ica.ipynb deleted file mode 100644 index 37b53b6..0000000 --- a/dim_reduction/pca_ica.ipynb +++ /dev/null @@ -1,358 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import sys\n", - "import os\n", - "sys.path.append(os.path.abspath('../'))\n", - "from scipy.io import loadmat\n", - "import loaders\n", - "from vsdi_preprocessing import clean_outliers,pca_ica,glm\n", - "from pathlib import Path" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "datapath = Path('/Users/davide/Dropbox/Projects/ATC/ATC_Data_preprocessed')\n", - "atc = loadmat(datapath.joinpath('A04/Day1/ATC1.mat'))\n", - "vsdi = loadmat(datapath.joinpath('A04/Day1/vsdi_ATC1.mat'))['vsdi_data']\n", - "mask = loadmat(datapath.joinpath(f'A04/Day1/vsdi_mask.mat'))['mask']\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(94, 54, 29999)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vsdi.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.decomposition import PCA, FastICA\n", - "from sklearn.preprocessing import StandardScaler\n", - "from sklearn.pipeline import Pipeline\n", - "\n", - "def pca_ica(vsdi,mask):\n", - " X = vsdi.transpose(2, 0, 1)\n", - " X = X*mask\n", - " X = X.reshape(X.shape[0], X.shape[1]*X.shape[2])\n", - "\n", - " # Create a pipeline with PCA and ICA\n", - " pipe = Pipeline([\n", - " ('scaler', StandardScaler()),\n", - " ('pca', PCA(n_components=10)),\n", - " ('ica', FastICA(n_components=10, max_iter=200,\n", - " random_state=1, whiten='unit-variance'))\n", - " ])\n", - "\n", - " out = pipe.fit(X)\n", - "\n", - " fingerprints = out.named_steps[\"ica\"].components_ @ out.named_steps[\"pca\"].components_\n", - " timecourses = fingerprints @ X.T\n", - "\n", - " return fingerprints,timecourses\n", - "\n", - "clean_vsdi = clean_outliers(vsdi,nsigma=5)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "'numpy.ndarray' object is not callable", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[23], line 11\u001b[0m\n\u001b[1;32m 8\u001b[0m vsdi2 \u001b[39m=\u001b[39m loadmat(datapath\u001b[39m.\u001b[39mjoinpath(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00manimal\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mday\u001b[39m}\u001b[39;00m\u001b[39m/vsdi_ATC2.mat\u001b[39m\u001b[39m'\u001b[39m))[\u001b[39m'\u001b[39m\u001b[39mvsdi_data\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[1;32m 9\u001b[0m mask \u001b[39m=\u001b[39m loadmat(datapath\u001b[39m.\u001b[39mjoinpath(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00manimal\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mday\u001b[39m}\u001b[39;00m\u001b[39m/vsdi_mask.mat\u001b[39m\u001b[39m'\u001b[39m))[\u001b[39m'\u001b[39m\u001b[39mmask\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[0;32m---> 11\u001b[0m vsd1 \u001b[39m=\u001b[39m clean_vsdi(vsdi1,nsigma\u001b[39m=\u001b[39;49m\u001b[39m5\u001b[39;49m)\n\u001b[1;32m 12\u001b[0m vsdi2 \u001b[39m=\u001b[39m clean_vsdi(vsdi2,nsigma\u001b[39m=\u001b[39m\u001b[39m5\u001b[39m)\n\u001b[1;32m 14\u001b[0m vsdi \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mdstack([vsdi1,vsdi2])\n", - "\u001b[0;31mTypeError\u001b[0m: 'numpy.ndarray' object is not callable" - ] - } - ], - "source": [ - "animals = ['A04']\n", - "days = ['Day1','Day3','Day5','Day7']\n", - "\n", - "for animal in animals:\n", - " vsdi_total = []\n", - " for day in days:\n", - " vsdi1 = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_ATC1.mat'))['vsdi_data']\n", - " vsdi2 = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_ATC2.mat'))['vsdi_data']\n", - " mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask']\n", - "\n", - " vsd1 = clean_vsdi(vsdi1,nsigma=5)\n", - " vsdi2 = clean_vsdi(vsdi2,nsigma=5)\n", - "\n", - " vsdi = np.dstack([vsdi1,vsdi2])\n", - " print(vsdi.shape)\n", - " vsdi_total.append(vsdi1)\n", - "\n", - "vsdi_total = np.dstack(vsdi_total)\n", - "print('Done')\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pca_ica(vsdi_total,mask)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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XZl9fvWrX8Xxxx+Pzs5OdHZ2Yt26dfjpT3865f7S+PznP4+6ujpcdNFF+9Xvpz71KdTV1ZX9rV27dlrPVVQiO5AdiP2zA2D6bUF2IDs4GMwFOwBm3hZkB7VN3uwAmNv3hANmB1HOuPbaa6Pm5uboW9/6VvSrX/0qet/73hcVCoVo165dE/r8T37yk+jv//7vox/+8IcRgOi6664r2//5z38+6urqiq6//vrowQcfjN785jdHa9asifbu3ZvZ59lnnx1dc8010datW6MHHnggeuMb3xitWrUq6u/vj4/5wAc+EB122GHR5s2bo3vuuSc644wzojPPPDOzzx//+MfRjTfeGD3++OPRtm3bor/7u7+Lmpqaoq1bt06pP89dd90VrV69Ojr++OOjj3zkI1M+zyiKossuuyw69thjox07dsR/L7zwwn71KaojO5AdiP23gyiafluQHcgODjRzxQ6iaGZtQXZQ2+TRDqJobt8TDpQd5O5l9bTTTos2bNgQr4+OjkYrVqyINm3aNOm+/EAcGxuLli1bFl1++eXxtmKxGLW0tET/8R//MeF+u7u7IwDRli1b4j6ampqi73//+/Exjz76aAQguuOOOybc74IFC6JvfOMb+91fX19fdNRRR0U333xz9Ad/8AfxQJxqv5dddll0wgknpO6brt8uypEdyA7E9NpBFM2MLcgOEmQHM8NctoMomh5bkB3UPrVgB1E0t+4JB8oOchUGPDw8jHvvvRfr16+Pt9XX12P9+vW444479rv/p556Cjt37izrv6urC6effvqk+u/p6QEALFy4EABw7733YmRkpKzftWvXYtWqVRPqd3R0FNdeey327NmDdevW7Xd/GzZswDnnnFP2+f09zyeeeAIrVqzAEUccgfPPPx/PPPPMtPx2UYnsQHYgZt4OgOmxBdmB7GAmmat2AEyvLcgOaptasQNg7t0TDoQdNE7q6BnmxRdfxOjoKJYuXVq2fenSpXjsscf2u/+dO3fG/fn+uW88xsbGcNFFF+FVr3oVjjvuuLjf5uZmFAqFSfX78MMPY926dRgcHER7ezuuu+46HHPMMXjggQem1B8AXHvttbjvvvtw9913V+yb6nmefvrp+Pa3v42Xv/zl2LFjBz796U/j93//97F169Yp9ymykR3IDsTM2wGw/7YgO5AdzDRzzQ6A6bcF2UHtUwt2AMy9e8KBsoNcvazWAhs2bMDWrVvx85//fL/7evnLX44HHngAPT09+MEPfoALLrgAW7ZsmXJ/zz77LD7ykY/g5ptvRmtr636fH3nDG94QLx9//PE4/fTTcfjhh+N73/se2trapu17RO0gO5AdCNmB7EAA02sHwPTaguxAHEjm2j3hQNlBrsKAFy9ejIaGhopKUbt27cKyZcv2u3/2MdX+L7zwQtxwww342c9+hpUrV5b1Ozw8jGKxOKl+m5ubceSRR+Lkk0/Gpk2bcMIJJ+Cf/umfptzfvffei+7ubpx00klobGxEY2MjtmzZgquuugqNjY1YunTplPr1FAoFHH300XjyySenfK4iG9mB7EDMvB0A+2cLsoMSsoOZZa7ZATC9tiA7mB3k3Q4A3ROAmbODXL2sNjc34+STT8bmzZvjbWNjY9i8eTPWrVu33/2vWbMGy5YtK+u/t7cXv/zlL6v2H0URLrzwQlx33XW45ZZbsGbNmrL9J598Mpqamsr63bZtG5555plJnffY2BiGhoam3N9ZZ52Fhx9+GA888ED8d8opp+D888+Pl6fjPPv7+/HrX/8ay5cvn7bfLhJkB7IDMfN2AEzNFmQH5cgOZpa5bgfA/tmC7GB2kFc7AHRPCJkxO5hUOaYDwLXXXhu1tLRE3/72t6NHHnkkev/73x8VCoVo586dE/p8X19fdP/990f3339/BCC64oorovvvvz96+umnoygqlaUuFArRj370o+ihhx6K3vKWt4xblvqDH/xg1NXVFd16661l5ZkHBgbiYz7wgQ9Eq1atim655ZbonnvuidatWxetW7cus89LLrkk2rJlS/TUU09FDz30UHTJJZdEdXV10X//939Pqb8swkpfU+33r//6r6Nbb701euqpp6Jf/OIX0fr166PFixdH3d3d03quIkF2IDsQ+28HUTT9tiA7kB0caOaKHUTRgbEF2UFtkkc7iKK5fU84UHaQu5fVKIqiL3/5y9GqVaui5ubm6LTTTovuvPPOCX/2Zz/7WQSg4u+CCy6IoqhUmvoTn/hEtHTp0qilpSU666yzom3btlXtM60/ANE111wTH7N3797oQx/6ULRgwYJo3rx50Vvf+tZox44dmX2++93vjg4//PCoubk5OuSQQ6KzzjorHoRT6S8LPxCn0u/b3/72aPny5VFzc3N06KGHRm9/+9ujJ598ctrP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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure(figsize=(10,5))\n", - "for i,f in enumerate(fingerprints):\n", - " ax = plt.subplot(2,5,i+1)\n", - " ax.matshow(f.reshape(vsdi.shape[:2]),cmap=plt.cm.gnuplot2)\n", - "plt.tight_layout()\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Match masks" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Mask clustering" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import product\n", - "\n", - "animals = ['A04','A06','A07','A08']\n", - "days = ['Day1','Day3','Day5','Day7']\n", - "\n", - "masks = []\n", - "for animal,day in product(animals,days):\n", - " try:\n", - " mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask']\n", - " masks.append(mask)\n", - "\n", - " except FileNotFoundError:\n", - " print(f\"Not found mask for {animal},{day}\")\n", - " masks.append(np.nan)\n", - " continue\n", - " except OSError:\n", - " print(f\"OS error for {animal},{day}\")\n", - " masks.append(np.nan)\n", - " continue\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(masks)" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0YAAAPeCAYAAAAoEQo2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAABT0klEQVR4nO3da5CV1b0n4P8WsGlAONACyuU0g4iGqwhq4miaSIwkGsTCIJrEZKxJvBUTPWqiE1vBa6Fy9JjjNcRUNJUao2Iuoo4y4zknUzGQaGSCkqgIIWCCjKFEEwWBNR9S3WTTXLqhL+/u9TxV/YG113732pffhx/r3e8upZRSAAAAZOyAjl4AAABAR1OMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZa/ViNHny5BgzZkxrH7bD/fCHP4x+/frFe++919FLaTNPP/109OrVKzZs2NDRS6ENyGblks3OTTYrl2x2XnJZufYnl3aMmmHbtm1x7bXXxuzZs6NXr16N4x9++GHMnTs3hg8fHlVVVTF8+PC44YYbYuvWrXs83o033hilUmm/Ard69eoolUq7/Psf/+N/7PZ+H374YYwaNSpKpVLcdtttZbdNnTo1RowYETfffPM+rwvak2xCMckmFI9c7l3XFt8jQz/96U/jd7/7XXz1q18tG//CF74QjzzySJx33nkxadKk+MUvfhH19fWxZs2auP/++3d5rLVr18ZNN90UPXv2bJW1nX322fGZz3ymbOxjH/vYbud/61vfijVr1uz29vPPPz8uv/zymDt3bhx00EGtskZoK7IJxSSbUDxy2QypldXV1aXRo0e39mE71LRp09IJJ5xQNrZ06dIUEam+vr5s/LLLLkulUiktW7Zsl8c666yz0kknnbTfr9OqVatSRKRbb7212fdZv3596tOnT7ruuut2e9/169enLl26pO985zv7vDaKSTZlk2KSTdmkeOQyz1y26FS6d999Ny655JIYNmxYVFVVxYABA+Lkk0+OF198scncV155JT7xiU9Ejx49YvDgwXHLLbeU3b5ly5a45pprYuLEidGnT5/o2bNnnHjiifHcc8+VzWvYYrvtttvi9ttvj9ra2qiuro66urpYvnx5k8f97W9/G2eeeWb069cvunfvHpMmTYqf/OQnTeatXLkyVq5cudfn/MEHH8TTTz8dn/zkJ8vGf/azn0VExKxZs8rGZ82aFSmlePjhh5sc6z/+4z/i0UcfjTvuuGOvj9sSf/nLX2LLli17nXfllVfGEUccEV/4whd2O2fAgAExbty4+PGPf9yaS6SNyeYOskmRyOYOsklRyOUOcrmTlrSoc845Jx144IHpn/7pn9KCBQvSvHnz0mc/+9n0/e9/v3FOXV1dGjRoUBo6dGj62te+lu6+++500kknpYhITz75ZOO8DRs2pEMPPTT90z/9U7rnnnvSLbfcko444ojUrVu39Otf/7pxXkOTHDt2bBo2bFiaN29emjt3burXr1/q379/+tOf/tQ4d/ny5alPnz5p1KhRad68eelf//Vf08c//vFUKpXSwoULy55LbW1tqq2t3etz/j//5/+kiEg/+clPysZvuummFBHpjTfeKBt/+eWXU0SkU045pWx869atady4cen8889vfJ1ao2H36tUrRUQqlUpp0qRJ6X/+z/+5y/lLlixJBxxwQPr5z3++13b+X//rf00HH3zwPq+N9iebO8gmRSKbO8gmRSGXO8hluRYVoz59+qSLL754j3Pq6upSRKQHH3ywcWzz5s3pkEMOSTNmzGgc27p1a9q8eXPZfTdu3JgGDhyYzjvvvMaxhiddXV2d1q5d2zi+ZMmSFBHp0ksvbRybMmVKGjt2bPrggw8ax7Zv356OP/74dPjhh5c9VnM/SAsWLEgRkX7zm9+UjT/22GMpItJDDz1UNn7vvfemiEhjxowpG//Xf/3X1KdPn/TWW2+llPb/g/T73/8+fepTn0r33HNP+slPfpLuuOOO9I//+I/pgAMOSE888UTZ3O3bt6djjz02nX322SmlvW9bNoRk/fr1+7w+2pds7iCbFIls7iCbFIVc7iCX5VpUjGpra9OkSZPSunXrdjunrq4u9erVK23fvr1sfNq0aWnChAm7vM+2bdvS22+/nTZs2JBOPfXUdNRRRzXe1vCkG16Ev3fcccelI444IqWU0ttvv51KpVK6/vrr04YNG8r+5s6dmyKi7IPYXPPmzdvlfd9///1UW1ubBg4cmB577LG0evXq9PDDD6eamprUtWvXdNhhhzXO/X//7/+lfv36pdtuu63sdWrtc1fffvvtNHDgwMbXpMEDDzyQqqur05o1a1JKe/8g3XPPPSki0ssvv9yq66PtyOYOskmRyOYOsklRyOUOclmuRd8xuuWWW2L58uUxdOjQOPbYY2POnDnxxhtvNJk3ZMiQKJVKZWN9+/aNjRs3lo1973vfi3HjxkX37t2jpqYm+vfvH4sWLYp33nmnyTEPP/zwJmMjR46M1atXR0TE66+/HimlqK+vj/79+5f9XXvttRER8dZbb7Xk6ZZJKZX9u3v37rFo0aKoqamJGTNmxLBhw+Lcc8+Na665Jvr161d2GcSrr746+vXrF7Nnz97nx2+Ofv36xX/5L/8lfve738XatWsjImLTpk1x1VVXxRVXXBFDhw5t1nEanuvO7yHFJZs7yCZFIps7yCZFIZc7yGW5Fl2ue+bMmXHiiSfG448/Hs8880zceuutMW/evFi4cGF8+tOfbpzXpUuXPS4wIuL73/9+fPnLX47p06fHFVdcEQMGDIguXbrEzTff3Kwvke1s+/btERFx+eWXxymnnLLLOSNGjGjxcWtqaiIiYuPGjTFkyJCy20aPHh3Lly+PV155JTZu3BijRo2K6urquPTSS6Ouri4iIl577bW4//7744477og333yz8b4ffPBBfPjhh7F69ero3bt39OvXr8Vr25WGD8uf//znGDJkSNx2222xZcuWOOussxpD1/Ah27hxY6xevToGDRoUBx54YOMxGgJ/8MEHt8qaaHuyKZsUk2zKJsUjl3K5W83f2Gpq/fr1afDgwek//+f/3Di2uy21L33pS2XnQJ5++ulp+PDhTbYojz/++LJ5zd16XL9+fYqIdNVVV+3PU2qi4ctqP/7xj5s1f9GiRSki0n333ZdSSum5555LEbHHv6997Wuttt7LLrssRUR68803U0p/e9339vh//+XAlHyJtDOQzaZkkyKQzaZkk44ml03lmstm7xht27Yt3nvvvejTp0/j2IABA2LQoEGxefPm5h6mUUMLTyk1bnEtWbIknn/++fjHf/zHJvN/9KMfxbp162Lw4MEREbF06dJYsmRJXHLJJY1rmTx5ctx3330xe/bsOPTQQ8vuv2HDhujfv3/jvxta/GGHHbbHdU6cODEOPPDA+NWvfhXTpk3b49z3338/6uvr49BDD42zzz47IiLGjBkTjz/+eJO5V199dbz77rvxL//yL3tdw67s/HwiItatWxcPPPBAjBs3rvH5/7f/9t9i+vTpZfPeeuutOP/88+PLX/5ynH766fGf/tN/Krv9hRde2OOPalEssimbFJNsyibFI5dyuSfNLkbvvvtuDBkyJM4888wYP3589OrVKxYvXhy//OUvY/78+S160IiI0047LRYuXBhnnHFGnHrqqbFq1aq49957Y9SoUfHee+81mT9ixIg44YQT4sILL4zNmzfHHXfcETU1NfH1r3+9cc5dd90VJ5xwQowdOza+8pWvxPDhw2P9+vXx/PPPx9q1a2PZsmWNc6dMmRIR0bgdtzvdu3ePT33qU7F48eK47rrrym6bOXNmDBo0KEaNGhWbNm2KBx54IN54441YtGhR46/sHnzwwU3eyIhovPb7zrfNmTMn5s6dG88991xMnjx5t+v6+te/HitXrowpU6bEoEGDYvXq1XHffffFX/7yl/iXf/mXxnlHH310HH300WX3bXjOo0eP3uWH7P/+3/8bF1988e5fFApFNmWTYpJN2aR45FIu96i5W0ubN29OV1xxRRo/fnw66KCDUs+ePdP48ePT3XffXTavuVuP27dvTzfddFOqra1NVVVVacKECemJJ55oMu/vrzgxf/78NHTo0FRVVZVOPPHEXf4a78qVK9O5556bDjnkkNStW7c0ePDgdNppp6VHH320bF5zL2+YUkoLFy5MpVKp8SoYDebNm5eOPPLI1L1799S3b980bdq0Jtt4u7O716nhl4ZXrFixx/v/4Ac/SB//+MdT//79U9euXdPBBx+czjjjjPTCCy/s9bH3dBWPe+65J/Xo0SNt2rSpWc+DjiebskkxyaZsUjxyKZd7sl/fMWoPe7sUX3vYunVrGjlyZLr66qvb/LGOOeaYdOaZZ7b54+zOUUcdlS655JIOe3wqh2y2L9mkuWSzfckmzSGX7Wtfc9miy3XnqkuXLnHdddfFXXfdtctt0dayadOmWLZsWZMtzvby9NNPx2uvvRZXXXVVhzw+tJRsQjHJJhSPXO5diy7XnbOzzjorzjrrrDZ9jN69e+/TF/9ay9SpU9s0KNAWZBOKSTaheORyz+wYAQAA2SultNNP4AIAAGTGjhEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wA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AIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACy1+rFaPLkyTFmzJjWPmyH++EPfxj9+vWL9957r6OX0maefvrp6NWrV2zYsKGjl0IbkM3KJZudm2xWLtnsvOSycu1PLu0YNcO2bdvi2muvjdmzZ0evXr0axz/88MOYO3duDB8+PKqqqmL48OFxww03xNatW3d5nBdffDGmTZsW/fr1ix49esSYMWPizjvv3K+1rVy5Ms4555wYMGBAVFdXx+GHHx7f/OY3m8xbsWJFTJ06NXr16hX9+vWLL37xi00+MFOnTo0RI0bEzTffvF9rgvYim1BMsgnFI5d713Wfn0FGfvrTn8bvfve7+OpXv1o2/oUvfCEeeeSROO+882LSpEnxi1/8Iurr62PNmjVx//33l8195pln4rOf/WxMmDAh6uvro1evXrFy5cpYu3btPq/rpZdeismTJ8fgwYPjsssui5qamlizZk384Q9/KJu3du3a+PjHPx59+vSJm266Kd5777247bbb4je/+U0sXbo0DjzwwMa5559/flx++eUxd+7cOOigg/Z5bdAeZBOKSTaheOSyGVIrq6urS6NHj27tw3aoadOmpRNOOKFsbOnSpSkiUn19fdn4ZZddlkqlUlq2bFnj2DvvvJMGDhyYzjjjjLRt27ZWWdO2bdvSmDFj0nHHHZf++te/7nHuhRdemKqrq9Pvf//7xrFnn302RUS67777yuauX78+denSJX3nO99plXVSHLIpmxSTbMomxSOXeeayRcVo06ZN6Wtf+1qqra1NBx54YOrfv3/65Cc/mV544YXGOQ0fpJdffjlNnjw5VVdXp0GDBqV58+aVHWvz5s2pvr4+HX300al3796pR48e6YQTTkj/+3//77J5q1atShGRbr311vTP//zP6R//8R9T9+7d08c//vH0m9/8pskaV6xYkWbMmJH69u2bqqqq0sSJE9OPf/zjJvNef/319Prrr+/1Ob///vvpwAMPTHPmzCkbnz9/foqI9PLLL5eN//KXv0wRkf77f//vjWP33HNPioj0yiuvpJRSeu+99/b7A/XUU0+liEhPPvlkSimlv/zlL2nr1q27nDtgwID0uc99rsn4yJEj05QpU5qMT5gwIU2bNm2/1kf7ks0dZJMikc0dZJOikMsd5LJci75jdMEFF8Q999wTM2bMiLvvvjsuv/zyqK6ujhUrVpTN27hxY0ydOjXGjx8f8+fPjyOPPDK+8Y1vxFNPPdU4Z9OmTbFgwYKYPHlyzJs3L+bMmRMbNmyIU045JV566aUmj/3ggw/GnXfeGRdffHFcddVVsXz58jjppJNi/fr1jXNefvnl+OhHPxorVqyIK6+8MubPnx89e/aM6dOnx+OPP152vClTpsSUKVP2+pxfeOGF2LJlSxx99NFl45s3b46IiOrq6rLxHj16NN6vweLFi6N3796xbt26OOKII6JXr17Ru3fvuPDCC+ODDz7Y6xp2ZfHixRERUVVVFZMmTYqePXtGjx49YtasWfHnP/+5cd66devirbfeikmTJjU5xrHHHhu//vWvm4xPnDgxfv7zn+/TuugYsrmDbFIksrmDbFIUcrmDXO6kJS2qT58+6eKLL97jnLq6uhQR6cEHH2wc27x5czrkkEPSjBkzGse2bt2aNm/eXHbfjRs3poEDB6bzzjuvcayhYVdXV6e1a9c2ji9ZsiRFRLr00ksbx6ZMmZLGjh2bPvjgg8ax7du3p+OPPz4dfvjhZY9VW1ubamtr9/qcFyxYkCKiSZt/7LHHUkSkhx56qGz83nvvTRGRxowZ0zg2bty41KNHj9SjR480e/bs9Nhjj6XZs2eniEizZs3a6xp2Zdq0aSkiUk1NTfr85z+fHn300VRfX5+6du2ajj/++LR9+/aU0o7G//fvR4MrrrgiRUTZ65VSSjfddFOKiLR+/fp9WhvtTzZ3kE2KRDZ3kE2KQi53kMtyLSpGtbW1adKkSWndunW7nVNXV5d69erV+EQaTJs2LU2YMGGX99m2bVt6++2304YNG9Kpp56ajjrqqMbbGj5IZ599dpP7HXfccemII45IKaX09ttvp1KplK6//vq0YcOGsr+5c+emiCj7IDbXvHnzdnnf999/P9XW1qaBAwemxx57LK1evTo9/PDDqaamJnXt2jUddthhjXOHDx+eIiJdcMEFZcc4//zzU0SkV199tcXrOumkk1JEpKlTp5aN33zzzSki0rPPPptSSuk//uM/UkSkhx9+uMkx6uvrU0SkjRs3lo03bJXuvK1KccnmDrJJkcjmDrJJUcjlDnJZrkWn0t1yyy2xfPnyGDp0aBx77LExZ86ceOONN5rMGzJkSJRKpbKxvn37xsaNG8vGvve978W4ceOie/fuUVNTE/37949FixbFO++80+SYhx9+eJOxkSNHxurVqyMi4vXXX4+UUtTX10f//v3L/q699tqIiHjrrbda8nTLpJTK/t29e/dYtGhR1NTUxIwZM2LYsGFx7rnnxjXXXBP9+vUruwxiw/bk2WefXXaMc845JyIinn/++RavZ2/HbNg6bJjXsFX69xq2PXfePm14rju/hxSXbO4gmxSJbO4gmxSFXO4gl+VadLnumTNnxoknnhiPP/54PPPMM3HrrbfGvHnzYuHChfHpT3+6cV6XLl12ef+/fzO+//3vx5e//OWYPn16XHHFFTFgwIDo0qVL3HzzzbFy5cqWLCsiIrZv3x4REZdffnmccsopu5wzYsSIFh+3pqYmIv52numQIUPKbhs9enQsX748Xnnlldi4cWOMGjUqqqur49JLL426urrGeYMGDYqXX345Bg4cWHb/AQMGNB67pQYNGhQRsddjHnrooRER8cc//rHJMf74xz9Gv379oqqqqmy84b4HH3xwi9dFx5BN2aSYZFM2KR65lMvdafHvGB166KFx0UUXxUUXXRRvvfVWHH300XHjjTeWfZCa49FHH43hw4fHwoULy5pcQxve2WuvvdZk7NVXX41hw4ZFRMTw4cMjIqJbt27xyU9+skVr2ZMjjzwyIiJWrVoVY8eObXJ7qVSK0aNHN/77ySefjO3bt5etYeLEifHss882flmtwZtvvhkREf3792/xuiZOnBjf/va3Y926dWXjOx9z8ODB0b9///jVr37V5BhLly6No446qsn4qlWr4uCDD96nddFxZLOcbFIUsllONikCuSwnl3/T7FPptm3b1mRLcMCAATFo0KBdbmvtTUML//vWvWTJkt1uw/3oRz8qe9GWLl0aS5YsafwADxgwICZPnhz33XffLtvkzr+Ku3LlymY1+YkTJ8aBBx64yzdiZ++//37U19fHoYceWrYlOHPmzIiI+M53vlM2f8GCBdG1a9eYPHnyXo+9s9NPPz2qqqriu9/9buP/LjQcMyLi5JNPbhybMWNGPPHEE2U/lPW//tf/ildffTU+97nPNTn2Cy+8EB/72MdavCY6hmzKJsUkm7JJ8cilXO5Rc7+MtHHjxtSzZ8/0pS99Kf3zP/9zuv/++9PMmTNTRKT58+c3ztvdD2J96UtfKrtqxgMPPJAiIk2bNi3dd9996corr0z/8A//kEaPHl02r+HLamPHjk3Dhg1L8+bNS9ddd13q169fqqmpSW+++Wbj3Jdffjn17ds31dTUpCuvvDLdf//96frrr0+f+cxn0rhx48rW09yreKSU0mmnnZY+9rGPNRn/3Oc+l772ta+l++67L916663pIx/5SKqqqkqLFy9uMve8885LEZFmzpyZ7rrrrvS5z30uRUS66qqryuZde+21KSLSc889t9d1XXfddSki0sknn5zuuuuu9NWvfjWVSqUmX+xbs2ZNqqmpSYcddli6884700033ZT69u3b5IonKe34QawFCxY045WhCGRTNikm2ZRNikcu5XJPml2MNm/enK644oo0fvz4dNBBB6WePXum8ePHp7vvvrtsXnM/SNu3b0833XRTqq2tTVVVVWnChAnpiSeeaDLv738Qa/78+Wno0KGpqqoqnXjiiWW/xttg5cqV6dxzz02HHHJI6tatWxo8eHA67bTT0qOPPlo2ryUfpIULF6ZSqZTWrFlTNj5v3rx05JFHpu7du6e+ffumadOmpV//+te7PMaWLVvSnDlzUm1tberWrVsaMWJEuv3225vMa/il4RUrVux1Xdu3b0/f+ta30siRI1O3bt3S0KFD09VXX522bNnSZO7y5cvTpz71qdSjR4/0D//wD+nzn/98+tOf/tRk3j333JN69OiRNm3atNfHpxhkUzYpJtmUTYpHLuVyT1p0ue6O8PcfpI6ydevWNHLkyHT11Ve3+WMdc8wx6cwzz2zzx9mdo446Kl1yySUd9vhUDtlsX7JJc8lm+5JNmkMu29e+5rJFl+vOVZcuXeK6666Lu+66K9577702e5xNmzbFsmXL4rrrrmuzx9iTp59+Ol577bW46qqrOuTxoaVkE4pJNqF45HLvWnxVulydddZZcdZZZ7XpY/Tu3XufvvjXWqZOndqmQYG2IJtQTLIJxSOXe2bHCAAAyF4ppZ1+AhcAACAzdowAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5i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BAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQvVYvRpMnT44xY8a09mE73A9/+MPo169fvPfeex29lDbzyiuvRNeuXWP58uUdvRTagGxWLtnsvOSycsll5yablWt/smnHqBm2bdsW1157bcyePTt69erVOP7hhx/G3LlzY/jw4VFVVRXDhw+PG264IbZu3brL47z44osxbdq06NevX/To0SPGjBkTd955536tbeXKlXHOOefEgAEDorq6Og4//PD45je/WTZn6dKlcdFFF8XEiROjW7duUSqVdnmsUaNGxamnnhrXXHPNfq0J2otsQvHIJRSTbO5d131afWZ++tOfxu9+97v46le/Wjb+hS98IR555JE477zzYtKkSfGLX/wi6uvrY82aNXH//feXzX3mmWfis5/9bEyYMCHq6+ujV69esXLlyli7du0+r+ull16KyZMnx+DBg+Oyyy6LmpqaWLNmTfzhD38om/fkk0/GggULYty4cTF8+PB49dVXd3vMCy64ID7zmc/EypUr47DDDtvntUF7kE0oHrmEYpLNZkitrK6uLo0ePbq1D9uhpk2blk444YSysaVLl6aISPX19WXjl112WSqVSmnZsmWNY++8804aOHBgOuOMM9K2bdtaZU3btm1LY8aMSccdd1z661//use5f/rTnxrnXHzxxWlPb/uWLVtS3759mzwvKp9syibFI5dySTHJZp7ZbNGpdO+++25ccsklMWzYsKiqqooBAwbEySefHC+++GKTua+88kp84hOfiB49esTgwYPjlltuKbt9y5Ytcc0118TEiROjT58+0bNnzzjxxBPjueeeK5u3evXqKJVKcdttt8Xtt98etbW1UV1dHXV1dbs8d/C3v/1tnHnmmdGvX7/o3r17TJo0KX7yk580mbdy5cpYuXLlXp/zBx98EE8//XR88pOfLBv/2c9+FhERs2bNKhufNWtWpJTi4Ycfbhz7wQ9+EOvXr48bb7wxDjjggPjLX/4S27dv3+tj78kzzzwTy5cvj2uvvTaqq6vjr3/9a2zbtm2XcwcOHBjV1dXNOm63bt1i8uTJ8eMf/3i/1kf7ks0dZJOikMsd5JIikc0dZLNci4rRBRdcEPfcc0/MmDEj7r777rj88sujuro6VqxYUTZv48aNMXXq1Bg/fnzMnz8/jjzyyPjGN74RTz31VOOcTZs2xYIFC2Ly5Mkxb968mDNnTmzYsCFOOeWUeOmll5o89oMPPhh33nlnXHzxxXHVVVfF8uXL46STTor169c3znn55Zfjox/9aKxYsSKuvPLKmD9/fvTs2TOmT58ejz/+eNnxpkyZElOmTNnrc37hhRdiy5YtcfTRR5eNb968OSKiyRvUo0ePxvs1WLx4cfTu3TvWrVsXRxxxRPTq1St69+4dF154YXzwwQd7XcOuLF68OCIiqqqqYtKkSdGzZ8/o0aNHzJo1K/785z/v0zEbTJw4MZYvXx6bNm3ar+PQfmRzB9mkKORyB7mkSGRzB9ncSUu2l/r06ZMuvvjiPc6pq6tLEZEefPDBxrHNmzenQw45JM2YMaNxbOvWrWnz5s1l9924cWMaOHBgOu+88xrHVq1alSIiVVdXp7Vr1zaOL1myJEVEuvTSSxvHpkyZksaOHZs++OCDxrHt27en448/Ph1++OFlj1VbW5tqa2v3+pwXLFiQIiL95je/KRt/7LHHUkSkhx56qGz83nvvTRGRxowZ0zg2bty41KNHj9SjR480e/bs9Nhjj6XZs2eniEizZs3a6xp2Zdq0aSkiUk1NTfr85z+fHn300VRfX5+6du2ajj/++LR9+/Zd3m9vW48ppfSDH/wgRURasmTJPq2N9iebO8gmRSGXO8glRSKbO8hmuRYVo9ra2jRp0qS0bt263c6pq6tLvXr1avJEpk2bliZMmLDL+2zbti29/fbbacOGDenUU09NRx11VONtDR+ks88+u8n9jjvuuHTEEUeklFJ6++23U6lUStdff33asGFD2d/cuXNTRJR9EJtr3rx5u7zv+++/n2pra9PAgQPTY489llavXp0efvjhVFNTk7p27ZoOO+ywxrnDhw9PEZEuuOCCsmOcf/75KSLSq6++2uJ1nXTSSSki0tSpU8vGb7755hQR6dlnn93l/ZrzQXrqqadSRKRFixa1eF10DNncQTYpCrncQS4pEtncQTbLtehUultuuSWWL18eQ4cOjWOPPTbmzJkTb7zxRpN5Q4YMaXIJvb59+8bGjRvLxr73ve/FuHHjonv37lFTUxP9+/ePRYsWxTvvvNPkmIcffniTsZEjR8bq1asjIuL111+PlFLU19dH//79y/6uvfbaiIh46623WvJ0y6SUyv7dvXv3WLRoUdTU1MSMGTNi2LBhce6558Y111wT/fr1K7sMYsP25Nlnn112jHPOOSciIp5//vkWr2dvx/z5z3/e4mM2aHiuu7sMIsUjmzvIJkUhlzvIJUUimzvIZrkWXa575syZceKJJ8bjjz8ezzzzTNx6660xb968WLhwYXz6059unNelS5c9LjAi4vvf/358+ctfjunTp8cVV1wRAwYMiC5dusTNN9/crC+R7azhy1+XX355nHLKKbucM2LEiBYft6amJiL+dp7pkCFDym4bPXp0LF++PF555ZXYuHFjjBo1Kqqrq+PSSy+Nurq6xnmDBg2Kl19+OQYOHFh2/wEDBjQeu6UGDRoUEdGqx2zQcN+DDz54n49B+5JN2aR45FIuKSbZlM3dafHvGB166KFx0UUXxUUXXRRvvfVWHH300XHjjTeWfZCa49FHH43hw4fHwoULy5pcQxve2WuvvdZk7NVXX41hw4ZFRMTw4cMj4m9Xodj5ihv748gjj4yIiFWrVsXYsWOb3F4qlWL06NGN/37yySdj+/btZWuYOHFiPPvss41fVmvw5ptvRkRE//79W7yuiRMnxre//e1Yt25d2fj+HLPBqlWr4oADDoiRI0fu8zFof7JZTjYpArksJ5cUhWyWk82/afapdNu2bWuyJThgwIAYNGhQ4xUtWqKhhf99616yZMlut+F+9KMflb1oS5cujSVLljR+gAcMGBCTJ0+O++67L/74xz82uf+GDRvK/t3cyxtOnDgxDjzwwPjVr36117nvv/9+1NfXx6GHHlq2JThz5syIiPjOd75TNn/BggXRtWvXmDx58l6PvbPTTz89qqqq4rvf/W7ZpRIXLFgQEREnn3xyi4/Z4IUXXojRo0dHnz599vkYtB/ZlE2KRy7lkmKSTdnck2bvGL377rsxZMiQOPPMM2P8+PHRq1evWLx4cfzyl7+M+fPnt3ixp512WixcuDDOOOOMOPXUU2PVqlVx7733xqhRo+K9995rMn/EiBFxwgknxIUXXhibN2+OO+64I2pq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slmuRcXoggsuiHvuuSdmzJgRd999d1x++eVRXV0dK1asKJu3cePGmDp1aowfPz7mz58fRx55ZHzjG9+Ip556qnHOpk2bYsGCBTF58uSYN29ezJkzJzZs2BCnnHJKvPTSS00e+8EHH4w777wzLr744rjqqqti+fLlcdJJJ8X69esb57z88svx0Y9+NFasWBFXXnllzJ8/P3r27BnTp0+Pxx9/vOx4U6ZMiSlTpuz1Ob/wwguxZcuWOProo8vGN2/eHBHR5A3q0aNH4/0aLF68OHr37h3r1q2LI444Inr16hW9e/eOCy+8MD744IO9rmFXFi9eHBERVVVVMWnSpOjZs2f06NEjZs2aFX/+85/36ZgNJk6cGMuXL49Nmzbt13FoP7K5g2xSFHK5g1xSJLK5g2zupCXbS3369EkXX3zxHufU1dWliEgPPvhg49jmzZvTIYcckmbMmNE4tnXr1rR58+ay+27cuDENHDgwnXfeeY1jq1atShGRqqur09q1axvHlyxZkiIiXXrppY1jU6ZMSWPHjk0ffPBB49j27dvT8ccfnw4//PCyx6qtrU21tbV7fc4LFixIEZF+85vflI0/9thjKSLSQw89VDZ+7733pohIY8aMaRwbN25c6tGjR+rRo0eaPXt2euyxx9Ls2bNTRKRZs2btdQ27Mm3atBQRqaamJn3+859Pjz76aKqvr09du3ZNxx9/fNq+ffsu77e3rceUUvrBD36QIiItWbJkn9ZG+5PNHWSTopDLHeSSIpHNHWSzXIuKUW1tbZo0aVJat27dbufU1dWlXr16NXki06ZNSxMmTNjlfbZt25befvvttGHDhnTqqaemo446qvG2hg/S2Wef3eR+xx13XDriiCNSSim9/fbbqVQqpeuvvz5t2LCh7G/u3LkpIso+iM01b968Xd73/fffT7W1tWngwIHpscceS6tXr04PP/xwqqmpSV27dk2HHXZY49zhw4eniEgXXHBB2THOP//8FBHp1VdfbfG6TjrppBQRaerUqWXjN998c4qI9Oyzz+7yfs35ID311FMpItKiRYtavC46hmzuIJsUhVzuIJcUiWzuIJvlWnQq3S233BLLly+PoUOHxrHHHhtz5syJN954o8m8IUOGNLmEXt++fWPjxo1lY9/73vdi3Lhx0b1796ipqYn+/fvHokWL4p133mlyzMMPP7zJ2MiRI2P16tUREfH6669HSinq6+ujf//+ZX/XXnttRES89dZbLXm6ZVJKZf/u3r17LFq0KGpqamLGjBkxbNiwOPfcc+Oaa66Jfv36lV0GsWF78uyzzy47xjnnnBMREc8//3yL17O3Y/785z9v8TEbNDzX3V0GkeKRzR1kk6KQyx3kkiKRzR1ks1yLLtc9c+bMOPHEE+Pxxx+PZ555Jm699daYN29eLFy4MD796U83zuvSpcseFxgR8f3vfz++/OUvx/Tp0+OKK66IAQMGRJcuXeLmm29u1pfIdtbw5a/LL788TjnllF3OGTFiRIuPW1NTExF/O890yJAhZbeNHj06li9fHq+88kps3LgxRo0aFdXV1XHppZdGXV1d47xBgwbFyy+/HAMHDiy7/4ABAxqP3VKDBg2KiGjVYzZouO/BBx+8z8egfcmmbFI8cimXFJNsyubutPh3jA499NC46KKL4qKLLoq33norjj766LjxxhvLPkjN8eijj8bw4cNj4cKFZU2uoQ3v7LXXXmsy9uqrr8awYcMiImL48OER8berUOx8xY39ceSRR0ZExKpVq2Ls2LFNbi+VSjF69OjGfz/55JOxffv2sjVMnDgxnn322cYvqzV48803IyKif//+LV7XxIkT49vf/nasW7eubHx/jtlg1apVccABB8TIkSP3+Ri0P9ksJ5sUgVyWk0uKQjbLyebfNPtUum3btjXZEhwwYEAMGjSo8YoWLdHQwv++dS9ZsmS323A/+tGPyl60pUuXxpIlSxo/wAMGDIjJkyfHfffdF3/84x+b3H/Dhg1l/27u5Q0nTpwYBx54YPzqV7/a69z3338/6uvr49BDDy3bEpw5c2ZERHznO98pm79gwYLo2rVrTJ48ea/H3tnpp58eVVVV8d3vfrfsUokLFiyIiIiTTz65xcds8MILL8To0aOjT58++3wM2o9syibFI5dySTHJpmzuSbN3jN59990YMmRInHnmmTF+/Pjo1atXLF68OH75y1/G/PnzW7zY0047LRYuXBhnnHFGnHrqqbFq1aq49957Y9SoUfHee+81mT9ixIg44YQT4sILL4zNmzfHHXfcETU1NfH1r3+9cc5dd90VJ5xwQowdOza+8pWvxPDhw2P9+vXx/PPPx9q1a2PZsmWNcxsubdhwTufudO/ePT71qU/F4sWL47rrriu7bebMmTFo0KAY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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure(figsize=(10,10))\n", - "for i,m in enumerate(masks):\n", - " ax = plt.subplot(4,4,i+1)\n", - " ax.matshow(mask,cmap=plt.cm.Greys)\n", - " plt.axis('off')\n", - " plt.title(f'shape: {m.shape}')\n", - "\n", - "plt.tight_layout()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [], - "source": [ - "from functools import reduce\n", - "def max_common_intersection(mask_list):\n", - " min_x = np.min([m.shape[0] for m in mask_list])\n", - " min_y = np.min([m.shape[1] for m in mask_list])\n", - "\n", - " cropped_masks = []\n", - " for m in masks:\n", - " if m.shape[0]> min_x and m.shape[1]>min_y:\n", - " cropped_masks.append(m[(m.shape[0]-min_x)//2:-(m.shape[0]-min_x)//2,\n", - " (m.shape[1]-min_y)//2:-(m.shape[1]-min_y)//2])\n", - "\n", - " elif m.shape[0] == min_x and m.shape[1]>min_y:\n", - " cropped_masks.append(m[:,(m.shape[1]-min_y)//2:-(m.shape[1]-min_y)//2])\n", - "\n", - " elif m.shape[0]> min_x and m.shape[1]== min_y:\n", - " cropped_masks.append(m[(m.shape[0]-min_x)//2:-(m.shape[0]-min_x)//2,:])\n", - "\n", - " else:\n", - " cropped_masks.append(m)\n", - " \n", - " # performs elementwise logical and\n", - " intersection = reduce(lambda x, y: np.logical_and(x, y), cropped_masks)\n", - "\n", - "\n", - " return intersection" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [], - "source": [ - "cm = max_common_intersection(masks)" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.matshow(cm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "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.8" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "a004f9109620e037dd6eb32a5065768d5476b766f6a5e98b9519dfa4bc5bb4ce" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/dim_reduction/pipeline.py b/dim_reduction/pipeline.py deleted file mode 100644 index a1ad191..0000000 --- a/dim_reduction/pipeline.py +++ /dev/null @@ -1,166 +0,0 @@ -import loaders -import args - -import glob -import numpy as np -import pandas as pd -from scipy import io -from sklearn.pipeline import Pipeline -from sklearn.decomposition import PCA -from sklearn.preprocessing import StandardScaler -import matplotlib.pyplot as plt - -import vsdi_preprocessing -import vsdi_visualization -import loaders - -#################################### - -##################################### -############### MAIN ################ -##################################### - -# Define paths -path = '/home/danteam/Documents/BScThesis' -data = f'{path}/data' -reports = f'{path}/reports' -figures = f'{reports}/figures' - -# Get arguments from command line -parameters = args.getArgs() -subject = parameters.subject -day = parameters.day -session = parameters.session - -def save_vsdi(): - vsdi1 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi3 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi5 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi7 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/vsdi_ATC{session}.mat')[0])['vsdi_data'] - - vsdi1 = vsdi1[:,:,0:29999] - vsdi3 = vsdi3[:,:,0:29999] - vsdi5 = vsdi5[:,:,0:29999] - vsdi7 = vsdi7[:,:,0:29999] - - vsdi = np.concatenate((vsdi1, vsdi3, vsdi5, vsdi7), axis = 2) - - del(vsdi1) - del(vsdi3) - del(vsdi5) - del(vsdi7) - - # Outliers correction - vsdi_clean = vsdi_preprocessing.clean_outliers(vsdi, nsigma=5) - - # Hemodynamics correction - vsdi_clean = vsdi_preprocessing.clean_hemodynamic_pca(vsdi_clean, bimodal_th = 0.6, verbose = True) - - del(vsdi) - - ## Mask to select just subject cortex - r = np.loadtxt(f'{data}/Patterns/mask_A0{subject}.csv', delimiter=',', dtype='bool') - - X = vsdi_clean.transpose(2, 0, 1) - X = X[:,r] - - del(vsdi_clean) - - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=10)) - ]) - - out = pipe.fit(X) - - f = out.named_steps['pca'].components_ - factor_scores = pipe.named_steps['pca'].transform(X) - - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_timecourse_part1.csv', factor_scores, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_fingerprint_part1.csv', f, delimiter=",") - - return 0 - -def save_behav(): - atc1 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/ATC{session}.mat') - atc3 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/ATC{session}.mat') - atc5 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/ATC{session}.mat') - atc7 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/ATC{session}.mat') - b_data1 = loaders.extract_behavioural_data(atc1) - b_data3 = loaders.extract_behavioural_data(atc3) - b_data5 = loaders.extract_behavioural_data(atc5) - b_data7 = loaders.extract_behavioural_data(atc7) - - del(atc1) - del(atc3) - del(atc5) - del(atc7) - - d1 = vsdi_preprocessing.design_matrix(b_data1) - d3 = vsdi_preprocessing.design_matrix(b_data3) - d5 = vsdi_preprocessing.design_matrix(b_data5) - d7 = vsdi_preprocessing.design_matrix(b_data7) - - d1 = d1[0:29999,:] - d3 = d3[0:29999,:] - d5 = d5[0:29999,:] - d7 = d7[0:29999,:] - - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d1_part{session}.csv', d1, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d3_part{session}.csv', d3, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d5_part{session}.csv', d5, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d7_part{session}.csv', d7, delimiter=",") - - return 0 - -def mask_norm(masks, threshold=0.5): - mask_mean = np.mean(masks, axis=0) - mask_mean[mask_mean > threshold] = 1 - mask_mean[mask_mean <= threshold] = 0 - - return mask_mean - -def save_mask(): - r1 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day1.csv', r1, delimiter=",") - r3 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day3.csv', r3, delimiter=",") - r5 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day5.csv', r5, delimiter=",") - r7 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day7.csv', r7, delimiter=",") - - del(r1) - del(r3) - del(r5) - del(r7) - - r1 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day1.csv', delimiter=",") - r3 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day3.csv', delimiter=",") - r5 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day5.csv', delimiter=",") - r7 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day7.csv', delimiter=",") - - print(r1.shape, r3.shape, r5.shape, r7.shape) - - masks = np.stack([r1, r3, r5, r7]) - mask_mean = mask_norm(masks) - - np.savetxt(f'/home/danteam/Documents/BScThesis/data/Patterns/mask_A0{subject}.csv', mask_mean.astype(int), fmt='%i', delimiter=",") - - return 0 - - -def main(): - # print(f'Saving Mask A0{subject} part {session}') - # save_mask() - print(f'Saving VSDI subject A0{subject} part {session}') - save_vsdi() - print(f'Saving Design matrices A0{subject} part {session}') - save_behav() - - return 0 - - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/dim_reduction/vsdi.py b/dim_reduction/vsdi.py deleted file mode 100644 index abda7e0..0000000 --- a/dim_reduction/vsdi.py +++ /dev/null @@ -1,164 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import matplotlib.pyplot as plt -import numpy as np -from scipy import stats -from scipy.stats import norm -from sklearn.decomposition import PCA -import seaborn as sns -sns.set_theme(context='notebook', - style='white', - font_scale=1.5, - rc = {'axes.spines.top':False,'axes.spines.right':False, - 'image.cmap':plt.cm.jet}) - -########################################################## -####################### VSDI CLASS ####################### -########################################################## - -class VSDI: - def __init__(self, vsdi, raw_mask): - """ - Constructor for VSDI class - """ - self.vsdi = self.correct_outliers(vsdi) - self.raw_mask = raw_mask - self.X = self.vsdi.transpose(2,0,1) # reshape in time x image format - self.T,self.h,self.w = self.X.shape # saves time, height and width for future use - self.X = self.X[:,self.raw_mask] # select only cortex pixels, returns a flattened image - - def time_course(self, start_time=0, end_time=600, framerate=50): - """ - Plot time course of a single PC - """ - plt.figure(figsize=(10, 5)) - t = np.linspace(start_time, end_time, int((end_time - start_time) * framerate - 1)) - plt.plot(t, self.vsdi) - plt.xlabel('Time (s)') - plt.ylabel('PC activation (a.u.)') - plt.show() - - def create_frame(self, t): - """ - Create a frame of the VSDI data - """ - plt.figure(figsize=(10, 10)) - plt.imshow(self.vsdi[:, :, t], cmap=plt.cm.inferno) - - def pca(self, n_components=50): - """ - Perform PCA on the VSDI data - """ - pca = PCA(n_components=n_components) - pca.fit(self.X) - - return pca - - def pca_projection(self, pca, num_pc): - """ - Plot the projection of the data onto the first 10 PCs - """ - PCs = pca.components_[:num_pc].T - Y = self.X @ PCs # compute the PC timecourse, by projecting the original data on each component - return Y - - def cumulative_explained_variance(self, pca): - """ - Plot cumulative explained variance - """ - evr = pca.explained_variance_ratio_ - c_evr = np.cumsum(evr) - plt.figure(figsize=(6, 6)) - plt.axhline(0.9, linestyle='--', label='90% explained variance') - plt.plot(range(1, len(c_evr) + 1), c_evr) - plt.legend() - plt.xlabel('# of components') - plt.ylabel('EVR') - - def fingerprint(self, pca, num_pc = 10): - """ - Plot topographic organzation of the weights of these ten components - """ - PCs = pca.components_[:num_pc] - plt.figure(figsize=(10, 5)) - for i, pc in enumerate(PCs): - plt.subplot(2, 5, i + 1) - plt.title(f'PC {i + 1}') - reshaped_pc = np.full((self.h, self.w), np.nan) - reshaped_pc[np.where(self.raw_mask)] = pc - plt.imshow(reshaped_pc, aspect='auto', cmap=plt.cm.jet) - plt.axis('off') - - def first_last_subsets(self, arr): - """ - Get first and last frame of each subset - """ - subsets = [] - start = 0 - end = 0 - while end < len(arr): - while end + 1 < len(arr) and arr[end + 1] - arr[start] == end - start + 1: - end += 1 - subsets.append((arr[start], arr[end])) - start = end = end + 1 - return np.array(subsets) - - def correct_outliers(self, vsdi, nsigma=4): - """ - Correct outliers in VSDI data - """ - # Array with average value of all frames in vsdi - mean_vsdi = np.mean(vsdi, axis=(0,1)) - std_vsdi = vsdi.std() - - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((mean_vsdi > nsigma*std_vsdi) | (mean_vsdi < -nsigma*std_vsdi)).ravel() - - # Get first and last frame of each subset - outliers_subsets = self.first_last_subsets(arr = outliers) - - # Set outlier frames to the mean between the previous and next frame - for i in range(len(outliers_subsets)): - start = outliers_subsets[i][0] - end = outliers_subsets[i][1] - if start == 0: - vsdi[:,:,start:end+1] = np.tile(vsdi[:,:,end+1][:, :, np.newaxis], (1, 1, end - start + 1)) - elif end == len(mean_vsdi)-1: - vsdi[:,:,start:end+1] = np.tile(vsdi[:,:,start-1][:, :, np.newaxis], (1, 1, end - start + 1)) - else: - average = np.divide(np.add(vsdi[:,:,start-1][:, :, np.newaxis], vsdi[:,:,end+1][:, :, np.newaxis]), 2) - vsdi[:,:,start:end+1] = average - return vsdi - - def bimodality_test(self, distribution): - """ - Test for bimodality using moving average to smooth the histogram - and get the x-axis location of the highest point in the histogram - """ - # Create a histogram - n, bins, patches = plt.hist(distribution, bins=1000) - # Define the window size for the moving average - window_size = 5 - # Create the moving average kernel - kernel = np.ones(window_size) / window_size - # Convolve the histogram data with the moving average kernel - smoothed = np.convolve(n, kernel, mode='same') - bins_adjusted = bins[:-1] - - # Find the x-axis location of the highest point in the histogram - x_max = bins_adjusted[np.argmax(smoothed)] - - return x_max - - def bimodal_components(self, Y, threshold=1): - """ - Get bimodal components - """ - bimodal_components = [] - for i in range(Y.shape[1]): - x_max = self.bimodality_test(Y[:,i]) - if abs(x_max) > threshold: - bimodal_components.append([i, x_max]) - - return bimodal_components \ No newline at end of file diff --git a/dim_reduction/vsdi_preprocessing.py b/dim_reduction/vsdi_preprocessing.py deleted file mode 100644 index 10a6ddc..0000000 --- a/dim_reduction/vsdi_preprocessing.py +++ /dev/null @@ -1,383 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import numpy as np -from sklearn.decomposition import PCA, FastICA -from sklearn.preprocessing import StandardScaler -from sklearn.pipeline import Pipeline -import scipy.stats as stats -import statsmodels.api as sm - - -########################################################## - -def peak_distance(component, smooth_window_size, hist_nbins): - # Create a histogram - n, bins = np.histogram(component, bins=hist_nbins) - # Define the window size for the moving average - window_size = smooth_window_size - # Create the moving average kernel - kernel = np.ones(window_size) / window_size - # Convolve the histogram data with the moving average kernel - smoothed = np.convolve(n, kernel, mode='same') - bins_adjusted = bins[:-1] - # Find the x-axis location of the highest point in the histogram - x_max = bins_adjusted[np.argmax(smoothed)] - - return x_max - - -def check_bimodal(components, th=1.0, smooth_window_size=5, hist_nbins=1000): - """ - Test for bimodality using moving average to smooth the histogram - and get the x-axis location of the highest point in the histogram - - Parameters - ---------- - components : numpy ndarray (components, time) - Timecourse of a single component - threshold : float - Threshold for bimodal distribution identification (distance from peak to zero) - - Returns - ------- - bimodal_components : list - List of components that are bimodal (1 if bimodal, 0 if not) - """ - # Initialize bimodal_components list - bimodal_components = np.zeros(components.shape[0]) - for i in range(components.shape[0]): - # Get peak distance - x_max = peak_distance(components[i], smooth_window_size, hist_nbins) - # Check if peak distance is above threshold - if abs(x_max) > th: - bimodal_components[i] = 1 - - return bimodal_components - - -def clean_hemodynamic_pca(vsdi, n_components=50, bimodal_th=1, - smooth_window=5, hist_nbins=1000, verbose=False): - """ - Clean hemodynamic noise from vsdi data - - Parameters - ---------- - vsdi : numpy array - vsdi data in format (time, pixels_y, pixels_X) - n_components : int - Number of components to keep after PCA - bimodal_th : float - Threshold for bimodal distribution identification - smooth_window : int - Window size for smoothing the histogram of timecourse distribution - hist_nbins : int - Number of bins for histogram of timecourse distribution - - Returns - ------- - clean_vsdi : numpy array in the same format as vsdi input - vsdi data with hemodynamic noise removed - """ - # reshape vsdi data to (time, pixels) - vsdi = vsdi.transpose(2, 0, 1) - # store original shape - vsdi_shape = vsdi.shape - # flatten 2d pixels to array - vsdi = vsdi.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # put out-of-mask values to zero - - # run PCA - pca = PCA(n_components=n_components) - # fit PCA to vsdi data and project it to the new space - timecourses = pca.fit_transform(vsdi) - - # get bimodal components indexes - bad_components = check_bimodal(timecourses.T, th=bimodal_th, - smooth_window_size=smooth_window, - hist_nbins=hist_nbins) - - if verbose: - with open('log.txt', 'a') as f: - # Print explained variance ratio - f.write( - f'{sum(pca.explained_variance_ratio_[np.where(bad_components)]):.4f} ') - # Print number of components - f.write(f'{sum(bad_components):.0f}\n') - - # get clean timecourses and components - good_timecourses = timecourses[:, np.logical_not(bad_components)] - good_components = pca.components_[np.logical_not(bad_components)] - - # reconstruct vsdi data - clean_vsdi = good_timecourses @ good_components - clean_vsdi = clean_vsdi.reshape( - vsdi_shape[0], vsdi_shape[1], vsdi_shape[2]) - clean_vsdi = clean_vsdi.transpose(1, 2, 0) - - return clean_vsdi - - -def clean_hemodynamics(vsdi, n_components=50, bimodal_th=0.8, ica_max_iter=200, - smooth_window=5, hist_nbins=1000, verbose=False): - """ - Clean hemodynamic noise from vsdi data - - Parameters - ---------- - vsdi : numpy array - vsdi data in format (time, pixels_y, pixels_X) - n_components : int - Number of components to keep after PCA - bimodal_th : float - Threshold for bimodal distribution identification - smooth_window : int - Window size for smoothing the histogram of timecourse distribution - hist_nbins : int - Number of bins for histogram of timecourse distribution - - Returns - ------- - clean_vsdi : numpy array in the same format as vsdi input - vsdi data with hemodynamic noise removed - """ - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - vsdi_shape = vsdi.shape - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA and ICA - pipe = Pipeline([ - ('pca', PCA(n_components=n_components)), - ('ica', FastICA(n_components=n_components, max_iter=ica_max_iter, - random_state=88, whiten='unit-variance')) - ]) - - # Fit the pipeline to vsdi data - timecourses = pipe.fit_transform(X) - - # get bimodal components indexes - bad_components = check_bimodal(timecourses.T, th=bimodal_th, - smooth_window_size=smooth_window, - hist_nbins=hist_nbins) - - if verbose: - with open('log.txt', 'a') as f: - # Print number of components - f.write(f'{sum(bad_components):.0f}\n') - - # get clean timecourses and components - good_timecourses = timecourses[:, np.logical_not(bad_components)] - good_components = pipe.named_steps['ica'].components_[ - np.logical_not(bad_components)] - - # reconstruct vsdi data - clean_vsdi = good_components @ pipe.named_steps['pca'].components_ - clean_vsdi = good_timecourses @ clean_vsdi - clean_vsdi = clean_vsdi.reshape( - vsdi_shape[0], vsdi_shape[1], vsdi_shape[2]) - - return clean_vsdi - - -def find_outliers_old(vsdi, mean_vsdi, std_vsdi, nsigma=4): - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((mean_vsdi > nsigma*std_vsdi) - | (mean_vsdi < -nsigma*std_vsdi)).ravel() - - subsets = [] - start = 0 - end = 0 - - # Iterate over array - while end < len(outliers): - # Get first and last frame of each subset - while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: - end += 1 - # Save first and last frame of each outlier subset - subsets.append((outliers[start], outliers[end])) - start = end = end + 1 - - return np.array(subsets) - - -def find_outliers(vsdi, nsigma=6): - mean_vsdi = np.mean(vsdi, axis=(0, 1)) - # How many standard deviations away a value is from the mean - zscore = stats.zscore(mean_vsdi, axis=0, ddof=0, nan_policy='propagate') - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((zscore > nsigma) | (zscore < -nsigma)).ravel() - - subsets = [] - start = 0 - end = 0 - - # Iterate over array - while end < len(outliers): - # Get first and last frame of each subset - while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: - end += 1 - # Save first and last frame of each outlier subset - subsets.append((outliers[start], outliers[end])) - start = end = end + 1 - - return np.array(subsets) - - -def clean_outliers(vsdi, nsigma=6): - """ - Correct outliers in VSDI data - - Parameters - ---------- - vsdi : numpy ndarray - vsdi data in format (h, w, time) - nsigma : float - Number of standard deviations to consider an outlier - - Returns - ------- - vsdi : numpy ndarray - vsdi data with outliers corrected - """ - vsdi = vsdi.copy() - # Get first and last frame of each subset - outliers_subsets = find_outliers(vsdi, nsigma) - - # Set outlier frames to the mean between the previous and next frame - for i in range(len(outliers_subsets)): - start = outliers_subsets[i][0] - end = outliers_subsets[i][1] - if start == 0: - vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, end+1] - [:, :, np.newaxis], (1, 1, end - start + 1)) - elif end == vsdi.shape[2]-1: - vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, start-1] - [:, :, np.newaxis], (1, 1, end - start + 1)) - else: - average = np.divide(np.add( - vsdi[:, :, (start-1)][:, :, np.newaxis], vsdi[:, :, (end+1)][:, :, np.newaxis]), 2) - vsdi[:, :, start:end+1] = average - return vsdi - - -def design_matrix(b_data): - # Design matrix - # Returns a matrix of size (time, 6) with the following columns: - # 0: CS+ (2s) - # 1: CS+ trace (1s) - # 2: CS- (2s) - # 3: CS- trace (1s) - # 4: Reward (1s) - # 5: Lick - - fps = 50 - - Lick = b_data['Lick'] - CSp = b_data['CSp'] - CSn = b_data['CSn'] - frames = b_data['frames'] - - length = len(frames) - X = np.zeros((length, 6)) - - # Iterate over lick events - for i in range(len(Lick)): - frame = np.argmin(np.abs(frames - Lick[i])) - X[frame:frame+4, 5] = 1 - - # Iterate over CSp events - for i in range(len(CSp)): - frame = np.argmin(np.abs(frames - CSp[i])) - X[frame:frame + (fps * 2), 0] = 1 - frame += (fps * 2) + 1 - X[frame:frame + (fps * 1), 1] = 1 - frame += (fps * 1) + 1 - X[frame:frame + (fps * 1), 4] = 1 - - # Iterate over CSn events - for i in range(len(CSn)): - frame = np.argmin(np.abs(frames - CSn[i])) - X[frame:frame + (fps * 2), 2] = 1 - frame += (fps * 2) + 1 - X[frame:frame + (fps * 1), 3] = 1 - - return X - - -def pca(vsdi, raw_mask=None, n_comp=10, normalize=True): - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - # vsdi_shape = vsdi.shape - if raw_mask is not None: - # put out-of-mask values to zero - X = X[:, raw_mask] - else: - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=10)) - ]) - - # Fit the pipeline to vsdi data - out = pipe.fit(X) - fingerprints = out.named_steps['pca'].components_ - timecourses = fingerprints @ X.T - - return fingerprints, timecourses - - -def pca_ica(vsdi, raw_mask, n_comp=50, ica_max_iter=200): - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - # vsdi_shape = vsdi.shape - if raw_mask is not None: - # put out-of-mask values to zero - X = X[:, raw_mask] - else: - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA and ICA - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=n_comp)), - ('ica', FastICA(n_components=n_comp, max_iter=ica_max_iter, - random_state=1, whiten='unit-variance')) - ]) - - out = pipe.fit(X) - fingerprints = out.named_steps["ica"].components_ @ out.named_steps["pca"].components_ - timecourses = fingerprints @ X.T - - return fingerprints, timecourses - - -def glm(Y, X): - # Fit Gaussian GLMs - X = sm.add_constant(X) - model = sm.GLM(Y, X, family=sm.families.Gaussian()) - results = model.fit() - - return results - - -def merge_masks(masks, threshold=0.5): - """ - Merge masks by voting majority / logical OR - - Input: masks (n_masks, h, w) - Output: mask_mean (h, w) - """ - mask_mean = np.mean(masks, axis=0) - mask_mean[mask_mean > threshold] = 1 - mask_mean[mask_mean <= threshold] = 0 - return mask_mean diff --git a/dim_reduction/vsdi_visualization.py b/dim_reduction/vsdi_visualization.py deleted file mode 100644 index 961686d..0000000 --- a/dim_reduction/vsdi_visualization.py +++ /dev/null @@ -1,170 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import matplotlib.pyplot as plt -import numpy as np -import seaborn as sns -from scipy.stats import sem -from scipy.ndimage import gaussian_filter1d -sns.set_theme(context='notebook', - style='white', - font_scale=1.5, - rc = {'axes.spines.top':False,'axes.spines.right':False, - 'image.cmap':plt.cm.jet}) - -########################################################## - -def plot_timecourse_histograms(timecourses, nbins_rule = 'freedman-diaconis'): - """ - Plot the histogram of the timecourses of the first 10 PCs - - Parameters - ---------- - timecourses : numpy.ndarray (n_timepoints, n_components) - Timecourses of the first 10 PCs - num_bins : int - Number of bins for the histogram - """ - plt.figure(figsize=(15, 25)) - - for i, tc in enumerate(timecourses.T): - # Freedman-Diaconis rulex - if nbins_rule == 'freedman-diaconis': - iqr = np.quantile(tc, 0.75) - np.quantile(tc, 0.25) - bin_width = (2 * iqr) / (len(tc) ** (1 / 3)) - nbins = int(np.ceil((tc.max() - tc.min()) / bin_width)) - - # Plot histogram - plt.subplot(5, 2, i+1) - plt.title(f'PC {i+1}') - plt.hist(tc, bins=nbins) - plt.xlim(-2*np.std(tc), 2*np.std(tc)) - -def plot_timecourses(timecourses): - """ - Plot the timecourses of the first 10 PCs - - Parameters - ---------- - timecourses : numpy.ndarray (n_timepoints, n_components) - Timecourses of the first 10 PCs - """ - start_time = 0 - end_time = 600 - # framerate = 50 - t = np.linspace(start_time,end_time,timecourses.shape[0]) - - plt.figure(figsize=(15, 25)) - for i, tc in enumerate(timecourses.T): - plt.subplot(5, 2, i+1) - plt.plot(t, tc) - plt.title(f'PC {i+1}') - -def plot_fingerprints(PCs, raw_mask): - """ - Plot the topographic organization of the weights of the first 10 PCs - - Parameters - ---------- - PCs : numpy ndarray - PCs matrix (n_components, n_pixels) - raw_mask : ndarray - Mask of the brain cortex - """ - plt.figure(figsize=(10,5)) - for i, pc in enumerate(PCs): - plt.subplot(2,5,i+1) - plt.title(f'PC {i+1}') - reshaped_pc = np.full((raw_mask.shape[0], raw_mask.shape[1]), np.nan) - reshaped_pc[np.where(raw_mask)] = pc - plt.imshow(reshaped_pc, aspect='auto', cmap=plt.cm.jet) - plt.axis('off') - -def create_frame(vsdi, t): - # VSDI - Should be already masked - plt.imshow(vsdi[:,:,t], cmap=plt.cm.jet) - plt.axis('off') - -def fingerprint_gif(vsdi, to, tf, step): - plt.figure(figsize=(20,15)) - for i, t in enumerate(range(to, tf, step)): - plt.subplot(1, step, i+1) - create_frame(vsdi, t) - -def plot_betas(results): - # Get the beta coefficients and their names - coefficients = results.params - names = ['Intercept'] + ["CS+ Onset", "CS+", "CS- Onset", "CS-", "Reward", "Lick"] - colors = ['#3C3C3C', '#1E70AA', '#8BBEE2', '#C11910', '#FFB3AF', 'green','#832F95'] - - # Plot the beta coefficients - plt.figure(figsize=(2, 3)) - plt.rc('xtick',labelsize=9) - plt.rc('ytick',labelsize=9) - plt.bar(names, coefficients, color=colors) - plt.xticks(ticks=range(len(names)), labels=names, rotation=-90) - # plt.show() - -def convert_pvalue_to_asterisks(pvalue): - if pvalue <= 0.0001: - return "****" - elif pvalue <= 0.001: - return "***" - elif pvalue <= 0.01: - return "**" - elif pvalue <= 0.05: - return "*" - return "" - -def timecourse_around(t, d, to, tf, feature, comp): - """ - Plot the timecourse of a given feature around a given timepoint - - Parameters - ---------- - t : numpy.ndarray (n_components, n_timepoints) - Timecourses of the first 10 PCs - d : numpy.ndarray (n_timepoints, n_features) - Design matrix - to : int - Start timepoint of interest - tf : int - Final timepoint - feature : int - Feature of interest in the following order: - ["CS+ Onset", "CS+", "CS- Onset", "CS-", "Reward", "Lick"] - comp : int - Principal component to plot - """ - - names = ["CS+", "CS+ Onset", "CS-", "CS- Onset", "Reward", "Lick"] - colors = ['#1E70AA', '#8BBEE2', '#C11910', '#FFB3AF', 'green', '#832F95'] - frame_rate = 50 - start_time = to - end_time = tf - peri_Y = [] # empty list for peri-lick timecourses - - for i, j in enumerate(d[:,feature]): - try: - if (j == 1) and d[(i-1),feature] == 0: - peri_Y.append(t[:,(i+(frame_rate*start_time)):(i+(frame_rate*end_time))]) # saves the slice of Y - except: - pass - - peri_Y = np.asarray(peri_Y) - mean_Y = np.mean(peri_Y, axis=0) # average over licks - error = sem(peri_Y, axis=0) # compute sem over licks - - y = mean_Y[comp-1,:] - err = error[comp-1,:] - - y = gaussian_filter1d(y,2) - err = gaussian_filter1d(err,2) - - t = np.linspace(start_time, end_time, int((end_time-start_time)*frame_rate)) - - plt.plot(t, y, color = colors[feature]) - plt.fill_between(t, y-err, y+err, alpha=0.2, color=colors[feature], cmap="Blues") - plt.xticks(np.arange(start_time, end_time+1, 1.0)) - plt.axvline(x=0,linestyle='--', color = "black", label=f'{names[feature]}') - plt.legend(prop={'size': 6}) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..747ffb7 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 0000000..61fa393 --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,54 @@ +/* Limit size of html logo */ +.wy-side-nav-search > a img.logo { + height: 80px; +} + +/* Hide "On Read the Docs", "On GitHub", and "Search" section from versions menu */ +div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(2) { + display: none; +} +div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(3) { + display: none; +} +div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { + display: none; +} + +/* Sidebar selected style */ +.wy-menu-vertical li.current > a { + background: #ffffff; +} +.wy-menu-vertical li.current > ul { + background: #F0E3DF; +} + +/* Sidebar style */ +.wy-side-nav-search, +.wy-nav-top, +.wy-side-scroll { + background: #202029; +} + +.wy-nav-top, +.wy-side-nav-search a, .wy-side-nav-search a:visited, .wy-side-nav-search a:hover, +.wy-nav-top a, .wy-nav-top a:visited, .wy-nav-top a:hover, +.wy-side-scroll a, .wy-side-scroll a:visited, .wy-side-scroll a:hover { + color: #F0F4F4 +} + +.rst-versions a, .rst-versions a:visited, .rst-versions a:hover { + color: #fcfcfc +} + +/* Make main content larger */ +body > div:nth-child(1) > section > div { + max-width: 1200px; +} + +/* Links */ +a, a:visited { + color: black; +} +a:hover { + color: #2980B9; +} \ No newline at end of file diff --git a/docs/source/_static/diagram.dot b/docs/source/_static/diagram.dot new file mode 100644 index 0000000..6697b7a --- /dev/null +++ b/docs/source/_static/diagram.dot @@ -0,0 +1,14 @@ +digraph architecture { + rankdir=LR; + node [shape=box, style=filled, color=lightblue]; + + "VSDI data" [shape=ellipse, color=lightgrey]; + "VSDI data" -> "io"; + "io" -> "session"; + "io" -> "utils"; + "io" -> "dimensionality\nreduction"; + "session" -> "utils"; + "session" -> "dimensionality\nreduction"; + "dimensionality\nreduction" -> "visualization"; + "utils" -> "visualization"; +} \ No newline at end of file diff --git a/docs/source/_static/diagram.png b/docs/source/_static/diagram.png new file mode 100644 index 0000000..79b1a16 Binary files /dev/null and b/docs/source/_static/diagram.png differ diff --git a/docs/source/_static/favicon/favicon.ico b/docs/source/_static/favicon/favicon.ico new file mode 100644 index 0000000..6b1f190 Binary files /dev/null and b/docs/source/_static/favicon/favicon.ico differ diff --git a/docs/source/_templates/apidoc.rst b/docs/source/_templates/apidoc.rst new file mode 100644 index 0000000..18460ed --- /dev/null +++ b/docs/source/_templates/apidoc.rst @@ -0,0 +1,6 @@ +{{ fullname | escape | underline }} + +.. automodule:: {{ fullname }} + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/_templates/breadcrumbs.html b/docs/source/_templates/breadcrumbs.html new file mode 100644 index 0000000..339f008 --- /dev/null +++ b/docs/source/_templates/breadcrumbs.html @@ -0,0 +1,4 @@ +{%- extends "sphinx_rtd_theme/breadcrumbs.html" %} + +{% block breadcrumbs_aside %} +{% endblock %} \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..d695b8d --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,53 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import os +import sys +sys.path.insert(0, os.path.abspath('../..')) + +project = 'VSDI Pipeline' +copyright = '2023, NeuroNetMem' +author = 'NeuroNetMem' +release = '0.1.0' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +# extensions = ['sphinx.ext.autodoc', +extensions = ["autodocsumm", + "numpydoc", + "sphinx.ext.graphviz"] + +autodoc_default_options = {"autosummary": True} +numpydoc_show_class_members = False + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +graphviz_dot = 'dot' +html_theme = 'sphinx_rtd_theme' +# html_theme = 'pydata_sphinx_theme' +# html_context = {"default_mode": "light"} +html_favicon = '_static/favicon/favicon.ico' +html_logo = '_static/favicon/favicon.ico' +html_show_sourcelink = False +html_static_path = ['_static'] + +def setup(app): + app.add_css_file("custom.css") + +# ----------------------------------------------------------------------------- +# Autosummary +# ----------------------------------------------------------------------------- + +# Make numpydoc to generate plots for example sections +# numpydoc_use_plots = True +# autosummary_generate = True diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..bdb823f --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,22 @@ +.. VSDI Pipeline documentation master file, created by + sphinx-quickstart on Mon Jun 12 21:54:34 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +VSDI Pipeline +========================================= + +Package for handling voltage sensitive dye imaging data + +.. image:: _static/diagram.png + +.. toctree:: + :maxdepth: 1 + :caption: Code Documentation + + vsdi.io + vsdi.dim_reduction + vsdi.embeddings + vsdi.utils + vsdi.VAE + vsdi.visualization diff --git a/docs/source/requirements.txt b/docs/source/requirements.txt new file mode 100644 index 0000000..0ef03d4 --- /dev/null +++ b/docs/source/requirements.txt @@ -0,0 +1,4 @@ +sphinx==6.2.1 +sphinx-rtd-theme==1.2.2 +autodocsumm==0.2.11 +numpydoc==1.5.0 \ No newline at end of file diff --git a/docs/source/vsdi.VAE.rst b/docs/source/vsdi.VAE.rst new file mode 100644 index 0000000..0321b88 --- /dev/null +++ b/docs/source/vsdi.VAE.rst @@ -0,0 +1,7 @@ +vsdi.VAE module +=============== + +.. automodule:: vsdi.VAE + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/vsdi.dim_reduction.rst b/docs/source/vsdi.dim_reduction.rst new file mode 100644 index 0000000..1bca8cc --- /dev/null +++ b/docs/source/vsdi.dim_reduction.rst @@ -0,0 +1,7 @@ +vsdi.dim\_reduction module +========================== + +.. automodule:: vsdi.dim_reduction + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/vsdi.embeddings.rst b/docs/source/vsdi.embeddings.rst new file mode 100644 index 0000000..184cdd4 --- /dev/null +++ b/docs/source/vsdi.embeddings.rst @@ -0,0 +1,7 @@ +vsdi.embeddings module +====================== + +.. automodule:: vsdi.embeddings + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/vsdi.io.rst b/docs/source/vsdi.io.rst new file mode 100644 index 0000000..9890cee --- /dev/null +++ b/docs/source/vsdi.io.rst @@ -0,0 +1,7 @@ +vsdi.io module +============== + +.. automodule:: vsdi.io + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/vsdi.utils.rst b/docs/source/vsdi.utils.rst new file mode 100644 index 0000000..88f56a3 --- /dev/null +++ b/docs/source/vsdi.utils.rst @@ -0,0 +1,7 @@ +vsdi.utils module +================= + +.. automodule:: vsdi.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/vsdi.visualization.rst b/docs/source/vsdi.visualization.rst new file mode 100644 index 0000000..b540d0e --- /dev/null +++ b/docs/source/vsdi.visualization.rst @@ -0,0 +1,7 @@ +vsdi.visualization module +========================= + +.. automodule:: vsdi.visualization + :members: + :undoc-members: + :show-inheritance: diff --git a/loaders.py b/loaders.py deleted file mode 100644 index 4af5b6d..0000000 --- a/loaders.py +++ /dev/null @@ -1,39 +0,0 @@ -import numpy as np - - -def read_data_fields(atc_data): - data = atc_data['Data_OE'][0][0] - names = np.asarray(atc_data['Data_OE'][0][0].dtype.names) - for i, k in enumerate(names): - print(f'{k}:{data[i].shape}') - - -def extract_behavioural_data(atc_data): - # reads daa fields in input .mat file - names = np.asarray(atc_data['Data_OE'][0][0].dtype.names) - # fields to extract - to_extract = ['CSp', 'CSn', 'Lick', 'frames'] - extracted_data = {} - for k in to_extract: - # check if field is in data - if not (k in names): - raise TypeError(f' field name {k} not found in data structure') - # find index corresponding to field name - idx = np.where(names == k)[0][0] - # extract data, flattens them - extracted_data[k] = atc_data['Data_OE'][0][0][idx].flatten() - - return extracted_data - - -def extract_lfp_data(atc_data): - names = np.asarray(atc_data['Data_OE'][0][0].dtype.names) - lfp_name = 'HPC_LFP' - if not lfp_name in names: - raise TypeError(f'{lfp_name} not found in data structure') - - lfp_idx = np.where(names == lfp_name)[0][0] - lfp_data = atc_data['Data_OE'][0][0][lfp_idx][0] - lfp = np.vstack([i.flatten() for i in lfp_data]) - - return lfp diff --git a/preprocessing/clustering.py b/preprocessing/clustering.py deleted file mode 100644 index e138467..0000000 --- a/preprocessing/clustering.py +++ /dev/null @@ -1,46 +0,0 @@ -import numpy as np -from scipy.spatial.distance import pdist, squareform -from sklearn.cluster import KMeans -from sklearn.manifold import TSNE -import matplotlib.pyplot as plt - -def compute_distance_matrix(arr_list): - """ - Given a list of 2D arrays, compute the pairwise distance matrix using Pearson correlation. - """ - # Get the number of arrays in the list - n_arrays = len(arr_list) - # Create an empty distance matrix with shape (n_arrays, n_arrays) - dist_mat = np.zeros((n_arrays, n_arrays)) - # Compute the pairwise distance between all pairs of arrays using Pearson correlation - for i in range(n_arrays): - for j in range(i+1, n_arrays): - corr = np.corrcoef(arr_list[i], arr_list[j])[0, 1] - dist = 1 - np.abs(corr) - dist_mat[i, j] = dist - dist_mat[j, i] = dist - # Return the distance matrix - return dist_mat - -def cluster_and_plot(arr_list, kind='betas'): - """ - Given a list of 2D arrays, compute the pairwise distance matrix, cluster it using k-means, - and plot the t-SNE projection of the distance matrix, colored by the cluster labels. - """ - # Compute the distance matrix using Pearson correlation - dist_mat = compute_distance_matrix(arr_list) - # Set the number of clusters for k-means - n_clusters = 10 - # Apply k-means clustering to the distance matrix - kmeans = KMeans(n_clusters=n_clusters) - labels = kmeans.fit_predict(dist_mat) - # Compute the t-SNE projection of the distance matrix - tsne = TSNE(n_components=2, perplexity=30, random_state=42) - emb = tsne.fit_transform(dist_mat) - # Plot the t-SNE projection, coloring each point by its cluster label - fig, ax = plt.subplots(figsize=(8, 8)) - scatter = ax.scatter(emb[:,0], emb[:,1], c=labels, cmap='viridis') - legend = ax.legend(*scatter.legend_elements(), loc="lower left", title="Clusters") - ax.add_artist(legend) - ax.set_title(f"t-SNE projection of {kind} distance matrix") - plt.show() diff --git a/preprocessing/pca_ica.ipynb b/preprocessing/pca_ica.ipynb deleted file mode 100644 index 37b53b6..0000000 --- a/preprocessing/pca_ica.ipynb +++ /dev/null @@ -1,358 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import sys\n", - "import os\n", - "sys.path.append(os.path.abspath('../'))\n", - "from scipy.io import loadmat\n", - "import loaders\n", - "from vsdi_preprocessing import clean_outliers,pca_ica,glm\n", - "from pathlib import Path" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "datapath = Path('/Users/davide/Dropbox/Projects/ATC/ATC_Data_preprocessed')\n", - "atc = loadmat(datapath.joinpath('A04/Day1/ATC1.mat'))\n", - "vsdi = loadmat(datapath.joinpath('A04/Day1/vsdi_ATC1.mat'))['vsdi_data']\n", - "mask = loadmat(datapath.joinpath(f'A04/Day1/vsdi_mask.mat'))['mask']\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(94, 54, 29999)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vsdi.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.decomposition import PCA, FastICA\n", - "from sklearn.preprocessing import StandardScaler\n", - "from sklearn.pipeline import Pipeline\n", - "\n", - "def pca_ica(vsdi,mask):\n", - " X = vsdi.transpose(2, 0, 1)\n", - " X = X*mask\n", - " X = X.reshape(X.shape[0], X.shape[1]*X.shape[2])\n", - "\n", - " # Create a pipeline with PCA and ICA\n", - " pipe = Pipeline([\n", - " ('scaler', StandardScaler()),\n", - " ('pca', PCA(n_components=10)),\n", - " ('ica', FastICA(n_components=10, max_iter=200,\n", - " random_state=1, whiten='unit-variance'))\n", - " ])\n", - "\n", - " out = pipe.fit(X)\n", - "\n", - " fingerprints = out.named_steps[\"ica\"].components_ @ out.named_steps[\"pca\"].components_\n", - " timecourses = fingerprints @ X.T\n", - "\n", - " return fingerprints,timecourses\n", - "\n", - "clean_vsdi = clean_outliers(vsdi,nsigma=5)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "'numpy.ndarray' object is not callable", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[23], line 11\u001b[0m\n\u001b[1;32m 8\u001b[0m vsdi2 \u001b[39m=\u001b[39m loadmat(datapath\u001b[39m.\u001b[39mjoinpath(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00manimal\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mday\u001b[39m}\u001b[39;00m\u001b[39m/vsdi_ATC2.mat\u001b[39m\u001b[39m'\u001b[39m))[\u001b[39m'\u001b[39m\u001b[39mvsdi_data\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[1;32m 9\u001b[0m mask \u001b[39m=\u001b[39m loadmat(datapath\u001b[39m.\u001b[39mjoinpath(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00manimal\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mday\u001b[39m}\u001b[39;00m\u001b[39m/vsdi_mask.mat\u001b[39m\u001b[39m'\u001b[39m))[\u001b[39m'\u001b[39m\u001b[39mmask\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[0;32m---> 11\u001b[0m vsd1 \u001b[39m=\u001b[39m clean_vsdi(vsdi1,nsigma\u001b[39m=\u001b[39;49m\u001b[39m5\u001b[39;49m)\n\u001b[1;32m 12\u001b[0m vsdi2 \u001b[39m=\u001b[39m clean_vsdi(vsdi2,nsigma\u001b[39m=\u001b[39m\u001b[39m5\u001b[39m)\n\u001b[1;32m 14\u001b[0m vsdi \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mdstack([vsdi1,vsdi2])\n", - "\u001b[0;31mTypeError\u001b[0m: 'numpy.ndarray' object is not callable" - ] - } - ], - "source": [ - "animals = ['A04']\n", - "days = ['Day1','Day3','Day5','Day7']\n", - "\n", - "for animal in animals:\n", - " vsdi_total = []\n", - " for day in days:\n", - " vsdi1 = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_ATC1.mat'))['vsdi_data']\n", - " vsdi2 = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_ATC2.mat'))['vsdi_data']\n", - " mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask']\n", - "\n", - " vsd1 = clean_vsdi(vsdi1,nsigma=5)\n", - " vsdi2 = clean_vsdi(vsdi2,nsigma=5)\n", - "\n", - " vsdi = np.dstack([vsdi1,vsdi2])\n", - " print(vsdi.shape)\n", - " vsdi_total.append(vsdi1)\n", - "\n", - "vsdi_total = np.dstack(vsdi_total)\n", - "print('Done')\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pca_ica(vsdi_total,mask)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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XZl9fvWrX8Xxxx+Pzs5OdHZ2Yt26dfjpT3865f7S+PznP4+6ujpcdNFF+9Xvpz71KdTV1ZX9rV27dlrPVVQiO5AdiP2zA2D6bUF2IDs4GMwFOwBm3hZkB7VN3uwAmNv3hANmB1HOuPbaa6Pm5uboW9/6VvSrX/0qet/73hcVCoVo165dE/r8T37yk+jv//7vox/+8IcRgOi6664r2//5z38+6urqiq6//vrowQcfjN785jdHa9asifbu3ZvZ59lnnx1dc8010datW6MHHnggeuMb3xitWrUq6u/vj4/5wAc+EB122GHR5s2bo3vuuSc644wzojPPPDOzzx//+MfRjTfeGD3++OPRtm3bor/7u7+Lmpqaoq1bt06pP89dd90VrV69Ojr++OOjj3zkI1M+zyiKossuuyw69thjox07dsR/L7zwwn71KaojO5AdiP23gyiafluQHcgODjRzxQ6iaGZtQXZQ2+TRDqJobt8TDpQd5O5l9bTTTos2bNgQr4+OjkYrVqyINm3aNOm+/EAcGxuLli1bFl1++eXxtmKxGLW0tET/8R//MeF+u7u7IwDRli1b4j6ampqi73//+/Exjz76aAQguuOOOybc74IFC6JvfOMb+91fX19fdNRRR0U333xz9Ad/8AfxQJxqv5dddll0wgknpO6brt8uypEdyA7E9NpBFM2MLcgOEmQHM8NctoMomh5bkB3UPrVgB1E0t+4JB8oOchUGPDw8jHvvvRfr16+Pt9XX12P9+vW444479rv/p556Cjt37izrv6urC6effvqk+u/p6QEALFy4EABw7733YmRkpKzftWvXYtWqVRPqd3R0FNdeey327NmDdevW7Xd/GzZswDnnnFP2+f09zyeeeAIrVqzAEUccgfPPPx/PPPPMtPx2UYnsQHYgZt4OgOmxBdmB7GAmmat2AEyvLcgOaptasQNg7t0TDoQdNE7q6BnmxRdfxOjoKJYuXVq2fenSpXjsscf2u/+dO3fG/fn+uW88xsbGcNFFF+FVr3oVjjvuuLjf5uZmFAqFSfX78MMPY926dRgcHER7ezuuu+46HHPMMXjggQem1B8AXHvttbjvvvtw9913V+yb6nmefvrp+Pa3v42Xv/zl2LFjBz796U/j93//97F169Yp9ymykR3IDsTM2wGw/7YgO5AdzDRzzQ6A6bcF2UHtUwt2AMy9e8KBsoNcvazWAhs2bMDWrVvx85//fL/7evnLX44HHngAPT09+MEPfoALLrgAW7ZsmXJ/zz77LD7ykY/g5ptvRmtr636fH3nDG94QLx9//PE4/fTTcfjhh+N73/se2trapu17RO0gO5AdCNmB7EAA02sHwPTaguxAHEjm2j3hQNlBrsKAFy9ejIaGhopKUbt27cKyZcv2u3/2MdX+L7zwQtxwww342c9+hpUrV5b1Ozw8jGKxOKl+m5ubceSRR+Lkk0/Gpk2bcMIJJ+Cf/umfptzfvffei+7ubpx00klobGxEY2MjtmzZgquuugqNjY1YunTplPr1FAoFHH300XjyySenfK4iG9mB7EDMvB0A+2cLsoMSsoOZZa7ZATC9tiA7mB3k3Q4A3ROAmbODXL2sNjc34+STT8bmzZvjbWNjY9i8eTPWrVu33/2vWbMGy5YtK+u/t7cXv/zlL6v2H0URLrzwQlx33XW45ZZbsGbNmrL9J598Mpqamsr63bZtG5555plJnffY2BiGhoam3N9ZZ52Fhx9+GA888ED8d8opp+D888+Pl6fjPPv7+/HrX/8ay5cvn7bfLhJkB7IDMfN2AEzNFmQH5cgOZpa5bgfA/tmC7GB2kFc7AHRPCJkxO5hUOaYDwLXXXhu1tLRE3/72t6NHHnkkev/73x8VCoVo586dE/p8X19fdP/990f3339/BCC64oorovvvvz96+umnoygqlaUuFArRj370o+ihhx6K3vKWt4xblvqDH/xg1NXVFd16661l5ZkHBgbiYz7wgQ9Eq1atim655ZbonnvuidatWxetW7cus89LLrkk2rJlS/TUU09FDz30UHTJJZdEdXV10X//939Pqb8swkpfU+33r//6r6Nbb701euqpp6Jf/OIX0fr166PFixdH3d3d03quIkF2IDsQ+28HUTT9tiA7kB0caOaKHUTRgbEF2UFtkkc7iKK5fU84UHaQu5fVKIqiL3/5y9GqVaui5ubm6LTTTovuvPPOCX/2Zz/7WQSg4u+CCy6IoqhUmvoTn/hEtHTp0qilpSU666yzom3btlXtM60/ANE111wTH7N3797oQx/6ULRgwYJo3rx50Vvf+tZox44dmX2++93vjg4//PCoubk5OuSQQ6KzzjorHoRT6S8LPxCn0u/b3/72aPny5VFzc3N06KGHRm9/+9ujJ598ctrP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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure(figsize=(10,5))\n", - "for i,f in enumerate(fingerprints):\n", - " ax = plt.subplot(2,5,i+1)\n", - " ax.matshow(f.reshape(vsdi.shape[:2]),cmap=plt.cm.gnuplot2)\n", - "plt.tight_layout()\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Match masks" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Mask clustering" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import product\n", - "\n", - "animals = ['A04','A06','A07','A08']\n", - "days = ['Day1','Day3','Day5','Day7']\n", - "\n", - "masks = []\n", - "for animal,day in product(animals,days):\n", - " try:\n", - " mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask']\n", - " masks.append(mask)\n", - "\n", - " except FileNotFoundError:\n", - " print(f\"Not found mask for {animal},{day}\")\n", - " masks.append(np.nan)\n", - " continue\n", - " except OSError:\n", - " print(f\"OS error for {animal},{day}\")\n", - " masks.append(np.nan)\n", - " continue\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(masks)" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0YAAAPeCAYAAAAoEQo2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAABT0klEQVR4nO3da5CV1b0n4P8WsGlAONACyuU0g4iGqwhq4miaSIwkGsTCIJrEZKxJvBUTPWqiE1vBa6Fy9JjjNcRUNJUao2Iuoo4y4zknUzGQaGSCkqgIIWCCjKFEEwWBNR9S3WTTXLqhL+/u9TxV/YG113732pffhx/r3e8upZRSAAAAZOyAjl4AAABAR1OMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZa/ViNHny5BgzZkxrH7bD/fCHP4x+/frFe++919FLaTNPP/109OrVKzZs2NDRS6ENyGblks3OTTYrl2x2XnJZufYnl3aMmmHbtm1x7bXXxuzZs6NXr16N4x9++GHMnTs3hg8fHlVVVTF8+PC44YYbYuvWrXs83o033hilUmm/Ard69eoolUq7/Psf/+N/7PZ+H374YYwaNSpKpVLcdtttZbdNnTo1RowYETfffPM+rwvak2xCMckmFI9c7l3XFt8jQz/96U/jd7/7XXz1q18tG//CF74QjzzySJx33nkxadKk+MUvfhH19fWxZs2auP/++3d5rLVr18ZNN90UPXv2bJW1nX322fGZz3ymbOxjH/vYbud/61vfijVr1uz29vPPPz8uv/zymDt3bhx00EGtskZoK7IJxSSbUDxy2QypldXV1aXRo0e39mE71LRp09IJJ5xQNrZ06dIUEam+vr5s/LLLLkulUiktW7Zsl8c666yz0kknnbTfr9OqVatSRKRbb7212fdZv3596tOnT7ruuut2e9/169enLl26pO985zv7vDaKSTZlk2KSTdmkeOQyz1y26FS6d999Ny655JIYNmxYVFVVxYABA+Lkk0+OF198scncV155JT7xiU9Ejx49YvDgwXHLLbeU3b5ly5a45pprYuLEidGnT5/o2bNnnHjiifHcc8+VzWvYYrvtttvi9ttvj9ra2qiuro66urpYvnx5k8f97W9/G2eeeWb069cvunfvHpMmTYqf/OQnTeatXLkyVq5cudfn/MEHH8TTTz8dn/zkJ8vGf/azn0VExKxZs8rGZ82aFSmlePjhh5sc6z/+4z/i0UcfjTvuuGOvj9sSf/nLX2LLli17nXfllVfGEUccEV/4whd2O2fAgAExbty4+PGPf9yaS6SNyeYOskmRyOYOsklRyOUOcrmTlrSoc845Jx144IHpn/7pn9KCBQvSvHnz0mc/+9n0/e9/v3FOXV1dGjRoUBo6dGj62te+lu6+++500kknpYhITz75ZOO8DRs2pEMPPTT90z/9U7rnnnvSLbfcko444ojUrVu39Otf/7pxXkOTHDt2bBo2bFiaN29emjt3burXr1/q379/+tOf/tQ4d/ny5alPnz5p1KhRad68eelf//Vf08c//vFUKpXSwoULy55LbW1tqq2t3etz/j//5/+kiEg/+clPysZvuummFBHpjTfeKBt/+eWXU0SkU045pWx869atady4cen8889vfJ1ao2H36tUrRUQqlUpp0qRJ6X/+z/+5y/lLlixJBxxwQPr5z3++13b+X//rf00HH3zwPq+N9iebO8gmRSKbO8gmRSGXO8hluRYVoz59+qSLL754j3Pq6upSRKQHH3ywcWzz5s3pkEMOSTNmzGgc27p1a9q8eXPZfTdu3JgGDhyYzjvvvMaxhiddXV2d1q5d2zi+ZMmSFBHp0ksvbRybMmVKGjt2bPrggw8ax7Zv356OP/74dPjhh5c9VnM/SAsWLEgRkX7zm9+UjT/22GMpItJDDz1UNn7vvfemiEhjxowpG//Xf/3X1KdPn/TWW2+llPb/g/T73/8+fepTn0r33HNP+slPfpLuuOOO9I//+I/pgAMOSE888UTZ3O3bt6djjz02nX322SmlvW9bNoRk/fr1+7w+2pds7iCbFIls7iCbFIVc7iCX5VpUjGpra9OkSZPSunXrdjunrq4u9erVK23fvr1sfNq0aWnChAm7vM+2bdvS22+/nTZs2JBOPfXUdNRRRzXe1vCkG16Ev3fcccelI444IqWU0ttvv51KpVK6/vrr04YNG8r+5s6dmyKi7IPYXPPmzdvlfd9///1UW1ubBg4cmB577LG0evXq9PDDD6eamprUtWvXdNhhhzXO/X//7/+lfv36pdtuu63sdWrtc1fffvvtNHDgwMbXpMEDDzyQqqur05o1a1JKe/8g3XPPPSki0ssvv9yq66PtyOYOskmRyOYOsklRyOUOclmuRd8xuuWWW2L58uUxdOjQOPbYY2POnDnxxhtvNJk3ZMiQKJVKZWN9+/aNjRs3lo1973vfi3HjxkX37t2jpqYm+vfvH4sWLYp33nmnyTEPP/zwJmMjR46M1atXR0TE66+/HimlqK+vj/79+5f9XXvttRER8dZbb7Xk6ZZJKZX9u3v37rFo0aKoqamJGTNmxLBhw+Lcc8+Na665Jvr161d2GcSrr746+vXrF7Nnz97nx2+Ofv36xX/5L/8lfve738XatWsjImLTpk1x1VVXxRVXXBFDhw5t1nEanuvO7yHFJZs7yCZFIps7yCZFIZc7yGW5Fl2ue+bMmXHiiSfG448/Hs8880zceuutMW/evFi4cGF8+tOfbpzXpUuXPS4wIuL73/9+fPnLX47p06fHFVdcEQMGDIguXbrEzTff3Kwvke1s+/btERFx+eWXxymnnLLLOSNGjGjxcWtqaiIiYuPGjTFkyJCy20aPHh3Lly+PV155JTZu3BijRo2K6urquPTSS6Ouri4iIl577bW4//7744477og333yz8b4ffPBBfPjhh7F69ero3bt39OvXr8Vr25WGD8uf//znGDJkSNx2222xZcuWOOussxpD1/Ah27hxY6xevToGDRoUBx54YOMxGgJ/8MEHt8qaaHuyKZsUk2zKJsUjl3K5W83f2Gpq/fr1afDgwek//+f/3Di2uy21L33pS2XnQJ5++ulp+PDhTbYojz/++LJ5zd16XL9+fYqIdNVVV+3PU2qi4ctqP/7xj5s1f9GiRSki0n333ZdSSum5555LEbHHv6997Wuttt7LLrssRUR68803U0p/e9339vh//+XAlHyJtDOQzaZkkyKQzaZkk44ml03lmstm7xht27Yt3nvvvejTp0/j2IABA2LQoEGxefPm5h6mUUMLTyk1bnEtWbIknn/++fjHf/zHJvN/9KMfxbp162Lw4MEREbF06dJYsmRJXHLJJY1rmTx5ctx3330xe/bsOPTQQ8vuv2HDhujfv3/jvxta/GGHHbbHdU6cODEOPPDA+NWvfhXTpk3b49z3338/6uvr49BDD42zzz47IiLGjBkTjz/+eJO5V199dbz77rvxL//yL3tdw67s/HwiItatWxcPPPBAjBs3rvH5/7f/9t9i+vTpZfPeeuutOP/88+PLX/5ynH766fGf/tN/Krv9hRde2OOPalEssimbFJNsyibFI5dyuSfNLkbvvvtuDBkyJM4888wYP3589OrVKxYvXhy//OUvY/78+S160IiI0047LRYuXBhnnHFGnHrqqbFq1aq49957Y9SoUfHee+81mT9ixIg44YQT4sILL4zNmzfHHXfcETU1NfH1r3+9cc5dd90VJ5xwQowdOza+8pWvxPDhw2P9+vXx/PPPx9q1a2PZsmWNc6dMmRIR0bgdtzvdu3ePT33qU7F48eK47rrrym6bOXNmDBo0KEaNGhWbNm2KBx54IN54441YtGhR46/sHnzwwU3eyIhovPb7zrfNmTMn5s6dG88991xMnjx5t+v6+te/HitXrowpU6bEoEGDYvXq1XHffffFX/7yl/iXf/mXxnlHH310HH300WX3bXjOo0eP3uWH7P/+3/8bF1988e5fFApFNmWTYpJN2aR45FIu96i5W0ubN29OV1xxRRo/fnw66KCDUs+ePdP48ePT3XffXTavuVuP27dvTzfddFOqra1NVVVVacKECemJJ55oMu/vrzgxf/78NHTo0FRVVZVOPPHEXf4a78qVK9O5556bDjnkkNStW7c0ePDgdNppp6VHH320bF5zL2+YUkoLFy5MpVKp8SoYDebNm5eOPPLI1L1799S3b980bdq0Jtt4u7O716nhl4ZXrFixx/v/4Ac/SB//+MdT//79U9euXdPBBx+czjjjjPTCCy/s9bH3dBWPe+65J/Xo0SNt2rSpWc+DjiebskkxyaZsUjxyKZd7sl/fMWoPe7sUX3vYunVrGjlyZLr66qvb/LGOOeaYdOaZZ7b54+zOUUcdlS655JIOe3wqh2y2L9mkuWSzfckmzSGX7Wtfc9miy3XnqkuXLnHdddfFXXfdtctt0dayadOmWLZsWZMtzvby9NNPx2uvvRZXXXVVhzw+tJRsQjHJJhSPXO5diy7XnbOzzjorzjrrrDZ9jN69e+/TF/9ay9SpU9s0KNAWZBOKSTaheORyz+wYAQAA2SultNNP4AIAAGTGjhEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wA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AIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACy1+rFaPLkyTFmzJjWPmyH++EPfxj9+vWL9957r6OX0maefvrp6NWrV2zYsKGjl0IbkM3KJZudm2xWLtnsvOSycu1PLu0YNcO2bdvi2muvjdmzZ0evXr0axz/88MOYO3duDB8+PKqqqmL48OFxww03xNatW3d5nBdffDGmTZsW/fr1ix49esSYMWPizjvv3K+1rVy5Ms4555wYMGBAVFdXx+GHHx7f/OY3m8xbsWJFTJ06NXr16hX9+vWLL37xi00+MFOnTo0RI0bEzTffvF9rgvYim1BMsgnFI5d713Wfn0FGfvrTn8bvfve7+OpXv1o2/oUvfCEeeeSROO+882LSpEnxi1/8Iurr62PNmjVx//33l8195pln4rOf/WxMmDAh6uvro1evXrFy5cpYu3btPq/rpZdeismTJ8fgwYPjsssui5qamlizZk384Q9/KJu3du3a+PjHPx59+vSJm266Kd5777247bbb4je/+U0sXbo0DjzwwMa5559/flx++eUxd+7cOOigg/Z5bdAeZBOKSTaheOSyGVIrq6urS6NHj27tw3aoadOmpRNOOKFsbOnSpSkiUn19fdn4ZZddlkqlUlq2bFnj2DvvvJMGDhyYzjjjjLRt27ZWWdO2bdvSmDFj0nHHHZf++te/7nHuhRdemKqrq9Pvf//7xrFnn302RUS67777yuauX78+denSJX3nO99plXVSHLIpmxSTbMomxSOXeeayRcVo06ZN6Wtf+1qqra1NBx54YOrfv3/65Cc/mV544YXGOQ0fpJdffjlNnjw5VVdXp0GDBqV58+aVHWvz5s2pvr4+HX300al3796pR48e6YQTTkj/+3//77J5q1atShGRbr311vTP//zP6R//8R9T9+7d08c//vH0m9/8pskaV6xYkWbMmJH69u2bqqqq0sSJE9OPf/zjJvNef/319Prrr+/1Ob///vvpwAMPTHPmzCkbnz9/foqI9PLLL5eN//KXv0wRkf77f//vjWP33HNPioj0yiuvpJRSeu+99/b7A/XUU0+liEhPPvlkSimlv/zlL2nr1q27nDtgwID0uc99rsn4yJEj05QpU5qMT5gwIU2bNm2/1kf7ks0dZJMikc0dZJOikMsd5LJci75jdMEFF8Q999wTM2bMiLvvvjsuv/zyqK6ujhUrVpTN27hxY0ydOjXGjx8f8+fPjyOPPDK+8Y1vxFNPPdU4Z9OmTbFgwYKYPHlyzJs3L+bMmRMbNmyIU045JV566aUmj/3ggw/GnXfeGRdffHFcddVVsXz58jjppJNi/fr1jXNefvnl+OhHPxorVqyIK6+8MubPnx89e/aM6dOnx+OPP152vClTpsSUKVP2+pxfeOGF2LJlSxx99NFl45s3b46IiOrq6rLxHj16NN6vweLFi6N3796xbt26OOKII6JXr17Ru3fvuPDCC+ODDz7Y6xp2ZfHixRERUVVVFZMmTYqePXtGjx49YtasWfHnP/+5cd66devirbfeikmTJjU5xrHHHhu//vWvm4xPnDgxfv7zn+/TuugYsrmDbFIksrmDbFIUcrmDXO6kJS2qT58+6eKLL97jnLq6uhQR6cEHH2wc27x5czrkkEPSjBkzGse2bt2aNm/eXHbfjRs3poEDB6bzzjuvcayhYVdXV6e1a9c2ji9ZsiRFRLr00ksbx6ZMmZLGjh2bPvjgg8ax7du3p+OPPz4dfvjhZY9VW1ubamtr9/qcFyxYkCKiSZt/7LHHUkSkhx56qGz83nvvTRGRxowZ0zg2bty41KNHj9SjR480e/bs9Nhjj6XZs2eniEizZs3a6xp2Zdq0aSkiUk1NTfr85z+fHn300VRfX5+6du2ajj/++LR9+/aU0o7G//fvR4MrrrgiRUTZ65VSSjfddFOKiLR+/fp9WhvtTzZ3kE2KRDZ3kE2KQi53kMtyLSpGtbW1adKkSWndunW7nVNXV5d69erV+EQaTJs2LU2YMGGX99m2bVt6++2304YNG9Kpp56ajjrqqMbbGj5IZ599dpP7HXfccemII45IKaX09ttvp1KplK6//vq0YcOGsr+5c+emiCj7IDbXvHnzdnnf999/P9XW1qaBAwemxx57LK1evTo9/PDDqaamJnXt2jUddthhjXOHDx+eIiJdcMEFZcc4//zzU0SkV199tcXrOumkk1JEpKlTp5aN33zzzSki0rPPPptSSuk//uM/UkSkhx9+uMkx6uvrU0SkjRs3lo03bJXuvK1KccnmDrJJkcjmDrJJUcjlDnJZrkWn0t1yyy2xfPnyGDp0aBx77LExZ86ceOONN5rMGzJkSJRKpbKxvn37xsaNG8vGvve978W4ceOie/fuUVNTE/37949FixbFO++80+SYhx9+eJOxkSNHxurVqyMi4vXXX4+UUtTX10f//v3L/q699tqIiHjrrbda8nTLpJTK/t29e/dYtGhR1NTUxIwZM2LYsGFx7rnnxjXXXBP9+vUruwxiw/bk2WefXXaMc845JyIinn/++RavZ2/HbNg6bJjXsFX69xq2PXfePm14rju/hxSXbO4gmxSJbO4gmxSFXO4gl+VadLnumTNnxoknnhiPP/54PPPMM3HrrbfGvHnzYuHChfHpT3+6cV6XLl12ef+/fzO+//3vx5e//OWYPn16XHHFFTFgwIDo0qVL3HzzzbFy5cqWLCsiIrZv3x4REZdffnmccsopu5wzYsSIFh+3pqYmIv52numQIUPKbhs9enQsX748Xnnlldi4cWOMGjUqqqur49JLL426urrGeYMGDYqXX345Bg4cWHb/AQMGNB67pQYNGhQRsddjHnrooRER8cc//rHJMf74xz9Gv379oqqqqmy84b4HH3xwi9dFx5BN2aSYZFM2KR65lMvdafHvGB166KFx0UUXxUUXXRRvvfVWHH300XHjjTeWfZCa49FHH43hw4fHwoULy5pcQxve2WuvvdZk7NVXX41hw4ZFRMTw4cMjIqJbt27xyU9+skVr2ZMjjzwyIiJWrVoVY8eObXJ7qVSK0aNHN/77ySefjO3bt5etYeLEifHss882flmtwZtvvhkREf3792/xuiZOnBjf/va3Y926dWXjOx9z8ODB0b9///jVr37V5BhLly6No446qsn4qlWr4uCDD96nddFxZLOcbFIUsllONikCuSwnl3/T7FPptm3b1mRLcMCAATFo0KBdbmvtTUML//vWvWTJkt1uw/3oRz8qe9GWLl0aS5YsafwADxgwICZPnhz33XffLtvkzr+Ku3LlymY1+YkTJ8aBBx64yzdiZ++//37U19fHoYceWrYlOHPmzIiI+M53vlM2f8GCBdG1a9eYPHnyXo+9s9NPPz2qqqriu9/9buP/LjQcMyLi5JNPbhybMWNGPPHEE2U/lPW//tf/ildffTU+97nPNTn2Cy+8EB/72MdavCY6hmzKJsUkm7JJ8cilXO5Rc7+MtHHjxtSzZ8/0pS99Kf3zP/9zuv/++9PMmTNTRKT58+c3ztvdD2J96UtfKrtqxgMPPJAiIk2bNi3dd9996corr0z/8A//kEaPHl02r+HLamPHjk3Dhg1L8+bNS9ddd13q169fqqmpSW+++Wbj3Jdffjn17ds31dTUpCuvvDLdf//96frrr0+f+cxn0rhx48rW09yreKSU0mmnnZY+9rGPNRn/3Oc+l772ta+l++67L916663pIx/5SKqqqkqLFy9uMve8885LEZFmzpyZ7rrrrvS5z30uRUS66qqryuZde+21KSLSc889t9d1XXfddSki0sknn5zuuuuu9NWvfjWVSqUmX+xbs2ZNqqmpSYcddli6884700033ZT69u3b5IonKe34QawFCxY045WhCGRTNikm2ZRNikcu5XJPml2MNm/enK644oo0fvz4dNBBB6WePXum8ePHp7vvvrtsXnM/SNu3b0833XRTqq2tTVVVVWnChAnpiSeeaDLv738Qa/78+Wno0KGpqqoqnXjiiWW/xttg5cqV6dxzz02HHHJI6tatWxo8eHA67bTT0qOPPlo2ryUfpIULF6ZSqZTWrFlTNj5v3rx05JFHpu7du6e+ffumadOmpV//+te7PMaWLVvSnDlzUm1tberWrVsaMWJEuv3225vMa/il4RUrVux1Xdu3b0/f+ta30siRI1O3bt3S0KFD09VXX522bNnSZO7y5cvTpz71qdSjR4/0D//wD+nzn/98+tOf/tRk3j333JN69OiRNm3atNfHpxhkUzYpJtmUTYpHLuVyT1p0ue6O8PcfpI6ydevWNHLkyHT11Ve3+WMdc8wx6cwzz2zzx9mdo446Kl1yySUd9vhUDtlsX7JJc8lm+5JNmkMu29e+5rJFl+vOVZcuXeK6666Lu+66K9577702e5xNmzbFsmXL4rrrrmuzx9iTp59+Ol577bW46qqrOuTxoaVkE4pJNqF45HLvWnxVulydddZZcdZZZ7XpY/Tu3XufvvjXWqZOndqmQYG2IJtQTLIJxSOXe2bHCAAAyF4ppZ1+AhcAACAzdowAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5i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BAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQvVYvRpMnT44xY8a09mE73A9/+MPo169fvPfeex29lDbzyiuvRNeuXWP58uUdvRTagGxWLtnsvOSycsll5yablWt/smnHqBm2bdsW1157bcyePTt69erVOP7hhx/G3LlzY/jw4VFVVRXDhw+PG264IbZu3brL47z44osxbdq06NevX/To0SPGjBkTd955536tbeXKlXHOOefEgAEDorq6Og4//PD45je/WTZn6dKlcdFFF8XEiROjW7duUSqVdnmsUaNGxamnnhrXXHPNfq0J2otsQvHIJRSTbO5d131afWZ++tOfxu9+97v46le/Wjb+hS98IR555JE477zzYtKkSfGLX/wi6uvrY82aNXH//feXzX3mmWfis5/9bEyYMCHq6+ujV69esXLlyli7du0+r+ull16KyZMnx+DBg+Oyyy6LmpqaWLNmTfzhD38om/fkk0/GggULYty4cTF8+PB49dVXd3vMCy64ID7zmc/EypUr47DDDtvntUF7kE0oHrmEYpLNZkitrK6uLo0ePbq1D9uhpk2blk444YSysaVLl6aISPX19WXjl112WSqVSmnZsmWNY++8804aOHBgOuOMM9K2bdtaZU3btm1LY8aMSccdd1z661//use5f/rTnxrnXHzxxWlPb/uWLVtS3759mzwvKp9syibFI5dySTHJZp7ZbNGpdO+++25ccsklMWzYsKiqqooBAwbEySefHC+++GKTua+88kp84hOfiB49esTgwYPjlltuKbt9y5Ytcc0118TEiROjT58+0bNnzzjxxBPjueeeK5u3evXqKJVKcdttt8Xtt98etbW1UV1dHXV1dbs8d/C3v/1tnHnmmdGvX7/o3r17TJo0KX7yk580mbdy5cpYuXLlXp/zBx98EE8//XR88pOfLBv/2c9+FhERs2bNKhufNWtWpJTi4Ycfbhz7wQ9+EOvXr48bb7wxDjjggPjLX/4S27dv3+tj78kzzzwTy5cvj2uvvTaqq6vjr3/9a2zbtm2XcwcOHBjV1dXNOm63bt1i8uTJ8eMf/3i/1kf7ks0dZJOikMsd5JIikc0dZLNci4rRBRdcEPfcc0/MmDEj7r777rj88sujuro6VqxYUTZv48aNMXXq1Bg/fnzMnz8/jjzyyPjGN74RTz31VOOcTZs2xYIFC2Ly5Mkxb968mDNnTmzYsCFOOeWUeOmll5o89oMPPhh33nlnXHzxxXHVVVfF8uXL46STTor169c3znn55Zfjox/9aKxYsSKuvPLKmD9/fvTs2TOmT58ejz/+eNnxpkyZElOmTNnrc37hhRdiy5YtcfTRR5eNb968OSKiyRvUo0ePxvs1WLx4cfTu3TvWrVsXRxxxRPTq1St69+4dF154YXzwwQd7XcOuLF68OCIiqqqqYtKkSdGzZ8/o0aNHzJo1K/785z/v0zEbTJw4MZYvXx6bNm3ar+PQfmRzB9mkKORyB7mkSGRzB9ncSUu2l/r06ZMuvvjiPc6pq6tLEZEefPDBxrHNmzenQw45JM2YMaNxbOvWrWnz5s1l9924cWMaOHBgOu+88xrHVq1alSIiVVdXp7Vr1zaOL1myJEVEuvTSSxvHpkyZksaOHZs++OCDxrHt27en448/Ph1++OFlj1VbW5tqa2v3+pwXLFiQIiL95je/KRt/7LHHUkSkhx56qGz83nvvTRGRxowZ0zg2bty41KNHj9SjR480e/bs9Nhjj6XZs2eniEizZs3a6xp2Zdq0aSkiUk1NTfr85z+fHn300VRfX5+6du2ajj/++LR9+/Zd3m9vW48ppfSDH/wgRURasmTJPq2N9iebO8gmRSGXO8glRSKbO8hmuRYVo9ra2jRp0qS0bt263c6pq6tLvXr1avJEpk2bliZMmLDL+2zbti29/fbbacOGDenUU09NRx11VONtDR+ks88+u8n9jjvuuHTEEUeklFJ6++23U6lUStdff33asGFD2d/cuXNTRJR9EJtr3rx5u7zv+++/n2pra9PAgQPTY489llavXp0efvjhVFNTk7p27ZoOO+ywxrnDhw9PEZEuuOCCsmOcf/75KSLSq6++2uJ1nXTSSSki0tSpU8vGb7755hQR6dlnn93l/ZrzQXrqqadSRKRFixa1eF10DNncQTYpCrncQS4pEtncQTbLtehUultuuSWWL18eQ4cOjWOPPTbmzJkTb7zxRpN5Q4YMaXIJvb59+8bGjRvLxr73ve/FuHHjonv37lFTUxP9+/ePRYsWxTvvvNPkmIcffniTsZEjR8bq1asjIuL111+PlFLU19dH//79y/6uvfbaiIh46623WvJ0y6SUyv7dvXv3WLRoUdTU1MSMGTNi2LBhce6558Y111wT/fr1K7sMYsP25Nlnn112jHPOOSciIp5//vkWr2dvx/z5z3/e4mM2aHiuu7sMIsUjmzvIJkUhlzvIJUUimzvIZrkWXa575syZceKJJ8bjjz8ezzzzTNx6660xb968WLhwYXz6059unNelS5c9LjAi4vvf/358+ctfjunTp8cVV1wRAwYMiC5dusTNN9/crC+R7azhy1+XX355nHLKKbucM2LEiBYft6amJiL+dp7pkCFDym4bPXp0LF++PF555ZXYuHFjjBo1Kqqrq+PSSy+Nurq6xnmDBg2Kl19+OQYOHFh2/wEDBjQeu6UGDRoUEdGqx2zQcN+DDz54n49B+5JN2aR45FIuKSbZlM3dafHvGB166KFx0UUXxUUXXRRvvfVWHH300XHjjTeWfZCa49FHH43hw4fHwoULy5pcQxve2WuvvdZk7NVXX41hw4ZFRMTw4cMj4m9Xodj5ihv748gjj4yIiFWrVsXYsWOb3F4qlWL06NGN/37yySdj+/btZWuYOHFiPPvss41fVmvw5ptvRkRE//79W7yuiRMnxre//e1Yt25d2fj+HLPBqlWr4oADDoiRI0fu8zFof7JZTjYpArksJ5cUhWyWk82/afapdNu2bWuyJThgwIAYNGhQ4xUtWqKhhf99616yZMlut+F+9KMflb1oS5cujSVLljR+gAcMGBCTJ0+O++67L/74xz82uf+GDRvK/t3cyxtOnDgxDjzwwPjVr36117nvv/9+1NfXx6GHHlq2JThz5syIiPjOd75TNn/BggXRtWvXmDx58l6PvbPTTz89qqqq4rvf/W7ZpRIXLFgQEREnn3xyi4/Z4IUXXojRo0dHnz599vkYtB/ZlE2KRy7lkmKSTdnck2bvGL377rsxZMiQOPPMM2P8+PHRq1evWLx4cfzyl7+M+fPnt3ixp512WixcuDDOOOOMOPXUU2PVqlVx7733xqhRo+K9995rMn/EiBFxwgknxIUXXhibN2+OO+64I2pq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slmuRcXoggsuiHvuuSdmzJgRd999d1x++eVRXV0dK1asKJu3cePGmDp1aowfPz7mz58fRx55ZHzjG9+Ip556qnHOpk2bYsGCBTF58uSYN29ezJkzJzZs2BCnnHJKvPTSS00e+8EHH4w777wzLr744rjqqqti+fLlcdJJJ8X69esb57z88svx0Y9+NFasWBFXXnllzJ8/P3r27BnTp0+Pxx9/vOx4U6ZMiSlTpuz1Ob/wwguxZcuWOProo8vGN2/eHBHR5A3q0aNH4/0aLF68OHr37h3r1q2LI444Inr16hW9e/eOCy+8MD744IO9rmFXFi9eHBERVVVVMWnSpOjZs2f06NEjZs2aFX/+85/36ZgNJk6cGMuXL49Nmzbt13FoP7K5g2xSFHK5g1xSJLK5g2zupCXbS3369EkXX3zxHufU1dWliEgPPvhg49jmzZvTIYcckmbMmNE4tnXr1rR58+ay+27cuDENHDgwnXfeeY1jq1atShGRqqur09q1axvHlyxZkiIiXXrppY1jU6ZMSWPHjk0ffPBB49j27dvT8ccfnw4//PCyx6qtrU21tbV7fc4LFixIEZF+85vflI0/9thjKSLSQw89VDZ+7733pohIY8aMaRwbN25c6tGjR+rRo0eaPXt2euyxx9Ls2bNTRKRZs2btdQ27Mm3atBQRqaamJn3+859Pjz76aKqvr09du3ZNxx9/fNq+ffsu77e3rceUUvrBD36QIiItWbJkn9ZG+5PNHWSTopDLHeSSIpHNHWSzXIuKUW1tbZo0aVJat27dbufU1dWlXr16NXki06ZNSxMmTNjlfbZt25befvvttGHDhnTqqaemo446qvG2hg/S2Wef3eR+xx13XDriiCNSSim9/fbbqVQqpeuvvz5t2LCh7G/u3LkpIso+iM01b968Xd73/fffT7W1tWngwIHpscceS6tXr04PP/xwqqmpSV27dk2HHXZY49zhw4eniEgXXHBB2THOP//8FBHp1VdfbfG6TjrppBQRaerUqWXjN998c4qI9Oyzz+7yfs35ID311FMpItKiRYtavC46hmzuIJsUhVzuIJcUiWzuIJvlWnQq3S233BLLly+PoUOHxrHHHhtz5syJN954o8m8IUOGNLmEXt++fWPjxo1lY9/73vdi3Lhx0b1796ipqYn+/fvHokWL4p133mlyzMMPP7zJ2MiRI2P16tUREfH6669HSinq6+ujf//+ZX/XXnttRES89dZbLXm6ZVJKZf/u3r17LFq0KGpqamLGjBkxbNiwOPfcc+Oaa66Jfv36lV0GsWF78uyzzy47xjnnnBMREc8//3yL17O3Y/785z9v8TEbNDzX3V0GkeKRzR1kk6KQyx3kkiKRzR1ks1yLLtc9c+bMOPHEE+Pxxx+PZ555Jm699daYN29eLFy4MD796U83zuvSpcseFxgR8f3vfz++/OUvx/Tp0+OKK66IAQMGRJcuXeLmm29u1pfIdtbw5a/LL788TjnllF3OGTFiRIuPW1NTExF/O890yJAhZbeNHj06li9fHq+88kps3LgxRo0aFdXV1XHppZdGXV1d47xBgwbFyy+/HAMHDiy7/4ABAxqP3VKDBg2KiGjVYzZouO/BBx+8z8egfcmmbFI8cimXFJNsyubutPh3jA499NC46KKL4qKLLoq33norjj766LjxxhvLPkjN8eijj8bw4cNj4cKFZU2uoQ3v7LXXXmsy9uqrr8awYcMiImL48OER8berUOx8xY39ceSRR0ZExKpVq2Ls2LFNbi+VSjF69OjGfz/55JOxffv2sjVMnDgxnn322cYvqzV48803IyKif//+LV7XxIkT49vf/nasW7eubHx/jtlg1apVccABB8TIkSP3+Ri0P9ksJ5sUgVyWk0uKQjbLyebfNPtUum3btjXZEhwwYEAMGjSo8YoWLdHQwv++dS9ZsmS323A/+tGPyl60pUuXxpIlSxo/wAMGDIjJkyfHfffdF3/84x+b3H/Dhg1l/27u5Q0nTpwYBx54YPzqV7/a69z3338/6uvr49BDDy3bEpw5c2ZERHznO98pm79gwYLo2rVrTJ48ea/H3tnpp58eVVVV8d3vfrfsUokLFiyIiIiTTz65xcds8MILL8To0aOjT58++3wM2o9syibFI5dySTHJpmzuSbN3jN59990YMmRInHnmmTF+/Pjo1atXLF68OH75y1/G/PnzW7zY0047LRYuXBhnnHFGnHrqqbFq1aq49957Y9SoUfHee+81mT9ixIg44YQT4sILL4zNmzfHHXfcETU1NfH1r3+9cc5dd90VJ5xwQowdOza+8pWvxPDhw2P9+vXx/PPPx9q1a2PZsmWNcxsubdhwTufudO/ePT71qU/F4sWL47rrriu7bebMmTFo0KAY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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure(figsize=(10,10))\n", - "for i,m in enumerate(masks):\n", - " ax = plt.subplot(4,4,i+1)\n", - " ax.matshow(mask,cmap=plt.cm.Greys)\n", - " plt.axis('off')\n", - " plt.title(f'shape: {m.shape}')\n", - "\n", - "plt.tight_layout()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [], - "source": [ - "from functools import reduce\n", - "def max_common_intersection(mask_list):\n", - " min_x = np.min([m.shape[0] for m in mask_list])\n", - " min_y = np.min([m.shape[1] for m in mask_list])\n", - "\n", - " cropped_masks = []\n", - " for m in masks:\n", - " if m.shape[0]> min_x and m.shape[1]>min_y:\n", - " cropped_masks.append(m[(m.shape[0]-min_x)//2:-(m.shape[0]-min_x)//2,\n", - " (m.shape[1]-min_y)//2:-(m.shape[1]-min_y)//2])\n", - "\n", - " elif m.shape[0] == min_x and m.shape[1]>min_y:\n", - " cropped_masks.append(m[:,(m.shape[1]-min_y)//2:-(m.shape[1]-min_y)//2])\n", - "\n", - " elif m.shape[0]> min_x and m.shape[1]== min_y:\n", - " cropped_masks.append(m[(m.shape[0]-min_x)//2:-(m.shape[0]-min_x)//2,:])\n", - "\n", - " else:\n", - " cropped_masks.append(m)\n", - " \n", - " # performs elementwise logical and\n", - " intersection = reduce(lambda x, y: np.logical_and(x, y), cropped_masks)\n", - "\n", - "\n", - " return intersection" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [], - "source": [ - "cm = max_common_intersection(masks)" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWUAAAJMCAYAAAAizrfYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAccUlEQVR4nO3df2zV1f3H8dctbW87aG8Bx207Cus2ZlUE5FetuM1AY+PXGRjNBglbmJqxYWEU3BxNBsimFtiGDIagjgDLZEyWINN9xZEqNbpSocCE6SpuZDSD227Jem+ttlR6vn/45c6LBbyXW+67t89H8knkc28v56zJc4f7OfdzPc45JwCACSmJHgAA4L+IMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhiOsobN27Upz/9aWVkZKi4uFivvfZaoocUs5dffll33XWX8vPz5fF49Mwzz0Q87pzT8uXLlZeXp8zMTJWWlurEiROJGWyMqqurNWnSJGVlZWnYsGGaMWOGGhsbI57T0dGhiooKDR06VIMGDVJ5ebmam5sTNOLYbNq0SWPGjFF2drays7NVUlKi559/Pvx4MszxQqtWrZLH41FlZWX4XDLM88EHH5TH44k4ioqKwo8nYo5mo/zb3/5WS5Ys0YoVK3T48GGNHTtWZWVlamlpSfTQYtLe3q6xY8dq48aNPT6+Zs0arV+/Xps3b1Z9fb0GDhyosrIydXR0XOWRxq62tlYVFRU6cOCA9u3bp66uLt1+++1qb28PP2fx4sV69tlntWvXLtXW1ur06dOaOXNmAkcdveHDh2vVqlVqaGjQoUOHNHXqVE2fPl1/+ctfJCXHHD/s4MGDevzxxzVmzJiI88kyzxtuuEFnzpwJH6+88kr4sYTM0Rk1efJkV1FREf7zuXPnXH5+vquurk7gqOJDktu9e3f4z93d3S43N9f95Cc/CZ9rbW11Xq/X/eY3v0nACOOjpaXFSXK1tbXOuQ/mlJaW5nbt2hV+zptvvukkubq6ukQNMy4GDx7sfvnLXybdHNva2tyoUaPcvn373Je+9CW3aNEi51zy/C5XrFjhxo4d2+NjiZqjyZXy2bNn1dDQoNLS0vC5lJQUlZaWqq6uLoEj6x0nT55UIBCImK/P51NxcXGfnm8wGJQkDRkyRJLU0NCgrq6uiHkWFRVpxIgRfXae586d086dO9Xe3q6SkpKkm2NFRYXuvPPOiPlIyfW7PHHihPLz8/WZz3xGc+bM0alTpyQlbo6pvfbKV+Df//63zp07J7/fH3He7/frr3/9a4JG1XsCgYAk9Tjf84/1Nd3d3aqsrNSUKVM0evRoSR/MMz09XTk5ORHP7YvzPHbsmEpKStTR0aFBgwZp9+7duv7663X06NGkmePOnTt1+PBhHTx48COPJcvvsri4WNu2bdO1116rM2fOaOXKlfrCF76g48ePJ2yOJqOMvq+iokLHjx+PeH8umVx77bU6evSogsGgfve732nu3Lmqra1N9LDipqmpSYsWLdK+ffuUkZGR6OH0mjvuuCP832PGjFFxcbFGjhypp59+WpmZmQkZk8m3L6655hoNGDDgI1c5m5ublZubm6BR9Z7zc0qW+S5YsEDPPfecXnrpJQ0fPjx8Pjc3V2fPnlVra2vE8/viPNPT0/W5z31OEyZMUHV1tcaOHauf//znSTPHhoYGtbS0aPz48UpNTVVqaqpqa2u1fv16paamyu/3J8U8L5STk6PPf/7zevvttxP2uzQZ5fT0dE2YMEE1NTXhc93d3aqpqVFJSUkCR9Y7CgsLlZubGzHfUCik+vr6PjVf55wWLFig3bt368UXX1RhYWHE4xMmTFBaWlrEPBsbG3Xq1Kk+Nc+edHd3q7OzM2nmOG3aNB07dkxHjx4NHxMnTtScOXPC/50M87zQO++8o7/97W/Ky8tL3O+y1y4hXqGdO3c6r9frtm3b5t544w03b948l5OT4wKBQKKHFpO2tjZ35MgRd+TIESfJrV271h05csT94x//cM45t2rVKpeTk+P27NnjXn/9dTd9+nRXWFjo3nvvvQSP/OObP3++8/l8bv/+/e7MmTPh49133w0/5zvf+Y4bMWKEe/HFF92hQ4dcSUmJKykpSeCoo7d06VJXW1vrTp486V5//XW3dOlS5/F43B//+EfnXHLMsScf3n3hXHLM8/7773f79+93J0+edK+++qorLS1111xzjWtpaXHOJWaOZqPsnHMbNmxwI0aMcOnp6W7y5MnuwIEDiR5SzF566SUn6SPH3LlznXMfbItbtmyZ8/v9zuv1umnTprnGxsbEDjpKPc1Pktu6dWv4Oe+9956777773ODBg90nPvEJ95WvfMWdOXMmcYOOwT333ONGjhzp0tPT3Sc/+Uk3bdq0cJCdS4459uTCKCfDPGfNmuXy8vJcenq6+9SnPuVmzZrl3n777fDjiZijxzm+OBUArDD5njIA9FdEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhpiOcmdnpx588EF1dnYmeii9qj/Mkzkmj/4wz0TO0fSHR0KhkHw+n4LBoLKzsxM9nF7TH+bJHJNHf5hnIudoeqUMAP1Nr0U5mb70FACull65yf35Lz3dvHmziouLtW7dOpWVlamxsVHDhg275M92d3fr9OnTysrKUltbm6QP/imRzM7PL5nnyRyTR3+YZ7zn6JxTW1ub8vPzlZJymbVwb9zl6Eq+9LSpqemidxvj4ODg6MtHU1PTZRsY95Xy+S89raqqCp+71JeednZ2RlzhdP9/3fFW/Y9SlRbv4QHAVfe+uvSK/ldZWVmXfW7coxztl55WV1dr5cqVPQwsTakeogwgCXyw1pTH47nsUxO++6KqqkrBYDB8NDU1JXpIAJAwcV8pR/ulp16vV16vN97DAIA+Ke4r5f72pacAEE+9siVuyZIlmjt3riZOnKjJkydr3bp1am9v1913390bfx0AJI1eifKsWbP0r3/9S8uXL1cgENC4ceO0d+/ej1z8AwBEMnfvi/OfOb9N09l9ASApvO+6tF97Pta9NBK++wIA8F9EGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhqYkeAOLvhdNHr/rfWZY/7qr/nUAyYqUMAIYQZQAwhCgDgCFEGQAM4UJfH5eIi3o9udg4uAAIRIeVMgAYQpQBwBCiDACGEGUAMIQoA4Ah7L7oI6zssogWuzKA6LBSBgBDiDIAGEKUAcAQogwAhhBlADCE3RfG9NVdFtHqaZ7syABYKQOAKUQZAAwhygBgCFEGAEOIMgAYwu4LmMF9MgBWygBgClEGAEOIMgAYQpQBwBAu9CVIf/k4dTxwARD9CStlADCEKAOAIUQZAAwhygBgCFEGAEPYfYE+i10ZSEaslAHAEKIMAIYQZQAwhCgDgCFRRbm6ulqTJk1SVlaWhg0bphkzZqixsTHiOR0dHaqoqNDQoUM1aNAglZeXq7m5Oa6DBoBkFVWUa2trVVFRoQMHDmjfvn3q6urS7bffrvb29vBzFi9erGeffVa7du1SbW2tTp8+rZkzZ8Z94MDFvHD66EcOoK+Iakvc3r17I/68bds2DRs2TA0NDfriF7+oYDCoLVu2aMeOHZo6daokaevWrbruuut04MAB3XzzzfEbOQAkoSt6TzkYDEqShgwZIklqaGhQV1eXSktLw88pKirSiBEjVFdX1+NrdHZ2KhQKRRwA0F/FHOXu7m5VVlZqypQpGj16tCQpEAgoPT1dOTk5Ec/1+/0KBAI9vk51dbV8Pl/4KCgoiHVIANDnxRzliooKHT9+XDt37ryiAVRVVSkYDIaPpqamK3o9AOjLYvqY9YIFC/Tcc8/p5Zdf1vDhw8Pnc3NzdfbsWbW2tkaslpubm5Wbm9vja3m9Xnm93liGAQBJJ6ooO+e0cOFC7d69W/v371dhYWHE4xMmTFBaWppqampUXl4uSWpsbNSpU6dUUlISv1H3MVz9Tzzuk4G+IqooV1RUaMeOHdqzZ4+ysrLC7xP7fD5lZmbK5/Pp3nvv1ZIlSzRkyBBlZ2dr4cKFKikpYecFAHwMUUV506ZNkqTbbrst4vzWrVv1zW9+U5L06KOPKiUlReXl5ers7FRZWZkee+yxuAwWAJJd1G9fXE5GRoY2btyojRs3xjwoAOivuPcFABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYEhM974AkgUfv4Y1rJQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhHtfAD3o6Z4Y3A8DVwMrZQAwhCgDgCFEGQAMIcoAYAgX+uLoYjdMB4CPi5UyABhClAHAEKIMAIYQZQAwhCgDgCHsvgA+povtruHj14gnVsoAYAhRBgBDiDIAGEKUAcAQogwAhrD7ArhC7MpAPLFSBgBDiDIAGEKUAcAQogwAhhBlADCE3RdAL2FXBmLBShkADCHKAGAIUQYAQ4gyABjChb4YXOwCDgBcKVbKAGAIUQYAQ4gyABhClAHAEKIMAIaw+wK4ynravcNHr3EeK2UAMIQoA4AhRBkADCHKAGAIUQYAQ9h9ARjADfFxHitlADCEKAOAIUQZAAwhygBgCFEGAEPYfQEYxq6M/oeVMgAYQpQBwBCiDACGEGUAMIQLfUAfxAXA5MVKGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEO49wWQRHq6Jwb3w+hbWCkDgCFEGQAMIcoAYAhRBgBDiDIAGMLui0u42Lc7AH0J31LSt7BSBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYwsesgX6Kj1/bxEoZAAwhygBgCFEGAEOIMgAYckVRXrVqlTwejyorK8PnOjo6VFFRoaFDh2rQoEEqLy9Xc3PzlY4TAPqFmHdfHDx4UI8//rjGjBkTcX7x4sX6wx/+oF27dsnn82nBggWaOXOmXn311SseLIDex66MxIpppfzOO+9ozpw5evLJJzV48ODw+WAwqC1btmjt2rWaOnWqJkyYoK1bt+pPf/qTDhw4ELdBA0CyiinKFRUVuvPOO1VaWhpxvqGhQV1dXRHni4qKNGLECNXV1fX4Wp2dnQqFQhEHAPRXUb99sXPnTh0+fFgHDx78yGOBQEDp6enKycmJOO/3+xUIBHp8verqaq1cuTLaYQBAUopqpdzU1KRFixbpqaeeUkZGRlwGUFVVpWAwGD6ampri8roA0BdFFeWGhga1tLRo/PjxSk1NVWpqqmpra7V+/XqlpqbK7/fr7Nmzam1tjfi55uZm5ebm9viaXq9X2dnZEQcA9FdRvX0xbdo0HTt2LOLc3XffraKiIv3gBz9QQUGB0tLSVFNTo/LycklSY2OjTp06pZKSkviNGgCSVFRRzsrK0ujRoyPODRw4UEOHDg2fv/fee7VkyRINGTJE2dnZWrhwoUpKSnTzzTfHb9QAkKTifpe4Rx99VCkpKSovL1dnZ6fKysr02GOPxfuvAYCk5HHOuUQP4sNCoZB8Pp9u03SletISOpaLbaIH+iM+PBK7912X9muPgsHgZa+bce8LADCEm9wD+Fh6+pcjq+f4Y6UMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIdz7AkDMLnYnRe6JETtWygBgCFEGAEOIMgAYQpQBwBAu9AGIOy4Axo6VMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGMI3jwC4avhGkstjpQwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMISPWQNIuJ4+ft1fP3rNShkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIdzkHoBJPd34Xkr+m9+zUgYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQ7n0BoE9J9ntisFIGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIamJHgAAxMMLp4/2eL4sf9xVHceVYqUMAIYQZQAwhCgDgCFEGQAMiTrK//znP/X1r39dQ4cOVWZmpm688UYdOnQo/LhzTsuXL1deXp4yMzNVWlqqEydOxHXQAJCsooryf/7zH02ZMkVpaWl6/vnn9cYbb+hnP/uZBg8eHH7OmjVrtH79em3evFn19fUaOHCgysrK1NHREffBA0CyiWpL3OrVq1VQUKCtW7eGzxUWFob/2zmndevW6Yc//KGmT58uSfrVr34lv9+vZ555RrNnz47TsAEgOUW1Uv7973+viRMn6qtf/aqGDRumm266SU8++WT48ZMnTyoQCKi0tDR8zufzqbi4WHV1dT2+Zmdnp0KhUMQBAP1VVFH++9//rk2bNmnUqFF64YUXNH/+fH33u9/V9u3bJUmBQECS5Pf7I37O7/eHH7tQdXW1fD5f+CgoKIhlHgCQFKKKcnd3t8aPH69HHnlEN910k+bNm6dvfetb2rx5c8wDqKqqUjAYDB9NTU0xvxYA9HVRRTkvL0/XX399xLnrrrtOp06dkiTl5uZKkpqbmyOe09zcHH7sQl6vV9nZ2REHAPRXUUV5ypQpamxsjDj31ltvaeTIkZI+uOiXm5urmpqa8OOhUEj19fUqKSmJw3ABILlFtfti8eLFuuWWW/TII4/oa1/7ml577TU98cQTeuKJJyRJHo9HlZWVeuihhzRq1CgVFhZq2bJlys/P14wZM3pj/ACQVKKK8qRJk7R7925VVVXpRz/6kQoLC7Vu3TrNmTMn/JwHHnhA7e3tmjdvnlpbW3Xrrbdq7969ysjIiPvgASDZeJxzLtGD+LBQKCSfz6fbNF2pnrSEjuVitwIE0HdYuHXn+65L+7VHwWDwstfNuPcFABjCTe4v4WL/D8sKGkBvYaUMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADAkNdED6IvK8sf1eP6F00ev6jgAJB9WygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ/iYNYCkcLHbH/Q1rJQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhHtfxOCF00cTPQSg30qWe1xcDCtlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhfMwagEnJ/nHqi2GlDACGEGUAMIQoA4AhRBkADCHKAGAIuy8ugZvZA1dHf91p0RNWygBgCFEGAEOIMgAYQpQBwBCiDACGsPviEi52RZhdGUBs2GVxeayUAcAQogwAhhBlADCEKAOAIVzoi0G0Fyu4MIj+hgt6sWOlDACGEGUAMIQoA4AhRBkADCHKAGAIuy+ugp6uRLMjA30NOyquDlbKAGAIUQYAQ4gyABhClAHAEKIMAIaw+yJBuH8GrGKXRWKxUgYAQ4gyABhClAHAkKiifO7cOS1btkyFhYXKzMzUZz/7Wf34xz+Wcy78HOecli9frry8PGVmZqq0tFQnTpyI+8ABIBlFFeXVq1dr06ZN+sUvfqE333xTq1ev1po1a7Rhw4bwc9asWaP169dr8+bNqq+v18CBA1VWVqaOjo64Dx4Ako3HfXiZexlf/vKX5ff7tWXLlvC58vJyZWZm6te//rWcc8rPz9f999+v733ve5KkYDAov9+vbdu2afbs2Zf9O0KhkHw+n27TdKV60mKYEi6GHRz9E7spEu9916X92qNgMKjs7OxLPjeqlfItt9yimpoavfXWW5KkP//5z3rllVd0xx13SJJOnjypQCCg0tLS8M/4fD4VFxerrq4u2nkAQL8T1T7lpUuXKhQKqaioSAMGDNC5c+f08MMPa86cOZKkQCAgSfL7/RE/5/f7w49dqLOzU52dneE/h0KhqCYAAMkkqpXy008/raeeeko7duzQ4cOHtX37dv30pz/V9u3bYx5AdXW1fD5f+CgoKIj5tQCgr4sqyt///ve1dOlSzZ49WzfeeKO+8Y1vaPHixaqurpYk5ebmSpKam5sjfq65uTn82IWqqqoUDAbDR1NTUyzzAICkENXbF++++65SUiI7PmDAAHV3d0uSCgsLlZubq5qaGo0bN07SB29H1NfXa/78+T2+ptfrldfrjWHoiFY8LvhwsdAGLt4lr6iifNddd+nhhx/WiBEjdMMNN+jIkSNau3at7rnnHkmSx+NRZWWlHnroIY0aNUqFhYVatmyZ8vPzNWPGjN4YPwAklaiivGHDBi1btkz33XefWlpalJ+fr29/+9tavnx5+DkPPPCA2tvbNW/ePLW2turWW2/V3r17lZGREffBA0CyiWqf8tXAPmXbePvCBt6+6Ft6bZ8yAKB3EWUAMISb3CMqyfbPZutvxyTb/964PFbKAGAIUQYAQ4gyABhClAHAEKIMAIaw+wL9GrsbYA0rZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAEOIMgAYQpQBwBCiDACGEGUAMIQoA4AhRBkADCHKAGAIUQYAQ4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYAhRBgBDiDIAGEKUAcAQogwAhhBlADCEKAOAIUQZAAwhygBgCFEGAENSEz2ACznnJEnvq0tyCR4MAMTB++qS9N++XYq5KLe1tUmSXtH/JngkABBfbW1t8vl8l3yOx32cdF9F3d3dOn36tLKystTW1qaCggI1NTUpOzs70UPrNaFQKOnnyRyTR3+YZ7zn6JxTW1ub8vPzlZJy6XeNza2UU1JSNHz4cEmSx+ORJGVnZyftL//D+sM8mWPy6A/zjOccL7dCPo8LfQBgCFEGAENMR9nr9WrFihXyer2JHkqv6g/zZI7Joz/MM5FzNHehDwD6M9MrZQDob4gyABhClAHAEKIMAIYQZQAwhCgDgCFEGQAMIcoAYMj/AfSkiCBBTAOCAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.matshow(cm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "base", - "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.8" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "a004f9109620e037dd6eb32a5065768d5476b766f6a5e98b9519dfa4bc5bb4ce" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/preprocessing/pipeline.py b/preprocessing/pipeline.py deleted file mode 100644 index a1ad191..0000000 --- a/preprocessing/pipeline.py +++ /dev/null @@ -1,166 +0,0 @@ -import loaders -import args - -import glob -import numpy as np -import pandas as pd -from scipy import io -from sklearn.pipeline import Pipeline -from sklearn.decomposition import PCA -from sklearn.preprocessing import StandardScaler -import matplotlib.pyplot as plt - -import vsdi_preprocessing -import vsdi_visualization -import loaders - -#################################### - -##################################### -############### MAIN ################ -##################################### - -# Define paths -path = '/home/danteam/Documents/BScThesis' -data = f'{path}/data' -reports = f'{path}/reports' -figures = f'{reports}/figures' - -# Get arguments from command line -parameters = args.getArgs() -subject = parameters.subject -day = parameters.day -session = parameters.session - -def save_vsdi(): - vsdi1 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi3 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi5 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi7 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/vsdi_ATC{session}.mat')[0])['vsdi_data'] - - vsdi1 = vsdi1[:,:,0:29999] - vsdi3 = vsdi3[:,:,0:29999] - vsdi5 = vsdi5[:,:,0:29999] - vsdi7 = vsdi7[:,:,0:29999] - - vsdi = np.concatenate((vsdi1, vsdi3, vsdi5, vsdi7), axis = 2) - - del(vsdi1) - del(vsdi3) - del(vsdi5) - del(vsdi7) - - # Outliers correction - vsdi_clean = vsdi_preprocessing.clean_outliers(vsdi, nsigma=5) - - # Hemodynamics correction - vsdi_clean = vsdi_preprocessing.clean_hemodynamic_pca(vsdi_clean, bimodal_th = 0.6, verbose = True) - - del(vsdi) - - ## Mask to select just subject cortex - r = np.loadtxt(f'{data}/Patterns/mask_A0{subject}.csv', delimiter=',', dtype='bool') - - X = vsdi_clean.transpose(2, 0, 1) - X = X[:,r] - - del(vsdi_clean) - - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=10)) - ]) - - out = pipe.fit(X) - - f = out.named_steps['pca'].components_ - factor_scores = pipe.named_steps['pca'].transform(X) - - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_timecourse_part1.csv', factor_scores, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_fingerprint_part1.csv', f, delimiter=",") - - return 0 - -def save_behav(): - atc1 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/ATC{session}.mat') - atc3 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/ATC{session}.mat') - atc5 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/ATC{session}.mat') - atc7 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/ATC{session}.mat') - b_data1 = loaders.extract_behavioural_data(atc1) - b_data3 = loaders.extract_behavioural_data(atc3) - b_data5 = loaders.extract_behavioural_data(atc5) - b_data7 = loaders.extract_behavioural_data(atc7) - - del(atc1) - del(atc3) - del(atc5) - del(atc7) - - d1 = vsdi_preprocessing.design_matrix(b_data1) - d3 = vsdi_preprocessing.design_matrix(b_data3) - d5 = vsdi_preprocessing.design_matrix(b_data5) - d7 = vsdi_preprocessing.design_matrix(b_data7) - - d1 = d1[0:29999,:] - d3 = d3[0:29999,:] - d5 = d5[0:29999,:] - d7 = d7[0:29999,:] - - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d1_part{session}.csv', d1, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d3_part{session}.csv', d3, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d5_part{session}.csv', d5, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d7_part{session}.csv', d7, delimiter=",") - - return 0 - -def mask_norm(masks, threshold=0.5): - mask_mean = np.mean(masks, axis=0) - mask_mean[mask_mean > threshold] = 1 - mask_mean[mask_mean <= threshold] = 0 - - return mask_mean - -def save_mask(): - r1 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day1.csv', r1, delimiter=",") - r3 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day3.csv', r3, delimiter=",") - r5 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day5.csv', r5, delimiter=",") - r7 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day7.csv', r7, delimiter=",") - - del(r1) - del(r3) - del(r5) - del(r7) - - r1 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day1.csv', delimiter=",") - r3 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day3.csv', delimiter=",") - r5 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day5.csv', delimiter=",") - r7 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day7.csv', delimiter=",") - - print(r1.shape, r3.shape, r5.shape, r7.shape) - - masks = np.stack([r1, r3, r5, r7]) - mask_mean = mask_norm(masks) - - np.savetxt(f'/home/danteam/Documents/BScThesis/data/Patterns/mask_A0{subject}.csv', mask_mean.astype(int), fmt='%i', delimiter=",") - - return 0 - - -def main(): - # print(f'Saving Mask A0{subject} part {session}') - # save_mask() - print(f'Saving VSDI subject A0{subject} part {session}') - save_vsdi() - print(f'Saving Design matrices A0{subject} part {session}') - save_behav() - - return 0 - - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/preprocessing/vsdi.py b/preprocessing/vsdi.py deleted file mode 100644 index abda7e0..0000000 --- a/preprocessing/vsdi.py +++ /dev/null @@ -1,164 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import matplotlib.pyplot as plt -import numpy as np -from scipy import stats -from scipy.stats import norm -from sklearn.decomposition import PCA -import seaborn as sns -sns.set_theme(context='notebook', - style='white', - font_scale=1.5, - rc = {'axes.spines.top':False,'axes.spines.right':False, - 'image.cmap':plt.cm.jet}) - -########################################################## -####################### VSDI CLASS ####################### -########################################################## - -class VSDI: - def __init__(self, vsdi, raw_mask): - """ - Constructor for VSDI class - """ - self.vsdi = self.correct_outliers(vsdi) - self.raw_mask = raw_mask - self.X = self.vsdi.transpose(2,0,1) # reshape in time x image format - self.T,self.h,self.w = self.X.shape # saves time, height and width for future use - self.X = self.X[:,self.raw_mask] # select only cortex pixels, returns a flattened image - - def time_course(self, start_time=0, end_time=600, framerate=50): - """ - Plot time course of a single PC - """ - plt.figure(figsize=(10, 5)) - t = np.linspace(start_time, end_time, int((end_time - start_time) * framerate - 1)) - plt.plot(t, self.vsdi) - plt.xlabel('Time (s)') - plt.ylabel('PC activation (a.u.)') - plt.show() - - def create_frame(self, t): - """ - Create a frame of the VSDI data - """ - plt.figure(figsize=(10, 10)) - plt.imshow(self.vsdi[:, :, t], cmap=plt.cm.inferno) - - def pca(self, n_components=50): - """ - Perform PCA on the VSDI data - """ - pca = PCA(n_components=n_components) - pca.fit(self.X) - - return pca - - def pca_projection(self, pca, num_pc): - """ - Plot the projection of the data onto the first 10 PCs - """ - PCs = pca.components_[:num_pc].T - Y = self.X @ PCs # compute the PC timecourse, by projecting the original data on each component - return Y - - def cumulative_explained_variance(self, pca): - """ - Plot cumulative explained variance - """ - evr = pca.explained_variance_ratio_ - c_evr = np.cumsum(evr) - plt.figure(figsize=(6, 6)) - plt.axhline(0.9, linestyle='--', label='90% explained variance') - plt.plot(range(1, len(c_evr) + 1), c_evr) - plt.legend() - plt.xlabel('# of components') - plt.ylabel('EVR') - - def fingerprint(self, pca, num_pc = 10): - """ - Plot topographic organzation of the weights of these ten components - """ - PCs = pca.components_[:num_pc] - plt.figure(figsize=(10, 5)) - for i, pc in enumerate(PCs): - plt.subplot(2, 5, i + 1) - plt.title(f'PC {i + 1}') - reshaped_pc = np.full((self.h, self.w), np.nan) - reshaped_pc[np.where(self.raw_mask)] = pc - plt.imshow(reshaped_pc, aspect='auto', cmap=plt.cm.jet) - plt.axis('off') - - def first_last_subsets(self, arr): - """ - Get first and last frame of each subset - """ - subsets = [] - start = 0 - end = 0 - while end < len(arr): - while end + 1 < len(arr) and arr[end + 1] - arr[start] == end - start + 1: - end += 1 - subsets.append((arr[start], arr[end])) - start = end = end + 1 - return np.array(subsets) - - def correct_outliers(self, vsdi, nsigma=4): - """ - Correct outliers in VSDI data - """ - # Array with average value of all frames in vsdi - mean_vsdi = np.mean(vsdi, axis=(0,1)) - std_vsdi = vsdi.std() - - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((mean_vsdi > nsigma*std_vsdi) | (mean_vsdi < -nsigma*std_vsdi)).ravel() - - # Get first and last frame of each subset - outliers_subsets = self.first_last_subsets(arr = outliers) - - # Set outlier frames to the mean between the previous and next frame - for i in range(len(outliers_subsets)): - start = outliers_subsets[i][0] - end = outliers_subsets[i][1] - if start == 0: - vsdi[:,:,start:end+1] = np.tile(vsdi[:,:,end+1][:, :, np.newaxis], (1, 1, end - start + 1)) - elif end == len(mean_vsdi)-1: - vsdi[:,:,start:end+1] = np.tile(vsdi[:,:,start-1][:, :, np.newaxis], (1, 1, end - start + 1)) - else: - average = np.divide(np.add(vsdi[:,:,start-1][:, :, np.newaxis], vsdi[:,:,end+1][:, :, np.newaxis]), 2) - vsdi[:,:,start:end+1] = average - return vsdi - - def bimodality_test(self, distribution): - """ - Test for bimodality using moving average to smooth the histogram - and get the x-axis location of the highest point in the histogram - """ - # Create a histogram - n, bins, patches = plt.hist(distribution, bins=1000) - # Define the window size for the moving average - window_size = 5 - # Create the moving average kernel - kernel = np.ones(window_size) / window_size - # Convolve the histogram data with the moving average kernel - smoothed = np.convolve(n, kernel, mode='same') - bins_adjusted = bins[:-1] - - # Find the x-axis location of the highest point in the histogram - x_max = bins_adjusted[np.argmax(smoothed)] - - return x_max - - def bimodal_components(self, Y, threshold=1): - """ - Get bimodal components - """ - bimodal_components = [] - for i in range(Y.shape[1]): - x_max = self.bimodality_test(Y[:,i]) - if abs(x_max) > threshold: - bimodal_components.append([i, x_max]) - - return bimodal_components \ No newline at end of file diff --git a/preprocessing/vsdi_preprocessing.py b/preprocessing/vsdi_preprocessing.py deleted file mode 100644 index b0f033d..0000000 --- a/preprocessing/vsdi_preprocessing.py +++ /dev/null @@ -1,379 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import numpy as np -from sklearn.decomposition import PCA, FastICA -from sklearn.preprocessing import StandardScaler -from sklearn.pipeline import Pipeline -import scipy.stats as stats -import statsmodels.api as sm - - -########################################################## - -def peak_distance(component, smooth_window_size, hist_nbins): - # Create a histogram - n, bins = np.histogram(component, bins=hist_nbins) - # Define the window size for the moving average - window_size = smooth_window_size - # Create the moving average kernel - kernel = np.ones(window_size) / window_size - # Convolve the histogram data with the moving average kernel - smoothed = np.convolve(n, kernel, mode='same') - bins_adjusted = bins[:-1] - # Find the x-axis location of the highest point in the histogram - x_max = bins_adjusted[np.argmax(smoothed)] - - return x_max - - -def check_bimodal(components, th=1.0, smooth_window_size=5, hist_nbins=1000): - """ - Test for bimodality using moving average to smooth the histogram - and get the x-axis location of the highest point in the histogram - - Parameters - ---------- - components : numpy ndarray (components, time) - Timecourse of a single component - threshold : float - Threshold for bimodal distribution identification (distance from peak to zero) - - Returns - ------- - bimodal_components : list - List of components that are bimodal (1 if bimodal, 0 if not) - """ - # Initialize bimodal_components list - bimodal_components = np.zeros(components.shape[0]) - for i in range(components.shape[0]): - # Get peak distance - x_max = peak_distance(components[i], smooth_window_size, hist_nbins) - # Check if peak distance is above threshold - if abs(x_max) > th: - bimodal_components[i] = 1 - - return bimodal_components - - -def clean_hemodynamic_pca(vsdi, n_components=50, bimodal_th=1, - smooth_window=5, hist_nbins=1000, verbose=False): - """ - Clean hemodynamic noise from vsdi data - - Parameters - ---------- - vsdi : numpy array - vsdi data in format (time, pixels_y, pixels_X) - n_components : int - Number of components to keep after PCA - bimodal_th : float - Threshold for bimodal distribution identification - smooth_window : int - Window size for smoothing the histogram of timecourse distribution - hist_nbins : int - Number of bins for histogram of timecourse distribution - - Returns - ------- - clean_vsdi : numpy array in the same format as vsdi input - vsdi data with hemodynamic noise removed - """ - # reshape vsdi data to (time, pixels) - vsdi = vsdi.transpose(2, 0, 1) - # store original shape - vsdi_shape = vsdi.shape - # flatten 2d pixels to array - vsdi = vsdi.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # put out-of-mask values to zero - - # run PCA - pca = PCA(n_components=n_components) - # fit PCA to vsdi data and project it to the new space - timecourses = pca.fit_transform(vsdi) - - # get bimodal components indexes - bad_components = check_bimodal(timecourses.T, th=bimodal_th, - smooth_window_size=smooth_window, - hist_nbins=hist_nbins) - - if verbose: - with open('log.txt', 'a') as f: - # Print explained variance ratio - f.write( - f'{sum(pca.explained_variance_ratio_[np.where(bad_components)]):.4f} ') - # Print number of components - f.write(f'{sum(bad_components):.0f}\n') - - # get clean timecourses and components - good_timecourses = timecourses[:, np.logical_not(bad_components)] - good_components = pca.components_[np.logical_not(bad_components)] - - # reconstruct vsdi data - clean_vsdi = good_timecourses @ good_components - clean_vsdi = clean_vsdi.reshape( - vsdi_shape[0], vsdi_shape[1], vsdi_shape[2]) - clean_vsdi = clean_vsdi.transpose(1, 2, 0) - - return clean_vsdi - - -def clean_hemodynamics(vsdi, n_components=50, bimodal_th=0.8, ica_max_iter=200, - smooth_window=5, hist_nbins=1000, verbose=False): - """ - Clean hemodynamic noise from vsdi data - - Parameters - ---------- - vsdi : numpy array - vsdi data in format (time, pixels_y, pixels_X) - n_components : int - Number of components to keep after PCA - bimodal_th : float - Threshold for bimodal distribution identification - smooth_window : int - Window size for smoothing the histogram of timecourse distribution - hist_nbins : int - Number of bins for histogram of timecourse distribution - - Returns - ------- - clean_vsdi : numpy array in the same format as vsdi input - vsdi data with hemodynamic noise removed - """ - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - vsdi_shape = vsdi.shape - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA and ICA - pipe = Pipeline([ - ('pca', PCA(n_components=n_components)), - ('ica', FastICA(n_components=n_components, max_iter=ica_max_iter, - random_state=88, whiten='unit-variance')) - ]) - - # Fit the pipeline to vsdi data - timecourses = pipe.fit_transform(X) - - # get bimodal components indexes - bad_components = check_bimodal(timecourses.T, th=bimodal_th, - smooth_window_size=smooth_window, - hist_nbins=hist_nbins) - - if verbose: - with open('log.txt', 'a') as f: - # Print number of components - f.write(f'{sum(bad_components):.0f}\n') - - # get clean timecourses and components - good_timecourses = timecourses[:, np.logical_not(bad_components)] - good_components = pipe.named_steps['ica'].components_[ - np.logical_not(bad_components)] - - # reconstruct vsdi data - clean_vsdi = good_components @ pipe.named_steps['pca'].components_ - clean_vsdi = good_timecourses @ clean_vsdi - clean_vsdi = clean_vsdi.reshape( - vsdi_shape[0], vsdi_shape[1], vsdi_shape[2]) - - return clean_vsdi - - -def find_outliers_old(vsdi, mean_vsdi, std_vsdi, nsigma=4): - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((mean_vsdi > nsigma*std_vsdi) - | (mean_vsdi < -nsigma*std_vsdi)).ravel() - - subsets = [] - start = 0 - end = 0 - - # Iterate over array - while end < len(outliers): - # Get first and last frame of each subset - while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: - end += 1 - # Save first and last frame of each outlier subset - subsets.append((outliers[start], outliers[end])) - start = end = end + 1 - - return np.array(subsets) - - -def find_outliers(vsdi, nsigma=6): - mean_vsdi = np.mean(vsdi, axis=(0, 1)) - # How many standard deviations away a value is from the mean - zscore = stats.zscore(mean_vsdi, axis=0, ddof=0, nan_policy='propagate') - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((zscore > nsigma) | (zscore < -nsigma)).ravel() - - subsets = [] - start = 0 - end = 0 - - # Iterate over array - while end < len(outliers): - # Get first and last frame of each subset - while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: - end += 1 - # Save first and last frame of each outlier subset - subsets.append((outliers[start], outliers[end])) - start = end = end + 1 - - return np.array(subsets) - - -def clean_outliers(vsdi, nsigma=6): - """ - Correct outliers in VSDI data - - Parameters - ---------- - vsdi : numpy ndarray - vsdi data in format (h, w, time) - nsigma : float - Number of standard deviations to consider an outlier - - Returns - ------- - vsdi : numpy ndarray - vsdi data with outliers corrected - """ - vsdi = vsdi.copy() - # Get first and last frame of each subset - outliers_subsets = find_outliers(vsdi, nsigma) - - # Set outlier frames to the mean between the previous and next frame - for i in range(len(outliers_subsets)): - start = outliers_subsets[i][0] - end = outliers_subsets[i][1] - if start == 0: - vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, end+1] - [:, :, np.newaxis], (1, 1, end - start + 1)) - elif end == vsdi.shape[2]-1: - vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, start-1] - [:, :, np.newaxis], (1, 1, end - start + 1)) - else: - average = np.divide(np.add( - vsdi[:, :, (start-1)][:, :, np.newaxis], vsdi[:, :, (end+1)][:, :, np.newaxis]), 2) - vsdi[:, :, start:end+1] = average - return vsdi - - -def design_matrix(b_data): - # Design matrix - # Returns a matrix of size (time, 6) with the following columns: - # 0: CS+ (2s) - # 1: CS+ trace (1s) - # 2: CS- (2s) - # 3: CS- trace (1s) - # 4: Reward (1s) - # 5: Lick - - fps = 50 - - Lick = b_data['Lick'] - CSp = b_data['CSp'] - CSn = b_data['CSn'] - frames = b_data['frames'] - - length = len(frames) - X = np.zeros((length, 6)) - - # Iterate over lick events - for i in range(len(Lick)): - frame = np.argmin(np.abs(frames - Lick[i])) - X[frame:frame+4, 5] = 1 - - # Iterate over CSp events - for i in range(len(CSp)): - frame = np.argmin(np.abs(frames - CSp[i])) - X[frame:frame + (fps * 2), 0] = 1 - frame += (fps * 2) + 1 - X[frame:frame + (fps * 1), 1] = 1 - frame += (fps * 1) + 1 - X[frame:frame + (fps * 1), 4] = 1 - - # Iterate over CSn events - for i in range(len(CSn)): - frame = np.argmin(np.abs(frames - CSn[i])) - X[frame:frame + (fps * 2), 2] = 1 - frame += (fps * 2) + 1 - X[frame:frame + (fps * 1), 3] = 1 - - return X - - -def pca(vsdi, raw_mask=None, n_comp=10, normalize=True): - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - # vsdi_shape = vsdi.shape - if raw_mask is not None: - # put out-of-mask values to zero - X = X[:, raw_mask] - else: - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=10)) - ]) - - # Fit the pipeline to vsdi data - out = pipe.fit(X) - fingerprints = out.named_steps['pca'].components_ - timecourses = fingerprints @ X.T - - return fingerprints, timecourses - - -def pca_ica(vsdi, raw_mask, n_comp=10,z_score = True,ica_random_state=42,ica_max_iter=200): - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - X = X*raw_mask - X = X.reshape(X.shape[0], X.shape[1]*X.shape[2]) - - if z_score: - X = StandardScaler().fit_transform(X) - - - # Create a pipeline with PCA and ICA - pipe = Pipeline([('pca', PCA(n_components=n_comp)), - ('ica', FastICA(n_components=n_comp, max_iter=ica_max_iter, - random_state=ica_random_state, whiten='unit-variance')) - ]) - - out = pipe.fit(X) - fingerprints = out.named_steps["ica"].components_ @ out.named_steps["pca"].components_ - timecourses = fingerprints @ X.T - - return fingerprints.reshape(n_comp,raw_mask.shape[0],raw_mask.shape[1]), timecourses - - -def glm(Y, X): - # Fit Gaussian GLMs - X = sm.add_constant(X) - model = sm.GLM(Y, X, family=sm.families.Gaussian()) - results = model.fit() - - return results - - -def merge_masks(masks, threshold=0.5): - """ - Merge masks by voting majority / logical OR - - Input: masks (n_masks, h, w) - Output: mask_mean (h, w) - """ - mask_mean = np.mean(masks, axis=0) - mask_mean[mask_mean > threshold] = 1 - mask_mean[mask_mean <= threshold] = 0 - return mask_mean diff --git a/preprocessing/vsdi_visualization.py b/preprocessing/vsdi_visualization.py deleted file mode 100644 index 961686d..0000000 --- a/preprocessing/vsdi_visualization.py +++ /dev/null @@ -1,170 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import matplotlib.pyplot as plt -import numpy as np -import seaborn as sns -from scipy.stats import sem -from scipy.ndimage import gaussian_filter1d -sns.set_theme(context='notebook', - style='white', - font_scale=1.5, - rc = {'axes.spines.top':False,'axes.spines.right':False, - 'image.cmap':plt.cm.jet}) - -########################################################## - -def plot_timecourse_histograms(timecourses, nbins_rule = 'freedman-diaconis'): - """ - Plot the histogram of the timecourses of the first 10 PCs - - Parameters - ---------- - timecourses : numpy.ndarray (n_timepoints, n_components) - Timecourses of the first 10 PCs - num_bins : int - Number of bins for the histogram - """ - plt.figure(figsize=(15, 25)) - - for i, tc in enumerate(timecourses.T): - # Freedman-Diaconis rulex - if nbins_rule == 'freedman-diaconis': - iqr = np.quantile(tc, 0.75) - np.quantile(tc, 0.25) - bin_width = (2 * iqr) / (len(tc) ** (1 / 3)) - nbins = int(np.ceil((tc.max() - tc.min()) / bin_width)) - - # Plot histogram - plt.subplot(5, 2, i+1) - plt.title(f'PC {i+1}') - plt.hist(tc, bins=nbins) - plt.xlim(-2*np.std(tc), 2*np.std(tc)) - -def plot_timecourses(timecourses): - """ - Plot the timecourses of the first 10 PCs - - Parameters - ---------- - timecourses : numpy.ndarray (n_timepoints, n_components) - Timecourses of the first 10 PCs - """ - start_time = 0 - end_time = 600 - # framerate = 50 - t = np.linspace(start_time,end_time,timecourses.shape[0]) - - plt.figure(figsize=(15, 25)) - for i, tc in enumerate(timecourses.T): - plt.subplot(5, 2, i+1) - plt.plot(t, tc) - plt.title(f'PC {i+1}') - -def plot_fingerprints(PCs, raw_mask): - """ - Plot the topographic organization of the weights of the first 10 PCs - - Parameters - ---------- - PCs : numpy ndarray - PCs matrix (n_components, n_pixels) - raw_mask : ndarray - Mask of the brain cortex - """ - plt.figure(figsize=(10,5)) - for i, pc in enumerate(PCs): - plt.subplot(2,5,i+1) - plt.title(f'PC {i+1}') - reshaped_pc = np.full((raw_mask.shape[0], raw_mask.shape[1]), np.nan) - reshaped_pc[np.where(raw_mask)] = pc - plt.imshow(reshaped_pc, aspect='auto', cmap=plt.cm.jet) - plt.axis('off') - -def create_frame(vsdi, t): - # VSDI - Should be already masked - plt.imshow(vsdi[:,:,t], cmap=plt.cm.jet) - plt.axis('off') - -def fingerprint_gif(vsdi, to, tf, step): - plt.figure(figsize=(20,15)) - for i, t in enumerate(range(to, tf, step)): - plt.subplot(1, step, i+1) - create_frame(vsdi, t) - -def plot_betas(results): - # Get the beta coefficients and their names - coefficients = results.params - names = ['Intercept'] + ["CS+ Onset", "CS+", "CS- Onset", "CS-", "Reward", "Lick"] - colors = ['#3C3C3C', '#1E70AA', '#8BBEE2', '#C11910', '#FFB3AF', 'green','#832F95'] - - # Plot the beta coefficients - plt.figure(figsize=(2, 3)) - plt.rc('xtick',labelsize=9) - plt.rc('ytick',labelsize=9) - plt.bar(names, coefficients, color=colors) - plt.xticks(ticks=range(len(names)), labels=names, rotation=-90) - # plt.show() - -def convert_pvalue_to_asterisks(pvalue): - if pvalue <= 0.0001: - return "****" - elif pvalue <= 0.001: - return "***" - elif pvalue <= 0.01: - return "**" - elif pvalue <= 0.05: - return "*" - return "" - -def timecourse_around(t, d, to, tf, feature, comp): - """ - Plot the timecourse of a given feature around a given timepoint - - Parameters - ---------- - t : numpy.ndarray (n_components, n_timepoints) - Timecourses of the first 10 PCs - d : numpy.ndarray (n_timepoints, n_features) - Design matrix - to : int - Start timepoint of interest - tf : int - Final timepoint - feature : int - Feature of interest in the following order: - ["CS+ Onset", "CS+", "CS- Onset", "CS-", "Reward", "Lick"] - comp : int - Principal component to plot - """ - - names = ["CS+", "CS+ Onset", "CS-", "CS- Onset", "Reward", "Lick"] - colors = ['#1E70AA', '#8BBEE2', '#C11910', '#FFB3AF', 'green', '#832F95'] - frame_rate = 50 - start_time = to - end_time = tf - peri_Y = [] # empty list for peri-lick timecourses - - for i, j in enumerate(d[:,feature]): - try: - if (j == 1) and d[(i-1),feature] == 0: - peri_Y.append(t[:,(i+(frame_rate*start_time)):(i+(frame_rate*end_time))]) # saves the slice of Y - except: - pass - - peri_Y = np.asarray(peri_Y) - mean_Y = np.mean(peri_Y, axis=0) # average over licks - error = sem(peri_Y, axis=0) # compute sem over licks - - y = mean_Y[comp-1,:] - err = error[comp-1,:] - - y = gaussian_filter1d(y,2) - err = gaussian_filter1d(err,2) - - t = np.linspace(start_time, end_time, int((end_time-start_time)*frame_rate)) - - plt.plot(t, y, color = colors[feature]) - plt.fill_between(t, y-err, y+err, alpha=0.2, color=colors[feature], cmap="Blues") - plt.xticks(np.arange(start_time, end_time+1, 1.0)) - plt.axvline(x=0,linestyle='--', color = "black", label=f'{names[feature]}') - plt.legend(prop={'size': 6}) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f0895a6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,23 @@ +[tool.poetry] +name = "vsdi" +version = "0.1.0" +description = "Preprocessing tools for voltage sensitive dye imaging data" +authors = ["NeuroNetMem"] +license = "MIT" +readme = "README.md" + +[tool.poetry.dependencies] +python = ">=3.9,<3.13" +scipy = "^1.10.1" +numpy = "^1.24.3" +tqdm = "^4.65.0" +statsmodels = "^0.14.0" +scikit-learn = "^1.2.2" +opencv-python = "^4.7.0.72" +statannotations = "^0.5.0" +h5py = "^3.8.0" +torch = "^2.0.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/vsdi/VAE.py b/vsdi/VAE.py new file mode 100644 index 0000000..c7e55b3 --- /dev/null +++ b/vsdi/VAE.py @@ -0,0 +1,365 @@ +""" +Module for Nonlinear Dimensionality Reduction. + +This module provides functionalities for training, analyzing and performing various operations with Convolutional Autoencoders (Conv_AE). The module is specifically designed for the purpose of training a convolutional autoencoder to compress image data into a low-dimensional latent representation and evaluate the quality of these representations. +""" + +import numpy as np +import torch +import torch.nn as nn +import torch.optim as optim +from torch.utils.data import DataLoader, TensorDataset +from tqdm import tqdm +from sklearn.linear_model import LinearRegression +from random import shuffle + +class Conv_AE(nn.Module): + """ + Convolutional Autoencoder (Conv_AE) Class. + + This class implements a convolutional autoencoder using PyTorch's nn.Module. + It includes an encoder and a decoder. The encoder compresses the input data + into a latent space, and the decoder reconstructs the original data from + the latent representation. The model is trained to minimize the difference + between the input and the output of the autoencoder. + """ + def __init__(self, latent_dim): + """ + Initializes the Conv_AE class. + + Parameters + ---------- + latent_dim : int + Dimensionality of the latent space. + """ + super(Conv_AE, self).__init__() + self.latent_dim = latent_dim + + # Encoder + self.encoder = nn.Sequential( + nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1), + nn.ReLU(), + nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1), + nn.ReLU(), + nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1), + nn.ReLU() + ) + + # Linear layer for mean and variance + self.fc = nn.Linear(64 * 84 * 48, self.latent_dim) + + # Decoder + self.decoder = nn.Sequential( + nn.Linear(self.latent_dim, 64 * 84 * 48), + nn.ReLU(), + nn.Unflatten(1, (64, 84, 48)), + nn.ConvTranspose2d(64, 32, kernel_size=3, stride=1, padding=1), + nn.ReLU(), + nn.ConvTranspose2d(32, 16, kernel_size=3, stride=1, padding=1), + nn.ReLU(), + nn.ConvTranspose2d(16, 1, kernel_size=3, stride=1, padding=1), + # nn.Tanh() + ) + + def forward(self, x): + """ + Passes the input through the encoder and decoder. + + Parameters + ---------- + x : torch.Tensor + The input to the autoencoder. + + Returns + ------- + reconstructed : torch.Tensor + The reconstructed input produced by the decoder. + + h : torch.Tensor + The latent representation of the input. + """ + # Encoder + encoded = self.encoder(x) + encoded = torch.flatten(encoded, start_dim=1) + + # Reparameterization + h = self.fc(encoded) + + # Decoder + reconstructed = self.decoder(h) + + return reconstructed, h + + def backward(self, optimizer, criterion, x, y_true): + """ + Computes the loss, performs backpropagation, and updates the model parameters. + + Parameters + ---------- + optimizer : torch.optim.Optimizer + The optimizer used to update the model parameters. + + criterion : torch.nn.modules.loss._Loss + The loss function used to measure the difference between the + reconstructed input and the original input. + + x : torch.Tensor + The input to the autoencoder. + + y_true : torch.Tensor + The true values (same as the input for an autoencoder). + + Returns + ------- + loss.item() : float + The computed loss value. + """ + optimizer.zero_grad() + y_pred, _ = self.forward(x) + mse = criterion(y_pred, y_true) + loss = mse + loss.backward() + optimizer.step() + return loss.item() + + +def create_dataloader(dataset, batch_size=128, reshuffle_after_epoch=True): + ''' + Creates a DataLoader for Pytorch to train the autoencoder with the image data converted to a tensor. + + Args: + dataset (4D numpy array): image dataset with shape (n_samples, n_channels, n_pixels_height, n_pixels_width). + batch_size (int; default=32): the size of the batch updates for the autoencoder training. + + Returns: + DataLoader (Pytorch DataLoader): dataloader that is ready to be used for training an autoencoder. + ''' + if dataset.shape[-1] == 3: + dataset = np.transpose(dataset, (0,3,1,2)) + tensor_dataset = TensorDataset(torch.from_numpy(dataset).float(), torch.from_numpy(dataset).float()) + return DataLoader(tensor_dataset, batch_size=batch_size, shuffle=reshuffle_after_epoch) + + +def train_autoencoder(model, train_loader, dataset=[], num_epochs=1000, learning_rate=1e-3, L2_weight_decay=0): + """ + Trains the autoencoder model. + + This function trains the autoencoder model using the Adam optimizer + and the Mean Squared Error loss function. It also tracks the history + of loss values for each epoch, and optionally, the evolution of the + latent vectors. + + Parameters + ---------- + model : Conv_AE + The autoencoder model to be trained. + + train_loader : torch.utils.data.DataLoader + The data loader that provides batches of training data. + + dataset : list, optional + If provided, this function will also track the evolution of the + latent vectors for each data point in this dataset. + + num_epochs : int, optional + The number of epochs for training the model. Default is 1000. + + learning_rate : float, optional + The learning rate for the Adam optimizer. Default is 1e-3. + + L2_weight_decay : float, optional + The weight decay (L2 penalty) for the Adam optimizer. Default is 0. + + Returns + ------- + history : list + A list containing the history of loss values for each epoch. + + embeddings : numpy.ndarray + A numpy array containing the evolution of the latent vectors + for each data point in the dataset (if provided). + """ + optimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=L2_weight_decay) + criterion = nn.MSELoss() + + model = model.to('cuda') + + history = [] + embeddings = [] + if len(dataset) > 0: + embeddings = [ get_latent_vectors(dataset=dataset, model=model) ] + for epoch in range(num_epochs): + running_loss = 0. + with tqdm(total=len(train_loader)) as pbar: + for i, data in enumerate(train_loader, 0): + inputs, _ = data + inputs = inputs.to('cuda') + + loss = model.backward(optimizer=optimizer, criterion=criterion, x=inputs, y_true=inputs) + running_loss += loss + + pbar.update(1) + pbar.set_description(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_loader):.4f}") + + history.append(running_loss/len(train_loader)) + + if len(dataset) > 0: + embeddings.append( get_latent_vectors(dataset=dataset, model=model) ) + + embeddings = np.array(embeddings) + + return history, embeddings + + +def predict(image, model): + ''' + Returns the output of model(image), and reshapes it to be compatible with plotting funtions such as plt.imshow(). + + Args: + image (3D numpy array): sample image with shape (n_channels, n_pixels_height, n_pixels_width). + model (Pytorch Module): convolutional autoencoder that is prepared to process images such as 'image'. + + Returns: + output_img (3D numpy array): output image with shape (n_pixels_height, n_pixels_width, n_channels) + ''' + if image.shape[-1] <= 4: + image = np.transpose(image, (2,0,1)) + n_channels, n_pixels_height, n_pixels_width = image.shape + image = np.reshape(image, (1, n_channels, n_pixels_height, n_pixels_width)) + image = torch.from_numpy(image).float().to(next(model.parameters()).device) + output_img = model(image)[0].detach().cpu().numpy() + output_img = np.reshape(output_img, (n_channels, n_pixels_height, n_pixels_width)) + output_img = np.transpose(output_img, (1,2,0)) + return output_img + + +def get_latent_vectors(dataset, model, batch_size=128): + ''' + Returns the latent activation vectors of the autoencoder model after passing all the images in the dataset. + + Args: + dataset (numpy array): image dataset with shape + model (Pytorch Module): convolutional autoencoder that is prepared to process the images in dataset. + + Returns: + latent_vectors (2D numpy array): latent activation vectors, matrix with shape (n_samples, n_hidden), where n_hidden is the number of units in the hidden layer. + ''' + if dataset.shape[-1] <= 4: + dataset = np.transpose(dataset, (0,3,1,2)) + tensor_dataset = TensorDataset(torch.from_numpy(dataset).float(), torch.from_numpy(dataset).float()) + data_loader = DataLoader(tensor_dataset, batch_size=batch_size, shuffle=False) + model.eval() + latent_vectors = [] + with torch.no_grad(): + for batch in data_loader: + inputs, _ = batch + latent = model(inputs.to('cuda'))[1] + latent_vectors.append(latent.cpu().numpy()) + latent_vectors = np.concatenate(latent_vectors) + return latent_vectors + + +def find_max_activation_images(model, n_hidden, img_shape=[1, 84, 49]): + images = [] + for i in range(n_hidden): + # Initialize input image + x = torch.randn(1, img_shape[0], img_shape[1], img_shape[2], device='cuda', requires_grad=True) + + # Use optimizer to perform gradient ascent + optimizer = optim.Adam([x], lr=1e-3) + + for j in range(1000): + optimizer.zero_grad() + _, mu, _ = model(x) + loss = -mu[0, i] # maximize activation of ith unit + loss.backward() + optimizer.step() + + # Add image to list + images.append(x.detach().cpu().numpy()[0, 0]) + + return np.array(images) + + +def shuffle_2D_matrix(m): + ''' + Shuffles a matrix across both axis (not only the first axis like numpy.permutation() or random.shuffle()). + + Args: + m (2D numpy array): 2D matrix with arbitrary values. + + Returns: + m_shuffled (2D numpy array): the original matrix 'm', with all the elements shuffled randomly. + ''' + N = m.size + ind_shuffled = np.arange(N) + shuffle(ind_shuffled) + ind_shuffled = ind_shuffled.reshape((m.shape[0], m.shape[1])) + ind_x = (ind_shuffled/m.shape[1]).astype(np.int_) + ind_y = (ind_shuffled%m.shape[1]).astype(np.int_) + m_shuffled = m[ind_x, ind_y] + return m_shuffled + + +def linear_decoding_score(embeddings, features, n_baseline=10000): + ''' + Computes the score of linear regression of embeddings --> features. Features will normally be position (x,y) + or orientation (radians or in vectorial form). + + Args: + embeddings (2D numpy array): 2D matrix containing the independent variable, with shape (n_samples, n_latent). + features (2D numpy array): 2D matrix containing the dependent variable, with shape (n_samples, n_features). + n_baseline (int; default=10000): number of permutation tests (i.e., shuffling the embeddings matrix) to compute the baseline. + + Returns: + scores (float list): a list with two scores: (1) the evaluation of the linear regression, and (2) an average & std + of n_baseline random permutation tests. + ''' + linear_model = LinearRegression() + linear_model.fit(embeddings, features) + linear_score = linear_model.score(embeddings, features) + + baselines = [] + for i in range(n_baseline): + embeddings_shuffled = shuffle_2D_matrix(np.copy(embeddings)) + linear_model_baseline = LinearRegression() + linear_model_baseline.fit(embeddings_shuffled, features) + random_score = linear_model_baseline.score(embeddings_shuffled, features) + baselines.append(random_score) + + baseline_score = [np.mean(baselines), np.std(baselines)] + ratio = linear_score/(baseline_score[0]) + return linear_score, baseline_score, ratio + + +def linear_decoding_error(embeddings, features, norm=1): + ''' + Computes the expected error of a linear decoder that uses the embeddings to predicts features (e.g. position in (x,y)). + + Args: + embeddings (2D numpy array): 2D matrix containing the independent variable, with shape (n_samples, n_latent). + features (2D numpy array): 2D matrix containing the dependent variable, with shape (n_samples, n_features). + norm (float; default=1): value used to normalize the MSE and bring it to a more convenient scale. + + Returns: + mean_dist (float): average euclidean distance between the predictions of the decoder and the actual features, normalized by a scalar. + ''' + linear_model = LinearRegression() + linear_model.fit(embeddings, features) + pred = linear_model.predict(embeddings) + + dist = np.sqrt(np.sum((pred - features)**2, axis=1)) + mean_dist = np.mean(dist) / norm + + return mean_dist + +def extract_hidden_features(model, clamping_value=1.): + features = [] + for i in np.arange(model.latent_dim): + input_ = torch.zeros(model.latent_dim).to('cuda') + input_[i] = clamping_value + input_ = input_.unsqueeze(0) + img = model.decoder(input_)[0].detach().cpu().numpy() + features.append(np.transpose(img, (1,2,0))) + + return np.array(features) diff --git a/__init__.py b/vsdi/__init__.py similarity index 100% rename from __init__.py rename to vsdi/__init__.py diff --git a/vsdi/clustering.py b/vsdi/clustering.py deleted file mode 100644 index e138467..0000000 --- a/vsdi/clustering.py +++ /dev/null @@ -1,46 +0,0 @@ -import numpy as np -from scipy.spatial.distance import pdist, squareform -from sklearn.cluster import KMeans -from sklearn.manifold import TSNE -import matplotlib.pyplot as plt - -def compute_distance_matrix(arr_list): - """ - Given a list of 2D arrays, compute the pairwise distance matrix using Pearson correlation. - """ - # Get the number of arrays in the list - n_arrays = len(arr_list) - # Create an empty distance matrix with shape (n_arrays, n_arrays) - dist_mat = np.zeros((n_arrays, n_arrays)) - # Compute the pairwise distance between all pairs of arrays using Pearson correlation - for i in range(n_arrays): - for j in range(i+1, n_arrays): - corr = np.corrcoef(arr_list[i], arr_list[j])[0, 1] - dist = 1 - np.abs(corr) - dist_mat[i, j] = dist - dist_mat[j, i] = dist - # Return the distance matrix - return dist_mat - -def cluster_and_plot(arr_list, kind='betas'): - """ - Given a list of 2D arrays, compute the pairwise distance matrix, cluster it using k-means, - and plot the t-SNE projection of the distance matrix, colored by the cluster labels. - """ - # Compute the distance matrix using Pearson correlation - dist_mat = compute_distance_matrix(arr_list) - # Set the number of clusters for k-means - n_clusters = 10 - # Apply k-means clustering to the distance matrix - kmeans = KMeans(n_clusters=n_clusters) - labels = kmeans.fit_predict(dist_mat) - # Compute the t-SNE projection of the distance matrix - tsne = TSNE(n_components=2, perplexity=30, random_state=42) - emb = tsne.fit_transform(dist_mat) - # Plot the t-SNE projection, coloring each point by its cluster label - fig, ax = plt.subplots(figsize=(8, 8)) - scatter = ax.scatter(emb[:,0], emb[:,1], c=labels, cmap='viridis') - legend = ax.legend(*scatter.legend_elements(), loc="lower left", title="Clusters") - ax.add_artist(legend) - ax.set_title(f"t-SNE projection of {kind} distance matrix") - plt.show() diff --git a/vsdi/dim_reduction.py b/vsdi/dim_reduction.py new file mode 100644 index 0000000..f678b9f --- /dev/null +++ b/vsdi/dim_reduction.py @@ -0,0 +1,126 @@ +""" +Linear Dimensionality Reduction Module. + +This module provides functionalities for performing Principal Component Analysis (PCA) and Independent Component Analysis (ICA) +on Voltage Sensitive Dye Imaging (VSDI) data. + +Functions: + - pca(vsdi, raw_mask=None, n_comp=10, normalize=True): Performs PCA on VSDI data and returns the principal components (fingerprints) and their corresponding timecourses. + - pca_ica(vsdi, mask): Performs PCA followed by ICA on VSDI data and returns the fingerprint patterns and their timecourses obtained from ICA, along with explained variance ratios from PCA. + +Dependencies: + - sklearn.decomposition: PCA, FastICA + - sklearn.preprocessing: StandardScaler + - sklearn.pipeline: Pipeline + +This module is designed for applying dimensionality reduction techniques to VSDI data, which is commonly used in neuroscience for imaging brain activity. +""" + +# Dimensionality reduction +from sklearn.decomposition import PCA, FastICA +from sklearn.preprocessing import StandardScaler +from sklearn.pipeline import Pipeline + +def pca(vsdi, raw_mask=None, n_comp=10, normalize=True): + """ + Perform Principal Component Analysis (PCA) on vsdi data. + + The function reshapes the vsdi data, optionally applies a raw mask, and then performs PCA on the reshaped data. + It returns the principal components (also known as "fingerprints") and their corresponding timecourses. + + Parameters + ---------- + vsdi : ndarray + The input vsdi data to be analyzed. It should be a 3D numpy array with dimensions (height, width, time). + + raw_mask : ndarray, optional + A mask to be applied to the vsdi data. The mask should be a 2D numpy array with the same spatial dimensions + as the vsdi data. Pixels outside the mask are set to zero. If None, no mask is applied. Default is None. + + n_comp : int, optional + The number of principal components to compute. Default is 10. + + normalize : bool, optional + Whether to normalize the input data before performing PCA. If True, the data are normalized to have zero mean + and unit variance. Default is True. + + Returns + ------- + fingerprints : ndarray + The principal components of the vsdi data. This is a 2D numpy array where each row corresponds to a principal + component and each column corresponds to a pixel. The components are ordered by their explained variance, with + the component that explains the most variance first. + + timecourses : ndarray + The timecourses corresponding to each principal component. This is a 2D numpy array where each row corresponds + to a principal component and each column corresponds to a time point. + + Examples + -------- + >>> vsdi_data = np.random.rand(100, 100, 1000) # Mock vsdi data + >>> fingerprints, timecourses = pca(vsdi_data) + """ + # reshape vsdi data to (time, pixels) + X = vsdi.transpose(2, 0, 1) + # store original shape + # vsdi_shape = vsdi.shape + if raw_mask is not None: + # put out-of-mask values to zero + X = X[:, raw_mask] + else: + # flatten 2d pixels to array + X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) + + # Create a pipeline with PCA + pipe = Pipeline([ + ('scaler', StandardScaler()), + ('pca', PCA(n_components=10)) + ]) + + # Fit the pipeline to vsdi data + out = pipe.fit(X) + fingerprints = out.named_steps['pca'].components_ + timecourses = fingerprints @ X.T + + return fingerprints, timecourses + + +def pca_ica(vsdi, mask): + """ + Perform PCA and ICA on VSDI data. + + Parameters + ---------- + vsdi : ndarray + Array containing VSDI data. + mask : ndarray + Array representing the mask to be applied to the VSDI data. + + Returns + ------- + fingerprints : ndarray + Array containing the fingerprint patterns obtained from ICA. + timecourses : ndarray + Array containing the timecourses obtained from ICA. + explained_variance : ndarray + Array containing the explained variance ratios from PCA. + """ + X = vsdi.transpose(2, 0, 1) + X = X*mask + X = X.reshape(X.shape[0], X.shape[1]*X.shape[2]) + + # Create a pipeline with PCA and ICA + pipe = Pipeline([ + ('pca', PCA(n_components=10)), + ('ica', FastICA(n_components=10, max_iter=200, + random_state=1, whiten='unit-variance')) + ]) + + out = pipe.fit(X) + + fingerprints = out.named_steps["ica"].components_ @ out.named_steps["pca"].components_ + timecourses = fingerprints @ X.T + + explained_variance = out.named_steps["pca"].explained_variance_ratio_ + + return fingerprints, timecourses, explained_variance diff --git a/vsdi/embeddings.py b/vsdi/embeddings.py new file mode 100644 index 0000000..f082be0 --- /dev/null +++ b/vsdi/embeddings.py @@ -0,0 +1,199 @@ +""" +This module provides a `DataLoader` class for handling VSDI (Voltage-Sensitive Dye Imaging) data stored in HDF5 files. + +Dependencies +------------ +- numpy +- scipy +- h5py +- loaders (imported but not defined within this file) +- pipeline_vsdi.preprocessing.utils (imported but not defined within this file) + +Usage +----- +1. Create a `DataLoader` instance by providing the path to the HDF5 file and the directory containing the VSI data files. +2. Use the `load_data` method to load VSI data into the HDF5 file. +3. Use the `clean_vsdi` method to clean VSDI data by removing outliers. +4. Use the `get_data` method to retrieve data from the HDF5 file. +""" + +from scipy.io import loadmat +import h5py +import vsdi.io as loaders +from vsdi.utils import make_design_matrix + +class DataLoader: + """ + Handling VSDI data full dataset using HDF5 files + + Parameters + ---------- + filepath : str + Path to the HDF5 file to be loaded. + """ + def __init__(self, filepath): + """Initialize the DataLoader.""" + self.filepath = filepath + + def __enter__(self): + """ + Enter method for the DataLoader context manager. + + Returns + ------- + self : DataLoader + The DataLoader instance. + """ + self.file = h5py.File(self.filepath, 'a') + return self + + def __exit__(self, type, value, traceback): + """Exit method for the DataLoader context manager.""" + self.file.close() + + def load_data(self, datapath, animals, days, sessions, event_sequences): + """ + Load VSI data into the HDF5 file. + + Parameters + ---------- + animals : list + List of animal names. + days : list + List of day names. + sessions : list + List of session names. + """ + for animal in animals: + animal_group = self.file.require_group(animal) + + for day in days: + day_group = animal_group.require_group(day) + + # Load mask file for each day + mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask'] + if 'mask' in day_group: + del day_group['mask'] + day_group.create_dataset('mask', data=mask) + + for session in sessions: + session_group = day_group.require_group(session) + + # Load matlab behavioural file + atc = loadmat(datapath.joinpath(f'{animal}/{day}/{session}.mat')) + + # Extract dictionary + b_data = loaders.extract_behavioural_data(atc) + # Create ndarray design matrix + X_matrix = make_design_matrix(b_data, event_sequences) + + if 'behavioral' in session_group: + del session_group['behavioral'] + session_group.create_dataset('behavioral', data=X_matrix) + + # Load VSDI + vsdi = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_{session}.mat'))['vsdi_data'] + + if 'vsdi' in session_group: + del session_group['vsdi'] + session_group.create_dataset('vsdi', data=vsdi) + + # Extract LFP data + lfp = loaders.extract_lfp_data(atc) + + if 'lfp' in session_group: + del session_group['lfp'] + session_group.create_dataset('lfp', data=lfp) + + def clean_vsdi(self, animal=None, day=None, session=None, nsigma=3): + """ + Clean VSDI data by removing outliers. + + Parameters + ---------- + animal : str, optional + Animal name. + day : str, optional + Day name. + session : str, optional + Session name. + nsigma : int, optional + Number of standard deviations for outlier removal. + """ + def clean(vsdi, mask): + # Normalize vsdi + vsdi_norm = normalize_vsdi(vsdi, mask) + # Clean outliers + vsdi_clean = clean_outliers(vsdi_norm, nsigma) + # Clean outliers by mean interpolation + return vsdi_clean + + def apply_clean(group, mask): + if isinstance(group, h5py.Dataset): + # Assuming 'vsdi', 'animal', 'day', 'session' are keys, not attributes + if group.name.split('/')[-1] == 'vsdi': + vsdi_data = group[...] + vsdi_data_cleaned = clean(vsdi_data, mask) + # Create a new dataset for cleaned VSDI data + if 'vsdi_clean' in group.parent: + del group.parent['vsdi_clean'] + group.parent.create_dataset('vsdi_clean', data=vsdi_data_cleaned) + else: + for key in group: + apply_clean(group[key], mask) + + if animal is not None and day is not None and session is not None: + mask = self.file[f"{animal}/{day}"]['mask'][...] + group = self.file[f"{animal}/{day}/{session}"] + apply_clean(group, mask) + elif animal is not None and day is not None: + mask = self.file[f"{animal}/{day}"]['mask'][...] + group = self.file[f"{animal}/{day}"] + apply_clean(group, mask) + elif animal is not None: + for day in self.file[animal].keys(): + mask = self.file[f"{animal}/{day}"]['mask'][...] + group = self.file[animal][day] + apply_clean(group, mask) + else: + for animal in self.file.keys(): + for day in self.file[animal].keys(): + mask = self.file[f"{animal}/{day}"]['mask'][...] + group = self.file[animal][day] + apply_clean(group, mask) + + def get_data(self, animal=None, day=None, session=None, type=None): + """ + Get data from the HDF5 file. + + Parameters + ---------- + animal : str, optional + Animal name. + day : str or list, optional + Day name or list of day names. + session : str, optional + Session name. + type : str, optional + Type of data. + + Returns + ------- + result : list + List of tuples containing the group name and data array. + """ + days = [day] if isinstance(day, str) else day + + def search(group): + result = [] + for key in group: + if isinstance(group[key], h5py.Group): + result.extend(search(group[key])) + elif ((animal is None or group.name.split('/')[1] == animal) and + (days is None or group.name.split('/')[2] in days) and + (session is None or group.name.split('/')[3] == session) and + (type is None or key == type)): + result.append((group.name.split('/')[1:], group[key][...])) + return result + + return search(self.file) diff --git a/vsdi/io.py b/vsdi/io.py new file mode 100644 index 0000000..c1beb04 --- /dev/null +++ b/vsdi/io.py @@ -0,0 +1,151 @@ +""" +This module contains functions to read and extract data from ATC (Assistive Technology Comparison) data objects. + +The ATC data objects are expected to be a dictionary like objects that represent the contents of .mat files, +which contain various fields of data related to behavioural experiments. + +The key functions in the module include: + +- read_data_fields: This function reads and prints the names and shapes of data fields in the given ATC data object. + +- extract_behavioural_data: This function extracts specific behavioural data fields from an ATC data object. + +- extract_lfp_data: This function extracts the local field potential (LFP) data from the given ATC data object. + +Please refer to the individual function docstrings for more detailed information on their usage and output. + +Example usage: + +>>> import scipy.io +>>> atc_data = scipy.io.loadmat('data.mat') # Load .mat file +>>> read_data_fields(atc_data) +>>> extracted_data = extract_behavioural_data(atc_data) +>>> lfp_data = extract_lfp_data(atc_data) +""" + +import numpy as np + + +def read_data_fields(atc_data): + """ + Reads and prints the names and shapes of data fields in the given ATC data object. + + This function reads the fields from the input ATC data object and then prints out each field's name and shape. + + Parameters + ---------- + atc_data : dictionary + The input ATC data object which contains multiple fields. It's expected to be a dictionary + like object (such as .mat file) that contains data fields. + + Returns + ------- + None + + Prints + ------ + For each field in the ATC data object, its name and shape are printed to the console. + + Examples + -------- + >>> atc_data = loadmat('data.mat') # Load .mat file with scipy.io.loadmat + >>> read_data_fields(atc_data) + """ + data = atc_data['Data_OE'][0][0] + names = np.asarray(atc_data['Data_OE'][0][0].dtype.names) + for i, k in enumerate(names): + print(f'{k}:{data[i].shape}') + + +def extract_behavioural_data(atc_data): + """ + Extracts specific behavioural data fields from an ATC data object. + + This function reads fields from the input ATC data, checks if the required fields are present, + and then extracts and flattens the required fields. + + Parameters + ---------- + atc_data : dictionary + The input ATC data object which contains multiple fields. It's expected to be a dictionary + like object (such as .mat file) that contains data fields. + + Returns + ------- + extracted_data : dictionary + A dictionary containing the extracted data for each of the required fields. Each field + is flattened and represented as a 1-D array. + + Raises + ------ + TypeError + If a required field is not found in the ATC data object, a TypeError is raised indicating + the missing field. + + Notes + ----- + The fields to be extracted are defined in the `to_extract` variable within the function. + Currently, these include 'CSp', 'CSn', 'Lick', and 'frames'. If other fields are needed, + this list should be updated accordingly. + + Examples + -------- + >>> atc_data = loadmat('data.mat') # Load .mat file with scipy.io.loadmat + >>> extracted_data = extract_behavioural_data(atc_data) + """ + # reads daa fields in input .mat file + names = np.asarray(atc_data['Data_OE'][0][0].dtype.names) + # fields to extract + to_extract = ['CSp', 'CSn', 'Lick', 'frames'] + extracted_data = {} + for k in to_extract: + # check if field is in data + if not (k in names): + raise TypeError(f' field name {k} not found in data structure') + # find index corresponding to field name + idx = np.where(names == k)[0][0] + # extract data, flattens them + extracted_data[k] = atc_data['Data_OE'][0][0][idx].flatten() + + return extracted_data + + +def extract_lfp_data(atc_data): + """ + Extracts the local field potential (LFP) data from the given ATC data object. + + This function reads the input ATC data object, checks if it contains the 'HPC_LFP' field, + and then extracts and returns the 'HPC_LFP' data. The 'HPC_LFP' data are flattened and stacked vertically. + + Parameters + ---------- + atc_data : dictionary + The input ATC data object which contains multiple fields including 'HPC_LFP'. It's expected to be a + dictionary like object (such as .mat file) that contains data fields. + + Returns + ------- + lfp : ndarray + A 2-D numpy array that contains the extracted 'HPC_LFP' data. Each sub-array is flattened and + the sub-arrays are stacked vertically. + + Raises + ------ + TypeError + If the 'HPC_LFP' field is not found in the ATC data object. + + Examples + -------- + >>> atc_data = loadmat('data.mat') # Load .mat file with scipy.io.loadmat + >>> lfp_data = extract_lfp_data(atc_data) + """ + names = np.asarray(atc_data['Data_OE'][0][0].dtype.names) + lfp_name = 'HPC_LFP' + if not lfp_name in names: + raise TypeError(f'{lfp_name} not found in data structure') + + lfp_idx = np.where(names == lfp_name)[0][0] + lfp_data = atc_data['Data_OE'][0][0][lfp_idx][0] + lfp = np.vstack([i.flatten() for i in lfp_data]) + + return lfp diff --git a/vsdi/pca_ica.ipynb b/vsdi/pca_ica.ipynb deleted file mode 100644 index 71b27e7..0000000 --- a/vsdi/pca_ica.ipynb +++ /dev/null @@ -1,356 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import sys\n", - "import os\n", - "sys.path.append(os.path.abspath('../'))\n", - "from scipy.io import loadmat\n", - "import loaders\n", - "from vsdi_preprocessing import clean_outliers,pca_ica,glm\n", - "from pathlib import Path" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "datapath = Path('/ceph/imaging1/davide/ATC_Data_preprocessed')\n", - "atc = loadmat(datapath.joinpath('A04/Day1/ATC1.mat'))\n", - "vsdi = loadmat(datapath.joinpath('A04/Day1/vsdi_ATC1.mat'))['vsdi_data']\n", - "mask = loadmat(datapath.joinpath(f'A04/Day1/vsdi_mask.mat'))['mask']\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(94, 54, 29999)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vsdi.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.decomposition import PCA, FastICA\n", - "from sklearn.preprocessing import StandardScaler\n", - "from sklearn.pipeline import Pipeline\n", - "\n", - "def pca_ica(vsdi,mask):\n", - " X = vsdi.transpose(2, 0, 1)\n", - " X = X*mask\n", - " X = X.reshape(X.shape[0], X.shape[1]*X.shape[2])\n", - "\n", - " # Create a pipeline with PCA and ICA\n", - " pipe = Pipeline([\n", - " ('scaler', StandardScaler()),\n", - " ('pca', PCA(n_components=10)),\n", - " ('ica', FastICA(n_components=10, max_iter=200,\n", - " random_state=1, whiten='unit-variance'))\n", - " ])\n", - "\n", - " out = pipe.fit(X)\n", - "\n", - " fingerprints = out.named_steps[\"ica\"].components_ @ out.named_steps[\"pca\"].components_\n", - " timecourses = fingerprints @ X.T\n", - "\n", - " return fingerprints,timecourses\n", - "\n", - "clean_vsdi = clean_outliers(vsdi,nsigma=5)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "'numpy.ndarray' object is not callable", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[23], line 11\u001b[0m\n\u001b[1;32m 8\u001b[0m vsdi2 \u001b[39m=\u001b[39m loadmat(datapath\u001b[39m.\u001b[39mjoinpath(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00manimal\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mday\u001b[39m}\u001b[39;00m\u001b[39m/vsdi_ATC2.mat\u001b[39m\u001b[39m'\u001b[39m))[\u001b[39m'\u001b[39m\u001b[39mvsdi_data\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[1;32m 9\u001b[0m mask \u001b[39m=\u001b[39m loadmat(datapath\u001b[39m.\u001b[39mjoinpath(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00manimal\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mday\u001b[39m}\u001b[39;00m\u001b[39m/vsdi_mask.mat\u001b[39m\u001b[39m'\u001b[39m))[\u001b[39m'\u001b[39m\u001b[39mmask\u001b[39m\u001b[39m'\u001b[39m]\n\u001b[0;32m---> 11\u001b[0m vsd1 \u001b[39m=\u001b[39m clean_vsdi(vsdi1,nsigma\u001b[39m=\u001b[39;49m\u001b[39m5\u001b[39;49m)\n\u001b[1;32m 12\u001b[0m vsdi2 \u001b[39m=\u001b[39m clean_vsdi(vsdi2,nsigma\u001b[39m=\u001b[39m\u001b[39m5\u001b[39m)\n\u001b[1;32m 14\u001b[0m vsdi \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mdstack([vsdi1,vsdi2])\n", - "\u001b[0;31mTypeError\u001b[0m: 'numpy.ndarray' object is not callable" - ] - } - ], - "source": [ - "animals = ['A04']\n", - "days = ['Day1','Day3','Day5','Day7']\n", - "\n", - "for animal in animals:\n", - " vsdi_total = []\n", - " for day in days:\n", - " vsdi1 = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_ATC1.mat'))['vsdi_data']\n", - " vsdi2 = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_ATC2.mat'))['vsdi_data']\n", - " mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask']\n", - "\n", - " vsd1 = clean_vsdi(vsdi1,nsigma=5)\n", - " vsdi2 = clean_vsdi(vsdi2,nsigma=5)\n", - "\n", - " vsdi = np.dstack([vsdi1,vsdi2])\n", - " print(vsdi.shape)\n", - " vsdi_total.append(vsdi1)\n", - "\n", - "vsdi_total = np.dstack(vsdi_total)\n", - "print('Done')\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pca_ica(vsdi_total,mask)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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XZl9fvWrX8Xxxx+Pzs5OdHZ2Yt26dfjpT3865f7S+PznP4+6ujpcdNFF+9Xvpz71KdTV1ZX9rV27dlrPVVQiO5AdiP2zA2D6bUF2IDs4GMwFOwBm3hZkB7VN3uwAmNv3hANmB1HOuPbaa6Pm5uboW9/6VvSrX/0qet/73hcVCoVo165dE/r8T37yk+jv//7vox/+8IcRgOi6664r2//5z38+6urqiq6//vrowQcfjN785jdHa9asifbu3ZvZ59lnnx1dc8010datW6MHHnggeuMb3xitWrUq6u/vj4/5wAc+EB122GHR5s2bo3vuuSc644wzojPPPDOzzx//+MfRjTfeGD3++OPRtm3bor/7u7+Lmpqaoq1bt06pP89dd90VrV69Ojr++OOjj3zkI1M+zyiKossuuyw69thjox07dsR/L7zwwn71KaojO5AdiP23gyiafluQHcgODjRzxQ6iaGZtQXZQ2+TRDqJobt8TDpQd5O5l9bTTTos2bNgQr4+OjkYrVqyINm3aNOm+/EAcGxuLli1bFl1++eXxtmKxGLW0tET/8R//MeF+u7u7IwDRli1b4j6ampqi73//+/Exjz76aAQguuOOOybc74IFC6JvfOMb+91fX19fdNRRR0U333xz9Ad/8AfxQJxqv5dddll0wgknpO6brt8uypEdyA7E9NpBFM2MLcgOEmQHM8NctoMomh5bkB3UPrVgB1E0t+4JB8oOchUGPDw8jHvvvRfr16+Pt9XX12P9+vW444479rv/p556Cjt37izrv6urC6effvqk+u/p6QEALFy4EABw7733YmRkpKzftWvXYtWqVRPqd3R0FNdeey327NmDdevW7Xd/GzZswDnnnFP2+f09zyeeeAIrVqzAEUccgfPPPx/PPPPMtPx2UYnsQHYgZt4OgOmxBdmB7GAmmat2AEyvLcgOaptasQNg7t0TDoQdNE7q6BnmxRdfxOjoKJYuXVq2fenSpXjsscf2u/+dO3fG/fn+uW88xsbGcNFFF+FVr3oVjjvuuLjf5uZmFAqFSfX78MMPY926dRgcHER7ezuuu+46HHPMMXjggQem1B8AXHvttbjvvvtw9913V+yb6nmefvrp+Pa3v42Xv/zl2LFjBz796U/j93//97F169Yp9ymykR3IDsTM2wGw/7YgO5AdzDRzzQ6A6bcF2UHtUwt2AMy9e8KBsoNcvazWAhs2bMDWrVvx85//fL/7evnLX44HHngAPT09+MEPfoALLrgAW7ZsmXJ/zz77LD7ykY/g5ptvRmtr636fH3nDG94QLx9//PE4/fTTcfjhh+N73/se2trapu17RO0gO5AdCNmB7EAA02sHwPTaguxAHEjm2j3hQNlBrsKAFy9ejIaGhopKUbt27cKyZcv2u3/2MdX+L7zwQtxwww342c9+hpUrV5b1Ozw8jGKxOKl+m5ubceSRR+Lkk0/Gpk2bcMIJJ+Cf/umfptzfvffei+7ubpx00klobGxEY2MjtmzZgquuugqNjY1YunTplPr1FAoFHH300XjyySenfK4iG9mB7EDMvB0A+2cLsoMSsoOZZa7ZATC9tiA7mB3k3Q4A3ROAmbODXL2sNjc34+STT8bmzZvjbWNjY9i8eTPWrVu33/2vWbMGy5YtK+u/t7cXv/zlL6v2H0URLrzwQlx33XW45ZZbsGbNmrL9J598Mpqamsr63bZtG5555plJnffY2BiGhoam3N9ZZ52Fhx9+GA888ED8d8opp+D888+Pl6fjPPv7+/HrX/8ay5cvn7bfLhJkB7IDMfN2AEzNFmQH5cgOZpa5bgfA/tmC7GB2kFc7AHRPCJkxO5hUOaYDwLXXXhu1tLRE3/72t6NHHnkkev/73x8VCoVo586dE/p8X19fdP/990f3339/BCC64oorovvvvz96+umnoygqlaUuFArRj370o+ihhx6K3vKWt4xblvqDH/xg1NXVFd16661l5ZkHBgbiYz7wgQ9Eq1atim655ZbonnvuidatWxetW7cus89LLrkk2rJlS/TUU09FDz30UHTJJZdEdXV10X//939Pqb8swkpfU+33r//6r6Nbb701euqpp6Jf/OIX0fr166PFixdH3d3d03quIkF2IDsQ+28HUTT9tiA7kB0caOaKHUTRgbEF2UFtkkc7iKK5fU84UHaQu5fVKIqiL3/5y9GqVaui5ubm6LTTTovuvPPOCX/2Zz/7WQSg4u+CCy6IoqhUmvoTn/hEtHTp0qilpSU666yzom3btlXtM60/ANE111wTH7N3797oQx/6ULRgwYJo3rx50Vvf+tZox44dmX2++93vjg4//PCoubk5OuSQQ6KzzjorHoRT6S8LPxCn0u/b3/72aPny5VFzc3N06KGHRm9/+9ujJ598ctrP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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure(figsize=(10,5))\n", - "for i,f in enumerate(fingerprints):\n", - " ax = plt.subplot(2,5,i+1)\n", - " ax.matshow(f.reshape(vsdi.shape[:2]),cmap=plt.cm.gnuplot2)\n", - "plt.tight_layout()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Match masks" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Mask clustering" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import product\n", - "\n", - "animals = ['A04','A06','A07','A08']\n", - "days = ['Day1','Day3','Day5','Day7']\n", - "\n", - "masks = []\n", - "for animal,day in product(animals,days):\n", - " try:\n", - " mask = loadmat(datapath.joinpath(f'{animal}/{day}/vsdi_mask.mat'))['mask']\n", - " masks.append(mask)\n", - "\n", - " except FileNotFoundError:\n", - " print(f\"Not found mask for {animal},{day}\")\n", - " masks.append(np.nan)\n", - " continue\n", - " except OSError:\n", - " print(f\"OS error for {animal},{day}\")\n", - " masks.append(np.nan)\n", - " continue\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(masks)" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0YAAAPeCAYAAAAoEQo2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAABT0klEQVR4nO3da5CV1b0n4P8WsGlAONACyuU0g4iGqwhq4miaSIwkGsTCIJrEZKxJvBUTPWqiE1vBa6Fy9JjjNcRUNJUao2Iuoo4y4zknUzGQaGSCkqgIIWCCjKFEEwWBNR9S3WTTXLqhL+/u9TxV/YG113732pffhx/r3e8upZRSAAAAZOyAjl4AAABAR1OMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZa/ViNHny5BgzZkxrH7bD/fCHP4x+/frFe++919FLaTNPP/109OrVKzZs2NDRS6ENyGblks3OTTYrl2x2XnJZufYnl3aMmmHbtm1x7bXXxuzZs6NXr16N4x9++GHMnTs3hg8fHlVVVTF8+PC44YYbYuvWrXs83o033hilUmm/Ard69eoolUq7/Psf/+N/7PZ+H374YYwaNSpKpVLcdtttZbdNnTo1RowYETfffPM+rwvak2xCMckmFI9c7l3XFt8jQz/96U/jd7/7XXz1q18tG//CF74QjzzySJx33nkxadKk+MUvfhH19fWxZs2auP/++3d5rLVr18ZNN90UPXv2bJW1nX322fGZz3ymbOxjH/vYbud/61vfijVr1uz29vPPPz8uv/zymDt3bhx00EGtskZoK7IJxSSbUDxy2QypldXV1aXRo0e39mE71LRp09IJJ5xQNrZ06dIUEam+vr5s/LLLLkulUiktW7Zsl8c666yz0kknnbTfr9OqVatSRKRbb7212fdZv3596tOnT7ruuut2e9/169enLl26pO985zv7vDaKSTZlk2KSTdmkeOQyz1y26FS6d999Ny655JIYNmxYVFVVxYABA+Lkk0+OF198scncV155JT7xiU9Ejx49YvDgwXHLLbeU3b5ly5a45pprYuLEidGnT5/o2bNnnHjiifHcc8+VzWvYYrvtttvi9ttvj9ra2qiuro66urpYvnx5k8f97W9/G2eeeWb069cvunfvHpMmTYqf/OQnTeatXLkyVq5cudfn/MEHH8TTTz8dn/zkJ8vGf/azn0VExKxZs8rGZ82aFSmlePjhh5sc6z/+4z/i0UcfjTvuuGOvj9sSf/nLX2LLli17nXfllVfGEUccEV/4whd2O2fAgAExbty4+PGPf9yaS6SNyeYOskmRyOYOsklRyOUOcrmTlrSoc845Jx144IHpn/7pn9KCBQvSvHnz0mc/+9n0/e9/v3FOXV1dGjRoUBo6dGj62te+lu6+++500kknpYhITz75ZOO8DRs2pEMPPTT90z/9U7rnnnvSLbfcko444ojUrVu39Otf/7pxXkOTHDt2bBo2bFiaN29emjt3burXr1/q379/+tOf/tQ4d/ny5alPnz5p1KhRad68eelf//Vf08c//vFUKpXSwoULy55LbW1tqq2t3etz/j//5/+kiEg/+clPysZvuummFBHpjTfeKBt/+eWXU0SkU045pWx869atady4cen8889vfJ1ao2H36tUrRUQqlUpp0qRJ6X/+z/+5y/lLlixJBxxwQPr5z3++13b+X//rf00HH3zwPq+N9iebO8gmRSKbO8gmRSGXO8hluRYVoz59+qSLL754j3Pq6upSRKQHH3ywcWzz5s3pkEMOSTNmzGgc27p1a9q8eXPZfTdu3JgGDhyYzjvvvMaxhiddXV2d1q5d2zi+ZMmSFBHp0ksvbRybMmVKGjt2bPrggw8ax7Zv356OP/74dPjhh5c9VnM/SAsWLEgRkX7zm9+UjT/22GMpItJDDz1UNn7vvfemiEhjxowpG//Xf/3X1KdPn/TWW2+llPb/g/T73/8+fepTn0r33HNP+slPfpLuuOOO9I//+I/pgAMOSE888UTZ3O3bt6djjz02nX322SmlvW9bNoRk/fr1+7w+2pds7iCbFIls7iCbFIVc7iCX5VpUjGpra9OkSZPSunXrdjunrq4u9erVK23fvr1sfNq0aWnChAm7vM+2bdvS22+/nTZs2JBOPfXUdNRRRzXe1vCkG16Ev3fcccelI444IqWU0ttvv51KpVK6/vrr04YNG8r+5s6dmyKi7IPYXPPmzdvlfd9///1UW1ubBg4cmB577LG0evXq9PDDD6eamprUtWvXdNhhhzXO/X//7/+lfv36pdtuu63sdWrtc1fffvvtNHDgwMbXpMEDDzyQqqur05o1a1JKe/8g3XPPPSki0ssvv9yq66PtyOYOskmRyOYOsklRyOUOclmuRd8xuuWWW2L58uUxdOjQOPbYY2POnDnxxhtvNJk3ZMiQKJVKZWN9+/aNjRs3lo1973vfi3HjxkX37t2jpqYm+vfvH4sWLYp33nmnyTEPP/zwJmMjR46M1atXR0TE66+/HimlqK+vj/79+5f9XXvttRER8dZbb7Xk6ZZJKZX9u3v37rFo0aKoqamJGTNmxLBhw+Lcc8+Na665Jvr161d2GcSrr746+vXrF7Nnz97nx2+Ofv36xX/5L/8lfve738XatWsjImLTpk1x1VVXxRVXXBFDhw5t1nEanuvO7yHFJZs7yCZFIps7yCZFIZc7yGW5Fl2ue+bMmXHiiSfG448/Hs8880zceuutMW/evFi4cGF8+tOfbpzXpUuXPS4wIuL73/9+fPnLX47p06fHFVdcEQMGDIguXbrEzTff3Kwvke1s+/btERFx+eWXxymnnLLLOSNGjGjxcWtqaiIiYuPGjTFkyJCy20aPHh3Lly+PV155JTZu3BijRo2K6urquPTSS6Ouri4iIl577bW4//7744477og333yz8b4ffPBBfPjhh7F69ero3bt39OvXr8Vr25WGD8uf//znGDJkSNx2222xZcuWOOussxpD1/Ah27hxY6xevToGDRoUBx54YOMxGgJ/8MEHt8qaaHuyKZsUk2zKJsUjl3K5W83f2Gpq/fr1afDgwek//+f/3Di2uy21L33pS2XnQJ5++ulp+PDhTbYojz/++LJ5zd16XL9+fYqIdNVVV+3PU2qi4ctqP/7xj5s1f9GiRSki0n333ZdSSum5555LEbHHv6997Wuttt7LLrssRUR68803U0p/e9339vh//+XAlHyJtDOQzaZkkyKQzaZkk44ml03lmstm7xht27Yt3nvvvejTp0/j2IABA2LQoEGxefPm5h6mUUMLTyk1bnEtWbIknn/++fjHf/zHJvN/9KMfxbp162Lw4MEREbF06dJYsmRJXHLJJY1rmTx5ctx3330xe/bsOPTQQ8vuv2HDhujfv3/jvxta/GGHHbbHdU6cODEOPPDA+NWvfhXTpk3b49z3338/6uvr49BDD42zzz47IiLGjBkTjz/+eJO5V199dbz77rvxL//yL3tdw67s/HwiItatWxcPPPBAjBs3rvH5/7f/9t9i+vTpZfPeeuutOP/88+PLX/5ynH766fGf/tN/Krv9hRde2OOPalEssimbFJNsyibFI5dyuSfNLkbvvvtuDBkyJM4888wYP3589OrVKxYvXhy//OUvY/78+S160IiI0047LRYuXBhnnHFGnHrqqbFq1aq49957Y9SoUfHee+81mT9ixIg44YQT4sILL4zNmzfHHXfcETU1NfH1r3+9cc5dd90VJ5xwQowdOza+8pWvxPDhw2P9+vXx/PPPx9q1a2PZsmWNc6dMmRIR0bgdtzvdu3ePT33qU7F48eK47rrrym6bOXNmDBo0KEaNGhWbNm2KBx54IN54441YtGhR46/sHnzwwU3eyIhovPb7zrfNmTMn5s6dG88991xMnjx5t+v6+te/HitXrowpU6bEoEGDYvXq1XHffffFX/7yl/iXf/mXxnlHH310HH300WX3bXjOo0eP3uWH7P/+3/8bF1988e5fFApFNmWTYpJN2aR45FIu96i5W0ubN29OV1xxRRo/fnw66KCDUs+ePdP48ePT3XffXTavuVuP27dvTzfddFOqra1NVVVVacKECemJJ55oMu/vrzgxf/78NHTo0FRVVZVOPPHEXf4a78qVK9O5556bDjnkkNStW7c0ePDgdNppp6VHH320bF5zL2+YUkoLFy5MpVKp8SoYDebNm5eOPPLI1L1799S3b980bdq0Jtt4u7O716nhl4ZXrFixx/v/4Ac/SB//+MdT//79U9euXdPBBx+czjjjjPTCCy/s9bH3dBWPe+65J/Xo0SNt2rSpWc+DjiebskkxyaZsUjxyKZd7sl/fMWoPe7sUX3vYunVrGjlyZLr66qvb/LGOOeaYdOaZZ7b54+zOUUcdlS655JIOe3wqh2y2L9mkuWSzfckmzSGX7Wtfc9miy3XnqkuXLnHdddfFXXfdtctt0dayadOmWLZsWZMtzvby9NNPx2uvvRZXXXVVhzw+tJRsQjHJJhSPXO5diy7XnbOzzjorzjrrrDZ9jN69e+/TF/9ay9SpU9s0KNAWZBOKSTaheORyz+wYAQAA2SultNNP4AIAAGTGjhEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQva4dvYDWUiqVWu1YKaVWOxbkTC6hmGQTikk2O5YdIwAAIHudZseoNe2urWve0HHkEopJNqGYZLPl7BgBAADZK6UKr42teS5mc1X4SwZtTi6hmGQTikk2i8GOEQAAkD3FaB+USqUOafbA7sklFJNsQjHJZlOKEQAAkL2K/Y5RkRpuhb6E0OrkEopJNqGYZLNY7BgBAADZU4xagXM0oXjkEopJNqGYZFMxAgAAqLzvGFVCk62wlxT2m1xCMckmFJNsFpMdIwAAIHuKURtwjiYUj1xCMckmFFOO2VSMAACA7FXMd4wqubFWyEsMLSaXUEyyCcUkm8VmxwgAAMieYgQAAGRPMQIAALKnGLWDSj6fFDoruYRikk0ophyyqRgBAADZK/xV6TpbOy34yw3NIpdQTLIJxSSblcGOEQAAkD3FqJ3l+CvCUHRyCcUkm1BMnTWbihEAAJA9xaiDdNamDZVMLqGYZBOKqbNlUzECAACy17WjF7A7nal9Qmchl1BMsgnFJJuVxY4RAACQPcWog3W2czOhM5BLKCbZhGLqLNlUjAqis3ygoDORSygm2YRiqvRsKkYAAED2FCMAACB7ihEAAJA9xahgKv3cTOiM5BKKSTahmCo1m4oRAACQvVJKKXX0Iv5eJbbLtlSwt4dMyWU5uaQoZLOcbFIUslmuUrJpxwgAAMieYgQAAGRPMQIAALKnGBVcpV7VAzozuYRikk0opkrJpmIEAABkTzECAACypxgBAADZK8zvGFXCeYdFUJC3i0zIZfPIJe1NNptHNmlvstk8Rc2mHSMAACB7ilGFqZSrekBO5BKKSTahmIqaTcUIAADInmIEAABkTzECAACypxhVqKKemwk5k0soJtmEYipaNhUjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDslVJKqUMXUKBrl1eyDn4b6WTksnXIJa1NNluHbNLaZLN1dHQ27RgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGHUSpVLJj4tBwcglFJNsQjF1dDYVIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7JVSSqlDHtjvB7SpDnpbqXBy2bbkkn0lm21LNtlXstm22jubdowAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGHVSrqsPxSOXUEyyCcXU3tlUjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMOrFSqeRH66Bg5BKKSTahmNozm4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2eva0Qug7aSUOnoJwE7kEopJNqGY2jObdowAAIDsdUgxKpVKHfGwwB7IJRSTbEIxyWbnY8cIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FKNOyg/VQfHIJRSTbEIxtXc2FSMAACB7pdRB/03iR7Hahv/1Yn/IZduQS/aXbLYN2WR/yWbb6Khs2jECAACypxgBAADZU4wAAIDsde3oBdA6nCcNxSOXUEyyCcXU0dm0YwQAAGSvw65K17gAV/PYLx3drOmc5HL/yCVtRTb3j2zSVmRz/xQlm3aMAACA7HX4jlEDTbtlCvK20cnJZcvIJe1FNltGNmkvstkyRcumHSMAACB7hdkx2pnGXa6gbxOZkctycklRyGY52aQoZLNc0bNpxwgAAMheYXeMGuTetAv+9pApuZRLikk2ZZNiks3KyKYdIwAAIHuF3zHaWWdv3BX2dkBEyCUUlWxCMclmMdkxAgAAsldxO0Y76yyNu8LfBigjl1BMsgnFJJvFYMcIAADIXsXvGO1O0Zt3J33ZYY/kEopJNqGYZLN92TECAACy12l3jFpTa7R1LzO0LrmEYpJNKCbZ3Ds7RgAAQPbsGLWhhmbuJYbikEsoJtmEYsopm3aMAACA7NkxAgAAsmfHCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACy1+rFaPLkyTFmzJjWPmyH++EPfxj9+vWL9957r6OX0maefvrp6NWrV2zYsKGjl0IbkM3KJZudm2xWLtnsvOSycu1PLu0YNcO2bdvi2muvjdmzZ0evXr0axz/88MOYO3duDB8+PKqqqmL48OFxww03xNatW3d5nBdffDGmTZsW/fr1ix49esSYMWPizjvv3K+1rVy5Ms4555wYMGBAVFdXx+GHHx7f/OY3m8xbsWJFTJ06NXr16hX9+vWLL37xi00+MFOnTo0RI0bEzTffvF9rgvYim1BMsgnFI5d713Wfn0FGfvrTn8bvfve7+OpXv1o2/oUvfCEeeeSROO+882LSpEnxi1/8Iurr62PNmjVx//33l8195pln4rOf/WxMmDAh6uvro1evXrFy5cpYu3btPq/rpZdeismTJ8fgwYPjsssui5qamlizZk384Q9/KJu3du3a+PjHPx59+vSJm266Kd5777247bbb4je/+U0sXbo0DjzwwMa5559/flx++eUxd+7cOOigg/Z5bdAeZBOKSTaheOSyGVIrq6urS6NHj27tw3aoadOmpRNOOKFsbOnSpSkiUn19fdn4ZZddlkqlUlq2bFnj2DvvvJMGDhyYzjjjjLRt27ZWWdO2bdvSmDFj0nHHHZf++te/7nHuhRdemKqrq9Pvf//7xrFnn302RUS67777yuauX78+denSJX3nO99plXVSHLIpmxSTbMomxSOXeeayRcVo06ZN6Wtf+1qqra1NBx54YOrfv3/65Cc/mV544YXGOQ0fpJdffjlNnjw5VVdXp0GDBqV58+aVHWvz5s2pvr4+HX300al3796pR48e6YQTTkj/+3//77J5q1atShGRbr311vTP//zP6R//8R9T9+7d08c//vH0m9/8pskaV6xYkWbMmJH69u2bqqqq0sSJE9OPf/zjJvNef/319Prrr+/1Ob///vvpwAMPTHPmzCkbnz9/foqI9PLLL5eN//KXv0wRkf77f//vjWP33HNPioj0yiuvpJRSeu+99/b7A/XUU0+liEhPPvlkSimlv/zlL2nr1q27nDtgwID0uc99rsn4yJEj05QpU5qMT5gwIU2bNm2/1kf7ks0dZJMikc0dZJOikMsd5LJci75jdMEFF8Q999wTM2bMiLvvvjsuv/zyqK6ujhUrVpTN27hxY0ydOjXGjx8f8+fPjyOPPDK+8Y1vxFNPPdU4Z9OmTbFgwYKYPHlyzJs3L+bMmRMbNmyIU045JV566aUmj/3ggw/GnXfeGRdffHFcddVVsXz58jjppJNi/fr1jXNefvnl+OhHPxorVqyIK6+8MubPnx89e/aM6dOnx+OPP152vClTpsSUKVP2+pxfeOGF2LJlSxx99NFl45s3b46IiOrq6rLxHj16NN6vweLFi6N3796xbt26OOKII6JXr17Ru3fvuPDCC+ODDz7Y6xp2ZfHixRERUVVVFZMmTYqePXtGjx49YtasWfHnP/+5cd66devirbfeikmTJjU5xrHHHhu//vWvm4xPnDgxfv7zn+/TuugYsrmDbFIksrmDbFIUcrmDXO6kJS2qT58+6eKLL97jnLq6uhQR6cEHH2wc27x5czrkkEPSjBkzGse2bt2aNm/eXHbfjRs3poEDB6bzzjuvcayhYVdXV6e1a9c2ji9ZsiRFRLr00ksbx6ZMmZLGjh2bPvjgg8ax7du3p+OPPz4dfvjhZY9VW1ubamtr9/qcFyxYkCKiSZt/7LHHUkSkhx56qGz83nvvTRGRxowZ0zg2bty41KNHj9SjR480e/bs9Nhjj6XZs2eniEizZs3a6xp2Zdq0aSkiUk1NTfr85z+fHn300VRfX5+6du2ajj/++LR9+/aU0o7G//fvR4MrrrgiRUTZ65VSSjfddFOKiLR+/fp9WhvtTzZ3kE2KRDZ3kE2KQi53kMtyLSpGtbW1adKkSWndunW7nVNXV5d69erV+EQaTJs2LU2YMGGX99m2bVt6++2304YNG9Kpp56ajjrqqMbbGj5IZ599dpP7HXfccemII45IKaX09ttvp1KplK6//vq0YcOGsr+5c+emiCj7IDbXvHnzdnnf999/P9XW1qaBAwemxx57LK1evTo9/PDDqaamJnXt2jUddthhjXOHDx+eIiJdcMEFZcc4//zzU0SkV199tcXrOumkk1JEpKlTp5aN33zzzSki0rPPPptSSuk//uM/UkSkhx9+uMkx6uvrU0SkjRs3lo03bJXuvK1KccnmDrJJkcjmDrJJUcjlDnJZrkWn0t1yyy2xfPnyGDp0aBx77LExZ86ceOONN5rMGzJkSJRKpbKxvn37xsaNG8vGvve978W4ceOie/fuUVNTE/37949FixbFO++80+SYhx9+eJOxkSNHxurVqyMi4vXXX4+UUtTX10f//v3L/q699tqIiHjrrbda8nTLpJTK/t29e/dYtGhR1NTUxIwZM2LYsGFx7rnnxjXXXBP9+vUruwxiw/bk2WefXXaMc845JyIinn/++RavZ2/HbNg6bJjXsFX69xq2PXfePm14rju/hxSXbO4gmxSJbO4gmxSFXO4gl+VadLnumTNnxoknnhiPP/54PPPMM3HrrbfGvHnzYuHChfHpT3+6cV6XLl12ef+/fzO+//3vx5e//OWYPn16XHHFFTFgwIDo0qVL3HzzzbFy5cqWLCsiIrZv3x4REZdffnmccsopu5wzYsSIFh+3pqYmIv52numQIUPKbhs9enQsX748Xnnlldi4cWOMGjUqqqur49JLL426urrGeYMGDYqXX345Bg4cWHb/AQMGNB67pQYNGhQRsddjHnrooRER8cc//rHJMf74xz9Gv379oqqqqmy84b4HH3xwi9dFx5BN2aSYZFM2KR65lMvdafHvGB166KFx0UUXxUUXXRRvvfVWHH300XHjjTeWfZCa49FHH43hw4fHwoULy5pcQxve2WuvvdZk7NVXX41hw4ZFRMTw4cMjIqJbt27xyU9+skVr2ZMjjzwyIiJWrVoVY8eObXJ7qVSK0aNHN/77ySefjO3bt5etYeLEifHss882flmtwZtvvhkREf3792/xuiZOnBjf/va3Y926dWXjOx9z8ODB0b9///jVr37V5BhLly6No446qsn4qlWr4uCDD96nddFxZLOcbFIUsllONikCuSwnl3/T7FPptm3b1mRLcMCAATFo0KBdbmvtTUML//vWvWTJkt1uw/3oRz8qe9GWLl0aS5YsafwADxgwICZPnhz33XffLtvkzr+Ku3LlymY1+YkTJ8aBBx64yzdiZ++//37U19fHoYceWrYlOHPmzIiI+M53vlM2f8GCBdG1a9eYPHnyXo+9s9NPPz2qqqriu9/9buP/LjQcMyLi5JNPbhybMWNGPPHEE2U/lPW//tf/ildffTU+97nPNTn2Cy+8EB/72MdavCY6hmzKJsUkm7JJ8cilXO5Rc7+MtHHjxtSzZ8/0pS99Kf3zP/9zuv/++9PMmTNTRKT58+c3ztvdD2J96UtfKrtqxgMPPJAiIk2bNi3dd9996corr0z/8A//kEaPHl02r+HLamPHjk3Dhg1L8+bNS9ddd13q169fqqmpSW+++Wbj3Jdffjn17ds31dTUpCuvvDLdf//96frrr0+f+cxn0rhx48rW09yreKSU0mmnnZY+9rGPNRn/3Oc+l772ta+l++67L916663pIx/5SKqqqkqLFy9uMve8885LEZFmzpyZ7rrrrvS5z30uRUS66qqryuZde+21KSLSc889t9d1XXfddSki0sknn5zuuuuu9NWvfjWVSqUmX+xbs2ZNqqmpSYcddli6884700033ZT69u3b5IonKe34QawFCxY045WhCGRTNikm2ZRNikcu5XJPml2MNm/enK644oo0fvz4dNBBB6WePXum8ePHp7vvvrtsXnM/SNu3b0833XRTqq2tTVVVVWnChAnpiSeeaDLv738Qa/78+Wno0KGpqqoqnXjiiWW/xttg5cqV6dxzz02HHHJI6tatWxo8eHA67bTT0qOPPlo2ryUfpIULF6ZSqZTWrFlTNj5v3rx05JFHpu7du6e+ffumadOmpV//+te7PMaWLVvSnDlzUm1tberWrVsaMWJEuv3225vMa/il4RUrVux1Xdu3b0/f+ta30siRI1O3bt3S0KFD09VXX522bNnSZO7y5cvTpz71qdSjR4/0D//wD+nzn/98+tOf/tRk3j333JN69OiRNm3atNfHpxhkUzYpJtmUTYpHLuVyT1p0ue6O8PcfpI6ydevWNHLkyHT11Ve3+WMdc8wx6cwzz2zzx9mdo446Kl1yySUd9vhUDtlsX7JJc8lm+5JNmkMu29e+5rJFl+vOVZcuXeK6666Lu+66K9577702e5xNmzbFsmXL4rrrrmuzx9iTp59+Ol577bW46qqrOuTxoaVkE4pJNqF45HLvWnxVulydddZZcdZZZ7XpY/Tu3XufvvjXWqZOndqmQYG2IJtQTLIJxSOXe2bHCAAAyF4ppZ1+AhcAACAzdowAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5i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BAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQPcUIAADInmIEAABkTzECAACypxgBAADZU4wAAIDsKUYAAED2FCMAACB7ihEAAJA9xQgAAMieYgQAAGRPMQIAALKnGAEAANlTjAAAgOwpRgAAQPYUIwAAIHuKEQAAkD3FCAAAyJ5iBAAAZE8xAgAAsqcYAQAA2VOMAACA7ClGAABA9hQjAAAge4oRAACQvVYvRpMnT44xY8a09mE73A9/+MPo169fvPfeex29lDbzyiuvRNeuXWP58uUdvRTagGxWLtnsvOSycsll5yablWt/smnHqBm2bdsW1157bcyePTt69erVOP7hhx/G3LlzY/jw4VFVVRXDhw+PG264IbZu3brL47z44osxbdq06NevX/To0SPGjBkTd955536tbeXKlXHOOefEgAEDorq6Og4//PD45je/WTZn6dKlcdFFF8XEiROjW7duUSqVdnmsUaNGxamnnhrXXHPNfq0J2otsQvHIJRSTbO5d131afWZ++tOfxu9+97v46le/Wjb+hS98IR555JE477zzYtKkSfGLX/wi6uvrY82aNXH//feXzX3mmWfis5/9bEyYMCHq6+ujV69esXLlyli7du0+r+ull16KyZMnx+DBg+Oyyy6LmpqaWLNmTfzhD38om/fkk0/GggULYty4cTF8+PB49dVXd3vMCy64ID7zmc/EypUr47DDDtvntUF7kE0oHrmEYpLNZkitrK6uLo0ePbq1D9uhpk2blk444YSysaVLl6aISPX19WXjl112WSqVSmnZsmWNY++8804aOHBgOuOMM9K2bdtaZU3btm1LY8aMSccdd1z661//use5f/rTnxrnXHzxxWlPb/uWLVtS3759mzwvKp9syibFI5dySTHJZp7ZbNGpdO+++25ccsklMWzYsKiqqooBAwbEySefHC+++GKTua+88kp84hOfiB49esTgwYPjlltuKbt9y5Ytcc0118TEiROjT58+0bNnzzjxxBPjueeeK5u3evXqKJVKcdttt8Xtt98etbW1UV1dHXV1dbs8d/C3v/1tnHnmmdGvX7/o3r17TJo0KX7yk580mbdy5cpYuXLlXp/zBx98EE8//XR88pOfLBv/2c9+FhERs2bNKhufNWtWpJTi4Ycfbhz7wQ9+EOvXr48bb7wxDjjggPjLX/4S27dv3+tj78kzzzwTy5cvj2uvvTaqq6vjr3/9a2zbtm2XcwcOHBjV1dXNOm63bt1i8uTJ8eMf/3i/1kf7ks0dZJOikMsd5JIikc0dZLNci4rRBRdcEPfcc0/MmDEj7r777rj88sujuro6VqxYUTZv48aNMXXq1Bg/fnzMnz8/jjzyyPjGN74RTz31VOOcTZs2xYIFC2Ly5Mkxb968mDNnTmzYsCFOOeWUeOmll5o89oMPPhh33nlnXHzxxXHVVVfF8uXL46STTor169c3znn55Zfjox/9aKxYsSKuvPLKmD9/fvTs2TOmT58ejz/+eNnxpkyZElOmTNnrc37hhRdiy5YtcfTRR5eNb968OSKiyRvUo0ePxvs1WLx4cfTu3TvWrVsXRxxxRPTq1St69+4dF154YXzwwQd7XcOuLF68OCIiqqqqYtKkSdGzZ8/o0aNHzJo1K/785z/v0zEbTJw4MZYvXx6bNm3ar+PQfmRzB9mkKORyB7mkSGRzB9ncSUu2l/r06ZMuvvjiPc6pq6tLEZEefPDBxrHNmzenQw45JM2YMaNxbOvWrWnz5s1l9924cWMaOHBgOu+88xrHVq1alSIiVVdXp7Vr1zaOL1myJEVEuvTSSxvHpkyZksaOHZs++OCDxrHt27en448/Ph1++OFlj1VbW5tqa2v3+pwXLFiQIiL95je/KRt/7LHHUkSkhx56qGz83nvvTRGRxowZ0zg2bty41KNHj9SjR480e/bs9Nhjj6XZs2eniEizZs3a6xp2Zdq0aSkiUk1NTfr85z+fHn300VRfX5+6du2ajj/++LR9+/Zd3m9vW48ppfSDH/wgRURasmTJPq2N9iebO8gmRSGXO8glRSKbO8hmuRYVo9ra2jRp0qS0bt263c6pq6tLvXr1avJEpk2bliZMmLDL+2zbti29/fbbacOGDenUU09NRx11VONtDR+ks88+u8n9jjvuuHTEEUeklFJ6++23U6lUStdff33asGFD2d/cuXNTRJR9EJtr3rx5u7zv+++/n2pra9PAgQPTY489llavXp0efvjhVFNTk7p27ZoOO+ywxrnDhw9PEZEuuOCCsmOcf/75KSLSq6++2uJ1nXTSSSki0tSpU8vGb7755hQR6dlnn93l/ZrzQXrqqadSRKRFixa1eF10DNncQTYpCrncQS4pEtncQTbLtehUultuuSWWL18eQ4cOjWOPPTbmzJkTb7zxRpN5Q4YMaXIJvb59+8bGjRvLxr73ve/FuHHjonv37lFTUxP9+/ePRYsWxTvvvNPkmIcffniTsZEjR8bq1asjIuL111+PlFLU19dH//79y/6uvfbaiIh46623WvJ0y6SUyv7dvXv3WLRoUdTU1MSMGTNi2LBhce6558Y111wT/fr1K7sMYsP25Nlnn112jHPOOSciIp5//vkWr2dvx/z5z3/e4mM2aHiuu7sMIsUjmzvIJkUhlzvIJUUimzvIZrkWXa575syZceKJJ8bjjz8ezzzzTNx6660xb968WLhwYXz6059unNelS5c9LjAi4vvf/358+ctfjunTp8cVV1wRAwYMiC5dusTNN9/crC+R7azhy1+XX355nHLKKbucM2LEiBYft6amJiL+dp7pkCFDym4bPXp0LF++PF555ZXYuHFjjBo1Kqqrq+PSSy+Nurq6xnmDBg2Kl19+OQYOHFh2/wEDBjQeu6UGDRoUEdGqx2zQcN+DDz54n49B+5JN2aR45FIuKSbZlM3dafHvGB166KFx0UUXxUUXXRRvvfVWHH300XHjjTeWfZCa49FHH43hw4fHwoULy5pcQxve2WuvvdZk7NVXX41hw4ZFRMTw4cMj4m9Xodj5ihv748gjj4yIiFWrVsXYsWOb3F4qlWL06NGN/37yySdj+/btZWuYOHFiPPvss41fVmvw5ptvRkRE//79W7yuiRMnxre//e1Yt25d2fj+HLPBqlWr4oADDoiRI0fu8zFof7JZTjYpArksJ5cUhWyWk82/afapdNu2bWuyJThgwIAYNGhQ4xUtWqKhhf99616yZMlut+F+9KMflb1oS5cujSVLljR+gAcMGBCTJ0+O++67L/74xz82uf+GDRvK/t3cyxtOnDgxDjzwwPjVr36117nvv/9+1NfXx6GHHlq2JThz5syIiPjOd75TNn/BggXRtWvXmDx58l6PvbPTTz89qqqq4rvf/W7ZpRIXLFgQEREnn3xyi4/Z4IUXXojRo0dHnz599vkYtB/ZlE2KRy7lkmKSTdnck2bvGL377rsxZMiQOPPMM2P8+PHRq1evWLx4cfzyl7+M+fPnt3ixp512WixcuDDOOOOMOPXUU2PVqlVx7733xqhRo+K9995rMn/EiBFxwgknxIUXXhibN2+OO+64I2pq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slmuRcXoggsuiHvuuSdmzJgRd999d1x++eVRXV0dK1asKJu3cePGmDp1aowfPz7mz58fRx55ZHzjG9+Ip556qnHOpk2bYsGCBTF58uSYN29ezJkzJzZs2BCnnHJKvPTSS00e+8EHH4w777wzLr744rjqqqti+fLlcdJJJ8X69esb57z88svx0Y9+NFasWBFXXnllzJ8/P3r27BnTp0+Pxx9/vOx4U6ZMiSlTpuz1Ob/wwguxZcuWOProo8vGN2/eHBHR5A3q0aNH4/0aLF68OHr37h3r1q2LI444Inr16hW9e/eOCy+8MD744IO9rmFXFi9eHBERVVVVMWnSpOjZs2f06NEjZs2aFX/+85/36ZgNJk6cGMuXL49Nmzbt13FoP7K5g2xSFHK5g1xSJLK5g2zupCXbS3369EkXX3zxHufU1dWliEgPPvhg49jmzZvTIYcckmbMmNE4tnXr1rR58+ay+27cuDENHDgwnXfeeY1jq1atShGRqqur09q1axvHlyxZkiIiXXrppY1jU6ZMSWPHjk0ffPBB49j27dvT8ccfnw4//PCyx6qtrU21tbV7fc4LFixIEZF+85vflI0/9thjKSLSQw89VDZ+7733pohIY8aMaRwbN25c6tGjR+rRo0eaPXt2euyxx9Ls2bNTRKRZs2btdQ27Mm3atBQRqaamJn3+859Pjz76aKqvr09du3ZNxx9/fNq+ffsu77e3rceUUvrBD36QIiItWbJkn9ZG+5PNHWSTopDLHeSSIpHNHWSzXIuKUW1tbZo0aVJat27dbufU1dWlXr16NXki06ZNSxMmTNjlfbZt25befvvttGHDhnTqqaemo446qvG2hg/S2Wef3eR+xx13XDriiCNSSim9/fbbqVQqpeuvvz5t2LCh7G/u3LkpIso+iM01b968Xd73/fffT7W1tWngwIHpscceS6tXr04PP/xwqqmpSV27dk2HHXZY49zhw4eniEgXXHBB2THOP//8FBHp1VdfbfG6TjrppBQRaerUqWXjN998c4qI9Oyzz+7yfs35ID311FMpItKiRYtavC46hmzuIJsUhVzuIJcUiWzuIJvlWnQq3S233BLLly+PoUOHxrHHHhtz5syJN954o8m8IUOGNLmEXt++fWPjxo1lY9/73vdi3Lhx0b1796ipqYn+/fvHokWL4p133mlyzMMPP7zJ2MiRI2P16tUREfH6669HSinq6+ujf//+ZX/XXnttRES89dZbLXm6ZVJKZf/u3r17LFq0KGpqamLGjBkxbNiwOPfcc+Oaa66Jfv36lV0GsWF78uyzzy47xjnnnBMREc8//3yL17O3Y/785z9v8TEbNDzX3V0GkeKRzR1kk6KQyx3kkiKRzR1ks1yLLtc9c+bMOPHEE+Pxxx+PZ555Jm699daYN29eLFy4MD796U83zuvSpcseFxgR8f3vfz++/OUvx/Tp0+OKK66IAQMGRJcuXeLmm29u1pfIdtbw5a/LL788TjnllF3OGTFiRIuPW1NTExF/O890yJAhZbeNHj06li9fHq+88kps3LgxRo0aFdXV1XHppZdGXV1d47xBgwbFyy+/HAMHDiy7/4ABAxqP3VKDBg2KiGjVYzZouO/BBx+8z8egfcmmbFI8cimXFJNsyubutPh3jA499NC46KKL4qKLLoq33norjj766LjxxhvLPkjN8eijj8bw4cNj4cKFZU2uoQ3v7LXXXmsy9uqrr8awYcMiImL48OER8berUOx8xY39ceSRR0ZExKpVq2Ls2LFNbi+VSjF69OjGfz/55JOxffv2sjVMnDgxnn322cYvqzV48803IyKif//+LV7XxIkT49vf/nasW7eubHx/jtlg1apVccABB8TIkSP3+Ri0P9ksJ5sUgVyWk0uKQjbLyebfNPtUum3btjXZEhwwYEAMGjSo8YoWLdHQwv++dS9ZsmS323A/+tGPyl60pUuXxpIlSxo/wAMGDIjJkyfHfffdF3/84x+b3H/Dhg1l/27u5Q0nTpwYBx54YPzqV7/a69z3338/6uvr49BDDy3bEpw5c2ZERHznO98pm79gwYLo2rVrTJ48ea/H3tnpp58eVVVV8d3vfrfsUokLFiyIiIiTTz65xcds8MILL8To0aOjT58++3wM2o9syibFI5dySTHJpmzuSbN3jN59990YMmRInHnmmTF+/Pjo1atXLF68OH75y1/G/PnzW7zY0047LRYuXBhnnHFGnHrqqbFq1aq49957Y9SoUfHee+81mT9ixIg44YQT4sILL4zNmzfHHXfcETU1NfH1r3+9cc5dd90VJ5xwQowdOza+8pWvxPDhw2P9+vXx/PPPx9q1a2PZsmWNcxsubdhwTufudO/ePT71qU/F4sWL47rrriu7bebMmTFo0KAY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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "plt.figure(figsize=(10,10))\n", - "for i,m in enumerate(masks):\n", - " ax = plt.subplot(4,4,i+1)\n", - " ax.matshow(mask,cmap=plt.cm.Greys)\n", - " plt.axis('off')\n", - " plt.title(f'shape: {m.shape}')\n", - "\n", - "plt.tight_layout()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [], - "source": [ - "from functools import reduce\n", - "def max_common_intersection(mask_list):\n", - " min_x = np.min([m.shape[0] for m in mask_list])\n", - " min_y = np.min([m.shape[1] for m in mask_list])\n", - "\n", - " cropped_masks = []\n", - " for m in masks:\n", - " if m.shape[0]> min_x and m.shape[1]>min_y:\n", - " cropped_masks.append(m[(m.shape[0]-min_x)//2:-(m.shape[0]-min_x)//2,\n", - " (m.shape[1]-min_y)//2:-(m.shape[1]-min_y)//2])\n", - "\n", - " elif m.shape[0] == min_x and m.shape[1]>min_y:\n", - " cropped_masks.append(m[:,(m.shape[1]-min_y)//2:-(m.shape[1]-min_y)//2])\n", - "\n", - " elif m.shape[0]> min_x and m.shape[1]== min_y:\n", - " cropped_masks.append(m[(m.shape[0]-min_x)//2:-(m.shape[0]-min_x)//2,:])\n", - "\n", - " else:\n", - " cropped_masks.append(m)\n", - " \n", - " # performs elementwise logical and\n", - " intersection = reduce(lambda x, y: np.logical_and(x, y), cropped_masks)\n", - "\n", - "\n", - " return intersection" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [], - "source": [ - "cm = max_common_intersection(masks)" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.matshow(cm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.10.9" - }, - "vscode": { - "interpreter": { - "hash": "a004f9109620e037dd6eb32a5065768d5476b766f6a5e98b9519dfa4bc5bb4ce" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/vsdi/pipeline.py b/vsdi/pipeline.py deleted file mode 100644 index a1ad191..0000000 --- a/vsdi/pipeline.py +++ /dev/null @@ -1,166 +0,0 @@ -import loaders -import args - -import glob -import numpy as np -import pandas as pd -from scipy import io -from sklearn.pipeline import Pipeline -from sklearn.decomposition import PCA -from sklearn.preprocessing import StandardScaler -import matplotlib.pyplot as plt - -import vsdi_preprocessing -import vsdi_visualization -import loaders - -#################################### - -##################################### -############### MAIN ################ -##################################### - -# Define paths -path = '/home/danteam/Documents/BScThesis' -data = f'{path}/data' -reports = f'{path}/reports' -figures = f'{reports}/figures' - -# Get arguments from command line -parameters = args.getArgs() -subject = parameters.subject -day = parameters.day -session = parameters.session - -def save_vsdi(): - vsdi1 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi3 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi5 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/vsdi_ATC{session}.mat')[0])['vsdi_data'] - vsdi7 = io.loadmat(glob.glob(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/vsdi_ATC{session}.mat')[0])['vsdi_data'] - - vsdi1 = vsdi1[:,:,0:29999] - vsdi3 = vsdi3[:,:,0:29999] - vsdi5 = vsdi5[:,:,0:29999] - vsdi7 = vsdi7[:,:,0:29999] - - vsdi = np.concatenate((vsdi1, vsdi3, vsdi5, vsdi7), axis = 2) - - del(vsdi1) - del(vsdi3) - del(vsdi5) - del(vsdi7) - - # Outliers correction - vsdi_clean = vsdi_preprocessing.clean_outliers(vsdi, nsigma=5) - - # Hemodynamics correction - vsdi_clean = vsdi_preprocessing.clean_hemodynamic_pca(vsdi_clean, bimodal_th = 0.6, verbose = True) - - del(vsdi) - - ## Mask to select just subject cortex - r = np.loadtxt(f'{data}/Patterns/mask_A0{subject}.csv', delimiter=',', dtype='bool') - - X = vsdi_clean.transpose(2, 0, 1) - X = X[:,r] - - del(vsdi_clean) - - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=10)) - ]) - - out = pipe.fit(X) - - f = out.named_steps['pca'].components_ - factor_scores = pipe.named_steps['pca'].transform(X) - - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_timecourse_part1.csv', factor_scores, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_fingerprint_part1.csv', f, delimiter=",") - - return 0 - -def save_behav(): - atc1 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/ATC{session}.mat') - atc3 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/ATC{session}.mat') - atc5 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/ATC{session}.mat') - atc7 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/ATC{session}.mat') - b_data1 = loaders.extract_behavioural_data(atc1) - b_data3 = loaders.extract_behavioural_data(atc3) - b_data5 = loaders.extract_behavioural_data(atc5) - b_data7 = loaders.extract_behavioural_data(atc7) - - del(atc1) - del(atc3) - del(atc5) - del(atc7) - - d1 = vsdi_preprocessing.design_matrix(b_data1) - d3 = vsdi_preprocessing.design_matrix(b_data3) - d5 = vsdi_preprocessing.design_matrix(b_data5) - d7 = vsdi_preprocessing.design_matrix(b_data7) - - d1 = d1[0:29999,:] - d3 = d3[0:29999,:] - d5 = d5[0:29999,:] - d7 = d7[0:29999,:] - - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d1_part{session}.csv', d1, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d3_part{session}.csv', d3, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d5_part{session}.csv', d5, delimiter=",") - np.savetxt(f'{data}/Patterns/SubjectA0{subject}_d7_part{session}.csv', d7, delimiter=",") - - return 0 - -def mask_norm(masks, threshold=0.5): - mask_mean = np.mean(masks, axis=0) - mask_mean[mask_mean > threshold] = 1 - mask_mean[mask_mean <= threshold] = 0 - - return mask_mean - -def save_mask(): - r1 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day1/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day1.csv', r1, delimiter=",") - r3 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day3/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day3.csv', r3, delimiter=",") - r5 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day5/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day5.csv', r5, delimiter=",") - r7 = io.loadmat(f'{data}/ATC_Data_preprocessed/A0{subject}/Day7/vsdi_mask.mat')['mask'].astype('bool') - np.savetxt(f'{data}/Patterns/raw_mask_{subject}_day7.csv', r7, delimiter=",") - - del(r1) - del(r3) - del(r5) - del(r7) - - r1 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day1.csv', delimiter=",") - r3 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day3.csv', delimiter=",") - r5 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day5.csv', delimiter=",") - r7 = np.loadtxt(f'{data}/Patterns/raw_mask_{subject}_day7.csv', delimiter=",") - - print(r1.shape, r3.shape, r5.shape, r7.shape) - - masks = np.stack([r1, r3, r5, r7]) - mask_mean = mask_norm(masks) - - np.savetxt(f'/home/danteam/Documents/BScThesis/data/Patterns/mask_A0{subject}.csv', mask_mean.astype(int), fmt='%i', delimiter=",") - - return 0 - - -def main(): - # print(f'Saving Mask A0{subject} part {session}') - # save_mask() - print(f'Saving VSDI subject A0{subject} part {session}') - save_vsdi() - print(f'Saving Design matrices A0{subject} part {session}') - save_behav() - - return 0 - - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/vsdi/utils.py b/vsdi/utils.py new file mode 100644 index 0000000..b3efd8f --- /dev/null +++ b/vsdi/utils.py @@ -0,0 +1,796 @@ +# Import data +from pathlib import Path +from scipy.io import loadmat + +# Logging +import logging +from datetime import datetime +import time +from tqdm import tqdm + +# Data management +import numpy as np +from scipy.stats import sem +from scipy.ndimage import gaussian_filter1d +import statsmodels.api as sm +from sklearn.preprocessing import StandardScaler +import scipy.stats as stats +import pickle + +# Dimensionality reduction +from sklearn.decomposition import PCA, FastICA +from sklearn.pipeline import Pipeline + +# VSDI components resizing +import cv2 +from functools import reduce + +# Visualization +import seaborn as sns +import matplotlib.pyplot as plt +from matplotlib.patches import Patch +import matplotlib.ticker as mticker +from statannotations.Annotator import Annotator + +# Decoder +from sklearn.model_selection import StratifiedKFold +from sklearn import svm +from sklearn.metrics import f1_score +from sklearn.utils import shuffle +import warnings +from sklearn.exceptions import ConvergenceWarning + +################ +### BEHAVIOR ### +################ + +def make_design_matrix(b_data, event_sequences, fps=50): + """ + Generates a design matrix based on the provided event sequences. + + The design matrix contains rows corresponding to frames and columns corresponding to events. Each column index in the output matrix represents an event in the event sequences. The number of columns in the design matrix equals the maximum column index specified in the event sequences plus one. + + Parameters + ---------- + event_sequences : dict + A dictionary where keys are event names and values are lists of tuples. Each tuple contains the name of an event, the duration of the event in seconds, and the column index in the output matrix. + + Returns + ------- + matrix : ndarray + Design matrix where each row corresponds to a frame and each column corresponds to an event. + + Examples + -------- + >>> event_sequences = { + ... 'Lick': [('Lick', 1, 5)], + ... 'CSp': [('CS+', 2, 0), ('CS+ Trace', 1, 1), ('Reward', 1, 4)], + ... 'CSn': [('CS-', 2, 2), ('CS- Trace', 1, 3)], + ... } + >>> design_matrix(event_sequences) + # Output: + # matrix with columns: + # 0: CS+ (2s) + # 1: CS+ trace (1s) + # 2: CS- (2s) + # 3: CS- trace (1s) + # 4: Reward (1s) + # 5: Lick + """ + frames = b_data['frames'] + length = len(frames) + n_columns = max(col for seq in event_sequences.values() for _, _, col in seq) + 1 + X = np.zeros((length, n_columns)) + + for event, sequence in event_sequences.items(): + event_data = b_data[event] + + for i in range(len(event_data)): + + frame = np.argmin(np.abs(frames - event_data[i])) + + for event_name, duration, column in sequence: + duration_unit = fps * duration if fps * duration != 0 else 1 # extreme case for licks + X[frame:(frame + int(duration_unit)), column] = 1 + frame += fps * duration + + return X + +def subsets(Set): + """ + Finds the starting indices of subsets of consecutive numbers within the provided set. + + This function identifies series of consecutive numbers (subsets) within the input set. + It returns a numpy array of the starting indices of each identified subset. + + Parameters + ---------- + Set : list or array-like + List or array-like object containing the series of numbers to be partitioned into subsets. + + Returns + ------- + subsets : ndarray + A numpy array containing the starting indices of each identified subset of consecutive numbers. + + Examples + -------- + >>> subsets([1, 2, 3, 5, 6, 8, 9, 10]) + # Output: array([1, 5, 8]) + + Notes + ----- + The subsets are defined as series of consecutive numbers. For example, in the array + [1, 2, 3, 5, 6, 8, 9, 10], the subsets of consecutive numbers are [1, 2, 3], [5, 6] + and [8, 9, 10], so the function returns the starting points [1, 5, 8]. + """ + subsets = [] + start = 0 + end = 0 + + # Iterate over array + while end < len(Set): + + # Get first and last frame of each subset + while end + 1 < len(Set) and Set[end + 1] - Set[start] == end - start + 1: + end += 1 + + # Save first and last frame of each outlier subset + subsets.append(Set[start]) + start = end = end + 1 + + return np.array(subsets) + +def get_trials(feature): + """ + Finds the starting indices of trials within the provided design matrix vector. + + This function identifies the start of each trial within the input design matrix vector, + where trials are defined as sequences where the feature equals 1. + + Parameters + ---------- + feature : list or array-like + List or array-like object representing a design matrix vector. The start of each + trial is defined as the index where the feature value equals 1. + + Returns + ------- + feature_trials : ndarray + A numpy array containing the starting indices of each identified trial. + + Examples + -------- + >>> get_trials([0, 0, 1, 1, 1, 0, 0, 1, 1, 0]) + # Output: array([2, 7]) + + Notes + ----- + The trials are defined as sequences where the feature equals 1. For example, in the array + [0, 0, 1, 1, 1, 0, 0, 1, 1, 0], the trials are [1, 1, 1] and [1, 1], so the function + returns the starting points [2, 7]. + """ + # Find the indices where feature is 1 + feature_trials = subsets(np.where(feature == 1)[0]) + + return feature_trials + +def compute_lick_rate(data, trial_onsets, fps): + """ + Compute the lick rate for each trial. + + For each trial, the function computes the number of licks during a 'baseline' period + of 1 second before CS presentation and during a 'trace' period of 1 second starting + 2 seconds after CS presentation. The lick rate for the trial is then computed as + the number of licks in the trace period minus the number of licks in the baseline period. + + Parameters + ---------- + data : ndarray + 1D numpy array containing lick data. Each element corresponds to a frame, and its + value indicates whether a lick occurred in that frame (1) or not (0). + + trial_onsets : ndarray + 1D numpy array containing the onset times (in frames) of each trial. + + fps : int + Frame rate of the data (frames per second). + + Returns + ------- + lick_rates : list + List of lick rates for each trial. + + Examples + -------- + >>> lick_data = np.random.randint(0, 2, 600) # Mock lick data + >>> trial_onsets = np.array([100, 300, 500]) # Mock trial onset times + >>> fps = 30 # Frame rate + >>> lick_rates = compute_lick_rate(lick_data, trial_onsets, fps) + """ + lick_rates = [] + + for i in range(len(trial_onsets)): + + trial_start = trial_onsets[i] + # Baseline -1 s before CS presentation + baseline_licks = np.sum(data[(trial_start-fps):trial_start]) + # Number of licks in trace period + trace_licks = np.sum(data[trial_start+(2*fps):trial_start+(3*fps)]) + # Corrected lick rate + lick_rate = trace_licks - baseline_licks + + lick_rates.append(lick_rate) + + return lick_rates + +def store_indices(animals, days, sessions, outpath): + """ + Store cumulative index (based on X matrix length) for each session, day, and animal, + as well as trial indices for CS+ and CS- trials in a nested dictionary structure. + + :param animals: List of animal names + :param days: List of days + :param sessions: List of sessions + :param outpath: Path to the output directory + :return: A nested dictionary containing the cumulative indices and trial indices + """ + # Initialize an empty dictionary + X = {animal: {day: {} for day in days} for animal in animals} + + # Iterate over all animals, days, and sessions + for animal in animals: + for day in days: + # Initialize the cumulative count + cumulative_count = 0 + + for session in sessions: + # Load design matrix + X_matrix = np.loadtxt(outpath.joinpath(f"X_{animal}_{day}_{session}.csv"), delimiter=",") + + # Here we are assuming 'CS+' info is in column 0 and 'CS-' info is in column 2 + trial_types = ['CS+', 'CS-'] + for trial_type, column in zip(trial_types, [0, 2]): + feature = X_matrix[:, column] + trial_indices = get_trials(feature) + + # Store the trial indices in the nested dictionary + if session not in X[animal][day]: + X[animal][day][session] = {} + X[animal][day][session][trial_type] = trial_indices + + # Update the cumulative count + cumulative_count += len(X_matrix) + + # Store the cumulative count in the nested dictionary + X[animal][day][session]['Cumulative Index'] = cumulative_count + + return X + + +############ +### VSDI ### +############ + +def apply_mask(vsdi, mask): + """ + Apply a mask to a numpy array and set masked values to NaN. + + Parameters + ---------- + vsdi : np.ndarray + The input array on which to apply the mask. + mask : np.ndarray + The mask to be applied. Same shape as `vsdi`. Masked locations are where mask equals 0. + + Returns + ------- + np.ndarray + A new array with the mask applied (i.e., positions where mask equals 0 are set to NaN). + + """ + vsdi_copy = vsdi.copy() + vsdi_copy[np.where(mask == 0)] = np.nan + return vsdi_copy + +def pca_ica(vsdi, mask): + X = vsdi.transpose(2, 0, 1) + X = X*mask + X = X.reshape(X.shape[0], X.shape[1]*X.shape[2]) + + # Create a pipeline with PCA and ICA + pipe = Pipeline([ + ('pca', PCA(n_components=10)), + ('ica', FastICA(n_components=10, max_iter=200, + random_state=1, whiten='unit-variance')) + ]) + + out = pipe.fit(X) + + fingerprints = out.named_steps["ica"].components_ @ out.named_steps["pca"].components_ + timecourses = fingerprints @ X.T + + explained_variance = out.named_steps["pca"].explained_variance_ratio_ + + return fingerprints, timecourses, explained_variance + +def normalize_vsdi(vsdi, mask): + # Transpose to this shape (time, x, y) + v_t = vsdi.transpose(2, 0, 1) + # Mask vsdi + v_masked = v_t * mask + v_reshaped = v_masked.reshape(v_masked.shape[0], v_masked.shape[1]*v_masked.shape[2]) + # Normalize usign Standard Scaler + v_norm = StandardScaler().fit_transform(v_reshaped) + v_norm_reshaped = v_norm.reshape(v_masked.shape[0], v_masked.shape[1], v_masked.shape[2]) + # Transpose to this shape (x, y, time) + v_norm_original = v_norm_reshaped.transpose(1, 2, 0) + + return v_norm_original + +def find_outliers(vsdi, nsigma=3): + """ + Identify the start and end indices of outlier frames in VSDI data + + Parameters + ---------- + vsdi : numpy ndarray + vsdi data in format (h, w, time) + nsigma : float + Number of standard deviations to consider an outlier + + Returns + ------- + outliers_subsets : list of tuples + Each tuple contains the start and end indices of an outlier subset + """ + mean_vsdi = np.mean(vsdi, axis=(0, 1)) + # How many standard deviations away a value is from the mean + zscore = stats.zscore(mean_vsdi, axis=0, ddof=0, nan_policy='propagate') + # zscore = StandardScaler().fit_transform(vsdi) + + # Get index of outliers from vsdi presenting average activity higher than 4 sigma + outliers = np.argwhere((zscore > nsigma) | (zscore < -nsigma)).ravel() + + subsets = [] + start = 0 + end = 0 + + # Iterate over array + while end < len(outliers): + # Get first and last frame of each subset + while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: + end += 1 + # Save first and last frame of each outlier subset + subsets.append((outliers[start], outliers[end])) + start = end = end + 1 + + return np.array(subsets) + +def clean_outliers(vsdi, nsigma=3): + """ + Correct outliers by pixel-wise linear interpolation in VSDI data + + Parameters + ---------- + vsdi : numpy ndarray + vsdi data in format (h, w, time) + nsigma : float + Number of standard deviations to consider an outlier + + Returns + ------- + vsdi : numpy ndarray + vsdi data with outliers corrected + """ + vsdi = vsdi.copy() + # Get first and last frame of each subset + outliers_subsets = find_outliers(vsdi, nsigma) + + # Set outlier frames to the mean between the previous and next frame + for i in range(len(outliers_subsets)): + start = outliers_subsets[i][0] + end = outliers_subsets[i][1] + if start == 0: + vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, end+1][:, :, np.newaxis], (1, 1, end - start + 1)) + elif end == vsdi.shape[2]-1: + vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, start-1][:, :, np.newaxis], (1, 1, end - start + 1)) + else: + average = np.divide(np.add(vsdi[:, :, (start-1)][:, :, np.newaxis], vsdi[:, :, (end+1)][:, :, np.newaxis]), 2) + vsdi[:, :, start:end+1] = average + return vsdi + +def find_bounding_rectangle(binary_image): + contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + if contours: + x, y, w, h = cv2.boundingRect(contours[0]) + return (x, y), (x + w, y + h) + else: + return None + +def crop_to_bounds(image, bounds): + return image[bounds[0][1]:bounds[1][1],bounds[0][0]:bounds[1][0]] + +def resize(mask_list): + max_h = np.max([x.shape[0] for x in mask_list]) + max_w = np.max([x.shape[1] for x in mask_list]) + + resized = [] + for m in mask_list: + resized_mask = cv2.resize(m, (max_w, max_h), interpolation=cv2.INTER_CUBIC) + resized.append(resized_mask) + + return resized + +def resize_video(video_list): + max_h = np.max([c.shape[0] for c in video_list]) + max_w = np.max([c.shape[1] for c in video_list]) + resized_vsdi = [] + + for arr in video_list: + # The last dimension (time) is not affected by resizing, + # so we need to iterate over it + reshaped_images = [] + for i in range(arr.shape[2]): + # Resize each 2D slice along the third axis + reshaped_img = cv2.resize(arr[:,:,i], (max_w, max_h), interpolation=cv2.INTER_CUBIC) + reshaped_images.append(reshaped_img) + + # Stack the reshaped images along the third axis + resized_vsdi.append(np.dstack(reshaped_images)) + + return(resized_vsdi) + +def filter_data2(data, onset, offset, idxs): + fragments = [] + # For ids + for idx in idxs: + # Check data dimensionality + if len(data.shape) == 1: + # Append data slice + fragment = data[idx+onset:idx+offset] + else: + slices = [slice(None)] * (data.ndim - 1) + slices.append(slice(idx+onset, idx+offset)) + fragment = data[tuple(slices)] + fragments.append(fragment) + # Return ndarrray of fragments + return np.stack(fragments) + +def filter_data(data, onset, offset, idxs): + """ + Get ndarray of data fragments based on index (idx+onset to idx+offset) + """ + fragments = [] + for idx in idxs: + if len(data.shape) == 1: + # Manage extreme cases (when onset offset falls outside data) Why are there onsets at the end of the data? + if idx + onset < 0 or idx + offset > data.shape[0]: + start = max(idx + onset, 0) + end = min(idx + offset, data.shape[0]) + length = offset - onset + fragment = np.full(length, 0) # Fill missing fragment of data with value + fragment[:end-start] = data[start:end] + else: + fragment = data[idx + onset:idx + offset] + else: + slices = [slice(None)] * (data.ndim - 1) + if idx + onset < 0 or idx + offset > data.shape[-1]: + start = max(idx + onset, 0) + end = min(idx + offset, data.shape[-1]) + length = offset - onset + fragment = np.full(data.shape[:-1] + (length,), 0) # Fill missing fragment of data with value + slices_start_end = slices + [slice(start, end)] + fragment[..., :end-start] = data[tuple(slices_start_end)] + else: + slices.append(slice(idx + onset, idx + offset)) + fragment = data[tuple(slices)] + fragments.append(fragment) + return np.stack(fragments) + +def split_data(data, labels, axis=-1, attr=1): + """ + Splits the provided data based on the given labels. + + The function partitions a multidimensional data array into smaller slices, + based on the shapes provided in the labels list. The slices are then stored in a dictionary, + where the keys are determined by the `attr` attribute of the info list. + + Parameters + ---------- + data : ndarray + Multidimensional array to be partitioned. + labels : list + List of tuples, where each tuple contains an info list and a shape integer. + Example: + [ + (['A07', 'Day1', 'ATC1'], 30000), + (['A07', 'Day1', 'ATC2'], 30000) + ] + axis : int, optional + The axis along which the data array is to be sliced, by default -1 (the last axis). + attr : int, optional + The index of the attribute in the info list that will be used as a key in the resulting dictionary, + by default 1 (the second item). + + Returns + ------- + partitioned_data : dict + A dictionary where keys are the extracted attribute from the info list, + and values are the partitioned slices of the input data. + + Examples + -------- + >>> data = np.arange(60000).reshape((2, 30000)) + >>> labels = [(['A07', 'Day1', 'ATC1'], 30000), (['A07', 'Day1', 'ATC2'], 30000)] + >>> split_data(data, labels, axis=0, attr=1) + {'Day1': [array([0, 1, ..., 29998, 29999]), array([30000, 30001, ..., 59998, 59999])]} + """ + # Start index for slicing + start = 0 + # Partitioned data dictionary + partitioned_data = {} + + for info, shape in labels: + day = info[attr] # Extracting 'Day' attribute from info list + + # Slicing the array + slices = [slice(None)] * data.ndim # Create as many slices as dimensions + slices[axis] = slice(start, start+shape) # Modify the slice for the specified axis + sliced = data[tuple(slices)] + + # Storing the sliced array into dictionary + if day in partitioned_data: + partitioned_data[day].append(sliced) + else: + partitioned_data[day] = [sliced] + + # Updating start index for next slice + start += shape + + return partitioned_data + +################ +### DECODING ### +################ + +def train_SVM_day(t_csp_day, t_csn_day, time_bin_size, n_splits=5, n_shuffles=100, n_iter=1000, tol=1e-4): + # concatenate the two ndarrays + t_all_day = np.concatenate((t_csp_day, t_csn_day), axis=0) + + # Create time points based on time bin size + time_points = range(0, t_all_day.shape[2], time_bin_size) + + # initialize StratifiedKFold + skf = StratifiedKFold(n_splits=n_splits) + + # prepare the label vector + stim_type = np.array([0] * t_csp_day.shape[0] + [1] * t_csn_day.shape[0]) + + avg_performance = [] + std_performance = [] + surrogate_performance = [] + + # for each time bin, train a separate SVM classifier + for i in time_points: + # Average within time bin for SVM + X_bin = np.mean(t_all_day[:, :, i:i+time_bin_size], axis=2) + + # flatten the data for SVM + X = X_bin.reshape(t_all_day.shape[0], -1) + y = stim_type + + accuracy_scores = [] + surrogate_scores = [] + + for train_index, test_index in skf.split(X, y): + print(f'Computing time bin {int(i/time_bin_size)}/{len(time_points)}') + X_train, X_test = X[train_index], X[test_index] + y_train, y_test = y[train_index], y[test_index] + + # Train SVM + clf = svm.LinearSVC(max_iter=n_iter, tol=tol) + clf.fit(X_train, y_train) + + # calculate accuracy + accuracy = f1_score(y_test, clf.predict(X_test)) + accuracy_scores.append(accuracy) + + # Surrogate analysis + for _ in tqdm(range(n_shuffles)): + y_train_shuffle = shuffle(y_train) + clf.fit(X_train, y_train_shuffle) + surrogate_accuracy = f1_score(y_test, clf.predict(X_test)) + surrogate_scores.append(surrogate_accuracy) + + # calculate average and standard deviation of accuracy for the current time point + avg_performance.append(np.mean(accuracy_scores)) + std_performance.append(np.std(accuracy_scores)) + surrogate_performance.append(surrogate_scores) + + avg_performance = np.asarray(avg_performance) + std_performance = np.asarray(std_performance) + surrogate_performance = np.asarray(surrogate_performance) + + return avg_performance, std_performance, surrogate_performance + +def train_SVM_baseline2(t_sound_day, t_baseline_day, time_bin_size, n_splits=5, n_shuffles=100, n_iter=1000, tol=1e-4): + # Create time points based on time bin size + time_points = range(0, t_sound_day.shape[2], time_bin_size) + + # initialize StratifiedKFold + skf = StratifiedKFold(n_splits=n_splits) + + avg_performance = [] + std_performance = [] + surrogate_performance = [] + + # for each time bin, train a separate SVM classifier + for i in time_points: + print(f'Computing time bin {int(i/time_bin_size)}/{len(time_points)}') + + # get the data for this time bin + t_sound_bin = t_sound_day[:, :, i:i+time_bin_size] + t_baseline_bin = np.tile(t_baseline_day, (1, 1, t_sound_bin.shape[2] // t_baseline_day.shape[2])) + + # concatenate the sound and baseline ndarrays for this time bin + t_all_bin = np.concatenate((t_sound_bin, t_baseline_bin), axis=0) + + # prepare the label vector + y = np.array([0] * t_sound_bin.shape[0] + [1] * t_baseline_bin.shape[0]) + + # flatten the data for SVM + X = t_all_bin.reshape(t_all_bin.shape[0], -1) + + accuracy_scores = [] + surrogate_scores = [] + + for train_index, test_index in skf.split(X, y): + X_train, X_test = X[train_index], X[test_index] + y_train, y_test = y[train_index], y[test_index] + + # Train SVM + clf = svm.LinearSVC(max_iter=n_iter, tol=tol) + clf.fit(X_train, y_train) + + # calculate accuracy + accuracy = f1_score(y_test, clf.predict(X_test)) + accuracy_scores.append(accuracy) + + # Surrogate analysis + for _ in tqdm(range(n_shuffles)): + y_train_shuffle = shuffle(y_train) + clf.fit(X_train, y_train_shuffle) + surrogate_accuracy = f1_score(y_test, clf.predict(X_test)) + surrogate_scores.append(surrogate_accuracy) + + # calculate average and standard deviation of accuracy for the current time point + avg_performance.append(np.mean(accuracy_scores)) + std_performance.append(np.std(accuracy_scores)) + surrogate_performance.append(surrogate_scores) + + avg_performance = np.asarray(avg_performance) + std_performance = np.asarray(std_performance) + surrogate_performance = np.asarray(surrogate_performance) + + return avg_performance, std_performance, surrogate_performance + +def train_SVM_baseline(t_sound_day, t_baseline_day, time_bin_size, n_splits=5, n_shuffles=100, n_iter=1000, tol=1e-4): + # Create time points based on time bin size + time_points = range(0, t_sound_day.shape[2], time_bin_size) + + # initialize StratifiedKFold + skf = StratifiedKFold(n_splits=n_splits) + + avg_performance = [] + std_performance = [] + surrogate_performance = [] + svm_coefficients = [] # to store the SVM coefficients + + # for each time bin, train a separate SVM classifier + for i in time_points: + print(f'Computing time bin {int(i/time_bin_size)}/{len(time_points)}') + + # get the data for this time bin + t_sound_bin = t_sound_day[:, :, i:i+time_bin_size].mean(axis=2) # taking average over time_bin dimension + t_baseline_bin = t_baseline_day.mean(axis=2) # taking average over time_bin dimension + + # concatenate the sound and baseline ndarrays for this time bin (trials, components) + t_all_bin = np.concatenate((t_sound_bin, t_baseline_bin), axis=0) + + # prepare the label vector + y = np.array([0] * t_sound_bin.shape[0] + [1] * t_baseline_bin.shape[0]) + + # flatten the data for SVM (trials, components) + X = t_all_bin.reshape(t_all_bin.shape[0], -1) + + accuracy_scores = [] + surrogate_scores = [] + + for train_index, test_index in skf.split(X, y): + X_train, X_test = X[train_index], X[test_index] + y_train, y_test = y[train_index], y[test_index] + + # Train SVM + clf = svm.LinearSVC(max_iter=n_iter, tol=tol) + clf.fit(X_train, y_train) + + # calculate accuracy + accuracy = f1_score(y_test, clf.predict(X_test)) + accuracy_scores.append(accuracy) + + svm_coefficients.append(clf.coef_) # store the SVM coefficients + + # Surrogate analysis + for _ in tqdm(range(n_shuffles)): + y_train_shuffle = shuffle(y_train) + clf.fit(X_train, y_train_shuffle) + surrogate_accuracy = f1_score(y_test, clf.predict(X_test)) + surrogate_scores.append(surrogate_accuracy) + + + # calculate average and standard deviation of accuracy for the current time point + avg_performance.append(np.mean(accuracy_scores)) + std_performance.append(np.std(accuracy_scores)) + surrogate_performance.append(surrogate_scores) + + svm_coefficients = np.array(svm_coefficients) + avg_performance = np.asarray(avg_performance) + std_performance = np.asarray(std_performance) + surrogate_performance = np.asarray(surrogate_performance) + + return avg_performance, std_performance, surrogate_performance, svm_coefficients + +def moving_average(a, n=3): + if n > 1: + ret = np.cumsum(a, dtype=float) + ret[n:] = ret[n:] - ret[:-n] + return ret[n - 1:] / n + else: + return a + +def plot_decoding_performance(avg_performance, std_performance, color, fps=50, time_bin_size=5, window_size=5, label=None, ypos=1): + # Apply moving average + avg_performance_smooth = moving_average(avg_performance, window_size) + std_performance_smooth = moving_average(std_performance, window_size) + + # Compute bin_centers_sec_smooth after smoothing + num_bins = len(avg_performance_smooth) + bin_centers_sec = np.arange(avg_performance.shape[0])*time_bin_size/fps - 100/50 # First calculate for the original performance data + + if window_size > 1: + bin_centers_sec_smooth = bin_centers_sec[:num_bins] # Then adjust for the smoothing + else: + bin_centers_sec_smooth = bin_centers_sec # No smoothing, so they are the same + + # Ensure the lengths match after smoothing + bin_centers_sec_smooth = bin_centers_sec_smooth[:len(avg_performance_smooth)] + + plt.plot(bin_centers_sec_smooth, avg_performance_smooth, color = color, zorder = 1) + plt.fill_between(bin_centers_sec_smooth, avg_performance_smooth - std_performance_smooth, + avg_performance_smooth + std_performance_smooth, color = color, alpha=0.2, zorder = 1) + + plt.axhline(y=0.5, color="black", linestyle=(0, (1, 5))) #, label='chance level') + # Add the axvspan for CS+ sound presentation + plt.axvspan(0, 2, color='lightgray', alpha=1, zorder=0) # label="Sound") + # Add the axvspan for Reward period + plt.axvspan(2 + 1, 2 + 2, color='#B5DBA8', alpha=1, zorder=0) # label="Reward") + + plt.xlabel('Time from sound onset (s)') + plt.ylabel('Accuracy (%)') + + # Modify y-tick labels to display as multiples of 100 without the % symbol + formatter = mticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x*100)) + plt.gca().yaxis.set_major_formatter(formatter) + + # Set y-limit + # plt.ylim(0, 1) + + # Get the current axes + ax = plt.gca() + # Modify the spines of the current axes + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + + # Add a colored label at the top left corner + plt.text(0.02, ypos, label, transform=plt.gca().transAxes, color=color, fontsize=12, va='top') diff --git a/vsdi/vsdi_visualization.py b/vsdi/visualization.py similarity index 95% rename from vsdi/vsdi_visualization.py rename to vsdi/visualization.py index 961686d..bd1b02c 100644 --- a/vsdi/vsdi_visualization.py +++ b/vsdi/visualization.py @@ -6,11 +6,11 @@ import seaborn as sns from scipy.stats import sem from scipy.ndimage import gaussian_filter1d -sns.set_theme(context='notebook', - style='white', - font_scale=1.5, - rc = {'axes.spines.top':False,'axes.spines.right':False, - 'image.cmap':plt.cm.jet}) +# sns.set_theme(context='notebook', +# style='white', +# font_scale=1.5, +# rc = {'axes.spines.top':False,'axes.spines.right':False, +# 'image.cmap':plt.cm.jet}) ########################################################## @@ -81,7 +81,6 @@ def plot_fingerprints(PCs, raw_mask): plt.axis('off') def create_frame(vsdi, t): - # VSDI - Should be already masked plt.imshow(vsdi[:,:,t], cmap=plt.cm.jet) plt.axis('off') diff --git a/vsdi/vsdi.py b/vsdi/vsdi.py deleted file mode 100644 index abda7e0..0000000 --- a/vsdi/vsdi.py +++ /dev/null @@ -1,164 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import matplotlib.pyplot as plt -import numpy as np -from scipy import stats -from scipy.stats import norm -from sklearn.decomposition import PCA -import seaborn as sns -sns.set_theme(context='notebook', - style='white', - font_scale=1.5, - rc = {'axes.spines.top':False,'axes.spines.right':False, - 'image.cmap':plt.cm.jet}) - -########################################################## -####################### VSDI CLASS ####################### -########################################################## - -class VSDI: - def __init__(self, vsdi, raw_mask): - """ - Constructor for VSDI class - """ - self.vsdi = self.correct_outliers(vsdi) - self.raw_mask = raw_mask - self.X = self.vsdi.transpose(2,0,1) # reshape in time x image format - self.T,self.h,self.w = self.X.shape # saves time, height and width for future use - self.X = self.X[:,self.raw_mask] # select only cortex pixels, returns a flattened image - - def time_course(self, start_time=0, end_time=600, framerate=50): - """ - Plot time course of a single PC - """ - plt.figure(figsize=(10, 5)) - t = np.linspace(start_time, end_time, int((end_time - start_time) * framerate - 1)) - plt.plot(t, self.vsdi) - plt.xlabel('Time (s)') - plt.ylabel('PC activation (a.u.)') - plt.show() - - def create_frame(self, t): - """ - Create a frame of the VSDI data - """ - plt.figure(figsize=(10, 10)) - plt.imshow(self.vsdi[:, :, t], cmap=plt.cm.inferno) - - def pca(self, n_components=50): - """ - Perform PCA on the VSDI data - """ - pca = PCA(n_components=n_components) - pca.fit(self.X) - - return pca - - def pca_projection(self, pca, num_pc): - """ - Plot the projection of the data onto the first 10 PCs - """ - PCs = pca.components_[:num_pc].T - Y = self.X @ PCs # compute the PC timecourse, by projecting the original data on each component - return Y - - def cumulative_explained_variance(self, pca): - """ - Plot cumulative explained variance - """ - evr = pca.explained_variance_ratio_ - c_evr = np.cumsum(evr) - plt.figure(figsize=(6, 6)) - plt.axhline(0.9, linestyle='--', label='90% explained variance') - plt.plot(range(1, len(c_evr) + 1), c_evr) - plt.legend() - plt.xlabel('# of components') - plt.ylabel('EVR') - - def fingerprint(self, pca, num_pc = 10): - """ - Plot topographic organzation of the weights of these ten components - """ - PCs = pca.components_[:num_pc] - plt.figure(figsize=(10, 5)) - for i, pc in enumerate(PCs): - plt.subplot(2, 5, i + 1) - plt.title(f'PC {i + 1}') - reshaped_pc = np.full((self.h, self.w), np.nan) - reshaped_pc[np.where(self.raw_mask)] = pc - plt.imshow(reshaped_pc, aspect='auto', cmap=plt.cm.jet) - plt.axis('off') - - def first_last_subsets(self, arr): - """ - Get first and last frame of each subset - """ - subsets = [] - start = 0 - end = 0 - while end < len(arr): - while end + 1 < len(arr) and arr[end + 1] - arr[start] == end - start + 1: - end += 1 - subsets.append((arr[start], arr[end])) - start = end = end + 1 - return np.array(subsets) - - def correct_outliers(self, vsdi, nsigma=4): - """ - Correct outliers in VSDI data - """ - # Array with average value of all frames in vsdi - mean_vsdi = np.mean(vsdi, axis=(0,1)) - std_vsdi = vsdi.std() - - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((mean_vsdi > nsigma*std_vsdi) | (mean_vsdi < -nsigma*std_vsdi)).ravel() - - # Get first and last frame of each subset - outliers_subsets = self.first_last_subsets(arr = outliers) - - # Set outlier frames to the mean between the previous and next frame - for i in range(len(outliers_subsets)): - start = outliers_subsets[i][0] - end = outliers_subsets[i][1] - if start == 0: - vsdi[:,:,start:end+1] = np.tile(vsdi[:,:,end+1][:, :, np.newaxis], (1, 1, end - start + 1)) - elif end == len(mean_vsdi)-1: - vsdi[:,:,start:end+1] = np.tile(vsdi[:,:,start-1][:, :, np.newaxis], (1, 1, end - start + 1)) - else: - average = np.divide(np.add(vsdi[:,:,start-1][:, :, np.newaxis], vsdi[:,:,end+1][:, :, np.newaxis]), 2) - vsdi[:,:,start:end+1] = average - return vsdi - - def bimodality_test(self, distribution): - """ - Test for bimodality using moving average to smooth the histogram - and get the x-axis location of the highest point in the histogram - """ - # Create a histogram - n, bins, patches = plt.hist(distribution, bins=1000) - # Define the window size for the moving average - window_size = 5 - # Create the moving average kernel - kernel = np.ones(window_size) / window_size - # Convolve the histogram data with the moving average kernel - smoothed = np.convolve(n, kernel, mode='same') - bins_adjusted = bins[:-1] - - # Find the x-axis location of the highest point in the histogram - x_max = bins_adjusted[np.argmax(smoothed)] - - return x_max - - def bimodal_components(self, Y, threshold=1): - """ - Get bimodal components - """ - bimodal_components = [] - for i in range(Y.shape[1]): - x_max = self.bimodality_test(Y[:,i]) - if abs(x_max) > threshold: - bimodal_components.append([i, x_max]) - - return bimodal_components \ No newline at end of file diff --git a/vsdi/vsdi_preprocessing.py b/vsdi/vsdi_preprocessing.py deleted file mode 100644 index 10a6ddc..0000000 --- a/vsdi/vsdi_preprocessing.py +++ /dev/null @@ -1,383 +0,0 @@ -########################################################## -######################## PACKAGES ######################## -########################################################## -import numpy as np -from sklearn.decomposition import PCA, FastICA -from sklearn.preprocessing import StandardScaler -from sklearn.pipeline import Pipeline -import scipy.stats as stats -import statsmodels.api as sm - - -########################################################## - -def peak_distance(component, smooth_window_size, hist_nbins): - # Create a histogram - n, bins = np.histogram(component, bins=hist_nbins) - # Define the window size for the moving average - window_size = smooth_window_size - # Create the moving average kernel - kernel = np.ones(window_size) / window_size - # Convolve the histogram data with the moving average kernel - smoothed = np.convolve(n, kernel, mode='same') - bins_adjusted = bins[:-1] - # Find the x-axis location of the highest point in the histogram - x_max = bins_adjusted[np.argmax(smoothed)] - - return x_max - - -def check_bimodal(components, th=1.0, smooth_window_size=5, hist_nbins=1000): - """ - Test for bimodality using moving average to smooth the histogram - and get the x-axis location of the highest point in the histogram - - Parameters - ---------- - components : numpy ndarray (components, time) - Timecourse of a single component - threshold : float - Threshold for bimodal distribution identification (distance from peak to zero) - - Returns - ------- - bimodal_components : list - List of components that are bimodal (1 if bimodal, 0 if not) - """ - # Initialize bimodal_components list - bimodal_components = np.zeros(components.shape[0]) - for i in range(components.shape[0]): - # Get peak distance - x_max = peak_distance(components[i], smooth_window_size, hist_nbins) - # Check if peak distance is above threshold - if abs(x_max) > th: - bimodal_components[i] = 1 - - return bimodal_components - - -def clean_hemodynamic_pca(vsdi, n_components=50, bimodal_th=1, - smooth_window=5, hist_nbins=1000, verbose=False): - """ - Clean hemodynamic noise from vsdi data - - Parameters - ---------- - vsdi : numpy array - vsdi data in format (time, pixels_y, pixels_X) - n_components : int - Number of components to keep after PCA - bimodal_th : float - Threshold for bimodal distribution identification - smooth_window : int - Window size for smoothing the histogram of timecourse distribution - hist_nbins : int - Number of bins for histogram of timecourse distribution - - Returns - ------- - clean_vsdi : numpy array in the same format as vsdi input - vsdi data with hemodynamic noise removed - """ - # reshape vsdi data to (time, pixels) - vsdi = vsdi.transpose(2, 0, 1) - # store original shape - vsdi_shape = vsdi.shape - # flatten 2d pixels to array - vsdi = vsdi.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # put out-of-mask values to zero - - # run PCA - pca = PCA(n_components=n_components) - # fit PCA to vsdi data and project it to the new space - timecourses = pca.fit_transform(vsdi) - - # get bimodal components indexes - bad_components = check_bimodal(timecourses.T, th=bimodal_th, - smooth_window_size=smooth_window, - hist_nbins=hist_nbins) - - if verbose: - with open('log.txt', 'a') as f: - # Print explained variance ratio - f.write( - f'{sum(pca.explained_variance_ratio_[np.where(bad_components)]):.4f} ') - # Print number of components - f.write(f'{sum(bad_components):.0f}\n') - - # get clean timecourses and components - good_timecourses = timecourses[:, np.logical_not(bad_components)] - good_components = pca.components_[np.logical_not(bad_components)] - - # reconstruct vsdi data - clean_vsdi = good_timecourses @ good_components - clean_vsdi = clean_vsdi.reshape( - vsdi_shape[0], vsdi_shape[1], vsdi_shape[2]) - clean_vsdi = clean_vsdi.transpose(1, 2, 0) - - return clean_vsdi - - -def clean_hemodynamics(vsdi, n_components=50, bimodal_th=0.8, ica_max_iter=200, - smooth_window=5, hist_nbins=1000, verbose=False): - """ - Clean hemodynamic noise from vsdi data - - Parameters - ---------- - vsdi : numpy array - vsdi data in format (time, pixels_y, pixels_X) - n_components : int - Number of components to keep after PCA - bimodal_th : float - Threshold for bimodal distribution identification - smooth_window : int - Window size for smoothing the histogram of timecourse distribution - hist_nbins : int - Number of bins for histogram of timecourse distribution - - Returns - ------- - clean_vsdi : numpy array in the same format as vsdi input - vsdi data with hemodynamic noise removed - """ - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - vsdi_shape = vsdi.shape - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA and ICA - pipe = Pipeline([ - ('pca', PCA(n_components=n_components)), - ('ica', FastICA(n_components=n_components, max_iter=ica_max_iter, - random_state=88, whiten='unit-variance')) - ]) - - # Fit the pipeline to vsdi data - timecourses = pipe.fit_transform(X) - - # get bimodal components indexes - bad_components = check_bimodal(timecourses.T, th=bimodal_th, - smooth_window_size=smooth_window, - hist_nbins=hist_nbins) - - if verbose: - with open('log.txt', 'a') as f: - # Print number of components - f.write(f'{sum(bad_components):.0f}\n') - - # get clean timecourses and components - good_timecourses = timecourses[:, np.logical_not(bad_components)] - good_components = pipe.named_steps['ica'].components_[ - np.logical_not(bad_components)] - - # reconstruct vsdi data - clean_vsdi = good_components @ pipe.named_steps['pca'].components_ - clean_vsdi = good_timecourses @ clean_vsdi - clean_vsdi = clean_vsdi.reshape( - vsdi_shape[0], vsdi_shape[1], vsdi_shape[2]) - - return clean_vsdi - - -def find_outliers_old(vsdi, mean_vsdi, std_vsdi, nsigma=4): - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((mean_vsdi > nsigma*std_vsdi) - | (mean_vsdi < -nsigma*std_vsdi)).ravel() - - subsets = [] - start = 0 - end = 0 - - # Iterate over array - while end < len(outliers): - # Get first and last frame of each subset - while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: - end += 1 - # Save first and last frame of each outlier subset - subsets.append((outliers[start], outliers[end])) - start = end = end + 1 - - return np.array(subsets) - - -def find_outliers(vsdi, nsigma=6): - mean_vsdi = np.mean(vsdi, axis=(0, 1)) - # How many standard deviations away a value is from the mean - zscore = stats.zscore(mean_vsdi, axis=0, ddof=0, nan_policy='propagate') - # Get index of outliers from vsdi presenting average activity higher than 4 sigma - outliers = np.argwhere((zscore > nsigma) | (zscore < -nsigma)).ravel() - - subsets = [] - start = 0 - end = 0 - - # Iterate over array - while end < len(outliers): - # Get first and last frame of each subset - while end + 1 < len(outliers) and outliers[end + 1] - outliers[start] == end - start + 1: - end += 1 - # Save first and last frame of each outlier subset - subsets.append((outliers[start], outliers[end])) - start = end = end + 1 - - return np.array(subsets) - - -def clean_outliers(vsdi, nsigma=6): - """ - Correct outliers in VSDI data - - Parameters - ---------- - vsdi : numpy ndarray - vsdi data in format (h, w, time) - nsigma : float - Number of standard deviations to consider an outlier - - Returns - ------- - vsdi : numpy ndarray - vsdi data with outliers corrected - """ - vsdi = vsdi.copy() - # Get first and last frame of each subset - outliers_subsets = find_outliers(vsdi, nsigma) - - # Set outlier frames to the mean between the previous and next frame - for i in range(len(outliers_subsets)): - start = outliers_subsets[i][0] - end = outliers_subsets[i][1] - if start == 0: - vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, end+1] - [:, :, np.newaxis], (1, 1, end - start + 1)) - elif end == vsdi.shape[2]-1: - vsdi[:, :, start:end+1] = np.tile(vsdi[:, :, start-1] - [:, :, np.newaxis], (1, 1, end - start + 1)) - else: - average = np.divide(np.add( - vsdi[:, :, (start-1)][:, :, np.newaxis], vsdi[:, :, (end+1)][:, :, np.newaxis]), 2) - vsdi[:, :, start:end+1] = average - return vsdi - - -def design_matrix(b_data): - # Design matrix - # Returns a matrix of size (time, 6) with the following columns: - # 0: CS+ (2s) - # 1: CS+ trace (1s) - # 2: CS- (2s) - # 3: CS- trace (1s) - # 4: Reward (1s) - # 5: Lick - - fps = 50 - - Lick = b_data['Lick'] - CSp = b_data['CSp'] - CSn = b_data['CSn'] - frames = b_data['frames'] - - length = len(frames) - X = np.zeros((length, 6)) - - # Iterate over lick events - for i in range(len(Lick)): - frame = np.argmin(np.abs(frames - Lick[i])) - X[frame:frame+4, 5] = 1 - - # Iterate over CSp events - for i in range(len(CSp)): - frame = np.argmin(np.abs(frames - CSp[i])) - X[frame:frame + (fps * 2), 0] = 1 - frame += (fps * 2) + 1 - X[frame:frame + (fps * 1), 1] = 1 - frame += (fps * 1) + 1 - X[frame:frame + (fps * 1), 4] = 1 - - # Iterate over CSn events - for i in range(len(CSn)): - frame = np.argmin(np.abs(frames - CSn[i])) - X[frame:frame + (fps * 2), 2] = 1 - frame += (fps * 2) + 1 - X[frame:frame + (fps * 1), 3] = 1 - - return X - - -def pca(vsdi, raw_mask=None, n_comp=10, normalize=True): - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - # vsdi_shape = vsdi.shape - if raw_mask is not None: - # put out-of-mask values to zero - X = X[:, raw_mask] - else: - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=10)) - ]) - - # Fit the pipeline to vsdi data - out = pipe.fit(X) - fingerprints = out.named_steps['pca'].components_ - timecourses = fingerprints @ X.T - - return fingerprints, timecourses - - -def pca_ica(vsdi, raw_mask, n_comp=50, ica_max_iter=200): - # reshape vsdi data to (time, pixels) - X = vsdi.transpose(2, 0, 1) - # store original shape - # vsdi_shape = vsdi.shape - if raw_mask is not None: - # put out-of-mask values to zero - X = X[:, raw_mask] - else: - # flatten 2d pixels to array - X = X.reshape(vsdi.shape[0], vsdi.shape[1]*vsdi.shape[2]) - - # Create a pipeline with PCA and ICA - pipe = Pipeline([ - ('scaler', StandardScaler()), - ('pca', PCA(n_components=n_comp)), - ('ica', FastICA(n_components=n_comp, max_iter=ica_max_iter, - random_state=1, whiten='unit-variance')) - ]) - - out = pipe.fit(X) - fingerprints = out.named_steps["ica"].components_ @ out.named_steps["pca"].components_ - timecourses = fingerprints @ X.T - - return fingerprints, timecourses - - -def glm(Y, X): - # Fit Gaussian GLMs - X = sm.add_constant(X) - model = sm.GLM(Y, X, family=sm.families.Gaussian()) - results = model.fit() - - return results - - -def merge_masks(masks, threshold=0.5): - """ - Merge masks by voting majority / logical OR - - Input: masks (n_masks, h, w) - Output: mask_mean (h, w) - """ - mask_mean = np.mean(masks, axis=0) - mask_mean[mask_mean > threshold] = 1 - mask_mean[mask_mean <= threshold] = 0 - return mask_mean