Shadron_Pena_Fig1.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. %% Does the actual reliability calculations. Ruff removed HRTF's have less
  2. % directions, so downsample normal files. Makes things go faster too.
  3. clear
  4. %update these paths
  5. cd('F:\MATLAB\')
  6. addpath('F:\MATLAB\Brian_Reliability\Scripts')
  7. % % Load HRIRs
  8. owl_folder{1}='Merry';
  9. owl_folder{2}='Owl19';
  10. owl_folder{3}='Owl39';
  11. owl_folder{4}='Ugly';
  12. owl_folder{5}='Vespucci';
  13. haircut_id{1}='normal';
  14. haircut_id{2}='ohne'; % maximum cut
  15. date_folder = '06-06-22 Data'; %change to current date if rerunning next section
  16. %% Full analysis of reliability. Takes a while...
  17. % Once this is done once, this and the next section can be skipped. Could
  18. % add another if loop to automatically skip this section.
  19. tic
  20. for o=2:5
  21. for h=1:2
  22. clearvars -except h haircut_id o owl_folder date_folder
  23. load(['HRTF_Wagner_Lab\results\' owl_folder{o} '\' owl_folder{o} '__' haircut_id{h} '__hrir_result.mat'])
  24. newazimuths = -160:20:160;
  25. newelevations = -60:20:80;
  26. dir=NaN(2,length(azimuths)*length(elevations));
  27. TF1=NaN(length(azimuths)*length(elevations),size(hrir_l,3));
  28. TF2=NaN(length(azimuths)*length(elevations),size(hrir_l,3));
  29. count=0;
  30. for a=1:length(azimuths)
  31. for e=1:length(elevations)
  32. count=count+1;
  33. dir(:,count)=[elevations(e);azimuths(a)];
  34. TF1(count,:)=hrir_l(a,e,:);
  35. TF2(count,:)=hrir_r(a,e,:);
  36. end
  37. end
  38. newdir=NaN(2,length(newazimuths)*length(newelevations));
  39. count=0;
  40. for a=1:length(newazimuths)
  41. for e=1:length(newelevations)
  42. count=count+1;
  43. newdir(:,count)=[newelevations(e);newazimuths(a)];
  44. end
  45. end
  46. dir = dir';
  47. newdir = newdir';
  48. downsample = ismember(dir, newdir, 'rows');
  49. TF1 = TF1(downsample, :);
  50. TF2 = TF2(downsample, :);
  51. dir = newdir';
  52. azimuth = newazimuths;
  53. elevation = newelevations;
  54. clear newdir newazimuth newelevation
  55. % % Analysis parameters
  56. %center frequencies of cochlear filters (Hz)
  57. cF = 400:200:10000;
  58. %cF = linspace(1000,9000, 9);
  59. n_cF=length(cF);
  60. %Sampling frequency for HRTFs (Hz)
  61. Fs = samplingrate;
  62. %Factor by which you will upsample
  63. Factor = 5;
  64. %Number of trials for each condition
  65. Nt=5;
  66. % % Get cochlear filters
  67. %Upsampled frequency
  68. FS=Fs*Factor;
  69. %Get filters
  70. fcoefs=getFilterCoefs(cF,FS);
  71. % % Number of directions and initialize
  72. nd_tot=size(TF1,1);
  73. n_dir = size(TF1,1);
  74. IPDm_all = zeros(n_dir, n_cF, Nt);
  75. IPDs_all = zeros(n_dir, n_cF, Nt);
  76. % ITDm=zeros(n_dir,n_cF);
  77. % ITDs=zeros(n_dir,n_cF);
  78. ILDm_all = zeros(n_dir, n_cF, Nt);
  79. ILDs_all = zeros(n_dir, n_cF, Nt);
  80. gainr_all = zeros(n_dir, n_cF, Nt);
  81. gainl_all = zeros(n_dir, n_cF, Nt);
  82. % %
  83. tic
  84. TF1_res = resample(TF1',Factor,1)';
  85. TF2_res = resample(TF2',Factor,1)';
  86. parfor idir = 1:n_dir % TODO parfor
  87. %Resample the HRIRs
  88. hL=TF1_res(idir,:);
  89. hR=TF2_res(idir,:);
  90. %Run over trials
  91. for tt=1:Nt
  92. %Generate a target sound
  93. s=genSignal(100,1/30,1,2,2*pi*12);
  94. s1=resample(s,Factor,1);
  95. %Generate a masker
  96. s=genSignal(100,1/30,1,2,2*pi*12);
  97. s2=resample(s,Factor,1);
  98. %Convolve target with HRIR
  99. sL1=conv(hL,s1);
  100. sR1=conv(hR,s1);
  101. Z=zeros(n_dir,n_cF);
  102. GL=zeros(n_dir,n_cF);
  103. GR=zeros(n_dir,n_cF);
  104. ITDp=zeros(n_cF,n_dir);
  105. %Run over masking directions
  106. %disp(num2str([toc o h idir tt]))
  107. for k=1:nd_tot
  108. %disp(num2str([o h idir tt k]))
  109. %Resample the HRIRs
  110. hL2=TF1_res(k,:); %#ok<PFBNS>
  111. hR2=TF2_res(k,:); %#ok<PFBNS>
  112. %Convolve masker with HRIR and add to target
  113. sL=sL1+conv(hL2,s2);
  114. sR=sR1+conv(hR2,s2);
  115. %cochlear (gammmatone) filterbank
  116. vL=ERBFilterBank(sL,fcoefs);
  117. vR=ERBFilterBank(sR,fcoefs);
  118. %Run over frequency and compute cross correlation
  119. for icF = 1:n_cF
  120. [x,l]=xcorr(vL(icF,:),vR(icF,:));
  121. [~,j]=max(x);
  122. ITDp(icF,k)=l(j)*1/Fs*1e6/Factor;
  123. end
  124. %Compute ILD
  125. R=rms(vR,2);
  126. L=rms(vL,2);
  127. Z(k,:)=20*log10(R./L);
  128. GR(k,:)=20*log10(R);
  129. GL(k,:)=20*log10(L);
  130. end
  131. %Run over frequency and compute mean and SD
  132. for n=1:n_cF
  133. IPDp=ITDp(n,:)*cF(n)/1e6*2*pi; %#ok<PFBNS>
  134. IPDs_all(idir,n,tt) = circstd(IPDp/Nt);
  135. IPDm_all(idir,n,tt) = circmean(IPDp/Nt);
  136. end
  137. %compute mean and SD for ILD.
  138. ILDm_all(idir,:,tt) = mean(Z,1);
  139. ILDs_all(idir,:,tt) = std(Z,[],1);
  140. %compute gain
  141. gainr_all(idir,:,tt) = mean(GR,1);
  142. gainl_all(idir,:,tt) = mean(GL,1);
  143. end
  144. end
  145. IPDs = sum(IPDs_all, 3);
  146. IPDm = sum(IPDm_all, 3);
  147. ITDs = (1e6 * IPDs) ./ (2 * pi * cF);
  148. ITDm = (1e6 * IPDm) ./ (2 * pi * cF);
  149. ILDs = sum(ILDs_all, 3)/Nt;
  150. ILDm = sum(ILDm_all, 3)/Nt;
  151. gainl = sum(gainl_all, 3)/Nt;
  152. gainr = sum(gainr_all, 3)/Nt;
  153. toc
  154. save(['Shadron_Pena_2022\', date_folder, '\', owl_folder{o} '__' haircut_id{h} '__hrtf_fig1.mat'])
  155. end
  156. end
  157. %% Some minor editing
  158. for o = 1:5
  159. for h = 1:2
  160. clearvars -except h haircut_id o owl_folder date_folder
  161. load(['Shadron_Pena_2022\', date_folder, '\', owl_folder{o} '__' haircut_id{h} '__hrtf_fig1.mat'])
  162. %have to wrap ITD's to make things make sense
  163. %Earlier had to convert 17x8x563 to a 136x563, so now have to revert
  164. %back to 17x8x20.
  165. x = size(hrir_l, 3);
  166. y = size(cF, 2);
  167. IxD.IPDm = zeros(17,8,y);
  168. IxD.IPDs = zeros(17,8,y);
  169. IxD.ITDm = zeros(17,8,y);
  170. IxD.ITDs = zeros(17,8,y);
  171. IxD.ILDm = zeros(17,8,y);
  172. IxD.ILDs = zeros(17,8,y);
  173. IxD.gainl = zeros(17,8,y);
  174. IxD.gainr = zeros(17,8,y);
  175. for n = 1:y
  176. for a = 1:17
  177. for e = 1:8
  178. counter = (a-1)*8 + e;
  179. IxD.IPDm(a,e,n) = IPDm(counter,n);
  180. IxD.IPDs(a,e,n) = IPDs(counter,n);
  181. IxD.ITDm(a,e,n) = ITDm(counter,n);
  182. IxD.ITDs(a,e,n) = ITDs(counter,n);
  183. IxD.ILDm(a,e,n) = ILDm(counter,n);
  184. IxD.ILDs(a,e,n) = ILDs(counter,n);
  185. IxD.gainl(a,e,n) = gainl(counter,n);
  186. IxD.gainr(a,e,n) = gainr(counter,n);
  187. end
  188. end
  189. end
  190. clear n a e count Factor Fs FS idir n n_cF n_dir nd_tot Nt tt x ILDm ILDs IPDm IPDp IPDs ITDp ITDs ITDm
  191. clear samplingrate s1 s2 sL1 sR1 TF1 TF2 Z ax counter fcoef dir s fcoefs hL hR hrir_l hrir_r
  192. if size(IxD.IPDm,2) > 8 %Loop occurs if spatial locations are > 17 azimuth and > 9 elevation positions
  193. %Resamples to have locations that are
  194. %-160:20:160 in azimuth and -60:20:80 in elevation
  195. for n = 1:y
  196. for a = 1:2:34
  197. for e = 2:2:16
  198. IxD2.IPDm((a+1)/2, e/2, n) = IxD.IPDm(a,e,n);
  199. IxD2.IPDs((a+1)/2, e/2, n) = IxD.IPDs(a,e,n);
  200. IxD2.ITDm((a+1)/2, e/2, n) = IxD.ITDm(a,e,n);
  201. IxD2.ITDs((a+1)/2, e/2, n) = IxD.ITDs(a,e,n);
  202. IxD2.ILDm((a+1)/2, e/2, n) = IxD.ILDm(a,e,n);
  203. IxD2.ILDs((a+1)/2, e/2, n) = IxD.ILDs(a,e,n);
  204. end
  205. end
  206. end
  207. clear IxD
  208. IxD = IxD2;
  209. clear IxD2
  210. azimuths = -160:20:160;
  211. elevations = -60:20:80;
  212. end
  213. save(['Shadron_Pena_2022\', date_folder, '\', owl_folder{o} '__' haircut_id{h} '__stats_fig1.mat'])
  214. end
  215. end
  216. %% Compile all data into one struct
  217. clearvars -except h haircut_id o owl_folder date_folder
  218. condition = [];
  219. for o = [1 2 3 4 5]
  220. for h = 1:2
  221. clearvars -except h haircut_id o owl_folder condition date_folder
  222. load(['Shadron_Pena_2022\', date_folder, '\', owl_folder{o} '__' haircut_id{h} '__stats_fig1.mat'])
  223. condition.(owl_folder{o}).(haircut_id{h}) = IxD;
  224. end
  225. end
  226. clear IxD name
  227. %average the owls
  228. for h=1:2
  229. for o = [1 2 3 4 5]
  230. if o == 1
  231. condition.(haircut_id{h}).avg.IPDm = condition.(owl_folder{o}).(haircut_id{h}).IPDm;
  232. condition.(haircut_id{h}).avg.IPDs = condition.(owl_folder{o}).(haircut_id{h}).IPDs;
  233. condition.(haircut_id{h}).avg.ITDm = condition.(owl_folder{o}).(haircut_id{h}).ITDm;
  234. condition.(haircut_id{h}).avg.ITDs = condition.(owl_folder{o}).(haircut_id{h}).ITDs;
  235. condition.(haircut_id{h}).avg.ILDm = condition.(owl_folder{o}).(haircut_id{h}).ILDm;
  236. condition.(haircut_id{h}).avg.ILDs = condition.(owl_folder{o}).(haircut_id{h}).ILDs;
  237. condition.(haircut_id{h}).avg.gainl = condition.(owl_folder{o}).(haircut_id{h}).gainl;
  238. condition.(haircut_id{h}).avg.gainr = condition.(owl_folder{o}).(haircut_id{h}).gainr;
  239. else
  240. condition.(haircut_id{h}).avg.IPDs = condition.(haircut_id{h}).avg.IPDs + condition.(owl_folder{o}).(haircut_id{h}).IPDs;
  241. condition.(haircut_id{h}).avg.ITDm = condition.(haircut_id{h}).avg.ITDm + condition.(owl_folder{o}).(haircut_id{h}).ITDm;
  242. condition.(haircut_id{h}).avg.ITDs = condition.(haircut_id{h}).avg.ITDs + condition.(owl_folder{o}).(haircut_id{h}).ITDs;
  243. condition.(haircut_id{h}).avg.ILDm = condition.(haircut_id{h}).avg.ILDm + condition.(owl_folder{o}).(haircut_id{h}).ILDm;
  244. condition.(haircut_id{h}).avg.ILDs = condition.(haircut_id{h}).avg.ILDs + condition.(owl_folder{o}).(haircut_id{h}).ILDs;
  245. condition.(haircut_id{h}).avg.gainl = condition.(haircut_id{h}).avg.gainl + condition.(owl_folder{o}).(haircut_id{h}).gainl;
  246. condition.(haircut_id{h}).avg.gainr = condition.(haircut_id{h}).avg.gainr + condition.(owl_folder{o}).(haircut_id{h}).gainr;
  247. end
  248. end
  249. condition.(haircut_id{h}).avg.IPDm = condition.(haircut_id{h}).avg.IPDm / 5;
  250. condition.(haircut_id{h}).avg.IPDs = condition.(haircut_id{h}).avg.IPDs / 5;
  251. condition.(haircut_id{h}).avg.ITDm = condition.(haircut_id{h}).avg.ITDm / 5;
  252. condition.(haircut_id{h}).avg.ITDs = condition.(haircut_id{h}).avg.ITDs / 5;
  253. condition.(haircut_id{h}).avg.ILDm = condition.(haircut_id{h}).avg.ILDm / 5;
  254. condition.(haircut_id{h}).avg.ILDs = condition.(haircut_id{h}).avg.ILDs / 5;
  255. condition.(haircut_id{h}).avg.gainl = condition.(haircut_id{h}).avg.gainl/5;
  256. condition.(haircut_id{h}).avg.gainr = condition.(haircut_id{h}).avg.gainr/5;
  257. end
  258. %% Makes the reliability maps across azimuth as in Cazettes et al (2014)
  259. lowf = 1200; % The lowest frequency you want to include in the normalization
  260. highf = 8000;
  261. %low = ((lowf-1000)/200);
  262. low = find(cF == lowf) - 1;
  263. high = find(cF == highf);
  264. for h = 1:2
  265. condition.(haircut_id{h}).avg.reliability.IPD = (condition.(haircut_id{h}).avg.IPDs.^-1);
  266. condition.(haircut_id{h}).avg.reliability.ILD = (condition.(haircut_id{h}).avg.ILDs.^-1);
  267. condition.(haircut_id{h}).avg.reliability.normalizedIPD = zeros(size(azimuths,1),high-low);
  268. condition.(haircut_id{h}).avg.reliability.normalizedILD = zeros(size(azimuths,1),high-low);
  269. condition.(haircut_id{h}).avg.reliability.normIPDaz = zeros(size(azimuths,1),2);
  270. for a = 1:17
  271. [big, pt] = max(condition.(haircut_id{h}).avg.reliability.IPD(a,4,1+low:high));
  272. for n = 1:high-low
  273. condition.(haircut_id{h}).avg.reliability.normalizedIPD(a,n) = condition.(haircut_id{h}).avg.reliability.IPD(a,4,n+low)/big;
  274. end
  275. condition.(haircut_id{h}).avg.reliability.normIPDaz(a,1) = mean(condition.(haircut_id{h}).avg.reliability.IPD(a,4,1+low:high).^-1);
  276. condition.(haircut_id{h}).avg.reliability.normIPDaz(a,2) = std(condition.(haircut_id{h}).avg.reliability.IPD(a,4,1+low:high).^-1);
  277. end
  278. for a = 1:17
  279. [big, pt] = max(condition.(haircut_id{h}).avg.reliability.ILD(a,4,1+low:high));
  280. for n = 1:high-low
  281. condition.(haircut_id{h}).avg.reliability.normalizedILD(a,n) = condition.(haircut_id{h}).avg.reliability.ILD(a,4,n+low)/big;
  282. end
  283. end
  284. end
  285. short = cF(1+low:high);
  286. % Can run to see overall pattern before normalization
  287. % figure
  288. % normalmap = imagesc(azimuths, short, condition.(haircut_id{1}).avg.reliability.normalizedIPD'); axis xy
  289. % title(['IPD Reliability Along Azimuth: ', haircut_id{1}, ' (n = 5)']); colorbar; colormap jet
  290. %
  291. % figure
  292. % ohnemap = imagesc(azimuths, short, condition.(haircut_id{2}).avg.reliability.normalizedIPD'); axis xy
  293. % title(['IPD Reliability Along Azimuth: ', haircut_id{2}, ' (n = 5)']); colorbar; colormap jet
  294. %% Figure 1a and 1b
  295. posazi = 0:20:160;
  296. shortKHz = short/1000;
  297. colors = f_gsafecmap(256);
  298. colormap(flipud(colors));
  299. d = figure;
  300. set(gcf,'Position',[100 100 600 450]);
  301. posnormalmap = imagesc(posazi, shortKHz, condition.(haircut_id{1}).avg.reliability.normalizedIPD(9:17,:)'); axis xy
  302. title('Normal')
  303. %title(['IPD Reliability Along Azimuth: ', haircut_id{1}, ' (n = 5)']);
  304. posnormalmapc = colorbar; colormap(flipud(colors)); clim([0.2 1]);
  305. %posnormalmapc.Label.String = 'Reliability'; posnormalmapc.Label.FontSize = 18;
  306. ylabel('Frequency (KHz)'); xlabel('Azimuth (°)');
  307. ylabel('Frequency (KHz)', 'FontSize', 22); xlabel('Azimuth (°)', 'FontSize', 22);
  308. set(gca,'XTick',[0 45 90 135 180], 'XTickLabel', [0 45 90 135 180], 'fontsize', 18);
  309. set(d,'Units','Inches');
  310. set(d,'PaperPositionMode','Auto','PaperUnits','Inches','PaperSize',[2.8, 2.24])
  311. text(-35,8.6, 'a', 'FontSize', 28);
  312. %saveas(posnormalmap, 'F:\Various Files\My Papers\Shadron and Pena 2022\Matlab\normreliab.png')
  313. figure
  314. set(gcf,'Position',[100 100 600 450]);
  315. posohnemap = imagesc(posazi, shortKHz, condition.(haircut_id{2}).avg.reliability.normalizedIPD(9:17,:)'); axis xy
  316. title('Ruffcut')
  317. %title(['IPD Reliability Along Azimuth: ', haircut_id{2}, ' (n = 5)']);
  318. posohnemapc = colorbar; colormap(flipud(colors)); clim([0.2 1]);
  319. posohnemapc.Label.String = 'Reliability'; posohnemapc.Label.FontSize = 22;
  320. %ylabel('Frequency (KHz)'); xlabel('Azimuth (deg)');
  321. xlabel('Azimuth (°)', 'FontSize', 22);
  322. set(gca,'XTick',[0 45 90 135 180], 'XTickLabel', [0 45 90 135 180], 'fontsize', 18);
  323. text(-35,8.6, 'b', 'FontSize', 28);
  324. %saveas(posohnemap, 'F:\Various Files\My Papers\Shadron and Pena 2022\Matlab\ruffcutreliab.png')
  325. %For non normalized:
  326. %imagesc(posazi, shortKHz, permute(squeeze(condition.(haircut_id{1}).avg.reliability.IPD(9:17,4,:)),[2 1]));colorbar
  327. %% Figure 1c
  328. diffIPD = condition.(haircut_id{2}).avg.reliability.IPD - condition.(haircut_id{1}).avg.reliability.IPD;
  329. diffILD = condition.(haircut_id{2}).avg.reliability.ILD - condition.(haircut_id{1}).avg.reliability.ILD;
  330. dIPD = squeeze(diffIPD(:,4,:));
  331. dILD = squeeze(diffILD(:,4,:));
  332. figure
  333. set(gcf,'Position',[100 100 600 450]);
  334. IPDd = imagesc(azimuths(9:end), cF(low:high), dIPD(9:end,low:high)'); axis xy;
  335. IPDdc = colorbar; clim([-.3 .3]); colors = f_gsafecmap(256); colormap(flipud(colors));
  336. ylabel('Frequency (KHz)', 'FontSize', 22);
  337. xlabel('Azimuth (°)', 'FontSize', 22);
  338. IPDdc.Label.String = 'Ruffcut IPD - Normal IPD';
  339. IPDdc.Label.FontSize = 22;
  340. IPDdc.FontSize = 16;
  341. set(gca,'XTick',[0 45 90 135 180], 'XTickLabel', [0 45 90 135 180], 'fontsize', 18);
  342. set(gca,'YTick',2000:2000:8000, 'YTickLabel', [2 4 6 8], 'fontsize', 18);
  343. text(-35,8600, 'c', 'FontSize', 24);
  344. %saveas(IPDd, 'F:\Various Files\My Papers\Shadron and Pena 2022\Matlab\reliabdiff.png')
  345. %set(IPDdc,'Units','Inches');
  346. % colors = f_gsafecmap(256);
  347. % colormap(flipud(colors));
  348. % ILDd = imagesc(azimuths(9:end), cF(4:end), dILD(9:end,4:end)'); axis xy; colorbar; caxis([-.5 .5]);
  349. % ylabel('Frequency (KHz)','FontSize', 20);
  350. % xlabel('Azimuth (Deg)','FontSize', 20);
  351. % title('Difference in ILD reliability', 'FontSize', 20)
  352. %% ILD, not shown in manuscript
  353. posazi = 160:-20:0;
  354. shortKHz = short/1000;
  355. colors = f_gsafecmap(256);
  356. colormap(flipud(colors));
  357. figure
  358. negnormalmap = imagesc(posazi, shortKHz, condition.(haircut_id{1}).avg.reliability.normalizedILD(1:9,:)'); axis xy
  359. title('Normal', 'FontSize', 20);
  360. negnormalmapc = colorbar; clim([0.2 1]);
  361. negnormalmapc.Label.String = 'Reliability'; negnormalmapc.Label.FontSize = 18;
  362. colormap(flipud(colors));
  363. ylabel('Frequency (KHz)', 'FontSize', 20); xlabel('Azimuth (deg)', 'FontSize', 20);
  364. set(gca,'XTick',[0 45 90 135 180], 'XTickLabel', [0 45 90 135 180], 'fontsize', 16);
  365. figure
  366. negohnemap = imagesc(posazi, shortKHz, condition.(haircut_id{2}).avg.reliability.normalizedILD(1:9,:)'); axis xy
  367. title('Ruff Cut', 'FontSize', 20);
  368. negohnemapc = colorbar; colormap(flipud(colors)); clim([0.2 1]);
  369. negohnemapc.Label.String = 'Reliability'; negohnemapc.Label.FontSize = 18;
  370. %ylabel('Frequency (KHz)','FontSize', 20);
  371. xlabel('Azimuth (deg)', 'FontSize', 20);
  372. set(gca,'XTick',[0 45 90 135 180], 'XTickLabel', [0 45 90 135 180], 'fontsize', 16);
  373. %For non normalized:
  374. %imagesc(posazi, shortKHz, permute(squeeze(condition.(haircut_id{1}).avg.reliability.IPD(9:17,4,:)),[2 1]));colorbar
  375. %% ILD reliability, not used in manuscript
  376. colors = f_gsafecmap(256);
  377. colormap(flipud(colors));
  378. figure
  379. posnormalmap = imagesc(posazi, shortKHz, condition.(haircut_id{1}).avg.reliability.normalizedILD(9:17,:)'); axis xy
  380. title('Normal: ILD reliability')
  381. %title(['ILD Reliability Along Azimuth: ', haircut_id{1}, ' (n = 5)']);
  382. posnormalmapc = colorbar; colormap(flipud(colors));
  383. posnormalmapc.Label.String = 'Reliability'; posnormalmapc.Label.FontSize = 12;
  384. ylabel('Frequency (KHz)'); xlabel('ITD (us)');
  385. figure
  386. posohnemap = imagesc(posazi, shortKHz, condition.(haircut_id{2}).avg.reliability.normalizedILD(9:17,:)'); axis xy
  387. title('Ruffcut: ILD reliability')
  388. %title(['IPD Reliability Along Azimuth: ', haircut_id{2}, ' (n = 5)']);
  389. posohnemapc = colorbar; colormap(flipud(colors));
  390. posohnemapc.Label.String = 'Reliability'; posohnemapc.Label.FontSize = 12;
  391. ylabel('Frequency (KHz)'); xlabel('ITD (us)');
  392. %For non normalized:
  393. %imagesc(posazi, shortKHz, permute(squeeze(condition.(haircut_id{1}).avg.reliability.IPD(9:17,4,:)),[2 1]));colorbar
  394. %% s.d. IPD averaged across freq for each azimuth, not used in manuscript
  395. IPDstd = figure;
  396. hold on
  397. scatter(azimuths, condition.(haircut_id{1}).avg.reliability.normIPDaz(:,1)/180, 40, 'blue', 'filled', 'o')
  398. scatter(azimuths, condition.(haircut_id{2}).avg.reliability.normIPDaz(:,1)/180, 40, 'red', 'filled', 'o')
  399. errorbar(azimuths, condition.(haircut_id{1}).avg.reliability.normIPDaz(:,1)/180, condition.(haircut_id{1}).avg.reliability.normIPDaz(:,2)/180, ...
  400. 'blue', 'LineStyle', 'none')
  401. errorbar(azimuths, condition.(haircut_id{2}).avg.reliability.normIPDaz(:,1)/180, condition.(haircut_id{2}).avg.reliability.normIPDaz(:,2)/180, ...
  402. 'red', 'LineStyle', 'none')
  403. xlabel('Azimuth (deg)')
  404. ylabel('IPD standard deviation')
  405. xlim([-10,90])
  406. legend('Normal', 'Ruff-Removed', 'Location', 'southeast')
  407. fontsize(gca, 16,"points")