Source code for allensdk.internal.model.glif.configure_model

#going to need to take preprocessed dictionaries and model configuration and create 
#a preprocessed model configuration and preprocessed_config file
#
#something will have to tell it what parameters to take out of the preprocessed dict
import numpy as np
import argparse
import allensdk.core.json_utilities as ju

[docs] class ModelConfigurationException( Exception ): pass
DEFAULT_NEURON_PARAMETERS = { "type": "GLIF", "dt": 5e-05, "El": 0, "asc_tau_array": [ 1, 1 ], "asc_amp_array": [ 0, 0 ], "init_AScurrents": [ 0.0, 0.0 ], "init_threshold": 0.02, "init_voltage": 0.0, "extrapolation_method_name": "endpoints", "dt_multiplier": 1 } DEFAULT_OPTIMIZER_PARAMETERS = { "xtol": 1e-05, "ftol": 1e-05, "sigma_outer": 0.3, "sigma_inner": 0.01, "inner_iterations": 3, "outer_iterations": 3, "internal_iterations": 10000000, "iteration_info": [], "param_fit_names": [], "cut": 0, "bessel": { 'N': 4, 'freq': 10000 } }
[docs] def specify_parameter_groups(dictionary, dict_specifer, neuron_type): '''Specifies which values from the preprocessor will be used in the model configuration. This is helpful if the preprocessor calculates many different values. Parameters ---------- dictionary: dict dictionary from preprocessor dict_specifier: string The following are available model levels 'LIF' (GLIF1) 'LIF_R' (GLIF2) 'LIF_ASC' (GLIF3) 'LIF_R_ASC' (GLIF_4) 'LIF_R_ASC_AT' (GLIF_5) neuron_type: string 'simple_neuron' is the only available option however here would be a good place for the user to implement their own configurations. Returns ------- output_dict: dict dictionary containing model configuration ''' output_dict={'El_reference':dictionary['El']['El_noise']['measured']['mean'], 'El':0., 'dt':dictionary['dt_used_for_preprocessor_calculations'], 'spike_cut_length':dictionary['spike_cutting']['NOdeltaV']['cut_length'], 'spike_cutting_intercept':dictionary['spike_cutting']['NOdeltaV']['intercept'], 'spike_cutting_slope':dictionary['spike_cutting']['NOdeltaV']['slope'], 'asc_amp_array':dictionary['asc']['amp'], 'asc_tau_array':(1./np.array(dictionary['asc']['k'])).tolist(), 'th_inf': dictionary['th_inf']['via_Vmeasure']['from_zero'], 'deltaV': None, 'threshold_adaptation': {'a_spike_component_of_threshold': dictionary['threshold_adaptation']['a_spike_component_of_threshold'], 'b_spike_component_of_threshold':dictionary['threshold_adaptation']['b_spike_component_of_threshold'], 'a_voltage_component_of_threshold':dictionary['threshold_adaptation']['a_voltage_comp_of_thr_from_fitab'], 'b_voltage_component_of_threshold': dictionary['threshold_adaptation']['b_voltage_comp_of_thr_from_fitab']}, 'MLIN': dictionary['MLIN'], 'spike_inds': { 'noise1': [ ], 'noise2': [ ] } } # specify specific values different for different levels. Although there is only one neuron # type here, this would be a good place to add other user defined neuron types if neuron_type=='simple_neuron': output_dict['C']=dictionary['capacitance']['C_test_list']['mean'] if dict_specifer in ['LIF', 'LIF_R']: output_dict['R_input']=dictionary['resistance']['R_test_list']['mean'] elif dict_specifer in ['LIF_ASC', 'LIF_R_ASC', 'LIF_R_ASC_AT']: output_dict['R_input']=dictionary['resistance']['R_fit_ASC_and_R']['mean'] for k,v in dictionary['sweep_properties']['noise1'].items(): output_dict['spike_inds']['noise1'].append( v['spike_ind'] ) output_dict['spike_inds']['noise2'].append( v['spike_ind'] ) return output_dict
[docs] def validate_method_requirements(method_config_name, has_mss): '''Confirm that the neuron has the specific sweeps required for the specified configuration Parameters ---------- method_config_name: string Specifies the model level. Options are: 'LIF' (GLIF1) 'LIF_R' (GLIF2) 'LIF_ASC' (GLIF3) 'LIF_R_ASC' (GLIF_4) 'LIF_R_ASC_AT' (GLIF_5) has_mss: boolean Specifies if the neuron has a multi short square sweep (for fitting spike component of threshold). ''' if not has_mss: valid_configs = ['LIF', 'LIF_ASC'] else: valid_configs = ['LIF', 'LIF_ASC','LIF_R', 'LIF_R_ASC', 'LIF_R_ASC_AT'] if method_config_name not in valid_configs: raise ModelConfigurationException("Model type %s cannot be configured due to missing data (mss: %s)" % ( method_config_name, str(has_mss)))
[docs] def update_neuron_method(method_type, arg_method_name, neuron_config): #TODO: documentation neuron_config[method_type] = { 'name': arg_method_name, 'params': None }
[docs] def configure_model(method_config, preprocessor_values): '''Configures the model from the specified method configuration and preprocessor values. Parameters ---------- method_config: dictionary contains values needed to configure the methods for the specified level within the dictionary preprocessor_values: dictionary dictionary from preprocessor ''' preprocessor_values = specify_parameter_groups(preprocessor_values, method_config['name'], 'simple_neuron') neuron_config = {} neuron_config.update(DEFAULT_NEURON_PARAMETERS) optimizer_config = {} optimizer_config.update(DEFAULT_OPTIMIZER_PARAMETERS) #a) select values want to use out of the preprocessor_values via specifying parameter_gropus #b) look what levels are available via the levels available in the preprocessor_values. # Skip trace if subthreshold noise has a spike in it. noise1_ind = [ n1i for n1i in preprocessor_values['spike_inds']['noise1'] if n1i is not None ] noise1_ind = np.concatenate(noise1_ind) if np.any(noise1_ind * preprocessor_values['dt'] < 8.0): raise ModelConfigurationException("Subthreshold region of noise1 stimulus contains spikes.") # check if there is a short square triple if preprocessor_values['threshold_adaptation']['b_spike_component_of_threshold'] and preprocessor_values['threshold_adaptation']['a_spike_component_of_threshold']: has_mss=True else: has_mss=False # make sure that the requested method config meets minimum requirements validate_method_requirements(method_config['name'], has_mss) update_neuron_method('AScurrent_dynamics_method', method_config['AScurrent_dynamics_method'], neuron_config) update_neuron_method('voltage_dynamics_method', method_config['voltage_dynamics_method'], neuron_config) update_neuron_method('threshold_dynamics_method', method_config['threshold_dynamics_method'], neuron_config) update_neuron_method('AScurrent_reset_method', method_config['AScurrent_reset_method'], neuron_config) update_neuron_method('voltage_reset_method', method_config['voltage_reset_method'], neuron_config) update_neuron_method('threshold_reset_method', method_config['threshold_reset_method'], neuron_config) neuron_config['El_reference'] = preprocessor_values['El_reference'] neuron_config['C'] = preprocessor_values['C'] neuron_config['El'] = preprocessor_values['El'] neuron_config['spike_cut_length'] = preprocessor_values['spike_cut_length'] neuron_config['asc_amp_array'] = preprocessor_values['asc_amp_array'] neuron_config['asc_tau_array'] = preprocessor_values['asc_tau_array'] neuron_config['R_input'] = preprocessor_values['R_input'] neuron_config['th_inf'] = preprocessor_values['th_inf'] optimizer_config['error_function'] = method_config['error_function'] optimizer_config['param_fit_names'] = method_config['param_fit_names'] #b) choose the sets want from the preprocessor_values configure_method_parameters(neuron_config, optimizer_config, preprocessor_values['spike_cutting_slope'], preprocessor_values['spike_cutting_intercept'], preprocessor_values['threshold_adaptation']['a_spike_component_of_threshold'], preprocessor_values['threshold_adaptation']['b_spike_component_of_threshold'], preprocessor_values['threshold_adaptation']['a_voltage_component_of_threshold'], preprocessor_values['threshold_adaptation']['b_voltage_component_of_threshold'], preprocessor_values['MLIN']['var_of_section'], preprocessor_values['MLIN']['sv_for_expsymm'], preprocessor_values['MLIN']['tau_from_AC']) return { 'neuron': neuron_config, 'optimizer': optimizer_config }
[docs] def configure_method_parameters(neuron_config, optimizer_config, v_reset_slope, v_reset_intercept, a_spike_component_of_threshold, b_spike_component_of_threshold, a_voltage_component_of_threshold, b_voltage_component_of_threshold, var_of_section, sv_for_expsymm, tau_from_AC): '''Configures the methods used to run the models Parameters ---------- neuron_config: dict contains neuron parameters optimizer_config: dict contains parameters for optimizaton v_reset_slope: float slope of the line in voltage reset v_reset_intercept: float intercept of the line in voltage reset a_spike_component_of_threshold: float or None amplitude of spike component of the threshold b_spike_component_of_threshold: float or None time course of spike component of the threshold a_voltage_component_of_threshold: float or None a parameter in voltage component of threshold b_voltage_component_of_threshold: float or None b parameter in voltage component of threshold var_of_section: float variance in noise of highest amplitude subthreshold long square pulse sv_for_expsymm: float parameter in MLIN optimization tau_from_AC: float time course of exponential fit to the autocorrelation ''' # configure voltage reset rules method_config = neuron_config['voltage_reset_method'] if method_config.get('params', None) is None: if method_config['name'] == 'zero': method_config['params'] = {} elif method_config['name'] == 'v_before': method_config['params'] = { 'a': v_reset_slope, 'b': v_reset_intercept } elif method_config['name'] == 'i_v_before': method_config['params'] = { 'a': 1, 'b': 2, 'c': 3 } raise ModelConfigurationException('i_v_before of voltage reset method is not yet implemented') elif method_config['name'] == 'fixed': raise ModelConfigurationException('cannot use fixed voltage reset method in preprocessor') else: method_config['params'] = {} # configure threshold reset rules method_config = neuron_config['threshold_reset_method'] if method_config.get('params', None) is None: coeff_th_inf = neuron_config.get('coeffs', {}).get('th_inf',1.0) adjusted_th_inf = neuron_config['th_inf'] * coeff_th_inf if method_config['name'] == 'max_v_th': raise ModelConfigurationException('max_v_th threshold reset rule is not currently in use') elif method_config['name'] == 'th_before': raise ModelConfigurationException('th_before is not currently in use') elif method_config['name'] == 'inf': method_config['params'] = {} neuron_config['init_threshold'] = adjusted_th_inf elif method_config['name'] == 'three_components': method_config['params'] = { 'a_spike': a_spike_component_of_threshold, 'b_spike': b_spike_component_of_threshold } neuron_config['init_threshold'] = adjusted_th_inf elif method_config['name'] == 'fixed': raise ModelConfigurationException("cannot use fixed threshold reset method in preprocessor") else: raise ModelConfigurationException("unknown threshold reset method: ", method_config['name']) # configure voltage dynamics rules method_config = neuron_config['voltage_dynamics_method'] if method_config.get('params', None) is None: if method_config['name'] == 'quadratic_i_of_v': raise ModelConfigurationException('quadraticIofV of voltage_dynamics_method preprocessing is not yet implemented') elif method_config['name'] == 'linear_forward_euler': method_config['params'] = {} elif method_config['name'] == 'linear_exact': method_config['params'] = {} else: raise ModelConfigurationException("unknown voltage dynamics method: ", method_config['name']) # configure threshold dynamics rules method_config = neuron_config['threshold_dynamics_method'] if method_config.get('params', None) is None: if method_config['name'] == 'three_components_forward': method_config['params'] = { 'a_spike': a_spike_component_of_threshold, 'b_spike': b_spike_component_of_threshold, 'a_voltage': a_voltage_component_of_threshold, 'b_voltage': b_voltage_component_of_threshold } elif method_config['name'] == 'three_components_exact': method_config['params'] = { 'a_spike': a_spike_component_of_threshold, 'b_spike': b_spike_component_of_threshold, 'a_voltage': a_voltage_component_of_threshold, 'b_voltage': b_voltage_component_of_threshold } elif method_config['name'] == 'spike_component': method_config['params'] = { 'a_spike': a_spike_component_of_threshold, 'b_spike': b_spike_component_of_threshold, 'a_voltage': 0, 'b_voltage': 0 } elif method_config['name'] == 'inf': method_config['params'] = {} else: raise ModelConfigurationException("unknown threshold dynamics method: ", method_config['name']) # configure ascurrent dynamics rules method_config = neuron_config['AScurrent_dynamics_method'] if method_config.get('params', None) is None: # TODO: rename 'vector' to something more specific if method_config['name'] == 'vector': method_config['params'] = { 'vector': [1, 2, 3] } raise ModelConfigurationException('vector of AScurrent_dynamics_method is not yet implemented') elif method_config['name'] == 'none': method_config['params'] = {} elif method_config['name'] == 'exp': method_config['params'] = {} else: raise ModelConfigurationException("unknown AScurrent dynamics method: ", method_config['name']) # configure ascurrent reset rule # this is down here because it depends on numbers computed for the AScurrent_dynamics_method method_config = neuron_config['AScurrent_reset_method'] if method_config.get('params', None) is None: if method_config['name'] == 'sum': method_config['params'] = { 'r': np.ones(len(neuron_config['asc_tau_array'])) } elif method_config['name'] == 'none': method_config['params'] = {} else: raise ModelConfigurationException("unknown AScurrent reset method: ", method_config['name']) # configure parameters for MLIN optimization if optimizer_config['error_function']=='MLIN': optimizer_config['error_function_data'] = { 'subthreshold_long_square_voltage_variance': var_of_section, 'sv_for_expsymm': sv_for_expsymm, 'tau_from_AC': tau_from_AC } # validation # make sure that the initial ascurrents have the correct size if len(neuron_config['init_AScurrents']) != len(neuron_config['asc_tau_array']): raise ModelConfigurationException("init_AScurrents have incorrect length.") spike_cut_length = neuron_config.get('spike_cut_length', None) if spike_cut_length is None: raise ModelConfigurationException("Spike cut length must be set, but it is not.") if spike_cut_length < 0: raise ModelConfigurationException("Spike cut length must be non-negative.")
[docs] def main(): parser = argparse.ArgumentParser() parser.add_argument('preprocessor_values_path', help='path to preprocessor values json') parser.add_argument('method_config_path', help='path to method configuration json') parser.add_argument('output_path', help='path to store final model configuration') args = parser.parse_args() preprocessor_values = ju.read(args.preprocessor_values_path) method_config = ju.read(args.method_config_path) out_config = configure_model(method_config, preprocessor_values) ju.write(args.output_path, out_config)
if __name__ == "__main__": main()