{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Run spike sorting by property\n\nSometimes you may want to spike sort different electrodes separately. For example your probe can have several channel\ngroups (for example tetrodes) or you might want to spike sort different brain regions separately, In these cases, you\ncan spike sort by property.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\nimport spikeinterface.extractors as se\nimport spikeinterface.sorters as ss"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Sometimes, you might want to sort your data depending on a specific\u00a0property of your recording channels.\n\u00a0\nFor example, when using multiple tetrodes, a good idea is to sort each tetrode separately. In this case, channels\nbelonging to the same tetrode will be in the same 'group'. Alternatively, for long silicon probes, such as\nNeuropixels, you could sort different areas separately, for example hippocampus and thalamus.\n\u00a0\nAll this can be done by sorting by 'property'. Properties can be loaded to the recording channels either manually\n(using the :code:`set_channel_property` method), or by using a probe file. In this example we will create a 16 channel\nrecording and split it in four channel groups (tetrodes).\n\nLet's create a toy example with 16 channels (the :code:`dumpable=True` dumps the extractors to a file, which is\nrequired for parallel sorting):\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "recording, sorting_true = se.toy_example(duration=[10.], num_segments=1, num_channels=16)\n# make dumpable\nrecording= recording.save()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Initially all channel are in the same group.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "print(recording.get_channel_groups())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Lets now change the probe mapping and assign a 4 tetrodes to this recording.\nfor this we will use the `probeinterface` module and create a `ProbeGroup` containing for dummy tetrode.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from probeinterface import generate_tetrode, ProbeGroup\n\nprobegroup = ProbeGroup()\nfor i in range(4):\n    tetrode = generate_tetrode()\n    tetrode.set_device_channel_indices(np.arange(4) + i * 4)\n    probegroup.add_probe(tetrode)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "now our new recording contain 4 groups\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "recording_4_tetrodes = recording.set_probegroup(probegroup, group_mode='by_probe')\n\n# get group\nprint(recording_4_tetrodes.get_channel_groups())\n# similar to this\nprint(recording_4_tetrodes.get_property('group'))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "this \"group\" property can be use to split our new recording into 4 recording\nwe get a list of 4 ChannelSliceRecording (ex \"sub-recording\")\nThis is done without any copy, each ChannelSliceRecording is a view of the parent recording\n Note that here we use 'group' for splitting but it could be done on any property.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "recordings = recording_4_tetrodes.split_by(property='group')\nprint(recordings)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can also get a dict instead of the list which is easier to handle group keys.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "recordings = recording_4_tetrodes.split_by(property='group', outputs='dict')\nprint(recordings)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can now use the `run_sorters()` function instead of the `run_sorter()`.\nThis function can run several sorters on several recording with different parallel engines.\n here we use engine 'loop' but we could use also  'joblib' or 'dask' for multi process or multi node computing.\n have a look to the documentation of this function that handle many cases.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "sorter_list = ['tridesclous']\nworking_folder = 'sorter_outputs'\nresults = ss.run_sorters(sorter_list, recordings, working_folder,\n            engine='loop', with_output=True, mode_if_folder_exists='overwrite')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "the output is a dict with all combinations of (group, sorter_name)\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from pprint import pprint\npprint(results)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "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.13"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}