{
 "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.55037 s (4%) simulated in 10s, estimated 3m 28s remaining.\n",
      "1.12206 s (9%) simulated in 20s, estimated 3m 14s remaining.\n",
      "1.65902 s (13%) simulated in 30s, estimated 3m 7s remaining.\n",
      "2.18387 s (18%) simulated in 40s, estimated 3m 0s remaining.\n",
      "2.70014 s (22%) simulated in 50s, estimated 2m 52s remaining.\n",
      "3.21276 s (26%) simulated in 1m 0s, estimated 2m 44s remaining.\n",
      "3.7235 s (31%) simulated in 1m 10s, estimated 2m 36s remaining.\n",
      "4.2211 s (35%) simulated in 1m 20s, estimated 2m 27s remaining.\n",
      "4.73678 s (39%) simulated in 1m 30s, estimated 2m 18s remaining.\n",
      "5.24956 s (43%) simulated in 1m 40s, estimated 2m 9s remaining.\n",
      "5.76513 s (48%) simulated in 1m 50s, estimated 1m 59s remaining.\n",
      "6.26639 s (52%) simulated in 2m 0s, estimated 1m 50s remaining.\n",
      "6.78077 s (56%) simulated in 2m 10s, estimated 1m 40s remaining.\n",
      "7.29337 s (60%) simulated in 2m 20s, estimated 1m 30s remaining.\n",
      "7.80479 s (65%) simulated in 2m 30s, estimated 1m 21s remaining.\n",
      "8.31249 s (69%) simulated in 2m 40s, estimated 1m 11s remaining.\n",
      "8.82273 s (73%) simulated in 2m 50s, estimated 1m 1s remaining.\n",
      "9.33258 s (77%) simulated in 3m 0s, estimated 51s remaining.\n",
      "9.84619 s (82%) simulated in 3m 10s, estimated 42s remaining.\n",
      "10.35697 s (86%) simulated in 3m 20s, estimated 32s remaining.\n",
      "10.8606 s (90%) simulated in 3m 30s, estimated 22s remaining.\n",
      "11.37014 s (94%) simulated in 3m 40s, estimated 12s remaining.\n",
      "11.87595 s (98%) simulated in 3m 50s, estimated 2s remaining.\n",
      "12. s (100%) simulated in 3m 52s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.collections.EventCollection at 0x1d9a0baa7f0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a0bc0d30>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a0bcbe20>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a126f130>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a127d670>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a128baf0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1298d60>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a12a4fd0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a12b8280>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a12c58b0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a12d2d60>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a12e5280>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a12f37c0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1300970>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a130cca0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a131e160>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a132e6a0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a133aa90>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1349e50>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13592b0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1368730>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1375760>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1383a30>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a138ec40>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13a20a0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13af430>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13bc7c0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13caca0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13d9ee0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13e9430>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a13f7820>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1403c70>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1418100>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1424550>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1433700>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a143ea30>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a144dc10>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a145af10>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a146c430>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1478640>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1487940>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1495c40>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14a6070>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14b2460>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14c37f0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14ceca0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14e11c0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14ed5e0>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a14fd910>,\n",
       " <matplotlib.collections.EventCollection at 0x1d9a1509d90>]"
      ]
     },
     "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\", 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
}