lif.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. # -*- coding: utf-8 -*-
  2. """
  3. Copyright © 2014 German Neuroinformatics Node (G-Node)
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted under the terms of the BSD License. See
  7. LICENSE file in the root of the Project.
  8. Author: Jan Grewe <jan.grewe@g-node.org>
  9. """
  10. import numpy as np
  11. class lif:
  12. def __init__(self, stepsize=0.0001, offset=1.6, tau_m=0.025, tau_a=0.02, da=0.0, D=3.5):
  13. self.stepsize = stepsize # simulation stepsize [s]
  14. self.offset = offset # offset curent [nA]
  15. self.tau_m = tau_m # membrane time_constant [s]
  16. self.tau_a = tau_a # adaptation time_constant [s]
  17. self.da = da # increment in adaptation current [nA]
  18. self.D = D # noise intensity
  19. self.v_threshold = 1.0 # spiking threshold
  20. self.v_reset = 0.0 # reset voltage after spiking
  21. self.i_a = 0.0 # current adaptation current
  22. self.v = self.v_reset # current membrane voltage
  23. self.t = 0.0 # current time [s]
  24. self.membrane_voltage = []
  25. self.spike_times = []
  26. def _reset(self):
  27. self.i_a = 0.0
  28. self.v = self.v_reset
  29. self.t = 0.0
  30. self.membrane_voltage = []
  31. self.spike_times = []
  32. def _lif(self, stimulus, noise):
  33. """
  34. euler solution of the membrane equation with adaptation current and noise
  35. """
  36. self.i_a -= self.i_a - self.stepsize/self.tau_a * (self.i_a)
  37. self.v += self.stepsize * ( -self.v + stimulus + noise + self.offset - self.i_a)/self.tau_m;
  38. self.membrane_voltage.append(self.v)
  39. def _next(self, stimulus):
  40. """
  41. working horse which delegates to the euler and gets the spike times
  42. """
  43. noise = self.D * (float(np.random.randn() % 10000) - 5000.0)/10000
  44. self._lif(stimulus, noise)
  45. self.t += self.stepsize
  46. if self.v > self.v_threshold and len(self.membrane_voltage) > 1:
  47. self.v = self.v_reset
  48. self.membrane_voltage[len(self.membrane_voltage)-1] = 2.0
  49. self.spike_times.append(self.t)
  50. self.i_a += self.da;
  51. def run_const_stim(self, steps, stimulus):
  52. """
  53. lif simulation with constant stimulus.
  54. """
  55. self._reset()
  56. for i in range(steps):
  57. self._next(stimulus);
  58. time = np.arange(len(self.membrane_voltage))*self.stepsize
  59. return time, np.array(self.membrane_voltage), np.array(self.spike_times)
  60. def run_stimulus(self, stimulus):
  61. """
  62. lif simulation with a predefined stimulus trace.
  63. """
  64. self._reset()
  65. for s in stimulus:
  66. self._next(s);
  67. time = np.arange(len(self.membrane_voltage))*self.stepsize
  68. return time, np.array(self.membrane_voltage), np.array(self.spike_times)
  69. def __str__(self):
  70. out = '\n'.join(["stepsize: \t" + str(self.stepsize),
  71. "offset:\t\t" + str(self.offset),
  72. "tau_m:\t\t" + str(self.tau_m),
  73. "tau_a:\t\t" + str(self.tau_a),
  74. "da:\t\t" + str(self.da),
  75. "D:\t\t" + str(self.D),
  76. "v_threshold:\t" + str(self.v_threshold),
  77. "v_reset:\t" + str(self.v_reset)])
  78. return out
  79. def __repr__(self):
  80. return self.__str__()