Skip to content
Romesh Abeysuriya edited this page Nov 1, 2015 · 2 revisions

This wiki page documents spatial fitting of multielectrode data.

Introduction

Spatial fitting essentially comes down to three parts

  1. Developing a formula for the power spectrum that takes into account spatial variations in parameter values
  2. Selecting a useful parametrization of the spatial variations
  3. 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

template_spatial

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.

  1. The model internally stores a params object
  2. The model calls apply_variation' on the paramsobject, which converts the BrainTrak model parameters into theparams` object representation
  3. The model calls params.spatial_spectrum which calculates the spectrum
  4. 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.

Clone this wiki locally