-
Notifications
You must be signed in to change notification settings - Fork 5
Spatial fitting
This wiki page documents spatial fitting of multielectrode data.
Spatial fitting essentially comes down to three parts
- Developing a formula for the power spectrum that takes into account spatial variations in parameter values
- Selecting a useful parametrization of the spatial variations
- Managing and displaying multiple spectra
The formula for the power spectrum given spatial variations was derived by O'Connor and Robinson (2004) and is implemented in the corticothalamic-model
repository as the spatial_spectrum
method. This is documented here and it is highly important to understand the implementation of spatial_spectrum
to then understand how it is used by BrainTrak.
The next step is to select a useful parametrization of the spatial variations. This is also included in the corticothalamic-model
repository, in the form of
a. The variation functions defined in model.params.variation_function()
, which provide various possibilities for spatial variations. The variation functions take in parameters like the amplitude of the variation, and these are the parameter that can be fitted
b. The model.params.apply_variation
method, which passes the parameter into the params
object, creating the appropriate variation function
Just as bt.model.template
is an abstract class for all BrainTrak models, bt.model.template_spatial
is an abstract class for models with spatial variations. The basic concept is that the model stores a params
object. When the objective function is called, the model calls apply_variation
and passes the model parameters into the params
object. Then, params.spatial_spectrum
is called, and the chisq
value can be calculated as usual.
- The model internally stores a
params
object - The model calls
apply_variation' on the
paramsobject, which converts the BrainTrak model parameters into the
params` object representation - The model calls
params.spatial_spectrum
which calculates the spectrum - The model evaluates
chisq
for all of the electrodes
Of the above steps, only (2) changes for different models. Therefore, bt.model.template_spatial
implements all of the other steps. In addition to supplying limits
, get_xyz
, validate_params
etc. (the abstract methods that classes derived from template
must implement), models inheriting from template_spatial
must also implement the set_params
method, which corresponds to (2). For example, consider bt.model.spatial_emg.set_params
:
function set_params(self,pars)
% This function is what decides what the spatial variations are actually going to be
%e.g. p.apply_variation('cosine','t0',pars(10));
self.p.gabcd = pars(1:5);
self.p.alpha(:) = pars(6);
self.p.beta(:) = pars(7);
self.p.t0 = pars(8);
self.p.taues = self.p.t0/2;
self.p.tause = self.p.t0/2;
self.p.emg_a = self.emg_scaling*pars(11);
self.p.apply_variation('t0','cosine_phased',pars(9),pars(10));
self.p.apply_variation('emg','cosine_2d_phased',self.emg_scaling*pars(12),pars(13),self.emg_scaling*pars(14),pars(15));
end
This function accesses self.p
, the internal model.params
instance created by bt.model.template_spatial
, and calls all self.p.apply_variation
. The parameters passed in are from the variable pars
, which is the array of variables in this BrainTrak model.
Since all spatial models compute the spectrum in the same way, the objective
method is implemented by template_spatial
. The critical part is the call to spatial_spectrum
:
[~,~,~,~,~,~,~,P] = self.p.spatial_spectrum(self.n_modes,self.n_truncate,self.output_x,self.output_y,self.target_f,false);
Note that the spectrum is evaluated at the positions self.output_x
and self.output_y
. These are set in bt.model.template_spatial.set_electrodes
:
[self.output_x,self.output_y] = bt.data.electrode_positions(self.electrodes,self.p.Lx,self.p.Lx);
Fitting proceeds as usual because all of the lower level fitting functions work in the same way regardless of whether spatial variations are present or not. Specifically, fit_spectrum
and chain
both just pass variables around - it is up to the model to decide how to compute the objective and deal with multiple spectra. The objective returned is always scalar, which means that the chisq
values for each electrode must be reduced into a single number - this is presently done by direct summation, but it may be useful in future to consider different weightings for the electrodes.
For visualization, bt.viewer
automatically handles multiple electrodes, and a variety of other plots are available as well - see the Walkthrough for worked examples.