Browse Source

added RAW video writer

asobolev 9 months ago
parent
commit
f0dc4e95ba

+ 38 - 34
SIT.ipynb

@@ -58,12 +58,15 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "#cfg_filename = os.path.join('profiles', 'gokce_timeSIT_50_52.5.json')\n",
-    "#cfg_filename = os.path.join('profiles', 'gokce_timeSIT_90_60.json')\n",
+    "cfg_filename = os.path.join('profiles', 'gokce_timeSIT_50_100.json')\n",
+    "# cfg_filename = os.path.join('profiles', 'gokce_timeSIT_90_99.json')\n",
     "#'gokce_timeSIT_90_108.json')\n",
     "\n",
-    "# cfg_filename = os.path.join('profiles', 'social_test_actual.json')\n",
-    "cfg_filename = os.path.join('profiles', 'andrey_ppcSIT_SL_009266.json')"
+    "# cfg_filename = os.path.join('profiles', 'gokce_socialSIT.json')\n",
+    "#cfg_filename = os.path.join('profiles', 'miguel_socialSIT_fireface.json')\n",
+    "# cfg_filename = os.path.join('profiles', 'miguel_socialSIT_fireface_chirp.json')\n",
+    "\n",
+    "# cfg_filename = os.path.join('profiles', 'andrey_ppcSIT_SL_009266.json')"
    ]
   },
   {
@@ -88,19 +91,6 @@
     "#print(json.dumps(cfg, indent=4))"
    ]
   },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# check if the sound interface is there\n",
-    "import sounddevice as sd\n",
-    "asio = [x for x in sd.query_devices() if x['name'].find('ASIO') > 0]\n",
-    "#if len(asio) == 0:\n",
-    "#    raise SystemExit('The sound interface is not found. Please restart the computer')"
-   ]
-  },
   {
    "cell_type": "markdown",
    "metadata": {},
@@ -112,7 +102,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -136,6 +126,8 @@
     "cfg['sound']['file_path'] = os.path.join(save_to, cfg['sound']['file_path'])\n",
     "cfg['position']['background_light'] = os.path.join('assets', cfg['position']['background_light'])\n",
     "cfg['position']['background_dark'] = os.path.join('assets', cfg['position']['background_dark'])\n",
+    "if 'wav_file' in cfg['sound']:\n",
+    "    cfg['sound']['wav_file'] = os.path.join('assets', cfg['sound']['wav_file'])\n",
     "if 'continuous' in cfg['sound']:\n",
     "    cfg['sound']['continuous']['wav_file'] = os.path.join('assets', cfg['sound']['continuous']['wav_file'])\n",
     "    \n",
@@ -153,7 +145,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -163,7 +155,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -174,7 +166,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -189,7 +181,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -215,7 +207,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 9,
    "metadata": {
     "scrolled": true
    },
@@ -227,6 +219,7 @@
       "Webcam stream 1024.0:768.0 at 30.00 FPS started\n",
       "Position tracker stopped\n",
       "Video writer stopped\n",
+      "Video writer stopped\n",
       "Camera released\n"
      ]
     }
@@ -263,10 +256,17 @@
     "vs = WebcamStream(cfg['camera'])\n",
     "vs.start()\n",
     "\n",
-    "# init video recorder\n",
-    "vw = VideoWriter(status, vs, cfg['video'])\n",
+    "# init video recorders\n",
+    "vw  = VideoWriter(status, vs, cfg['video'])  # recorder with infos\n",
     "vw.start()\n",
     "\n",
+    "cfg_video_raw = dict(cfg['video'])\n",
+    "cfg_video_raw['file_path']       = os.path.join(save_to, 'raw.avi')\n",
+    "cfg_video_raw['csv_path']        = os.path.join(save_to, 'raw.csv')\n",
+    "cfg_video_raw['frame_attr_name'] = 'frame_raw'\n",
+    "vwr = VideoWriter(status, vs, cfg_video_raw)  # recorder of raw video\n",
+    "vwr.start()\n",
+    "\n",
     "# init microphone controller, if required\n",
     "if cfg['microphones']['record_audio']:\n",
     "    mc = mp.Process(target=MicrophoneController.run, args=(status,cfg[\"microphones\"]))\n",
@@ -280,7 +280,7 @@
     "dc = SITDisplay(pt, cfg['video'])\n",
     "\n",
     "# playing sound in a separate process for performance\n",
-    "sc = mp.Process(target=SoundController.run, args=(sound, status, cfg['sound']))\n",
+    "sc = mp.Process(target=SoundController.run, args=(sound, status, cfg['sound'], SoundController.commutator))\n",
     "sc.start()\n",
     "\n",
     "cfg_pos = cfg['position']\n",
@@ -324,6 +324,7 @@
     "        \n",
     "        # ---------- rendering logic -----------\n",
     "        frame = vs.read()\n",
+    "                \n",
     "        if frame is None:\n",
     "            time.sleep(0.1)\n",
     "            continue # wait for the stream\n",
@@ -342,7 +343,6 @@
     "        if len(islands) > 0:  # target island X, Y\n",
     "            target = [i for i in islands if not i.is_distractor][0]\n",
     "            text_infos.append('Target: %.3f %.3f' % (target.x, target.y))\n",
-    "#         print(frame.shape)    \n",
     "        text_infos.append('Time: %.2f' % float(c_time - t_start) if t_start is not None else 'Time: Idle')  # stopwatch\n",
     "        text_infos.append('Trial: %.2f' % float(cfg_exp['trial_duration'] - (c_time - trial_start)) if phase == 1 else 'Trial: not started')\n",
     "        text_infos.append('Trial: %s' % trial)\n",
@@ -350,6 +350,7 @@
     "        text_infos.append('In target: %.2f' % float(c_time - target_since) if target_since is not None else 'In target: --')\n",
     "        text_infos.append('ITI distance: %.2f' % iti_distance if iti_distance > 0 else 'ITI distance: --')\n",
     "\n",
+    "        vs.frame_raw = frame  # save raw frame\n",
     "        frame, frame_to_save = dc.render(frame, status, islands=islands, angles=angles, text_infos=text_infos)\n",
     "            \n",
     "        # assign the frame back to the video stream for other controllers\n",
@@ -374,7 +375,8 @@
     "\n",
     "                    elif c_time - target_since > cfg_exp['target_duration']: # successful trial\n",
     "                        log_event(c_time, round(tgt.x, 4), round(tgt.y, 4), round(tgt.r, 4), trial, 1) # log trial success\n",
-    "                        board.feed()\n",
+    "                        tf = threading.Timer(0, board.feed, args=[])\n",
+    "                        tf.start()\n",
     "                        \n",
     "                        # init inter-trial interval and new trial\n",
     "                        trial_start = c_time + cfg_exp['iti_duration'] + 5 * np.random.rand()  # random b/w 20-25 sec\n",
@@ -590,7 +592,7 @@
     "    \n",
     "    cv2.destroyAllWindows()\n",
     "    sc.join()\n",
-    "    for ctrl in [pt, vw, vs]:\n",
+    "    for ctrl in [pt, vw, vwr, vs]:\n",
     "        ctrl.stop()\n",
     "\n",
     "    # stop microphones recording process\n",
@@ -611,7 +613,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 10,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -623,7 +625,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [
     {
@@ -633,7 +635,7 @@
      "traceback": [
       "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
       "\u001b[1;31mIndexError\u001b[0m                                Traceback (most recent call last)",
-      "\u001b[1;32m<ipython-input-12-df6d003c4298>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[1;31m# do pack data to HDF5\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mh5name\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpack\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msession_path\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      6\u001b[0m \u001b[0mtrial\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;32m<ipython-input-11-df6d003c4298>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[1;31m# do pack data to HDF5\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mh5name\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpack\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msession_path\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      6\u001b[0m \u001b[0mtrial\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
       "\u001b[1;32mD:\\runSIT\\..\\pipeline\\postprocessing\\pack.py\u001b[0m in \u001b[0;36mpack\u001b[1;34m(session_path)\u001b[0m\n\u001b[0;32m    165\u001b[0m         \u001b[1;31m# head direction\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    166\u001b[0m         \u001b[0mtemp_tl\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcolumn_stack\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mpos_at_freq\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx_smooth\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my_smooth\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mspeed\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 167\u001b[1;33m         \u001b[0mhd\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mhead_direction\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtemp_tl\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    168\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    169\u001b[0m         \u001b[1;31m# trial numbers\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
       "\u001b[1;32mD:\\runSIT\\..\\pipeline\\postprocessing\\head_direction.py\u001b[0m in \u001b[0;36mhead_direction\u001b[1;34m(tl, hd_update_speed)\u001b[0m\n\u001b[0;32m     22\u001b[0m     \u001b[0mcrit\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwhere\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdiff\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0midle_idxs\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m>\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     23\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 24\u001b[1;33m     \u001b[0midle_periods\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0midle_idxs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0midle_idxs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mcrit\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m)\u001b[0m  \u001b[1;31m# first idle period\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     25\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpoint\u001b[0m \u001b[1;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcrit\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     26\u001b[0m         \u001b[0midx_start\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0midle_idxs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mcrit\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
       "\u001b[1;31mIndexError\u001b[0m: index 0 is out of bounds for axis 0 with size 0"
@@ -834,7 +836,9 @@
    "execution_count": null,
    "metadata": {},
    "outputs": [],
-   "source": []
+   "source": [
+    "\n"
+   ]
   }
  ],
  "metadata": {
@@ -853,7 +857,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.10.8"
+   "version": "3.8.8"
   }
  },
  "nbformat": 4,

+ 4 - 4
controllers/camera.ipynb

@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 1,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -17,7 +17,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -95,7 +95,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
     {
@@ -113,7 +113,7 @@
      "traceback": [
       "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
       "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
-      "\u001b[1;32m<ipython-input-9-0e84daf67e4d>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     10\u001b[0m             \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mimshow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Webcam'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mframe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     11\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m         \u001b[0mk\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwaitKey\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m33\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     13\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mk\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mord\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'q'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     14\u001b[0m             \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;32m<ipython-input-3-0e84daf67e4d>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     10\u001b[0m             \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mimshow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Webcam'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mframe\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     11\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m         \u001b[0mk\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwaitKey\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m33\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     13\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mk\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mord\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'q'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     14\u001b[0m             \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
       "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
      ]
     }

+ 1 - 1
controllers/display.ipynb

@@ -40,7 +40,7 @@
     "        \n",
     "        # mask unused areas\n",
     "        frame = cv2.bitwise_and(src1=input_frame, src2=self.pt.mask)\n",
-    "        self.masked_frame = frame.copy()\n",
+    "        #self.masked_frame = frame.copy()\n",
     "\n",
     "        # size of the arena and status indicator\n",
     "        cv2.circle(frame, (self.pt.cfg['arena_x'], self.pt.cfg['arena_y']), self.pt.cfg['arena_radius'], COLORS['red'], 2)\n",

+ 5 - 5
controllers/position.ipynb

@@ -129,7 +129,7 @@
     "\n",
     "            if self.status.value == 2 and self.positions_in_px is not None:\n",
     "                self.save_position()\n",
-    "                self.save_contours()                  \n",
+    "                #self.save_contours()                  \n",
     "\n",
     "    # generic interface\n",
     "\n",
@@ -187,8 +187,8 @@
     "        \n",
     "        with open(cfg['file_path'], 'w') as f:\n",
     "            f.write(\"time,x,y\\n\")\n",
-    "        with open(cfg['contour_path'], 'w') as f:\n",
-    "            f.write(\"x:y,...\\n\")\n",
+    "        #with open(cfg['contour_path'], 'w') as f:\n",
+    "        #    f.write(\"x:y,...\\n\")\n",
     "            \n",
     "    def detect_position(self, frame):\n",
     "        masked_frame = cv2.bitwise_and(src1=frame, src2=self.mask)\n",
@@ -325,8 +325,8 @@
     "       \n",
     "        with open(cfg['file_path'], 'w') as f:\n",
     "            f.write(\"time,x1,y1,x2,y2\\n\")\n",
-    "        with open(cfg['contour_path'], 'w') as f:\n",
-    "            f.write(\"x:y,...\\n\")\n",
+    "        #with open(cfg['contour_path'], 'w') as f:\n",
+    "        #    f.write(\"x:y,...\\n\")\n",
     "\n",
     "    def detect_position(self, frame):\n",
     "        masked_frame = cv2.bitwise_and(src1=frame, src2=self.mask)\n",

+ 16 - 16
controllers/sound.ipynb

@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
@@ -46,6 +46,18 @@
     "        \"file_path\": \"sounds.csv\"\n",
     "    }\n",
     "    \n",
+    "    commutator = {\n",
+    "        -1: 'noise',\n",
+    "        0:  'silence',\n",
+    "        1:  'background',\n",
+    "        2:  'target',\n",
+    "        3:  'distractor1',\n",
+    "        4:  'distractor2',\n",
+    "        5:  'distractor3',\n",
+    "        6:  'distractor4',\n",
+    "        7:  'distractor5'\n",
+    "    }\n",
+    "        \n",
     "    @classmethod\n",
     "    def get_pure_tone(cls, freq, duration, sample_rate=44100):\n",
     "        x = np.linspace(0, duration * freq * 2*np.pi, int(duration*sample_rate), dtype=np.float32)\n",
@@ -107,7 +119,7 @@
     "        return sounds\n",
     "        \n",
     "    @classmethod\n",
-    "    def run(cls, selector, status, cfg):\n",
+    "    def run(cls, selector, status, cfg, commutator):\n",
     "        \"\"\"\n",
     "        selector        mp.Value object to set the sound to be played\n",
     "        status          mp.Value object to stop the loop\n",
@@ -116,18 +128,6 @@
     "        import numpy as np\n",
     "        import time\n",
     "        \n",
-    "        commutator = {\n",
-    "            -1: 'noise',\n",
-    "            0:  'silence',\n",
-    "            1:  'background',\n",
-    "            2:  'target',\n",
-    "            3:  'distractor1',\n",
-    "            4:  'distractor2',\n",
-    "            5:  'distractor3',\n",
-    "            6:  'distractor4',\n",
-    "            7:  'distractor5'\n",
-    "        }\n",
-    "        \n",
     "        sounds = cls.get_tone_stack(cfg)\n",
     "\n",
     "        sd.default.device = cfg['device']\n",
@@ -999,7 +999,7 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3 (ipykernel)",
+   "display_name": "Python 3",
    "language": "python",
    "name": "python3"
   },
@@ -1013,7 +1013,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.13"
+   "version": "3.8.8"
   }
  },
  "nbformat": 4,

+ 13 - 13
controllers/sound.py

@@ -29,6 +29,18 @@ class SoundController:
         "file_path": "sounds.csv"
     }
     
+    commutator = {
+        -1: 'noise',
+        0:  'silence',
+        1:  'background',
+        2:  'target',
+        3:  'distractor1',
+        4:  'distractor2',
+        5:  'distractor3',
+        6:  'distractor4',
+        7:  'distractor5'
+    }
+        
     @classmethod
     def get_pure_tone(cls, freq, duration, sample_rate=44100):
         x = np.linspace(0, duration * freq * 2*np.pi, int(duration*sample_rate), dtype=np.float32)
@@ -90,7 +102,7 @@ class SoundController:
         return sounds
         
     @classmethod
-    def run(cls, selector, status, cfg):
+    def run(cls, selector, status, cfg, commutator):
         """
         selector        mp.Value object to set the sound to be played
         status          mp.Value object to stop the loop
@@ -99,18 +111,6 @@ class SoundController:
         import numpy as np
         import time
         
-        commutator = {
-            -1: 'noise',
-            0:  'silence',
-            1:  'background',
-            2:  'target',
-            3:  'distractor1',
-            4:  'distractor2',
-            5:  'distractor3',
-            6:  'distractor4',
-            7:  'distractor5'
-        }
-        
         sounds = cls.get_tone_stack(cfg)
 
         sd.default.device = cfg['device']

+ 4 - 4
controllers/video.ipynb

@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 2,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -18,7 +18,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -26,7 +26,7 @@
     "    # precise timing https://stackoverflow.com/questions/42565297/precise-loop-timing-in-python\n",
     "    \n",
     "    default_cfg = {\n",
-    "        'fps': 20,\n",
+    "        'fps': 30,\n",
     "        'file_path': 'test_video.avi',\n",
     "    }\n",
     "    \n",
@@ -65,7 +65,7 @@
     "                    continue  # TODO sleep here?\n",
     "\n",
     "                #frame = self.video_stream.read()\n",
-    "                frame = self.video_stream.frame_with_infos\n",
+    "                frame = getattr(self.video_stream, self.cfg['frame_attr_name'])\n",
     "                if frame is not None:\n",
     "                    self.count()  # count FPS\n",
     "                    t0 = time.time()\n",

File diff suppressed because it is too large
+ 31 - 54
passive.ipynb


+ 66 - 13
profiles/default.json

@@ -10,15 +10,21 @@
     "video": {
         "fps": 30,
         "file_path": "video.avi",
+        "frame_attr_name": "frame_with_infos",
         "save_contours": false,
         "csv_path": "video.csv"
     },
     "microphones": {
         "record_audio": false,
         "sample_rate": 192000,
-        "device": 58,
+        "device": "ASIO Fireface USB",
         "number_channels": 4,
-        "channel_selectors": [8,9,10,11],
+        "channel_selectors": [
+            8,
+            9,
+            10,
+            11
+        ],
         "file_path": "audio.mat5",
         "csv_path": "microphones.csv"
     },
@@ -45,17 +51,56 @@
         "flip_y": false
     },
     "sound": {
-        "device": [1, 26],
-        "n_channels": 10,
+        "device": "ASIO Fireface USB",
+        "n_channels": 16,
         "sounds": {
-            "noise": {"amp": 0.2, "channels": [6, 8]},
-            "background": {"freq": 660, "amp": 0.05, "duration": 0.05, "harmonics": true, "channels": [1, 8]},
-            "target": {"freq": 660, "amp": 0.1, "duration": 0.05, "harmonics": true, "channels": [2, 8]}, 
-            "distractor1": {"freq": 660, "amp": 0.05, "duration": 0.05, "harmonics": true, "channels": [3, 8], "enabled": true},
-            "distractor2": {"freq": 660, "amp": 0.1, "duration": 0.05, "harmonics": true, "channels": [2, 8], "enabled": false}
+            "noise": {
+                "amp": 0.2,
+                "channels": [
+                    6
+                ]
+            },
+            "background": {
+                "freq": 660,
+                "amp": 0.05,
+                "duration": 0.05,
+                "harmonics": true,
+                "channels": [
+                    5
+                ]
+            },
+            "target": {
+                "freq": 660,
+                "amp": 0.1,
+                "duration": 0.05,
+                "harmonics": true,
+                "channels": [
+                    4
+                ]
+            },
+            "distractor1": {
+                "freq": 660,
+                "amp": 0.05,
+                "duration": 0.05,
+                "harmonics": true,
+                "channels": [
+                    5
+                ],
+                "enabled": true
+            },
+            "distractor2": {
+                "freq": 660,
+                "amp": 0.1,
+                "duration": 0.05,
+                "harmonics": true,
+                "channels": [
+                    4
+                ],
+                "enabled": false
+            }
         },
         "pulse_duration": 0.05,
-        "sample_rate": 44100,
+        "sample_rate": 192000,
         "latency": 0.25,
         "volume": 0.7,
         "roving": 5.0,
@@ -73,9 +118,17 @@
         "experiment_type": "hippoSIT",
         "MCSArduinoPort": "COM10",
         "file_path": "events.csv",
-        "light_events": [9600, 92400],
+        "light_events": [
+            9600,
+            92400
+        ],
         "phi_max": 45,
-        "timepoints": [9600, 91200, 91800, 92400],
+        "timepoints": [
+            9600,
+            91200,
+            91800,
+            92400
+        ],
         "iti_distance": 2.0,
         "iti_duration": 20,
         "punishment_duration": 10,
@@ -83,4 +136,4 @@
         "distractor_fail": false,
         "enable_motors": false
     }
-}
+}