analyzePRFcomputesupergridseeds.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. function [seeds,rvalues] = analyzePRFcomputesupergridseeds(...
  2. res,stimulus,data,modelfun,maxpolydeg,dimdata,dimtime,typicalgain,noisereg,modeltype)
  3. % function [seeds,rvalues] = analyzePRF_computesupergridseeds(res,stimulus,data,modelfun,maxpolydeg,dimdata,dimtime,typicalgain,noisereg)
  4. %
  5. % <res> is [R C] with the resolution of the stimuli
  6. % <stimulus> is a cell vector of time x (pixels+1)
  7. % <data> is a cell vector of X x Y x Z x time (or XYZ x time)
  8. % <modelfun> is a function that accepts parameters (pp) and stimuli (dd) and outputs predicted time-series (time x 1)
  9. % <maxpolydeg> is a vector of degrees (one element for each run)
  10. % <dimdata> is number of dimensions that pertain to voxels
  11. % <dimtime> is the dimension that is the time dimension
  12. % <typicalgain> is a typical value for the gain in each time-series
  13. % <noisereg> is [] or a set of noise regressors (cell vector of matrices)
  14. %
  15. % this is an internal function called by analyzePRF.m. this function returns <seeds>
  16. % as a matrix of dimensions X x Y x Z x parameters (or XYZ x parameters)
  17. % with the best seed from the super-grid. also, returns <rvalues> as X x Y x Z
  18. % (or XYZ x 1) with the corresponding correlation (r) values.
  19. %
  20. % history:
  21. % 2015/02/07 - make less memory intensive
  22. % internal notes:
  23. % - note that the gain seed is fake (it is not set the correct value but instead
  24. % to the <typicalgain>)
  25. % internal constants
  26. eccs = [0 0.00551 0.014 0.0269 0.0459 0.0731 0.112 0.166 0.242 0.348 0.498 0.707 1];
  27. angs = linspacecircular(0,2*pi,16);
  28. expts = [0.5 0.25 0.125];
  29. sdratio = [1 1.5 2 2.5 3];
  30. normamp = [0 0.1 0.25 0.5 1];
  31. % calc
  32. numvxs = prod(sizefull(data{1},dimdata)); % total number of voxels
  33. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% calculate a long list of potential seeds
  34. % calc
  35. resmx = max(res);
  36. % calculate sigma gridding (pRF size is 1 px, 2 px, 4 px, ..., up to resmx)
  37. maxn = floor(log2(resmx));
  38. ssindices = 2.^(0:maxn);
  39. % construct full list of seeds (seeds x params) [R C S G N]
  40. fprintf('constructing seeds.\n');
  41. if strcmp(modeltype,'linear_hrf') || strcmp(modeltype,'linear_ephys')
  42. allseeds = zeros(length(eccs)*length(angs)*length(ssindices),4);
  43. elseif strcmp(modeltype,'css_hrf') || strcmp(modeltype,'css_ephys')
  44. allseeds = zeros(length(eccs)*length(angs)*length(ssindices)*length(expts),5);
  45. elseif strcmp(modeltype,'dog_hrf') || strcmp(modeltype,'dog_ephys')
  46. allseeds = zeros(length(eccs)*length(angs)*length(ssindices)*length(sdratio)*length(normamp),6);
  47. end
  48. cnt = 1;
  49. for p=1:length(eccs)
  50. for q=1:length(angs)
  51. if p==1 && q>1 % for the center-of-gaze, only do the first angle
  52. continue;
  53. end
  54. for s=1:length(ssindices)
  55. if strcmp(modeltype,'linear_hrf') || strcmp(modeltype,'linear_ephys')
  56. allseeds(cnt,:) = [(1+res(1))/2 - sin(angs(q)) * (eccs(p)*resmx) ...
  57. (1+res(2))/2 + cos(angs(q)) * (eccs(p)*resmx) ...
  58. ssindices(s) 1 ];
  59. cnt = cnt + 1;
  60. elseif strcmp(modeltype,'css_hrf') || strcmp(modeltype,'css_ephys')
  61. for r=1:length(expts)
  62. allseeds(cnt,:) = [(1+res(1))/2 - sin(angs(q)) * (eccs(p)*resmx) ...
  63. (1+res(2))/2 + cos(angs(q)) * (eccs(p)*resmx) ...
  64. ssindices(s)*sqrt(expts(r)) 1 expts(r)];
  65. cnt = cnt + 1;
  66. end
  67. elseif strcmp(modeltype,'dog_hrf') || strcmp(modeltype,'dog_ephys')
  68. for v=1:length(sdratio)
  69. for w=1:length(normamp)
  70. allseeds(cnt,:) = [(1+res(1))/2 - sin(angs(q)) * (eccs(p)*resmx) ...
  71. (1+res(2))/2 + cos(angs(q)) * (eccs(p)*resmx) ...
  72. ssindices(s) 1 sdratio(v) normamp(w)];
  73. cnt = cnt + 1;
  74. end
  75. end
  76. end
  77. end
  78. end
  79. end
  80. allseeds(cnt:end,:) = []; % chop because of the omission above
  81. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% generate the predicted time-series for each seed
  82. % generate predicted time-series [note that some time-series are all 0]
  83. predts = zeros(sum(cellfun(@(x) size(x,1),stimulus)),size(allseeds,1),'single'); % time x seeds
  84. temp = catcell(1,stimulus);
  85. fprintf('generating super-grid time-series...'); tic
  86. parfor p=1:size(allseeds,1)
  87. predts(:,p) = modelfun(allseeds(p,:),temp);
  88. end
  89. fprintf('done.'); toc
  90. clear temp;
  91. % % inspect for sanity on range and fineness [OBSOLETE]
  92. % figure;
  93. % for r=1:4:length(rrindices)
  94. % for c=1:4:length(ccindices)
  95. % for s=1:length(ssindices)
  96. % cnt = (r-1)*(length(ccindices)*length(ssindices)) + (c-1)*length(ssindices) + s;
  97. % clf;
  98. % plot(predts(:,cnt)');
  99. % title(sprintf('r=%d, c=%d, s=%d',r,c,s));
  100. % pause;
  101. % end
  102. % end
  103. % end
  104. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% prepare data and model predictions
  105. % construct polynomials, noise regressors, and projection matrix
  106. pregressors = {};
  107. for p=1:length(maxpolydeg)
  108. pregressors{p} = constructpolynomialmatrix(size(data{p},dimtime),0:maxpolydeg(p));
  109. if ~isempty(noisereg)
  110. pregressors{p} = cat(2,pregressors{p},noisereg{p});
  111. end
  112. end
  113. pmatrix = projectionmatrix(blkdiag(pregressors{:}));
  114. % project out and scale to unit length
  115. predts = unitlength(pmatrix*predts, 1,[],0); % time x seeds [NOTE: some are all NaN]
  116. % OLD: datats = unitlength(pmatrix*squish(catcell(dimtime,data),dimdata)',1,[],0); % time x voxels
  117. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% find the seed with the max correlation
  118. % compute correlation and find maximum for each voxel
  119. chunks = chunking(1:numvxs,100);
  120. rvalues = {};
  121. bestseedix = {};
  122. fprintf('finding best seed for each voxel.\n');
  123. parfor p=1:length(chunks)
  124. % project out and scale to unit length
  125. datats = unitlength(pmatrix*catcell(2,cellfun(@(x) subscript(squish(x,dimdata),{chunks{p} ':'}),data,'UniformOutput',0))',1,[],0); % time x voxels
  126. % voxels x 1 with index of the best seed (max corr)
  127. [rvalues{p},bestseedix{p}] = max(datats'*predts,[],2); % voxels x seeds -> max corr along dim 2 [NaN is ok]
  128. end
  129. rvalues = catcell(1,rvalues); % voxels x 1
  130. bestseedix = catcell(1,bestseedix); % voxels x 1
  131. % prepare output
  132. rvalues = reshape(rvalues,[sizefull(data{1},dimdata) 1]);
  133. seeds = allseeds(bestseedix,:); % voxels x parameters
  134. seeds(:,4) = typicalgain; % set gain to typical gain
  135. seeds = reshape(seeds,[sizefull(data{1},dimdata) size(allseeds,2)]);
  136. % predts(:,p) = modelfun([allseeds(p,:) flatten(hrf)],temp);
  137. % <hrf> is T x 1 with the HRF