{
 "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*2 * nS, LOW: 0.25 * nS, OFF: 0 * nS}\n",
    "    INHIBITORY_NOISE_VARIANCE = {HIGH: 1.25*2 * 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.58272 s (4%) simulated in 10s, estimated 3m 16s remaining.\n",
      "1.14927 s (9%) simulated in 20s, estimated 3m 9s remaining.\n",
      "1.67399 s (13%) simulated in 30s, estimated 3m 5s remaining.\n",
      "2.19125 s (18%) simulated in 40s, estimated 2m 59s remaining.\n",
      "2.71573 s (22%) simulated in 50s, estimated 2m 51s remaining.\n",
      "3.24193 s (27%) simulated in 1m 0s, estimated 2m 42s remaining.\n",
      "3.77003 s (31%) simulated in 1m 10s, estimated 2m 33s remaining.\n",
      "4.29039 s (35%) simulated in 1m 20s, estimated 2m 24s remaining.\n",
      "4.78492 s (39%) simulated in 1m 30s, estimated 2m 16s remaining.\n",
      "5.29911 s (44%) simulated in 1m 40s, estimated 2m 6s remaining.\n",
      "5.82855 s (48%) simulated in 1m 50s, estimated 1m 56s remaining.\n",
      "6.35737 s (52%) simulated in 2m 0s, estimated 1m 47s remaining.\n",
      "6.88508 s (57%) simulated in 2m 10s, estimated 1m 37s remaining.\n",
      "7.41467 s (61%) simulated in 2m 20s, estimated 1m 27s remaining.\n",
      "7.94274 s (66%) simulated in 2m 30s, estimated 1m 17s remaining.\n",
      "8.45976 s (70%) simulated in 2m 40s, estimated 1m 7s remaining.\n",
      "8.98715 s (74%) simulated in 2m 50s, estimated 57s remaining.\n",
      "9.51 s (79%) simulated in 3m 0s, estimated 47s remaining.\n",
      "10.0222 s (83%) simulated in 3m 10s, estimated 38s remaining.\n",
      "10.51679 s (87%) simulated in 3m 20s, estimated 28s remaining.\n",
      "11.03177 s (91%) simulated in 3m 30s, estimated 18s remaining.\n",
      "11.55222 s (96%) simulated in 3m 40s, estimated 9s remaining.\n",
      "12. s (100%) simulated in 3m 48s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.collections.EventCollection at 0x2af51a433d0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51a567c0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51a64c10>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51a76070>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51a831c0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51a90760>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51a9eb20>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51aace50>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51abd280>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51acc610>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51ad8910>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51ae6dc0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51af72b0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b075e0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b13940>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b20ac0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b2ee20>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b3f1c0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b4b340>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b5b700>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b689d0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b75d60>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b871f0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51b95490>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51ba2760>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51baf9a0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51bbdcd0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51bcf130>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51bdb3a0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51bea670>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51bf7af0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c06f10>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c173a0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c24790>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c31b20>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c40f10>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c53460>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c5f610>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c6c970>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c7bc10>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c8b160>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51c9a610>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51ca7790>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51cb5940>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51cc2e20>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51cd2190>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51ce2520>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51cef7f0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51cfdca0>,\n",
       " <matplotlib.collections.EventCollection at 0x2af51d0e190>]"
      ]
     },
     "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 = 400 * 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\", 65 * 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
}