library.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. import numpy as np
  2. import cv2
  3. from scipy import interpolate
  4. def SimpleLowpass(signal, dt, RC):
  5. Nsamples = signal.size
  6. output = np.zeros(Nsamples)
  7. s = dt / (RC + dt)
  8. output[0] = s*signal[0]
  9. for i in range(1,Nsamples):
  10. output[i] = output[i-1] + s * (signal[i] - output[i-1])
  11. return output
  12. def SimpleHighpass(signal, dt, RC):
  13. Nsamples = signal.size
  14. output = np.zeros(Nsamples)
  15. s = dt / (RC + dt)
  16. output[0] = s*signal[0]
  17. for i in range(1,Nsamples):
  18. output[i] = output[i-1] + s * (signal[i] - output[i-1])
  19. return signal - output
  20. def LuminanceGainControl(signal, dt, RC):
  21. Nsamples = signal.size
  22. output = np.zeros(Nsamples) # Initialization of output
  23. helper = np.zeros(Nsamples) # Internal helper variable, i.e. LP filtered output
  24. s = dt / (RC + dt)
  25. output[0] = 0
  26. helper[0] = 1
  27. for i in range(1,Nsamples):
  28. helper[i] = helper[i-1] + s * (output[i-1] - helper[i-1]) # this LP filters the last output to get new helper
  29. output[i] = signal[i] / helper[i]
  30. return output
  31. def rec(x):
  32. return x*(x>0)
  33. def nlplus(x, c1):
  34. return (1 + rec(x)/c1)**2
  35. def nlc(x, q0, q1, c2):
  36. return q0 + q1*x/(c2 + x)
  37. def nltan(x, k):
  38. return (2/np.pi)*np.arctan(k*x)
  39. def ContrastGainControlLoop(signal, dt, RCplus, RCA, c1):
  40. Nsamples = signal.size
  41. output = np.zeros(Nsamples)
  42. cA = np.zeros(Nsamples)
  43. d = np.ones(Nsamples)
  44. output[0] = 0
  45. d[0] = 1
  46. for i in range(1,Nsamples):
  47. # First, calculate the HP filtered input with TC RC
  48. s = dt / (RCA + dt)
  49. cA[i] = cA[i-1] + s * (signal[i] - cA[i-1])
  50. # In Contrast gain, divisive normalization for output
  51. s = dt / (RCplus + dt)
  52. d[i] = d[i-1] + s * (output[i-1] - d[i-1])
  53. output[i] = (signal[i] - cA[i]) / nlplus(d[i], c1)
  54. return output
  55. def delay_signal(signal, dt, delay):
  56. """
  57. This delays a signal by "delay"
  58. Internally, the signal is
  59. (1) resampled at rate RESAMPLED: int (default 100) with cubic spline
  60. (2) shifted by the time DELAY
  61. (3) resampled at original sampling
  62. """
  63. RESAMPLED = 100
  64. times = np.arange(0, len(signal)*dt, dt)
  65. interpolationfunction = interpolate.interp1d(times, signal, kind='cubic')
  66. times_fine = np.arange(0, np.max(times), dt/RESAMPLED)
  67. signal_fine = interpolationfunction(times_fine)
  68. new_idx = int( delay / (dt/RESAMPLED) )
  69. delayed_signal = np.roll(signal_fine, new_idx)
  70. delayed_signal[0:new_idx] = 0
  71. interpolationfunction2 = interpolate.interp1d(times_fine, delayed_signal, kind='cubic', fill_value="extrapolate")
  72. new_signal = interpolationfunction2(times)
  73. return new_signal
  74. def receptiveField(x, y, xoff, yoff, rcenter):
  75. center = np.exp( -((x-xoff)**2 + (y-yoff)**2) / (2*rcenter*rcenter)) /(2*np.pi*rcenter*rcenter)
  76. return center
  77. def get_RF(xoff, yoff, center):
  78. X = np.linspace(-128, 128, 256)
  79. Y = np.linspace(-128, 128, 256)
  80. x, y = np.meshgrid(X,Y)
  81. RF = receptiveField(x, y, xoff, yoff, center)
  82. return RF
  83. def filter_video_PC(filename, maxframe, fitparameters):
  84. xoff = fitparameters['xoff']
  85. yoff = fitparameters['yoff']
  86. rcenterM = fitparameters['rcenterM']
  87. rcenterL = fitparameters['rcenterL']
  88. RFM = get_RF(xoff, yoff, rcenterM)
  89. RFL = get_RF(xoff, yoff, rcenterL)
  90. vidcap = cv2.VideoCapture(filename)
  91. counter = 0
  92. success = True
  93. ratesM = []
  94. ratesL = []
  95. while success and (counter < 9750):
  96. success, image = vidcap.read()
  97. scone, mcone, lcone = image_to_cone(image)
  98. rateM = np.sum(mcone*RFM)
  99. rateL = np.sum(lcone*RFL)
  100. ratesM.append( rateM )
  101. ratesL.append( rateL )
  102. counter += 1
  103. return np.array(ratesM), np.array(ratesL)
  104. def filter_video_MC(filename, maxframe, fitparameters):
  105. xoff = fitparameters['xoff']
  106. yoff = fitparameters['yoff']
  107. rcenter = fitparameters['rcenter']
  108. rsurr = fitparameters['rsurr']
  109. RFcenter = get_RF(xoff, yoff, rcenter)
  110. RFsurround = get_RF(xoff, yoff, rsurr)
  111. vidcap = cv2.VideoCapture(filename)
  112. counter = 0
  113. success = True
  114. rates_center = []
  115. rates_surround = []
  116. while success and (counter < maxframe):
  117. success, image = vidcap.read()
  118. scone, mcone, lcone = image_to_cone(image)
  119. luminance_frame = mcone + lcone
  120. rate_center = np.sum(luminance_frame*RFcenter)
  121. rates_center.append(rate_center)
  122. rate_surround = np.sum(luminance_frame*RFsurround)
  123. rates_surround.append(rate_surround)
  124. counter += 1
  125. return np.array(rates_center), np.array(rates_surround)
  126. def filter_video_BO(filename, maxframe, fitparameters):
  127. xoff = fitparameters['xoff']
  128. yoff = fitparameters['yoff']
  129. rcenterY = fitparameters['rcenterY']
  130. rcenterB = fitparameters['rcenterB']
  131. RFY = get_RF(xoff, yoff, rcenterY)
  132. RFB = get_RF(xoff, yoff, rcenterB)
  133. vidcap = cv2.VideoCapture(filename)
  134. counter = 0
  135. success = True
  136. ratesL = []
  137. ratesM = []
  138. ratesB = []
  139. while success and (counter < maxframe):
  140. success, image = vidcap.read()
  141. scone, mcone, lcone = image_to_cone(image)
  142. rateL = np.sum(lcone*RFY)
  143. rateM = np.sum(mcone*RFY)
  144. rateB = np.sum(scone*RFB)
  145. ratesL.append( rateL )
  146. ratesM.append( rateM )
  147. ratesB.append( rateB )
  148. counter += 1
  149. return np.array(ratesL), np.array(ratesM), np.array(ratesB)
  150. def image_to_cone(image):
  151. """
  152. Spectral fits and parameters for this display, measured by Barry and Hans
  153. Image has to be BGR!
  154. """
  155. #Raw RGB values
  156. im_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  157. red = np.double(im_rgb[:,:,0])
  158. green = np.double(im_rgb[:,:,1])
  159. blue = np.double(im_rgb[:,:,2])
  160. #Hans' gamma correction
  161. rgamma = 0.01451 + 0.9855*((1.0*red/256)**2.3122)
  162. ggamma = 0.005123 + 0.9949*((1.0*green/256)**2.2752)
  163. bgamma = 0.02612 + 0.9739*((1.0*blue/256)**2.2818)
  164. lcone = 1.0*(2.74*rgamma + 3.4*ggamma + 1.34*bgamma)
  165. mcone = 1.21*(1.06*rgamma + 3.58*ggamma + 2.07*bgamma)
  166. scone = 0.212*rgamma + 8.28*ggamma + 285*bgamma
  167. return scone, mcone, lcone
  168. def get_MC_response(rates_center, rates_surround, fitparameters, type):
  169. rC = SimpleLowpass(fitparameters['lum_factor']*rates_center, fitparameters['dt'], fitparameters['tau1'])
  170. rC = SimpleLowpass(rC, fitparameters['dt'], fitparameters['tau1'])
  171. rC = SimpleLowpass(rC, fitparameters['dt'], fitparameters['tau1'])
  172. rC = LuminanceGainControl(rC, fitparameters['dt'], fitparameters['tau2'])
  173. rS = SimpleLowpass(fitparameters['lum_factor']*rates_surround, fitparameters['dt'], fitparameters['tau1'])
  174. rS = SimpleLowpass(rS, fitparameters['dt'], fitparameters['tau1'])
  175. rS = SimpleLowpass(rS, fitparameters['dt'], fitparameters['tau1'])
  176. rS = LuminanceGainControl(rS, fitparameters['dt'], fitparameters['tau2'])
  177. #Delay surround
  178. delayed_surround = delay_signal(rS, fitparameters['dt'], fitparameters['surround_delay'])
  179. #Calculate input signal from center - surround
  180. lum_signal = rec( rC - fitparameters['ksurr'] * delayed_surround )
  181. if type == "on-cell":
  182. b = nltan(lum_signal, fitparameters['k1'])
  183. elif type == "off-cell":
  184. b = -1*nltan(lum_signal, fitparameters['k1'])
  185. else:
  186. error(type + " ...not defined.")
  187. filtered_signal = ContrastGainControlLoop(b, fitparameters['dt'], fitparameters['tauplus'], fitparameters['tauA'], fitparameters['c1'])
  188. Rpc = rec( nltan(filtered_signal, fitparameters['k2']) )
  189. return Rpc
  190. def get_PC_response(lum_signalM, lum_signalL, fitparameters, type):
  191. signalM = SimpleLowpass(fitparameters['lum_factor']*lum_signalM, fitparameters['dt'], fitparameters['tau1'])
  192. signalM = SimpleLowpass(signalM, fitparameters['dt'], fitparameters['tau1'])
  193. signalM = SimpleLowpass(signalM, fitparameters['dt'], fitparameters['tau1'])
  194. signalM = LuminanceGainControl(signalM, fitparameters['dt'], fitparameters['tau2'])
  195. signalL = SimpleLowpass(fitparameters['lum_factor']*lum_signalL, fitparameters['dt'], fitparameters['tau1'])
  196. signalL = SimpleLowpass(signalL, fitparameters['dt'], fitparameters['tau1'])
  197. signalL = SimpleLowpass(signalL, fitparameters['dt'], fitparameters['tau1'])
  198. signalL = LuminanceGainControl(signalL, fitparameters['dt'], fitparameters['tau2'])
  199. bM = nltan(signalM, fitparameters['k1'])
  200. bL = nltan(signalL, fitparameters['k1'])
  201. if type == "Ron":
  202. out = rec(bL - fitparameters['alpha']*bM)
  203. elif type == "Gon":
  204. out = rec(bM - fitparameters['alpha']*bL)
  205. else:
  206. error(type + " ...not defined.")
  207. out = SimpleHighpass(out, fitparameters['dt'], fitparameters['tau3'])
  208. Rpc = rec( fitparameters['k2']*out + fitparameters['o1'])
  209. return Rpc
  210. def get_BO_response(lum_signalB, lum_signalM, lum_signalL, fitparameters):
  211. signalM = SimpleLowpass(lum_signalM, fitparameters['dt'], fitparameters['tau1'])
  212. signalM = SimpleLowpass(signalM, fitparameters['dt'], fitparameters['tau1'])
  213. signalM = SimpleLowpass(signalM, fitparameters['dt'], fitparameters['tau1'])
  214. signalM = LuminanceGainControl(signalM, fitparameters['dt'], fitparameters['tau2'])
  215. bM = nltan(signalM, fitparameters['kM'])
  216. signalL = SimpleLowpass(lum_signalL, fitparameters['dt'], fitparameters['tau1'])
  217. signalL = SimpleLowpass(signalL, fitparameters['dt'], fitparameters['tau1'])
  218. signalL = SimpleLowpass(signalL, fitparameters['dt'], fitparameters['tau1'])
  219. signalL = LuminanceGainControl(signalL, fitparameters['dt'], fitparameters['tau2'])
  220. bL = nltan(signalL, fitparameters['kL'])
  221. bY = fitparameters['alpha']*bM + fitparameters['beta']*bL
  222. bY = delay_signal(bY, fitparameters['dt'], fitparameters['delay'])
  223. signalB = SimpleLowpass(lum_signalB, fitparameters['dt'], fitparameters['tau1'])
  224. signalB = SimpleLowpass(signalB, fitparameters['dt'], fitparameters['tau1'])
  225. signalB = SimpleLowpass(signalB, fitparameters['dt'], fitparameters['tau1'])
  226. signalB = LuminanceGainControl(signalB, fitparameters['dt'], fitparameters['tau2'])
  227. bB = nltan(signalB, fitparameters['kB'])
  228. out = rec(bB - bY)
  229. Rpc = SimpleHighpass(out, fitparameters['dt'], fitparameters['tau3'])
  230. Rpc = rec(Rpc - fitparameters['offset'])
  231. return Rpc
  232. def compare_to_file(filename, Rpc, dt, column, shift):
  233. cell_activity = np.loadtxt(filename)
  234. time_cell = np.arange(0, len(cell_activity))*dt + 5000 - shift*6.66
  235. cell = cell_activity[(time_cell>5500) * (time_cell<64980), column]
  236. time = np.arange(0, len(Rpc)*dt, dt)
  237. model = Rpc[(time>=5500) * (time<64980)]
  238. r = np.corrcoef(cell, model)
  239. return r[0,1]