simulate_spikes.m 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. function [spktimes, rate_function] = simulate_spikes(event_ts, kernel, event_weights, varargin)
  2. %[spktimes, rate_function] = simulate_spikes(event_ts, kernel, event_weights, [krn_bin_size, krn_offset, baseline])
  3. % Inputs:
  4. % event_ts An N x M matrix, where N is the number of trials, and M is
  5. % the number of distinct events in that trial. Each element is the time of
  6. % the event relative to the beginning of the session.
  7. % kernel A cell array of length M. Each kernel is convolved with the
  8. % respective event in event_ts.
  9. % event_weights A matrix the same size as event_ts. These weights scale the
  10. % kernel for each event on each trial.
  11. %
  12. %
  13. % krn_bin_size [0.2 s] This is the resolution of the kernels.
  14. % krn_offset [0] By default each krn is center-aligned to the respective event
  15. % To shift this (e.g. to have the kernel follow or
  16. % preceed the event) pass in either a single offset, which
  17. % will be applied to all kernels or a list of M offsets to
  18. % apply to the M specified kernels. The offset should be in
  19. % bins.
  20. %
  21. %
  22. % E.g.
  23. if nargin==0 % Part of help!
  24. fprintf(1,'Running demo....\n');
  25. krn_bin_size = 0.1;
  26. kernel = {gampdf(0:krn_bin_size:2,3,0.1), gampdf(0:0.1:6,5,0.4)};
  27. kernel{1} = [zeros(size(kernel{1})), kernel{1}./max(kernel{1})*7];
  28. kernel{2} = [zeros(size(kernel{2})),kernel{2}./max(kernel{2})*2];
  29. n_trials = 100;
  30. trial_starts = linspace(0,500, n_trials )';
  31. event_ts = [trial_starts trial_starts + rand(size(trial_starts))+0.1];
  32. event_weights = randi([-1 5], n_trials, numel(kernel))*3;
  33. [spktimes, rate_function] = stats.simulate_spikes(event_ts, kernel, event_weights,'krn_bin_size',krn_bin_size,'baseline',20);
  34. figure; draw.exampleraster(event_ts(:,1), spktimes,'cnd',event_weights(:,1),'errorbars',0)
  35. figure; draw.exampleraster(event_ts(:,2), spktimes,'cnd',event_weights(:,2),'errorbars',0)
  36. return
  37. end
  38. %%
  39. inpd = @utils.inputordefault;
  40. [krn_bin_size, args] = inpd('krn_bin_size',0.2, varargin);
  41. [krn_offset, args] = inpd('krn_offset',0, args);
  42. [baseline, args] = inpd('baseline',0, args);
  43. if ~isempty(args)
  44. warning('Did not process some inputs in simulate_spikes. Did you make some typos?')
  45. disp(args)
  46. end
  47. if isscalar(krn_offset)
  48. krn_offset = zeros(size(kernel))+krn_offset;
  49. end
  50. % Shift the kernels by the offset by padding with zeros
  51. for kx = 1:numel(kernel)
  52. if krn_offset(kx)<0
  53. kernel{kx} = [kernel{kx}(:); zeros(abs(krn_offset),1)];
  54. elseif krn_offset(kx)>0
  55. kernel{kx} = [zeros(krn_offset,1); kernel{kx}(:)];
  56. end
  57. end
  58. %% Check args
  59. assert(all(size(event_ts) == size(event_weights)), 'event_ts and event_weight must have the same size');
  60. assert(numel(kernel) == size(event_ts,2), 'kernel should be a cell array with number of elements equal to columns of event_ts');
  61. assert(isscalar(baseline),'baseline must be a scalar')
  62. assert(numel(krn_offset)==1 || numel(krn_offset)==numel(kernel), 'krn_offset must be 1 or the number of kernels.')
  63. %% Generate delta functions
  64. start_time = min(event_ts(:)) - min(krn_offset)*krn_bin_size;
  65. stop_time = max(event_ts(:)) + max(cellfun(@(x)numel(x), kernel))*krn_bin_size;
  66. timeax = start_time:krn_bin_size:stop_time;
  67. deltas = zeros(numel(timeax), numel(kernel));
  68. cdeltas = deltas;
  69. for kx = 1:numel(kernel)
  70. this_ind = stats.qfind(timeax, event_ts(:,kx));
  71. deltas(this_ind,kx) = event_weights(:,kx);
  72. cdeltas(:,kx) = conv(deltas(:,kx), kernel{kx}, 'same');
  73. end
  74. rate_function = sum(cdeltas,2) + baseline;
  75. f = @(x)utils.nanidx(stats.qfind(timeax,x),rate_function);
  76. spktimes = stats.inhomopoissrnd(f, 'pre',start_time,'post',stop_time,'binsize',krn_bin_size);