#NEWLINE# def csp( x , cl , numcomp = None ) : #NEWLINE# #INDENT# 'Calculate common spatial patterns (CSP).\n\n    Parameters\n    ----------\n    x : array, shape (trials, channels, samples) or (channels, samples)\n        EEG data set.\n    cl : list of valid dict keys\n        Class labels associated with each trial. Currently, only two classes\n        are supported.\n    numcomp : int, optional\n        Number of patterns to keep after applying CSP. If `numcomp` is greater\n        than channels or None, all patterns are returned.\n\n    Returns\n    -------\n    w : array, shape (channels, components)\n        CSP weight matrix.\n    v : array, shape (components, channels)\n        CSP projection matrix.\n    ' #NEWLINE# x = np . asarray ( x ) #NEWLINE# cl = np . asarray ( cl ) . ravel ( ) #NEWLINE# if ( ( x . ndim != 3 ) or ( x . shape [ 0 ] < 2 ) ) : #NEWLINE# #INDENT# raise AttributeError ( 'CSP requires at least two trials.' ) #NEWLINE# #UNINDENT# ( t , m , n ) = x . shape #NEWLINE# if ( t != cl . size ) : #NEWLINE# #INDENT# raise AttributeError ( 'CSP only works with multiple classes. Number of elements in cl ({}) must equal the first dimension of x ({})' . format ( cl . size , t ) ) #NEWLINE# #UNINDENT# labels = np . unique ( cl ) #NEWLINE# if ( labels . size != 2 ) : #NEWLINE# #INDENT# raise AttributeError ( 'CSP is currently implemented for two classes only (got {}).' . format ( labels . size ) ) #NEWLINE# #UNINDENT# x1 = x [ ( cl == labels [ 0 ] ) , : , : ] #NEWLINE# x2 = x [ ( cl == labels [ 1 ] ) , : , : ] #NEWLINE# sigma1 = np . zeros ( ( m , m ) ) #NEWLINE# for t in range ( x1 . shape [ 0 ] ) : #NEWLINE# #INDENT# sigma1 += ( np . cov ( x1 [ t , : , : ] ) / x1 . shape [ 0 ] ) #NEWLINE# #UNINDENT# sigma1 /= sigma1 . trace ( ) #NEWLINE# sigma2 = np . zeros ( ( m , m ) ) #NEWLINE# for t in range ( x2 . shape [ 0 ] ) : #NEWLINE# #INDENT# sigma2 += ( np . cov ( x2 [ t , : , : ] ) / x2 . shape [ 0 ] ) #NEWLINE# #UNINDENT# sigma2 /= sigma2 . trace ( ) #NEWLINE# ( e , w ) = eigh ( sigma1 , ( sigma1 + sigma2 ) , overwrite_a = True , overwrite_b = True , check_finite = False ) #NEWLINE# order = np . argsort ( e ) [ : : ( - 1 ) ] #NEWLINE# w = w [ : , order ] #NEWLINE# v = np . linalg . inv ( w ) #NEWLINE# if ( numcomp is None ) : #NEWLINE# #INDENT# numcomp = w . shape [ 1 ] #NEWLINE# #UNINDENT# while ( w . shape [ 1 ] > numcomp ) : #NEWLINE# #INDENT# i = int ( np . floor ( ( w . shape [ 1 ] / 2 ) ) ) #NEWLINE# w = np . delete ( w , i , 1 ) #NEWLINE# v = np . delete ( v , i , 0 ) #NEWLINE# #UNINDENT# return ( w , v )