123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- classdef KernelRegressionA
- properties
- baseline_per_trial = false
- core_kernel % this is the matrix for a single kernel. Will use it as a convolution kernel
- core_kernel_matrix % This is the core_kernel convolued with the event times.
- event_times
- kernel_bin_size = 0.01 % seconds
- kernel_dof = 50
- kernel_duration = 2 % seconds
- kernel_smoothing = 3
- kernel_smoothing_style = 'normal'
- kernel_weights % The result of the kernel estimation step.
- spiketimes
- trial_types
- trial_weights % The result of the trial weight estimation step
- weighted_kernel_matrix % core_kernel_matrix multiplied by trial_weights
- end
-
- properties (Dependent)
- number_of_events
- kernel_bins
- kernels % Combine the kernel_weights with core_kernel to get the kernels
- total_time_steps
- end
- methods
- function obj = KernelRegressionA(e, s, t)
- obj.event_times = e;
- obj.spiketimes = s;
- if nargin < 3
- obj.trial_types = col(1:size(e,1));
- else
- obj.trial_types = t;
- % This allows you to fit fewer than # of trial trial_weights. Eg. if you want to assume the weights on
- % the same trial type is the same.
- end
- obj.trial_weights = ones(numel(unique(obj.trial_types)),1);
- end
-
- function obj = run(obj)
- generateCoreKernel(obj);
- generateKernelMatrix(obj);
- generateCoreWeights(obj);
- generateWeightMatrix(obj);
- fit(obj);
- end
-
- function obj = generateCoreKernel(obj) % tested, OK
- % To do the kernel regression we need a regression matrix to specify
- % where each element of the kernel influences the firing rate.
- % We will start with the
- % assumption that all kernels have the same length: kernel_duration.
-
- % Initialize the matrix to be the right size.
- obj.core_kernel = zeros(obj.kernel_bins, obj.kernel_dof);
- obj.kernel_weights = ones(size(obj.event_times,2), obj.kernel_dof);
- % Put ones every where they should be.
- bins_per_dof = obj.kernel_bins/ obj.kernel_dof;
- tmpA = repmat(1:obj.kernel_bins:numel(obj.core_kernel),bins_per_dof,1) + (0:(bins_per_dof-1))';
- idx = tmpA + (0:bins_per_dof:(obj.kernel_bins-1));
- obj.core_kernel(idx(:)) = 1;
-
- % Apply smoothing
- if obj.kernel_smoothing > 0
- smooth_factor = obj.kernel_smoothing * bins_per_dof;
- switch obj.kernel_smoothing_style
- case 'normal'
- smooth_krn = normpdf(-(5*smooth_factor):(5*smooth_factor), 0, smooth_factor)';
- case 'box'
- smooth_krn = ones(smooth_factor,1);
- otherwise
- error('Do not know how to smooth using %s');
- end
-
- obj.core_kernel = conv2(obj.core_kernel, smooth_krn, 'same');
- obj.core_kernel = obj.core_kernel ./ sum(obj.core_kernel,2);
-
- end
-
- end
-
- function obj = generateKernelMatrix(obj)
- % Initialize a matrix that is [session_duration / bin_size x # of
- % kernels * kernel_bins + 1] (the one is for baseline). o
- if obj.baseline_per_trial
- % Should baseline be allowed to vary for different trials of the same trial_type? I guess yes.
- obj.core_kernel_matrix = zeros(obj.total_time_steps, obj.number_of_events*obj.kernel_bins + size(obj.event_times,1));
- else
- obj.core_kernel_matrix = zeros(obj.total_time_steps, obj.number_of_events*obj.kernel_bins + 1);
- end
-
-
- kernel_matrix = zeros(obj.total_time_steps, obj.number_of_events*obj.kernel_bins);
- % just for the kernels. Deal with the baseline later
-
- % We have a big matrix of zeros. We want to put the core_kernel
- % everywhere there is an event. Our plan for doing this is to put a 1
- % whereever we want the kernel and then convolve this with our
- % core_kernel. We can then use this to estimate the kernel_weights.
-
- row_offset = floor(obj.kernel_bins/2);
- col_offset = floor(obj.kernel_dof/2);
- krn_offset = obj.kernel_dof;
- event_index = floor((obj.event_times - min(obj.event_times(:))) /obj.kernel_bin_size); % Converts event_times to indices
-
- row_idx = event_index(:) + row_offset;
- col_idx = col(repmat((0:(obj.number_of_events-1))*krn_offset,obj.) +
- idx = sub2ind(size(kernel_matrix), row_idx, col_idx);
- kernel_matrix(idx) = 1;
- kernel_matrix = conv2(kernel_matrix, obj.core_kernel, 'same');
-
- end
-
- function number_of_events = get.number_of_events(obj)
- number_of_events = size(obj.event_times, 2);
- end
-
- function total_time_steps = get.total_time_steps(obj)
- total_time_steps = (max(obj.event_times(:)) - min(obj.event_times(:))) ./ obj.kernel_bin_size + obj.kernel_bins;
- end
-
- function kernel_bins = get.kernel_bins(obj)
- kernel_bins = obj.kernel_duration/obj.kernel_bin_size;
- assert(rem(kernel_bins,1)==0, 'The kernel_duration should be an integer multiple of kernel_bin_size');
- end
-
- function kernels = get.kernels(obj)
- % tested, OK
- kernels = obj.kernel_weights * obj.core_kernel';
- end
-
- end
- end
- function y = col(x)
- y = x(:);
- end
|