{
 "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.41653 s (3%) simulated in 10s, estimated 4m 38s remaining.\n",
      "0.81049 s (6%) simulated in 20s, estimated 4m 36s remaining.\n",
      "1.15915 s (9%) simulated in 30s, estimated 4m 41s remaining.\n",
      "1.48118 s (12%) simulated in 40s, estimated 4m 44s remaining.\n",
      "1.78162 s (14%) simulated in 50s, estimated 4m 47s remaining.\n",
      "2.12197 s (17%) simulated in 1m 0s, estimated 4m 39s remaining.\n",
      "2.49113 s (20%) simulated in 1m 10s, estimated 4m 27s remaining.\n",
      "2.86309 s (23%) simulated in 1m 20s, estimated 4m 15s remaining.\n",
      "3.23022 s (26%) simulated in 1m 30s, estimated 4m 4s remaining.\n",
      "3.58474 s (29%) simulated in 1m 40s, estimated 3m 55s remaining.\n",
      "3.91757 s (32%) simulated in 1m 50s, estimated 3m 47s remaining.\n",
      "4.27537 s (35%) simulated in 2m 0s, estimated 3m 37s remaining.\n",
      "4.61378 s (38%) simulated in 2m 10s, estimated 3m 28s remaining.\n",
      "4.96864 s (41%) simulated in 2m 20s, estimated 3m 18s remaining.\n",
      "5.16882 s (43%) simulated in 2m 30s, estimated 3m 18s remaining.\n",
      "5.43911 s (45%) simulated in 2m 40s, estimated 3m 13s remaining.\n",
      "5.79125 s (48%) simulated in 2m 50s, estimated 3m 2s remaining.\n",
      "6.07186 s (50%) simulated in 3m 0s, estimated 2m 56s remaining.\n",
      "6.43009 s (53%) simulated in 3m 10s, estimated 2m 45s remaining.\n",
      "6.80086 s (56%) simulated in 3m 20s, estimated 2m 33s remaining.\n",
      "7.16667 s (59%) simulated in 3m 30s, estimated 2m 22s remaining.\n",
      "7.51557 s (62%) simulated in 3m 40s, estimated 2m 11s remaining.\n",
      "7.85826 s (65%) simulated in 3m 50s, estimated 2m 1s remaining.\n",
      "8.21375 s (68%) simulated in 4m 0s, estimated 1m 51s remaining.\n",
      "8.55005 s (71%) simulated in 4m 10s, estimated 1m 41s remaining.\n",
      "8.88856 s (74%) simulated in 4m 20s, estimated 1m 31s remaining.\n",
      "9.24984 s (77%) simulated in 4m 30s, estimated 1m 20s remaining.\n",
      "9.58008 s (79%) simulated in 4m 40s, estimated 1m 11s remaining.\n",
      "9.90759 s (82%) simulated in 4m 50s, estimated 1m 1s remaining.\n",
      "10.26161 s (85%) simulated in 5m 0s, estimated 51s remaining.\n",
      "10.61882 s (88%) simulated in 5m 10s, estimated 40s remaining.\n",
      "10.99196 s (91%) simulated in 5m 20s, estimated 29s remaining.\n",
      "11.34692 s (94%) simulated in 5m 30s, estimated 19s remaining.\n",
      "11.70678 s (97%) simulated in 5m 40s, estimated 9s remaining.\n",
      "12. s (100%) simulated in 5m 48s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.collections.EventCollection at 0x17008cbfb50>,\n",
       " <matplotlib.collections.EventCollection at 0x1700936bd60>,\n",
       " <matplotlib.collections.EventCollection at 0x17009386070>,\n",
       " <matplotlib.collections.EventCollection at 0x17009397430>,\n",
       " <matplotlib.collections.EventCollection at 0x170093aa730>,\n",
       " <matplotlib.collections.EventCollection at 0x170093bfa30>,\n",
       " <matplotlib.collections.EventCollection at 0x170093d2e50>,\n",
       " <matplotlib.collections.EventCollection at 0x170093e93a0>,\n",
       " <matplotlib.collections.EventCollection at 0x170093fd700>,\n",
       " <matplotlib.collections.EventCollection at 0x17009412ac0>,\n",
       " <matplotlib.collections.EventCollection at 0x17009424eb0>,\n",
       " <matplotlib.collections.EventCollection at 0x17009437fd0>,\n",
       " <matplotlib.collections.EventCollection at 0x17009450220>,\n",
       " <matplotlib.collections.EventCollection at 0x17009464730>,\n",
       " <matplotlib.collections.EventCollection at 0x170094779d0>,\n",
       " <matplotlib.collections.EventCollection at 0x1700948abe0>,\n",
       " <matplotlib.collections.EventCollection at 0x170094a3100>,\n",
       " <matplotlib.collections.EventCollection at 0x170094b55b0>,\n",
       " <matplotlib.collections.EventCollection at 0x170094c8790>,\n",
       " <matplotlib.collections.EventCollection at 0x170094dd9a0>,\n",
       " <matplotlib.collections.EventCollection at 0x170094f0d90>,\n",
       " <matplotlib.collections.EventCollection at 0x17009508160>,\n",
       " <matplotlib.collections.EventCollection at 0x1700951b490>,\n",
       " <matplotlib.collections.EventCollection at 0x1700952f790>,\n",
       " <matplotlib.collections.EventCollection at 0x17009543b20>,\n",
       " <matplotlib.collections.EventCollection at 0x17009557f70>,\n",
       " <matplotlib.collections.EventCollection at 0x1700956e1f0>,\n",
       " <matplotlib.collections.EventCollection at 0x17009580430>,\n",
       " <matplotlib.collections.EventCollection at 0x170095946a0>,\n",
       " <matplotlib.collections.EventCollection at 0x170095a88b0>,\n",
       " <matplotlib.collections.EventCollection at 0x170095bc9a0>,\n",
       " <matplotlib.collections.EventCollection at 0x170095ced90>,\n",
       " <matplotlib.collections.EventCollection at 0x170095e81c0>,\n",
       " <matplotlib.collections.EventCollection at 0x170095fa4c0>,\n",
       " <matplotlib.collections.EventCollection at 0x1700960d850>,\n",
       " <matplotlib.collections.EventCollection at 0x17009621cd0>,\n",
       " <matplotlib.collections.EventCollection at 0x1700963a160>,\n",
       " <matplotlib.collections.EventCollection at 0x1700964c2e0>,\n",
       " <matplotlib.collections.EventCollection at 0x17009660820>,\n",
       " <matplotlib.collections.EventCollection at 0x17009674b20>,\n",
       " <matplotlib.collections.EventCollection at 0x1700968c0a0>,\n",
       " <matplotlib.collections.EventCollection at 0x170096a0340>,\n",
       " <matplotlib.collections.EventCollection at 0x170096b3610>,\n",
       " <matplotlib.collections.EventCollection at 0x170096c6a60>,\n",
       " <matplotlib.collections.EventCollection at 0x170096d9eb0>,\n",
       " <matplotlib.collections.EventCollection at 0x170096f21c0>,\n",
       " <matplotlib.collections.EventCollection at 0x17009705310>,\n",
       " <matplotlib.collections.EventCollection at 0x170097187c0>,\n",
       " <matplotlib.collections.EventCollection at 0x1700972dc10>,\n",
       " <matplotlib.collections.EventCollection at 0x17009741f10>]"
      ]
     },
     "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\", 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
}