MakeFig_T5Tm9_SpaceTimeTuning_corr_Fig6.m 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. ccc
  2. %% Define search path.
  3. parentDir = fileparts(fileparts(mfilename('fullpath')));
  4. saveFolder = [parentDir filesep 'data'];
  5. load([saveFolder filesep 'Fig6-T5Tm9-processedTable'], 'ProcessedTable');
  6. %%
  7. figDir = [parentDir filesep 'figures' filesep 'Fig6' filesep];
  8. if ~exist(figDir, 'dir')
  9. mkdir(figDir);
  10. end
  11. %%
  12. stimSetCellStr = getStimSetCellStr(4);
  13. StimTable = getStimSubsetTable(ProcessedTable, stimSetCellStr, 7);
  14. tuningMethods = StimTable.nonParamTuning{1}(1).tuningMethods;
  15. fieldNamesToUse = {'spacing', 'temporalFrequency'};
  16. [ stimSize, sortedFieldNameInds, fieldNames, stimParamsFlat ] = ...
  17. StimulusDomain_ND( StimTable.stimParams{1}{1}, fieldNamesToUse );
  18. %%
  19. spacing = [StimTable.stimParams{1}{1}(2:end).spacing];
  20. stimtrans = [StimTable.stimParams{1}{1}(2:end).stimtrans];
  21. temporalFreq = unique([stimtrans.mean] ./ spacing);
  22. spatialFreq = 1 ./ unique(spacing);
  23. %%
  24. selectedTuningMethod = '1F_amplitude';
  25. tcRoiCell = cellfun(@(x) ...
  26. getTuningCurvePerROI(x(1).tc, tuningMethods, '1F_amplitude'), ...
  27. StimTable.nonParamTuning, 'uni', 0);
  28. tm9TCs = [tcRoiCell{:}];
  29. %%
  30. tcRoiCell = cellfun(@(x) ...
  31. getTuningCurvePerROI(x(2).tc, tuningMethods, '1F_amplitude'), ...
  32. StimTable.nonParamTuning, 'uni', 0);
  33. t5TCs = [tcRoiCell{:}];
  34. %%
  35. [xGrid, yGrid] = meshgrid(spatialFreq, temporalFreq);
  36. %% These are the maps which average is shown in figure 6g
  37. respIndex = cell2mat(StimTable.responseIndex')';
  38. validInds = all(respIndex > 0.5, 2);
  39. figure
  40. hAx = createSquarishSubplotGrid(sum(validInds));
  41. iAx = 1;
  42. for iRoi = find(validInds)'
  43. imagesc(hAx(iAx), t5TCs{iRoi})
  44. iAx = iAx + 1;
  45. end
  46. figure
  47. hAx = createSquarishSubplotGrid(sum(validInds));
  48. iAx = 1;
  49. for iRoi = find(validInds)'
  50. imagesc(hAx(iAx), tm9TCs{iRoi})
  51. iAx = iAx + 1;
  52. end
  53. %% Export maps for figure 6g
  54. % Columns are increasing temporal frequency, rows are increasing spatial
  55. % frequency. But transpose the array so it matches the spatial and temporal frequency
  56. % axes. Then columns are increasing spatial frequency and rows increasing
  57. % temporal frequency.
  58. [spatialFreqGrid, temporalFreqGrid] = meshgrid(spatialFreq, temporalFreq); % xGrid-space, yGrid-time
  59. % Create table to append columns with ROI tunint to it.
  60. DataTable = table(spatialFreqGrid(:), temporalFreqGrid(:), 'VariableNames', {'spatial_frequency_cycles_per_deg', 'temporal_frequency_Hz'});
  61. for iRoi = find(validInds)'
  62. tm9Map = tm9TCs{iRoi}';
  63. t5Map = t5TCs{iRoi}';
  64. DataTable.(sprintf(['ROI%d_Tm9_F1_amplitude'], iRoi)) = tm9Map(:);
  65. DataTable.(sprintf(['ROI%d_T5_F1_amplitude'], iRoi)) = t5Map(:);
  66. end
  67. dataFileName = [figDir filesep 'Fig6.xls'];
  68. sheetName = 'Fig6g';
  69. writetable(DataTable, dataFileName, 'Sheet', sheetName, 'Range', 'A1');
  70. %% Figure 6h
  71. hFig = createPrintFig(10*[1/3 1]);
  72. support = [-1-eps 1+eps];
  73. plotOrientation = 'vertical'; % Can change to plotHorizontalBool.
  74. halveBean = false;
  75. useAlpha = true;
  76. bwOption = true;
  77. mapCorrs = cellfun(@(x,y) corr2(x, y), t5TCs(validInds), tm9TCs(validInds));
  78. beanPlot({mapCorrs},{'Tm9-T5'},'k', 1, gca, support, plotOrientation, halveBean);
  79. % beanPlot({mapCorrs},{'Tm4-T5'},'k', 1, gca, support, plotOrientation, halveBean);
  80. print(gcf, [figDir 'tuningMap-corr-bean' '.pdf'], '-dpdf', '-r300');
  81. %% Export pairwise correlation values ffrom figure 6h
  82. labelStrCell = sprintfc(['ROI%d_T5vsTm9_F1_Amplitude_CorrelationCoefficient'], find(validInds));
  83. for iRow = 1: numel(labelStrCell)
  84. xlswrite(dataFileName, labelStrCell(iRow), 'Fig6h', ['A' num2str(iRow)])
  85. xlswrite(dataFileName, {mapCorrs(iRow)}, 'Fig6h', ['B' num2str(iRow)])
  86. end
  87. %% Shuffle control for correlation of maps for confidence interval in Fig 6h
  88. validT5TCs = t5TCs(validInds);
  89. validTm9TCs = tm9TCs(validInds);
  90. mapCorrs = cellfun(@(x,y) corr2(x, y), validT5TCs, validTm9TCs);
  91. nShuffles = 1000000;
  92. % exactShuffles = nchoosek(2 * sum(validInds), sum(validInds)); %even 14
  93. % gives 40116600 shuffles, so 1e6 is ok approximation
  94. shuffleMapCorrs = zeros(nShuffles, 1);
  95. for iShuffle = 1: nShuffles
  96. shuffleInds = randperm(numel(validTm9TCs));
  97. shuffleMapCorrs(iShuffle) = mean(cellfun(@(x,y) corr2(x, y), ...
  98. validT5TCs, ...
  99. validTm9TCs(shuffleInds)));
  100. end
  101. pValueCorrMaps = sum(shuffleMapCorrs > mean(mapCorrs)) / nShuffles;
  102. corrConfInt = arrayfun(@(x) quantile(shuffleMapCorrs, x), [0.05, 0.95]);
  103. meanShuffleCorr = mean(shuffleMapCorrs);
  104. %%
  105. % Plot spatial tuning by collapsing over temporal frequencies.
  106. spatialTuning{1} = cell2mat(cellfun(@(x) mean(x, 2)', t5TCs, 'uni', 0)');
  107. spatialTuning{2} = cell2mat(cellfun(@(x) mean(x, 2)', tm9TCs, 'uni', 0)');
  108. % Plot temporal tuning by collapsing over spatial frequencies.
  109. temporalTuning{1} = cell2mat(cellfun(@(x) mean(x, 1), t5TCs, 'uni', 0)');
  110. temporalTuning{2} = cell2mat(cellfun(@(x) mean(x, 1), tm9TCs, 'uni', 0)');
  111. %%
  112. spatialTuning = cellfun(@(x) x./max(x, [], 2), spatialTuning, 'uni', 0);
  113. temporalTuning = cellfun(@(x) x./max(x, [], 2), temporalTuning, 'uni', 0);
  114. validInds = all(respIndex > 0.5, 2); % Response quality threshold
  115. %% From here we get mean maps in figure 6g
  116. selectedTuningMethod = '1F_amplitude';
  117. createPrintFig(10*[1 1]);
  118. plotROISpatioTemporalTuning(spatialFreq, temporalFreq, mean(cat(3, t5TCs{validInds}), 3))
  119. print(gcf, [figDir 'tuningMap-roiMean-0p5respInd' selectedTuningMethod 'T5' '.pdf'], '-dpdf', '-r300');
  120. createPrintFig(10*[1 1]);
  121. plotROISpatioTemporalTuning(spatialFreq, temporalFreq, mean(cat(3, tm9TCs{validInds}), 3))
  122. print(gcf, [figDir 'tuningMap-roiMean-0p5respInd' selectedTuningMethod 'Tm9' '.pdf'], '-dpdf', '-r300');
  123. %%
  124. ProcessedTable = ProcessedTable(ProcessedTable.typeOfProblem == 0, :);
  125. for iFly = 1: numel(unique(ProcessedTable.flyInd))
  126. flyIndsCell = ProcessedTable.flyInd == iFly;
  127. flyStims = ProcessedTable(flyIndsCell, :).stimParamFileName;
  128. % Find if stim is within the chosen subset.
  129. flyStimInds{iFly} = (cellfun(@(x) find(strcmp(x, stimSetCellStr)), flyStims, 'uni', 0));
  130. % If it contains stimuli, check that it includes the 5 chosen.
  131. if ~isempty(flyStimInds{iFly})
  132. setDiff{iFly} = setdiff(1: 7, [flyStimInds{iFly}{:}]);
  133. else
  134. setDiff{iFly} = -1;
  135. end
  136. % For flies with all chosen stimuli order the table accordingly.
  137. if isempty(setDiff{iFly})
  138. sortFlyIndsTemp = find(flyIndsCell);
  139. [~, sortInd] = sort([flyStimInds{iFly}{:}]);
  140. sortFlyInds{iFly} = sortFlyIndsTemp(sortInd);
  141. end
  142. end
  143. StimOrderedTable = ProcessedTable(cat(1, sortFlyInds{:}), :);
  144. StimOrderedTable = StimOrderedTable(StimOrderedTable.flyInd~=7,:);
  145. %% Split table into cell types.
  146. tokens = arrayfun(@(x) regexp(x, '.*Tm(\d).*', 'tokens'), StimOrderedTable.timeSeriesPath);
  147. cellTypeNumArray = cellfun(@(x) str2num(x{1}{1}), tokens);
  148. cellTypeNum = unique(cellTypeNumArray);
  149. for iNeuron = 1: numel(cellTypeNum)
  150. StimTableNeuronCell{iNeuron} = StimOrderedTable(cellTypeNumArray == cellTypeNum(iNeuron), :);
  151. end
  152. %%
  153. stimInd = 1;
  154. nStims = numel(stimSetCellStr);
  155. for iNeuron = 1: numel(cellTypeNum)
  156. for jStim = 1: nStims
  157. StimTableNeuronStim{iNeuron, jStim} = getStimSubsetTable(StimTableNeuronCell{iNeuron}, stimSetCellStr, jStim);
  158. end
  159. end
  160. %% Extract the parameters for the analysis of spatial RFs.
  161. clear amp pos width rsquare responseIndex
  162. jBar = 1;
  163. for iStim = 2:5
  164. dummyTable = StimTableNeuronStim{1, iStim};
  165. for jChannel = 1: 2
  166. responseIndex{jChannel}(jBar, :) = cell2mat(cellfun(@(x, y) x(jChannel, 1: end - 1*0), dummyTable.responseIndex, 'uni', 0)');
  167. paramsCell = cellfun(@(x) x(jChannel, 1: end - 1*0), dummyTable.paramTuning, 'uni', 0);
  168. amp{jChannel}(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.a1, x, 'uni', 1), paramsCell, 'uni', 0)');
  169. pos{jChannel}(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.b1, x, 'uni', 1), paramsCell, 'uni', 0)');
  170. width{jChannel}(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.fit.c1, x, 'uni', 1), paramsCell, 'uni', 0)');
  171. rsquare{jChannel}(jBar, :) = cell2mat(cellfun(@(x) arrayfun(@(y) y.gof.rsquare, x, 'uni', 1), paramsCell, 'uni', 0)');
  172. end
  173. jBar = jBar + 1;
  174. end
  175. pos = cellfun(@(x) 2 * (x - 1), pos, 'uni', 0);
  176. width = cellfun(@(x) 2 * (2 * sqrt(log(2))) * x, width, 'uni', 0);
  177. %%
  178. flyInds = repelem(1:size(StimTableNeuronStim{1}), ...
  179. cellfun(@(x) size(x, 2), StimTableNeuronStim{1}.responseIndex));
  180. responseIndexOff = cat(1, responseIndex{1}(1:2, :), responseIndex{2}(1:2, :));
  181. rSquareOff = cat(1, rsquare{1}(1:2, :), rsquare{2}(1:2, :));
  182. minOffRSquare = cell2mat(cellfun(@(x) min(x(1:2, :)), rsquare, 'uni', 0)');
  183. minOnRSquare = cell2mat(cellfun(@(x) min(x(3:4, :)), rsquare, 'uni', 0)');
  184. thresholdRSquare = 0.25;
  185. minRSquare = min(minOffRSquare);
  186. minRespInd = min(responseIndexOff);
  187. isAboveThreshold = minRSquare > thresholdRSquare & minRespInd > 0.3;
  188. %% Figure 6f and supplementary figure 5a
  189. responseIndexOff = cat(1, responseIndex{1}(1:2, :), responseIndex{2}(1:2, :));
  190. responseIndexOn = cat(1, responseIndex{1}(3:4, :), responseIndex{2}(3:4, :));
  191. rSquareOff = cat(1, rsquare{1}(1:2, :), rsquare{2}(1:2, :));
  192. rSquareOn = cat(1, rsquare{1}(3:4, :), rsquare{2}(3:4, :));
  193. minOffRSquare = cell2mat(cellfun(@(x) min(x(1:2, :)), rsquare, 'uni', 0)');
  194. minOnRSquare = cell2mat(cellfun(@(x) min(x(3:4, :)), rsquare, 'uni', 0)');
  195. plotOFF = true;
  196. if plotOFF
  197. minRespInd = min(responseIndexOff);
  198. thresholdRSquare = 0.25;
  199. minRSquare = min(minOffRSquare);
  200. isAboveThreshold = minRSquare > thresholdRSquare & minRespInd > 0.3;
  201. else
  202. if 0
  203. minRespInd = max(responseIndexOn);
  204. thresholdRSquare = 0;
  205. minRSquare = max(minOnRSquare);
  206. isAboveThreshold = minRSquare > thresholdRSquare & minRespInd > 0.3;
  207. else
  208. minRespInd = min(responseIndexOff);
  209. thresholdRSquare = 0.25;
  210. minRSquare = min(minOffRSquare);
  211. isAboveThreshold = minRSquare > thresholdRSquare & minRespInd > 0.3;
  212. end
  213. end
  214. clear hSubAx
  215. hFig = createPrintFig(20 * [1 2/3]);
  216. set(hFig,'color','w');
  217. colorLims = [-1 1] + 0*thresholdRSquare;
  218. fitParamsCell = {width , pos};
  219. for jOrientation = 1: 2
  220. for iParam = 1: numel(fitParamsCell)
  221. iAx = numel(fitParamsCell) * (jOrientation - 1) + iParam;
  222. hSubAx(iAx) = subplot(2, numel(fitParamsCell), iAx);
  223. if plotOFF
  224. x = fitParamsCell{iParam}{1}(jOrientation, isAboveThreshold);
  225. y = fitParamsCell{iParam}{2}(jOrientation, isAboveThreshold);
  226. else
  227. x = fitParamsCell{iParam}{1}(2 + jOrientation, isAboveThreshold);
  228. y = fitParamsCell{iParam}{2}(2 + jOrientation, isAboveThreshold);
  229. end
  230. hScatter = scatter(x, y, [], [1 1 1]*0.25, 'filled', 'MarkerFaceAlpha', 1);
  231. minVal = min([hSubAx(iAx).XLim(1) hSubAx(iAx).YLim(1)]);
  232. maxVal = min([hSubAx(iAx).XLim(2) hSubAx(iAx).YLim(2)]);
  233. lsline
  234. line([minVal maxVal], [minVal maxVal], 'Color', 0.5 * [1 1 1]);
  235. hChildren = get(hSubAx(iAx), 'Children');
  236. set(gca, 'Children', [hChildren(end); hChildren(1: end - 1)]);
  237. axis square;
  238. [corrCoef, p] = corr(x(:), y(:));
  239. legStr = ['n = ' num2str(numel(x)) ', corr = ' num2str(corrCoef, 2) ', p = ' num2str(p, 2)];
  240. hLeg = legend(hScatter, legStr, 'Location', 'northoutside');
  241. hLeg.Box = 'off';
  242. end
  243. end
  244. linkaxes(hSubAx([1,3]), 'xy')
  245. linkaxes(hSubAx([2,4]), 'xy')
  246. hYLabel(1) = ylabel(hSubAx(1), 'T5 OFF RF FWHM Horizontal Bar (deg)');
  247. hXLabel(1) = xlabel(hSubAx(1), 'Tm9 OFF RF FWHM Horizontal Bar (deg)');
  248. hYLabel(2) = ylabel(hSubAx(2), 'T5 OFF RF Center Horizontal Bar (deg)');
  249. hXLabel(2) = xlabel(hSubAx(2), 'Tm9 OFF RF Center Horizontal Bar (deg)');
  250. hYLabel(3) = ylabel(hSubAx(3), 'T5 OFF RF FWHM Vertical Bar (deg)');
  251. hXLabel(3) = xlabel(hSubAx(3), 'Tm9 OFF RF FWHM Vertical Bar (deg)');
  252. hYLabel(4) = ylabel(hSubAx(4), 'T5 OFF RF Center Vertical Bar (deg)');
  253. hXLabel(4) = xlabel(hSubAx(4), 'Tm9 OFF RF Center Vertical Bar (deg)');
  254. [hXLabel.FontSize] = deal(10);
  255. [hYLabel.FontSize] = deal(10);
  256. hLeg.FontSize = 8;
  257. [hSubAx.FontSize] = deal(8);
  258. [hSubAx.Color] = deal('none');
  259. arrayfun(@prettifyAxes, [hSubAx]);
  260. if plotOFF
  261. print(gcf, [figDir 'rfFitParamsScatter-Off-rSquare-' num2str(thresholdRSquare) '.pdf'], '-dpdf', '-r300');
  262. else
  263. print(gcf, [figDir 'rfFitParamsScatter-On-rSquare-' num2str(thresholdRSquare) '.pdf'], '-dpdf', '-r300');
  264. end
  265. %% Export data for figure 6f ans supplementary figure 6a
  266. tm9XFWHM = width{1}(1, isAboveThreshold);
  267. t5XFWHM = width{2}(1, isAboveThreshold);
  268. tm9YFWHM = width{1}(2, isAboveThreshold);
  269. t5YFWHM = width{2}(2, isAboveThreshold);
  270. tm9XPos = pos{1}(1, isAboveThreshold);
  271. t5XPos = pos{2}(1, isAboveThreshold);
  272. tm9YPos = pos{1}(2, isAboveThreshold);
  273. t5YPos = pos{2}(2, isAboveThreshold);
  274. DataTable = table(tm9XFWHM(:), t5XFWHM(:), tm9YFWHM(:), t5YFWHM(:), ...
  275. tm9XPos(:), t5XPos(:), tm9YPos(:), t5YPos(:), ...
  276. 'VariableNames', ...
  277. {'Tm9_OFF_RF_FWHM_Horizontal_Bar_deg', ...
  278. 'T5_OFF_RF_FWHM_Horizontal_Bar_deg', ...
  279. 'Tm9_OFF_RF_FWHM_Vertical_Bar_deg', ...
  280. 'T5_OFF_RF_FWHM_Vertical_Bar_deg', ...
  281. 'Tm9_OFF_RF_Position_Horizontal_Bar_deg', ...
  282. 'T5_OFF_RF_Position_Horizontal_Bar_deg', ...
  283. 'Tm9_OFF_RF_Position_Vertical_Bar_deg', ...
  284. 'T5_OFF_RF_Position_Vertical_Bar_deg', ...
  285. });
  286. dataFileName = [figDir filesep 'Fig6.xls'];
  287. sheetName = 'Fig6f';
  288. writetable(DataTable(:, 1: 4), dataFileName, 'Sheet', sheetName, 'Range', 'A1');
  289. sheetName = 'SuppFig6ab';
  290. writetable(DataTable(:, 5: 8), dataFileName, 'Sheet', sheetName, 'Range', 'A1');
  291. %% Reply to reviwer#1 comment 5
  292. doBootstrap = 0;
  293. xH = vec(width{1}(1, isAboveThreshold));
  294. yH = vec(width{2}(1, isAboveThreshold));
  295. xV = vec(width{1}(2, isAboveThreshold));
  296. yV = vec(width{2}(2, isAboveThreshold));
  297. tmpInds = flyInds(isAboveThreshold);
  298. nValidFlies = numel(unique(tmpInds));
  299. iAx = 1;
  300. clear hSubAx
  301. mSize = 15;
  302. hFig = createPrintFig(25 * [1 1/3]);
  303. for iFly = unique(tmpInds)
  304. hSubAx(iAx, 1) = subplot(2, nValidFlies, iAx);
  305. x = xH(iFly == tmpInds);
  306. y = yH(iFly == tmpInds);
  307. scatter(xH, yH, mSize, 'filled', 'MarkerFaceAlpha', 0.1, 'MarkerFaceColor', 'k');
  308. hold on;
  309. hScatter = scatter(x, y, mSize);
  310. hLines = lsline;
  311. delete(hLines(2));
  312. % refline(1,0)
  313. if doBootstrap && numel(x) > 1
  314. [bootstrapCorrCI, bootstrapCorrs] = bootci(10000, @corr, x(:), y(:));
  315. legStr = sprintf('n = %d\ncorr = %.2f\n0.95-CI = [%.2f, %.2f]', ...
  316. numel(x), mean(bootstrapCorrs), bootstrapCorrCI);
  317. else
  318. [corrCoef, p] = corr(x(:), y(:));
  319. legStr = ['n = ' num2str(numel(x)) ...
  320. ', \n corr = ' num2str(corrCoef, 2) ', \n p = ' num2str(p, 2)];
  321. % hLeg = legend(hScatter, legStr, 'Location', 'northoutside');
  322. end
  323. % hLeg.Box = 'off';
  324. title(sprintf(legStr));
  325. corrArray(iAx, 1) = corrCoef;
  326. hSubAx(iAx, 2) = subplot(2, nValidFlies, nValidFlies + iAx);
  327. x = xV(iFly == tmpInds);
  328. y = yV(iFly == tmpInds);
  329. scatter(xV, yV, mSize, 'filled', 'MarkerFaceAlpha', 0.1, 'MarkerFaceColor', 'k');
  330. hold on;
  331. hScatter = scatter(x, y, mSize);
  332. hLines = lsline;
  333. delete(hLines(2));
  334. if doBootstrap && numel(x) > 1
  335. [bootstrapCorrCI, bootstrapCorrs] = bootci(10000, @corr, x(:), y(:));
  336. legStr = sprintf('n = %d\ncorr = %.2f\n0.95-CI = [%.2f, %.2f]', ...
  337. numel(x), mean(bootstrapCorrs), bootstrapCorrCI);
  338. else
  339. [corrCoef, p] = corr(x(:), y(:));
  340. legStr = ['n = ' num2str(numel(x)) ...
  341. '\n corr = ' num2str(corrCoef, 2) '\n p = ' num2str(p, 2)];
  342. % hLeg = legend(hScatter, legStr, 'Location', 'northoutside');
  343. end
  344. title(sprintf(legStr))
  345. corrArray(iAx, 2) = corrCoef;
  346. iAx = iAx + 1;
  347. end
  348. axis(hSubAx, 'square');
  349. linkaxes(hSubAx, 'xy')
  350. clear hXLabel hYLabel
  351. hXLabel(1) = xlabel(hSubAx(1, 1), 'Tm9 fwhm hor. (deg)');
  352. hYLabel(1) = ylabel(hSubAx(1, 1), 'T5 fwhm hor. (deg)');
  353. hXLabel(2) = xlabel(hSubAx(1, 2), 'Tm9 fwhm vert. (deg)');
  354. hYLabel(2) = ylabel(hSubAx(1, 2), 'T5 fwhm vert. (deg)');
  355. [hXLabel(1).FontSize] = deal(10);
  356. [hYLabel(1).FontSize] = deal(10);
  357. % hLeg.FontSize = 8;
  358. [hSubAx.FontSize] = deal(8);
  359. [hSubAx.Color] = deal('none');
  360. arrayfun(@prettifyAxes, [hSubAx]);
  361. print(gcf, [figDir 'rfFwhmScatterPerFly-Off-rSquare-' num2str(thresholdRSquare) '.pdf'], '-dpdf', '-r300');
  362. %% average values within fly and plot
  363. % fly means
  364. xHFlyMeans = accumarray(tmpInds', xH, [], @mean);
  365. yHFlyMeans = accumarray(tmpInds', yH, [], @mean);
  366. xHFlyStds = accumarray(tmpInds', xH, [], @std);
  367. yHFlyStds = accumarray(tmpInds', yH, [], @std);
  368. xHFlyMins = accumarray(tmpInds', xH, [], @min);
  369. yHFlyMins = accumarray(tmpInds', yH, [], @min);
  370. xHFlyMaxs = accumarray(tmpInds', xH, [], @max);
  371. yHFlyMaxs = accumarray(tmpInds', yH, [], @max);
  372. [x, y] = deal(xHFlyMeans(xHFlyMeans~=0), yHFlyMeans(xHFlyMeans~=0));
  373. [xStd, yStd] = deal(xHFlyStds(xHFlyMeans~=0), yHFlyStds(xHFlyMeans~=0));
  374. [xMin, yMin] = deal(xHFlyMins(xHFlyMeans~=0), yHFlyMins(xHFlyMeans~=0));
  375. [xMax, yMax] = deal(xHFlyMaxs(xHFlyMeans~=0), yHFlyMaxs(xHFlyMeans~=0));
  376. hFig = createPrintFig(7 * [1 1]);
  377. hScatter = errorbar(x, y, xMin - x, xMax - x, yMin - y, yMax - y, ...
  378. 'LineStyle', 'none', 'CapSize', 0, 'LineWidth', 1, ...
  379. 'Color', [1 1 1] * 0.4);
  380. hold on
  381. hScatter = scatter(x, y, 25, 'filled', 'MarkerFaceColor', [1 1 1] * 0.20);
  382. lsline
  383. if doBootstrap && numel(x) > 1
  384. [bootstrapCorrCI, bootstrapCorrs] = bootci(10000, @corr, x(:), y(:));
  385. legStr = sprintf('n = %d, corr = %.2f\n0.95-CI = [%.2f, %.2f]', ...
  386. numel(x), mean(bootstrapCorrs), bootstrapCorrCI);
  387. else
  388. [corrCoef, p] = corr(x(:), y(:));
  389. legStr = ['n = ' num2str(numel(x)) ...
  390. ', \n corr = ' num2str(corrCoef, 2) ', \n p = ' num2str(p, 2)];
  391. end
  392. title(sprintf(legStr));
  393. xlabel('Tm9 fwhm hor. (deg)');
  394. ylabel('T5 fwhm hor. (deg)');
  395. % hLeg = legend(hScatter, legStr, 'Location', 'northoutside');
  396. % hLeg.Box = 'off';
  397. prettifyAxes(gca);
  398. print(gcf, [figDir 'rfFwhmScatterFlyMeans-XOff-rSquare-' num2str(thresholdRSquare) '.pdf'], '-dpdf', '-r300');
  399. %% Same fo vertical
  400. xHFlyMeans = accumarray(tmpInds', xV, [], @mean);
  401. yHFlyMeans = accumarray(tmpInds', yV, [], @mean);
  402. xHFlyStds = accumarray(tmpInds', xV, [], @std);
  403. yHFlyStds = accumarray(tmpInds', yV, [], @std);
  404. xHFlyMins = accumarray(tmpInds', xV, [], @min);
  405. yHFlyMins = accumarray(tmpInds', yV, [], @min);
  406. xHFlyMaxs = accumarray(tmpInds', xV, [], @max);
  407. yHFlyMaxs = accumarray(tmpInds', yV, [], @max);
  408. [x, y] = deal(xHFlyMeans(xHFlyMeans~=0), yHFlyMeans(xHFlyMeans~=0));
  409. [xStd, yStd] = deal(xHFlyStds(xHFlyMeans~=0), yHFlyStds(xHFlyMeans~=0));
  410. [xMin, yMin] = deal(xHFlyMins(xHFlyMeans~=0), yHFlyMins(xHFlyMeans~=0));
  411. [xMax, yMax] = deal(xHFlyMaxs(xHFlyMeans~=0), yHFlyMaxs(xHFlyMeans~=0));
  412. hFig = createPrintFig(7 * [1 1]);
  413. hScatter = errorbar(x, y, xMin - x, xMax - x, yMin - y, yMax - y, ...
  414. 'LineStyle', 'none', 'CapSize', 0, 'LineWidth', 1, ...
  415. 'Color', [1 1 1] * 0.4);
  416. % hScatter = errorbar(x, y, -xStd, xStd, -yStd, yStd, ...
  417. % 'LineStyle', 'none', 'CapSize', 0, 'LineWidth', 1, ...
  418. % 'Color', [1 1 1] * 0.2);
  419. hold on
  420. hScatter = scatter(x, y, 25, 'filled', 'MarkerFaceColor', [1 1 1] * 0.20);
  421. lsline
  422. if doBootstrap && numel(x) > 1
  423. [bootstrapCorrCI, bootstrapCorrs] = bootci(10000, @corr, x(:), y(:));
  424. legStr = sprintf('n = %d, corr = %.2f\n0.95-CI = [%.2f, %.2f]', ...
  425. numel(x), mean(bootstrapCorrs), bootstrapCorrCI);
  426. else
  427. [corrCoef, p] = corr(x(:), y(:));
  428. legStr = ['n = ' num2str(numel(x)) ...
  429. ', \n corr = ' num2str(corrCoef, 2) ', \n p = ' num2str(p, 2)];
  430. end
  431. title(sprintf(legStr));
  432. xlabel('Tm9 fwhm vert. (deg)');
  433. ylabel('T5 fwhm vert. (deg)');
  434. % hLeg = legend(hScatter, legStr, 'Location', 'northoutside');
  435. % hLeg.Box = 'off';
  436. prettifyAxes(gca);
  437. print(gcf, [figDir 'rfFwhmScatterFlyMeans-YOff-rSquare-' num2str(thresholdRSquare) '.pdf'], '-dpdf', '-r300');
  438. %% Check RF position distribution
  439. xH = vec(pos{1}(1, isAboveThreshold));
  440. yH = vec(pos{2}(1, isAboveThreshold));
  441. xV = vec(pos{1}(2, isAboveThreshold));
  442. yV = vec(pos{2}(2, isAboveThreshold));
  443. tmpInds = flyInds(isAboveThreshold);
  444. nValidFlies = numel(unique(tmpInds));
  445. iAx = 1;
  446. hFig = createPrintFig(7 * [ 1 2/3]);
  447. hHAx(1) = subplot(1, 2, 1);
  448. hHist(1) = histogram(xH - yH);
  449. hHAx(2) = subplot(1, 2, 2);
  450. hHist(2) = histogram(xV - yV);
  451. [hHist.EdgeColor] = deal('w');
  452. [hHist.FaceColor] = deal([1 1 1] * 0.0);
  453. title(hHAx(1), {'Hor. RF Pos.', '(Tm9 - T5)'});
  454. title(hHAx(2), {'Hor. RF Pos.', '(Tm9 - T5)'});
  455. xlabel(hHAx(1), 'RF Pos. Diff. (deg)');
  456. arrayfun(@prettifyAxes, hHAx);
  457. setFontForThesis(hHAx, hFig);
  458. print(gcf, [figDir 'rfPosDiffScatter-Off-rSquare-' num2str(thresholdRSquare) '.pdf'], '-dpdf', '-r300');
  459. %% Extract the parameters for the analysis of spatial RFs.
  460. % clear amp pos width rsquare responseIndex
  461. tuningMethod = 'median';
  462. StimTableTmp = StimTableNeuronStim{2};
  463. tuningInd = strcmp(tuningMethod, StimTableTmp.nonParamTuning{1}(1).tuningMethods);
  464. jBar = 1;
  465. for iStim = 2:5
  466. dummyTable = StimTableNeuronStim{1, iStim};
  467. for jChannel = 1: 2
  468. responseIndex{jChannel}(jBar, :) = cell2mat(cellfun(@(x, y) x(jChannel, 1: end - 1*0), dummyTable.responseIndex, 'uni', 0)');
  469. % Hard coded getting rid of background ROI, but this should also be
  470. % imporved to handle the roiMeta field to discard invalid ROIs
  471. % (rois with NaNs)
  472. tuningCurves{jChannel}(jBar, :) = cellfun(@(x) squeeze(x(jChannel).tc{tuningInd}(:, 1: end - 1, :)), ...
  473. dummyTable.nonParamTuning, 'uni', 0);
  474. end
  475. jBar = jBar + 1;
  476. end
  477. %% Plot tuning curves.
  478. for iStim = 1: 4
  479. tm9AllTCs{iStim} = cat(1, tuningCurves{1}{iStim, :});
  480. t5AllTCs{iStim} = cat(1, tuningCurves{2}{iStim, :});
  481. end
  482. % Align to fit
  483. % pos is already original parameter b1 as 2*(b1 - 1)
  484. lagsCell = cellfun(@(x, y) round(x/2+1 - size(y, 2) / 2), ...
  485. mat2cell(pos{1}, [1 1 1 1])', tm9AllTCs, 'uni', 0);
  486. Tm9BarRFs = cellfun(@(x, y) alignRFsToAbsMax(x, 0, y'), tm9AllTCs, lagsCell, 'uni', 0);
  487. lagsCell = cellfun(@(x, y) round(x/2+1 - size(y, 2) / 2), ...
  488. mat2cell(pos{2}, [1 1 1 1])', t5AllTCs, 'uni', 0);
  489. T5BarRFs = cellfun(@(x, y) alignRFsToAbsMax(x, 0, y'), t5AllTCs, lagsCell, 'uni', 0);
  490. %% Blank epoch was already deleted, now delete vertical bars on edges of screen.
  491. Tm9BarRFs{2}(:, end-1: end) = [];
  492. Tm9BarRFs{4}(:, end-1: end) = [];
  493. Tm9BarRFs{2}(:, 1: 2) = [];
  494. Tm9BarRFs{4}(:, 1: 2) = [];
  495. T5BarRFs{2}(:, end-1: end) = [];
  496. T5BarRFs{4}(:, end-1: end) = [];
  497. T5BarRFs{2}(:, 1: 2) = [];
  498. T5BarRFs{4}(:, 1: 2) = [];
  499. %% Plot only analyzed OFF RFs.
  500. minRespInd = min(responseIndexOff);
  501. thresholdRSquare = 0.25;
  502. minRSquare = min(minOffRSquare);
  503. isAboveThreshold = minRSquare > thresholdRSquare & minRespInd > 0.3;
  504. Tm9BarRFs = cellfun(@(x) x(isAboveThreshold, :), Tm9BarRFs, 'uni', 0);
  505. T5BarRFs = cellfun(@(x) x(isAboveThreshold, :), T5BarRFs, 'uni', 0);
  506. %%
  507. % Plot lasagna plots, separate figures for off and on, and reapeated panel
  508. % is to have a colorbar that does not distort existing axis of interest.
  509. hFig = createPrintFig(15 * [ 1 1/4]);
  510. hSubAx = plotLasagnaTracesFromCell(gcf, [Tm9BarRFs, Tm9BarRFs(1)], brewermap(6, 'Paired'));
  511. colorbar
  512. arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'on'), hSubAx([1, 3], 1));
  513. arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'off'), hSubAx(2: end, 2));
  514. arrayfun(@prettifyAxes, hSubAx)
  515. arrayfun(@offsetAxes, hSubAx)
  516. arrayfun(@(x) set(x, 'Color', 'none'), hSubAx);
  517. % set(hSubAx, 'Visible', 'off')
  518. linkaxes(hSubAx(1: 2, 1), 'y')
  519. linkaxes(hSubAx(3: 4, 1), 'y')
  520. hFig.Color = 'none';
  521. figFileName = ['Tm9-RFcurves-OFF-XY-lasagna'];
  522. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  523. %%
  524. hFig = createPrintFig(15 * [ 1 1/4]);
  525. hSubAx = plotLasagnaTracesFromCell(gcf, [T5BarRFs, T5BarRFs(1)], brewermap(6, 'Paired'));
  526. colorbar
  527. arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'on'), hSubAx([1, 3], 1));
  528. arrayfun(@(x) set(get(x, 'YAxis'), 'Visible', 'off'), hSubAx(2: end, 2));
  529. arrayfun(@prettifyAxes, hSubAx)
  530. arrayfun(@offsetAxes, hSubAx)
  531. arrayfun(@(x) set(x, 'Color', 'none'), hSubAx);
  532. % set(hSubAx, 'Visible', 'off')
  533. linkaxes(hSubAx(1: 2, 1), 'y')
  534. linkaxes(hSubAx(3: 4, 1), 'y')
  535. hFig.Color = 'none';
  536. figFileName = ['T5-RFcurves-OFF-XY-lasagna'];
  537. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  538. %% Export data for figure 6b-e
  539. receptiveFields = [Tm9BarRFs; T5BarRFs];
  540. dataFileName = [figDir filesep 'Fig6.xls'];
  541. cellTypeStr = {'Tm9', 'T5'};
  542. sheetNamesCell = {'bc', 'de'};
  543. stimNameStrCell = {'_OFF_horizontal_position_deg', '_OFF_vertical_position_deg', ...
  544. '_ON_horizontal_position_deg', '_ON_vertical_position_deg'};
  545. for iCellType = 1: numel(cellTypeStr)
  546. startRow = 1;
  547. sheetName = ['Fig6' sheetNamesCell{iCellType}];
  548. for iStim = 1: 4
  549. parameterLabel = [cellTypeStr{iCellType} stimNameStrCell{iStim}];
  550. DataTable = createRFsTable(receptiveFields{iCellType, iStim}, parameterLabel);
  551. writetable(DataTable, dataFileName, 'Sheet', sheetName, 'Range', ['A' num2str(startRow)]);
  552. startRow = startRow + size(DataTable, 1) + 2;
  553. end
  554. end
  555. %% Tests if T5 ON response is 0 for reviewer #2
  556. xH = vec(amp{1}(3, isAboveThreshold));
  557. yH = vec(amp{2}(3, isAboveThreshold));
  558. xV = vec(amp{1}(4, isAboveThreshold));
  559. yV = vec(amp{2}(4, isAboveThreshold));
  560. % use minimum for negative ON response.
  561. minPeaks = cellfun(@(x) min(x, [], 2), T5BarRFs(3: 4), 'uni', 0);
  562. tcStd = cellfun(@(x) std(x, [], 2), T5BarRFs(3: 4), 'uni', 0);
  563. peakStdRatio = cellfun(@(x, y) x ./ y, minPeaks, tcStd, 'uni', 0);
  564. % figure
  565. % for iAx = 1: 2
  566. % subplot(1, 2, iAx);
  567. % histogram(peakStdRatio{iAx})
  568. % end
  569. % check if the fitted amplitude is higher than the tuning curve values
  570. % (noise), signrank uses x - y, so tc - amp shuould be positive for a
  571. % smaller amplitude (larger negative peak), so we need right tail test.
  572. [pValCell, isSignificant] = cellfun(@(x, y) arrayfun(@(z) signrank(x(z, :), y(z), 'tail', 'right'), 1: numel(y)), ...
  573. T5BarRFs(3: 4), {yH, yV}, 'uni', 0);
  574. proportionSignificant = cellfun(@(x) sum(x) / numel(x), isSignificant);
  575. clear hAx
  576. hFig = createPrintFig(15 * [3/4 1]);
  577. hAx(1) = subplot(3, 2, 1);
  578. histogram(yH);
  579. hAx(2) = subplot(3, 2, 2);
  580. histogram(yV);
  581. for iAx = 1: 2
  582. hAx(2 + iAx) = subplot(3, 2, 2 * iAx + 1);
  583. histogram(pValCell{iAx}, 'NumBins', 100);
  584. end
  585. hAx(5) = subplot(3, 2, [4, 6]);
  586. hBar = bar([proportionSignificant; 1 - proportionSignificant]', 'stacked');
  587. hLeg = legend(hAx(5), {'p < 0.05', 'p >= 0.05'}, 'Location', 'best');
  588. hAx(5).XTickLabels = {'Hor.', 'Vert.'};
  589. ylim([0 1])
  590. suptitle('T5 Responses to ON bars')
  591. arrayfun(@prettifyAxes, hAx);
  592. setFontForThesis(hAx, hFig);
  593. xLabelCell = {'Amplitude Hor. (\Delta F / F_0)', ...
  594. 'Amplitude Vert. (\Delta F / F_0)', ...
  595. '', 'p-Value', 'Bar orientation'};
  596. yLabelCell = {'No. ROIs', '', 'No. ROIs', 'No. ROIs', 'Proportion of ROIs'};
  597. arrayfun(@(x, y) xlabel(x, y), hAx, xLabelCell);
  598. arrayfun(@(x, y) ylabel(x, y), hAx, yLabelCell);
  599. figFileName = ['T5-ON-Amp-XY-stats'];
  600. print(hFig, [figDir figFileName '.pdf'], '-dpdf')
  601. %%
  602. function tcRoiCell = getTuningCurvePerROI(tc, tuningMethods, selectedTuningMethod)
  603. %% Expose single Roi tuning maps.
  604. % The epochs are varying first in the spacing then in the temporal
  605. % frequency, so tc consists of 1 x nTFreqs and each element is of shape
  606. % 1 x nRois x nSFreqs.
  607. % Here we first extract per Roi the nSFreqs tuning, as column vector, and
  608. % concatenate the nTFreqs column vectors arising this way to get a tuning
  609. % matrix of nSFreqs x nTFreqs.
  610. % tc1F = tc(:, strcmp(tuningMethods, '1F_amplitude'));
  611. tc = tc(:, strcmp(tuningMethods, selectedTuningMethod));
  612. tcRoiCell = cell(1, size(tc{1}, 2));
  613. for iRoi = 1: size(tc{1}, 2)
  614. tcRoiCell{iRoi} = cell2mat(cellfun(@(x) squeeze(x(:, iRoi, :)), tc, 'uni', 0)');
  615. end
  616. if 0
  617. % Try to reshape the tc into one tc array for each roi. is equivalent but
  618. % maybe less clear. First concatenate along stim dimension to get an array
  619. % of dims 1 x nRois x (nSFreqs x nTFreqs), squeeze it to get an array of
  620. % dims nRois x (nSFreqs x nTFreqs), and reshape it into an array of dims
  621. % nRois x nSFreqs x nTFreqs. Now we slice it along the first dimension into
  622. % a cell array of nRois x 1, each cell being nSFreqs x nTFreqs.
  623. tcRoiCell = mat2cell(reshape(squeeze(cat(3, tc{:})), sizeTC(2), sizeTC(3), []), ...
  624. ones(1, sizeTC(2)), stimSizeTC(1), stimSizeTC(2));
  625. end
  626. end