{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0b85a598",
   "metadata": {},
   "outputs": [],
   "source": [
    "from brian2 import *\n",
    "\n",
    "from adex_sine import *\n",
    "\n",
    "defaultclock.dt = 10 * us\n",
    "\n",
    "\n",
    "class Model:\n",
    "    # Model type flags\n",
    "    SINE = 0\n",
    "    EXP2SYN = 1\n",
    "\n",
    "    # Noise flags\n",
    "    HIGH = 0\n",
    "    LOW = 1\n",
    "    OFF = -1\n",
    "\n",
    "    # Noise parameters\n",
    "    EXCITATORY_NOISE_VARIANCE = {HIGH: 0.5*3 * nS, LOW: 0.25 * nS, OFF: 0 * nS}\n",
    "    INHIBITORY_NOISE_VARIANCE = {HIGH: 1.25*3 * nS, LOW: 0.625 * nS, OFF: 0 * nS}\n",
    "\n",
    "    # Noise mean conductance\n",
    "    EXCITATORY_CONDUCTANCE = 1 * nS\n",
    "    INHIBITORY_CONDUCTANCE = 4 * nS\n",
    "\n",
    "    DEFAULT_PARAMETERS = {\n",
    "        \"sigma_flux\" : 6.75*pA,     \n",
    "        \"c\": 85 * pF,\n",
    "        \"tau_w\": 18 * ms,\n",
    "        \"b\": 0.25 * nA,\n",
    "        \"a\": 1.3 * nS,\n",
    "        \"v_T\": -45 * mV,\n",
    "        \"v_thresh\": 0 * mV,\n",
    "        \"DeltaT\": 0.2 * mV,\n",
    "        # EQUILIBRIUM POTENTIAL\n",
    "        \"e_l\": -65 * mV,\n",
    "        \"e_ex\": 0 * mV,\n",
    "        \"e_in\": -70 * mV,\n",
    "        # CONDUCTANCES\n",
    "        \"g_l\": 3 * nS,\n",
    "        \"mu_ex\": 0 * nS,\n",
    "        \"mu_in\": 0 * nS,\n",
    "        # EXCITATORY NOISE\n",
    "        \"sigma_ex\": 0 * nS,\n",
    "        \"tau_noise_ex\": 3 * ms,\n",
    "        # INHIBITORY NOISE\n",
    "        \"sigma_in\": 0 * nS,\n",
    "        \"tau_noise_in\": 10 * ms,\n",
    "        # SINE INPUT\n",
    "        \"f\": 100 * Hz,\n",
    "        \"A\": 0 * pA,\n",
    "        \"i_injected\": 0 * pA,\n",
    "        \"v_reset\": -70 * mV,\n",
    "        # m current\n",
    "        \"g_adapt\": 10 * nS,\n",
    "        \"e_k\": -90*mV,\n",
    "        \"beta_z\": -35*mV,\n",
    "        \"gamma_z\": 4*mV,     #5\n",
    "        \"tau_z\": 100*ms,\n",
    "    }\n",
    "\n",
    "    def __init__(\n",
    "        self, n, *, stim=None, noise=None, resistance=None, additional_vars=()\n",
    "    ):\n",
    "        if resistance is None:\n",
    "            raise ValueError(\"Resistance must be specified\")\n",
    "\n",
    "        if noise is None:\n",
    "            raise ValueError(\"Noise must be specified\")\n",
    "\n",
    "        self.stim_type = stim\n",
    "        self._input_resistance = None\n",
    "        self._noise_level = None\n",
    "        self._duration = 0\n",
    "        self.recorded_vars = (\"v\",) + additional_vars\n",
    "\n",
    "        self.neurons = self.set_default(n_neuron=n)\n",
    "        self.set_resistance(resistance)\n",
    "        self.set_noise(noise)\n",
    "\n",
    "        self.spikes = None\n",
    "        self.spiker = None\n",
    "        self.synapses = None\n",
    "        self.inhib_synapses = None\n",
    "        self.smon = None\n",
    "        self.network = None\n",
    "        self.build_network()\n",
    "\n",
    "    def create_model(self):\n",
    "        return ADEX_MODEL, self.DEFAULT_PARAMETERS\n",
    "\n",
    "    def set_default(self, n_neuron):\n",
    "        model, parameters = self.create_model()\n",
    "\n",
    "        neurons = NeuronGroup(\n",
    "            n_neuron,\n",
    "            model=model,\n",
    "            method=\"Euler\",\n",
    "            name=\"neurons\",\n",
    "            threshold=\"v > v_thresh\",\n",
    "            reset=\"v = v_reset; w += b\",\n",
    "        )\n",
    "\n",
    "        for parameter, value in parameters.items():\n",
    "            neurons.__setattr__(parameter, value)\n",
    "\n",
    "        neurons.v = neurons.e_l  # remove most of transient\n",
    "\n",
    "        return neurons\n",
    "\n",
    "    def set_resistance(self, level):\n",
    "        if level == self.LOW:\n",
    "            exc_conductance = self.EXCITATORY_CONDUCTANCE\n",
    "            inhib_conductance = self.INHIBITORY_CONDUCTANCE\n",
    "\n",
    "        else:\n",
    "            exc_conductance = inhib_conductance = 0\n",
    "\n",
    "        self._input_resistance = level\n",
    "        self._set_variable(\"mu_ex\", exc_conductance)\n",
    "        self._set_variable(\"mu_in\", inhib_conductance)\n",
    "\n",
    "    def set_noise(self, level):\n",
    "        if level == self.HIGH or level == self.LOW:\n",
    "            exc_noise = self.EXCITATORY_NOISE_VARIANCE[level]\n",
    "            inhib_noise = self.INHIBITORY_NOISE_VARIANCE[level]\n",
    "\n",
    "        else:\n",
    "            exc_noise = inhib_noise = 0\n",
    "\n",
    "        self._noise_level = level\n",
    "        self._set_variable(\"sigma_ex\", exc_noise)\n",
    "        self._set_variable(\"sigma_in\", inhib_noise)\n",
    "\n",
    "    def set_injected_current(self, amplitude):\n",
    "        self._set_variable(\"i_injected\", amplitude)\n",
    "        self._set_variable(\"A\", 0 * pA)\n",
    "\n",
    "    def set_stimulus_current(self, amplitude):\n",
    "        self._set_variable(\"A\", amplitude)\n",
    "        self._set_variable(\"i_injected\", 0 * pA)\n",
    "\n",
    "    @property\n",
    "    def f(self):\n",
    "        return self.neurons.f\n",
    "\n",
    "    @f.setter\n",
    "    def f(self, new_f):\n",
    "        self._set_variable(\"f\", new_f)  # this will reset smon\n",
    "        if self.stim_type == self.EXP2SYN:\n",
    "            self.spiker.T = 1 / new_f\n",
    "\n",
    "    def run(self, duration, report=\"stdout\"):\n",
    "        self._duration = duration\n",
    "        self.network.run(duration, report=report)\n",
    "\n",
    "    def build_network(self):\n",
    "        self.smon = StateMonitor(\n",
    "            self.neurons, self.recorded_vars, record=True, name=\"smon\"\n",
    "        )\n",
    "        self.spikes = SpikeMonitor(self.neurons, name=\"spikes\")\n",
    "\n",
    "        self.network = Network(self.neurons, self.smon, self.spikes)\n",
    "\n",
    "    def _set_variable(self, name, value):\n",
    "        self.neurons.__setattr__(name, value)\n",
    "        self.reset_recording()\n",
    "\n",
    "    def reset_recording(self):\n",
    "        try:\n",
    "            self.network\n",
    "        except AttributeError:\n",
    "            return  # network not yet initialized\n",
    "\n",
    "        self.network.remove(self.smon, self.spikes)\n",
    "\n",
    "        self.smon = StateMonitor(\n",
    "            self.neurons, self.recorded_vars, record=True, name=\"smon\"\n",
    "        )\n",
    "        self.spikes = SpikeMonitor(self.neurons, name=\"spikes\")\n",
    "\n",
    "        self.network.add(self.smon, self.spikes)\n",
    "\n",
    "    @property\n",
    "    def spike_train(self):\n",
    "        return self.spikes.spike_trains()\n",
    "\n",
    "    @property\n",
    "    def firing_rate(self):\n",
    "        return self.spikes.count / self.duration\n",
    "\n",
    "    @property\n",
    "    def duration(self):\n",
    "        return self._duration\n",
    "\n",
    "    @property\n",
    "    def input_resistance(self):\n",
    "        if self._input_resistance == self.HIGH:\n",
    "            return \"HIGH\"\n",
    "        else:\n",
    "            return \"LOW\"\n",
    "\n",
    "    @property\n",
    "    def noise_level(self):\n",
    "        if self._noise_level == self.HIGH:\n",
    "            return \"HIGH\"\n",
    "        elif self._noise_level == self.LOW:\n",
    "            return \"LOW\"\n",
    "        else:\n",
    "            return \"NO\"\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f\"{self.neurons.N} Neurons with {self.input_resistance} input resistance and {self.noise_level} noise\"\n",
    "\n",
    "    def __str__(self):\n",
    "        return self.__repr__()\n",
    "\n",
    "    def store(self, name):\n",
    "        self.network.store(name)\n",
    "\n",
    "    def restore(self, name):\n",
    "        self.network.restore(name)\n",
    "\n",
    "    @property\n",
    "    def v(self):\n",
    "        return self.smon.v\n",
    "\n",
    "    @property\n",
    "    def t(self):\n",
    "        return self.smon.t\n",
    "\n",
    "    @property\n",
    "    def injected_current(self):\n",
    "        return self.neurons.i_injected\n",
    "\n",
    "    @property\n",
    "    def stimulus_amplitude(self):\n",
    "        return self.neurons.A\n",
    "\n",
    "\n",
    "class CurrentModel(Model):\n",
    "    def __init__(self, **kwargs):\n",
    "        super().__init__(stim=self.SINE, **kwargs)\n",
    "\n",
    "    def create_model(self):\n",
    "        model, parameters = super().create_model()\n",
    "        model += CURRENT_INPUT\n",
    "\n",
    "        return model, parameters\n",
    "\n",
    "\n",
    "class SineModel(CurrentModel):\n",
    "    def create_model(self):\n",
    "        model, parameters = super().create_model()\n",
    "        model += SINE_INPUT\n",
    "\n",
    "        return model, parameters\n",
    "\n",
    "\n",
    "class SawModel(CurrentModel):\n",
    "    def create_model(self):\n",
    "        model, parameters = super().create_model()\n",
    "        model += SAW_INPUT\n",
    "\n",
    "        return model, parameters\n",
    "\n",
    "\n",
    "class SynapticModel(Model):\n",
    "    def __init__(self, **kwargs):\n",
    "        super().__init__(stim=self.EXP2SYN, **kwargs)\n",
    "\n",
    "    SYNAPTIC_PARAMETERS = {\n",
    "        \"tau_input_1\": 0.4 * ms,\n",
    "        \"tau_input_2\": 4 * ms,\n",
    "        \"offset_A\": 1.48793507e-11,\n",
    "        \"offset_B\": -2.66359562e-08,\n",
    "        \"offset_C\": 1.77538800e-05,\n",
    "        \"offset_D\": -8.05925810e-04,\n",
    "        \"offset_E\": -3.51463644e-02,\n",
    "        \"offset_switch\": 0,\n",
    "    }\n",
    "\n",
    "    def create_model(self):\n",
    "        model, parameters = super().create_model()\n",
    "        model += EXP2SYN_WAVEFORM + SUMMATION_OFFSET\n",
    "        parameters = {**parameters, **self.SYNAPTIC_PARAMETERS}\n",
    "\n",
    "        return model, parameters\n",
    "\n",
    "    def build_network(self):\n",
    "        super().build_network()\n",
    "        self.spiker = NeuronGroup(\n",
    "            self.neurons.N,\n",
    "            \"\"\"T : second (constant)\n",
    "                                     lastspike : second\"\"\",\n",
    "            threshold=\"timestep(t-lastspike, dt)>=timestep(T, dt)\",\n",
    "            reset=\"lastspike=t\",\n",
    "        )\n",
    "        self.spiker.T = 1 / self.neurons.f\n",
    "        self.synapses = Synapses(\n",
    "            self.spiker, self.neurons, on_pre=\"input_aux += 1\"\n",
    "        )  # connect input to neurons\n",
    "        self.synapses.connect(\"i==j\")  # one synapse goes to one neuron\n",
    "\n",
    "        self.network.add(self.spiker, self.synapses)\n",
    "\n",
    "\n",
    "class SynapticCurrentModel(SynapticModel):\n",
    "    def __init__(self, offset=True, **kwargs):\n",
    "        self.offset = 1 if offset else 0\n",
    "        super().__init__(**kwargs)\n",
    "\n",
    "    def create_model(self):\n",
    "        model, parameters = super().create_model()\n",
    "        model += CURRENT_INPUT + SYNAPTIC_INPUT_CURRENT\n",
    "        parameters = {**parameters, **{\"offset_switch\": self.offset}}\n",
    "\n",
    "        return model, parameters\n",
    "\n",
    "\n",
    "class SynapticConductanceModel(SynapticModel):\n",
    "    FLAT = 0\n",
    "    ACTIVE = 1\n",
    "\n",
    "    CONDUCTANCE_PARAMETERS = {\n",
    "        \"A\": 0 * nS,  # overwrite A to be conductance\n",
    "        \"g_i\": 1 * nS,\n",
    "    }\n",
    "\n",
    "    INHIBITION_PARAMETERS = {\n",
    "        \"tau_inhibition_1\": 1 * ms,\n",
    "        \"tau_inhibition_2\": 10 * ms,\n",
    "    }\n",
    "\n",
    "    def __init__(self, offset=ACTIVE, **kwargs):\n",
    "        self.offset = offset\n",
    "        super().__init__(**kwargs)\n",
    "\n",
    "    def create_model(self):\n",
    "        model, parameters = super().create_model()\n",
    "        if self.offset == self.FLAT:\n",
    "            model += CONDUCTANCE_INPUT + SYNAPTIC_CONDUCTANCE_FLAT\n",
    "            parameters = {\n",
    "                **parameters,\n",
    "                **self.SYNAPTIC_PARAMETERS,\n",
    "                **self.CONDUCTANCE_PARAMETERS,\n",
    "                **{\"offset_switch\": 1},\n",
    "            }\n",
    "\n",
    "        elif self.offset == self.ACTIVE:\n",
    "            model += CONDUCTANCE_INPUT + SYNAPTIC_CONDUCTANCE_STIM\n",
    "            parameters = {\n",
    "                **parameters,\n",
    "                **self.SYNAPTIC_PARAMETERS,\n",
    "                **self.CONDUCTANCE_PARAMETERS,\n",
    "                **self.INHIBITION_PARAMETERS,\n",
    "            }\n",
    "\n",
    "        return model, parameters\n",
    "\n",
    "    def build_network(self):\n",
    "        super().build_network()\n",
    "        if self.offset != self.ACTIVE:\n",
    "            return\n",
    "\n",
    "        self.inhib_synapses = Synapses(\n",
    "            self.spiker, self.neurons, on_pre=\"input_inhib_aux += 1\", delay=2 * ms\n",
    "        )  # connect input to neurons\n",
    "        self.inhib_synapses.connect(\"i==j\")  # one synapse goes to one neuron\n",
    "\n",
    "        self.network.add(self.inhib_synapses)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c82769f2",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING    Cannot use Cython, a test compilation failed: Microsoft Visual C++ 14.0 or greater is required. Get it with \"Microsoft C++ Build Tools\": https://visualstudio.microsoft.com/visual-cpp-build-tools/ (DistutilsPlatformError) [brian2.codegen.runtime.cython_rt.cython_rt.failed_compile_test]\n",
      "INFO       Cannot use compiled code, falling back to the numpy code generation target. Note that this will likely be slower than using compiled code. Set the code generation to numpy manually to avoid this message:\n",
      "prefs.codegen.target = \"numpy\" [brian2.devices.device.codegen_fallback]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting simulation at t=0. s for a duration of 12. s\n",
      "0.41954 s (3%) simulated in 10s, estimated 4m 36s remaining.\n",
      "0.85044 s (7%) simulated in 20s, estimated 4m 22s remaining.\n",
      "1.28283 s (10%) simulated in 30s, estimated 4m 11s remaining.\n",
      "1.71302 s (14%) simulated in 40s, estimated 4m 0s remaining.\n",
      "2.11757 s (17%) simulated in 50s, estimated 3m 53s remaining.\n",
      "2.54866 s (21%) simulated in 1m 0s, estimated 3m 43s remaining.\n",
      "2.97738 s (24%) simulated in 1m 10s, estimated 3m 32s remaining.\n",
      "3.38012 s (28%) simulated in 1m 20s, estimated 3m 24s remaining.\n",
      "3.8022 s (31%) simulated in 1m 30s, estimated 3m 14s remaining.\n",
      "4.19263 s (34%) simulated in 1m 40s, estimated 3m 6s remaining.\n",
      "4.62499 s (38%) simulated in 1m 50s, estimated 2m 55s remaining.\n",
      "5.06078 s (42%) simulated in 2m 0s, estimated 2m 45s remaining.\n",
      "5.49463 s (45%) simulated in 2m 10s, estimated 2m 34s remaining.\n",
      "5.93086 s (49%) simulated in 2m 20s, estimated 2m 23s remaining.\n",
      "6.32397 s (52%) simulated in 2m 30s, estimated 2m 15s remaining.\n",
      "6.74177 s (56%) simulated in 2m 40s, estimated 2m 5s remaining.\n",
      "7.10363 s (59%) simulated in 2m 50s, estimated 1m 57s remaining.\n",
      "7.4961 s (62%) simulated in 3m 0s, estimated 1m 48s remaining.\n",
      "7.90949 s (65%) simulated in 3m 10s, estimated 1m 38s remaining.\n",
      "8.34317 s (69%) simulated in 3m 20s, estimated 1m 28s remaining.\n",
      "8.77449 s (73%) simulated in 3m 30s, estimated 1m 17s remaining.\n",
      "9.20855 s (76%) simulated in 3m 40s, estimated 1m 7s remaining.\n",
      "9.61079 s (80%) simulated in 3m 50s, estimated 57s remaining.\n",
      "10.01383 s (83%) simulated in 4m 0s, estimated 48s remaining.\n",
      "10.43715 s (86%) simulated in 4m 10s, estimated 37s remaining.\n",
      "10.85812 s (90%) simulated in 4m 20s, estimated 27s remaining.\n",
      "11.26712 s (93%) simulated in 4m 30s, estimated 18s remaining.\n",
      "11.69942 s (97%) simulated in 4m 40s, estimated 7s remaining.\n",
      "12. s (100%) simulated in 4m 46s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.collections.EventCollection at 0x16a8730aca0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87326f40>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8733d2b0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87353400>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87365550>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87377820>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8738cbe0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a873a1f70>,\n",
       " <matplotlib.collections.EventCollection at 0x16a873b83a0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a873cb5b0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a873de760>,\n",
       " <matplotlib.collections.EventCollection at 0x16a873f2970>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87405b20>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87418b80>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8742cd00>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8743ff10>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87457310>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8746b580>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8747d790>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87491a90>,\n",
       " <matplotlib.collections.EventCollection at 0x16a874a4df0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a874bc070>,\n",
       " <matplotlib.collections.EventCollection at 0x16a874ce3a0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a874e46d0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a874f88e0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8750a8e0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8751da90>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87530f10>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87549340>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8755c760>,\n",
       " <matplotlib.collections.EventCollection at 0x16a875709d0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87584b80>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87596be0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a875a9d30>,\n",
       " <matplotlib.collections.EventCollection at 0x16a875c3070>,\n",
       " <matplotlib.collections.EventCollection at 0x16a875d52e0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a875e8250>,\n",
       " <matplotlib.collections.EventCollection at 0x16a875fc370>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8760e6a0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a876248b0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87636a90>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87648dc0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8765bfd0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a876744f0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a87686520>,\n",
       " <matplotlib.collections.EventCollection at 0x16a8769b6d0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a876af940>,\n",
       " <matplotlib.collections.EventCollection at 0x16a876c2c70>,\n",
       " <matplotlib.collections.EventCollection at 0x16a876d4eb0>,\n",
       " <matplotlib.collections.EventCollection at 0x16a876ed0a0>]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#from models import Model, SynapticConductanceModel\n",
    "from brian2 import *\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "model = SynapticConductanceModel(resistance=Model.LOW, # Model.LOW, Model.HIGH\n",
    "                                 noise=Model.HIGH, n=50, # Model.OFF, Model.LOW, Model,HIGH\n",
    "                                 offset=SynapticConductanceModel.ACTIVE)\n",
    "\n",
    "\n",
    "# model = SineModel(resistance=Model.LOW, # Model.LOW, Model.HIGH\n",
    "#                                   noise=Model.OFF, n=1, # Model.OFF, Model.LOW, Model,HIGH\n",
    "#                                 )\n",
    "\n",
    "\n",
    "model.f = 200 * Hz\n",
    "model.set_stimulus_current(400 * nS) # current should be scaled by 100x for Active Offset so (500nS is actually 5nS)\n",
    "model._set_variable(\"i_injected\", 90 * pA)\n",
    "\n",
    "\n",
    "model.run(12*second)\n",
    "\n",
    "spike_times = [s/ms for s in model.spike_train.values()]\n",
    "\n",
    "plt.eventplot(spike_times)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7f22e21e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#print(spike_times)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "20e3191c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import scipy.io\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "file_path = 'data0.mat'\n",
    "scipy.io.savemat(file_path, {'data0': spike_times[0]})\n",
    "\n",
    "file_path = 'data1.mat'\n",
    "scipy.io.savemat(file_path, {'data1': spike_times[1]})\n",
    "\n",
    "file_path = 'data2.mat'\n",
    "scipy.io.savemat(file_path, {'data2': spike_times[2]})\n",
    "\n",
    "file_path = 'data3.mat'\n",
    "scipy.io.savemat(file_path, {'data3': spike_times[3]})\n",
    "\n",
    "file_path = 'data4.mat'\n",
    "scipy.io.savemat(file_path, {'data4': spike_times[4]})\n",
    "\n",
    "file_path = 'data5.mat'\n",
    "scipy.io.savemat(file_path, {'data5': spike_times[5]})\n",
    "\n",
    "file_path = 'data6.mat'\n",
    "scipy.io.savemat(file_path, {'data6': spike_times[6]})\n",
    "\n",
    "file_path = 'data7.mat'\n",
    "scipy.io.savemat(file_path, {'data7': spike_times[7]})\n",
    "\n",
    "file_path = 'data8.mat'\n",
    "scipy.io.savemat(file_path, {'data8': spike_times[8]})\n",
    "\n",
    "file_path = 'data9.mat'\n",
    "scipy.io.savemat(file_path, {'data9': spike_times[9]})\n",
    "\n",
    "file_path = 'data10.mat'\n",
    "scipy.io.savemat(file_path, {'data10': spike_times[10]})\n",
    "\n",
    "file_path = 'data11.mat'\n",
    "scipy.io.savemat(file_path, {'data11': spike_times[11]})\n",
    "\n",
    "file_path = 'data12.mat'\n",
    "scipy.io.savemat(file_path, {'data12': spike_times[12]})\n",
    "\n",
    "file_path = 'data13.mat'\n",
    "scipy.io.savemat(file_path, {'data13': spike_times[13]})\n",
    "\n",
    "file_path = 'data14.mat'\n",
    "scipy.io.savemat(file_path, {'data14': spike_times[14]})\n",
    "\n",
    "file_path = 'data15.mat'\n",
    "scipy.io.savemat(file_path, {'data15': spike_times[15]})\n",
    "\n",
    "file_path = 'data16.mat'\n",
    "scipy.io.savemat(file_path, {'data16': spike_times[16]})\n",
    "\n",
    "file_path = 'data17.mat'\n",
    "scipy.io.savemat(file_path, {'data17': spike_times[17]})\n",
    "\n",
    "file_path = 'data18.mat'\n",
    "scipy.io.savemat(file_path, {'data18': spike_times[18]})\n",
    "\n",
    "file_path = 'data19.mat'\n",
    "scipy.io.savemat(file_path, {'data19': spike_times[19]})\n",
    "\n",
    "file_path = 'data20.mat'\n",
    "scipy.io.savemat(file_path, {'data20': spike_times[20]})\n",
    "\n",
    "file_path = 'data21.mat'\n",
    "scipy.io.savemat(file_path, {'data21': spike_times[21]})\n",
    "\n",
    "file_path = 'data22.mat'\n",
    "scipy.io.savemat(file_path, {'data22': spike_times[22]})\n",
    "\n",
    "file_path = 'data23.mat'\n",
    "scipy.io.savemat(file_path, {'data23': spike_times[23]})\n",
    "\n",
    "file_path = 'data24.mat'\n",
    "scipy.io.savemat(file_path, {'data24': spike_times[24]})\n",
    "\n",
    "file_path = 'data25.mat'\n",
    "scipy.io.savemat(file_path, {'data25': spike_times[25]})\n",
    "\n",
    "file_path = 'data26.mat'\n",
    "scipy.io.savemat(file_path, {'data26': spike_times[26]})\n",
    "\n",
    "file_path = 'data27.mat'\n",
    "scipy.io.savemat(file_path, {'data27': spike_times[27]})\n",
    "\n",
    "file_path = 'data28.mat'\n",
    "scipy.io.savemat(file_path, {'data28': spike_times[28]})\n",
    "\n",
    "file_path = 'data29.mat'\n",
    "scipy.io.savemat(file_path, {'data29': spike_times[29]})\n",
    "\n",
    "file_path = 'data30.mat'\n",
    "scipy.io.savemat(file_path, {'data30': spike_times[30]})\n",
    "\n",
    "file_path = 'data31.mat'\n",
    "scipy.io.savemat(file_path, {'data31': spike_times[31]})\n",
    "\n",
    "file_path = 'data32.mat'\n",
    "scipy.io.savemat(file_path, {'data32': spike_times[32]})\n",
    "\n",
    "file_path = 'data33.mat'\n",
    "scipy.io.savemat(file_path, {'data33': spike_times[33]})\n",
    "\n",
    "file_path = 'data34.mat'\n",
    "scipy.io.savemat(file_path, {'data34': spike_times[34]})\n",
    "\n",
    "file_path = 'data35.mat'\n",
    "scipy.io.savemat(file_path, {'data35': spike_times[35]})\n",
    "\n",
    "file_path = 'data36.mat'\n",
    "scipy.io.savemat(file_path, {'data36': spike_times[36]})\n",
    "\n",
    "file_path = 'data37.mat'\n",
    "scipy.io.savemat(file_path, {'data37': spike_times[37]})\n",
    "\n",
    "file_path = 'data38.mat'\n",
    "scipy.io.savemat(file_path, {'data38': spike_times[38]})\n",
    "\n",
    "file_path = 'data39.mat'\n",
    "scipy.io.savemat(file_path, {'data39': spike_times[39]})\n",
    "\n",
    "file_path = 'data40.mat'\n",
    "scipy.io.savemat(file_path, {'data40': spike_times[40]})\n",
    "\n",
    "file_path = 'data41.mat'\n",
    "scipy.io.savemat(file_path, {'data41': spike_times[41]})\n",
    "\n",
    "file_path = 'data42.mat'\n",
    "scipy.io.savemat(file_path, {'data42': spike_times[42]})\n",
    "\n",
    "file_path = 'data43.mat'\n",
    "scipy.io.savemat(file_path, {'data43': spike_times[43]})\n",
    "\n",
    "file_path = 'data44.mat'\n",
    "scipy.io.savemat(file_path, {'data44': spike_times[44]})\n",
    "\n",
    "file_path = 'data45.mat'\n",
    "scipy.io.savemat(file_path, {'data45': spike_times[45]})\n",
    "\n",
    "file_path = 'data46.mat'\n",
    "scipy.io.savemat(file_path, {'data46': spike_times[46]})\n",
    "\n",
    "file_path = 'data47.mat'\n",
    "scipy.io.savemat(file_path, {'data47': spike_times[47]})\n",
    "\n",
    "file_path = 'data48.mat'\n",
    "scipy.io.savemat(file_path, {'data48': spike_times[48]})\n",
    "\n",
    "file_path = 'data49.mat'\n",
    "scipy.io.savemat(file_path, {'data49': spike_times[49]})\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d353eff4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}