def getDistance(trace, featureName, mean, std): """Calculate distance value for a list of traces. Parameters ========== trace : trace dicts Trace dict that represents one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' featureName : string Name of the the features for which to calculate the distance mean : float Mean to calculate the distance from std : float Std to scale the distance with Returns ======= distance : float The absolute number of standard deviation the feature is away from the mean. In case of anomalous results a value of '250' standard deviations is returned. This can happen if: a feature generates an error, there are spikes outside of the stimulus interval, the feature returns a NaN, etc. """ _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) return efel.cppcore.getDistance(featureName, mean, std)
def getDistance(trace, featureName, mean, std): """Calculate distance value for a list of traces. Parameters ========== trace : trace dicts Trace dict that represents one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' featureName : string Name of the the features for which to calculate the distance mean : float Mean to calculate the distance from std : float Std to scale the distance with Returns ======= distance : float The absolute number of standard deviation the feature is away from the mean. In case of anomalous results a value of '250' standard deviations is returned. This can happen if: a feature generates an error, there are spikes outside of the stimulus interval, the feature returns a NaN, etc. """ _initialise() # Next set time, voltage and the stimulus start and end for item in trace.keys(): cppcore.setFeatureDouble(item, [x for x in trace[item]]) return efel.cppcore.getDistance(featureName, mean, std)
def _getDistance_cpp( trace, featureName, mean, std, trace_check=None, error_dist=None): """Calculate distance value for a list of traces. Parameters ========== trace : trace dicts Trace dict that represents one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' featureName : string Name of the the features for which to calculate the distance mean : float Mean to calculate the distance from std : float Std to scale the distance with trace_check : float Let the library check if there are spikes outside of stimulus interval error_dist : float Distance returned when error, default is 250 Returns ======= distance : float The absolute number of standard deviation the feature is away from the mean. In case of anomalous results a value of 'error_dist' standard deviations is returned. This can happen if: a feature generates an error, there are spikes outside of the stimulus interval, the feature returns a NaN, etc. """ _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) kwargs = {} kwargs['feature_name'] = featureName kwargs['mean'] = mean kwargs['std'] = std if trace_check is not None: kwargs['trace_check'] = 1 if trace_check else 0 if error_dist is not None: kwargs['error_dist'] = error_dist return efel.cppcore.getDistance(**kwargs)
def _getDistance_cpp(trace, featureName, mean, std, trace_check=None, error_dist=None): """Calculate distance value for a list of traces. Parameters ========== trace : trace dicts Trace dict that represents one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' featureName : string Name of the the features for which to calculate the distance mean : float Mean to calculate the distance from std : float Std to scale the distance with trace_check : float Let the library check if there are spikes outside of stimulus interval error_dist : float Distance returned when error, default is 250 Returns ======= distance : float The absolute number of standard deviation the feature is away from the mean. In case of anomalous results a value of 'error_dist' standard deviations is returned. This can happen if: a feature generates an error, there are spikes outside of the stimulus interval, the feature returns a NaN, etc. """ _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) kwargs = {} kwargs['feature_name'] = featureName kwargs['mean'] = mean kwargs['std'] = std if trace_check is not None: kwargs['trace_check'] = 1 if trace_check else 0 if error_dist is not None: kwargs['error_dist'] = error_dist return efel.cppcore.getDistance(**kwargs)
def _initialise(): """Set cppcore initial values""" cppcore.Initialize(_settings.dependencyfile_path, "log") # First set some settings that are used by the feature extraction for setting_name, int_setting in list(_int_settings.items()): cppcore.setFeatureInt(setting_name, [int_setting]) for setting_name, double_setting in list(_double_settings.items()): cppcore.setFeatureDouble(setting_name, [double_setting])
def _get_feature_values_serial(trace_featurenames): """Single thread of getFeatureValues""" trace, featureNames, raise_warnings = trace_featurenames featureDict = {} if 'stim_start' in trace and 'stim_end' in trace: try: len(trace['stim_start']) len(trace['stim_end']) except: raise Exception('Unable to determine length of stim_start or ' 'stim_end, are you sure these are lists ?') if len(trace['stim_start']) == 1 and len(trace['stim_end']) == 1: if trace['stim_end'][0] <= trace['stim_start'][0]: raise Exception( 'stim_end needs to be larger than ' 'stim_start:\nstim_start=%f stim_end=%f' % (trace['stim_start'][0], trace['stim_end'][0])) else: raise Exception( 'stim_start and stim_end in the trace ' 'dictionary need to be lists of exactly 1 element') else: raise Exception('stim_start or stim_end missing from trace') _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) for featureName in featureNames: cppcoreFeatureValues = list() exitCode = cppcore.getFeature(featureName, cppcoreFeatureValues) if exitCode < 0: if raise_warnings: import warnings warnings.warn( "Error while calculating feature %s: %s" % (featureName, cppcore.getgError()), RuntimeWarning) featureDict[featureName] = None else: featureDict[featureName] = numpy.array(cppcoreFeatureValues) return featureDict
def _get_feature_values_serial(trace_featurenames): """Single thread of getFeatureValues""" trace, featureNames, raise_warnings = trace_featurenames featureDict = {} if 'stim_start' in trace and 'stim_end' in trace: try: len(trace['stim_start']) len(trace['stim_end']) except BaseException: raise Exception('Unable to determine length of stim_start or ' 'stim_end, are you sure these are lists ?') if len(trace['stim_start']) == 1 and len(trace['stim_end']) == 1: if trace['stim_end'][0] <= trace['stim_start'][0]: raise Exception( 'stim_end needs to be larger than ' 'stim_start:\nstim_start=%f stim_end=%f' % (trace['stim_start'][0], trace['stim_end'][0])) else: raise Exception( 'stim_start and stim_end in the trace ' 'dictionary need to be lists of exactly 1 element') else: raise Exception('stim_start or stim_end missing from trace') _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) for featureName in featureNames: featureDict[featureName] = _get_feature( featureName, raise_warnings=raise_warnings) return featureDict
def _get_feature_values_serial(trace_featurenames): """Single thread of getFeatureValues""" trace, featureNames, raise_warnings = trace_featurenames featureDict = {} if 'stim_start' in trace and 'stim_end' in trace: try: len(trace['stim_start']) len(trace['stim_end']) except BaseException: raise Exception('Unable to determine length of stim_start or ' 'stim_end, are you sure these are lists ?') if len(trace['stim_start']) == 1 and len(trace['stim_end']) == 1: if trace['stim_end'][0] <= trace['stim_start'][0]: raise Exception('stim_end needs to be larger than ' 'stim_start:\nstim_start=%f stim_end=%f' % (trace['stim_start'][0], trace['stim_end'][0])) else: raise Exception('stim_start and stim_end in the trace ' 'dictionary need to be lists of exactly 1 element') else: raise Exception('stim_start or stim_end missing from trace') _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) for featureName in featureNames: featureDict[featureName] = _get_feature(featureName, raise_warnings=raise_warnings) return featureDict
def getDistance(trace, featureName, mean, std, trace_check=True, error_dist=250): """Calculate distance value for a list of traces. Parameters ========== trace : trace dicts Trace dict that represents one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' featureName : string Name of the the features for which to calculate the distance mean : float Mean to calculate the distance from std : float Std to scale the distance with trace_check : float Let the library check if there are spikes outside of stimulus interval, default is True error_dist : float Distance returned when error, default is 250 Returns ======= distance : float The absolute number of standard deviation the feature is away from the mean. In case of anomalous results a value of 'error_dist' standard deviations is returned. This can happen if: a feature generates an error, there are spikes outside of the stimulus interval, the feature returns a NaN, etc. """ _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) if trace_check: cppcoreFeatureValues = list() retval = cppcore.getFeature('trace_check', cppcoreFeatureValues) if retval < 0: return error_dist feature_values = _get_feature(featureName) distance = 0 if feature_values is None or len(feature_values) < 1: return error_dist else: # Am not using anything more fancy to avoid breaking exact # reproducibility of legacy C++ code for feature_value in feature_values: distance += abs(feature_value - mean) distance = distance / std / len(feature_values) # Check for NaN if distance != distance: return error_dist return distance
def getFeatureValues(traces, featureNames): """Calculate feature values for a list of traces. This function is the core of the eFEL API. A list of traces (in the form of dictionaries) is passed as argument, together with a list of feature names. The return value consists of a list of dictionaries, one for each input trace. The keys in the dictionaries are the names of the calculated features, the corresponding values are lists with the feature values. Beware that every feature returns an array of values. E.g. AP_amplitude will return a list with the amplitude of every action potential. Parameters ========== traces : list of trace dicts Every trace dict represent one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' feature_names : list of string List with the names of the features to be calculated on all the traces. Returns ======= feature_values : list of dicts For every input trace a feature value dict is return (in the same order). The dict contains the keys of 'feature_names', every key contains a numpy array with the feature values returned by the C++ efel code. The value is None if an error occured during the calculation of the feature. """ featureDicts = [] for trace in traces: featureDict = {} if 'stim_start' in trace and 'stim_end' in trace: if len(trace['stim_start']) == 1 and len(trace['stim_end']) == 1: if trace['stim_end'][0] <= trace['stim_start'][0]: raise Exception( 'stim_end needs to be larger than ' 'stim_start:\nstim_start=%f stim_end=%f' % (trace['stim_start'][0], trace['stim_end'][0])) else: raise Exception('stim_start and stim_end in the trace ' 'dictionary need to be lists of 1 element') else: raise Exception('stim_start or stim_end missing from trace') _initialise() # Next set time, voltage and the stimulus start and end for item in trace.keys(): cppcore.setFeatureDouble(item, [x for x in trace[item]]) for featureName in featureNames: featureType = cppcore.featuretype(featureName) if featureType == "double": cppcoreFeatureValues = list() try: exitCode = cppcore.getFeatureDouble( featureName, cppcoreFeatureValues) except: exitCode = -1 elif featureType == "int": cppcoreFeatureValues = list() exitCode = cppcore.getFeatureInt(featureName, cppcoreFeatureValues) else: print "Feature %s has an unknown type: %s" % \ (featureName, featureType) exit(1) if exitCode < 0: import warnings warnings.warn( "Error while calculating feature %s: %s" % (featureName, cppcore.getgError()), RuntimeWarning) featureDict[featureName] = None else: featureDict[featureName] = numpy.array(cppcoreFeatureValues) featureDicts.append(featureDict) return featureDicts
def _initialise(): """Set cppcore initial values""" cppcore.Initialize(_settings.dependencyfile_path, "log") # First set some settings that are used by the feature extraction cppcore.setFeatureDouble('spike_skipf', [0.1]) cppcore.setFeatureInt('max_spike_skip', [2]) cppcore.setFeatureDouble('Threshold', [_settings.threshold]) cppcore.setFeatureDouble('DerivativeThreshold', [_settings.derivative_threshold]) cppcore.setFeatureDouble('interp_step', [0.1]) cppcore.setFeatureDouble('burst_factor', [1.5]) cppcore.setFeatureDouble("initial_perc", [0.1])
def getFeatureValues(traces, featureNames): """Calculate feature values for a list of traces. This function is the core of the eFEL API. A list of traces (in the form of dictionaries) is passed as argument, together with a list of feature names. The return value consists of a list of dictionaries, one for each input trace. The keys in the dictionaries are the names of the calculated features, the corresponding values are lists with the feature values. Beware that every feature returns an array of values. E.g. AP_amplitude will return a list with the amplitude of every action potential. Parameters ========== traces : list of trace dicts Every trace dict represent one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' feature_names : list of string List with the names of the features to be calculated on all the traces. Returns ======= feature_values : list of dicts For every input trace a feature value dict is return (in the same order). The dict contains the keys of 'feature_names', every key contains a numpy array with the feature values returned by the C++ efel code. The value is None if an error occured during the calculation of the feature. """ featureDicts = [] for trace in traces: featureDict = {} if 'stim_start' in trace and 'stim_end' in trace: try: len(trace['stim_start']) len(trace['stim_end']) except: raise Exception('Unable to determine length of stim_start or ' 'stim_end, are you sure these are lists ?') if len(trace['stim_start']) == 1 and len(trace['stim_end']) == 1: if trace['stim_end'][0] <= trace['stim_start'][0]: raise Exception( 'stim_end needs to be larger than ' 'stim_start:\nstim_start=%f stim_end=%f' % (trace['stim_start'][0], trace['stim_end'][0])) else: raise Exception( 'stim_start and stim_end in the trace ' 'dictionary need to be lists of exactly 1 element') else: raise Exception('stim_start or stim_end missing from trace') _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) for featureName in featureNames: featureType = cppcore.featuretype(featureName) if featureType == "double": cppcoreFeatureValues = list() try: exitCode = cppcore.getFeatureDouble( featureName, cppcoreFeatureValues) except: exitCode = -1 elif featureType == "int": cppcoreFeatureValues = list() exitCode = cppcore.getFeatureInt( featureName, cppcoreFeatureValues) elif featureType == "": raise TypeError("Feature %s has no type " "(does it exist ?): %s" % (featureName, featureType)) else: raise TypeError("Feature %s has an unknown type: %s" % (featureName, featureType)) if exitCode < 0: import warnings warnings.warn( "Error while calculating feature %s: %s" % (featureName, cppcore.getgError()), RuntimeWarning) featureDict[featureName] = None else: featureDict[featureName] = numpy.array(cppcoreFeatureValues) featureDicts.append(featureDict) return featureDicts
def getDistance( trace, featureName, mean, std, trace_check=True, error_dist=250): """Calculate distance value for a list of traces. Parameters ========== trace : trace dicts Trace dict that represents one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' featureName : string Name of the the features for which to calculate the distance mean : float Mean to calculate the distance from std : float Std to scale the distance with trace_check : float Let the library check if there are spikes outside of stimulus interval, default is True error_dist : float Distance returned when error, default is 250 Returns ======= distance : float The absolute number of standard deviation the feature is away from the mean. In case of anomalous results a value of 'error_dist' standard deviations is returned. This can happen if: a feature generates an error, there are spikes outside of the stimulus interval, the feature returns a NaN, etc. """ _initialise() # Next set time, voltage and the stimulus start and end for item in list(trace.keys()): cppcore.setFeatureDouble(item, [x for x in trace[item]]) if trace_check: cppcoreFeatureValues = list() retval = cppcore.getFeature('trace_check', cppcoreFeatureValues) if retval < 0: return error_dist feature_values = _get_feature(featureName) distance = 0 if feature_values is None or len(feature_values) < 1: return error_dist else: # Am not using anything more fancy to avoid breaking exact # reproducibility of legacy C++ code for feature_value in feature_values: distance += abs(feature_value - mean) distance = distance / std / len(feature_values) # Check for NaN if distance != distance: return error_dist return distance
def getFeatureValues(traces, featureNames): """Calculate feature values for a list of traces. This function is the core of the eFEL API. A list of traces (in the form of dictionaries) is passed as argument, together with a list of feature names. The return value consists of a list of dictionaries, one for each input trace. The keys in the dictionaries are the names of the calculated features, the corresponding values are lists with the feature values. Beware that every feature returns an array of values. E.g. AP_amplitude will return a list with the amplitude of every action potential. Parameters ========== traces : list of trace dicts Every trace dict represent one trace. The dict should have the following keys: 'T', 'V', 'stim_start', 'stim_end' feature_names : list of string List with the names of the features to be calculated on all the traces. Returns ======= feature_values : list of dicts For every input trace a feature value dict is return (in the same order). The dict contains the keys of 'feature_names', every key contains a numpy array with the feature values returned by the C++ efel code. The value is None if an error occured during the calculation of the feature. """ featureDicts = [] for trace in traces: featureDict = {} if 'stim_start' in trace and 'stim_end' in trace: if len(trace['stim_start']) == 1 and len(trace['stim_end']) == 1: if trace['stim_end'][0] <= trace['stim_start'][0]: raise Exception( 'stim_end needs to be larger than ' 'stim_start:\nstim_start=%f stim_end=%f' % (trace['stim_start'][0], trace['stim_end'][0])) else: raise Exception('stim_start and stim_end in the trace ' 'dictionary need to be lists of 1 element') else: raise Exception('stim_start or stim_end missing from trace') cppcore.Initialize(_settings.dependencyfile_path, "log") # First set some settings that are used by the feature extraction cppcore.setFeatureDouble('spike_skipf', [0.1]) cppcore.setFeatureInt('max_spike_skip', [2]) cppcore.setFeatureDouble('Threshold', [_settings.threshold]) cppcore.setFeatureDouble('DerivativeThreshold', [_settings.derivative_threshold]) cppcore.setFeatureDouble('interp_step', [0.1]) cppcore.setFeatureDouble('burst_factor', [1.5]) cppcore.setFeatureDouble("initial_perc", [0.1]) # Next set time, voltage and the stimulus start and end for item in trace.keys(): cppcore.setFeatureDouble(item, [x for x in trace[item]]) for featureName in featureNames: featureType = cppcore.featuretype(featureName) if featureType == "double": cppcoreFeatureValues = list() try: exitCode = cppcore.getFeatureDouble( featureName, cppcoreFeatureValues) except: exitCode = -1 elif featureType == "int": cppcoreFeatureValues = list() exitCode = cppcore.getFeatureInt( featureName, cppcoreFeatureValues) else: print "Feature %s has an unknown type: %s" % \ (featureName, featureType) exit(1) if exitCode < 0: import warnings warnings.warn( "Error while calculating feature %s: %s" % (featureName, cppcore.getgError()), RuntimeWarning) featureDict[featureName] = None else: featureDict[featureName] = numpy.array(cppcoreFeatureValues) featureDicts.append(featureDict) return featureDicts