{
 "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.51387 s (4%) simulated in 10s, estimated 3m 44s remaining.\n",
      "1.06933 s (8%) simulated in 20s, estimated 3m 24s remaining.\n",
      "1.62519 s (13%) simulated in 30s, estimated 3m 12s remaining.\n",
      "2.1851 s (18%) simulated in 40s, estimated 3m 0s remaining.\n",
      "2.68479 s (22%) simulated in 50s, estimated 2m 53s remaining.\n",
      "3.07156 s (25%) simulated in 1m 0s, estimated 2m 54s remaining.\n",
      "3.25615 s (27%) simulated in 1m 10s, estimated 3m 8s remaining.\n",
      "3.43981 s (28%) simulated in 1m 20s, estimated 3m 19s remaining.\n",
      "3.62592 s (30%) simulated in 1m 30s, estimated 3m 28s remaining.\n",
      "3.80914 s (31%) simulated in 1m 40s, estimated 3m 35s remaining.\n",
      "3.9879 s (33%) simulated in 1m 50s, estimated 3m 41s remaining.\n",
      "4.50662 s (37%) simulated in 2m 0s, estimated 3m 20s remaining.\n",
      "5.08451 s (42%) simulated in 2m 10s, estimated 2m 57s remaining.\n",
      "5.64734 s (47%) simulated in 2m 20s, estimated 2m 38s remaining.\n",
      "6.19517 s (51%) simulated in 2m 30s, estimated 2m 21s remaining.\n",
      "6.74133 s (56%) simulated in 2m 40s, estimated 2m 5s remaining.\n",
      "7.28072 s (60%) simulated in 2m 50s, estimated 1m 50s remaining.\n",
      "7.82226 s (65%) simulated in 3m 0s, estimated 1m 36s remaining.\n",
      "8.35873 s (69%) simulated in 3m 10s, estimated 1m 23s remaining.\n",
      "8.85484 s (73%) simulated in 3m 20s, estimated 1m 11s remaining.\n",
      "9.34112 s (77%) simulated in 3m 30s, estimated 1m 0s remaining.\n",
      "9.88237 s (82%) simulated in 3m 40s, estimated 47s remaining.\n",
      "10.41997 s (86%) simulated in 3m 50s, estimated 35s remaining.\n",
      "10.9423 s (91%) simulated in 4m 0s, estimated 23s remaining.\n",
      "11.41773 s (95%) simulated in 4m 10s, estimated 13s remaining.\n",
      "11.91749 s (99%) simulated in 4m 20s, estimated 2s remaining.\n",
      "12. s (100%) simulated in 4m 21s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.collections.EventCollection at 0x19d45bc8bb0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45be77f0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45bfa2b0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c09e80>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c1ba60>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c2d520>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c3ce20>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c4e880>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c62490>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c71f10>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c83be0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45c94580>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45ca4f10>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45cb5a00>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45cc9640>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45cdc1f0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45cebb80>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45cfc880>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d0d250>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d1ec70>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d309a0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d43460>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d50e80>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d63790>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d751f0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d85e20>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45d96880>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45da94f0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45dbc130>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45dcaca0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45ddd8e0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45df0580>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e031f0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e11dc0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e229d0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e376a0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e4a070>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e58c70>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e6a760>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e7c220>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e8bbe0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45e9d760>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45eb12b0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45ebee20>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45ed19a0>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45ee4370>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45ef7130>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45f05d90>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45f18940>,\n",
       " <matplotlib.collections.EventCollection at 0x19d45f2a2b0>]"
      ]
     },
     "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 = 100 * 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
}