alignRFsToAbsMax.m 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. function [alignedRFs, lagDiffs] = alignRFsToAbsMax(receptiveFields, padWithNaNs, varargin)
  2. if isempty(receptiveFields)
  3. warning('Empty array, no RF to align!!')
  4. return
  5. end
  6. switch nargin
  7. case 2
  8. lagDiffs = calculateRFShifts(receptiveFields);
  9. case 3
  10. lagDiffs = varargin{1};
  11. case 4
  12. lagDiffs = varargin{1};
  13. polarity = varargin{2};
  14. if isempty(lagDiffs)
  15. lagDiffs = calculateRFShifts(receptiveFields, polarity);
  16. end
  17. otherwise
  18. lagDiffs = calculateRFShifts(receptiveFields);
  19. end
  20. alignedRFs = shiftReceptiveFields(receptiveFields, lagDiffs, padWithNaNs);
  21. end
  22. function lagDiffs = calculateRFShifts(receptiveFields, varargin)
  23. nEpochs = size(receptiveFields, 2);
  24. if ~isempty(varargin)
  25. polarity = varargin{1};
  26. else
  27. polarity = '';
  28. end
  29. % Get reference ROIs with center close to the center of screen.
  30. switch polarity
  31. case 'on'
  32. [~, maxInd] = min((receptiveFields), [], 2);
  33. case 'off'
  34. [~, maxInd] = max((receptiveFields), [], 2);
  35. otherwise
  36. [~, maxInd] = max(abs(receptiveFields), [], 2);
  37. end
  38. % Consider signal to noise ration to avoid biasing towards noisy RFs.
  39. %%
  40. medianToStd = @ (x) median(x, 2) ./ std(x, [], 2);
  41. signalToNoise = medianToStd(abs(receptiveFields));
  42. % Take only data above 90 percentile.
  43. snrCutoff = quantile(signalToNoise, 0.7);
  44. %%
  45. % Check distribution of center locations.
  46. distanceToCenter = abs(maxInd - nEpochs / 2);
  47. distanceCutoff = max(quantile(distanceToCenter, 0.5), 6);
  48. validRFCenters = distanceToCenter <= distanceCutoff & signalToNoise >= snrCutoff;
  49. referenceRF = mean(receptiveFields(validRFCenters, :), 1);
  50. % Align center RFs to reference RF.
  51. alignedRefRFs = nan * ones(size(receptiveFields, 1), nEpochs);
  52. for iCell = find(validRFCenters)'
  53. [alignedRefRFs(iCell, :), ~] = crossCorrShiftRF(receptiveFields(iCell, :), referenceRF);
  54. end
  55. referenceRF = nanmean(alignedRefRFs, 1);
  56. alignedRFs = ones(size(receptiveFields)) * nan;
  57. % Shift single
  58. for iCell = 1: size(receptiveFields, 1)
  59. [alignedRFs(iCell, :), lagDiffs(iCell)] = crossCorrShiftRF(receptiveFields(iCell, :), referenceRF);
  60. end
  61. % Shift reference to center to get total shift.
  62. [~, maxInd] = max(abs(nanmean(alignedRFs, 1)));
  63. globalShift = floor(maxInd - nEpochs / 2);
  64. % alignedRFs = circshift(alignedRFs, -globalShift, 2);
  65. lagDiffs = lagDiffs + globalShift;
  66. end
  67. function alignedRFs = shiftReceptiveFields(receptiveFields, lagDiffs, padWithNaNs)
  68. nEpochs = size(receptiveFields, 2);
  69. for iCell = 1: size(receptiveFields, 1)
  70. alignedRFs(iCell, :) = circshift(receptiveFields(iCell, :), -lagDiffs(iCell));
  71. if lagDiffs(iCell) > nEpochs
  72. alignedRFs(iCell, :) = nan * receptiveFields(iCell, :);
  73. end
  74. end
  75. lagDiffs = -lagDiffs;
  76. for iCell = 1: size(receptiveFields, 1)
  77. % Set the shifted portion of tuning curve to nan.
  78. if padWithNaNs
  79. if sign(lagDiffs(iCell)) > 0
  80. alignedRFs(iCell, 1: lagDiffs(iCell)) = nan;
  81. elseif abs(lagDiffs(iCell)) < nEpochs || sign(lagDiffs(iCell)) < 0
  82. alignedRFs(iCell, end + lagDiffs(iCell): end) = nan;
  83. else
  84. alignedRFs(iCell, :) = nan;
  85. end
  86. end
  87. end
  88. end