comparison cortical_model.py @ 4:29cd3e735c4c

* Added run.py for testing * Changed frequency decomposition to bank of gammatones
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Sat, 22 Feb 2014 13:53:55 +0000
parents 2d80632482b3
children d7b2784ff5a3
comparison
equal deleted inserted replaced
3:2d80632482b3 4:29cd3e735c4c
249 """ 249 """
250 250
251 input = np.array(input) 251 input = np.array(input)
252 inputOMFir = outMidFir(input) 252 inputOMFir = outMidFir(input)
253 inputPa = v_Pascal(inputOMFir, SPL) 253 inputPa = v_Pascal(inputOMFir, SPL)
254 gtfs = gamma_tone_filter(inputPa, fs, verbose = verbose) 254 b = gamma_tone_filter(fs)
255 gtfs = decomposition(inputPa, b, verbose = verbose)
255 if (rectify): 256 if (rectify):
256 gtfs = half_rectification(gtfs) 257 gtfs = half_rectification(gtfs)
257 gtfs = pa_i(gtfs) 258 gtfs = pa_i(gtfs)
258 gtfs = at_normalise(gtfs) 259 gtfs = at_normalise(gtfs)
259 b,a = exp_smoothing(fs) 260 b,a = exp_smoothing(fs)
260 gtfs = sp.lfilter(b,a,gtfs) 261 gtfs = sp.lfilter(b,a,gtfs)
261 262
262 return gtfs 263 return gtfs
263 264
264 def plot_excitation_response(input = 0, fs = 44100, outMidFilt = True, xscale = 'log', yscale = 'log'): 265 def plot_excitation_response(input = None, fs = 44100, outMidFilt = True, gammatone = True, xscale = 'log', yscale = 'log'):
265 """ 266 """
266 A function that plots the transfer function of the outer middle ear and each gammatone filter. 267 A function that plots the transfer function of the outer middle ear and each gammatone filter.
267 268
268 Parameters: 269 Parameters:
269 * fs (type: numerical) - the sampling frequency of the signal. (Optional; Default = 44100) 270 * fs (type: numerical) - the sampling frequency of the signal. (Optional; Default = 44100)
270 * outMidFilt (type: boolean) - filter the signal by the outer and middle ear FIR filter. (Optional; Default = True) 271 * outMidFilt (type: boolean) - filter the signal by the outer and middle ear FIR filter. (Optional; Default = True)
271 * xscale (type: string) - the scale of the frequency axis. Values are 'log' or 'linear'. (Optional; Default = 'log') 272 * xscale (type: string) - the scale of the frequency axis. Values are 'log' or 'linear'. (Optional; Default = 'log')
272 * yscale (type: string) - the scale of the amplitude axis. Values are 'log' or 'linear'. (Optional; Default = 'log') 273 * yscale (type: string) - the scale of the amplitude axis. Values are 'log' or 'linear'. (Optional; Default = 'log')
273 274 """
274 Returns: 275
275 * y (type: numpy array of floats) - array with size ((39,np.ceil(fs))) containing the impulse response of the 276 if input == None:
276 signal at each gammatone filter (and optionally, including the outer middle ear response). The response at the 277 input = np.zeros((np.ceil(fs)))
277 nth gammatone filter can be accessed by y[n].
278 """
279
280 if ((np.shape(input)==())):
281 input = np.zeros(np.ceil(fs))
282 input[0] = 1 278 input[0] = 1
279
283 if(outMidFilt): input = outMidFir(input) 280 if(outMidFilt): input = outMidFir(input)
284 y = gamma_tone_filter(input, fs) 281 if(gammatone):
285 282 b = gamma_tone_filter(fs)
286 for i in range(np.shape(y)[0]): 283 input = decomposition(input, b)
287 utils.plot_fft(y[i],xscale, yscale, False) 284 #input = holdsworthGamma(input,fs)
285 numPlot = range(np.shape(input)[0])
286 else:
287 numPlot = (0,)
288 input = input.reshape(1,len(input))
289
290 for i in numPlot:
291 utils.plot_fft(input[i],xscale, yscale, False)
288 292
289 plt.show() 293 plt.show()
290 294
291 return fft.fft(y) 295 return
292 296
293 def get_modulation_i(input, fs): 297 def get_modulation_i(input, fs):
294 """ 298 """
295 A function to calculate the modulation intensity of the input intensity signal. The function implements a 299 A function to calculate the modulation intensity of the input intensity signal. The function implements a
296 filter bank of bandpass filters with cut off frequencies ranging from 0.25 to 16 Hz. 300 filter bank of bandpass filters with cut off frequencies ranging from 0.25 to 16 Hz.
332 b = utils.load_outMidFir_coeff() 336 b = utils.load_outMidFir_coeff()
333 y = sp.lfilter(b, (1), input) 337 y = sp.lfilter(b, (1), input)
334 338
335 return y 339 return y
336 340
337 def gamma_tone_filter(input, fs, verbose = False): 341 def gamma_tone_filter(fs):
338 """ 342 """
339 A function to filter to decompose the input signal into 39 different gammatones filtered signals modelling the ERBs. 343 A function to filter to decompose the input signal into 39 different gammatones filtered signals modelling the ERBs.
340 344
341 Parameters: 345 Parameters:
342 * input (type: array-like matrix of floats) - signal normalised to an amplitude range of -1 to 1. (Required) 346 * input (type: array-like matrix of floats) - signal normalised to an amplitude range of -1 to 1. (Required)
345 Returns: 349 Returns:
346 * y (type: numpy array of floats) - array with size ((39),np.shape(input)) containing the impulse response of the 350 * y (type: numpy array of floats) - array with size ((39),np.shape(input)) containing the impulse response of the
347 signal at each gammatone filter. The response at the nth gammatone filter can be accessed by y[n]. 351 signal at each gammatone filter. The response at the nth gammatone filter can be accessed by y[n].
348 """ 352 """
349 353
350 input = np.array(input) 354 nerbs = 39
351 fc, bw = utils.load_erb_data() 355 erbs = np.array(range(1,nerbs+1))
352 y = decomposition(input,fs,fc,bw, verbose = verbose) 356 fc = (10**(erbs/21.366)-1)/0.004368
353 357 bw = 24.673 * (1 + 0.004368*fc)
354 return y 358 N = 4
359 filterLength = 4096
360 t = 1.0*np.array(range(filterLength))/fs
361
362 gain=((1.019*bw*(2.0*np.pi)/float(fs))**4)/6.0
363
364 PI = N * np.arctan(1)
365
366 b = np.zeros((nerbs,filterLength))
367
368 for i in range(39):
369 b[i] = gain[i] * t**(N-1) * fs**(N-1) * np.exp(-2*np.pi*bw[i]*t) * np.cos(2*np.pi*fc[i]*t)
370
371 return b
372
373 def holdsworthGamma(input, fs):
374 """
375
376 """
377 input = np.array(input)
378 input = input + 0j
379
380 T = 1.0/fs
381
382 ERBs = np.array(range(1,40))
383 f0 = (10**(ERBs/21.4)-1)/4.37e-3
384
385 inLen = len(input)
386 b = 24.673 * (1 + 0.004368*f0)
387 k = np.array(range(inLen)) + 0j
388 out = np.zeros((39,inLen))
389
390 for erb in range(39):
391
392 zArr = input*np.exp(-2*np.pi*1j*f0[erb]*k*T)
393 wArr = np.zeros((inLen+1))
394
395 for i in range(1,inLen+1):
396 wArr[i] = wArr[i-1] + (1 - np.exp(-2*np.pi*b[erb]*T))*(zArr[i-1] - wArr[i-1])
397
398 out[erb] = (wArr[1:]*np.exp(2*np.pi*1j*f0[erb]*k*T)).real
399
400 return out
401
355 402
356 def v_Pascal(input, SPL): 403 def v_Pascal(input, SPL):
357 """ 404 """
358 A function to convert a signal, normalised to an amplitude range of -1 to 1, to a signal represented in pressure (units: Pascal). 405 A function to convert a signal, normalised to an amplitude range of -1 to 1, to a signal represented in pressure (units: Pascal).
359 406
449 y = np.array(input) 496 y = np.array(input)
450 y[y<0] = 0 497 y[y<0] = 0
451 498
452 return y 499 return y
453 500
454 def decomposition(input, fs, fc, bw, order=1024, verbose = False): 501 def decomposition(input, b, a = None, verbose = False):
455 """ 502 """
456 A function to run the input filter through a bandpass filter bank of length equal to the length of fc. Each 503 A function to run the input through a bandpass filter bank with parameters defined by the b and a coefficints.
504
505 Parameters:
506 * input (type: array-like matrix of floats) - input signal. (Required)
507 * b (type: array-like matrix of floats) - the b coefficients of each filter in shape b[numOfFilters][numOfCoeffs]. (Required)
508 * a (type: array-like matrix of floats) - the a coefficients of each filter in shape a[numOfFilters][numOfCoeffs].
509 If not specified, the filter is treated as a FIR filter. (Optional; Default = 1)
510 * verbose (type: boolean) - determines whether to display the current subroutine/progress of the procedure.
511 (Optional; Default = False)
512
513 Returns:
514 * y (type: numpy array of floats) - an array with inner dimensions equal to that of the input and outer dimension equal to
515 the length of fc (i.e. the number of bandpass filters in the bank) containing the outputs to each filter. The output
516 signal of the nth filter can be accessed using y[n].
517 """
518
519 input = np.array(input)
520 bShape = np.shape(b)
521 nFilters = bShape[0]
522
523 if a == None:
524 a = np.ones(nFilters)
525
526 shape = (nFilters,) + np.shape(input)
527 shape = shape[0:]
528 y = np.zeros(shape)
529
530 if(verbose): print "Running decomposition."
531 for i in range(nFilters):
532 if(verbose): print str(100.0*i/nFilters) + "% complete."
533 x = deepcopy(input)
534 y[i] = sp.lfilter(b[i],a[i],x)
535
536 return y
537
538 def get_Modulation_filter_bank_coefficients(fs, fc, bw, order = 1024, verbose = False):
539 """
540 A function which returns the b and a coefficients of the modulation filter bank of length equal to the length of fc. Each
457 bandpass filter is designed by defining the centre frequencies, fc, and bandwidths, bw. 541 bandpass filter is designed by defining the centre frequencies, fc, and bandwidths, bw.
458 542
459 Parameters: 543 Parameters:
460 * input (type: array-like matrix of floats) - input signal. (Required)
461 * fs (type: numerical) - the sampling frequency of the input signal. (Required) 544 * fs (type: numerical) - the sampling frequency of the input signal. (Required)
462 * fc (type: array-like vector of floats) - the centre off frequencies (unnormalised) of each bandpass filter. 545 * fc (type: array-like vector of floats) - the centre off frequencies (unnormalised) of each bandpass filter.
463 The length of this vector determines the number of filters in the bank. 546 The length of this vector determines the number of filters in the bank.
464 * bw (type: array-like vector of floats) - the bandwidths (unnormalised) of each bandpass filter. Must be equal 547 * bw (type: array-like vector of floats) - the bandwidths (unnormalised) of each bandpass filter. Must be equal
465 to or more than the length of fc. If the length is more, all elements exceeding the length of fc - 1 will be 548 to or more than the length of fc. If the length is more, all elements exceeding the length of fc - 1 will be
467 * order (type: numerical int) - the order of the filter (number of taps minus 1) (Optional; Default = 1024) 550 * order (type: numerical int) - the order of the filter (number of taps minus 1) (Optional; Default = 1024)
468 * verbose (type: boolean) - determines whether to display the current subroutine/progress of the procedure. 551 * verbose (type: boolean) - determines whether to display the current subroutine/progress of the procedure.
469 (Optional; Default = False) 552 (Optional; Default = False)
470 553
471 Returns: 554 Returns:
472 * y (type: numpy array of floats) - an array with inner dimensions equal to that of the input and outer dimension equal to 555 * b (type: numpy array of floats) - an array of size order + 1 (i.e. a coefficient for each tap)
473 the length of fc (i.e. the number of bandpass filters in the bank) containing the outputs to each filter. The output 556 """
474 signal of the nth filter can be accessed using y[n]. 557
475 """ 558
476
477 input = np.array(input)
478 nFreqs = len(fc) 559 nFreqs = len(fc)
479 shape = (nFreqs,) + np.shape(input) 560
480 shape = shape[0:]
481 y = np.zeros(shape)
482
483 if(verbose): print "Running frequency decomposition." 561 if(verbose): print "Running frequency decomposition."
562
484 for i in range(nFreqs): 563 for i in range(nFreqs):
485 if(verbose): print str(100.0*i/nFreqs) + "% complete." 564 if(verbose): print str(100.0*i/nFreqs) + "% complete."
486 low = fc[i]-bw[i]/2; 565 low = fc[i]-bw[i]/2;
487 high = fc[i]+bw[i]/2; 566 high = fc[i]+bw[i]/2;
488 if(verbose): print "Low: " + str(low) + "; High: " + str(high) 567 if(verbose): print "Low: " + str(low) + "; High: " + str(high)
489 b = fir_bandpass(low, high, fs, order, verbose) 568 b = fir_bandpass(low, high, fs, order, verbose)
490 x = deepcopy(input) 569
491 y[i] = sp.lfilter(b,(1),x) 570 return b
492
493 return y
494 571
495 def exp_smoothing(fs, tc = 0.01): 572 def exp_smoothing(fs, tc = 0.01):
496 """ 573 """
497 Designs an exponential filter, y[n] = alpha*x[n] - -(1-alpha)*y[n-1], where alpha = T/(tc+T), where T 574 Designs an exponential filter, y[n] = alpha*x[n] - -(1-alpha)*y[n-1], where alpha = T/(tc+T), where T
498 is the inverse of the sampling frequency and time constant, tc, is specified. 575 is the inverse of the sampling frequency and time constant, tc, is specified.
532 fcNorm = fc/nyquist 609 fcNorm = fc/nyquist
533 b = sp.firwin(order+1, fcNorm) 610 b = sp.firwin(order+1, fcNorm)
534 611
535 return b 612 return b
536 613
537 def fir_bandpass(low, high, fs, order = 1024, verbose = False): 614 def fir_bandpass(low, high, fs, order = 4096, verbose = False):
538 """ 615 """
539 A function which returns the b coefficients for a bandpass fir filter with specified requirements. 616 A function which returns the b coefficients for a bandpass fir filter with specified requirements.
540 617
541 Parameters: 618 Parameters:
542 * low - the lower cutoff frequency of the filter. (Required) 619 * low - the lower cutoff frequency of the filter. (Required)