MakeRFNoiseComparison_Fig2ef.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. %% Make fig 2 e, f
  2. close all;
  3. clear all;
  4. clc;
  5. %% Define search path.
  6. parentDir = fileparts(fileparts(mfilename('fullpath')));
  7. saveFolder = [parentDir filesep 'data'];
  8. load([saveFolder filesep 'Fig2-Tm9-Bars-Noise-processedTableWithBackgroundOnOffNoiseCropped'], 'ProcessedTable');
  9. %%
  10. figDir = [parentDir filesep 'figures' filesep 'Fig2' filesep];
  11. if ~exist(figDir, 'dir')
  12. mkdir(figDir);
  13. end
  14. %% Define search path.
  15. datasetInd = 3;
  16. [~, ~, stimSetCellStr] = parseDatasetVars(datasetInd);
  17. %%
  18. ProcessedTable = ProcessedTable(ProcessedTable.typeOfProblem == 0, :);
  19. % Check only bars.
  20. nStims = 8; % 8 for fff, bars, and noise; 5 for fff and bars.
  21. stimSetCellStr = stimSetCellStr(1: nStims);
  22. %% Split table into cell types.
  23. tokens = arrayfun(@(x) regexp(x, '.*Tm(\d).*', 'tokens'), ProcessedTable.timeSeriesPath);
  24. cellTypeNumArray = cellfun(@(x) str2num(x{1}{1}), tokens);
  25. cellTypeNum = unique(cellTypeNumArray);
  26. for iNeuron = 1: numel(cellTypeNum)
  27. StimTableNeuronCell{iNeuron} = ProcessedTable(cellTypeNumArray == cellTypeNum(iNeuron), :);
  28. end
  29. %%
  30. stimInd = 1;
  31. nStims = numel(stimSetCellStr);
  32. for iNeuron = 1: numel(cellTypeNum)
  33. for jStim = 1: nStims
  34. StimTableNeuronStim{iNeuron, jStim} = getStimSubsetTable(StimTableNeuronCell{iNeuron}, stimSetCellStr, jStim);
  35. end
  36. end
  37. for iFly = 1: numel(unique(ProcessedTable.flyInd))
  38. flyInds = ProcessedTable.flyInd == iFly;
  39. flyStims = ProcessedTable(flyInds, :).stimParamFileName;
  40. % Find if stim is within the chosen subset.
  41. flyStimInds{iFly} = (cellfun(@(x) find(strcmp(x, stimSetCellStr)), flyStims, 'uni', 0));
  42. % If it contains stimuli, check that it includes the 5 chosen.
  43. if ~isempty(flyStimInds{iFly})
  44. setDiff{iFly} = setdiff(1: nStims, [flyStimInds{iFly}{:}]);
  45. else
  46. setDiff{iFly} = -1;
  47. end
  48. % For flies with all chosen stimuli order the table accordingly.
  49. if isempty(setDiff{iFly})
  50. sortFlyIndsTemp = find(flyInds);
  51. [~, sortInd] = sort([flyStimInds{iFly}{:}]);
  52. sortFlyInds{iFly} = sortFlyIndsTemp(sortInd);
  53. end
  54. end
  55. StimOrderedTable = ProcessedTable(cat(1, sortFlyInds{:}), :);
  56. %% Split table into cell types.
  57. tokens = arrayfun(@(x) regexp(x, '.*Tm(\d).*', 'tokens'), StimOrderedTable.timeSeriesPath);
  58. cellTypeNumArray = cellfun(@(x) str2num(x{1}{1}), tokens);
  59. cellTypeNum = unique(cellTypeNumArray);
  60. for iNeuron = 1: numel(cellTypeNum)
  61. StimTableNeuronCell{iNeuron} = StimOrderedTable(cellTypeNumArray == cellTypeNum(iNeuron), :);
  62. end
  63. %%
  64. nStims = numel(stimSetCellStr);
  65. for iNeuron = 1: numel(cellTypeNum)
  66. for jStim = 1: nStims
  67. StimTableNeuronStim{iNeuron, jStim} = getStimSubsetTable(StimTableNeuronCell{iNeuron}, stimSetCellStr, jStim);
  68. end
  69. end
  70. OriginalStimTableNeuronStim = StimTableNeuronStim;
  71. %% Delete invalid rois for all flies and stimuli.
  72. bgRois = cellfun(@(y) cellfun(@(x) x.backgroundRois, y.roiMeta), StimTableNeuronStim, 'uni', 0);
  73. %Test if all background rois are the same for all stimuli.
  74. assert(isequal(bgRois{:}));
  75. invalidRois = zeros(size(StimTableNeuronStim{1}, 1), size(StimTableNeuronStim, 2));
  76. for iFly = 1: size(StimTableNeuronStim{1}, 1)
  77. for jStim = 1: size(StimTableNeuronStim, 2)
  78. invalidInds = StimTableNeuronStim{jStim}.roiMeta{iFly}.invalidRois;
  79. if ~isempty(invalidInds)
  80. invalidRois(iFly, jStim) = invalidInds;
  81. end
  82. end
  83. end
  84. roisToDeletePerFly = sum(unique(invalidRois', 'rows'))';
  85. %% Extract the parameters for the analysis of spatial RFs.
  86. jBar = 1;
  87. for iStim = 2:5
  88. dummyTable = StimTableNeuronStim{iStim};
  89. paramsCell = cellfun(@(x) x(1: end - 1*0), dummyTable.paramTuning, 'uni', 0);
  90. responseIndex = cellfun(@(x, y) x(1: end - 1*0), dummyTable.responseIndex, 'uni', 0);
  91. for jFly = find(roisToDeletePerFly ~= 0)
  92. if invalidRois(jFly, iStim) == 0
  93. paramsCell{jFly}(roisToDeletePerFly(jFly) - 1*0) = [];
  94. responseIndex{jFly}(roisToDeletePerFly(jFly) - 1*0) = [];
  95. end
  96. end
  97. amp(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.a1, x, 'uni', 1), paramsCell, 'uni', 0)');
  98. pos(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.b1, x, 'uni', 1), paramsCell, 'uni', 0)');
  99. width(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.c1, x, 'uni', 1), paramsCell, 'uni', 0)');
  100. rsquare(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.gof.rsquare, x, 'uni', 1), paramsCell, 'uni', 0)');
  101. jBar = jBar + 1;
  102. end
  103. for iStim = [7, 8]
  104. dummyTable = StimTableNeuronStim{iStim};
  105. paramsCell = cellfun(@(x) x(1: end - 1*0), dummyTable.paramTuning, 'uni', 0);
  106. % responseIndex = cellfun(@(x, y) x(1: end - 1), dummyTable.responseIndex, 'uni', 0);
  107. for jFly = find(roisToDeletePerFly ~= 0)
  108. if invalidRois(jFly, iStim) == 0
  109. paramsCell{jFly}(roisToDeletePerFly(jFly) - 1*0) = [];
  110. % responseIndex{jFly}(roisToDeletePerFly(jFly) - 1*0) = [];
  111. end
  112. end
  113. amp(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.a1, x, 'uni', 1), paramsCell, 'uni', 0)');
  114. pos(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.b1, x, 'uni', 1), paramsCell, 'uni', 0)');
  115. width(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.c1, x, 'uni', 1), paramsCell, 'uni', 0)');
  116. rsquare(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.gof.rsquare, x, 'uni', 1), paramsCell, 'uni', 0)');
  117. jBar = jBar + 1;
  118. end
  119. pos(1: 4, :) = 2 * (pos(1: 4, :) - 1);
  120. pos(5: 6, :) = 5 * pos(5: 6, :);
  121. width = (2 * sqrt(log(2))) * width;
  122. width(1: 4, :) = 2 * width(1: 4, :);
  123. width(5: 6, :) = 5 * width(5: 6, :);
  124. validInds = all(rsquare([1, 2, 5, 6], :) > 0.5) & all(rsquare([3, 4], :) > 0.1);
  125. %%
  126. flyInds = repelem(1:size(StimTableNeuronStim{1}),cellfun(@numel, StimTableNeuronStim{1}.responseIndex));
  127. flyInds(roisToDeletePerFly(1)) = [];
  128. flyInds(validInds)
  129. numel(unique(flyInds(validInds)))
  130. %%
  131. clear allRFs
  132. for iStim = 2: 5
  133. tuningMethods = StimTableNeuronStim{iStim}.nonParamTuning{1}.tuningMethods;
  134. tuningMethodInd = strcmp(tuningMethods, 'extreme');
  135. tcCellArray = cellfun(@(x) squeeze(x.tc{tuningMethodInd}(:, 1: end - 1, :)), StimTableNeuronStim{iStim}.nonParamTuning, 'uni', 0);
  136. allRFs{iStim - 1} = cell2mat(tcCellArray);
  137. end
  138. %%
  139. noiseRFs{1} = getSpaceFilterArrayFromTable(StimTableNeuronStim{7}); % Az is horizontal
  140. noiseRFs{2} = getSpaceFilterArrayFromTable(StimTableNeuronStim{8}); % El is vertical
  141. %%
  142. % Delete invalid roi that shifts all images by one;
  143. barRFs = cellfun(@(x) x(setdiff(1: length(allRFs{1}), roisToDeletePerFly(1)), 1: end), ...
  144. allRFs, 'uni', 0);
  145. noiseRFs{1}(roisToDeletePerFly(1), :) = [];
  146. %%
  147. % The screen is about 48-60 deg, we center the RFs at about the center 24
  148. % deg, using the fit positions for higher presicion.
  149. lagsBars = round((pos(1: 4, :) - 25) / 2);
  150. for iBar = 1: numel(barRFs)
  151. barRFs{iBar} = alignRFsToAbsMax(barRFs{iBar}, 0, lagsBars(iBar, :)');
  152. end
  153. lagsNoise = round((pos(5: 6, :) - 30) / 5);
  154. for iBar = 1: numel(noiseRFs)
  155. noiseRFs{iBar} = alignRFsToAbsMax(noiseRFs{iBar}, 0, lagsNoise(iBar, :));
  156. end
  157. %% Blank epoch was already deleted, now delete vertical bars on edges of screen.
  158. barRFs{2}(:, end-1: end) = [];
  159. barRFs{4}(:, end-1: end) = [];
  160. barRFs{2}(:, 1: 2) = [];
  161. barRFs{4}(:, 1: 2) = [];
  162. %% Fig2e
  163. hFig = figure;
  164. splitSign = 1;
  165. doSmoothing = 1;
  166. indsToPlot = validInds;
  167. subplot_tight(1, 3, 1);
  168. plotRFEnsemble(noiseRFs{1}, noiseRFs{2}, splitSign, doSmoothing, indsToPlot);
  169. title('White noise spatial filters')
  170. % Plot bar RFs. OFF.
  171. subplot_tight(1, 3, 2);
  172. plotRFEnsemble(barRFs{1}, barRFs{2}, splitSign, doSmoothing, indsToPlot);
  173. title('OFF flashing bar filters')
  174. % Plot bar RFs. ON.
  175. subplot_tight(1, 3, 3);
  176. plotRFEnsemble(barRFs{3}, barRFs{4}, splitSign, doSmoothing, indsToPlot);
  177. title('ON flashing bar filters')
  178. suptitle('Cartesian product (X \times Y) of one dimensional tuning curves');
  179. figFileName = ['RFIm-ON-OFF-Noise'];
  180. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  181. % print(hFig, [figDir figFileName '.png'], '-dpng', '-r
  182. %% Write data for fig2e
  183. dataFileName = [figDir filesep 'Fig2.xls'];
  184. DataTable = createRFsTable(noiseRFs{1}(indsToPlot, :), 'Noise_horizontal_position_deg');
  185. % Correct spacing from 2 deg for bars to 5 deg for noise.
  186. DataTable(:, 1).Noise_horizontal_position_deg = 5 / 2 * DataTable(:, 1).Noise_horizontal_position_deg;
  187. writetable(DataTable, dataFileName, 'Sheet', 'Fig2e')
  188. DataTable = createRFsTable(noiseRFs{1}(indsToPlot, :), 'Noise_vertical_position_deg');
  189. % Correct spacing from 2 deg for bars to 5 deg for noise.
  190. DataTable(:, 1).Noise_vertical_position_deg = 5 / 2 * DataTable(:, 1).Noise_vertical_position_deg;
  191. writetable(DataTable, dataFileName, 'Sheet', 'Fig2e', 'Range', 'A15')
  192. DataTable = createRFsTable(barRFs{1}(indsToPlot, :), 'OFF_horizontal_position_deg');
  193. writetable(DataTable, dataFileName, 'Sheet', 'Fig2e', 'Range', 'A29')
  194. DataTable = createRFsTable(barRFs{2}(indsToPlot, :), 'OFF_vertical_position_deg');
  195. writetable(DataTable, dataFileName, 'Sheet', 'Fig2e', 'Range', 'A56')
  196. DataTable = createRFsTable(barRFs{3}(indsToPlot, :), 'ON_horizontal_position_deg');
  197. writetable(DataTable, dataFileName, 'Sheet', 'Fig2e', 'Range', 'A83')
  198. DataTable = createRFsTable(barRFs{4}(indsToPlot, :), 'ON_vertical_position_deg');
  199. writetable(DataTable, dataFileName, 'Sheet', 'Fig2e', 'Range', 'A110')
  200. %%
  201. offX = barRFs{1}(validInds, :);
  202. offY = barRFs{2}(validInds, :);
  203. onX = barRFs{3}(validInds, :);
  204. onY = barRFs{4}(validInds, :);
  205. lnX = noiseRFs{1}(validInds, :);
  206. lnY = noiseRFs{2}(validInds, :);
  207. lnX = interp1(linspace(2.5,60, 12), lnX', linspace(2.5,60, 25))';
  208. lnY = interp1(linspace(2.5,60, 12), lnY', linspace(2.5,60, 25))';
  209. % Realign noise to center now at 2 deg precision.
  210. [~, peakInd] = max(abs(lnX), [], 2);
  211. lnX = alignRFsToAbsMax(lnX, 0, peakInd - round(length(lnX) / 2) - 1);
  212. [~, peakInd] = max(abs(lnY), [], 2);
  213. lnY = alignRFsToAbsMax(lnY, 0, peakInd - round(length(lnY) / 2) - 1);
  214. maxNorm = @(x, dim) x ./ max(abs(x), [], dim);
  215. getRow = @(x, nRow) x(nRow, :);
  216. normRFs = cellfun(@(x) cell2mat(arrayfun(@(y) smooth(getRow(maxNorm(x,2), y))', 1: size(x, 1), 'uni', 0)'), ...
  217. {offX, offY, onX, onY, lnX, lnY}, 'uni', 0);
  218. normRFs = cellfun(@(x) maxNorm(x,2), normRFs, 'uni', 0);
  219. hFig = createPrintFig(15 * [ 1 1 / 3]);
  220. for iRFType = 1:3
  221. subplot_tight(1, 3, iRFType);
  222. imshow(getRFIm(mean(normRFs{2*iRFType}), mean(normRFs{2*iRFType - 1})))
  223. end
  224. figFileName = ['RFIm-ON-OFF-Noise-mean'];
  225. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  226. hFig = createPrintFig(15 * [ 1 2/3]);
  227. hSubAx = plotLasagnaTracesFromCell(gcf, normRFs, brewermap(6, 'Paired'));
  228. ylim(hSubAx(:, 1), [-1 1]);
  229. arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'on'), hSubAx(1, :))
  230. cellfun(@(x) caxis(ZeroCenteredBounds(x, [0 100])), normRFs, 'uni', 0)
  231. arrayfun(@prettifyAxes, hSubAx)
  232. arrayfun(@offsetAxes, hSubAx)
  233. set(hSubAx, 'Visible', 'off')
  234. figFileName = ['RFcurves-ON-OFF-Noise-XY-lasagna'];
  235. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  236. %%
  237. hFig = createPrintFig(15 * [1 1/2]);
  238. pairsToAverage = {[1, 2], [3, 4], [5, 6]};
  239. meanWidths = cellfun(@(x) mean(width(x, validInds)), pairsToAverage, 'uni', 0);
  240. meanWidths = cellfun(@(x) mean(width(x, validInds)), pairsToAverage, 'uni', 0);
  241. beanPlot(meanWidths, {'off', 'on', 'noise'}, flipud(brewermap(3, 'Set1')), 1, gca, [0-eps 50], 'vertical', false, true)
  242. figFileName = ['RF-ON-OFF-Noise-FWHM-Bean'];
  243. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  244. %% Save data for Fig 2f
  245. xlswrite(dataFileName, {'FHWM-OFF-bars'}, 'Fig2f', 'A1')
  246. xlswrite(dataFileName, meanWidths{1}, 'Fig2f', 'B1')
  247. xlswrite(dataFileName, {'FHWM-ON-bars'}, 'Fig2f', 'A2')
  248. xlswrite(dataFileName, meanWidths{2}, 'Fig2f', 'B2')
  249. xlswrite(dataFileName, {'FHWM-Noise-bars'}, 'Fig2f', 'A3')
  250. xlswrite(dataFileName, meanWidths{3}, 'Fig2f', 'B3')
  251. %% Permutation test for mean RF width difference.
  252. [pValOFFvsON, obsDiff] = permutationTest(meanWidths{1},meanWidths{2}, 100000)
  253. [pValONvsNoise, obsDiff] = permutationTest(meanWidths{2},meanWidths{3}, 100000)
  254. [pValOFFvsNoise, obsDiff] = permutationTest(meanWidths{1},meanWidths{3}, 100000)
  255. %%
  256. hFig = createPrintFig(15 * [1/2 1/2]);
  257. meanAmps = cellfun(@(x) mean(amp(x, validInds)), pairsToAverage(1:2), 'uni', 0);
  258. beanPlot(meanAmps, {'off', 'on'}, flipud(brewermap(3, 'Set1')), 1, gca,'unbounded', 'vertical', false, true)
  259. figFileName = ['RF-ON-OFF-Noise-Amp-Bean'];
  260. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  261. %% Save data for Fig 2f
  262. xlswrite(dataFileName, {'Amp-OFF-bars'}, 'Fig2f', 'A5')
  263. xlswrite(dataFileName, meanAmps{1}, 'Fig2f', 'B5')
  264. xlswrite(dataFileName, {'Amp-ON-bars'}, 'Fig2f', 'A6')
  265. xlswrite(dataFileName, meanAmps{2}, 'Fig2f', 'B6')
  266. %%
  267. % pairsToPlot = {[1 5], [2 6], [3 5], [4 6]};
  268. pairsToPlot = {[1 2], [3 4], [1 4], [1 3], [2 4], [2 3]};
  269. labelsCell = {'X OFF', 'Y OFF', 'X ON', 'Y ON', 'X Noise', 'Y Noise'};
  270. indsToPlot = validInds;
  271. % fwhmArray = [mean(width(1: 2, :)); mean(width(3: 4, :)); mean(width(5: 6, :))]';
  272. fwhmArray = width';
  273. rSquare = rsquare';
  274. % hFig = createFullScreenFig;
  275. % set(hFig, 'Units', 'Centimeters')
  276. % set(hFig, 'Position', [hFig.Position(1:2) + 10 14 14]);
  277. hFig = createPrintFig(15 * [ 1 2/3]);
  278. for iPair = 1: numel(pairsToPlot)
  279. hScattAx(iPair) = subplot(2, 3, iPair); hold on;
  280. xInd = pairsToPlot{iPair}(1);
  281. yInd = pairsToPlot{iPair}(2);
  282. scatter(fwhmArray(indsToPlot, xInd), fwhmArray(indsToPlot, yInd), [], ...
  283. min(rSquare(indsToPlot, xInd), rSquare(indsToPlot, yInd)), 'filled');
  284. [correlation, pValue] = corr(fwhmArray(indsToPlot, xInd), fwhmArray(indsToPlot, yInd), 'type', 'Pearson' );
  285. x = fwhmArray(indsToPlot, xInd);
  286. [b, bInt]= regress(fwhmArray(indsToPlot, yInd), [ones(length(x), 1) x]);
  287. hFit = plot(x, b(1) + x*b(2), 'Color', [1 1 1] * 0.5);
  288. maxVal = max([fwhmArray(indsToPlot, xInd); fwhmArray(indsToPlot, yInd)]);
  289. maxVal = quantile(vec(fwhmArray(indsToPlot, :)), 1);
  290. plot([0 maxVal], [0 maxVal], 'Color', [1 1 1] * 0.5);
  291. prettifyAxes(gca);
  292. set(gca, 'XLim', [0 maxVal], 'YLim', [0 maxVal], 'CLim', [0 1]);
  293. axis square;
  294. xlabel(labelsCell{xInd});
  295. ylabel(labelsCell{yInd});
  296. title({['\rho = ' num2str(correlation, 2) ', p = ' num2str(pValue, 2) ],...
  297. ['m = ' num2str(b(2), 2) ' (' num2str(bInt(2, 1), 2) ', ' num2str(bInt(2, 2), 2) ')']})
  298. setFavoriteColormap
  299. end
  300. setFontForThesis(hScattAx, gcf);
  301. arrayfun(@prettifyAxes, hScattAx)
  302. arrayfun(@offsetAxes, hScattAx)
  303. % set(hSubAx, 'Visible', 'off')
  304. figFileName = ['BarRFs-Corr-Pearson'];
  305. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  306. %%
  307. offWidth = mean(width(1: 2, indsToPlot), 1);
  308. onWidth = mean(width(3: 4, indsToPlot), 1);
  309. [corrWidth, pCorrWidth] = corr(offWidth(:), onWidth(:))
  310. %%
  311. offWidth = width(1: 2, indsToPlot);
  312. onWidth = width(3: 4, indsToPlot);
  313. [corrWidth, pCorrWidth] = corr(offWidth(:), onWidth(:))
  314. %%
  315. [corrWidth, pCorrWidth] = corr(width(1:4, indsToPlot)', 'type','Spearman' )