{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cf49a46e-4d11-4132-bd62-87b00b1fb470",
   "metadata": {},
   "source": [
    "# Create Experiment with VoDEx"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "934a51b1-6037-4d56-9a8a-2d23e13ffd3e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "import vodex as vx\n",
    "\n",
    "# for plotting :\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.axes_grid1 import ImageGrid"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06a0a73c-f133-47b8-acbc-dbb5e973e61b",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Adding information about the Volumes\n",
    "\n",
    "You need to provide the folder with the data. Vodex will look into the folder, find all tiff files and assume it's one movie... so probably don't store any extra tiff files in that folder. It is generally a good idea to keed your raw data in a separate folder anyway. If you have to modify the order of the files or exclude some, yo ucan do too (not shown in this example, see FileManager class for more info on how to do it)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "caccfe24-2d4e-4bcf-aab1-57b3849dc183",
   "metadata": {},
   "outputs": [],
   "source": [
    "# data to create an experiment\n",
    "TEST_DATA = \"D:/Code/repos/vodex/data/test\"\n",
    "data_dir = Path(TEST_DATA, \"test_movie\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecf36f4a-8dbf-4c50-9442-204e596bedb5",
   "metadata": {},
   "source": [
    "Now give some information about the volumes. If your data is 2D - set frames_per_volume = 1 , it should work. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a68f7160-b98f-481a-8646-d12e09425ae5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Total frames : 42\n",
       "Volumes start on frame : 0\n",
       "Total good volumes : 4\n",
       "Frames per volume : 10\n",
       "Tailing frames (not a full volume , at the end) : 2"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "frames_per_volume = 10\n",
    "volume_m = vx.VolumeManager.from_dir(data_dir, frames_per_volume)\n",
    "volume_m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58f98125-4126-4c52-b3c3-ff8fb61637d7",
   "metadata": {},
   "source": [
    "The output above looks good. The number of frames is 42, as it should be in the whole movie. You can look at the files  to make sure they are in the correct order : "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "235d18b3-f30c-4e61-9232-1e6aa68ed2bc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image files information :\n",
      "\n",
      "files directory: D:\\Code\\repos\\vodex\\data\\test\\test_movie\n",
      "files [number of frames]: \n",
      "0) mov0.tif [7]\n",
      "1) mov1.tif [18]\n",
      "2) mov2.tif [17]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(volume_m.file_manager)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8399c4a0-19e4-4e90-80fe-f986a9c73835",
   "metadata": {},
   "source": [
    "The file order looks correct! \n",
    "## Initialise experiment\n",
    "To load the volumes or access the annotation you will be using Experiment class. The rest of the calsses are just the helpers to initialise the Experiment. Let's create an experiment class that doesn't have any time annotation information for now. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b0a2b8c4-30e4-4e66-8a24-a4cded9dfd55",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copied 24 of 24 pages...\n"
     ]
    }
   ],
   "source": [
    "annotations = []\n",
    "experiment = vx.Experiment.create(volume_m, annotations)\n",
    "experiment.save(\"test.db\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3663239-5d60-4b99-b907-486762fef2df",
   "metadata": {},
   "source": [
    "Even though we didn't add any annotation , we can use it to simply load the volumes and not worry about what file they are coming from. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "69a520df-7d47-4862-b22a-09e612be3aef",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Code\\repos\\vodex\\src\\vodex\\core.py:1148: UserWarning: The are some frames at the end of the recording that don't correspond to a full volume.\n",
      "  warnings.warn(f\"The are some frames at the end of the recording \"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([-2,  0,  1,  2,  3])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# this gives you the volume list : \n",
    "# positive integer for each whole volume\n",
    "# -1 if you have some extra frames at the beginning \n",
    "# -2 if there are some extra frames at the end , that don't form a whole volume\n",
    "# also throws a warning if there are any of those extra frames\n",
    "experiment.list_volumes()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "99f76e6d-c4e0-4b52-804e-36c8a86bf577",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 10, 200, 200)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# so we have 4 full volumes : 0,1,2,3 and some extra frames at the end (-2)\n",
    "# let's load two full volumes , 0 and 2: \n",
    "vol02 = experiment.load_volumes([0,2])\n",
    "vol02.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7591729-5d06-4033-b5a4-fb4c16e4784d",
   "metadata": {},
   "source": [
    "This will print out the two volumes, frame by frame : "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "393378f7-bb33-4d55-91f3-61cb64a2bb8b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 100180 characters]\n",
      "text/plain": [
       "<Figure size 4000x20000 with 40 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(40., 200.))\n",
    "grid = ImageGrid(fig, 111,  \n",
    "                 nrows_ncols=(2, 10),  \n",
    "                 axes_pad=0.1,  \n",
    "                 )\n",
    "\n",
    "for ax, im in zip(grid, vol02.reshape((20,200,200))):\n",
    "    # Iterating over the grid returns the Axes.\n",
    "    ax.imshow(im)\n",
    "    ax.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1abb6338-8157-4a38-9efa-75ed1a5a2701",
   "metadata": {},
   "source": [
    "If you want to have a look at the rfames at the \" tail\" , you can do so by asking for the \" volume -2\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6834a189-358f-4467-b8a3-f7ef3c5a9ad3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 2, 200, 200)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "volm2 = experiment.load_volumes([-2])\n",
    "volm2.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f115fda8-2846-49e6-ab76-21f0fae2d2e4",
   "metadata": {},
   "source": [
    "Notice how this volume only has 2 frames! "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd8f3386-71c8-4b19-9057-35a453f6be74",
   "metadata": {},
   "source": [
    "## Adding the Time Annotation\n",
    "\n",
    "To add the annotation, you will need to first specify the type of labels that you will be using. You don't have to specify all the annotations at once - you can add more to the experiment later. \n",
    "\n",
    "The Labels class needs the information about the \"label group\" , like what is it describing : light / drug/ sound/ visual stimuli ... and what values the labels can take in that group. Note , that there could be a group \" light\" with labels \"on\" and \"off\" and the label group \"sound\" with labels \"on\" and \"off\" as well.  Labels in different groups can have the same names , but labels per group should be distinct and the group names should be distinct as well... \n",
    "\n",
    "You can also add some optional discriptions, they are not needed for anything - but you might want to save them for your future self reference. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "4763ef58-f678-4bec-94e0-dab7f2d77da8",
   "metadata": {},
   "outputs": [],
   "source": [
    "c_label = vx.Labels(# label type ( group name), string\n",
    "                    \"c label\", \n",
    "                    # label names, keep this brief\n",
    "                    # same rules as for variable names:\n",
    "                    # no leading numbers, no spaces, no special characters\n",
    "                    [\"c1\", \"c2\", \"c3\"], \n",
    "                    # optional: info about the labels\n",
    "                    # {label_name : label information}\n",
    "                    state_info={\"c1\": \"written c1\", \"c2\": \"written c1\"})\n",
    "\n",
    "shape = vx.Labels(\"shape\", \n",
    "                  [\"c\", \"s\"],\n",
    "                  state_info={\"c\": \"circle on the screen\", \"s\": \"square on the screen\"})\n",
    "\n",
    "light = vx.Labels(\"light\",\n",
    "                  [\"on\", \"off\"],\n",
    "                  state_info={\"on\": \"the intensity of the background is high\",\n",
    "                           \"off\": \"the intensity of the background is low\"},\n",
    "                 # optional: information about the group, string\n",
    "                  group_info=\"Light on inverts the colors\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d1eb265-62c5-41f2-9ee1-f3cefa023d98",
   "metadata": {},
   "source": [
    "Now describe what's happening in terms of those labels that you've just made. You can use a cycle for the repeated labels; timeline if you ant to specify what label was active for how many frames , but it's not cyclic , and you can load an annotation from a csv (this feature actually doesn't work right now, but will be back soon ) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "54c590ca-9663-46d2-a3f1-5c8393520a9c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cycle : c label\n",
      "Length: 30\n",
      "Label c1: for 10 frames\n",
      "Label c2: for 10 frames\n",
      "Label c3: for 10 frames\n",
      "\n",
      "Cycle : shape\n",
      "Length: 20\n",
      "Label c: for 5 frames\n",
      "Label s: for 10 frames\n",
      "Label c: for 5 frames\n",
      "\n",
      "Timeline : light\n",
      "Length: 42\n",
      "Label off: for 10 frames\n",
      "Label on: for 20 frames\n",
      "Label off: for 12 frames\n",
      "\n"
     ]
    }
   ],
   "source": [
    "c_label_cyc = vx.Cycle(# order of label presentation\n",
    "                       # how they go in cycle \n",
    "                       [c_label.c1, c_label.c2, c_label.c3],\n",
    "                       # duration of each presentation  \n",
    "                       [10,10,10])\n",
    "shape_cyc = vx.Cycle([shape.c, shape.s, shape.c],\n",
    "                     [5,10,5])\n",
    "\n",
    "light_tml = vx.Timeline(# order of label presentation \n",
    "                        # how they go in WHOLE RECORDING \n",
    "                        [light.off, light.on, light.off], \n",
    "                        # duration of each presentation\n",
    "                        # for timeline: \n",
    "                        # the total duration MUST sum up \n",
    "                        # to the total number of frames in the recording\n",
    "                        [10,20,12])\n",
    "print(c_label_cyc)\n",
    "print(shape_cyc)\n",
    "print(light_tml)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9788b947-8ef7-4e36-a37c-df7c17cfd5c1",
   "metadata": {},
   "source": [
    "Now, using the cycles and timeline you've just created, make the annotatins. This would assign a label to each frame n the movie. You need to provide the total number of frames to do so ( Why? : think how the cycle would tile the whole movie, for example ) \n",
    "\n",
    "You can get the number of frames from the volume manager that you created earlier, or provide it by hand."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "0f805940-a045-408e-8bc4-53ec4dc7fb62",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Annotation type: c label\n",
      "Total frames : 42\n",
      "\n",
      "Annotation type: shape\n",
      "Total frames : 42\n",
      "\n",
      "Annotation type: light\n",
      "Total frames : 42\n",
      "\n"
     ]
    }
   ],
   "source": [
    "n_frames = volume_m.n_frames # 42\n",
    "c_label_an = vx.Annotation.from_cycle(  # the total number of frames in the recording\n",
    "                                        n_frames, \n",
    "                                        # the labels for the corresponding annotation\n",
    "                                        c_label, \n",
    "                                        # the annotation itself: a cycle, a timeline or a file \n",
    "                                        c_label_cyc)\n",
    "shape_an = vx.Annotation.from_cycle(n_frames, shape, shape_cyc)\n",
    "light_an = vx.Annotation.from_timeline(n_frames, light, light_tml)\n",
    "print(c_label_an)\n",
    "print(shape_an)\n",
    "print(light_an)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0fa2b85-146c-4370-864b-f994688767f6",
   "metadata": {},
   "source": [
    "Add annotations to the experiment and rewrite the database that you saved earlier. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "61e73506-446d-4675-ab62-dff8348990ea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copied 24 of 24 pages...\n"
     ]
    }
   ],
   "source": [
    "experiment.add_annotations([shape_an, c_label_an, light_an])\n",
    "experiment.save(\"test.db\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b95805f3-06e2-4ebb-8584-023159a6c250",
   "metadata": {},
   "source": [
    "## Load volumes for certain conditions\n",
    "\n",
    "You will use to methods for thie : \"choose_volumes\" to get the IDs of the volumes that correspond to the condition and then \"load_volumes\" to actually load them"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3b9635b4-2653-40b4-823b-2b1e96841151",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 3]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# let's see what volumes correspond to light \"off\"\n",
    "light_off_ids = experiment.choose_volumes([(\"light\",\"off\")], logic=\"and\")\n",
    "light_off_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "368739d8-1295-432f-a322-9f8ff434f389",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# how about light \"off\" and \"on\" (empty ... which makes sense :) can't be on AND off at the same time)\n",
    "light_off_ids = experiment.choose_volumes([(\"light\",\"off\"),(\"light\",\"on\")], logic=\"and\")\n",
    "light_off_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "7838aeeb-79b6-404f-8782-122ab96dd2b3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# while on OR off highlights all the whole volumes, whihc makes sense too :)\n",
    "light_off_ids = experiment.choose_volumes([(\"light\",\"off\"),(\"light\",\"on\")], logic=\"or\")\n",
    "light_off_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "2c1d9d03-8874-4125-8ef0-10d97beabc6d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 3]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# you can go and experiment with this... \n",
    "light_off_ids = experiment.choose_volumes([(\"light\",\"off\"),(\"c label\",\"c2\")], logic=\"or\")\n",
    "light_off_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "a03bb816-59d1-495f-919c-0e8b8dcd5bb4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 10, 200, 200)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# load the volumes you've chosen \n",
    "vol_off_or_c2 = experiment.load_volumes(light_off_ids)\n",
    "vol_off_or_c2.shape"
   ]
  }
 ],
 "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.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
