{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import time, os\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import multiprocessing as mp\n",
    "\n",
    "import nbimporter\n",
    "from utils import FPSTimes\n",
    "from camera import WebcamStream\n",
    "from video import VideoWriter\n",
    "from position import PositionTracker\n",
    "from sound import SoundController"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test all controllers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Webcam stream 960.0:720.0 at 20.00 FPS started\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred\n",
      "ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred\n",
      "ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sound stopped\n",
      "Position tracker stopped\n",
      "Video writer stopped\n",
      "Camera released\n"
     ]
    }
   ],
   "source": [
    "# sound selector: 0 - silence, 1 - tone 1, 2 - tone 2\n",
    "selector = mp.Value('i', 1)\n",
    "\n",
    "# experiment status: 1 - idle, 2 - running (logging), 0 - stopped\n",
    "status = mp.Value('i', 1)\n",
    "\n",
    "# first start the camera stream\n",
    "vs = WebcamStream(WebcamStream.default_cfg)\n",
    "vs.start()\n",
    "\n",
    "# recording video\n",
    "vw = VideoWriter(status, vs, VideoWriter.default_cfg)\n",
    "vw.start()\n",
    "\n",
    "# tracking position\n",
    "pt_cfg = PositionTracker.default_cfg\n",
    "pt_cfg['background_file'] = os.path.join('..', 'assets', 'background.png')\n",
    "pt = PositionTracker(status, vs, pt_cfg)\n",
    "pt.start()\n",
    "\n",
    "# playing sound in a separate process for performance\n",
    "sc = mp.Process(target=SoundController.run, args=(selector, status, SoundController.default_cfg))\n",
    "sc.start()\n",
    "\n",
    "fps = FPSTimes()\n",
    "names = ['camera', 'video', 'position', 'main']\n",
    "try:\n",
    "    while True:\n",
    "        frame = vs.read()\n",
    "        if frame is not None:\n",
    "            fps.count()\n",
    "            if pt.x is not None:\n",
    "                cv2.circle(frame, (pt.x, pt.y), 3, (127, 255, 0), -1)\n",
    "                \n",
    "            for i, ctrl in enumerate([vs, vw, pt, fps]):\n",
    "                frame = cv2.putText(frame, '%s: %.2f FPS' % (names[i], ctrl.get_avg_fps()), \n",
    "                         (10, 20 * (i+1)), cv2.FONT_HERSHEY_DUPLEX, .5, (255, 255, 255))\n",
    "            \n",
    "            cv2.imshow(\"Experiment\", frame)\n",
    "\n",
    "        k = cv2.waitKey(33)\n",
    "        if k == ord('q'):\n",
    "            break\n",
    "\n",
    "        if k == ord('s'):\n",
    "            status.value = 2 if status.value == 1 else 1\n",
    "\n",
    "finally:\n",
    "    status.value = 0\n",
    "    time.sleep(0.01)\n",
    "    cv2.destroyAllWindows()\n",
    "    sc.join()\n",
    "    for ctrl in [pt, vw, vs]:\n",
    "        ctrl.stop()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Profiling FPS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 87384 characters]\n",
      "text/plain": [
       "<Figure size 1080x432 with 8 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "names = ['camera', 'video', 'position', 'main']\n",
    "ctrls = [vs, vw, pt, fps]\n",
    "\n",
    "fig, axes = plt.subplots(2, len(ctrls), figsize=(15,6))\n",
    "\n",
    "for i, ctrl in enumerate(ctrls):\n",
    "    diffs = ctrl.get_time_diffs()\n",
    "    \n",
    "    # latency histograms\n",
    "    axes[0][i].hist(diffs, 30)\n",
    "    axes[0][i].set_title('%s (%.2f FPS)' % (names[i], 1.0/diffs.mean()), fontsize=14)\n",
    "    \n",
    "    # latency plots\n",
    "    axes[1][i].plot(diffs)\n",
    "    axes[1][i].axhline(diffs.mean(), color='red')\n",
    "    axes[1][i].set_xlabel('Samples', fontsize=14)\n",
    "    if i == 0:\n",
    "        axes[1][i].set_ylabel('Latency, s', fontsize=14)\n",
    "    \n",
    "fig.tight_layout()"
   ]
  },
  {
   "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.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
