Implementation
Core classes
- class model(peq, p0, D, fr, params_size, grid, peq_model=None, p0_model=None, fr_model=None, with_cuda=False)
Model class supports one or multiple Langevin dynamics defined by peq(x), p0(x), D, fr(x). For multiple dynamics, some of the parameters can be shared which is defined by params_size dictionary. For example, if we want to model 4 conditions, we might want a model with four Langevin dynamics.
- Parameters:
- peqnumpy array, (num_models, grid.N)
peq function evaluated on a grid.
- p0numpy array, (num_models, grid.N) or None
p0 function evaluated on a grid. If set to None, assume equilibirum model.
- Dnumpy array, (num_models,)
Diffusion, or noise magnitude.
- frnumpy array, (num_models, grid.N, num_neuron)
Firing rate function for each neuron.
- params_sizedict
Number of distinct functions in the model. For each of the parameters (peq, p0, D, fr), it specifies whether the parameter is shared across the dynamics (in which case the value is 1), or non-shared (in which case the value is equal to num_models). For example, if there are 4 Langevin dynamics with distinct potentials, but shared p0, D, and fr, then params_size = {‘peq’: 4, ‘p0’: 1, ‘D’: 1, ‘fr’: 1}.
- gridgrid.GLLgrid object
Initialized GLL grid. Should be initiatialized with with_cuda=True for GPU support.
- peq_modeldict, optional
Specify peq model that was used to initialize peq. This is only needed to keep a record. The default is None.
- p0_modeldict, optional
Specify p0 model that was used to initialize p0. This is only needed to keep a record. The default is None.
- fr_modellist, optional
For each neuron this specifies a fr model. This is only needed to keep a record (and also can be used for data generation). The default is None.
- with_cudabool, optional
Whether to include GPU support. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is False.
Methods
FeatureComplexity([model, model_num, ...])Calculate feature complexity
FeatureComplexityFderiv(peq[, device])Calculate variational derivative of equilirium model complexity w.r.t.
Fr_from_fr(fr[, device])Calculates Fr (an auxiliary function for tuning function optimization) from fr (tuning function)
compute_rho0(p0, peq[, device, min_peq])Compute rho0 from p0 and peq
force_from_peq(peq[, device])Calculates driving force F from peq
fr_from_Fr(Fr[, C, device])Calculates fr (tuning function) from Fr (an auxiliary function for tuning function optimization) and C (a scaling constant)
Extract firing rate function
get_params(model_num[, device])Extract peq, p0, D, fr
get_params_for_grad(model_num[, device])Extract peq, rho0, D, fr
new_model(peq_model, p0_model, D, fr_model, grid)Initialize a model
peq_from_force(F[, device])Calculates normalized peq from a given driving Force
sync_model([mode])Sync GPU and CPU by coping a model over.
- FeatureComplexity(model=None, model_num=0, pde_solver=None, device='CPU')
Calculate feature complexity
- FeatureComplexityFderiv(peq, device='CPU')
Calculate variational derivative of equilirium model complexity w.r.t. force F. Used in Genkin, Engel 2020 for regularization.
- Fr_from_fr(fr, device=None)
Calculates Fr (an auxiliary function for tuning function optimization) from fr (tuning function)
- Parameters:
- frnumpy array
An array that represents tuning function f(x).
- Returns:
- Frnumpy array
An array that represents an auxiliary function Fr(x) for tuning function optimization.
- compute_rho0(p0, peq, device='CPU', min_peq=1e-20)
Compute rho0 from p0 and peq
- Parameters:
- p0numpy array
p0(x) distribution.
- peqnumpy array
peq distribution.
- devicestr, optional
“CPU” or “GPU”. The default is None, which is “CPU”.
- min_peqfloat, optional
Min peq to avoid division by zero. The default is 10**-20.
- Returns:
- rho0numpy array
rho0 distribution.
- force_from_peq(peq, device=None)
Calculates driving force F from peq
- Parameters:
- peqnumpy array
peq.
- Returns:
- Fnumpy array
Driving force.
- fr_from_Fr(Fr, C=1, device=None)
Calculates fr (tuning function) from Fr (an auxiliary function for tuning function optimization) and C (a scaling constant)
- Parameters:
- Frnumpy array
Fr reprsented on the grid.
- Cfloat, optional
Constant C. The default is 1.
- devicestr, optional
“CPU” or “GPU”. The default is None, which is CPU.
- Returns:
- numpy array
Tuning function fr.
- get_fr_lambda()
Extract firing rate function
- get_params(model_num, device='CPU')
Extract peq, p0, D, fr
- get_params_for_grad(model_num, device='CPU')
Extract peq, rho0, D, fr
- classmethod new_model(peq_model, p0_model, D, fr_model, grid, params_size=None, with_cuda=False)
Initialize a model
- Parameters:
- peq_modelcallable or dict or np.array
peq function. Can be either callable lambda, or dictionary that specify peq from peq_models.py, or an array of peq values evaluated on the grid.
- p0_modelcallable or dict or np.array
p0 function. Can be either callable lambda, or dictionary that specify peq from peq_models.py, or an array of peq values evaluated on the grid.
- Dnp.array or float
Diffusion coefficint. Either an array that contains a value for each of the models, or a float.
- fr_modellist or np.array
Firing rate functions. Either a list of callables/dict (one entry for each neuron), or np.array.
- gridgrid.GLLgrid object
Initialized GLL grid. Should be initiatialized with with_cuda=True for GPU support.
- params_sizedict, optional
Number of distinct functions in the model. For each of the parameters (peq, p0, D, fr), it specifies whether the parameter is shared across the dynamics (in which case the value is 1), or non-shared (in which case the value is equal to num_models). For example, if there are 4 Langevin dynamics with distinct potentials, but shared p0, D, and fr, then params_size = {‘peq’: 4, ‘p0’: 1, ‘D’: 1, ‘fr’: 1}.
- with_cudabool, optional
Whether to include GPU support. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is False.
- Returns:
- model
Initialized model.
- peq_from_force(F, device=None)
Calculates normalized peq from a given driving Force
- Parameters:
- Fnumpy array
Driving force.
- Returns:
- peqnumpy array
peq.
- sync_model(mode='GPU_to_CPU')
Sync GPU and CPU by coping a model over.
- class GLLgrid(xbegin=-1, xend=1, Np=8, Ne=64, with_cuda=False)
Grid class that calculates Gauss-Lobatto-Legendre grid and implements integration and differentiation on the grid.
- Parameters:
- xbeginfloat
The left boundary of the latent state. The default is -1.
- xendfloat
The right boundary of the latent state. The default is 1.
- Npint
The degree of Langrange interpolation polynomial, also the number of grid points at each element. The default is 8.
- Neint
Number of SEM elements. The default is 64.
- with_cudabool, optional
Whether to include GPU support. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is False.
Methods
Differentiate(f[, result, device])Take a derivative of function f
Integrate(f[, result, device])Indefinite integral of a function f using integration matrix.
- Differentiate(f, result=None, device='CPU')
Take a derivative of function f
- Parameters:
- fnumpy array, dtype=float
Function values evaluated on the grid
- resultnumpy array, dtype=float
A container for the results (to avoid additional allocation). If not provided, will return a result. The default is None.
- devicestr, optional
ENUM(‘CPU’, ‘GPU’). The default is ‘CPU’.
- Returns:
- numpy array
If the result is not provided at the input, it will be returned.
- Integrate(f, result=None, device='CPU')
Indefinite integral of a function f using integration matrix.
- Parameters:
- fnumpy array, dtype=float
Function values evaluated on the grid
- resultnumpy array, dtype=float
A container for the results (to avoid additional allocation). If not provided, will return a result. The default is None.
- Returns:
- numpy array
If the result is not provided at the input, it will be returned.
- class SpikeData(data, dformat='ISIs', time_epoch=None, num_neuron=None, with_trial_end=True, with_cuda=False)
A class for storing spike data in an ISI format and also for conversion between spiketimes and ISI formats
- Parameters:
- datanumpy array
Two formats are supported: 1) ISIs format: the data is numpy array of the size (N,2) of type np.ndarray, where each elements is a 1D array. N is the number of trials, and for each trial the first column contains all of the inter spike intervals (ISIs) in seconds, and the second column contains the corresponding neuronal IDs (trial termination, if recorded, is indicated with -1). Neuronal Ids start from zero. ISIs are represented as 1D arrays of floats, and neuronal indices as 1D array of integers.
- data[i][0] - 1D array, ISIs of type float for the trial i.
The last entry can optionally be the time interval between the last spike and trial termination time.
- data[i][1] - 1D array, neuronal IDs of type int64 for the trial
i. The last entry is -1 if the trial termination time is recorded.
- Example: create a data with 3 neurons (id 0,1,2) and two trials.
Trial 0 started at time 0 s and ended at 1.55 s, where neuron 1 spiked at 0.05 s and neuron 2 spikes at 0.55 s. Trial 1 also started at 0 s, ended at 10.05 s, where neuron 0 spiked at 0.05 s, neuron 1 spiked at 3.05 s, and neuron 2 spiked at 1.05 and 6.05 s. ISIs = np.empty((2, 2), dtype=np.ndarray) ISIs[0][0] = np.array([0.05,0.5,1]) ISIs[0][1] = np.array([1,2,-1]) ISIs[1][0] = np.array([0.05,1,2,3,4]) ISIs[1][1] = np.array([0,2,1,2,-1])
2) spiketimes format, where the data is numpy array of size (num_neuron, N) of type object, N is the number of trials. Each of the entries is 1D array that specify spiketimes of each neuron on each trial. In this case time_epoch array specify each trial start and end times. For the example above, the spiketimes format would be the following:
- spiketimes = np.array(
- [
[np.array([], dtype=np.float64), np.array([0.05])], [np.array([0.05]), np.array([3.05])], [np.array([0.55]), np.array([1.05, 6.05])] ],
dtype=object )
timeepoch = [(0, 1.55), (0, 10.05)]
- dformatstr, optional
ENUM(‘spiketimes’, ‘ISIs’). The default is ‘ISIs’.
- time_epochlist, optional
For each trial, specify trial start time and trial end time as a tuple. Only needed for spiketimes format. The default is None.
- num_neuronint, optional
Number of neurons in the data. If not provided, will be inferred. The default is None.
- with_trial_endbool, optional
Whether trial end time is recorded. The default is True.
- with_cudabool, optional
Whether to include GPU support. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is False.
Methods
change_format(new_format[, record_trial_end])Convert the data between spiketimes and ISIs format.
to_GPU()Copy data to GPU memory.
transform_isis_to_spikes(data)Convert ISIs to spikes
transform_spikes_to_isi(spikes, time_epoch)Convert spike times to ISI format, which is a suitable format for optimization.
For each neuron, compute trial-average firing rate.
- change_format(new_format, record_trial_end=True)
Convert the data between spiketimes and ISIs format.
- Parameters:
- new_formatstr
ENUM(‘spiketimes’, ‘ISIs’).
- record_trial_endbool, optional
Whether to record trial end time in ISIs format. The default is True.
- to_GPU()
Copy data to GPU memory.
- static transform_isis_to_spikes(data)
Convert ISIs to spikes
- static transform_spikes_to_isi(spikes, time_epoch, record_trial_end=True)
Convert spike times to ISI format, which is a suitable format for optimization.
- trial_average_fr()
For each neuron, compute trial-average firing rate. This is needed to scale the initial guess of the firing rate function to match the average spike rate in the data.
Optimization routines
- class Optimization(dataTR, init_model, optimizer_name, opt_options, line_search_options={}, pde_solve_params={}, boundary_mode='absorbing', save_options={}, dataCV=None, device='CPU')
- Parameters:
- dataTRlist
List that contains neuralflow.spike_data.SpikeData object for each datasample in the data. For each datasample a separate model will be trained, however, it is allowed to have shared parameters across datasamples (e.g. allow different potentials but the same D, p0, and fr). Usually the number of datasamples is the number of conditions in the experimental data.
- init_modelneuralflow.model.model
A model object. model.num_models should be equal to number of data samples.
- optimizer_namestr
ENUM(‘ADAM’, ‘GD’).
- opt_optionsdict
Optimization options (see init method of each of the optimizers).
- line_search_optionsdict, optional
Line search options. The default is {}.
- pde_solve_paramsdict, optional
Parameters for solving FPE. The default is {}.
- boundary_modestr, optional
‘absorbing’ or ‘reflecting’. The default is ‘absorbing’.
- save_optionsdict, optional
Options for saving the results. The default is {}.
- dataCVlist, optional
Validation data. The default is None.
- devicestr, optional
‘CPU’ or ‘GPU’. The default is ‘CPU’.
Methods
compute_tr_loglik(cur_samp, epoch)Compute training negative loglik
compute_val_loglik(cur_samp, epoch)Compute validation negative loglik
line_search_score_C(dataTR, model, ...)Line search function for optimization
line_search_score_D(dataTR, model, ...)Line search function for optimization
Optimize the model on the data Inputs are defined at initialization, see __init__ docstring.
- compute_tr_loglik(cur_samp, epoch)
Compute training negative loglik
- compute_val_loglik(cur_samp, epoch)
Compute validation negative loglik
- line_search_score_C(dataTR, model, model_num, fr, param_num, chi)
Line search function for optimization
- line_search_score_D(dataTR, model, model_num, D, param_num, chi)
Line search function for optimization
- run_optimization()
Optimize the model on the data Inputs are defined at initialization, see __init__ docstring.
- Returns:
- None.
- class adam_opt(dataTR, init_model, opt_options, line_search_options={}, pde_solve_params={}, boundary_mode='absorbing', save_options={}, dataCV=None, device='CPU')
ADAM optimizer
Methods
get_dataCV(nsample)Return nsample sample of validation data
get_dataTR(nsample)Return nsample sample of training data
initialize(dataTR, init_model, opt_options, ...)Initialize ADAM optimizer
- classmethod initialize(dataTR, init_model, opt_options, line_search_options, pde_solve_params={}, boundary_mode='absorbing', save_options={}, dataCV=None, device='CPU')
Initialize ADAM optimizer
- Parameters:
- dataTRlist
List that contains neuralflow.spike_data.SpikeData object for each datasample in the data. For each datasample a separate model will be trained, however, it is allowed to have shared parameters across datasamples (e.g. allow different potentials but the same D, p0, and fr). Usually the number of datasamples is the number of conditions in the experimental data.
- init_modelneuralflow.model.model
A model object. model.num_models should be equal to number of data samples.
- opt_optionsdict
- Optimization options dictionary:
- learning_ratedict
- ADAM learning rates:
alpha : the main ADAM learning rate. beta1 : ADAM weight for momentum. The default is 0.9. beta2 : ADAM weight for RMS prop. The default is 0.99. epsilon : ADAM epsilon. The default is 10**-8.
- max_epochsint
Maximum number of optimization epochs. The default is 100.
- mini_batch_numberint
Number of minibatches. On each epoch ADAM will update the model by iterating through each of the minibatches. Thus, the number of iterations per each epoch is equal to the product of number of data samples and mini_batch_number. Sometimes we cannot achieve the desired number of minibatches, in which case the actual number of minibatches will be smaller than mini_batch_number.
- params_to_optlist
The parameters that will be optimized. The default is [‘F’, ‘F0’, ‘D’, ‘Fr’, ‘C’].
- etaffloat
Regularization strength for potenial. Was used in 2020 paper. The default is zero.
- line_search_optionsdict
- Line search options dictionary:
- C_optdictionary
- Options for line search of C:
- max_fun_evalint
Maximum number of function evaluation passed to scipy.optimize.minimize. The default is 3.
- epoch_schedulenumpy array, dtype = int
Epochs on which line search will be performed. The default is np.array([]).
- nSearchPerEpochint
Number of line searches per epoch. The default is 1.
- D_opt: dictionary.
Options for line search of D. Same entries as in C_opt.
- pde_solve_paramsdict
Parameters for solveing FP equation. By default these will be inherited from model.grid. Only provide if some unusual option is needed, e.g. using some unusual boundary conditions. Possible parameters:
- xbeginfloat
The left boundary of the latent state. The default is -1.
- xendfloat
The right boundary of the latent state. The default is 1.
- Npint
The degree of Langrange interpolation polynomial, also the number of grid points at each element. The default is 8.
- Neint
Number of SEM elements. The default is 64.
- BoundConddict
Boundary conditions. Only include if you want to enforce unusual boundary conditions. Otherwise, use boundary_mode to specify boundary conditions.
- Nvint, optional
Number of retained eigenvalues and eigenvectors of the operator H. If set to None, will be equal to grid.N-2, which is the maximum possible value. If Dirichlet BCs are used, it is stongly recommended to set this to None to avoid spurious high-freq oscillations in the fitted functions. The default is None.
- boundary_modestr
Boundary mode, can be either absorbing or reflecting. The default is ‘absorbing’.
- save_optionsdict
- Options for saving the results:
- pathstr
Local path for saving intermediate results. The default is None, in which case nothing will be saved (the results will only be in RAM).
- strideint
Save intermediate files every stride number of epochs. The default is max_iteration (only save the final file).
- schedulenumpy array, dtype=int
1D array with epoch numbers on which the fitted models (peq, D, p0, fr) are saved to RAM. The default is np.arange(1-new_sim, max_iteration+1), which includes all of the epochs.
- sim_startint
Starting epoch number (0 if new simulation, otherwise int > 0). The default is 0. Don’t change as loading the intermediate results and continuing optimization is not supported yet.
- dataCVlist or None
List that contains neuralflow.spike_data.SpikeData object for each datasample in the data. If not provided, validation loglik will not be calculated. The default is None.
- devicestr
Can be ‘CPU’ or ‘GPU’. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is ‘CPU’.
- Returns:
- self
Initialized optimizer object.
- class gd_opt(dataTR, init_model, opt_options, line_search_options={}, pde_solve_params={}, boundary_mode='absorbing', save_options={}, dataCV=None, device='CPU')
Gradient-descent optimizer
Methods
get_dataCV(nsample)Return nsample sample of validation data
get_dataTR(nsample)Return nsample sample of training data
initialize(dataTR, init_model, opt_options, ...)Initialize GD optimizer
- classmethod initialize(dataTR, init_model, opt_options, line_search_options, pde_solve_params={}, boundary_mode='absorbing', save_options={}, dataCV=None, device='CPU')
Initialize GD optimizer
- Parameters:
- dataTRlist
List that contains neuralflow.spike_data.SpikeData object for each datasample in the data. For each datasample a separate model will be trained, however, it is allowed to have shared parameters across datasamples (e.g. allow different potentials but the same D, p0, and fr). Usually the number of datasamples is the number of conditions in the experimental data.
- init_modelneuralflow.model.model
A model object. model.num_models should be equal to number of data samples.
- opt_optionsdict
- Optimization options dictionary:
- learning_ratedict
Keys are each of the parameters to be optimized, and values are the learning rates, e.g. {‘F’: 0.01, ‘F0’: 0.02}.
- max_epochsint
Maximum number of optimization epochs. The default is 100.
- mini_batch_numberint
Number of minibatches. On each epoch ADAM will update the model by iterating through each of the minibatches. Thus, the number of iterations per each epoch is equal to the product of number of data samples and mini_batch_number.
- params_to_optlist
The parameters that will be optimized. The default is [‘F’, ‘F0’, ‘D’, ‘Fr’, ‘C’].
- etaffloat
Regularization strength for potenial. The default is zero.
- line_search_optionsdict
- Line search options dictionary:
- C_optdictionary
- Options for line search of C:
- max_fun_evalint
Maximum number of function evaluation passed to scipy.optimize.minimize. The default is 3.
- epoch_schedulenumpy array, dtype = int
Epochs on which line search will be performed. The default is np.array([]).
- nSearchPerEpochint
Number of line searches per epoch. The default is 1.
- D_opt: dictionary.
Options for line search of D. Same entries as in C_opt.
- pde_solve_paramsdict
Parameters for solveing FP equation. By default these will be inherited from model.grid. Only provide if some unusual option is needed, e.g. using some unusual boundary conditions. Possible parameters:
- xbeginfloat
The left boundary of the latent state. The default is -1.
- xendfloat
The right boundary of the latent state. The default is 1.
- Npint
The degree of Langrange interpolation polynomial, also the number of grid points at each element. The default is 8.
- Neint
Number of SEM elements. The default is 64.
- BoundConddict
Boundary conditions. Only include if you want to enforce unusual boundary conditions. Otherwise, use boundary_mode to specify boundary conditions.
- Nvint, optional
Number of retained eigenvalues and eigenvectors of the operator H. If set to None, will be equal to grid.N-2, which is the maximum possible value. If Dirichlet BCs are used, it is stongly recommended to set this to None to avoid spurious high-freq oscillations in the fitted functions. The default is None.
- boundary_modestr
Boundary mode, can be either absorbing or reflecting. The default is ‘absorbing’.
- save_optionsdict
- Options for saving the results:
- pathstr
Local path for saving intermediate results. The default is None, in which case nothing will be saved (the results will only be in RAM).
- strideint
Save intermediate files every stride number of epochs. The default is max_iteration (only save the final file).
- schedulenumpy array, dtype=int
1D array with epoch numbers on which the fitted models (peq, D, p0, fr) are saved to RAM. The default is np.arange(1-new_sim, max_iteration+1), which includes all of the epochs.
- sim_startint
Starting epoch number (0 if new simulation, otherwise int > 0). The default is 0. Don’t change as loading the intermediate results and continuing optimization is not supported yet.
- dataCVlist or None
List that contains neuralflow.spike_data.SpikeData object for each datasample in the data. If not provided, validation loglik will not be calculated. The default is None.
- devicestr
Can be ‘CPU’ or ‘GPU’. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is ‘CPU’.
- class Grads(pde_solve_params, boundary_mode='absorbing', grad_list=[], num_neuron=1, with_trial_end=True, device='CPU')
Grad class for loglikelihoods and gradient calculations.
- Parameters:
- pde_solve_paramsdict
- Parameters for solveing FP equation:
- xbeginfloat
The left boundary of the latent state. The default is -1.
- xendfloat
The right boundary of the latent state. The default is 1.
- Npint
The degree of Langrange interpolation polynomial, also the number of grid points at each element. The default is 8.
- Neint
Number of SEM elements. The default is 64.
- BoundConddict
Boundary conditions. Only include if you want to enforce unusual boundary conditions. Otherwise, use boundary_mode to specify boundary conditions.
- boundary_modeENUM(‘absorbing’, ‘reflecting’), optional
Boundary mode. The default is ‘absorbing’.
- grad_listlist, optional
List of paramters for gradient calculation. Can include ‘F’, ‘F0’, ‘D’, ‘C’, ‘Fr’. The default is [].
- num_neuronint, optional
Number of neurons in the model/data. The default is 1.
- with_trial_endbool, optional
Whether to take into account trial end time. The default is True.
- deviceENUM(‘CPU’, ‘GPU’), optional
Device for the computations. The default is ‘CPU’. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is ‘CPU’.
Methods
get_grad_data(data, model[, model_num, ...])Calculates loglikelihood and/or gradients
- get_grad_data(data, model, model_num=0, mode='loglik', EV_solution=None)
Calculates loglikelihood and/or gradients
- Parameters:
- datadatanumpy array (num_trials, 2), dtype = np.ndarray.
Data in ISI format. See spike_data class for details.
- model: model
An instance of neuralflow.model.
- model_numint, optional
Model number to be used. The default is 0.
- modeENUM(‘loglik’, ‘gradient’)
Whether to only compute loglik, or also a gradient.
- EV_solutiondicionary
Dictionary with the solution of the eigenvector-eigenvalue (EV) problem. The format is {‘lQ’: lQ, ‘QxOrig’: QxOrig, ‘Qx’: Qx, ‘lQd’:lQd, ‘Qd’: Qd}. If not provided, will be calculated. The default is None.
- Returns:
- results_alldictionary
Dictionary with the results. Possible entries depends on the grad_list, and can include ‘loglik’, ‘F’, ‘F0’, ‘D’, ‘Fr’, ‘C’.
- class PDESolve(xbegin=-1.0, xend=1.0, Np=8, Ne=64, BoundCond={'leftB': 'Dirichlet', 'rightB': 'Dirichlet'}, Nv=None, with_cuda=False)
Numerical solution of Stourm-Liouville problem and Fokker-Planck.
- Parameters:
- xbeginfloat, optional
The left boundary of the latent state. The default is -1.
- xendfloat
The right boundary of the latent state. The default is 1.
- Npint
The degree of Langrange interpolation polynomial, also the number of grid points at each element. The default is 8.
- Neint
Number of SEM elements. The default is 64.
- BoundConddict
A dictionary that specifies boundary conditions (Dirichlet, Neumann or Robin). The default is {‘leftB’: ‘Dirichlet’,
‘rightB’: ‘Dirichlet’}.
In case of Robin, the dictionary must also contain ‘leftBCoeff’ and/or ‘rightBCoeff’, each are dictionaries with two entries ‘c1’ and ‘c2’ that specify BCs coefficients in the following format: c1*y[xbegin]+c2*y’[xbegin]=0 (left boundary) c1*y[xend]+c2*y’[xend]=0 (right boundary)
- Nvint, optional
Number of retained eigenvalues and eigenvectors of the operator H. If set to None, will be equal to grid.N-2, which is the maximum possible value. If Dirichlet BCs are used, it is stongly recommended to set this to None to avoid spurious high-freq oscillations in the fitted functions. The default is None.
- with_cudabool, optional
Whether to include GPU support. For GPU optimization, the platform has to be cuda-enabled, and cupy package has to be installed. The default is False.
Methods
init_from_grid(grid[, boundary_mode, BoundCond])Init from grid object
set_BoundCond(BoundCond)Set new boundary conditions for the Stourm-Liouville probelem
solve_EV([peq, D, q, w, mode, fr, device])Solve the Sturm-Liouville/FP/FPE eigenvalue-eigenvector problem.
- classmethod init_from_grid(grid, boundary_mode=None, BoundCond=None)
Init from grid object
- Parameters:
- gridneuralflow.grid
Grid object.
- boundary_modestr, optional
Absorbing or reflecting. If None, BoundCond will be used for boundary conditions. The default is None.
- BoundConddict
A dictionary that specifies boundary conditions (Dirichlet, Neumann or Robin). The default is {‘leftB’: ‘Dirichlet’,
‘rightB’: ‘Dirichlet’}.
In case of Robin, the dictionary must also contain ‘leftBCoeff’ and/or ‘rightBCoeff’, each are dictionaries with two entries ‘c1’ and ‘c2’ that specify BCs coefficients in the following format: c1*y[xbegin]+c2*y’[xbegin]=0 (left boundary) c1*y[xend]+c2*y’[xend]=0 (right boundary)
- Returns:
- self
Initialized PDESolve object.
- set_BoundCond(BoundCond)
Set new boundary conditions for the Stourm-Liouville probelem
- Parameters:
- BoundConddictionary or str
If str, can be ‘absorbing’ or ‘reflecting’. Alternatively, specify boundary conditions as a dict: keys : ‘leftB’, ‘rightB’, (optionally: ‘leftBCoeff’, ‘rightBCoeff’) values : ‘Dirichlet’ ‘Neumann’ or ‘Robin’. If ‘Robin’, addionally specify coefficients as a dictionary with two keys: [c1,c2], consistent with the boundary condition of the form: c1*y(B)+c2*y’(B)=0. Example: {‘leftB’:’Robin’,’leftBCoeff’:{‘c1’=1, ‘c2’=2},
‘rightB’:’Robin’,’rightBCoeff’:{‘c1’=3, ‘c2’=4}}
- solve_EV(peq=None, D=1, q=None, w=None, mode='hdark', fr=None, device='CPU')
Solve the Sturm-Liouville/FP/FPE eigenvalue-eigenvector problem.
- Parameters:
- peqnumpy array, dtype=float
Equilibirum probabilioty distribution that determines potential Phi(x), or a function p(x) in S-L problem.
- Dfloat
Noise magnitude.
- qnumpy array, dtype=float
A function q(x) in the S-L problem. The default value is None, in this case q(x)=0.
- wnumpy array, dtype=float
A function w(x) in the S-L problem (non-negative). The default is None, in this case w(x)=1.
- modestr
- Specify mode. Availiable modes:
‘normal’: solve Sturm-Liouville problem, ignore D and fr. ‘h0’: solve for eigenvalues and vectors of FP operator H0. ‘hdark’: solve for eigenvalues and vector of FP operator H.
The default is ‘hdark’.
- frnumpy array
The firing rate function (required for ‘hdark’ mode). This firing rate function is an elementwise sum of the firing rate functions of all the neuronal responses. The default is None.
- devicestr
Can be ‘CPU’ or ‘GPU’.
- Returns:
- lQnumpy array (Nv,), dtype=float
The least Nv eigenvalues for the eigenvalue problem of H0 operator.
- QxOrignumpy array (Nv,Nv), dtype=float
The corresponding scaled eigenvectors
- Qxnumpy array (Nv,Nv), dtype=float
The eigenvectors of EV problem of H0 operator (only for ‘h0’ and ‘hdark’ modes).
- lQd: numpy array (Nv,), dtype=float
The eigenvalues of H operator (only for ‘hdark’ mode).
- Qd: numpy array (Nv,Nv), dtype=float
The corresponding eigenvectors in H0 basis (only for ‘hdark’ mode).
Predefined peq models
Template peq functions. Equilibirum probability distribution is related to potential U(x)=-log(peq).
- cos_fourth_power(x, w, xbegin=-1.0, xend=1.0)
Cosine^4 peq model.
- y, L –> peq(y, L) ~ cos( y*pi/L )**2, integral peq(x) dx =1
where y - x centered on the middle of the domain, L - domain length
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- xbegin: float
Left boundary of the x domain. The default is -1.
- xend: float
Right boundary of the x-domain. The default is 1.
- Returns:
- peqnumpy array, dtype=float
Probability density distribution evaluated at grid ponits x.
- cos_square(x, w, xbegin=-1.0, xend=1.0)
Cosine-squareed model.
y, L –> peq(y, L) ~ cos( y*pi/L )**2
integral peq(x) dx =1 y - x centered on the middle of the domain L - domain length
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- xbegin: float
Left boundary of the x domain. The default is -1.
- xend: float
Right boundary of the x-domain. The default is 1.
- Returns:
- peqnumpy array (N,), dtype=float
Probability density distribution evaluated at grid ponits x.
- custom(x, w, lambdafunc=None)
Custom model (for example, for real data fitting).
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- lambdafunc: function or None
Either supply a function, or leave None if the model of the generated data is not known, in which case x and w are ignored.
- Returns:
- peqnumpy array (N,), dtype=float
Probability density distribution evaluated at grid ponits x.
- double_well(x, w, xmax=0, xmin=0.3, depth=4.0, sig=0)
Peq derived from a double-well potential.
peq(x) = exp[ -U(x) ]
y = x - xmax ymin = xmin - xmax
U(y) = depth * (y/ymin)**4 - 2*depth * (y/ymin)**2 +sig*y
integral peq(x) dx =1
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- xmaxfloat
position of the maximum of the potential in the symmetrix case (sig=0)
- xminfloat
position of the two symmetric minima for sig=0 case. The default is 0.
- depthfloat
depth of the potential wells (U_max - U_min) for the symmetric case (sig=0). The default is 4.
- sigfloat
assymetry parameter, to bias one well over another. The default is 0.
- Returns:
- peqnumpy array (N,), dtype=float
Probability density distribution evaluated at grid ponits x.
- linear_pot(x, w, slope=1)
Ramping model derived from a linear potential
V(x)=slope*x peq(x) = exp (-slope*x) / || exp (-slope*x) ||
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- slope: float
Slope of the potential function.
- Returns:
- peqnumpy array, dtype=float
Probability density distribution evaluated at grid ponits x.
- manual(x, w, interp_x=[-1, -0.3, 0, 0.3, 1], interp_y=[0, 10, 5, 10, 0], bc_left=[(1, 0), (1, 0)], bc_right=[(1, 0), (1, 0)], stationary_points=None)
Define arbitrary model by specifiying minima and maxima of the potential
- mixture(x, w, theta=0.5, model1={'model': 'cos_square', 'params': {}}, model2={'model': 'double_well', 'params': {}})
Convex mixture of two models.
peq = theta*peq_model_1 + (1-theta)*peq*model_2
integral peq(x) dx =1
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- thetafloat
convex weight, 0<=theta<=1. The default is 0.5.
- model1dictionary.
Dictionary that contains model name (one of the built-in models) and the corresponding parameters. The default is {‘model’: ‘cos_square’, ‘params’: {}}
- model2dictionary.
Dictionary that contains model name (one of the built-in models) and the corresponding parameters. The default is {‘model’: ‘double_well’, ‘params’: {}}
- Returns:
- peqnumpy array (N,), dtype=float
Probability density distribution evaluated at grid ponits x.
- single_well(x, w, xmin=0, miu=10.0, sig=0)
Peq derived from a single well quadratic potential.
peq(x) = exp[ -U(x) ]
y = x - xmin
U(y) = miu * y**2 + sig*y
integral peq(x) dx =1
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- xminfloat
position of the minimum for sig=0 case. The default is 0.
- miufloat
curvature (steepness) of the potential. The default is 10.
- sigfloat
assymetry parameter, to bias left vs. rights sides of the potential. The default is 0.
- Returns:
- peqnumpy array, dtype=float
Probability density distribution evaluated at grid ponits x.
- stepping(x, w, interp_x=[-1, -0.5, 0, 0.3, 1], interp_y=[0, 4, 0, 1, -1], bc_left=[(1, 0), (1, 0)], bc_right=[(1, 0), (1, 0)])
Stepping model.
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- interp_x: numpy array (5,), dtype=float, or list
The x positions of the boundaries, maixma and minima of the potential, sorted from the left to the right. Contains 5 values: the left boundary, the first maximum, the minimum, the second maximum and the right boundary. The default is [-1, -0.5, 0, 0.3, 1], which corresponds to the stepping potential used in M. Genkin, O. Hughes, T.A. Engel, Nat Commun 12, 5986 (2021).
- interp_y: numpy array (5,), dtype=float, or list
The corresponding y-values of the potential at the points specified by interp_x. The default is [0, 4, 0, 1, -1], which corresponds to the stepping potential used in M. Genkin, O. Hughes, T.A. Engel paper, Nat Commun 12, 5986 (2021).
- bc_left: list
A list that contains two tuples that specify boundary conditions for the potential on the left boundary. The format is the same as in bc_type argument of scipy.interpolate.CubicSpline function. The default is [(1, 0), (1, 0)], which corresponds to a zero-derivative (Neumann) BCs for the potential.
- bc_right: list
Same as bc_left, but for a right boundary. The default is [(1, 0), (1, 0)], which corresponds to a zero-derivative (Neumann) BCs for the potential.
- Returns:
- peqnumpy array, dtype=float
Probability density distribution evaluated at grid ponits x.
- uniform(x, w)
Uniform peq model, derived from a constant potential.
peq = const
integral peq(x) dx =1
- Parameters:
- xnumpy array (N,), dtype=float
Grid points in which the model will be evaluated. N is the number of grid points.
- wnumpy array (N,), dtype=float
Weights used to evaluate integrals by the Gaussian quadrature.
- Returns
- ——-
- peqnumpy array (N,), dtype=float
Probability density distribution evaluated at grid ponits x.
Predefined firing rate models
Template firing rate functions.
- cos_square(x, amp=1000, freq=1.5707963267948966, bias=0)
Cosine-squareed model with a given amplitude and frequency
- Parameters:
- xnumpy array, dtype=float
SEM grid points
- ampfloat
Amplitude. The default is 1000.
- freqfloat
Frequency. The default is np.pi/2.
- biasfloat
Bias. The default is 0.
- Returns:
- numpy array
Firing rate function evaluated on SEM grid
- custom(x, lambdafunc=None)
Custom fr model. Either supply a function, or leave None if the model of the generated data is not known (and define fr manually after).
- Parameters:
- xnumpy array, dtype=float
SEM grid points
- lambdafuncfunction object.
The default is None.
- Returns:
- frnumpy array
Firing rate function evaluated on SEM grid
- linear(x, slope=50.0, bias=2)
Linear firing rate model. r(x, slope, bias) = max[slope * x + bias, 0]
- Parameters:
- xnumpy array, dtype=float
SEM grid points
- slopefloat
Firing-rate slope parameter. The default is 50.0.
- biasfloat
Firing threshold parameter. The default is 2.
- Returns:
- numpy array
Firing rate function evaluated on SEM grid
- peaks(A*exp((x-x0)^2/w^2))
Sum of gaussian peaks f= SUM(A*exp((x-x0)^2/w^2))
- Parameters:
- xnumpy array, dtype=float
SEM grid points
- centernumpy array, dtype=float
Centers of Gaussian peaks. The default is np.array([-0.5,0.5]).
- widthnumpy array, dtype=float
Widths of Gaussian peaks. The default is np.array([0.2,0.3]).
- ampnumpy array, dtype=float
Magnitudes of Gaussian peaks. The default is np.array([100,80]).
- Returns:
- numpy array
Firing rate function evaluated on SEM grid
- rectified_linear(x, slope=50.0, x_thresh=-1.0)
Rectified-linear firing rate model. r(x, slope, thresh) = max[slope*(x - x_thresh), 0]
- Parameters:
- xnumpy array, dtype=float
SEM grid points
- slopefloat
Firing-rate slope parameter. The default is 50.0.
- thresholdfloat
Firing threshold parameter. The default is -1.0.
- Returns:
- numpy array
Firing rate function evaluated on SEM grid
- sinus(x, bias=100, amp=30, freq=3.141592653589793)
Rectified sinusoid
- Parameters:
- xnumpy array, dtype=float
SEM grid points
- biasfloat
Bias. The default is 100.
- ampfloat
Amplitude of the sinusoid. The default is 30.
- freqfloat
Frequency of the sinusoid. The default is np.pi.
- Returns:
- numpy array
Firing rate function evaluated on SEM grid
Feature complexity analysis
- class FC_tools(non_equilibrium, model, terminal_time=1, number_of_timesteps=10, boundary_mode='absorbing')
Feature consistency analysis for model selection
- Parameters:
- non_equilibriumbool
Whether or not the model is non_equilibrium.
- modelneuralflow.model
Model class variable, which is used to extract those parameters that were not optimized. Also used for the integration/differention operations on GLL grid.
- terminal_timefloat, optional
Terminal time for non-equilibrium JS divergence calculation in seconds. Only used for non-equilibrium analysis. Should set to a a typical reaction time for absorbing case. If working with reflective mode, set it to trial duration. Different trial durations for reflecting are not supported. The default is 1.
- number_of_timestepsint, optional
Number of timesteps for non-equilibrium JS divergence calculation. Only used for non-equilibrium analysis. It is recommended to set this equal to ten times terminal_time. The default is 10.
- boundary_modestr, optional
Boundary mode is needed for non-equilibrium analysis, as we need to solve FPE to compute feature complexity and JS divergence. The default is ‘absorbing’.
Methods
FeatureConsistencyAnalysis(data1, data2[, ...])Perform feature consistency analysis
JS_divergence_non_st(peq1, peq2)JS divergence between two distributions peq1 and peq2 that are not normalized.
JS_divergence_st(peq1, peq2[, normalized])JS divergence between two stationary distributions peq1 and peq2.
JS_divergence_timedep(peq1, p01, lQ1, Qx1, ...)Compute JS divergence between two non-stationary Langevin models
NeedToReflect(result1, result2)Find if model2 has to be reflected around the axis y=0.
compute_FC([data, indices, invert])Compute feature complexities for selected models in the data.
moving_average(x, w)Moving average filter
- FeatureConsistencyAnalysis(data1, data2, JS_thres=0.0015, FC_stride=5, smoothing_kernel=0, num_models=10000, epoch_offset=0)
Perform feature consistency analysis
- Parameters:
- data1Dictionary
Dictionary with the fitting results on datasample 1.
- data2Dictionary
Dictionary with the fitting results on datasample 2.
- JS_thresfloat, optional
Threshold JS at which models are considered different. The default is 0.0015.
- FC_strideint, optional
Slack in the second sequence of models. For each Feature complexity calculated from data1, we consider 2*FC_stride + 1 models from data2 and choose the one that minimizes JS. The default is 5.
- smoothing_kernelint, optional
Smooth JS with moving average before thresholding. The default is 0.
- num_modelsint, optional
Number of model on which feature complexities will be computed. The code will pick the models from data1/data2 on logarithmic scale, so that more models on early epochs will be selected. Smaller number can accelerate the code, but can be inaccurate. The default is 10000.
- epoch_offsetint, optional.
Ignore threshold breaks for the first epochs_offset epochs. The optimization speed is usually faster initially, so JS might diverge because of that. The default is 0.
- Returns:
- FCs1numpy array
Feature complexities for data1. Also serves as a “common” feature complexity axis.
- min_inds_1numpy array
Indices of models in data1 for each FC1. To get peq of a model that corresponds to FC1[i], we take data1[‘peq’][min_inds_1[i]].
- FCs2numpy array
Feature complexities for data2.
- min_inds_2numpy array
Indices of models in data2 for each FC2. To get peq of a model that corresponds to FC2[i], we take data2[‘peq’][min_inds_2[i]].
- JSnumpy array
Jensen-Shannon divergence between models from data1 and data2.
- FC_opt_indint
The index of an optimal model in FC1/JS.
- JS_divergence_non_st(peq1, peq2)
JS divergence between two distributions peq1 and peq2 that are not normalized.
- JS_divergence_st(peq1, peq2, normalized=False)
JS divergence between two stationary distributions peq1 and peq2. Note that in 2020 paper a slightly different metric was used: we used symmetrized KL divergence, which is not the same as JS divergence
- JS_divergence_timedep(peq1, p01, lQ1, Qx1, peq2, p02, lQ2, Qx2)
Compute JS divergence between two non-stationary Langevin models
- NeedToReflect(result1, result2)
Find if model2 has to be reflected around the axis y=0.
- compute_FC(data={}, indices=None, invert=False)
Compute feature complexities for selected models in the data.
- Parameters:
- datadictionary, optional
Dictionary with the fitting results. The default is {}.
- indicesarray, optional
Indices of models in data dictionary on which FCs will be computed. If None, will compute FC on all indices. The default is None.
- invertbool, optional
Whether to invert potenial and p0. The default is False.
- Returns:
- FCs_array: numpy array
Evaluated feature complexities.
- lQ_array: numpy array
Eigenvalues of H0 operator needed for further analysis. Only for non-equilibirum mode.
- Qx_array: numpy array
Eigenvectors of H0 operator needed for further analysis. Only for non-equilibirum mode.
- static moving_average(x, w)
Moving average filter
- Parameters:
- xnumpy array
signal.
- wint
Kernel width.
- Returns:
- outnumpy array
Filtered array.
Data generation from Langevin dynamics
- class SyntheticData(model, boundary_mode, dt=0.0001, record_trial_end=True)
Spike data generation from a Langevin model
- Parameters:
- modelmodel
An instance of neuralflow.model.
- boundary_modeENUM(‘absorbing’, ‘reflecting’)
Boundary behavior.
- dtfloat, optional
Time bin size for Langevin ODE integration. The default is 0.0001.
- record_trial_endbool, optional
Whether or not to include trial end. Usually True is the best choice. The default is True.
Methods
generate_data([trial_start, trial_end, ...])Generate spike data and latent trajectories.
Notes
No GPU support. Data generation is usually pretty fast, so CPU is sufficient for this purpose.
- generate_data(trial_start=0, trial_end=1, num_trials=2, model_num=0)
Generate spike data and latent trajectories.
- Parameters:
- trial_startfloat or list, optional
Trial start time. To specify the same trial start time for all trials, provide a single float, or provide a list for each trial. The default is 0.
- trial_endfloat or list, optional
Trial end time. To specify the same trial end time for all trials, provide a single float, or provide a list for each trial. Note that for absorbing boundary mode this serves as a timeout and the actual trial end time can be smaller if the boundary is reached before this time. The default is 1.
- num_trialsint, optional
Number of trials to be generated. The default is 2.
- model_numint, optional
Which model to use for data generation. The default is 0.
- Returns:
- datanumpy array (num_trials, 2), dtype = np.ndarray.
Data in ISI format. See spike_data class for details.
- time_binsnumpy array (num_trials,), dtype = np.ndarray
For each trial contains times at which latent trajectory was recorded. Each entry is 1D numpy array of floats.
- xnumpy array (num_trials,), dtype = np.ndarray
Latent trajectories for each trial. Each entry is 1D array of floats. Same shape as time_bins
Other modules and classes
Viterbi algorithm. Only supported on CPU
- class Viterbi(grad)
Viterbi algorithm
- Parameters:
- gradneuralflow.Grads
Gradient object is needed for solving FPE.
Methods
run_viterbi(data, model[, model_num])Viterbi algorithm Finds the latent path X that maximizes joint probability P(X,Y).
- Returns:
- None.
- run_viterbi(data, model, model_num=0)
Viterbi algorithm Finds the latent path X that maximizes joint probability P(X,Y). The path X is sampled at trial start/trial end time, and at the time of each of spike.
- Parameters:
- dataneuralflow.spike_data.SpikeData.
SpikeData object in ISI format.
- modelneuralflow.model.model
A model object.
- model_nummodel number to be used. The default is 0.
- Returns:
- trajectoriesnumpy array, dtype=np.ndarray
Latent trajectory sampled at spike times for each trial in the data.
- state_indsindeces of trajectory latent states on the gird.