MakeFigBarRFs_Fig2bc.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. close all;
  2. clear all;
  3. clc;
  4. %% Define search path.
  5. parentDir = fileparts(fileparts(mfilename('fullpath')));
  6. saveFolder = [parentDir filesep 'data'];
  7. load([saveFolder filesep 'Fig2-Tm9-processedTableWithBackgroundOnOff'], 'ProcessedTable');
  8. %%
  9. figDir = [parentDir filesep 'figures' filesep 'Fig2' filesep];
  10. if ~exist(figDir, 'dir')
  11. mkdir(figDir);
  12. end
  13. %%
  14. % Stimuli of interest.
  15. stimSetCellStr = getStimSetCellStr(2);
  16. %%
  17. StimTable = ProcessedTable;
  18. StimSubTablesCell = arrayfun(@(x) getStimSubsetTable(ProcessedTable, ...
  19. stimSetCellStr, x), ...
  20. 1: numel(stimSetCellStr), 'uni', 0);
  21. %% Plot tuning curves.
  22. StimTableCell = StimSubTablesCell(2: end);
  23. % This extracts the unaligned tuning curves (TCs).
  24. % Retrieve table data in arrays.
  25. [tcArrayCell, responseIndArrayCell, rSquareArrayCell, fitParamsCell, ...
  26. tcExtCellArray, tcArgExtCellArray] = cellfun(@getTuningCurveArrayFromTable, ...
  27. StimTableCell, 'uni', 0);
  28. % Align to fit
  29. posCell = cellfun(@(x) arrayfun(@(y) y.b1, x, 'uni', 0), fitParamsCell, 'uni', 1);
  30. widthCell = cellfun(@(x) arrayfun(@(y) 2 * (2 * sqrt(log(2))) * y.c1, x, 'uni', 0), ...
  31. fitParamsCell, 'uni', 1); % The 2 factor is because of bar separation.
  32. lagsCell = cellfun(@(x, y) round(x - size(y, 2) / 2), posCell, tcArrayCell, 'uni', 0);
  33. barRFs = cellfun(@(x, y) alignRFsToAbsMax(x, 0, y'), tcArrayCell, lagsCell, 'uni', 0);
  34. validIndsCell = cellfun(@(x, y) x(:) > 0.2 & y(:) > 0.5, ...
  35. rSquareArrayCell, responseIndArrayCell, 'uni', 0)';
  36. %% Blank epoch was already deleted, now delete vertical bars on edges of screen.
  37. barRFs{2}(:, end-1: end) = [];
  38. barRFs{4}(:, end-1: end) = [];
  39. barRFs{2}(:, 1: 2) = [];
  40. barRFs{4}(:, 1: 2) = [];
  41. %%
  42. offX = barRFs{1}(validIndsCell{1}, :);
  43. offY = barRFs{2}(validIndsCell{2}, :);
  44. onX = barRFs{3}(validIndsCell{3}, :);
  45. onY = barRFs{4}(validIndsCell{4}, :);
  46. % normalize to peak and smooth and normalize again.
  47. maxNorm = @(x, dim) x ./ max(abs(x), [], dim);
  48. getRow = @(x, nRow) x(nRow, :);
  49. normRFs = cellfun(@(x) cell2mat(arrayfun(@(y) smooth(getRow(maxNorm(x,2), y))', 1: size(x, 1), 'uni', 0)'), ...
  50. {offX, offY, onX, onY}, 'uni', 0);
  51. normRFs = cellfun(@(x) maxNorm(x,2), normRFs, 'uni', 0);
  52. %%
  53. % Plot lasagna plots, separate figures for off and on, and reapeated panel
  54. % is to have a colorbar that does not distort existing axis of interest.
  55. hFig = createPrintFig(15 * [ 1 2/3]);
  56. hSubAx = plotLasagnaTracesFromCell(gcf, {offX, offY, offY}, brewermap(6, 'Paired'));
  57. colorbar
  58. % arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'on'), hSubAx(1, :))
  59. arrayfun(@prettifyAxes, hSubAx)
  60. arrayfun(@offsetAxes, hSubAx)
  61. % set(hSubAx, 'Visible', 'off')
  62. figFileName = ['RFcurves-OFF-XY-lasagna'];
  63. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  64. %%
  65. colorbar
  66. hFig = createPrintFig(15 * [ 1 2/3]);
  67. hSubAx = plotLasagnaTracesFromCell(gcf, {onX, onY, onY}, brewermap(6, 'Paired'));
  68. colorbar
  69. % arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'on'), hSubAx(1, :))
  70. arrayfun(@prettifyAxes, hSubAx)
  71. arrayfun(@offsetAxes, hSubAx)
  72. % set(hSubAx, 'Visible', 'off')
  73. figFileName = ['RFcurves-ON-XY-lasagna'];
  74. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  75. %% For nat comms editorial policies source data
  76. dataFileName = [figDir filesep 'Fig2.xls'];
  77. DataTable = createRFsTable(offX, 'OFF_horizontal_position_deg');
  78. writetable(DataTable, dataFileName, 'Sheet', 'Fig2b')
  79. DataTable = createRFsTable(offY, 'OFF_vertical_position_deg');
  80. writetable(DataTable, dataFileName, 'Sheet', 'Fig2b', 'Range', 'A28:IV100')
  81. DataTable = createRFsTable(onX, 'ON_horizontal_position_deg');
  82. writetable(DataTable, dataFileName, 'Sheet', 'Fig2b', 'Range', 'A56:IV100')
  83. DataTable = createRFsTable(onY, 'ON_vertical_position_deg');
  84. writetable(DataTable, dataFileName, 'Sheet', 'Fig2b', 'Range', 'A84:IV100')
  85. %% This produces panel 2
  86. validWidthCell = getCellArrayFromIndexThreshold(widthCell, validIndsCell', 0);
  87. hFig = createPrintFig(15 * [ 1/3 1/3]);
  88. hWidthAx = beanPlot(validWidthCell, {'xOFF' 'yOFF' 'xON' 'yON'}, getONOFFXYColors, ...
  89. 1, gca, [0-eps 100], 'vertical', 0, 1, 0);
  90. setFontForThesis(hWidthAx, gcf);
  91. arrayfun(@prettifyAxes, hWidthAx)
  92. arrayfun(@offsetAxes, hWidthAx)
  93. figFileName = ['RF-FWHM-bean'];
  94. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  95. %% Write data for fig2c
  96. xlswrite(dataFileName, {'FHWM-OFF-bars-horizontal'}, 'Fig2c', 'A1')
  97. xlswrite(dataFileName, validWidthCell{1}, 'Fig2c', 'B1')
  98. xlswrite(dataFileName, {'FHWM-OFF-bars-vertical'}, 'Fig2c', 'A2')
  99. xlswrite(dataFileName, validWidthCell{2}, 'Fig2c', 'B2')
  100. xlswrite(dataFileName, {'FHWM-ON-bars-horizontal'}, 'Fig2c', 'A3')
  101. xlswrite(dataFileName, validWidthCell{3}, 'Fig2c', 'B3')
  102. xlswrite(dataFileName, {'FHWM-ON-bars-vertical'}, 'Fig2c', 'A4')
  103. xlswrite(dataFileName, validWidthCell{4}, 'Fig2c', 'B4')
  104. %% Range and mean of ON RF fwhm
  105. min([validWidthCell{3}(:); validWidthCell{4}(:)])
  106. max([validWidthCell{3}(:); validWidthCell{4}(:)])
  107. mean([validWidthCell{3}(:); validWidthCell{4}(:)])
  108. std([validWidthCell{3}(:); validWidthCell{4}(:)])
  109. %%
  110. threshold = 0.5;
  111. rSquareThreshold = 0.2;
  112. qualityMeasure = 'responseQuality';
  113. widthCell = plotParamsThresholdedDistribution(StimTableCell, threshold, qualityMeasure, figDir, rSquareThreshold);
  114. %% Do stats for panel 2c
  115. % Not really normal lly distributed
  116. cellfun(@lillietest, widthCell);
  117. % Test offX vs onX and offY vs onY
  118. [pX, meanXDiff, ~] = permutationTest(widthCell{1}, widthCell{3}, 100000);
  119. [pY, meanYDiff, ~] = permutationTest(widthCell{2}, widthCell{4}, 100000);
  120. %% Nested permutations
  121. flyIndsCell = cellfun(@(y) repelem(y.flyInd, cellfun(@numel, y.responseIndex)), ...
  122. StimTableCell, 'uni', 0);
  123. for iStim = 1: size(StimTableCell, 2)
  124. flyIndsCellArray{iStim} = mat2cell(flyIndsCell{iStim}, ...
  125. cellfun(@numel, StimTableCell{iStim}.responseIndex));
  126. inputCellArray = flyIndsCellArray{iStim};
  127. StimTable = StimTableCell{iStim};
  128. nonParamTunings = getRoisFeaturePerChannel(cellfun(@(x) x', StimTable.nonParamTuning, 'uni', 0));
  129. domainCellArray = arrayfun(@(x) x.domain, nonParamTunings, 'uni', 0);
  130. domainSize = cellfun(@numel, domainCellArray);
  131. outputCellArray{iStim} = cell2mat(inputCellArray(domainSize == mode(domainSize)));
  132. end
  133. correctedFlyInds = outputCellArray;
  134. %%
  135. goodFlyIndsCell = getCellArrayFromIndexThreshold(correctedFlyInds, validIndsCell', 0);
  136. nFlies = cellfun(@(x) numel(unique(x)), goodFlyIndsCell);
  137. %% Store the fly indices
  138. xlswrite(dataFileName, {'FlyID-OFF-bars-horizontal'}, 'Fig2c', 'A6')
  139. xlswrite(dataFileName, goodFlyIndsCell{1}', 'Fig2c', 'B6')
  140. xlswrite(dataFileName, {'FlyID-OFF-bars-vertical'}, 'Fig2c', 'A7')
  141. xlswrite(dataFileName, goodFlyIndsCell{2}', 'Fig2c', 'B7')
  142. xlswrite(dataFileName, {'FlyID-ON-bars-horizontal'}, 'Fig2c', 'A8')
  143. xlswrite(dataFileName, goodFlyIndsCell{3}', 'Fig2c', 'B8')
  144. xlswrite(dataFileName, {'FlyID-ON-bars-vertical'}, 'Fig2c', 'A9')
  145. xlswrite(dataFileName, goodFlyIndsCell{4}', 'Fig2c', 'B9')
  146. %% Still do the nested permutation
  147. nROIsPerFlyCell = cellfun(@(x) accumarray(x(:), 1), goodFlyIndsCell, 'uni', 0);
  148. % Delete flies with no rois to analyze.
  149. for iStim = 1: numel(nROIsPerFlyCell)
  150. nROIsPerFlyCell{iStim}(nROIsPerFlyCell{iStim} == 0) = [];
  151. end% generate continuos numbering.
  152. reorderedFlyIndsCell = cellfun(@(x) repelem(1: numel(x), x), nROIsPerFlyCell, 'uni', 0);
  153. %%
  154. % samples are cells, but we will permute all cells of a fly together.
  155. % Test only within orientation differences
  156. sample1 = 1: numel(nROIsPerFlyCell{1});
  157. sample2 = numel(sample1) + (1: numel(nROIsPerFlyCell{3}));
  158. permutations = 10000;
  159. sidedness = 'both';
  160. plotresult = 1;
  161. [obsDiffX, pValX] = nestetPermutationTest(sample1, sample2, ...
  162. widthCell([1, 3]), ...
  163. reorderedFlyIndsCell([1, 3]), ...
  164. permutations, sidedness, plotresult);
  165. sample1 = 1: numel(nROIsPerFlyCell{2});
  166. sample2 = numel(sample1) + (1: numel(nROIsPerFlyCell{4}));
  167. [obsDiffY, pValY] = nestetPermutationTest(sample1, sample2, ...
  168. widthCell([2, 4]), ...
  169. reorderedFlyIndsCell([2, 4]), ...
  170. permutations, sidedness, plotresult);
  171. %% Plot raw traces for supplementary figure.
  172. hFig = createPrintFig(15 * [1 1]);
  173. drawRandomSubset = 1;
  174. for iStim = 1: size(StimTableCell, 2)
  175. inputCellArray = StimTableCell{iStim}.paddedEpochStacks;
  176. StimTable = StimTableCell{iStim};
  177. % To remove flies with different number of epochs than the majority.
  178. nonParamTunings = getRoisFeaturePerChannel(cellfun(@(x) x', StimTable.nonParamTuning, 'uni', 0));
  179. domainCellArray = arrayfun(@(x) x.domain, nonParamTunings, 'uni', 0);
  180. domainSize = cellfun(@numel, domainCellArray);
  181. outputCellArray{iStim} = inputCellArray(domainSize == mode(domainSize));
  182. allRFTraces = cell2mat(cellfun(@(x) cat(1, x{:})', ...
  183. outputCellArray{iStim}, 'uni', 0));
  184. size(allRFTraces)
  185. rng('default')
  186. % imagesc(allRFTraces(validIndsCell{1}, :))
  187. hTracesAx(iStim) = subplot(2, 2, iStim);
  188. cla
  189. plotInds = find(validIndsCell{iStim});
  190. if drawRandomSubset
  191. plotInds = plotInds(randperm(10));
  192. end
  193. barResponseTraces{iStim} = allRFTraces(plotInds, :);
  194. timePoints{iStim} = (1: numel(allRFTraces(plotInds(1), :))) / 10; % Data interpolated at 10Hz
  195. plot(timePoints{iStim}, bsxfun(@plus, allRFTraces(plotInds, :)', ...
  196. 0.9 * (1: numel(plotInds))), 'LineWidth', 1, 'Color', 0.25 * [1 1 1]);
  197. hold on;
  198. axis tight
  199. hLines = arrayfun(@(x) refline(0, x), 0.9 * (1: numel(plotInds)));
  200. [hLines.Color] = deal([1 1 1] * 0.5);
  201. [hLines.LineWidth] = deal(0.5);
  202. timePointsPerEpoch = size(allRFTraces, 2) / mode(domainSize);
  203. hLines = arrayfun(@(x) line([x, x], ylim), ...
  204. timePointsPerEpoch / 10 * (1/3: 1: mode(domainSize)) + 1/3);
  205. [hLines.Color] = deal([1 1 1] * 0.75);
  206. [hLines.LineWidth] = deal(0.5);
  207. [hLines.LineStyle] = deal(':');
  208. % Send the reference lines to the back.
  209. chH = get(gca,'Children');
  210. set(gca,'Children',flipud(chH));
  211. end
  212. xlabel(hTracesAx(3), 'Time (s)')
  213. xlabel(hTracesAx(4), 'Time (s)')
  214. ylabel(hTracesAx(1), '\DeltaF/F_0')
  215. ylabel(hTracesAx(3), '\DeltaF/F_0')
  216. setFontForThesis(hTracesAx, gcf);
  217. arrayfun(@prettifyAxes, hTracesAx)
  218. arrayfun(@offsetAxes, hTracesAx)
  219. figFileName = ['Fig2-suppl-meanTraces-sortedPositions'];
  220. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  221. %% Export data for Supplementary Fig 2
  222. dataFileName = [figDir filesep 'Fig2.xls'];
  223. sheetName = 'SupFig2';
  224. stimNameStrCell = {'Tm9_OFF_horizontal_bar_time_seconds', 'Tm9_OFF_vertical_bar_time_seconds', ...
  225. 'Tm9_ON_horizontal_bar_time_seconds', 'Tm9_ON_vertical_bar_time_seconds'};
  226. startRow = 1;
  227. for iStim = 1: 4
  228. DataTable = createRFsTable(barResponseTraces{iStim}, stimNameStrCell{iStim});
  229. DataTable(:, 1).(stimNameStrCell{iStim}) = timePoints{iStim}(:);
  230. writetable(DataTable, dataFileName, 'Sheet', sheetName, 'Range', ['A' num2str(startRow)]);
  231. startRow = startRow + size(DataTable, 1) + 2;
  232. end
  233. %% Now pick a value an compare stimuli. And do some statistics.
  234. plotBootstrapCoeffOfVariationTest(widthCell, figDir, threshold, rSquareThreshold)
  235. %% Variance plot
  236. plotBarVariance(widthCell, figDir, threshold, rSquareThreshold)