def test_lead_field_class_same_output_as_function(): global old_code lf = Lead_Field() for i in range(len(old_code)): lead_field_class = lf.calculate(old_code[i]['gen_conf']) lead_field_function = calculate_lead_field(old_code[i]['gen_conf']) assert_array_equal(lead_field_class, lead_field_function)
def __init__(self, parameter_list=None, parameters=None, n_sub=23, n_gen=1): # Optimal bounds for fitting self.magnitude_bounds = (0, None) # unnecessary? self.depth_bounds = (4.49, 7.05) # cortex self.theta_bounds = (0,pi/2) self.phi_bounds = (0,2*pi) # unnecessary? self.orientation_bounds = (0, pi/2) self.orientation_phi_bounds = (0,2*pi) # unnecessary? self.gen_variance_bounds = (None, None) self.gen_covariance_bounds = (None, None) self.el_variance_bounds = (None, None) # Parameter limits for randomizing model self.magnitude_lim = (1, 10000000) self.depth_lim = (4.49, 7.05) # cortex self.phi_lim = (0,2*pi) self.theta_lim = (0,pi/2) self.orientation_lim = (0, pi/2) # cortex self.orientation_phi_lim = (0,2*pi) self.gen_variance_lim = [0, 1000000] self.gen_covariance_lim = [0, 1000000] self.el_variance_lim = [0, 20] # Variability parameters self.sigma_e = 0 self.sigma_g = 0 self.sigma_c = 0 self.n_gen = n_gen self.n_sub = n_sub self.n_el = 60 self.lf = Lead_Field() self.gen_conf = None self.up_to_date = {} if parameter_list == None or 'locations and orientations' not in parameter_list: self.set_random_parameters(['locations and orientations']) # Amplitudes should be set separately, but for now they're not... #self.set_random_parameters(['locations and orientations', # 'amplitudes']) if parameter_list != None: self.set_parameters(parameter_list, parameters) # This is not working, amplitudes are being set above along with # locations and orientations, which shouldn't be the case #if 'amplitudes' not in parameter_list: # self.set_random_parameters(['amplitudes']) self.recalculate_model()
def __init__( self, n_sub, n_gen, variability_electrodes="none", variability_generators="none", variability_connections="none" ): self.n_gen = n_gen # generators self.n_sub = n_sub # subjects self.n_el = 60 # Hard-coded to use a specific electrode set self.up_to_date = {} self.set_parameter_limits() self.gen_conf = None self.lf = Lead_Field() self.set_variability_type(variability_electrodes, variability_generators, variability_connections) self.sigma_e = 0 self.sigma_g = zeros(self.n_gen) self.sigma_c = zeros((self.n_gen, self.n_gen))
class ERP_Variability_Model: def __init__( self, n_sub, n_gen, variability_electrodes="none", variability_generators="none", variability_connections="none" ): self.n_gen = n_gen # generators self.n_sub = n_sub # subjects self.n_el = 60 # Hard-coded to use a specific electrode set self.up_to_date = {} self.set_parameter_limits() self.gen_conf = None self.lf = Lead_Field() self.set_variability_type(variability_electrodes, variability_generators, variability_connections) self.sigma_e = 0 self.sigma_g = zeros(self.n_gen) self.sigma_c = zeros((self.n_gen, self.n_gen)) def print_model(self, topographies=False): print ("ERP Model Parameters") print ("====================") print ("Number of generators: " + str(self.n_gen) + "\n") print ("Variability") print ("-----------") print ("* Electrodes (self.sigma_e)") print self.sigma_e print ("* Generators (self.cov_gen)") print self.cov_gen print ("* Final covariance matrix (self.cov)") print self.cov for gen in range(self.n_gen): print ("\nGenerator " + str(gen + 1)) print ("-------------------") print ("LOCATION, Depth: " + str(self.gen_conf[gen]["depth"])) print ("LOCATION, Theta: " + str(self.gen_conf[gen]["theta"])) print ("LOCATION, Phi: " + str(self.gen_conf[gen]["phi"])) print ("ORIENTATION: " + str(self.gen_conf[gen]["orientation"])) print ("ORIENTATION, Phi: " + str(self.gen_conf[gen]["orientation_phi"])) print ("MAGNITUDE: " + str(self.gen_conf[gen]["magnitude"])) if topographies: pyplot.figure() plot_topographic_map((self.gen_conf[gen]["magnitude"] * self.lf.calculate([self.gen_conf[gen]]))[:, 0]) def plot_model(self, to_plot): for one_plot in to_plot: if one_plot == "mean": plot_topographic_map(self.mean) pyplot.title("Topographic map of mean") # Individual generator means pyplot.figure() for i in range(self.n_gen): pyplot.subplot(1, self.n_gen, i) plot_topographic_map(self.mean) pyplot.figtext(0.5, 0.75, "Topographic maps of means of each generator", ha="center") if one_plot == "variance": pyplot.figure() plot_topographic_map(self.cov.diagonal()) pyplot.title("Topographic map of variance") # Individual generator variances pyplot.figure() for i in range(self.n_gen): pyplot.subplot(1, self.n_gen, i) single_cov = dot(transpose(self.lead_field[:, i][newaxis]), self.lead_field[:, i][newaxis]) if self.variability_generators == "constant": single_cov = self.sigma_g * single_cov elif self.variability_generators == "individual": single_cov = self.sigma_g[i] * single_cov plot_topographic_map(single_cov.diagonal()) pyplot.figtext(0.5, 0.75, "Topographic maps of variance of each generator", ha="center") if one_plot == "covariance matrix": pyplot.figure() plot_covariance_matrix(self.data, self.cov) pyplot.title("Covariance matrix") def set_parameter_limits(self): # Parameter bounds for randomizing model parameters self.limits = {} # Location and orientation self.limits["depth"] = (4.49, 7.05) # roughly the cortex self.limits["phi"] = (0, 2 * pi) self.limits["theta"] = (0, pi / 2) self.limits["orientation"] = (0, pi / 2) # cortex self.limits["orientation_phi"] = (0, 2 * pi) # Magnitude self.limits["magnitude"] = (0, 1000) # Variability self.limits["generator_variance"] = [0, 1000000] self.limits["electrode_variance"] = [0, 20] # Covariance needs no limits becuase it is limited by the variance of # the two generators in question # self.limits['generator_covariance'] = [0, 1000000] # Constant number of generators self.limits["n_gen"] = (self.n_gen, self.n_gen) def set_variability_type(self, variability_electrodes, variability_generators, variability_connections): if variability_electrodes not in ["constant", "individual", "none"]: raise ValueError else: self.variability_electrodes = variability_electrodes if variability_generators not in ["constant", "individual", "none"]: raise ValueError else: self.variability_generators = variability_generators if variability_connections not in ["individual", "none"]: raise ValueError else: self.variability_connections = variability_connections def set_gen_conf(self, gen_conf): self.gen_conf = gen_conf self.n_gen = len(gen_conf) def set_random(self): self.set_random_locations_orientations() self.set_random_magnitudes() self.set_random_variability() def set_random_locations_orientations(self): self.gen_conf = random_generator_placement(self.limits) self.up_to_date["lead field"] = False self.up_to_date["mean"] = False self.up_to_date["covariance generators"] = False self.up_to_date["covariance"] = False def set_random_magnitudes(self): limits = self.limits["magnitude"] for i in range(self.n_gen): self.gen_conf[i]["magnitude"] = limits[0] + uniform(limits[1] - limits[0]) self.up_to_date["mean"] = False def set_random_variability(self): self.set_random_variability_electrodes() self.set_random_variability_generators() self.set_random_variability_connections() def set_random_variability_electrodes(self): limits = self.limits["electrode_variance"] if self.variability_electrodes == "none": self.sigma_e = 0 elif self.variability_electrodes == "constant": self.sigma_e = limits[0] + uniform(limits[1] - limits[0]) elif self.variability_electrodes == "individual": self.sigma_e = [] for i in range(self.n_el): self.sigma_e.append(limits[0] + uniform(limits[1] - limits[0])) def set_random_variability_generators(self): limits = self.limits["generator_variance"] if self.variability_generators == "none": self.sigma_g = 0 elif self.variability_generators == "constant": self.sigma_g = limits[0] + uniform(limits[1] - limits[0]) elif self.variability_generators == "individual": self.sigma_g = [] for i in range(self.n_gen): self.sigma_g.append(limits[0] + uniform(limits[1] - limits[0])) def set_random_variability_connections(self): if self.variability_connections == "none": self.sigma_c = zeros((self.n_gen, self.n_gen)) elif self.variability_connections == "individual": self.sigma_c = zeros((self.n_gen, self.n_gen)) for row in range(self.n_gen): for column in range(self.n_gen): if row < column: sigma_c = uniform(sqrt(self.sigma_g[row] * self.sigma_g[column])) self.sigma_c[row, column] = sigma_c self.sigma_c[column, row] = sigma_c def calculate_lead_field(self): self.lead_field = self.lf.calculate(self.gen_conf) self.up_to_date["lead field"] = True self.up_to_date["mean"] = False self.up_to_date["covariance generators"] = False self.up_to_date["covariance"] = False return self.lead_field def calculate_mean(self): if not self.up_to_date["lead field"]: self.calculate_lead_field() gen_amplitudes = [] for i in range(self.n_gen): gen_amplitudes.append(self.gen_conf[i]["magnitude"]) self.mean = dot(self.lead_field, gen_amplitudes) self.up_to_date["mean"] = True return self.mean def calculate_cov_gen(self): if not self.up_to_date["lead field"]: self.calculate_lead_field() self.cov_gen = zeros((self.n_gen, self.n_gen)) for row in range(self.n_gen): for column in range(self.n_gen): if row == column: if self.variability_generators == "individual": self.cov_gen[row, column] = self.sigma_g[row] elif self.variability_generators == "constant": self.cov_gen[row, column] = self.sigma_g elif column > row: if self.variability_connections == "individual": self.cov_gen[row, column] = self.sigma_c[row, column] self.cov_gen[column, row] = self.sigma_c[row, column] self.up_to_date["covariance generators"] = True self.up_to_date["covariance"] = False return self.cov_gen def calculate_cov(self): if not self.up_to_date["lead field"]: self.calculate_lead_field() if not self.up_to_date["covariance generators"]: self.calculate_cov_gen() # TODO: Make it work for individual electrode variance as well self.cov = dot(dot(self.lead_field, self.cov_gen), transpose(self.lead_field)) + self.sigma_e * identity( self.n_el ) self.up_to_date["covariance"] = True return self.cov def simulate(self): self.data = multivariate_normal(self.mean, self.cov, self.n_sub) return self.data def recalculate_model(self): self.up_to_date["lead field"] = False self.up_to_date["mean"] = False self.up_to_date["covariance generators"] = False self.up_to_date["covariance"] = False self.calculate_lead_field() self.calculate_mean() self.calculate_cov() self.simulate()
class ERP_Model(): def __init__(self, parameter_list=None, parameters=None, n_sub=23, n_gen=1): # Optimal bounds for fitting self.magnitude_bounds = (0, None) # unnecessary? self.depth_bounds = (4.49, 7.05) # cortex self.theta_bounds = (0,pi/2) self.phi_bounds = (0,2*pi) # unnecessary? self.orientation_bounds = (0, pi/2) self.orientation_phi_bounds = (0,2*pi) # unnecessary? self.gen_variance_bounds = (None, None) self.gen_covariance_bounds = (None, None) self.el_variance_bounds = (None, None) # Parameter limits for randomizing model self.magnitude_lim = (1, 10000000) self.depth_lim = (4.49, 7.05) # cortex self.phi_lim = (0,2*pi) self.theta_lim = (0,pi/2) self.orientation_lim = (0, pi/2) # cortex self.orientation_phi_lim = (0,2*pi) self.gen_variance_lim = [0, 1000000] self.gen_covariance_lim = [0, 1000000] self.el_variance_lim = [0, 20] # Variability parameters self.sigma_e = 0 self.sigma_g = 0 self.sigma_c = 0 self.n_gen = n_gen self.n_sub = n_sub self.n_el = 60 self.lf = Lead_Field() self.gen_conf = None self.up_to_date = {} if parameter_list == None or 'locations and orientations' not in parameter_list: self.set_random_parameters(['locations and orientations']) # Amplitudes should be set separately, but for now they're not... #self.set_random_parameters(['locations and orientations', # 'amplitudes']) if parameter_list != None: self.set_parameters(parameter_list, parameters) # This is not working, amplitudes are being set above along with # locations and orientations, which shouldn't be the case #if 'amplitudes' not in parameter_list: # self.set_random_parameters(['amplitudes']) self.recalculate_model() def print_model(self, topographies=False): print('ERP Model Parameters') print('====================') print('Number of generators: ' + str(self.n_gen) + '\n') print('Variability') print('-----------') if self.sigma_e == 0: print('* No electrode variance.') else: print('* Electrode variance: ' + str(self.sigma_e)) print('* Generator covariance matrix:') print(self.cov_gen) #if self.n_gen > 1 and isinstance(self.sigma_g, list): # print('* Individual generator variance.') #elif self.n_gen > 1: # print('* Generator variance: ' + str(self.sigma_g)) #if self.n_gen > 1 and isinstance(self.sigma_c, list): # print('* Individual generator covariance.') #elif self.n_gen > 1: # print('* Generator variance: ' + str(self.sigma_g)) for gen in range(self.n_gen): print('Generator ' + str(gen+1)) print('-------------------') print('LOCATION, Depth: ' + str(self.gen_conf[gen]['depth'])) print('LOCATION, Theta: ' + str(self.gen_conf[gen]['theta'])) print('LOCATION, Phi: ' + str(self.gen_conf[gen]['phi'])) print('ORIENTATION: ' + str(self.gen_conf[gen]['orientation'])) print('ORIENTATION, Phi: ' + str(self.gen_conf[gen]['orientation_phi'])) print('MAGNITUDE: ' + str(self.gen_conf[gen]['magnitude'])) if topographies: pyplot.figure() plot_topographic_map((self.gen_conf[gen]['magnitude'] * self.lf.calculate( [self.gen_conf[gen]]))[:,0]) def set_random_parameters(self, parameter_list): for i in range(len(parameter_list)): if parameter_list[i] == 'locations and orientations': self.gen_conf = random_generator_configuration((self.n_gen, self.n_gen), self.depth_lim, self.orientation_lim, self.magnitude_lim)[0] elif parameter_list[i] == 'generator variance': self.sigma_g = self.gen_variance_lim[0] +\ uniform(self.gen_variance_lim[1] -\ self.gen_variance_lim[0]) elif parameter_list[i] == 'generator variances individual': self.sigma_g = [] for j in range(self.n_gen): sigma_g = self.gen_variance_lim[0] +\ uniform(self.gen_variance_lim[1] -\ self.gen_variance_lim[0]) self.sigma_g.append(sigma_g) elif parameter_list[i] == 'generator covariance': self.sigma_c = self.gen_covariance_lim[0] +\ uniform(self.gen_covariance_lim[1] -\ self.gen_covariance_lim[0]) elif parameter_list[i] == 'generator covariances individual': self.sigma_c = zeros((self.n_gen, self.n_gen)) for row in range(self.n_gen): for column in range(self.n_gen): if row < column: sigma_c = self.gen_covariance_lim[0] +\ uniform(self.gen_covariance_lim[1] -\ self.gen_covariance_lim[0]) self.sigma_c[row,column] = sigma_c self.sigma_c[column,row] = sigma_c elif parameter_list[i] == 'electrode variance': self.sigma_e = self.el_variance_lim[0] +\ uniform(self.el_variance_lim[1] -\ self.el_variance_lim[0]) self.up_to_date['lead field'] = False self.up_to_date['mean'] = False self.up_to_date['covariance generators'] = False self.up_to_date['covariance'] = False def set_parameters(self, parameter_list, parameters): """This function enables you to fit any sets of parameters, i.e.: * location and orientations * amplitudes * generator variance * generator variances individual * generator covariance * generator covariances individual * electrode variance You need to pass the list of parameters and a list of their values: set_parameters(self, parameter_list, parameters), where parameter_list would be of the form (GLVM model): ['locations and orientations', 'amplitudes', 'equal variance'] and depending on what parameters are listed, the parameters variable will be expected to hold different values, but always in a list """ par = 0 # the current parameter for i in range(len(parameter_list)): gen_amplitudes = [] for j in range(self.n_gen): gen_amplitudes.append(self.gen_conf[j]['magnitude']) if parameter_list[i] == 'locations and orientations': self.gen_conf = [] n_gen_parameters = 5 # Creating generator configuration for gen in range(self.n_gen): self.gen_conf.append({}) self.gen_conf[gen]['depth'] = parameters[par] self.gen_conf[gen]['orientation'] = parameters[par + 1] self.gen_conf[gen]['orientation_phi'] = parameters[par + 2] self.gen_conf[gen]['phi'] = parameters[par + 3] self.gen_conf[gen]['theta'] = parameters[par + 4] self.gen_conf[gen]['magnitude'] = gen_amplitudes[gen] par += n_gen_parameters if parameter_list[i] == 'amplitudes': if self.gen_conf == None: print('WARNING: Trying to set amplitudes without generators') for gen in range(self.n_gen): self.gen_conf[gen]['magnitude'] = parameters[par] par += 1 if parameter_list[i] == 'generator variance': self.sigma_g = parameters[par] par += 1 if parameter_list[i] == 'generator variances individual': self.sigma_g = list(parameters[par : par + self.n_gen]) par += self.n_gen if parameter_list[i] == 'generator covariance': self.sigma_c = parameters[par] par += 1 if parameter_list[i] == 'generator covariances individual': self.sigma_c = zeros((self.n_gen, self.n_gen)) for row in range(self.n_gen): for col in range(self.n_gen): if row < col: self.sigma_c[row,col] = parameters[par] self.sigma_c[col,row] = parameters[par] par += 1 if parameter_list[i] == 'electrode variance': self.sigma_e = parameters[par] par += 1 self.up_to_date['lead field'] = False self.up_to_date['mean'] = False self.up_to_date['covariance generators'] = False self.up_to_date['covariance'] = False def get_parameters(self, parameter_list): parameters = [] for i in range(len(parameter_list)): if parameter_list[i] == 'locations and orientations': for gen in range(self.n_gen): parameters.append(self.gen_conf[gen]['depth']) parameters.append(self.gen_conf[gen]['orientation']) parameters.append(self.gen_conf[gen]['orientation_phi']) parameters.append(self.gen_conf[gen]['phi']) parameters.append(self.gen_conf[gen]['theta']) if parameter_list[i] == 'amplitudes': for gen in range(self.n_gen): parameters.append(self.gen_conf[gen]['magnitude']) if parameter_list[i] == 'generator variance': if not isinstance(self.sigma_g, list): parameters.append(self.sigma_g) else: print('WARNING: Variances expected to be identical for \ all generators, however self.sigma_g holds a list, \ not a single value') if parameter_list[i] == 'generator variances individual': if isinstance(self.sigma_g, list): for j in range(len(self.sigma_g)): parameters.append(self.sigma_g[j]) else: print('WARNING: Variances expected to be different for \ all generators, however self.sigma_g does not hold \ a list') if parameter_list[i] == 'generator covariance': if not isinstance(self.sigma_c, ndarray): parameters.append(self.sigma_c) else: print('WARNING: Generator covariance expected to be \ identical for all generators, however self.sigma_c \ holds an array, not a single value') if parameter_list[i] == 'generator covariances individual': if isinstance(self.sigma_c, ndarray): for row in range(self.n_gen): for col in range(self.n_gen): if row < col: parameters.append(self.sigma_c[row,col]) else: print('WARNING: Generator covariances expected to be \ different for all generator pairs, however \ self.sigma_c is not an array') if parameter_list[i] == 'electrode variance': parameters.append(self.sigma_e) return parameters def get_bounds(self, parameter_list): bounds = [] for i in range(len(parameter_list)): if parameter_list[i] == 'locations and orientations': for j in range(self.n_gen): bounds.append(self.depth_bounds) bounds.append(self.orientation_bounds) bounds.append(self.orientation_phi_bounds) bounds.append(self.phi_bounds) bounds.append(self.theta_bounds) if parameter_list[i] == 'amplitudes': for j in range(self.n_gen): bounds.append(self.magnitude_bounds) if parameter_list[i] == 'generator variance': bounds.append(self.gen_variance_bounds) if parameter_list[i] == 'generator variances individual': for j in range(self.n_gen): bounds.append(self.gen_variance_bounds) if parameter_list[i] == 'generator covariance': bounds.append(self.gen_covariance_bounds) if parameter_list[i] == 'generator covariances individual': for j in range(self.n_gen*(self.n_gen-1)/2): bounds.append(self.gen_covariance_bounds) if parameter_list[i] == 'electrode variance': bounds.append(self.el_variance_bounds) return bounds def calculate_lead_field(self): self.lead_field = self.lf.calculate(self.gen_conf) self.up_to_date['lead field'] = True self.up_to_date['mean'] = False self.up_to_date['covariance'] = False return self.lead_field def calculate_mean(self): if not self.up_to_date['lead field']: self.calculate_lead_field() gen_amplitudes = [] for i in range(self.n_gen): gen_amplitudes.append(self.gen_conf[i]['magnitude']) self.mean = dot(self.lead_field, gen_amplitudes) self.up_to_date['mean'] = True return self.mean def calculate_cov_gen(self): self.cov_gen = zeros((self.n_gen, self.n_gen)) for row in range(self.n_gen): for column in range(self.n_gen): if row == column: if isinstance(self.sigma_g, list): self.cov_gen[row,column] = self.sigma_g[row] else: self.cov_gen[row,column] = self.sigma_g elif column > row: if isinstance(self.sigma_c, ndarray): self.cov_gen[row,column] = self.sigma_c[row,column] self.cov_gen[column,row] = self.sigma_c[row,column] else: self.cov_gen[row,column] = self.sigma_c self.cov_gen[column,row] = self.sigma_c self.up_to_date['covariance generators'] = True self.up_to_date['covariance'] = False return self.cov_gen def calculate_cov(self): if not self.up_to_date['lead field']: self.calculate_lead_field() if not self.up_to_date['covariance generators']: self.calculate_cov_gen() self.cov = dot(dot(self.lead_field, self.cov_gen), transpose(self.lead_field)) + self.sigma_e *\ identity(self.n_el) self.up_to_date['covariance'] = True return self.cov def simulate(self): self.data = multivariate_normal(self.mean,self.cov,self.n_sub) return self.data def recalculate_model(self): self.calculate_lead_field() self.calculate_mean() self.calculate_cov() self.simulate()
def test_lead_field_class(): global old_code lf = Lead_Field() for i in range(len(old_code)): lead_field = lf.calculate(old_code[i]['gen_conf']) assert_array_almost_equal(lead_field, old_code[i]['lead_field'], 17)