OSCR

Dorsal prefrontal cortex drives perseverative behavior in mice.

Code ↔ Paper

7 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 7 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Unit alignment ↔ paper_code/AP_operant_learning/AP_operant_learning_figures_v4.m, lines 3495–3628 · score 0.84 · Anterior cingulate area, Secondary motor area, Infralimbic area, Prelimbic area, Allen atlas, location
  2. [2] § Methods › Unit alignment ↔ paper_code/AP_operant_learning/AP_operant_learning_figures_v3.m, lines 1542–1666 · score 0.84 · Anterior cingulate area, Secondary motor area, Infralimbic area, Prelimbic area, Allen atlas, location
  3. [3] § Methods › Task ↔ behavior/AP_operant_behavior.m, lines 205–298 · score 0.56 · rotary encoder, Wheel movements, surrounded, behavioral, mouse, stimuli
  4. [4] § Methods › Task ↔ paper_code/AP_operant_learning/AP_operant_learning_preprocessing.m, lines 10–122 · score 0.54 · rotary encoder, Wheel movements, surrounded, behavioral, stimuli, Rewards
  5. [5] § Results › Recordings across the forebrain reveal correlates of future choice specifically in MOs ↔ paper_code/AP_operant_learning/AP_operant_learning_figures_v4.m, lines 3495–3628 · score 0.52 · anterior cingulate, secondary motor, infralimbic, prelimbic, probes, brain
  6. [6] § Results › Recordings across the forebrain reveal correlates of future choice specifically in MOs ↔ paper_code/AP_operant_learning/AP_operant_learning_figures_v3.m, lines 1542–1666 · score 0.52 · anterior cingulate, secondary motor, infralimbic, prelimbic, probes, brain
  7. [7] § Methods › Electrophysiological recordings ↔ AP_kilosort_config_IMEC_P3O2.m, the whole file · a weak match · score 0.50 · Kilosort, phy, clusters, channels, noise, probes

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 3,716 lines · 134 KB · no license · 2 matches

  1. % Generate figures for operant learning paper
  2. % (data is prepared in AP_operant_learning_preprocessing)
  3. %
  4. % Code blocks with symbols:
  5. % load data first: run code block at top with same symbol
  6. %
  7. % v4: for revision
  8. %% ------- LOAD DATA ---------------------------
  9. %% >> Load task data
  10. % Load data
  11. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  12. data_fn = 'trial_activity_task_teto';
  13. AP_load_trials_operant;
  14. min_n = 4; % (minimum n to plot data)
  15. % Load behavior, exclude animals not in dataset, get learned day
  16. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  17. bhv_fn = [data_path filesep 'bhv_teto'];
  18. load(bhv_fn);
  19. bhv = bhv(ismember({bhv.animal},animals));
  20. learned_day = cellfun(@(x) find(x,1),{bhv.learned_days})';
  21. learned_day_animal = cellfun(@(ld,n) [1:n]'-(ld), ...
  22. num2cell(learned_day),num2cell(cellfun(@length,trial_info_all)), ...
  23. 'uni',false);
  24. % Get animal and day index for each trial
  25. trial_animal = cell2mat(arrayfun(@(x) ...
  26. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  27. [1:length(wheel_all)]','uni',false));
  28. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  29. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  30. wheel_all,'uni',false));
  31. trial_learned_day = trial_day - learned_day(trial_animal);
  32. learned_day_unique = unique(trial_learned_day)';
  33. [~,trial_learned_day_id] = ismember(trial_learned_day,learned_day_unique);
  34. % Get number of trials by animal/recording
  35. trials_allcat = size(wheel_allcat,1);
  36. trials_animal = arrayfun(@(x) size(vertcat(wheel_all{x}{:}),1),1:size(wheel_all));
  37. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  38. % Get movement hemisphere ratio (from rewardable no-stim movements)
  39. % (average movement activity across days for each mouse and get hemiratio)
  40. % (by ROI)
  41. fluor_move_nostim_roi = cellfun(@(x) ...
  42. AP_svd_roi(U_master(:,:,1:n_vs), ...
  43. permute(nanmean(cell2mat(x),1),[3,2,1]),[],[],cat(3,wf_roi.mask)), ...
  44. fluor_move_nostim_rewardable_all,'uni',false);
  45. roi_hemiflip = circshift(1:n_rois,n_rois/2);
  46. fluor_move_nostim_roi_hemiratio = cellfun(@(x) ...
  47. arrayfun(@(roi) ...
  48. x(roi_hemiflip(roi),:)'\x(roi,:)',1:n_rois), ...
  49. fluor_move_nostim_roi,'uni',false);
  50. trial_move_hemiratio = cell2mat(cellfun(@(x,tr) ...
  51. permute(repmat(x,tr,1),[1,3,2]), ...
  52. fluor_move_nostim_roi_hemiratio,num2cell(trials_animal)','uni',false));
  53. % (by pixel)
  54. fluor_move_nostim_rewardable_animalavg_px = ...
  55. cellfun(@(x) AP_svdFrameReconstruct(U_master(:,:,1:n_vs), ...
  56. permute(nanmean(cell2mat(x),1),[3,2,1])), ...
  57. fluor_move_nostim_rewardable_all,'uni',false);
  58. % scaling as cov(v1,v2)/var(v2)
  59. fluor_move_nostim_rewardable_animalavg_px_hemiratio = ...
  60. cellfun(@(x,x_flip) ...
  61. reshape(sum(reshape(x-nanmean(x,3),[],size(x,3)).* ...
  62. reshape(x_flip-nanmean(x_flip,3),[],size(x,3)),2) ./ ...
  63. sum(reshape(x_flip-nanmean(x_flip,3),[],size(x,3)).* ...
  64. reshape(x_flip-nanmean(x_flip,3),[],size(x,3)),2), ...
  65. size(x,1),size(x,2)), ...
  66. fluor_move_nostim_rewardable_animalavg_px, ...
  67. cellfun(@AP_reflect_widefield,fluor_move_nostim_rewardable_animalavg_px,'uni',false), ...
  68. 'uni',false);
  69. %% ++ Load passive data
  70. % Load data
  71. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  72. data_fn = 'trial_activity_passive_teto';
  73. AP_load_trials_operant;
  74. n_naive = 3; % (number of naive passive-only days, just hard-coding)
  75. min_n = 4; % (minimum n to plot data)
  76. % Load behavior, exclude animals not in dataset, get learned day
  77. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  78. bhv_fn = [data_path filesep 'bhv_teto'];
  79. load(bhv_fn);
  80. bhv = bhv(ismember({bhv.animal},animals));
  81. learned_day = cellfun(@(x) find(x,1),{bhv.learned_days})';
  82. % Get animal and day index for each trial
  83. trial_animal = cell2mat(arrayfun(@(x) ...
  84. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  85. [1:length(wheel_all)]','uni',false));
  86. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  87. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  88. wheel_all,'uni',false));
  89. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  90. % Get "learned day" for each trial
  91. trial_learned_day = cell2mat(cellfun(@(x,ld) cell2mat(cellfun(@(curr_day,x) ...
  92. curr_day*ones(size(x,1),1),num2cell([1:length(x)]-ld)',x,'uni',false)), ...
  93. wheel_all,num2cell(learned_day + n_naive),'uni',false));
  94. % Define learning stages
  95. % (learning stages: day 1-3 passive-only, then pre/post learning)
  96. trial_stage = 1*(trial_day <= 3) + ...
  97. 2*(trial_day > 3 & trial_learned_day < 0) + ...
  98. 3*(trial_learned_day >= 0);
  99. n_stages = length(unique(trial_stage));
  100. % Get trials with movement during stim to exclude
  101. quiescent_trials = ~any(abs(wheel_allcat(:,t >= 0 & t <= 0.5)) > 0,2);
  102. % Turn values into IDs for grouping
  103. stim_unique = unique(trial_stim_allcat);
  104. [~,trial_stim_id] = ismember(trial_stim_allcat,stim_unique);
  105. learned_day_unique = unique(trial_learned_day);
  106. [~,trial_learned_day_id] = ismember(trial_learned_day,learned_day_unique);
  107. % Get average fluorescence by animal/day/stim
  108. stim_v_avg = cell(length(animals),1);
  109. stim_roi_avg = cell(length(animals),1);
  110. for curr_animal = 1:length(animals)
  111. for curr_day = 1:max(trial_day(trial_animal == curr_animal))
  112. for curr_stim_idx = 1:length(stim_unique)
  113. use_trials = quiescent_trials & ...
  114. trial_animal == curr_animal & ...
  115. trial_day == curr_day & ...
  116. trial_stim_allcat == stim_unique(curr_stim_idx);
  117. stim_v_avg{curr_animal}(:,:,curr_day,curr_stim_idx) = ...
  118. permute(nanmean(fluor_allcat_deconv(use_trials,:,:),1),[3,2,1]);
  119. stim_roi_avg{curr_animal}(:,:,curr_day,curr_stim_idx) = ...
  120. permute(nanmean(fluor_roi_deconv(use_trials,:,:),1),[3,2,1]);
  121. end
  122. end
  123. end
  124. %% ------- GENERATE FIGS -----------------------
  125. %% [FIG 1B]: example performance
  126. animal = 'AP106';
  127. protocol = 'AP_stimWheelRight';
  128. experiments = AP_find_experiments(animal,protocol);
  129. plot_days = [1,3,7];
  130. figure;
  131. h = tiledlayout(length(plot_days),1);
  132. for curr_day = plot_days
  133. day = experiments(curr_day).day;
  134. experiment = experiments(curr_day).experiment;
  135. load_parts.imaging = false;
  136. AP_load_experiment;
  137. t = Timeline.rawDAQTimestamps;
  138. % Convert wheel velocity from clicks/s to mm/s
  139. % (mm in clicks from +hw.DaqRotaryEncoder, Lilrig encoder = 100)
  140. wheel_click2mm = 0.4869;
  141. wheel_velocity_mm = wheel_velocity*wheel_click2mm;
  142. % (minimum ITI: new trial + trial quiescence)
  143. min_iti_t = signals_events.newTrialTimes + ...
  144. signals_events.trialQuiescenceValues;
  145. plot_t = [100,150];
  146. plot_t_idx = t > plot_t(1) & t < plot_t(2);
  147. plot_stim_idx = find(stimOn_times > plot_t(1) & stimOn_times < plot_t(2))';
  148. plot_min_iti_t_idx = find(min_iti_t > plot_t(1) & min_iti_t < plot_t(2));
  149. plot_reward_idx = find(reward_t_timeline > plot_t(1) & reward_t_timeline < plot_t(2));
  150. nexttile; hold on;
  151. % Plot stim and rewards
  152. yyaxis left; hold on;
  153. area(t(plot_t_idx),stimOn_epochs(plot_t_idx), ...
  154. 'EdgeColor','none','FaceColor',[1,1,0.8])
  155. for i = plot_reward_idx
  156. line(repmat(reward_t_timeline(i),2,1), ...
  157. [0,1],'color','b','linewidth',2);
  158. end
  159. % Plot wheel velocity
  160. yyaxis right;
  161. plot(t(plot_t_idx),wheel_velocity_mm(plot_t_idx),'k');
  162. axis off;
  163. title(sprintf('Day %d',curr_day));
  164. end
  165. h_ax = flipud(allchild(h));
  166. linkaxes(h_ax,'y');
  167. % Draw scalebars
  168. t_scale = 5;
  169. vel_scale = 100;
  170. AP_scalebar(t_scale,vel_scale);
  171. %% [FIG 1C-F, FIG 3C, FIG S1]: behavior
  172. % Load behavior
  173. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  174. bhv_fn = [data_path filesep 'bhv_teto'];
  175. load(bhv_fn);
  176. animals = {bhv.animal};
  177. % Grab learned day
  178. learned_day = cellfun(@(x) find(x,1),{bhv.learned_days})';
  179. % Load muscimol injection info
  180. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  181. muscimol_fn = [data_path filesep 'muscimol.mat'];
  182. load(muscimol_fn);
  183. % Use days before muscimol
  184. use_days = cell(size(bhv));
  185. for curr_animal = 1:length(bhv)
  186. muscimol_animal_idx = ismember({muscimol.animal},bhv(curr_animal).animal);
  187. if ~any(muscimol_animal_idx)
  188. use_days{curr_animal} = true(length(bhv(curr_animal).day),1);
  189. continue
  190. end
  191. muscimol_day_idx = datenum(bhv(curr_animal).day) >= ...
  192. datenum(muscimol(muscimol_animal_idx).day(1));
  193. use_days{curr_animal} = ~muscimol_day_idx;
  194. end
  195. % Set max days (for padding) and plot days (minimum n)
  196. max_days = max(cellfun(@sum,use_days));
  197. min_n = 4;
  198. plot_days = find(accumarray(cell2mat(cellfun(@find,use_days,'uni',false)'),1) >= min_n);
  199. % Get reaction/resampled alt reaction times for all regular days
  200. % (exclude trials without alts: rare, from wheel click issues)
  201. use_rxn = cellfun(@(x) cellfun(@(x) cellfun(@(x) ...
  202. ~isempty(x),x),x,'uni',false),{bhv.alt_stim_move_t},'uni',false);
  203. rxn_measured = cellfun(@(rxn,use_days,use_trials) ...
  204. cellfun(@(rxn,use_trials) rxn(use_trials),rxn(use_days),use_trials(use_days),'uni',false), ...
  205. {bhv.stim_move_t},use_days,use_rxn,'uni',false)';
  206. n_rxn_altsample = 1000;
  207. rxn_alt = cellfun(@(rxn,use_days,use_trials) ...
  208. cellfun(@(rxn,use_trials) ...
  209. cell2mat(cellfun(@(x) datasample(x,n_rxn_altsample)',rxn(use_trials),'uni',false)), ...
  210. rxn(use_days),use_trials(use_days),'uni',false), ...
  211. {bhv.alt_stim_move_t},use_days,use_rxn,'uni',false)';
  212. % Concatenate and get indicies
  213. rxn_measured_allcat = cell2mat(cellfun(@cell2mat,rxn_measured,'uni',false));
  214. rxn_alt_allcat = cell2mat(cellfun(@cell2mat,rxn_alt,'uni',false));
  215. animal_idx = cell2mat(cellfun(@(x,animal) repmat(animal,length(cell2mat(x)),1), ...
  216. rxn_measured,num2cell(1:length(bhv))','uni',false));
  217. day_idx = cell2mat(cellfun(@(x) cell2mat(cellfun(@(x,day) ...
  218. repmat(day,length(x),1),x,num2cell(1:length(x))','uni',false)), ...
  219. rxn_measured,'uni',false));
  220. % Set bins for reaction time histograms
  221. rxn_bins = [0:0.01:0.5];
  222. rxn_bin_centers = rxn_bins(1:end-1) + diff(rxn_bins)./2;
  223. % Get rxn histograms by animal/day and plot heatmap
  224. animal_rxn = nan(max_days,length(rxn_bin_centers),length(animals));
  225. for curr_animal = 1:length(bhv)
  226. for curr_day = find(use_days{curr_animal})'
  227. animal_rxn(curr_day,:,curr_animal,:) = ...
  228. histcounts(bhv(curr_animal).stim_move_t{curr_day}, ...
  229. rxn_bins,'normalization','probability');
  230. end
  231. end
  232. figure;
  233. imagesc([],rxn_bin_centers,nanmean(animal_rxn(plot_days,:,:),3)');
  234. colormap(1-gray);
  235. h = colorbar;ylabel(h,'Probability');
  236. xlabel('Day');
  237. ylabel('Reaction time');
  238. caxis([0,0.12]);
  239. % Get histogram of reaction times in day groups (across animals)
  240. day_grps = [1,3,5,7,Inf];
  241. day_grp = discretize(day_idx,day_grps);
  242. figure;
  243. h = tiledlayout(length(day_grps)-1,1);
  244. for curr_day_grp = 1:length(day_grps)-1
  245. animal_rxn_measured_cathist = cell2mat(arrayfun(@(x) ...
  246. histcounts(rxn_measured_allcat( ...
  247. animal_idx == x & ...
  248. day_grp == curr_day_grp), ...
  249. rxn_bins,'normalization','probability')',1:length(bhv),'uni',false));
  250. animal_rxn_alt_cathist = cell2mat(permute( ...
  251. arrayfun(@(rep) cell2mat(arrayfun(@(x) ...
  252. histcounts(rxn_alt_allcat( ...
  253. animal_idx == x & ...
  254. day_grp == curr_day_grp,rep), ...
  255. rxn_bins,'normalization','probability')',1:length(bhv),'uni',false)), ...
  256. 1:n_rxn_altsample,'uni',false),[1,3,2]));
  257. animal_rxn_alt_cathist_ci = ...
  258. squeeze(prctile(nanmean(animal_rxn_alt_cathist,2),[5,95],3));
  259. nexttile; hold on;
  260. AP_errorfill(rxn_bin_centers,nanmean(nanmean(animal_rxn_alt_cathist,2),3), ...
  261. animal_rxn_alt_cathist_ci,[0.5,0.5,0.5],[],false);
  262. plot(rxn_bin_centers,nanmean(animal_rxn_measured_cathist,2),'k','linewidth',2);
  263. xlabel('Reaction time');
  264. ylabel('Frequency');
  265. title(sprintf('Day %d-%d',day_grps(curr_day_grp),day_grps(curr_day_grp+1)-1));
  266. xlim([0,0.5]);
  267. end
  268. linkaxes(allchild(h),'xy');
  269. % Reaction time median: whole day
  270. % (exclude too-fast rxn < 0.1)
  271. rxn_measured_med = accumarray([day_idx,animal_idx], ...
  272. rxn_measured_allcat.*AP_nanout(rxn_measured_allcat < 0.1), ...
  273. [max_days,length(bhv)],@(x) nanmedian(x),NaN);
  274. rxn_alt_med = cell2mat(permute(arrayfun(@(x) ...
  275. accumarray([day_idx,animal_idx], ...
  276. rxn_alt_allcat(:,x).*AP_nanout(rxn_alt_allcat(:,x) < 0.1), ...
  277. [max_days,length(bhv)],@(x) nanmedian(x),NaN), ...
  278. 1:n_rxn_altsample,'uni',false),[1,3,2]));
  279. % (plot mice separately)
  280. [~,learn_sort_idx] = sort(learned_day,'ascend');
  281. figure; h = tiledlayout('flow','TileSpacing','tight','padding','tight');
  282. for curr_animal = 1:length(animals)
  283. nexttile; hold on; set(gca,'YScale','log');
  284. plot(rxn_measured_med(:,curr_animal),'k','linewidth',2);
  285. AP_errorfill([],[],prctile(rxn_alt_med(:,curr_animal,:),[5,95],3),[0.5,0.5,0.5]);
  286. xline(learned_day(curr_animal),'color','r');
  287. set(gca,'children',circshift(get(gca,'children'),-1))
  288. title(sprintf('Mouse %d',curr_animal));
  289. ylim([0,2]);
  290. set(gca,'YTick',[0,0.2,2,20]);
  291. if curr_animal == 1
  292. ylabel('Reaction time');
  293. xlabel('Training session');
  294. end
  295. end
  296. linkaxes(allchild(h),'xy');
  297. % (plot median across mice)
  298. figure;
  299. subplot(1,2,1,'YScale','log');hold on
  300. rxn_alt_med_ci = squeeze(prctile(nanmedian(rxn_alt_med,2),[5,95],3));
  301. AP_errorfill([],[],rxn_alt_med_ci(plot_days,:),[0.5,0.5,0.5],[],false);
  302. errorbar(nanmedian(rxn_measured_med(plot_days,:),2), ...
  303. mad(rxn_measured_med(plot_days,:),1,2),'k','CapSize',0,'linewidth',2)
  304. xlabel('Training day');
  305. ylabel('Median reaction time (s)');
  306. axis tight;
  307. ylim([0,3]);
  308. set(gca,'YTick',[0,0.25,0.5,1,2]);
  309. xlim(xlim + [-0.5,0.5]);
  310. ytickformat('%.2f')
  311. subplot(1,2,2);hold on
  312. rxn_measured_med_altdiff = rxn_measured_med - nanmedian(rxn_alt_med,3);
  313. rxn_alt_med_altdiff = rxn_alt_med - nanmedian(rxn_alt_med,3);
  314. rxn_alt_med_altdiff_ci = squeeze(prctile(nanmedian(rxn_alt_med_altdiff,2),[5,95],3));
  315. AP_errorfill([],[],rxn_alt_med_altdiff_ci(plot_days,:),[0.5,0.5,0.5],[],false);
  316. errorbar(nanmedian(rxn_measured_med_altdiff(plot_days,:),2), ...
  317. mad(rxn_measured_med_altdiff(plot_days,:),1,2),'k','CapSize',0,'linewidth',2)
  318. xlabel('Training day');
  319. ylabel('Median reaction time (meas-null) (s)');
  320. axis tight;
  321. xlim(xlim + [-0.5,0.5]);
  322. % Reaction time median: daysplit
  323. % (exclude too-fast rxn < 0.1)
  324. n_daysplit = 3;
  325. daysplit_idx = cell2mat(cellfun(@(x) ...
  326. min(floor(linspace(1,n_daysplit+1,length(x))),n_daysplit)', ...
  327. cat(1,rxn_measured{:}),'uni',false));
  328. rxn_measured_med_daysplit = accumarray([daysplit_idx,day_idx,animal_idx], ...
  329. rxn_measured_allcat.*AP_nanout(rxn_measured_allcat < 0.1), ...
  330. [n_daysplit,max_days,length(bhv)],@(x) nanmedian(x),NaN);
  331. rxn_alt_med_daysplit = cell2mat(permute(arrayfun(@(x) ...
  332. accumarray([daysplit_idx,day_idx,animal_idx], ...
  333. rxn_alt_allcat(:,x).*AP_nanout(rxn_alt_allcat(:,x) < 0.1), ...
  334. [n_daysplit,max_days,length(bhv)],@(x) nanmedian(x),NaN), ...
  335. 1:n_rxn_altsample,'uni',false),[1,3,4,2]));
  336. % Put NaNs between days to plot with gaps
  337. rxn_measured_med_long = reshape(padarray(rxn_measured_med_daysplit,[1,0,0],NaN,'post'),[],length(animals));
  338. rxn_alt_med_long = reshape(padarray(rxn_alt_med_daysplit,[1,0,0],NaN,'post'),[],length(animals),n_rxn_altsample);
  339. % Plot relative to learned day (daysplit)
  340. learned_day_x = [1:max_days]'-learned_day';
  341. learned_daysplit_x = cell2mat(cellfun(@(x) x+(0:n_daysplit)'/(n_daysplit+1), ...
  342. num2cell(learned_day_x),'uni',false));
  343. [rxn_learn_med_daysplit,rxn_learn_mad_daysplit,learned_day_grp_daysplit,learned_day_n_daysplit] = ...
  344. grpstats(rxn_measured_med_long(:),learned_daysplit_x(:), ...
  345. {'nanmedian',@(x) mad(x,1),'gname','numel'});
  346. rxn_alt_learn_med_daysplit = ...
  347. grpstats(reshape(rxn_alt_med_long,[],n_rxn_altsample),learned_daysplit_x(:), ...
  348. {'nanmedian'});
  349. learned_day_grp_daysplit = cellfun(@str2num,learned_day_grp_daysplit);
  350. plot_learned = learned_day_n_daysplit >= min_n | isnan(rxn_learn_med_daysplit);
  351. figure; hold on;set(gca,'YScale','log');
  352. rxn_alt_learn_ci = prctile(rxn_alt_learn_med_daysplit,[1,99],2);
  353. p1 = AP_errorfill(learned_day_grp_daysplit(plot_learned), ...
  354. nanmean(rxn_alt_learn_med_daysplit(plot_learned,:),2), ...
  355. rxn_alt_learn_ci(plot_learned,:),[0.5,0.5,0.5],[],false);
  356. p2 = errorbar(learned_day_grp_daysplit(plot_learned),rxn_learn_med_daysplit(plot_learned), ...
  357. rxn_learn_mad_daysplit(plot_learned),'k','linewidth',2,'CapSize',0);
  358. ylabel('Median reaction time')
  359. xlabel('Learned day');
  360. axis tight;
  361. line([0,0],ylim,'color','k','linestyle','--');
  362. legend([p1(1),p2(1)],{'Null','Measured'});
  363. set(gca,'YTick',[0,0.25,0.5,1,2]);
  364. xlim(xlim + [-0.5,0.5]);
  365. ylim([0,5]);
  366. ytickformat('%.2f')
  367. % Plot histogram of learned days
  368. figure;histogram(learned_day,[1;plot_days]-0.5,'EdgeColor','none','FaceColor','k')
  369. xlabel('Learned day');
  370. ylabel('Number of mice');
  371. xlim([0.5,max(plot_days)+0.5]);
  372. % Plot frequency of non-response/response movements
  373. nonresponse_move_rate = AP_padcatcell(cellfun(@(x,use_days) x(use_days), ...
  374. {bhv.nonresponse_move_rate},use_days,'uni',false));
  375. trial_rate = AP_padcatcell(cellfun(@(n_trials,duration,use_days) ...
  376. n_trials(use_days)./(duration(use_days)*60), ...
  377. {bhv.n_trials},{bhv.session_duration},use_days,'uni',false));
  378. figure; hold on
  379. errorbar(nanmean(nonresponse_move_rate(plot_days,:),2), ...
  380. AP_sem(nonresponse_move_rate(plot_days,:),2),'k','linewidth',2);
  381. errorbar(nanmean(trial_rate(plot_days,:),2), ...
  382. AP_sem(trial_rate(plot_days,:),2),'b','linewidth',2);
  383. legend({'Non-response move rate','Trial rate'})
  384. xlabel('Training day');
  385. ylabel('Rate (number/sec)')
  386. %% [FIG 1F-G, FIG S2A-B]: muscimol behavior and retinotopy
  387. % Set animal to use
  388. % (only use tetO mice with successful injections evidenced by retinotopic
  389. % map loss - manually set)
  390. muscimol_v1_animals = {'AP100','AP105','AP106','AP107','AP108'};
  391. % Load behavior
  392. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  393. bhv_fn = [data_path filesep 'bhv_teto'];
  394. bhv_all = load(bhv_fn);
  395. animals_all = {bhv_all.bhv.animal};
  396. use_animals = ismember(animals_all,muscimol_v1_animals);
  397. bhv = bhv_all.bhv(use_animals);
  398. % Load muscimol injection info
  399. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  400. muscimol_fn = [data_path filesep 'muscimol.mat'];
  401. load(muscimol_fn);
  402. % Grab day index of [last pre-muscimol, V1 muscimol, washout] and data to plot
  403. n_conditions = 3;
  404. condition_labels = {'Pre-muscimol','V1 muscimol','Washout'};
  405. muscimol_v1_days = nan(length(bhv),n_conditions);
  406. muscimol_v1_retinotopy = cell(size(muscimol_v1_days));
  407. muscimol_v1_stim_surround_wheel = cell(size(muscimol_v1_days));
  408. muscimol_v1_wheel_mm = nan(size(muscimol_v1_days));
  409. for curr_animal = 1:length(bhv)
  410. muscimol_animal_idx = ismember({muscimol.animal},bhv(curr_animal).animal);
  411. if ~any(muscimol_animal_idx)
  412. continue
  413. end
  414. % (find last day before muscimol)
  415. curr_premuscimol_dayidx = find(datenum(bhv(curr_animal).day) < ...
  416. datenum(muscimol(muscimol_animal_idx).day{1}),1,'last');
  417. % (find last V1 muscimol day)
  418. curr_v1_muscimol = find(strcmp(lower( ...
  419. muscimol(muscimol_animal_idx).area),'v1'),1,'last');
  420. curr_v1_muscimol_dayidx = find(strcmp(bhv(curr_animal).day, ...
  421. muscimol(muscimol_animal_idx).day(curr_v1_muscimol)));
  422. % (find first washout after V1 muscimol)
  423. curr_v1_washout = curr_v1_muscimol + ...
  424. find(strcmp(lower( ...
  425. muscimol(muscimol_animal_idx).area(curr_v1_muscimol+1:end)), ...
  426. 'washout'),1,'first');
  427. curr_v1_washout_dayidx = find(strcmp(bhv(curr_animal).day, ...
  428. muscimol(muscimol_animal_idx).day(curr_v1_washout)));
  429. % (combine conditions)
  430. condition_dayidx = [curr_premuscimol_dayidx,curr_v1_muscimol_dayidx,curr_v1_washout_dayidx];
  431. % Grab days
  432. muscimol_v1_days(curr_animal,:) = condition_dayidx;
  433. % Grab retinotopy
  434. % (pre-muscimol)
  435. animal = muscimol(muscimol_animal_idx).animal;
  436. retinotopy_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\widefield_alignment\retinotopy';
  437. load([retinotopy_path filesep animal '_retinotopy'])
  438. curr_premuscimol_vfs_dayidx = find(datenum({retinotopy.day}) < ...
  439. datenum(muscimol(muscimol_animal_idx).day{1}),1,'last');
  440. curr_premuscimol_vfs = AP_align_widefield( ...
  441. retinotopy(curr_premuscimol_vfs_dayidx).vfs,animal, ...
  442. retinotopy(curr_premuscimol_vfs_dayidx).day);
  443. % (add post-muscimol)
  444. muscimol_v1_retinotopy(curr_animal,:) = ...
  445. [{curr_premuscimol_vfs} , ...
  446. muscimol(muscimol_animal_idx).vfs([curr_v1_muscimol,curr_v1_washout])];
  447. % Grab stim-aligned movement
  448. % (NaN-out times during quiescence)
  449. stim_surround_t = bhv(1).stim_surround_t;
  450. curr_stim_surround_wheel = ...
  451. bhv(curr_animal).stim_surround_wheel(condition_dayidx);
  452. curr_quiescence_t = ...
  453. bhv(curr_animal).quiescence_t(condition_dayidx);
  454. for curr_cond = 1:2
  455. for curr_trial = 1:size(curr_stim_surround_wheel{curr_cond},1)
  456. q_time = stim_surround_t >= -curr_quiescence_t{curr_cond}(curr_trial) & ...
  457. stim_surround_t <= 0;
  458. curr_stim_surround_wheel{curr_cond}(curr_trial,q_time) = NaN;
  459. end
  460. end
  461. muscimol_v1_stim_surround_wheel(curr_animal,:) = curr_stim_surround_wheel;
  462. % Grab wheel travel/time
  463. muscimol_v1_wheel_mm(curr_animal,:) = ...
  464. bhv(curr_animal).wheel_mm(condition_dayidx)./ ...
  465. bhv(curr_animal).session_duration(condition_dayidx);
  466. end
  467. % Plot retinotopy difference
  468. figure;
  469. h = tiledlayout(1,n_conditions,'TileSpacing','compact','padding','compact');
  470. for curr_cond = 1:n_conditions
  471. nexttile;
  472. imagesc(nanmean(cat(3,muscimol_v1_retinotopy{:,curr_cond}),3));
  473. axis image off;
  474. caxis([-1,1]);
  475. AP_reference_outline('ccf_aligned',[0.5,0.5,0.5]);
  476. title(condition_labels{curr_cond})
  477. end
  478. colormap(brewermap([],'*RdBu'));
  479. % (set 'use_days' to copy code from above)
  480. use_days = mat2cell(muscimol_v1_days,ones(length(muscimol_v1_animals),1),n_conditions)';
  481. % Get reaction/resampled alt reaction times for all regular days
  482. % (exclude trials without alts: rare, from wheel click issues)
  483. use_rxn = cellfun(@(x) cellfun(@(x) cellfun(@(x) ...
  484. ~isempty(x),x),x,'uni',false),{bhv.alt_stim_move_t},'uni',false);
  485. rxn_measured = cellfun(@(rxn,use_days,use_trials) ...
  486. cellfun(@(rxn,use_trials) rxn(use_trials),rxn(use_days),use_trials(use_days),'uni',false), ...
  487. {bhv.stim_move_t},use_days,use_rxn,'uni',false)';
  488. n_rxn_altsample = 1000;
  489. rxn_alt = cellfun(@(rxn,use_days,use_trials) ...
  490. cellfun(@(rxn,use_trials) ...
  491. cell2mat(cellfun(@(x) datasample(x,n_rxn_altsample)',rxn(use_trials),'uni',false)), ...
  492. rxn(use_days),use_trials(use_days),'uni',false), ...
  493. {bhv.alt_stim_move_t},use_days,use_rxn,'uni',false)';
  494. % Concat muscimol/washout
  495. rxn_measured_cat = cat(2,rxn_measured{:});
  496. rxn_alt_cat = cat(2,rxn_alt{:});
  497. % Set bins for reaction time histograms
  498. rxn_bins = [0:0.02:0.5];
  499. rxn_bin_centers = rxn_bins(1:end-1) + diff(rxn_bins)./2;
  500. % Plot reaction time histogram for pre/post muscimol
  501. rxn_measured_hist = cellfun(@(x) ...
  502. histcounts(x,rxn_bins,'normalization','probability'), ...
  503. rxn_measured_cat,'uni',false);
  504. rxn_alt_hist = cellfun(@(x) cell2mat(arrayfun(@(rep)...
  505. histcounts(x(:,rep),rxn_bins,'normalization','probability'), ...
  506. 1:n_rxn_altsample,'uni',false)'),rxn_alt_cat,'uni',false);
  507. rxn_alt_hist_ci = ...
  508. arrayfun(@(cond) prctile(nanmean(cat(3,rxn_alt_hist{cond,:}),3), ...
  509. [5,95],1),1:n_conditions,'uni',false);
  510. figure;
  511. h = tiledlayout(1,n_conditions,'TileSpacing','compact','padding','compact');
  512. for curr_cond = 1:n_conditions
  513. nexttile; hold on
  514. p1 = AP_errorfill(rxn_bin_centers,[], ...
  515. rxn_alt_hist_ci{curr_cond}',[0.5,0.5,0.5],[],false);
  516. p2 = plot(rxn_bin_centers, ...
  517. nanmean(cat(1,rxn_measured_hist{curr_cond,:}),1)','k','linewidth',2);
  518. legend({'Null','Measured'});
  519. xlabel('Reaction time');
  520. ylabel('Probability')
  521. title(condition_labels{curr_cond});
  522. end
  523. linkaxes(allchild(h),'xy');
  524. % Plot total velocity
  525. figure; hold on;
  526. errorbar(nanmean(muscimol_v1_wheel_mm,1), ...
  527. AP_sem(muscimol_v1_wheel_mm,1),'k','linewidth',2,'capsize',0);
  528. xlim(xlim+[-0.5,0.5]);
  529. ylim([0,max(ylim)])
  530. set(gca,'XTick',1:n_conditions,'XTickLabel',condition_labels);
  531. ylabel('Wheel mm/min');
  532. p = anova1(muscimol_v1_wheel_mm,[],'off');
  533. fprintf('Muscimol wheel travel, 1-way anova = %.2d\n',p);
  534. % Get reaction times median (exclude too-fast <0.1)
  535. rxn_measured_med = cellfun(@(x) nanmedian(x.*AP_nanout(x < 0.1),1),rxn_measured_cat);
  536. rxn_alt_med = cell2mat(cellfun(@(x) ...
  537. reshape(nanmedian(x.*AP_nanout(x < 0.1),1),1,1,[]),rxn_alt_cat,'uni',false));
  538. rxn_measured_med_altdiff = rxn_measured_med - nanmean(rxn_alt_med,3);
  539. rxn_alt_med_altdiff = rxn_alt_med - nanmean(rxn_alt_med,3);
  540. figure;
  541. subplot(1,2,1,'YScale','log'); hold on;
  542. rxn_alt_med_ci = permute(prctile(nanmean(rxn_alt_med,2),[5,95],3),[1,3,2]);
  543. AP_errorfill([],nanmean(rxn_alt_med_ci,2),rxn_alt_med_ci,[0.5,0.5,0.5],[],false);
  544. errorbar(nanmean(rxn_measured_med,2),AP_sem(rxn_measured_med,2),'k','linewidth',2,'capsize',0);
  545. xlim([0,n_conditions] + 0.5);
  546. set(gca,'XTick',1:n_conditions,'XTickLabel',condition_labels);
  547. ylabel('Median reaction time (s)');
  548. set(gca,'YTick',[0,0.25,0.5,1,2]);
  549. xlim(xlim + [-0.5,0.5]);
  550. ylim([0,3]);
  551. ytickformat('%.2f')
  552. p = anova1(rxn_measured_med',[],'off');
  553. fprintf('Muscimol reaction time, 1-way anova = %.2d\n',p);
  554. subplot(1,2,2); hold on
  555. rxn_alt_med_altdiff_ci = permute(prctile(nanmean(rxn_alt_med_altdiff,2),[5,95],3),[1,3,2]);
  556. AP_errorfill([],nanmean(rxn_alt_med_altdiff_ci,2),rxn_alt_med_altdiff_ci,[0.5,0.5,0.5],[],false);
  557. errorbar(nanmean(rxn_measured_med_altdiff,2),AP_sem(rxn_measured_med_altdiff,2),'k','linewidth',2,'capsize',0);
  558. xlim([0,n_conditions] + 0.5);
  559. set(gca,'XTick',1:n_conditions,'XTickLabel',condition_labels);
  560. ylabel('Median reaction time (meas-null,s)');
  561. %% >> [FIG 2A]: task pixels stim/move aligned by novice/learned
  562. % Set trials to use
  563. learned_day_grp_edges = [-Inf,0,Inf];
  564. trial_learned_day_grp = discretize(trial_learned_day,learned_day_grp_edges);
  565. n_learn_grps = length(learned_day_grp_edges)-1;
  566. % Set timepoints post stim/move
  567. plot_t = {0.1,0};
  568. align_labels = {'Stim','Move'};
  569. % Get interpolated time points aligned to stim and move
  570. align_v = cell(2,1);
  571. for curr_align = 1:2
  572. switch curr_align
  573. case 1
  574. curr_v_align = fluor_allcat_deconv;
  575. case 2
  576. curr_v_align = fluor_move_allcat_deconv;
  577. end
  578. curr_v_align_avg = nan(n_vs,length(t),n_learn_grps, ...
  579. length(animals),class(curr_v_align));
  580. for curr_animal = 1:length(animals)
  581. for curr_learned_grp = 1:n_learn_grps
  582. curr_trials = trial_animal == curr_animal & ...
  583. trial_learned_day_grp == curr_learned_grp & ...
  584. trial_outcome_allcat == 1;
  585. curr_v_align_avg(:,:,curr_learned_grp,curr_animal) = ...
  586. permute(nanmean(curr_v_align(curr_trials,:,:),1),[3,2,1]);
  587. end
  588. end
  589. % (get time point and store)
  590. curr_v_align_t = permute( ...
  591. interp1(t,permute(curr_v_align_avg,[2,1,3,4]),plot_t{curr_align}), ...
  592. [2,1,3,4]);
  593. align_v{curr_align} = curr_v_align_t;
  594. end
  595. % Get average pixels across animals
  596. align_px_avg = cellfun(@(x) ...
  597. nanmean(AP_svdFrameReconstruct(U_master(:,:,1:n_vs),x),5), ...
  598. align_v,'uni',false);
  599. % Plot pixels
  600. c = [0,0.007];
  601. figure;
  602. h = tiledlayout(n_learn_grps,length(cell2mat(plot_t)), ...
  603. 'TileSpacing','compact','padding','compact');
  604. for curr_learn_grp = 1:n_learn_grps
  605. for curr_align = 1:2
  606. for curr_plot_t = 1:length(plot_t{curr_align})
  607. curr_px = align_px_avg{curr_align}(:,:,curr_plot_t,curr_learn_grp);
  608. nexttile
  609. imagesc(curr_px);
  610. AP_reference_outline('ccf_aligned',[0.5,0.5,0.5]);
  611. axis image off;
  612. colormap(gca,AP_colormap('WG',[],1.5));
  613. caxis(c);
  614. title([align_labels{curr_align} ': ' num2str(plot_t{curr_align}(curr_plot_t)) ' sec']);
  615. end
  616. end
  617. end
  618. linkaxes(allchild(h),'xy');
  619. colorbar;
  620. %% >> [FIG 2B]: task pixels hemidiff stim window by novice/learned
  621. % Set trials to use
  622. learned_day_grp_edges = [-Inf,0,Inf];
  623. trial_learned_day_grp = discretize(trial_learned_day,learned_day_grp_edges);
  624. n_learn_grps = length(learned_day_grp_edges)-1;
  625. fluor_learning_animal = nan(n_vs,length(t),n_learn_grps, ...
  626. length(animals),class(fluor_allcat_deconv));
  627. for curr_animal = 1:length(animals)
  628. for curr_learned_grp = 1:n_learn_grps
  629. curr_trials = trial_animal == curr_animal & ...
  630. trial_learned_day_grp == curr_learned_grp & ...
  631. trial_outcome_allcat == 1;
  632. fluor_learning_animal(:,:,curr_learned_grp,curr_animal) = ...
  633. permute(nanmean(fluor_allcat_deconv(curr_trials,:,:),1),[3,2,1]);
  634. end
  635. end
  636. fluor_learning_animal_px = AP_svdFrameReconstruct(U_master(:,:,1:n_vs),fluor_learning_animal);
  637. fluor_learning_animal_px_avg = nanmean(fluor_learning_animal_px,5);
  638. fluor_learning_animal_px_hemidiff_avg = nanmean(fluor_learning_animal_px - ...
  639. cat(5,fluor_move_nostim_rewardable_animalavg_px_hemiratio{:}).* ...
  640. AP_reflect_widefield(fluor_learning_animal_px),5);
  641. % (white-out non-imaged pixels)
  642. fluor_learning_animal_px_hemidiff_avg(isnan(fluor_learning_animal_px_hemidiff_avg)) = 0;
  643. % Plot movies (for presentations)
  644. AP_imscroll(fluor_learning_animal_px_avg,t)
  645. caxis(max(abs(caxis))*[-1,1]);
  646. colormap(AP_colormap('KWG',[],1.5));
  647. axis image off;
  648. AP_reference_outline('ccf_aligned',[0.5,0.5,0.5]);
  649. AP_imscroll(fluor_learning_animal_px_hemidiff_avg(:,1:size(U_master,2)/2,:,:),t)
  650. caxis(max(abs(caxis))*[-1,1]);
  651. colormap(AP_colormap('KWP',[],1.5));
  652. axis image off;
  653. AP_reference_outline('ccf_aligned_lefthemi',[0.5,0.5,0.5]);
  654. % Get time window fluorescence
  655. use_t = t >= 0 & t <= 0.2;
  656. figure; tiledlayout(2,2);
  657. c = [0,0.007];
  658. c_hemi = [0,0.002];
  659. for curr_learn = 1:n_learn_grps
  660. nexttile;
  661. imagesc(max(fluor_learning_animal_px_avg(:,:,use_t,curr_learn),[],3));
  662. colormap(gca,AP_colormap('WG',[],1.5)); caxis(c);
  663. axis image off;
  664. AP_reference_outline('ccf_aligned',[0.5,0.5,0.5]);
  665. colorbar
  666. nexttile;
  667. imagesc(max(fluor_learning_animal_px_hemidiff_avg(:,1:size(U_master,2)/2,use_t,curr_learn),[],3));
  668. colormap(gca,AP_colormap('WP',[],1.5)); caxis(c_hemi);
  669. axis image off;
  670. AP_reference_outline('ccf_aligned_lefthemi',[0.5,0.5,0.5]);
  671. colorbar
  672. end
  673. %% >> [FIG 2C]: task average L/R ROI timecourse (stim/move align, novice/learned)
  674. plot_rois = [1,7,6];
  675. trial_learned_stage = discretize(trial_learned_day,[-Inf,0,Inf]);
  676. % Set activity
  677. curr_act = fluor_roi_deconv;
  678. curr_act_move = fluor_move_roi_deconv;
  679. % Get indicies for averaging (learned stage x t x roi x animal)
  680. [learned_day_idx,t_idx,roi_idx] = ...
  681. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  682. [learned_stage_idx,~] = ndgrid(trial_learned_stage,1:length(t),1:n_rois);
  683. [animal_idx,~,~] = ...
  684. ndgrid(trial_animal,1:length(t),1:n_rois);
  685. accum_stage_idx = cat(4,learned_stage_idx,t_idx,roi_idx,animal_idx);
  686. % (roi activity avg: learned stage x t x roi x animal)
  687. roi_stim_learn_avg = accumarray( ...
  688. reshape(accum_stage_idx,[],size(accum_stage_idx,4)), ...
  689. curr_act(:), ...
  690. [max(trial_learned_stage),length(t),n_rois,length(animals)], ...
  691. @nanmean,NaN('single'));
  692. roi_move_learn_avg = accumarray( ...
  693. reshape(accum_stage_idx,[],size(accum_stage_idx,4)), ...
  694. curr_act_move(:), ...
  695. [max(trial_learned_stage),length(t),n_rois,length(animals)], ...
  696. @nanmean,NaN('single'));
  697. % Plot L-R stim/move, learning overlaid
  698. median_move_t = median(move_t(trial_learned_day>0));
  699. x_limit = [-0.1,median_move_t];
  700. figure;
  701. h = tiledlayout(2,length(plot_rois)*2);
  702. hemi_col = [0.7,0,0;0,0,0.7];
  703. for curr_stage = unique(trial_learned_stage)'
  704. for curr_roi = plot_rois
  705. curr_rois = curr_roi + [0,size(wf_roi,1)];
  706. curr_data_stim = permute(roi_stim_learn_avg(curr_stage,:,curr_rois,:),[2,3,4,1]);
  707. curr_data_move = permute(roi_move_learn_avg(curr_stage,:,curr_rois,:),[2,3,4,1]);
  708. nexttile; hold on;
  709. AP_errorfill(t,nanmean(curr_data_stim,3),AP_sem(curr_data_stim,3),hemi_col);
  710. xlabel('Stim');
  711. ylabel(wf_roi(curr_roi).area(1:end-2));
  712. xline(0);set(gca,'children',circshift(get(gca,'children'),-1))
  713. xlim(x_limit);
  714. nexttile; hold on;
  715. AP_errorfill(t,nanmean(curr_data_move,3),AP_sem(curr_data_move,3),hemi_col);
  716. xlabel('Move');
  717. ylabel(wf_roi(curr_roi).area(1:end-2));
  718. xline(0);set(gca,'children',circshift(get(gca,'children'),-1))
  719. xlim(x_limit - x_limit(1));
  720. end
  721. end
  722. % (link all y-axes);
  723. linkaxes(allchild(h),'y');
  724. % Draw scalebars
  725. x_scale = 0.1;
  726. y_scale = 0.002;
  727. AP_scalebar(x_scale,y_scale);
  728. %% >> [FIG 2C ALT]: ROI stim-aligned sorted trials
  729. plot_rois = [1,7,6];
  730. trial_learned_stage = discretize(trial_learned_day,[-Inf,0,Inf]);
  731. n_trial_smooth = 200;
  732. % Set activity
  733. roi_hemiflip = circshift(1:n_rois,n_rois/2);
  734. curr_act = fluor_roi_deconv;
  735. % Plot trial activity
  736. figure;
  737. h = tiledlayout(2,length(plot_rois));
  738. for curr_stage = 1:max(trial_learned_stage)
  739. for curr_roi = plot_rois
  740. use_trials = find(trial_learned_stage == curr_stage);
  741. [~,sort_idx] = sort(move_t(use_trials));
  742. curr_data_sort = curr_act(use_trials(sort_idx),:,curr_roi);
  743. curr_data_sort_smooth = convn(curr_data_sort, ...
  744. ones(n_trial_smooth,1)./n_trial_smooth,'same');
  745. nexttile;
  746. imagesc(t,[],curr_data_sort_smooth);hold on;
  747. caxis(0.007.*[-1,1])
  748. colormap(AP_colormap('KWG',[],1));
  749. xline(0,'color',[0.8,0,0],'linewidth',2);
  750. plot(move_t(use_trials(sort_idx)),1:length(use_trials),'color','k','linewidth',2);
  751. xlabel('Time from stim (s)');
  752. ylabel('Trial (rxn-time sorted)');
  753. title(sprintf('%s, stage %d',wf_roi(curr_roi).area,curr_stage));
  754. end
  755. end
  756. linkaxes(allchild(h),'xy');
  757. xlim([-0.2,1]);
  758. ax = reshape(flipud(allchild(h)),[],2)';
  759. x_scale = 0.2;
  760. y_scale = 2000;
  761. axes(ax(1,end)); AP_scalebar(x_scale,y_scale);
  762. axes(ax(2,end)); AP_scalebar(x_scale,y_scale);
  763. colorbar;
  764. %% >> [FIG 2D]: task average hemidiff ROI timecourse (stim/move align, novice/learned)
  765. plot_rois = [1,7,6];
  766. trial_learned_stage = discretize(trial_learned_day,[-Inf,0,Inf]);
  767. % Set activity
  768. roi_hemiflip = circshift(1:n_rois,n_rois/2);
  769. curr_act = fluor_roi_deconv - ...
  770. trial_move_hemiratio.*fluor_roi_deconv(:,:,roi_hemiflip);
  771. curr_act_move = fluor_move_roi_deconv - ...
  772. trial_move_hemiratio.*fluor_move_roi_deconv(:,:,roi_hemiflip);
  773. % Get indicies for averaging (learned stage x t x roi x animal)
  774. [learned_day_idx,t_idx,roi_idx] = ...
  775. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  776. [learned_stage_idx,~] = ndgrid(trial_learned_stage,1:length(t),1:n_rois);
  777. [animal_idx,~,~] = ...
  778. ndgrid(trial_animal,1:length(t),1:n_rois);
  779. accum_stage_idx = cat(4,learned_stage_idx,t_idx,roi_idx,animal_idx);
  780. % (roi activity avg: learned stage x t x roi x animal)
  781. roi_stim_learn_avg = accumarray( ...
  782. reshape(accum_stage_idx,[],size(accum_stage_idx,4)), ...
  783. curr_act(:), ...
  784. [max(trial_learned_stage),length(t),n_rois,length(animals)], ...
  785. @nanmean,NaN('single'));
  786. roi_move_learn_avg = accumarray( ...
  787. reshape(accum_stage_idx,[],size(accum_stage_idx,4)), ...
  788. curr_act_move(:), ...
  789. [max(trial_learned_stage),length(t),n_rois,length(animals)], ...
  790. @nanmean,NaN('single'));
  791. % Plot L-R stim/move, learning overlaid
  792. median_move_t = median(move_t(trial_learned_day>0));
  793. x_limit = [-0.1,median_move_t];
  794. figure;
  795. h = tiledlayout(1,length(plot_rois)*2);
  796. stage_col = min(1,AP_colormap('WP',1) + [0.5;0]);
  797. for curr_roi = plot_rois
  798. curr_data_stim = permute(roi_stim_learn_avg(:,:,curr_roi,:),[2,1,4,3]);
  799. curr_data_move = permute(roi_move_learn_avg(:,:,curr_roi,:),[2,1,4,3]);
  800. nexttile; hold on;
  801. AP_errorfill(t,nanmean(curr_data_stim,3),AP_sem(curr_data_stim,3),stage_col);
  802. xlabel('Stim');
  803. ylabel(wf_roi(curr_roi).area(1:end-2));
  804. xline(0);yline(0);set(gca,'children',circshift(get(gca,'children'),-2))
  805. xlim(x_limit);
  806. p_t = t >= 0 & t <= 0.2;
  807. p = anova1(permute(max(curr_data_stim(p_t,:,:),[],1),[3,2,1]));
  808. fprintf('Stim-aligned hemidiff t-max %s, 1-way anova p = %.2g\n',wf_roi(curr_roi).area(1:end-2),p);
  809. % Draw scalebars
  810. x_scale = 0.1;
  811. y_scale = 2e-4;
  812. AP_scalebar(x_scale,y_scale);
  813. nexttile; hold on;
  814. AP_errorfill(t,nanmean(curr_data_move,3),AP_sem(curr_data_move,3),stage_col);
  815. xlabel('Move');
  816. ylabel(wf_roi(curr_roi).area(1:end-2));
  817. xline(0);set(gca,'children',circshift(get(gca,'children'),-1))
  818. xlim(x_limit - x_limit(1));
  819. end
  820. % (link ROI y-axes)
  821. ax = reshape(allchild(h),2,length(plot_rois));
  822. for curr_roi = 1:length(plot_rois)
  823. linkaxes(ax(:,curr_roi),'y');
  824. end
  825. %% ++ [FIG 2E-G] passive pixels and L/R ROI in stim window
  826. % Average V/ROI by learning stage
  827. % (combined naive and pre-learn)
  828. stim_v_avg_stage = cell2mat(permute(cellfun(@(x,ld) ...
  829. cat(3, ...
  830. nanmean(x(:,:,1:ld-1,:),3), ...
  831. nanmean(x(:,:,ld:end,:),3)), ...
  832. stim_v_avg,num2cell(learned_day+n_naive), ...
  833. 'uni',false),[2,3,4,5,1]));
  834. stim_roi_avg_stage = cell2mat(permute(cellfun(@(x,ld) ...
  835. cat(3, ...
  836. nanmean(x(:,:,1:ld-1,:),3), ...
  837. nanmean(x(:,:,ld:end,:),3)), ...
  838. stim_roi_avg,num2cell(learned_day+n_naive), ...
  839. 'uni',false),[2,3,4,5,1]));
  840. n_stages = size(stim_v_avg_stage,3);
  841. % Get pixels and pixel timemax by stage
  842. stim_px_avg_stage = AP_svdFrameReconstruct(U_master(:,:,1:n_vs),stim_v_avg_stage);
  843. use_t = t >= 0 & t <= 0.2;
  844. stim_px_avg_stage_tmax = ...
  845. squeeze(max(stim_px_avg_stage(:,:,use_t,:,:,:),[],3));
  846. % Plot pixel timeavg
  847. figure;
  848. h = tiledlayout(n_stages,length(stim_unique));
  849. c = [0,0.003];
  850. for curr_stage = 1:n_stages
  851. for curr_stim = 1:length(stim_unique)
  852. curr_px = nanmean(stim_px_avg_stage_tmax(:,:,curr_stage,curr_stim,:),5);
  853. nexttile;
  854. imagesc(curr_px);
  855. axis image off;
  856. AP_reference_outline('ccf_aligned',[0.5,0.5,0.5]);
  857. colormap(gca,AP_colormap('WG',[],1.5));
  858. caxis(c)
  859. end
  860. end
  861. linkaxes(allchild(h),'xy');
  862. colorbar;
  863. % Plot ROIs by stage (L/R overlay)
  864. figure;
  865. plot_rois = [1,6];
  866. hemi_stage_col = min(1,reshape([0.7,0,0;0,0,0.7]' + cat(3,0.5,0),3,[]))';
  867. h = tiledlayout(length(plot_rois),3,'TileSpacing','compact','padding','compact');
  868. for curr_roi = plot_rois
  869. curr_rois = curr_roi + [0,size(wf_roi,1)];
  870. for curr_stim = stim_unique'
  871. nexttile;
  872. AP_errorfill(t, ...
  873. reshape(permute(nanmean(stim_roi_avg_stage(curr_rois,:,:,stim_unique == curr_stim,:),5),[2,1,3]),length(t),[]), ...
  874. reshape(permute(AP_sem(stim_roi_avg_stage(curr_rois,:,:,stim_unique == curr_stim,:),5),[2,1,3]),length(t),[]), ...
  875. hemi_stage_col(:,:));
  876. xlabel('Time from stim (s)');
  877. ylabel(sprintf('%s \\DeltaF/F_0',wf_roi(curr_roi).area));
  878. axis tight;xlim([-0.2,1])
  879. end
  880. % Stats (by learning and stimuli)
  881. [t_idx,stage_idx,stim_idx,animal_idx] = ndgrid(1:length(t),1:2,1:length(stim_unique),1:length(animals));
  882. [p_l,~,stats] = anovan(reshape(stim_roi_avg_stage(curr_rois(1),:,:,:,:),[],1), ...
  883. [t_idx(:),stage_idx(:),stim_idx(:)],'continuous',1,'model','interaction','display','on');
  884. [p_r,~,stats] = anovan(reshape(stim_roi_avg_stage(curr_rois(2),:,:,:,:),[],1), ...
  885. [t_idx(:),stage_idx(:),stim_idx(:)],'continuous',1,'model','interaction','display','off');
  886. fprintf('%s t/stage/stim 3-way anova p(stage) = %.2g\n',wf_roi(curr_rois(1)).area,p_l(2));
  887. fprintf('%s t/stage/stim 3-way anova p(stage) = %.2g\n',wf_roi(curr_rois(2)).area,p_r(2));
  888. % Stats (L vs R ROI on right-hand stimuli)
  889. use_t = t > 0 & t <= 0.2;
  890. curr_Lstim_tmax_act = squeeze(max(stim_roi_avg_stage(curr_rois,use_t,:,1,:),[],2));
  891. [roi_idx,stage_idx] = ndgrid(1:2,1:2,1:length(animals));
  892. [p,~,stats] = anovan(reshape(curr_Lstim_tmax_act,[],1), ...
  893. [roi_idx(:),stage_idx(:)],'model','interaction','display','off');
  894. fprintf('%s hemi/stage 2-way anova p(hemi) = %.2g, p(stage) = %.2g\n', ...
  895. wf_roi(curr_rois(1)).area(1:end-2),p(1),p(2));
  896. end
  897. % Link ROI axes
  898. ax = reshape(flipud(allchild(h)),[],length(plot_rois))';
  899. for curr_roi = 1:length(plot_rois)
  900. linkaxes(ax(curr_roi,:),'xy');
  901. % Draw scalebars
  902. axes(ax(curr_roi,end));
  903. x_scale = 0.2;
  904. y_scale = 4e-4;
  905. AP_scalebar(x_scale,y_scale);
  906. end
  907. % (shade stim area and put in back)
  908. arrayfun(@(x) patch(x,[0,0.5,0.5,0], ...
  909. reshape(repmat(ylim(x),2,1),[],1),[1,1,0.8], ...
  910. 'linestyle','none'),allchild(h));
  911. arrayfun(@(x) set(x,'children',circshift(get(x,'children'),-1)),allchild(h));
  912. %% >> [FIG 3A1] task hemidiff ROI timecourse by learned day
  913. roi_hemiflip = circshift(1:n_rois,n_rois/2);
  914. curr_act = fluor_roi_deconv - ...
  915. trial_move_hemiratio.*fluor_roi_deconv(:,:,roi_hemiflip);
  916. % Get indicies for averaging
  917. [learned_day_idx,t_idx,roi_idx] = ...
  918. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  919. [animal_idx,~,~] = ...
  920. ndgrid(trial_animal,1:length(t),1:n_rois);
  921. [trained_day_idx,~,~] = ...
  922. ndgrid(trial_day,1:length(t),1:n_rois);
  923. accum_learnedday_idx = cat(4,learned_day_idx,t_idx,roi_idx,animal_idx);
  924. accum_trainedday_idx = cat(4,trained_day_idx,t_idx,roi_idx,animal_idx);
  925. use_trials = true(size(move_t));
  926. roi_trainday_avg = accumarray( ...
  927. reshape(accum_trainedday_idx(use_trials,:,:,:),[],size(accum_trainedday_idx,4)), ...
  928. reshape(curr_act(use_trials,:,:),[],1), ...
  929. [max(learned_day_idx(:)),length(t),n_rois,length(animals)], ...
  930. @nanmean,NaN('single'));
  931. roi_learnday_avg = accumarray( ...
  932. reshape(accum_learnedday_idx(use_trials,:,:,:),[],size(accum_learnedday_idx,4)), ...
  933. reshape(curr_act(use_trials,:,:),[],1), ...
  934. [max(learned_day_idx(:)),length(t),n_rois,length(animals)], ...
  935. @nanmean,NaN('single'));
  936. use_t = t > 0 & t <= 0.2;
  937. stim_roi_learnday_avg_tmax = squeeze(max(roi_learnday_avg(:,use_t,:,:,:),[],2));
  938. % Plot ROI timecourse first trained day / peri-learned days
  939. plot_rois = [6];
  940. plot_trained_days = 1;
  941. plot_learned_days = -2:1;
  942. figure;
  943. plot_col = AP_colormap('WP',1);
  944. h = tiledlayout(length(plot_rois), ...
  945. length(plot_trained_days) + length(plot_learned_days));
  946. for curr_roi = plot_rois
  947. for curr_td = plot_trained_days
  948. curr_data = squeeze(roi_trainday_avg(curr_td,:,curr_roi,:));
  949. nexttile; hold on;
  950. AP_errorfill(t,nanmean(curr_data,2),AP_sem(curr_data,2),plot_col);
  951. xline(0); yline(0);
  952. title(sprintf('Trained day %d',curr_td));
  953. end
  954. for curr_ld = plot_learned_days
  955. curr_data = squeeze(roi_learnday_avg(learned_day_unique == curr_ld,:,curr_roi,:));
  956. nexttile; hold on;
  957. AP_errorfill(t,nanmean(curr_data,2),AP_sem(curr_data,2),plot_col);
  958. xline(0); yline(0);
  959. title(sprintf('Learned day %d',curr_ld));
  960. end
  961. ylabel(wf_roi(curr_roi).area);
  962. % Stats: difference between ld -2/-1 vs -1/0
  963. p_t = t >= 0 & t <= 0.2;
  964. p_prelearn = signrank( ...
  965. squeeze(max(roi_learnday_avg(learned_day_unique == -2,p_t,curr_roi,:),[],2)), ...
  966. squeeze(max(roi_learnday_avg(learned_day_unique == -1,p_t,curr_roi,:),[],2)));
  967. p_postlearn = signrank( ...
  968. squeeze(max(roi_learnday_avg(learned_day_unique == -1,p_t,curr_roi,:),[],2)), ...
  969. squeeze(max(roi_learnday_avg(learned_day_unique == -0,p_t,curr_roi,:),[],2)));
  970. fprintf('%s t-max signrank: p(-2 v -1) = %.2g, p(-1 v 0) = %.2g\n', ...
  971. wf_roi(curr_roi).area,p_prelearn,p_postlearn);
  972. end
  973. % (link ROI y-axes)
  974. ax = reshape(flipud(allchild(h)),[],length(plot_rois))';
  975. for curr_roi_idx = 1:length(plot_rois)
  976. linkaxes(ax(curr_roi_idx,:),'xy');
  977. xlim([-0.1,0.3]);
  978. ylim(prctile(reshape(cell2mat(ylim(ax(curr_roi_idx,:))),[],1),[0,100]));
  979. end
  980. % Draw scalebars
  981. x_scale = 0.2;
  982. y_scale = 2e-4;
  983. AP_scalebar(x_scale,y_scale);
  984. %% >> [FIG 3D(1)] task hemidiff ROI stim window daysplit by learned day
  985. % Activity to average
  986. stim_roi_act = fluor_roi_deconv - ...
  987. trial_move_hemiratio.*fluor_roi_deconv(:,:,roi_hemiflip);
  988. % Get indicies for averaging
  989. [learned_day_idx,t_idx,roi_idx] = ...
  990. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  991. trial_learned_stage = discretize(trial_learned_day,[-Inf,-2,-1,0,1,2,Inf]);
  992. [learned_stage_idx,~] = ndgrid(trial_learned_stage,1:length(t),1:n_rois);
  993. [animal_idx,~,~] = ...
  994. ndgrid(trial_animal,1:length(t),1:n_rois);
  995. n_daysplit = 3;
  996. x_day_spacing = 1; % (plot gaps between days)
  997. trial_daysplit_idx = cell2mat(arrayfun(@(x) ...
  998. min(floor(linspace(1,n_daysplit+1,x)),n_daysplit)', ...
  999. trials_recording,'uni',false));
  1000. [daysplit_idx,~,~] = ...
  1001. ndgrid(trial_daysplit_idx,1:length(t),1:n_rois);
  1002. accum_learnedday_daysplit_idx = cat(4,learned_day_idx,daysplit_idx,t_idx,roi_idx,animal_idx);
  1003. % (roi activity daysplit: learned day x (daysplit) x t x roi x animal)
  1004. stim_roi_act_learn_avg_daysplit = accumarray( ...
  1005. reshape(accum_learnedday_daysplit_idx,[],size(accum_learnedday_daysplit_idx,4)), ...
  1006. stim_roi_act(:), ...
  1007. [max(learned_day_idx(:)),n_daysplit,length(t),n_rois,length(animals)], ...
  1008. @nanmean,NaN('single'));
  1009. % (tmax activity: learned day x daysplit x roi x animal)
  1010. use_t = t > 0 & t <= 0.2;
  1011. stim_roi_act_tmax_daysplit = ...
  1012. permute(max(stim_roi_act_learn_avg_daysplit(:,:,use_t,:,:),[],3),[1,2,4,5,3]);
  1013. % Get x-values for plotting
  1014. learned_day_x_range = [min(learned_day_unique),max(learned_day_unique)];
  1015. learned_day_x = [learned_day_x_range(1):learned_day_x_range(2)]';
  1016. learned_daysplit_x = learned_day_x + ...
  1017. (0:(n_daysplit+x_day_spacing-1))/(n_daysplit+x_day_spacing);
  1018. % Get days to plot with minimum n
  1019. plot_learned_day_idx = sum(~isnan(stim_roi_act_tmax_daysplit(:,1,1,:)),4) >= min_n;
  1020. % Plot
  1021. figure('Name','mPFC task learned day');
  1022. plot_rois = [6];
  1023. tiledlayout(length(plot_rois),1);
  1024. for curr_roi = plot_rois
  1025. nexttile;
  1026. errorbar(reshape(learned_daysplit_x(plot_learned_day_idx,:)',[],1), ...
  1027. reshape(padarray(nanmean( ...
  1028. stim_roi_act_tmax_daysplit(plot_learned_day_idx,:,curr_roi,:),4), ...
  1029. [0,x_day_spacing],NaN,'post')',[],1), ...
  1030. reshape(padarray(AP_sem( ...
  1031. stim_roi_act_tmax_daysplit(plot_learned_day_idx,:,curr_roi,:),4), ...
  1032. [0,x_day_spacing],NaN,'post')',[],1),'k','linewidth',2,'CapSize',0);
  1033. xlabel('Learned day');
  1034. ylabel(sprintf('%s \\DeltaF/F_0',wf_roi(curr_roi).area));
  1035. xline(0,'linestyle','--');
  1036. axis tight;
  1037. xlim(xlim+[-0.5,0.5]);
  1038. end
  1039. %% ++ [FIG 3B,D(2), FIG S3] passive - L/R ROI timecourse/stim window by learned day
  1040. % Set ROIs to plot
  1041. plot_rois = [6];
  1042. % Get indicies for averaging
  1043. [trained_day_idx,t_idx,roi_idx] = ...
  1044. ndgrid(trial_day,1:length(t),1:n_rois);
  1045. [learned_day_idx,~,~] = ...
  1046. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  1047. [animal_idx,~,~] = ...
  1048. ndgrid(trial_animal,1:length(t),1:n_rois);
  1049. [stim_idx,~,~] = ...
  1050. ndgrid(trial_stim_id,1:length(t),1:n_rois);
  1051. accum_idx = cat(4,trained_day_idx,learned_day_idx,t_idx,roi_idx,stim_idx,animal_idx);
  1052. use_trials_naive = quiescent_trials & trial_day <= n_naive;
  1053. use_trials_training = quiescent_trials & trial_day > n_naive;
  1054. roi_naive_avg = accumarray( ...
  1055. reshape(accum_idx(use_trials_naive,:,:,[1,3,4,5,6]),[],5), ...
  1056. reshape(fluor_roi_deconv(use_trials_naive,:,:),[],1), ...
  1057. [n_naive,length(t),n_rois,length(stim_unique),length(animals)], ...
  1058. @nanmean,NaN('single'));
  1059. roi_trainday_avg = accumarray( ...
  1060. reshape(accum_idx(use_trials_training,:,:,[1,3,4,5,6]),[],5), ...
  1061. reshape(fluor_roi_deconv(use_trials_training,:,:),[],1), ...
  1062. [max(trial_day),length(t),n_rois,length(stim_unique),length(animals)], ...
  1063. @nanmean,NaN('single'));
  1064. roi_learnday_avg = accumarray( ...
  1065. reshape(accum_idx(use_trials_training,:,:,[2,3,4,5,6]),[],5), ...
  1066. reshape(fluor_roi_deconv(use_trials_training,:,:),[],1), ...
  1067. [length(learned_day_unique),length(t),n_rois,length(stim_unique),length(animals)], ...
  1068. @nanmean,NaN('single'));
  1069. % Plot ROI timecourse by learned day (L/R)
  1070. plot_trained_days = 1;
  1071. plot_learned_days = -2:1;
  1072. figure;
  1073. hemi_col = [0.7,0,0;0,0,0.7];
  1074. h = tiledlayout(length(plot_rois),length(plot_trained_days) + length(plot_learned_days));
  1075. for curr_roi = plot_rois
  1076. curr_lr_roi = curr_roi + [0,size(wf_roi,1)];
  1077. for curr_td = plot_trained_days
  1078. curr_td_postnaive = curr_td + n_naive;
  1079. curr_data = squeeze(roi_trainday_avg(curr_td_postnaive,:, ...
  1080. curr_lr_roi,stim_unique == 1,:));
  1081. nexttile; hold on;
  1082. AP_errorfill(t,nanmean(curr_data,3),AP_sem(curr_data,3),hemi_col);
  1083. xline(0); yline(0);
  1084. title(sprintf('Trained day %d',curr_td));
  1085. end
  1086. for curr_ld = plot_learned_days
  1087. curr_data = squeeze(roi_learnday_avg(learned_day_unique == curr_ld,:, ...
  1088. curr_lr_roi,stim_unique == 1,:));
  1089. nexttile; hold on;
  1090. AP_errorfill(t,nanmean(curr_data,3),AP_sem(curr_data,3),hemi_col);
  1091. xline(0); yline(0);
  1092. title(sprintf('Learned day %d',curr_ld));
  1093. end
  1094. ylabel(wf_roi(curr_roi).area(1:end-2));
  1095. % Stats: difference between ld -2/-1 vs -1/0
  1096. p_t = t >= 0 & t <= 0.2;
  1097. p_prelearn = signrank( ...
  1098. squeeze(max(roi_learnday_avg(learned_day_unique == -2,p_t,curr_roi,stim_unique == 1,:),[],2)), ...
  1099. squeeze(max(roi_learnday_avg(learned_day_unique == -1,p_t,curr_roi,stim_unique == 1,:),[],2)));
  1100. p_postlearn = signrank( ...
  1101. squeeze(max(roi_learnday_avg(learned_day_unique == -1,p_t,curr_roi,stim_unique == 1,:),[],2)), ...
  1102. squeeze(max(roi_learnday_avg(learned_day_unique == 0,p_t,curr_roi,stim_unique == 1,:),[],2)));
  1103. fprintf('%s t-max signrank: p(-2 v -1) = %.2g, p(-1 v 0) = %.2g\n', ...
  1104. wf_roi(curr_roi).area,p_prelearn,p_postlearn);
  1105. end
  1106. % (link ROI y-axes)
  1107. ax = reshape(flipud(allchild(h)),[],length(plot_rois))';
  1108. for curr_roi_idx = 1:length(plot_rois)
  1109. linkaxes(ax(curr_roi_idx,:),'xy');
  1110. xlim(ax(curr_roi_idx,:),[-0.1,0.3]);
  1111. ylim(ax(curr_roi_idx,:), ...
  1112. prctile(reshape(cell2mat(ylim(ax(curr_roi_idx,:))),[],1),[0,100]));
  1113. end
  1114. % Draw scalebars
  1115. x_scale = 0.2;
  1116. y_scale = 4e-4;
  1117. AP_scalebar(x_scale,y_scale);
  1118. % Get ROI activity within stim window
  1119. use_t = t > 0 & t <= 0.2;
  1120. stim_roi_naive_avg_tmax = squeeze(max(roi_naive_avg(:,use_t,:,:,:),[],2));
  1121. stim_roi_learnday_avg_tmax = squeeze(max(roi_learnday_avg(:,use_t,:,:,:),[],2));
  1122. % Get days to plot by minimum n
  1123. learned_days_n = sum(any(any(stim_roi_learnday_avg_tmax,2),3),4);
  1124. plot_learned_day_idx = learned_days_n >= min_n;
  1125. % Plot ROI stim window activity by learned day
  1126. figure('Name','mPFC passive learned day');
  1127. plot_stim = [1,-1];
  1128. plot_stim_linestyle = {'-',':'};
  1129. h = tiledlayout(length(plot_rois),1);
  1130. for curr_roi = plot_rois
  1131. curr_lr_roi = curr_roi + [0,size(wf_roi,1)];
  1132. nexttile; hold on;
  1133. set(gca,'ColorOrder',hemi_col);
  1134. for curr_stim = plot_stim
  1135. curr_stim_idx = ismember(stim_unique,curr_stim);
  1136. % (naive and training as split lines)
  1137. curr_x = [learned_day_unique(1:3);NaN;learned_day_unique(plot_learned_day_idx)];
  1138. curr_data = squeeze([...
  1139. padarray(stim_roi_naive_avg_tmax(:,curr_lr_roi,curr_stim_idx,:),1,NaN,'post'); ...
  1140. stim_roi_learnday_avg_tmax(plot_learned_day_idx,curr_lr_roi,curr_stim_idx,:)]);
  1141. p = errorbar(repmat(curr_x,1,length(plot_stim)), ...
  1142. nanmean(curr_data,3),AP_sem(curr_data,3),'linewidth',2,'capsize',0, ...
  1143. 'linestyle',plot_stim_linestyle{ismember(plot_stim,curr_stim)});
  1144. end
  1145. xlabel('Time from stim (s)');
  1146. ylabel(wf_roi(curr_roi).area(1:end-2));
  1147. axis tight; xlim(xlim + [-0.5,0.5]);
  1148. xline(0);
  1149. legend({wf_roi(curr_lr_roi).area})
  1150. end
  1151. % STATS - DONT KNOW WHAT TO DO HERE YET
  1152. %
  1153. % %%%%% MAYBE JUST DO A SHUFFLE TEST?
  1154. % [ld_idx,stim_idx,~] = ndgrid(1:size(curr_data,1),1:length(stim_unique),1:length(animals));
  1155. % [p,~,stats] = anovan(curr_data(~isnan(curr_data)),[ld_idx(~isnan(curr_data)),stim_idx(~isnan(curr_data))],'model','interaction','display','on');
  1156. % c = multcompare(stats,'Dimension',[1,2]);
  1157. % fprintf('%s t-max, 2-way anova p(stim) = %.2g,p(stage) = %.2g\n',wf_roi(curr_rois(1)).area,p_l(1),p_l(2));
  1158. %
  1159. % curr_lrstim_diff = nanmean(abs(diff(curr_data(:,ismember(stim_unique,[-1,1]),:),[],2)),3);
  1160. % n_shuff = 1000;
  1161. % curr_lrstim_diff_shuff = nan(length(curr_x),n_shuff);
  1162. % for curr_shuff = 1:n_shuff
  1163. % curr_lrstim_diff_shuff(:,curr_shuff) = ...
  1164. % nanmean(abs(diff(AP_shake(curr_data(:,ismember(stim_unique,[-1,1]),:),2),[],2)),3);
  1165. % end
  1166. % curr_lrstim_diff_rank = cell2mat(arrayfun(@(x) ...
  1167. % tiedrank([curr_lrstim_diff(x),curr_lrstim_diff_shuff(x,:)]), ...
  1168. % (1:length(curr_x))','uni',false));
  1169. % curr_lrstim_diff_p = curr_lrstim_diff_rank(:,1)./(n_shuff+1);
  1170. %% ((run FIG 3D1-2)) [FIG 3D combined]: task & passive daysplit
  1171. % First make plots for passive and task daysplit mPFC activity
  1172. % Grab figure handles
  1173. fig_task = findall(groot,'type','figure','name','mPFC task learned day');
  1174. fig_passive = findall(groot,'type','figure','name','mPFC passive learned day');
  1175. if isempty(fig_task) || isempty(fig_passive)
  1176. error('Task and passive figures not open');
  1177. end
  1178. % Grab errorbar handles
  1179. % (flip passive to get order plotted)
  1180. task_errorbar = findall(fig_task,'type','ErrorBar');
  1181. passive_errorbar = flipud(findall(fig_passive,'type','ErrorBar'));
  1182. % Pull data from task errorbar
  1183. xt = get(task_errorbar,'XData');
  1184. yt = get(task_errorbar,'YData');
  1185. et = get(task_errorbar,'UData');
  1186. % Pull data from passive errorbar
  1187. % (plot order: stim-L hemi-L/R, stim-R hemi L/R)
  1188. xp = get(passive_errorbar,'XData');
  1189. ypl = get(passive_errorbar,'YData');
  1190. epl = get(passive_errorbar,'UData');
  1191. % Get task daysplit
  1192. n_daysplit = mode(diff(find(isnan(yt)))) - 1;
  1193. tp_daysplit_offset = linspace(0,1,n_daysplit+2);
  1194. xp_offset = tp_daysplit_offset(end-1);
  1195. % Re-distribute x-values to make room for passive
  1196. xtr = xt(1:n_daysplit+1:end) + tp_daysplit_offset';
  1197. ytr = padarray(reshape(yt,n_daysplit+1,[]),[1,0],NaN,'post');
  1198. etr = padarray(reshape(et,n_daysplit+1,[]),[1,0],NaN,'post');
  1199. figure; hold on;
  1200. % (plot task redistributed with an extra space)
  1201. yyaxis left;
  1202. task_col = AP_colormap('WP',1);
  1203. errorbar(xtr(:),ytr(:),etr(:),'color',task_col,'linewidth',2,'CapSize',0);
  1204. ylim([0,max(ytr(:))*1.3])
  1205. ylabel('\DeltaF/F_0');
  1206. ax = gca; ax.YColor = task_col;
  1207. % Plot passive
  1208. yyaxis right;
  1209. hemi_col = [0.7,0,0;0,0,0.7];
  1210. % (plot L-hemi R-stim)
  1211. curr_passive_plot = 1;
  1212. errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'.','MarkerSize',15, ...
  1213. 'color',hemi_col(1,:),'linestyle','none','linewidth',2,'CapSize',0);
  1214. % (plot R-hemi R-stim)
  1215. curr_passive_plot = 2;
  1216. errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'.','MarkerSize',15, ...
  1217. 'color',hemi_col(2,:),'linestyle','none','linewidth',2,'CapSize',0);
  1218. % (TESTING DIFFERENT KINDS OF PLOTS)
  1219. % % (plot L-hemi L-stim)
  1220. % curr_passive_plot = 3;
  1221. % errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'o','MarkerSize',5, ...
  1222. % 'color',hemi_col(1,:),'linestyle','none','linewidth',2,'CapSize',0);
  1223. % % (plot R-hemi L-stim)
  1224. % curr_passive_plot = 4;
  1225. % errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'o','MarkerSize',5, ...
  1226. % 'color',hemi_col(2,:),'linestyle','none','linewidth',2,'CapSize',0);
  1227. % % (plot L-hemi L-stim)
  1228. % curr_passive_plot = 3;
  1229. % AP_errorfill(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot}, ...
  1230. % hemi_col(1,:),0.2,false);
  1231. % % (plot R-hemi L-stim)
  1232. % curr_passive_plot = 4;
  1233. % AP_errorfill(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot}, ...
  1234. % hemi_col(2,:),0.2,false);
  1235. % % (plot L-hemi L-stim)
  1236. % curr_passive_plot = 3;
  1237. % errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'MarkerSize',5, ...
  1238. % 'color',hemi_col(1,:),'linestyle','-','linewidth',2,'CapSize',0);
  1239. % % (plot R-hemi L-stim)
  1240. % curr_passive_plot = 4;
  1241. % errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'MarkerSize',5, ...
  1242. % 'color',hemi_col(2,:),'linestyle','-','linewidth',2,'CapSize',0);
  1243. % curr_passive_plot = 3;
  1244. % errorbar(xp{curr_passive_plot}+xp_offset,ypl{curr_passive_plot},epl{curr_passive_plot},'*','MarkerSize',8, ...
  1245. % 'color',hemi_col(1,:),'linestyle','none','linewidth',2,'CapSize',0);
  1246. xlim(prctile(horzcat(xp{:}),[0,100]) + [-0.5,1.5]);
  1247. ylim([0,max(horzcat(ypl{:}))*1.3])
  1248. xline(0);
  1249. xlabel('Learned day');
  1250. ylabel('\DeltaF/F_0');
  1251. ax = gca; ax.YColor = 'k';
  1252. %% (OLD NOW) [FIG 4A]: ephys - plot probe position
  1253. animals = {'AP100','AP101','AP104','AP105','AP106'};
  1254. % Load CCF annotated volume
  1255. allen_atlas_path = fileparts(which('template_volume_10um.npy'));
  1256. av = readNPY([allen_atlas_path filesep 'annotation_volume_10um_by_index.npy']);
  1257. st = loadStructureTree([allen_atlas_path filesep 'structure_tree_safe_2017.csv']);
  1258. figure;
  1259. animal_col = repmat([0,0,0],length(animals),1);
  1260. % Set up 3D axes
  1261. ccf_3d_axes = subplot(1,4,1);
  1262. [~, brain_outline] = plotBrainGrid([],ccf_3d_axes);
  1263. set(ccf_3d_axes,'ZDir','reverse');
  1264. hold(ccf_3d_axes,'on');
  1265. axis vis3d equal off manual
  1266. view([-30,25]);
  1267. axis tight;
  1268. h = rotate3d(ccf_3d_axes);
  1269. h.Enable = 'on';
  1270. % Set up 2D axes
  1271. bregma_ccf = [540,44,570];
  1272. ccf_size = size(av);
  1273. ccf_axes = gobjects(3,1);
  1274. ccf_axes(1) = subplot(1,4,2,'YDir','reverse');
  1275. hold on; axis image off;
  1276. ccf_axes(2) = subplot(1,4,3,'YDir','reverse');
  1277. hold on; axis image off;
  1278. ccf_axes(3) = subplot(1,4,4,'YDir','reverse');
  1279. hold on; axis image off;
  1280. for curr_view = 1:3
  1281. curr_outline = bwboundaries(squeeze((max(av,[],curr_view)) > 1));
  1282. cellfun(@(x) plot(ccf_axes(curr_view),x(:,2),x(:,1),'k','linewidth',2),curr_outline)
  1283. curr_bregma = fliplr(bregma_ccf(setdiff(1:3,curr_view)));
  1284. plot(ccf_axes(curr_view),curr_bregma(1),curr_bregma(2),'rx');
  1285. curr_size = fliplr(ccf_size(setdiff(1:3,curr_view)));
  1286. xlim(ccf_axes(curr_view),[0,curr_size(1)]);
  1287. ylim(ccf_axes(curr_view),[0,curr_size(2)]);
  1288. end
  1289. linkaxes(ccf_axes);
  1290. % Plot specific areas
  1291. plot_structure_names = {'Secondary motor area', ...
  1292. 'Anterior cingulate area','Prelimbic area','Infralimbic area'};
  1293. plot_structure_colors = lines(length(plot_structure_names));
  1294. for plot_structure_name = plot_structure_names
  1295. plot_structure = find(strcmp(st.safe_name,plot_structure_name));
  1296. % Get all areas within and below the selected hierarchy level
  1297. plot_structure_id = st.structure_id_path{plot_structure};
  1298. plot_ccf_idx = find(cellfun(@(x) contains(x,plot_structure_id), ...
  1299. st.structure_id_path));
  1300. % plot the structure
  1301. slice_spacing = 5;
  1302. plot_structure_color = plot_structure_colors( ...
  1303. strcmp(plot_structure_name,plot_structure_names),:);
  1304. % Get structure volume
  1305. plot_ccf_volume = ismember(av(1:slice_spacing:end,1:slice_spacing:end,1:slice_spacing:end),plot_ccf_idx);
  1306. for curr_view = 1:3
  1307. curr_outline = bwboundaries(squeeze((max(plot_ccf_volume,[],curr_view))));
  1308. cellfun(@(x) plot(ccf_axes(curr_view),x(:,2)*slice_spacing, ...
  1309. x(:,1)*slice_spacing,'color',plot_structure_color,'linewidth',2),curr_outline)
  1310. end
  1311. end
  1312. % Plot probe locations
  1313. probe_coords_mean_all = nan(length(animals),3);
  1314. for curr_animal = 1:length(animals)
  1315. animal = animals{curr_animal};
  1316. % Load animal probe histology
  1317. [probe_ccf_fn,probe_ccf_fn_exists] = AP_cortexlab_filename(animal,[],[],'probe_ccf');
  1318. load(probe_ccf_fn);
  1319. % Get line of best fit through mean of marked points
  1320. probe_coords_mean = mean(probe_ccf.points,1);
  1321. % (store mean for plotting later)
  1322. probe_coords_mean_all(curr_animal,:) = probe_coords_mean;
  1323. xyz = bsxfun(@minus,probe_ccf.points,probe_coords_mean);
  1324. [~,~,V] = svd(xyz,0);
  1325. histology_probe_direction = V(:,1);
  1326. % (make sure the direction goes down in DV - flip if it's going up)
  1327. if histology_probe_direction(2) < 0
  1328. histology_probe_direction = -histology_probe_direction;
  1329. end
  1330. % Evaluate line of best fit (length of probe to deepest point)
  1331. [~,deepest_probe_idx] = max(probe_ccf.points(:,2));
  1332. probe_deepest_point = probe_ccf.points(deepest_probe_idx,:);
  1333. probe_deepest_point_com_dist = pdist2(probe_coords_mean,probe_deepest_point);
  1334. probe_length_ccf = 3840/10; % mm / ccf voxel size
  1335. probe_line_eval = probe_deepest_point_com_dist - [probe_length_ccf,0];
  1336. probe_line = (probe_line_eval'.*histology_probe_direction') + probe_coords_mean;
  1337. % Draw probe in 3D view
  1338. line(ccf_3d_axes,probe_line(:,1),probe_line(:,3),probe_line(:,2), ...
  1339. 'linewidth',2,'color',animal_col(curr_animal,:))
  1340. % Draw probes on coronal + saggital
  1341. line(ccf_axes(1),probe_line(:,3),probe_line(:,2),'linewidth',2,'color',animal_col(curr_animal,:));
  1342. line(ccf_axes(3),probe_line(:,2),probe_line(:,1),'linewidth',2,'color',animal_col(curr_animal,:));
  1343. % Draw probe mean on horizontal
  1344. plot(ccf_axes(2), probe_coords_mean(:,3),probe_coords_mean(:,1), ...
  1345. '.','MarkerSize',10,'color',animal_col(curr_animal,:));
  1346. drawnow
  1347. end
  1348. % Plot scalebar
  1349. scalebar_length = 1000/10; % um/voxel size
  1350. line(ccf_axes(3),[0,0],[0,scalebar_length],'color','m','linewidth',3);
  1351. %% [FIG 4B]: Example single unit rasters
  1352. animal = 'AP100';
  1353. day = '2021-05-25';
  1354. plot_units = [292,252,260];
  1355. % stim: 282 290 292
  1356. % stim+move: 270 252 286 233
  1357. % move: 260 301 393
  1358. % Set up subplots
  1359. figure;
  1360. h = tiledlayout(length(plot_units)*2,2,'tileindexing','columnmajor');
  1361. % Set raster time bins
  1362. raster_window = [-0.2,0.7];
  1363. psth_bin_size = 0.001;
  1364. raster_t_bins = raster_window(1):psth_bin_size:raster_window(2);
  1365. raster_t = raster_t_bins(1:end-1) + diff(raster_t_bins)./2;
  1366. for experiment = 1:2
  1367. % (load LFP to find cortex start)
  1368. preload_vars = who;
  1369. lfp_channel = 'all';
  1370. ephys_align = 'cortex';
  1371. ephys_quality_control = false;
  1372. AP_load_experiment;
  1373. %%% JF code for loading good single units from bombcell
  1374. % unitType: 0 = noise, 1 = good, 2 = multiunit
  1375. ephysDirPath = AP_cortexlab_filename(animal, day, experiment, 'ephys_dir');
  1376. qMetric_fn = fullfile(ephysDirPath, 'qMetrics');
  1377. load(fullfile(qMetric_fn, 'qMetric.mat'))
  1378. load(fullfile(qMetric_fn, 'param.mat'))
  1379. clearvars unitType;
  1380. % DEFAULT CHANGE: eliminate amplitude cutoff
  1381. % (for one recording it got rid of almost all cells, and
  1382. % cells under amplitude cutoff still look good)
  1383. param.minAmplitude = 0;
  1384. % (classify good cells)
  1385. unitType = nan(length(qMetric.percSpikesMissing), 1);
  1386. unitType( ...
  1387. qMetric.nPeaks > param.maxNPeaks | ...
  1388. qMetric.nTroughs > param.maxNTroughs | ...
  1389. qMetric.somatic ~= param.somatic | ...
  1390. qMetric.spatialDecaySlope <= param.minSpatialDecaySlope | ...
  1391. qMetric.waveformDuration < param.minWvDuration |...
  1392. qMetric.waveformDuration > param.maxWvDuration | ...
  1393. qMetric.waveformBaseline >= param.maxWvBaselineFraction) = 0;
  1394. unitType( ...
  1395. any(qMetric.percSpikesMissing <= param.maxPercSpikesMissing, 2)' & ...
  1396. qMetric.nSpikes > param.minNumSpikes & ...
  1397. any(qMetric.Fp <= param.maxRPVviolations, 2)' & ...
  1398. qMetric.rawAmplitude > param.minAmplitude & isnan(unitType)') = 1;
  1399. unitType(isnan(unitType)') = 2;
  1400. % Templates already 1/re-indexed, grab good ones
  1401. good_templates = unitType == 1;
  1402. good_templates_idx = find(good_templates);
  1403. % Throw out all non-good template data
  1404. templates = templates(good_templates,:,:);
  1405. template_depths = template_depths(good_templates);
  1406. waveforms = waveforms(good_templates,:);
  1407. templateDuration = templateDuration(good_templates);
  1408. templateDuration_us = templateDuration_us(good_templates);
  1409. % Throw out all non-good spike data
  1410. good_spike_idx = ismember(spike_templates,good_templates_idx);
  1411. spike_times = spike_times(good_spike_idx);
  1412. spike_templates_0idx = spike_templates_0idx(good_spike_idx);
  1413. template_amplitudes = template_amplitudes(good_spike_idx);
  1414. spike_depths = spike_depths(good_spike_idx);
  1415. spike_times_timeline = spike_times_timeline(good_spike_idx);
  1416. % Rename the spike templates according to the remaining templates
  1417. % (and make 1-indexed from 0-indexed)
  1418. new_spike_idx = nan(max(spike_templates_0idx)+1,1);
  1419. new_spike_idx(unique(spike_templates_0idx)+1) = 1:length(unique(spike_templates_0idx));
  1420. spike_templates = new_spike_idx(spike_templates_0idx+1);
  1421. % Get area of each unit
  1422. probe_area_boundary_starts = cellfun(@(x) x(1),probe_area_boundaries);
  1423. [~,area_sort] = sort(probe_area_boundary_starts);
  1424. unit_area = probe_areas(area_sort(discretize(template_depths, ...
  1425. [-Inf;probe_area_boundary_starts(area_sort(2:end));Inf])));
  1426. % Get raster alignment times
  1427. if contains(expDef,'stimWheel')
  1428. % If task, get rewardable movements and raster all events
  1429. wheel_moves_deg = arrayfun(@(x) wheel_position_deg( ...
  1430. Timeline.rawDAQTimestamps >= wheel_starts(x) & ...
  1431. Timeline.rawDAQTimestamps <= wheel_stops(x)) - ...
  1432. wheel_position_deg(find(Timeline.rawDAQTimestamps >= wheel_starts(x),1)), ...
  1433. 1:length(wheel_starts),'uni',false);
  1434. deg_reward = -90;
  1435. deg_punish = 90;
  1436. wheel_moves_deg_rewardlimit = find(cellfun(@(x) ...
  1437. any(x <= deg_reward) && ...
  1438. ~any(x >= deg_punish),wheel_moves_deg));
  1439. wheel_move_nostim_rewardable_idx = ...
  1440. intersect(wheel_move_nostim_idx, wheel_moves_deg_rewardlimit);
  1441. % Raster events: rewardable delay movements
  1442. use_align = wheel_starts(wheel_move_nostim_rewardable_idx);
  1443. align_label = 'Move onset';
  1444. elseif contains(expDef,'Passive')
  1445. % If passive, get quiescent movement and raster right-hand stim trials
  1446. wheel_window = [0,0.5];
  1447. wheel_window_t = wheel_window(1):1/Timeline.hw.daqSampleRate:wheel_window(2);
  1448. wheel_window_t_peri_event = bsxfun(@plus,stimOn_times,wheel_window_t);
  1449. event_aligned_wheel = interp1(Timeline.rawDAQTimestamps, ...
  1450. +wheel_move,wheel_window_t_peri_event,'previous');
  1451. quiescent_trials = ~any(abs(event_aligned_wheel) > 0,2);
  1452. % Raster event: quiescent right-hand stim onset
  1453. plot_trials = quiescent_trials & stimIDs == 3;
  1454. use_align = stimOn_times(plot_trials);
  1455. align_label = 'Stim onset';
  1456. end
  1457. t_peri_event = use_align + raster_t_bins;
  1458. for curr_unit = plot_units
  1459. % Bin spikes (use only spikes within time range, big speed-up)
  1460. curr_spikes_idx = ismember(spike_templates,curr_unit);
  1461. curr_raster_spike_times = spike_times_timeline(curr_spikes_idx);
  1462. curr_raster_spike_times(curr_raster_spike_times < min(t_peri_event(:)) | ...
  1463. curr_raster_spike_times > max(t_peri_event(:))) = [];
  1464. curr_raster = cell2mat(arrayfun(@(x) ...
  1465. histcounts(curr_raster_spike_times,t_peri_event(x,:)), ...
  1466. [1:size(t_peri_event,1)]','uni',false));
  1467. % Get smoothed PSTH
  1468. smooth_size = 51;
  1469. gw = gausswin(smooth_size,3)';
  1470. smWin = gw./sum(gw);
  1471. bin_t = mean(diff(raster_t));
  1472. curr_psth = nanmean(curr_raster,1);
  1473. curr_smoothed_psth = conv2(padarray(curr_psth, ...
  1474. [0,floor(length(smWin)/2)],'replicate','both'), ...
  1475. smWin,'valid')./bin_t;
  1476. % Plot PSTH and raster
  1477. nexttile;
  1478. plot(raster_t,curr_smoothed_psth,'k','linewidth',1);
  1479. axis tight off
  1480. xline(0);
  1481. title(sprintf('%s %s %s',animal,day,expDef), ...
  1482. sprintf('unit %d %s',curr_unit,unit_area{curr_unit}));
  1483. nexttile;
  1484. [raster_y,raster_x] = find(curr_raster);
  1485. plot(raster_t(raster_x),raster_y,'.k');
  1486. axis tight off
  1487. set(gca,'ydir','reverse');
  1488. xlabel(align_label);
  1489. drawnow;
  1490. end
  1491. clearvars('-except',preload_vars{:})
  1492. end
  1493. ax = reshape(flipud(allchild(h)),2,[]);
  1494. % Link all psth/raster y-axes
  1495. linkaxes(ax(1,:),'y')
  1496. linkaxes(ax(2,:),'y')
  1497. % Link all x-axes
  1498. linkaxes(ax,'x')
  1499. % Scalebars
  1500. t_scale = 0.2;
  1501. rate_scale = 20;
  1502. axes(ax(end-1));
  1503. AP_scalebar(t_scale,rate_scale)
  1504. %% (OLD NOW) [FIG 4C]: ephys - passive stim response
  1505. % Load data
  1506. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  1507. data_fn = 'trial_activity_passive_ephys';
  1508. AP_load_trials_operant;
  1509. % Get animal and day index for each trial
  1510. trial_animal = cell2mat(arrayfun(@(x) ...
  1511. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  1512. [1:length(wheel_all)]','uni',false));
  1513. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  1514. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  1515. wheel_all,'uni',false));
  1516. trial_recording = cell2mat(cellfun(@(tr,day) ...
  1517. day*ones(size(tr,1),1), ...
  1518. cat(1,wheel_all{:}),num2cell(1:length(cat(1,wheel_all{:})))', ...
  1519. 'uni',false));
  1520. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  1521. % Get trials with movement during stim to exclude
  1522. quiescent_trials = ~any(abs(wheel_allcat(:,t >= 0 & t <= 0.5)) > 0,2);
  1523. % Get average response timecourses
  1524. stim_unique = unique(trial_stim_allcat);
  1525. [~,trial_stim_id] = ismember(trial_stim_allcat,stim_unique);
  1526. use_trials = quiescent_trials;
  1527. % (loop through cell types)
  1528. for curr_celltype = 1:size(mua_area_allcat,4)
  1529. [recording_idx,t_idx,area_idx] = ...
  1530. ndgrid(trial_recording(use_trials),1:length(t),1:length(mua_areas));
  1531. [stim_idx,~,~,] = ...
  1532. ndgrid(trial_stim_id(use_trials),1:length(t),1:length(mua_areas));
  1533. mua_recording_avg = accumarray([recording_idx(:),t_idx(:),stim_idx(:),area_idx(:)], ...
  1534. reshape(mua_area_allcat(use_trials,:,:,curr_celltype),[],1), ...
  1535. [length(trials_recording),length(t),length(stim_unique),length(mua_areas)], ...
  1536. @nanmean,NaN);
  1537. % Get DV position of each area in CCF for sorting
  1538. allen_atlas_path = fileparts(which('template_volume_10um.npy'));
  1539. av = readNPY([allen_atlas_path filesep 'annotation_volume_10um_by_index.npy']);
  1540. st = loadStructureTree([allen_atlas_path filesep 'structure_tree_safe_2017.csv']);
  1541. mua_areas_dvmin = nan(size(mua_areas));
  1542. for curr_area = mua_areas'
  1543. curr_structure_idx = find(strcmp(st.safe_name,curr_area));
  1544. curr_structure_id = st.structure_id_path{curr_structure_idx};
  1545. curr_ccf_idx = find(cellfun(@(x) contains(x,curr_structure_id), ...
  1546. st.structure_id_path));
  1547. slice_spacing = 5;
  1548. curr_ccf_volume = ...
  1549. ismember(av(1:slice_spacing:end, ...
  1550. 1:slice_spacing:end,1:slice_spacing:end),curr_ccf_idx);
  1551. curr_ccf_coronal_max = permute(max(curr_ccf_volume,[],1),[2,3,1]);
  1552. curr_min_dv = find(any(curr_ccf_coronal_max,2),1);
  1553. mua_areas_dvmin(strcmp(curr_area,mua_areas)) = curr_min_dv;
  1554. end
  1555. % (get areas to plot: anything present in all recordings)
  1556. [~,area_idx] = cellfun(@(x) ismember(x,mua_areas),mua_areas_cat,'uni',false);
  1557. area_recording_n = accumarray(cell2mat(area_idx),1);
  1558. plot_areas = find(area_recording_n == length(trials_recording));
  1559. [~,plot_area_sort_idx] = sort(mua_areas_dvmin(plot_areas));
  1560. % Plot stim overlaid
  1561. figure;
  1562. stim_color = [0,0,0.8;0.5,0.5,0.5;0.8,0,0];
  1563. h = tiledlayout(length(plot_areas),1);
  1564. for curr_area = plot_areas(plot_area_sort_idx)'
  1565. nexttile;
  1566. AP_errorfill(t', ...
  1567. squeeze(nanmean(mua_recording_avg(:,:,:,curr_area),1)), ...
  1568. squeeze(AP_sem(mua_recording_avg(:,:,:,curr_area),1)),stim_color);
  1569. yline(0);
  1570. ylabel(mua_areas(curr_area));
  1571. end
  1572. linkaxes(allchild(h),'xy');
  1573. % (shade stim area and put in back)
  1574. arrayfun(@(x) patch(x,[0,0.5,0.5,0], ...
  1575. reshape(repmat(ylim(x),2,1),[],1),[1,1,0.8], ...
  1576. 'linestyle','none'),allchild(h));
  1577. arrayfun(@(x) set(x,'children',circshift(get(x,'children'),-1)),allchild(h));
  1578. xlim([-0.2,0.7]);
  1579. x_scale = 0.2;
  1580. y_scale = 0.5;
  1581. AP_scalebar(x_scale,y_scale);
  1582. title(h,sprintf('Cell type %d',curr_celltype));
  1583. end
  1584. %% [FIG 4D] ephys - move (no stim) response
  1585. % Load data
  1586. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  1587. data_fn = 'trial_activity_task_ephys';
  1588. AP_load_trials_operant;
  1589. % Get animal and day index for each trial
  1590. trial_animal = cell2mat(arrayfun(@(x) ...
  1591. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  1592. [1:length(wheel_all)]','uni',false));
  1593. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  1594. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  1595. wheel_all,'uni',false));
  1596. trial_recording = cell2mat(cellfun(@(tr,day) ...
  1597. day*ones(size(tr,1),1), ...
  1598. cat(1,wheel_all{:}),num2cell(1:length(cat(1,wheel_all{:})))', ...
  1599. 'uni',false));
  1600. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  1601. % Plot average activity aligned to stim and move
  1602. % (loop through cell types)
  1603. celltype_label = {'Wide','Narrow'};
  1604. for curr_celltype = 1:length(celltype_label)
  1605. % Get average response timecourses
  1606. mua_move_nostim_recording_avg = ...
  1607. mua_area_move_nostim_rewardable_allcat(:,:,:,curr_celltype);
  1608. % Get DV position of each area in CCF for sorting
  1609. allen_atlas_path = fileparts(which('template_volume_10um.npy'));
  1610. av = readNPY([allen_atlas_path filesep 'annotation_volume_10um_by_index.npy']);
  1611. st = loadStructureTree([allen_atlas_path filesep 'structure_tree_safe_2017.csv']);
  1612. mua_areas_dvmin = nan(size(mua_areas));
  1613. for curr_area = mua_areas'
  1614. curr_structure_idx = find(strcmp(st.safe_name,curr_area));
  1615. curr_structure_id = st.structure_id_path{curr_structure_idx};
  1616. curr_ccf_idx = find(cellfun(@(x) contains(x,curr_structure_id), ...
  1617. st.structure_id_path));
  1618. slice_spacing = 5;
  1619. curr_ccf_volume = ...
  1620. ismember(av(1:slice_spacing:end, ...
  1621. 1:slice_spacing:end,1:slice_spacing:end),curr_ccf_idx);
  1622. curr_ccf_coronal_max = permute(max(curr_ccf_volume,[],1),[2,3,1]);
  1623. curr_min_dv = find(any(curr_ccf_coronal_max,2),1);
  1624. mua_areas_dvmin(strcmp(curr_area,mua_areas)) = curr_min_dv;
  1625. end
  1626. % Plot timecourses overlaid
  1627. % (get areas to plot: anything present in all recordings)
  1628. [~,area_idx] = cellfun(@(x) ismember(x,mua_areas),mua_areas_cat,'uni',false);
  1629. area_recording_n = accumarray(cell2mat(area_idx),1);
  1630. plot_areas = find(area_recording_n == length(trials_recording));
  1631. [~,plot_area_sort_idx] = sort(mua_areas_dvmin(plot_areas));
  1632. % Plot move no-stim aligned
  1633. figure;
  1634. h = tiledlayout(length(plot_areas),1);
  1635. for curr_area = plot_areas(plot_area_sort_idx)'
  1636. nexttile;
  1637. AP_errorfill(t', ...
  1638. squeeze(nanmean(mua_move_nostim_recording_avg(:,:,curr_area),1)), ...
  1639. squeeze(AP_sem(mua_move_nostim_recording_avg(:,:,curr_area),1)),'k');
  1640. xlabel('Move');
  1641. xline(0);yline(0);
  1642. ylabel(mua_areas(curr_area));
  1643. end
  1644. linkaxes(allchild(h),'xy');
  1645. xlim([-0.2,0.7]);
  1646. x_scale = 0.2;
  1647. y_scale = 0.5;
  1648. AP_scalebar(x_scale,y_scale);
  1649. title(h,celltype_label{curr_celltype});
  1650. end
  1651. %% [FIG 4E-F] ephys single cell classification and stim/move response
  1652. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  1653. data_fn = 'single_unit_data_all';
  1654. load(fullfile(data_path,data_fn));
  1655. % Unpack (event rates are stored as event x unit x pre/post)
  1656. unit_area_cat = horzcat(single_unit_data_all.unit_area)';
  1657. n_units_exp = cellfun(@length,unit_area_cat);
  1658. waveform_duration_exp = horzcat(single_unit_data_all.waveform_duration_JF);
  1659. passive_stim_fr_cat = horzcat(single_unit_data_all.passive_stim_fr)';
  1660. task_move_fr_cat = horzcat(single_unit_data_all.task_move_fr)';
  1661. passive_stim_psth_allcat = cell2mat(horzcat(single_unit_data_all.passive_stim_psth)');
  1662. task_move_psth_allcat = cell2mat(horzcat(single_unit_data_all.task_move_psth)');
  1663. % (PSTH time - just re-make here)
  1664. raster_window = [-0.5,1];
  1665. raster_sample_rate = 50;
  1666. raster_sample_time = 1/raster_sample_rate;
  1667. t = raster_window(1):raster_sample_time:raster_window(2);
  1668. % Classify narrow vs. wide waveforms
  1669. % (cutoff from Bartho JNeurophys 2004)
  1670. % (wide = 1, narrow = 2);
  1671. waveform_duration_cutoff = 400;
  1672. celltype_exp = cellfun(@(x) (x < waveform_duration_cutoff)+1, ...
  1673. waveform_duration_exp,'uni',false)';
  1674. n_celltypes = length(unique(cell2mat(celltype_exp)));
  1675. celltype_label = {'Wide','Narrow'};
  1676. % (sanity check: plot waveforms by cell type)
  1677. waveform_allcat = cell2mat(horzcat(single_unit_data_all.waveform)');
  1678. figure; hold on
  1679. celltype_col = lines(max(vertcat(celltype_exp{:})));
  1680. for curr_celltype = 1:max(vertcat(celltype_exp{:}))
  1681. plot(waveform_allcat(cell2mat(celltype_exp) == curr_celltype,:)', ...
  1682. 'color',celltype_col(curr_celltype,:));
  1683. end
  1684. wp = gobjects(max(vertcat(celltype_exp{:})),1);
  1685. for curr_celltype = 1:max(vertcat(celltype_exp{:}))
  1686. wp(curr_celltype) = ...
  1687. plot(nanmean(waveform_allcat(cell2mat(celltype_exp) == curr_celltype,:),1), ...
  1688. 'color',max(0,celltype_col(curr_celltype,:)-0.4),'linewidth',3);
  1689. end
  1690. legend(wp,celltype_label);
  1691. % Get firing rate change for stim (passive) and movement (delay)
  1692. passive_stim_fr_diff = cellfun(@(x) nanmean(diff(x,[],3),1), ...
  1693. passive_stim_fr_cat,'uni',false);
  1694. task_move_fr_diff = cellfun(@(x) nanmean(diff(x,[],3),1), ...
  1695. task_move_fr_cat,'uni',false);
  1696. % Get significance from pre/post event shuffle
  1697. stim_sig = cell(length(unit_area_cat),1);
  1698. move_sig = cell(length(unit_area_cat),1);
  1699. for curr_exp = 1:length(unit_area_cat)
  1700. curr_n_units = length(unit_area_cat{curr_exp});
  1701. n_shuff = 1000;
  1702. stim_fr_diff_shuff = nan(n_shuff,curr_n_units);
  1703. move_fr_diff_shuff = nan(n_shuff,curr_n_units);
  1704. for curr_shuff = 1:n_shuff
  1705. stim_fr_diff_shuff(curr_shuff,:) = ...
  1706. nanmean(diff(AP_shake(passive_stim_fr_cat{curr_exp},3),[],3),1);
  1707. move_fr_diff_shuff(curr_shuff,:) = ...
  1708. nanmean(diff(AP_shake(task_move_fr_cat{curr_exp},3),[],3),1);
  1709. end
  1710. % p-value of absolute difference
  1711. stim_fr_diff_p = 1 - cell2mat(arrayfun(@(x) ...
  1712. tiedrank(abs([passive_stim_fr_diff{curr_exp}(x);stim_fr_diff_shuff(:,x)])), ...
  1713. 1:curr_n_units,'uni',false))./(n_shuff+1);
  1714. move_fr_diff_p = 1 - cell2mat(arrayfun(@(x) ...
  1715. tiedrank(abs([task_move_fr_diff{curr_exp}(x);move_fr_diff_shuff(:,x)])), ...
  1716. 1:curr_n_units,'uni',false))./(n_shuff+1);
  1717. % Define significance
  1718. sig_thresh = 0.01;
  1719. stim_fr_diff_sig = stim_fr_diff_p(1,:) <= sig_thresh;
  1720. move_fr_diff_sig = move_fr_diff_p(1,:) <= sig_thresh;
  1721. % Store
  1722. stim_sig{curr_exp} = stim_fr_diff_sig';
  1723. move_sig{curr_exp} = move_fr_diff_sig';
  1724. end
  1725. % Hard-code areas to plot
  1726. plot_areas = ...
  1727. {'Secondary motor area', ...
  1728. 'Anterior cingulate area dorsal part', ...
  1729. 'Prelimbic area', ...
  1730. 'Infralimbic area'};
  1731. % Get and plot fraction of responsive cells by region/experiment
  1732. [~,unit_area_idx] = cellfun(@(x) ismember(x,plot_areas),unit_area_cat,'uni',false);
  1733. stim_frac = cell2mat(permute(cellfun(@(area,celltype,stim_sig,move_sig) ...
  1734. accumarray([area(area ~= 0),celltype(area ~= 0)], ...
  1735. stim_sig(area ~= 0) & ~move_sig(area ~= 0), ...
  1736. [length(plot_areas),2],@mean), ...
  1737. unit_area_idx,celltype_exp,stim_sig,move_sig,'uni',false),[3,2,1]));
  1738. move_frac = cell2mat(permute(cellfun(@(area,celltype,stim_sig,move_sig) ...
  1739. accumarray([area(area ~= 0),celltype(area ~= 0)], ...
  1740. ~stim_sig(area ~= 0) & move_sig(area ~= 0), ...
  1741. [length(plot_areas),2],@mean), ...
  1742. unit_area_idx,celltype_exp,stim_sig,move_sig,'uni',false),[3,2,1]));
  1743. stimmove_frac = cell2mat(permute(cellfun(@(area,celltype,stim_sig,move_sig) ...
  1744. accumarray([area(area ~= 0),celltype(area ~= 0)], ...
  1745. stim_sig(area ~= 0) & move_sig(area ~= 0), ...
  1746. [length(plot_areas),2],@mean), ...
  1747. unit_area_idx,celltype_exp,stim_sig,move_sig,'uni',false),[3,2,1]));
  1748. class_frac = permute(cat(3,nanmean(stim_frac,3), ...
  1749. nanmean(stimmove_frac,3),nanmean(move_frac,3)),[1,3,2]);
  1750. class_col = [0.8,0,0;0.8,0.5,0.5;0.5,0.5,0.5;1,1,1];
  1751. figure; h = tiledlayout(length(plot_areas),n_celltypes);
  1752. for curr_area = 1:length(plot_areas)
  1753. for curr_celltype = 1:n_celltypes
  1754. nexttile;
  1755. curr_data = [class_frac(curr_area,:,curr_celltype), ...
  1756. 1-sum(class_frac(curr_area,:,curr_celltype))];
  1757. pie(curr_data);
  1758. title(sprintf('%s %s',plot_areas{curr_area},celltype_label{curr_celltype}));
  1759. end
  1760. end
  1761. colormap(class_col);
  1762. title(h,'Average fraction across experiments')
  1763. % (plot as bar plot also)
  1764. class_frac_sem = permute(cat(3,AP_sem(stim_frac,3), ...
  1765. AP_sem(stimmove_frac,3),AP_sem(move_frac,3)),[1,3,2]);
  1766. figure; h = tiledlayout(1,n_celltypes);
  1767. for curr_celltype = 1:n_celltypes
  1768. nexttile; hold on; set(gca,'ColorOrder',class_col);
  1769. curr_data = [class_frac(:,:,curr_celltype), ...
  1770. 1-sum(class_frac(:,:,curr_celltype),2)];
  1771. bar(curr_data,'stacked');
  1772. curr_sem = class_frac_sem(:,:,curr_celltype);
  1773. errorbar(cumsum(curr_data(:,1:end-1),2),curr_sem,'k','linewidth',2,'linestyle','none');
  1774. title(celltype_label{curr_celltype});
  1775. set(gca,'XTick',1:length(plot_areas),'XTickLabel',plot_areas);
  1776. ylabel('Fraction of cells');
  1777. end
  1778. % Get and plot fraction of responsive cells (all combined)
  1779. unit_area_idx_allcat = cell2mat(unit_area_idx);
  1780. celltype_allcat = cell2mat(celltype_exp);
  1781. stim_sig_allcat = cell2mat(stim_sig);
  1782. move_sig_allcat = cell2mat(move_sig);
  1783. use_cells = unit_area_idx_allcat ~= 0;
  1784. stim_frac_allcat = ...
  1785. accumarray([unit_area_idx_allcat(use_cells),celltype_allcat(use_cells)], ...
  1786. stim_sig_allcat(use_cells) & ~move_sig_allcat(use_cells),[],@mean);
  1787. move_frac_allcat = ...
  1788. accumarray([unit_area_idx_allcat(use_cells),celltype_allcat(use_cells)], ...
  1789. ~stim_sig_allcat(use_cells) & move_sig_allcat(use_cells),[],@mean);
  1790. stimmove_frac_allcat = ...
  1791. accumarray([unit_area_idx_allcat(use_cells),celltype_allcat(use_cells)], ...
  1792. stim_sig_allcat(use_cells) & move_sig_allcat(use_cells),[],@mean);
  1793. class_frac_allcat = permute(cat(3,stim_frac_allcat, ...
  1794. stimmove_frac_allcat,move_frac_allcat),[1,3,2]);
  1795. figure; h = tiledlayout(length(plot_areas),n_celltypes);
  1796. for curr_area = 1:length(plot_areas)
  1797. for curr_celltype = 1:n_celltypes
  1798. nexttile;
  1799. pie([class_frac_allcat(curr_area,:,curr_celltype), ...
  1800. 1-sum(class_frac_allcat(curr_area,:,curr_celltype))]);
  1801. title(sprintf('%s %s',plot_areas{curr_area},celltype_label{curr_celltype}));
  1802. end
  1803. end
  1804. colormap(class_col);
  1805. title(h,'All cells pooled')
  1806. % Print mean and sem of stim and move cells in MOs and ACA
  1807. stim_frac_dmpfc = cellfun(@(area,sig) ...
  1808. nanmean(sig(ismember(area,[1,2]))), ...
  1809. unit_area_idx,stim_sig);
  1810. move_frac_dmpfc = cellfun(@(area,sig) ...
  1811. nanmean(sig(ismember(area,[1,2]))), ...
  1812. unit_area_idx,move_sig);
  1813. fprintf('Stim dmPFC: %0.2f +- %0.2f\n',nanmean(stim_frac_dmpfc),std(stim_frac_dmpfc));
  1814. fprintf('Move dmPFC: %0.2f +- %0.2f\n',nanmean(move_frac_dmpfc),std(move_frac_dmpfc));
  1815. % Get chance of stim & move cells (combined areas of interest)
  1816. stimmove_frac_total = cellfun(@(area,stim,move) ...
  1817. mean(stim(area~=0) & move(area~=0)),unit_area_idx,stim_sig,move_sig);
  1818. n_shuff = 1000;
  1819. stimmove_frac_total_shuff = nan(length(unit_area_cat),n_shuff);
  1820. for curr_shuff = 1:n_shuff
  1821. % (shuffle movement significance by area)
  1822. curr_move_sig_shuff = cellfun(@(sig,area) ...
  1823. AP_shake(sig,1,area),move_sig,unit_area_cat,'uni',false);
  1824. % (get fraction of sitim & move in shuffle)
  1825. stimmove_frac_total_shuff(:,curr_shuff) = ...
  1826. cellfun(@(area,stim,move) ...
  1827. mean(stim(area~=0) & move(area~=0)), ...
  1828. unit_area_idx,stim_sig,curr_move_sig_shuff);
  1829. end
  1830. stimmove_frac_rank = tiedrank([nanmean(stimmove_frac_total,1), ...
  1831. nanmean(stimmove_frac_total_shuff,1)]);
  1832. stimmove_frac_p = 1 - stimmove_frac_rank(1)./(n_shuff+1);
  1833. fprintf('Stim & move shuffle p = %.2f\n',stimmove_frac_p);
  1834. %%%%%%%%%%%%%% IN PROGRESS ADDITION: PSTHS AND NARROW/WIDE DIFF STATS
  1835. % DO HERE: sort by stim FR diff, and then category?
  1836. passive_stim_fr_diff_cat = horzcat(passive_stim_fr_diff{:})';
  1837. task_move_fr_diff_cat = horzcat(task_move_fr_diff{:})';
  1838. baseline_t = t < -0.2;
  1839. softnorm = 1;
  1840. passive_stim_psth_allcat_norm = ...
  1841. (passive_stim_psth_allcat - nanmean(passive_stim_psth_allcat(:,baseline_t),2))./ ...
  1842. (nanmean(passive_stim_psth_allcat(:,baseline_t),2) + softnorm);
  1843. task_move_psth_allcat_norm = ...
  1844. (task_move_psth_allcat - nanmean(task_move_psth_allcat(:,baseline_t),2))./ ...
  1845. (nanmean(task_move_psth_allcat(:,baseline_t),2) + softnorm);
  1846. figure; h = tiledlayout(length(plot_areas),2*n_celltypes);
  1847. sig_idx = sum([stim_sig_allcat & ~move_sig_allcat, ...
  1848. stim_sig_allcat & move_sig_allcat, ...
  1849. ~stim_sig_allcat & move_sig_allcat].*[1:3],2);
  1850. for curr_area = 1:length(plot_areas)
  1851. for curr_celltype = 1:n_celltypes
  1852. curr_cells = find(unit_area_idx_allcat == curr_area & ...
  1853. celltype_allcat == curr_celltype & stim_sig_allcat);
  1854. % (sort by passive fr diff?)
  1855. [~,sort_idx] = sortrows([passive_stim_fr_diff_cat(curr_cells), ...
  1856. task_move_fr_diff_cat(curr_cells)],[1,2],'descend');
  1857. plot_cells = curr_cells(sort_idx);
  1858. smooth_filt = ones(1,3)/3;
  1859. nexttile;
  1860. imagesc(t,[],convn(passive_stim_psth_allcat_norm(plot_cells,:),smooth_filt,'same'));
  1861. colormap(AP_colormap('BWR'));
  1862. caxis([-1,1].*5);
  1863. nexttile;
  1864. imagesc(t,[],convn(task_move_psth_allcat_norm(plot_cells,:),smooth_filt,'same'));
  1865. colormap(AP_colormap('BWR'));
  1866. caxis([-1,1].*5);
  1867. end
  1868. end
  1869. % linkaxes(allchild(h),'xy');
  1870. % Difference in stim responses in narrow/wide cells
  1871. stim_sig_meas = nanmean(cell2mat(permute(cellfun(@(area,celltype,stim_sig,move_sig) ...
  1872. accumarray([area(area ~= 0),celltype(area ~= 0)], ...
  1873. stim_sig(area ~= 0), ...
  1874. [length(plot_areas),n_celltypes],@mean), ...
  1875. unit_area_idx,celltype_exp,stim_sig,move_sig,'uni',false),[3,2,1])),3);
  1876. n_shuff = 1000;
  1877. stim_sig_shuff = nan(length(plot_areas),n_celltypes,n_shuff);
  1878. for curr_shuff = 1:n_shuff
  1879. stim_sig_shuff(:,:,curr_shuff) = nanmean( ...
  1880. cell2mat(permute(cellfun(@(area,celltype,stim_sig,move_sig) ...
  1881. accumarray([area(area ~= 0),AP_shake(celltype(area ~= 0))], ...
  1882. stim_sig(area ~= 0), ...
  1883. [length(plot_areas),n_celltypes],@mean), ...
  1884. unit_area_idx,celltype_exp,stim_sig,move_sig,'uni',false),[3,2,1])),3);
  1885. end
  1886. figure; hold on;
  1887. AP_errorfill([],[],prctile(diff(stim_sig_shuff,[],2),[5,95],3));
  1888. plot(diff(stim_sig_meas,[],2),'k','linewidth',2);
  1889. set(gca,'XTick',1:length(plot_areas),'XTickLabel',plot_areas);
  1890. ylabel('Narrow - Wide fraction stim-responsive');
  1891. %%%%% TRYING OUT: as above, but just combine dmPFC
  1892. %%%%%%%%%%%%%%%%%% --->>> I THINK THIS IS GOOD,= RUN WITH THIS
  1893. baseline_t = t < -0.3;
  1894. softnorm = 10;
  1895. passive_stim_psth_allcat_norm = ...
  1896. (passive_stim_psth_allcat - nanmean(passive_stim_psth_allcat(:,baseline_t),2))./ ...
  1897. (nanmean(passive_stim_psth_allcat(:,baseline_t),2) + softnorm);
  1898. task_move_psth_allcat_norm = ...
  1899. (task_move_psth_allcat - nanmean(task_move_psth_allcat(:,baseline_t),2))./ ...
  1900. (nanmean(task_move_psth_allcat(:,baseline_t),2) + softnorm);
  1901. % Plot PSTH for dmPFC
  1902. figure; h = tiledlayout(2,n_celltypes);
  1903. for curr_celltype = 1:n_celltypes
  1904. curr_cells = find(ismember(unit_area_idx_allcat,[1,2]) & ...
  1905. celltype_allcat == curr_celltype & stim_sig_allcat);
  1906. % (sort by passive fr diff?)
  1907. [~,sort_idx] = sortrows([move_sig_allcat(curr_cells), ...
  1908. passive_stim_fr_diff_cat(curr_cells)],[1,2],'descend');
  1909. % [~,sort_idx] = sort(passive_stim_fr_diff_cat(curr_cells),'descend');
  1910. plot_cells = curr_cells(sort_idx);
  1911. smooth_filt = ones(1,3)/3;
  1912. nexttile;
  1913. imagesc(t,[],convn(passive_stim_psth_allcat_norm(plot_cells,:),smooth_filt,'same'));
  1914. colormap(AP_colormap('BWR'));
  1915. caxis([-1,1].*2);
  1916. xline(0,'color','k','linewidth',2);
  1917. yline(sum(move_sig_allcat(curr_cells)),'color','k','linewidth',2);
  1918. title(sprintf('dmPFC %s Stim',celltype_label{curr_celltype}));
  1919. nexttile;
  1920. imagesc(t,[],convn(task_move_psth_allcat_norm(plot_cells,:),smooth_filt,'same'));
  1921. colormap(AP_colormap('BWR'));
  1922. caxis([-1,1].*2);
  1923. xline(0,'color','k','linewidth',2);
  1924. yline(sum(move_sig_allcat(curr_cells)),'color','k','linewidth',2);
  1925. title(sprintf('dmPFC %s Move',celltype_label{curr_celltype}));
  1926. end
  1927. dmpfc_units = cellfun(@(area) ismember(area,[1,2]),unit_area_idx,'uni',false);
  1928. class_idx = cellfun(@(stim_sig,move_sig) sum( ...
  1929. [(stim_sig & ~move_sig), ...
  1930. (stim_sig & move_sig), ...
  1931. (~stim_sig & move_sig), ...
  1932. (~stim_sig & ~move_sig)].*[1:4],2), ...
  1933. stim_sig,move_sig,'uni',false); % (1:4 = stim,stim+move,move,none)
  1934. dmpfc_class_frac = cell2mat(permute(cellfun(@(dmpfc,celltype,class_idx) ...
  1935. accumarray([celltype(dmpfc),class_idx(dmpfc)],1,[],@sum)./ ...
  1936. accumarray(celltype(dmpfc),1,[],@sum), ...
  1937. dmpfc_units,celltype_exp,class_idx,'uni',false),[2,3,1]));
  1938. figure; hold on;
  1939. class_col = [0.8,0,0;0.8,0.5,0.5;0.5,0.5,0.5;1,1,1];
  1940. set(gca,'ColorOrder',class_col);
  1941. bar(nanmean(dmpfc_class_frac,3),'stacked');
  1942. errorbar(cumsum(nanmean(dmpfc_class_frac,3),2), ...
  1943. AP_sem(dmpfc_class_frac,3),'k','linewidth',2,'linestyle','none');
  1944. ylabel('Fraction units')
  1945. title('dmPFC')
  1946. set(gca,'XTick',1:n_celltypes,'XTickLabel',celltype_label);
  1947. %%% (shuffle for dmpfc)
  1948. n_shuff = 1000;
  1949. dmpfc_class_frac_shuff = nan(n_celltypes,max(cell2mat(class_idx)),n_shuff);
  1950. for curr_shuff = 1:n_shuff
  1951. dmpfc_class_frac_shuff(:,:,curr_shuff) = nanmean( ...
  1952. cell2mat(permute(cellfun(@(dmpfc,celltype,class_idx) ...
  1953. accumarray([AP_shake(celltype(dmpfc)),class_idx(dmpfc)],1,[],@sum)./ ...
  1954. accumarray(celltype(dmpfc),1,[],@sum), ...
  1955. dmpfc_units,celltype_exp,class_idx,'uni',false),[2,3,1])),3);
  1956. end
  1957. dmpfc_celltype_diff_rank = ...
  1958. tiedrank(vertcat(diff(nanmean(dmpfc_class_frac,3),[],1), ...
  1959. permute(diff(dmpfc_class_frac_shuff,[],1),[3,2,1])));
  1960. dmpfc_celltype_diff_p = dmpfc_celltype_diff_rank(1,:)./(n_shuff+1);
  1961. fprintf('\n Stim p = %.2f\n Stim & Move p = %.2f\n Move p = %.2f\n', ...
  1962. dmpfc_celltype_diff_p(1),dmpfc_celltype_diff_p(2),dmpfc_celltype_diff_p(3));
  1963. % dmPFC waveforms
  1964. dmpfc_units_allcat = cell2mat(dmpfc_units);
  1965. waveform_allcat = cell2mat(horzcat(single_unit_data_all.waveform)');
  1966. [dmpfc_waveform_mean,dmpfc_waveform_std] = ...
  1967. grpstats(waveform_allcat(dmpfc_units_allcat,:), ...
  1968. celltype_allcat(dmpfc_units_allcat),{'mean','std'});
  1969. figure; hold on
  1970. AP_errorfill([],dmpfc_waveform_mean',dmpfc_waveform_std');
  1971. celltype_col = lines(max(vertcat(celltype_exp{:})));
  1972. for curr_celltype = 1:max(vertcat(celltype_exp{:}))
  1973. plot(waveform_allcat(cell2mat(celltype_exp) == curr_celltype,:)', ...
  1974. 'color',celltype_col(curr_celltype,:));
  1975. end
  1976. wp = gobjects(max(vertcat(celltype_exp{:})),1);
  1977. for curr_celltype = 1:max(vertcat(celltype_exp{:}))
  1978. wp(curr_celltype) = ...
  1979. plot(nanmean(waveform_allcat(cell2mat(celltype_exp) == curr_celltype,:),1), ...
  1980. 'color',max(0,celltype_col(curr_celltype,:)-0.4),'linewidth',3);
  1981. end
  1982. legend(wp,celltype_label);
  1983. %% [FIG S2C-E]: V1 muscimol ROI activity pre/post
  1984. % Load data
  1985. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  1986. data_fn = 'trial_activity_passive_teto_muscimol';
  1987. AP_load_trials_operant;
  1988. % Get animal and day index for each trial
  1989. trial_animal = cell2mat(arrayfun(@(x) ...
  1990. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  1991. [1:length(wheel_all)]','uni',false));
  1992. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  1993. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  1994. wheel_all,'uni',false));
  1995. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  1996. % Get trials with movement during stim to exclude
  1997. quiescent_trials = ~any(abs(wheel_allcat(:,t >= 0 & t <= 0.5)) > 0,2);
  1998. % Get average fluorescence by animal, day, stim
  1999. stim_unique = unique(trial_stim_allcat);
  2000. stim_v_avg = cell(length(animals),1);
  2001. stim_roi_avg = cell(length(animals),1);
  2002. stim_roi = cell(length(animals),1);
  2003. for curr_animal = 1:length(animals)
  2004. for curr_day = 1:max(trial_day(trial_animal == curr_animal))
  2005. for curr_stim_idx = 1:length(stim_unique)
  2006. use_trials = quiescent_trials & ...
  2007. trial_animal == curr_animal & ...
  2008. trial_day == curr_day & ...
  2009. trial_stim_allcat == stim_unique(curr_stim_idx);
  2010. stim_v_avg{curr_animal}(:,:,curr_day,curr_stim_idx) = ...
  2011. permute(nanmean(fluor_allcat_deconv(use_trials,:,:),1),[3,2,1]);
  2012. stim_roi_avg{curr_animal}(:,:,curr_day,curr_stim_idx) = ...
  2013. permute(nanmean(fluor_roi_deconv(use_trials,:,:),1),[3,2,1]);
  2014. stim_roi{curr_animal}{curr_day}{curr_stim_idx} = ...
  2015. fluor_roi_deconv(use_trials,:,:);
  2016. end
  2017. end
  2018. end
  2019. % Plot average ROIs
  2020. stim_roi_avg_stage = cat(5,stim_roi_avg{:});
  2021. figure;
  2022. plot_rois = [1,6];
  2023. stage_col = [0.5,0.7,0.7;0,0,0];
  2024. h = tiledlayout(length(plot_rois),2);
  2025. for curr_roi_idx = 1:length(plot_rois)
  2026. curr_l_roi = plot_rois(curr_roi_idx);
  2027. curr_r_roi = curr_l_roi + size(wf_roi,1);
  2028. % (plot left ROI w/ right stim)
  2029. hl = nexttile;
  2030. AP_errorfill(t, ...
  2031. squeeze(nanmean(stim_roi_avg_stage(curr_l_roi,:,:,stim_unique == 1,:),5)), ...
  2032. squeeze(AP_sem(stim_roi_avg_stage(curr_l_roi,:,:,stim_unique == 1,:),5)),stage_col);
  2033. xlabel('Time from stim (s)');
  2034. ylabel('\DeltaF/F_0');
  2035. title(wf_roi(curr_l_roi).area);
  2036. xline([0,0.5]);
  2037. % (plot right ROI with left stim)
  2038. hr =nexttile;
  2039. AP_errorfill(t, ...
  2040. squeeze(nanmean(stim_roi_avg_stage(curr_r_roi,:,:,stim_unique == -1,:),5)), ...
  2041. squeeze(AP_sem(stim_roi_avg_stage(curr_r_roi,:,:,stim_unique == -1,:),5)),stage_col);
  2042. xlabel('Time from stim (s)');
  2043. ylabel('\DeltaF/F_0');
  2044. title(wf_roi(curr_r_roi).area);
  2045. xline([0,0.5]);
  2046. % (link axes with same ROI)
  2047. linkaxes([hl,hr],'xy');
  2048. end
  2049. % (link ROI y-axes)
  2050. ax = reshape(flipud(allchild(h)),2,length(plot_rois))';
  2051. for curr_roi = 1:length(plot_rois)
  2052. linkaxes(ax(:,curr_roi),'y');
  2053. end
  2054. linkaxes(ax,'x');
  2055. xlim([-0.2,0.7]);
  2056. % (draw scalebars)
  2057. x_scale = 0.2;
  2058. y_scale = 3e-3;
  2059. AP_scalebar(x_scale,y_scale);
  2060. % Plot ROI time-max pre/post muscimol
  2061. use_t = t >= 0 & t <= 0.2;
  2062. stim_roi_avg_stage_tmax = squeeze(max(stim_roi_avg_stage(:,use_t,:,:,:),[],2));
  2063. plot_rois = [1,6];
  2064. plot_stim = 3;
  2065. figure; hold on
  2066. curr_data = squeeze(stim_roi_avg_stage_tmax(plot_rois,:,plot_stim,:));
  2067. plot(squeeze(curr_data(1,:,:)),squeeze(curr_data(2,:,:)),'k');
  2068. p1 = plot(squeeze(curr_data(1,2,:)),squeeze(curr_data(2,2,:)),'.','MarkerSize',30,'color',stage_col(2,:));
  2069. p2 = plot(squeeze(curr_data(1,1,:)),squeeze(curr_data(2,1,:)),'.','MarkerSize',30,'color',stage_col(1,:));
  2070. xlabel(wf_roi(plot_rois(1)).area);
  2071. ylabel(wf_roi(plot_rois(2)).area);
  2072. legend([p1,p2],{'Washout','V1 Muscimol'},'location','nw');
  2073. axis square;
  2074. ax = gca;
  2075. ax.XAxis.Exponent = 0;
  2076. ax.YAxis.Exponent = 0;
  2077. % Stats (few values - do left-sided test)
  2078. p = signrank(squeeze(curr_data(2,1,:)),squeeze(curr_data(2,2,:)),'tail','left');
  2079. fprintf('%s muscimol left-sided signed-rank: p = %.2g\n',wf_roi(plot_rois(2)).area,p);
  2080. %% [FIG S4A]: example pupil and facecam frame
  2081. animal = 'AP106';
  2082. day = '2021-06-25';
  2083. experiment = 2;
  2084. load_parts.cam = true;
  2085. verbose = true;
  2086. AP_load_experiment;
  2087. % Pick a frame from the movie
  2088. AP_mousemovie(eyecam_fn,eyecam_t,eyecam_dlc);
  2089. % Get aligned whisker mask for animal/day
  2090. facecam_processing_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\facecam_processing';
  2091. facecam_align_fn = fullfile(facecam_processing_path,'facecam_align.mat');
  2092. load(facecam_align_fn);
  2093. facecam_align_animalidx = find(strcmp(animal,{facecam_align.animal}));
  2094. facecam_align_dayidx = find(strcmp(day,[facecam_align(facecam_align_animalidx).day]));
  2095. whisker_mask = facecam_align(facecam_align_animalidx).whisker_mask{facecam_align_dayidx};
  2096. % Grab sample facecam frame (last frame)
  2097. vr = VideoReader(facecam_fn);
  2098. grab_frame = vr.NumFrames;
  2099. facecam_sample_frame = read(vr,grab_frame);
  2100. % Plot facecam frame and whisker ROI overlaid
  2101. figure;
  2102. image(imoverlay(mat2gray(facecam_sample_frame),whisker_mask,'r'));
  2103. axis image off
  2104. %% ++ [FIG S4 C-G]: passive whisker/pupil and ROI activity
  2105. % Get average pupil diameter and whisker movement to stimuli
  2106. [~,trial_stim_allcat_id] = ismember(trial_stim_allcat,stim_unique);
  2107. [stim_idx,t_idx] = ndgrid(trial_stim_allcat_id,1:length(t));
  2108. [animal_idx,~] = ndgrid(trial_animal,1:length(t));
  2109. [learned_day_id_idx,~] = ndgrid(trial_learned_day_id,1:length(t));
  2110. bhv_accum_idx = cat(3,stim_idx(quiescent_trials,:), ...
  2111. t_idx(quiescent_trials,:), ...
  2112. learned_day_id_idx(quiescent_trials,:), ...
  2113. animal_idx(quiescent_trials,:));
  2114. pupil_diff_stim_avg = accumarray(reshape(bhv_accum_idx,[],size(bhv_accum_idx,3)), ...
  2115. reshape(pupil_diameter_allcat_diff(quiescent_trials,:),[],1),[length(stim_unique),length(t), ...
  2116. max(trial_learned_day_id),length(animals)],@nanmean,NaN);
  2117. whisker_stim_avg = accumarray(reshape(bhv_accum_idx,[],size(bhv_accum_idx,3)), ...
  2118. reshape(whisker_allcat(quiescent_trials,:),[],1),[length(stim_unique),length(t), ...
  2119. max(trial_learned_day_id),length(animals)],@nanmean,NaN);
  2120. bhv_stim_avg = cat(5,pupil_diff_stim_avg,whisker_stim_avg);
  2121. bhv_label = {'Pupil diff','Whisker'};
  2122. [~,~,learning_stage] = unique(learned_day_unique >= 0);
  2123. figure;
  2124. h = tiledlayout(size(bhv_stim_avg,5),max(learning_stage));
  2125. stim_col = [0,0,1;0,0,0;1,0,0];
  2126. for curr_bhv = 1:size(bhv_stim_avg,5)
  2127. for curr_stage = 1:max(learning_stage)
  2128. nexttile;
  2129. curr_mean = nanmean(nanmean(bhv_stim_avg(:,:, ...
  2130. learning_stage == curr_stage,:,curr_bhv),3),4)';
  2131. curr_sem = AP_sem(nanmean(bhv_stim_avg(:,:, ...
  2132. learning_stage == curr_stage,:,curr_bhv),3),4)';
  2133. AP_errorfill(t,curr_mean,curr_sem,stim_col);
  2134. xlabel('Time from stim (s)');
  2135. ylabel(bhv_label{curr_bhv});
  2136. title(sprintf('Stage %d',curr_stage));
  2137. axis tight;
  2138. xlim([-0.2,0.7]);
  2139. xline(0);xline(0.5);
  2140. yline(0);
  2141. end
  2142. end
  2143. % Link bhv y-axes
  2144. ax = reshape(flipud(allchild(h)),2,2)';
  2145. for curr_bhv = 1:2
  2146. linkaxes(ax(curr_bhv,:),'y');
  2147. switch curr_bhv
  2148. case 1
  2149. y_scale = 0.04;
  2150. case 2
  2151. y_scale = 0.1;
  2152. end
  2153. axes(ax(curr_bhv,2));
  2154. x_scale = 0.2;
  2155. AP_scalebar(x_scale,y_scale);
  2156. end
  2157. % Plot whisker movement over time
  2158. use_t = t > 0 & t <= 0.2;
  2159. whisker_stim_tmax = squeeze(max(whisker_stim_avg(:,use_t,:,:),[],2));
  2160. plot_days = min(sum(~isnan(whisker_stim_tmax),3)) >= min_n;
  2161. figure; hold on
  2162. set(gca,'ColorOrder',stim_col);
  2163. errorbar(repmat(learned_day_unique(plot_days),1,length(stim_unique)), ...
  2164. nanmean(whisker_stim_tmax(:,plot_days,:),3)', ...
  2165. AP_sem(whisker_stim_tmax(:,plot_days,:),3)','linewidth',2,'CapSize',0);
  2166. axis tight;
  2167. xlim(xlim+[-0.5,0.5]);
  2168. xline(0,'color','k','linestyle','--');
  2169. xlabel('Learned day');
  2170. ylabel('Whisker movement');
  2171. % Plot fluorescence/whisker by discretized whisker movement
  2172. plot_rois = [6];
  2173. min_trials = 10; % (minimum trials to use within recording)
  2174. trial_learned_stage = discretize(trial_learned_day,[-Inf,0,Inf]);
  2175. % (discretize whisker movement within recording - use R stim trials)
  2176. use_t = t > 0 & t <= 0.2;
  2177. whisker_allcat_tavg = max(whisker_allcat(:,use_t),[],2);
  2178. whisker_grp_use_trials = quiescent_trials & ...
  2179. ~all(isnan(whisker_allcat),2);
  2180. whisker_recording = mat2cell(whisker_allcat_tavg,trials_recording);
  2181. whisker_grp_use_trials_recording = mat2cell(whisker_grp_use_trials,trials_recording);
  2182. whisker_grp_use_recordings = cellfun(@(whisker,use_trials) ...
  2183. ~all(isnan(whisker)) & sum(use_trials) > min_trials,...
  2184. whisker_recording,whisker_grp_use_trials_recording);
  2185. n_whisker_grps = 4;
  2186. whisker_grp = cellfun(@(x) nan(size(x)),whisker_recording,'uni',false);
  2187. whisker_grp(whisker_grp_use_recordings) = cellfun(@(whisker,use_trials) ...
  2188. discretize(whisker, ...
  2189. prctile(whisker(use_trials),linspace(0,100,n_whisker_grps+1))), ...
  2190. whisker_recording(whisker_grp_use_recordings), ...
  2191. whisker_grp_use_trials_recording(whisker_grp_use_recordings),'uni',false);
  2192. whisker_grp = cell2mat(whisker_grp);
  2193. % (get indicies for grouping)
  2194. [animal_idx,t_idx,roi_idx] = ndgrid(trial_animal,1:length(t),1:n_rois);
  2195. [whisker_grp_idx,~,~] = ndgrid(whisker_grp,1:length(t),1:n_rois);
  2196. [learned_stage_idx,~,~] = ndgrid(trial_learned_stage,1:length(t),1:n_rois);
  2197. accum_whisker_idx = cat(4,whisker_grp_idx,t_idx,learned_stage_idx,roi_idx,animal_idx);
  2198. % (plot grouped whisker movements and ROI fluorescence)
  2199. line_fig = figure;
  2200. stim_col = [0,0,1;0,0,0;1,0,0];
  2201. whisker_grp_col = copper(n_whisker_grps);
  2202. ax = gobjects((length(plot_rois)+1)*max(trial_learned_stage),length(stim_unique));
  2203. for curr_stim_idx = 1:length(stim_unique)
  2204. curr_stim = stim_unique(curr_stim_idx);
  2205. use_trials = trial_stim_allcat == curr_stim & quiescent_trials & ...
  2206. ~all(isnan(whisker_allcat),2) & ~isnan(whisker_grp);
  2207. whisker_whiskergrp_avg = accumarray( ...
  2208. reshape(accum_whisker_idx(use_trials,:,1,[1,2,3,5],:),[],size(accum_whisker_idx,4)-1), ...
  2209. reshape(whisker_allcat(use_trials,:),[],1),[],@nanmean,NaN);
  2210. fluor_roi_whiskergrp_avg = accumarray( ...
  2211. reshape(accum_whisker_idx(use_trials,:,:,:),[],size(accum_whisker_idx,4)), ...
  2212. reshape(fluor_roi_deconv(use_trials,:,:),[],1),[],@nanmean,NaN('single'));
  2213. figure;
  2214. h = tiledlayout(max(trial_learned_stage),length(plot_rois)+1, ...
  2215. 'TileSpacing','compact','padding','compact');
  2216. for curr_stage = 1:max(trial_learned_stage)
  2217. nexttile;
  2218. AP_errorfill(t, ...
  2219. nanmean(whisker_whiskergrp_avg(:,:,curr_stage,:),4)', ...
  2220. AP_sem(whisker_whiskergrp_avg(:,:,curr_stage,:),4)', ...
  2221. whisker_grp_col);
  2222. title(sprintf('Whiskers, stage %d',curr_stage));
  2223. axis tight;
  2224. xlim([-0.2,0.7]);
  2225. xline(0);
  2226. xlabel('Time from stim (s)');
  2227. ylabel('Pixel intensity change');
  2228. for curr_roi = plot_rois
  2229. nexttile;
  2230. AP_errorfill(t, ...
  2231. squeeze(nanmean(fluor_roi_whiskergrp_avg(:,:,curr_stage,curr_roi,:),5))', ...
  2232. squeeze(AP_sem(fluor_roi_whiskergrp_avg(:,:,curr_stage,curr_roi,:),5))', ...
  2233. whisker_grp_col);
  2234. title(sprintf('%s, stage %d',wf_roi(curr_roi).area,curr_stage));
  2235. axis tight;
  2236. xlim([-0.2,0.7]);
  2237. xline(0);
  2238. xlabel('Time from stim (s)');
  2239. ylabel('\DeltaF/F0');
  2240. end
  2241. end
  2242. ax(:,curr_stim_idx) = flipud(allchild(h));
  2243. title(h,sprintf('Whisker move groups (stim %d)',curr_stim));
  2244. % Plot line plot of fluorescence vs whisker
  2245. stage_col = [0.5,0.5,0.5;0,0,0];
  2246. for curr_stage = 1:max(trial_learned_stage)
  2247. for curr_roi_idx = 1:length(plot_rois)
  2248. curr_roi = plot_rois(curr_roi_idx);
  2249. curr_ax = subplot(1,length(plot_rois),curr_roi_idx,'Parent',line_fig);
  2250. hold(curr_ax,'on');
  2251. curr_whisker_whiskergrp_tavg = ...
  2252. squeeze(nanmean(whisker_whiskergrp_avg(:,use_t,curr_stage,:),2));
  2253. curr_fluor_roi_whiskergrp_tavg = ...
  2254. squeeze(nanmean(fluor_roi_whiskergrp_avg(:,use_t,curr_stage,curr_roi,:),2));
  2255. x = nanmean(curr_whisker_whiskergrp_tavg,2);
  2256. x_err = AP_sem(curr_whisker_whiskergrp_tavg,2);
  2257. y = nanmean(curr_fluor_roi_whiskergrp_tavg,2);
  2258. y_err = AP_sem(curr_fluor_roi_whiskergrp_tavg,2);
  2259. errorbar(curr_ax,x,y,-y_err,y_err,-x_err,x_err, ...
  2260. 'linewidth',2,'capsize',0,'color', ...
  2261. min(1,stim_col(curr_stim_idx,:) + stage_col(curr_stage,:)));
  2262. xlabel(curr_ax,'Whisker movement');
  2263. ylabel(curr_ax,'\DeltaF/F_0');
  2264. title(curr_ax,wf_roi(curr_roi).area);
  2265. end
  2266. end
  2267. end
  2268. % (link modality axes across figures)
  2269. for i = 1:length(plot_rois)+1
  2270. linkaxes(ax(i:length(plot_rois)+1:end,:),'xy');
  2271. axes(ax(i,end));
  2272. if i == 1
  2273. y_scale = 0.2;
  2274. else
  2275. y_scale = 4e-4;
  2276. end
  2277. x_scale = 0.2;
  2278. AP_scalebar(x_scale,y_scale);
  2279. drawnow;
  2280. end
  2281. % (legend for line plots - yes, ridiculous code)
  2282. line_fig_ax = get(line_fig,'Children');
  2283. line_fig_ax_lines = get(line_fig_ax(1),'Children');
  2284. legend(line_fig_ax_lines, ...
  2285. fliplr(flipud(cellfun(@(x,y) [x ', ' y], ...
  2286. repmat(arrayfun(@(x) sprintf('Stage %d',x), ...
  2287. 1:max(trial_learned_stage),'uni',false),length(stim_unique),1), ...
  2288. repmat(arrayfun(@(x) sprintf('Stim %d',x), ...
  2289. stim_unique,'uni',false),1,max(trial_learned_stage)),'uni',false)')), ...
  2290. 'location','nw');
  2291. % Stats: ANOVA
  2292. for curr_stim = stim_unique'
  2293. use_trials = trial_stim_allcat == curr_stim & quiescent_trials & ...
  2294. ~all(isnan(whisker_allcat),2) & ~isnan(whisker_grp);
  2295. fluor_roi_whiskergrp_avg = accumarray( ...
  2296. reshape(accum_whisker_idx(use_trials,:,:,:),[],size(accum_whisker_idx,4)), ...
  2297. reshape(fluor_roi_deconv(use_trials,:,:),[],1),[],@nanmean,NaN('single'));
  2298. curr_data = squeeze(nanmean(fluor_roi_whiskergrp_avg(:,use_t,:,curr_roi,:),2));
  2299. p = anova2(reshape(permute(curr_data,[3,1,2]),[],2),length(animals),'off');
  2300. fprintf('%s stim %d 2-way anova: p(stage) = %.2g\n',wf_roi(curr_roi).area,curr_stim,p(1));
  2301. end
  2302. %% (diagram: plot widefield ROIs)
  2303. wf_roi_fn = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\wf_processing\wf_rois\wf_roi';
  2304. load(wf_roi_fn);
  2305. n_rois = numel(wf_roi);
  2306. plot_rois = reshape([1,6,7]' + [0,size(wf_roi,1)],[],1)';
  2307. roi_col = copper(n_rois);
  2308. roi_cat = cat(3,wf_roi.mask);
  2309. figure;
  2310. subplot(1,2,1); hold on
  2311. set(gca,'YDir','reverse');
  2312. AP_reference_outline('ccf_aligned_lefthemi',[0.7,0.7,0.7]);
  2313. for curr_roi = plot_rois
  2314. curr_roi_boundary = cell2mat(bwboundaries(roi_cat(:,:,curr_roi)));
  2315. patch(curr_roi_boundary(:,2),curr_roi_boundary(:,1),roi_col(curr_roi,:), ...
  2316. 'EdgeColor','none');
  2317. end
  2318. axis image off;
  2319. subplot(1,2,2); hold on;
  2320. set(gca,'YDir','reverse');
  2321. AP_reference_outline('ccf_aligned',[0.7,0.7,0.7]);
  2322. for curr_roi = plot_rois
  2323. curr_roi_boundary = cell2mat(bwboundaries(roi_cat(:,:,curr_roi)));
  2324. patch(curr_roi_boundary(:,2),curr_roi_boundary(:,1),roi_col(curr_roi,:), ...
  2325. 'EdgeColor','none');
  2326. end
  2327. axis image off;
  2328. %% ------- REVISION: IN PROGRESS -----------------------
  2329. %% ++ Long-term post-learning widefield
  2330. % Get training data from subset of long-term animals
  2331. long_term_animals = {'AP113','AP114','AP115'};
  2332. use_animals = ismember(animals,long_term_animals);
  2333. % Average V/ROI by learning stage
  2334. % (combined naive and pre-learn)
  2335. stim_v_avg_stage = cell2mat(permute(cellfun(@(x,ld) ...
  2336. cat(3, ...
  2337. nanmean(x(:,:,1:ld-1,:),3), ...
  2338. nanmean(x(:,:,ld:end,:),3)), ...
  2339. stim_v_avg,num2cell(learned_day+n_naive), ...
  2340. 'uni',false),[2,3,4,5,1]));
  2341. stim_roi_avg_stage = cell2mat(permute(cellfun(@(x,ld) ...
  2342. cat(3, ...
  2343. nanmean(x(:,:,1:ld-1,:),3), ...
  2344. nanmean(x(:,:,ld:end,:),3)), ...
  2345. stim_roi_avg,num2cell(learned_day+n_naive), ...
  2346. 'uni',false),[2,3,4,5,1]));
  2347. % Get pixels and pixel timemax by stage
  2348. stim_px_avg_stage = AP_svdFrameReconstruct(U_master(:,:,1:n_vs),stim_v_avg_stage);
  2349. use_t = t >= 0 & t <= 0.2;
  2350. stim_px_avg_stage_tmax = ...
  2351. squeeze(max(stim_px_avg_stage(:,:,use_t,:,:,:),[],3));
  2352. % Set ROIs to plot
  2353. % Get indicies for averaging
  2354. [trained_day_idx,t_idx,roi_idx] = ...
  2355. ndgrid(trial_day,1:length(t),1:n_rois);
  2356. [learned_day_idx,~,~] = ...
  2357. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  2358. [animal_idx,~,~] = ...
  2359. ndgrid(trial_animal,1:length(t),1:n_rois);
  2360. [stim_idx,~,~] = ...
  2361. ndgrid(trial_stim_id,1:length(t),1:n_rois);
  2362. accum_idx = cat(4,trained_day_idx,learned_day_idx,t_idx,roi_idx,stim_idx,animal_idx);
  2363. use_trials_naive = quiescent_trials & trial_day <= n_naive;
  2364. use_trials_training = quiescent_trials & trial_day > n_naive;
  2365. roi_learnday_avg = accumarray( ...
  2366. reshape(accum_idx(use_trials_training,:,:,[2,3,4,5,6]),[],5), ...
  2367. reshape(fluor_roi_deconv(use_trials_training,:,:),[],1), ...
  2368. [length(learned_day_unique),length(t),n_rois,length(stim_unique),length(animals)], ...
  2369. @nanmean,NaN('single'));
  2370. % Keep pixels and ROI data from training, then clear
  2371. plot_stim = 1;
  2372. % (pixels)
  2373. px_training_stage = nanmean(stim_px_avg_stage_tmax(:,:,:, ...
  2374. stim_unique == plot_stim,use_animals),5);
  2375. % (ROI)
  2376. plot_roi = 6;
  2377. use_t = t > 0 & t <= 0.2;
  2378. mpfc_training_stage = squeeze(max(cat(1,...
  2379. nanmean(roi_learnday_avg(learned_day_unique < 0,use_t, ...
  2380. plot_roi,stim_unique == plot_stim,use_animals),1), ...
  2381. nanmean(roi_learnday_avg(learned_day_unique >= 0,use_t, ...
  2382. plot_roi,stim_unique == plot_stim,use_animals),1)),[],2));
  2383. clearvars -except px_training_stage mpfc_training_stage
  2384. %%% LOAD POST-TRAINING DATA
  2385. % Load data
  2386. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  2387. data_fn = 'trial_activity_passive_teto_postlearn';
  2388. AP_load_trials_operant;
  2389. % Get animal and day index for each trial
  2390. trial_animal = cell2mat(arrayfun(@(x) ...
  2391. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  2392. [1:length(wheel_all)]','uni',false));
  2393. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  2394. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  2395. wheel_all,'uni',false));
  2396. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  2397. % Store day relative to last task day
  2398. task_relative_day = cellfun(@(day,taskday) day' - taskday, ...
  2399. recording_day,last_task_right_day,'uni',false)';
  2400. retired_relative_day = cellfun(@(day,taskday) day' - taskday, ...
  2401. recording_day,last_task_left_day,'uni',false)';
  2402. trial_postlearn_day = cell2mat(cellfun(@(x,day) cell2mat(cellfun(@(x,day) ...
  2403. day*ones(size(x,1),1),x,num2cell(day),'uni',false)), ...
  2404. wheel_all,task_relative_day,'uni',false));
  2405. % Get trials with movement during stim to exclude
  2406. quiescent_trials = ~any(abs(wheel_allcat(:,t >= 0 & t <= 0.5)) > 0,2);
  2407. % Turn values into IDs for grouping
  2408. stim_unique = unique(trial_stim_allcat);
  2409. [~,trial_stim_id] = ismember(trial_stim_allcat,stim_unique);
  2410. % Get average fluorescence by animal/day/stim
  2411. stim_v_avg = cell(length(animals),1);
  2412. stim_roi_avg = cell(length(animals),1);
  2413. for curr_animal = 1:length(animals)
  2414. for curr_day = 1:max(trial_day(trial_animal == curr_animal))
  2415. for curr_stim_idx = 1:length(stim_unique)
  2416. use_trials = quiescent_trials & ...
  2417. trial_animal == curr_animal & ...
  2418. trial_day == curr_day & ...
  2419. trial_stim_allcat == stim_unique(curr_stim_idx);
  2420. stim_v_avg{curr_animal}(:,:,curr_day,curr_stim_idx) = ...
  2421. permute(nanmean(fluor_allcat_deconv(use_trials,:,:),1),[3,2,1]);
  2422. stim_roi_avg{curr_animal}(:,:,curr_day,curr_stim_idx) = ...
  2423. permute(nanmean(fluor_roi_deconv(use_trials,:,:),1),[3,2,1]);
  2424. end
  2425. end
  2426. end
  2427. %%% Get post-learning pixels and ROI
  2428. % Get relative post-learned days
  2429. % (all animals imaged in same intervals, so unique should be same as length)
  2430. task_relative_day_unique = unique(cat(1,task_relative_day{:}));
  2431. retired_relative_day_unique = unique(cat(1,retired_relative_day{:}));
  2432. if ~all(task_relative_day_unique == cat(2,task_relative_day{:}),'all')
  2433. error('Different relative days across animals');
  2434. end
  2435. % Get average image by day
  2436. use_stim = stim_unique == 1;
  2437. use_t = t >= 0 & t <= 0.2;
  2438. stim_v_dayavg = nanmean(cat(5,stim_v_avg{:}),5);
  2439. stim_px_dayavg = AP_svdFrameReconstruct(U_master(:,:,1:n_vs),stim_v_dayavg(:,:,:,use_stim));
  2440. stim_px_dayavg_tmax = squeeze(max(stim_px_dayavg(:,:,use_t,:),[],3));
  2441. % Get average ROI by day
  2442. stim_roi_avg_cat = cat(5,stim_roi_avg{:});
  2443. stim_roi_day = squeeze(stim_roi_avg_cat(:,:,:,use_stim,:));
  2444. % Get ROI activity within stim window
  2445. use_t = t > 0 & t <= 0.2;
  2446. stim_roi_avg_tmax = squeeze(max(stim_roi_avg_cat(:,use_t,:,:,:),[],2));
  2447. % Grab pixels and ROI data from post-training, concatenate to pre-training
  2448. plot_stim = 1;
  2449. % (pixels)
  2450. px_posttraining_stage = stim_px_dayavg_tmax;
  2451. % (ROI)
  2452. plot_roi = 6;
  2453. mpfc_posttraining_stage = squeeze(stim_roi_avg_tmax(plot_roi,:,stim_unique == plot_stim,:));
  2454. px_prepost_training = cat(3,px_training_stage,px_posttraining_stage);
  2455. mpfc_prepost_training = cat(1,mpfc_training_stage,mpfc_posttraining_stage);
  2456. % Plot pixels and ROIs across pre/post-training
  2457. prepost_training_labels = [{'Novice','Trained', ...
  2458. sprintf('%d days from R task',task_relative_day_unique(1))}, ...
  2459. cellfun(@(x) sprintf('%d days devalued',x), ...
  2460. num2cell(retired_relative_day_unique(2:end))','uni',false)];
  2461. figure;
  2462. h = tiledlayout(1,size(px_prepost_training,3));
  2463. c = [0,0.003];
  2464. for curr_stage = 1:size(px_prepost_training,3)
  2465. nexttile;
  2466. imagesc(px_prepost_training(:,:,curr_stage));
  2467. axis image off;
  2468. AP_reference_outline('ccf_aligned',[0.5,0.5,0.5]);
  2469. colormap(gca,AP_colormap('WG',[],1.5));
  2470. caxis(c);
  2471. title(prepost_training_labels{curr_stage});
  2472. end
  2473. linkaxes(allchild(h),'xy');
  2474. colorbar;
  2475. figure; hold on;
  2476. plot(mpfc_prepost_training,'color',[0.5,0.5,0.5]);
  2477. plot(nanmean(mpfc_prepost_training,2),'color','k','linewidth',2);
  2478. ylabel(wf_roi(plot_roi).area);
  2479. set(gca,'XTick',1:length(prepost_training_labels), ...
  2480. 'XTickLabels',prepost_training_labels);
  2481. %% ++ Reaction time by activity plot
  2482. % (this is a bit messy - clean this up)
  2483. % Load behavior, exclude animals not in dataset, get learned day
  2484. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  2485. bhv_fn = [data_path filesep 'bhv_teto'];
  2486. load(bhv_fn);
  2487. bhv = bhv(ismember({bhv.animal},animals));
  2488. learned_day = cellfun(@(x) find(x,1),{bhv.learned_days})';
  2489. learned_day_animal = cellfun(@(ld,n) [1:n]'-(ld), ...
  2490. num2cell(learned_day),num2cell(cellfun(@length,trial_info_all)), ...
  2491. 'uni',false);
  2492. % Load muscimol injection info
  2493. data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  2494. muscimol_fn = [data_path filesep 'muscimol.mat'];
  2495. load(muscimol_fn);
  2496. % Use days before muscimol
  2497. use_days = cell(size(bhv));
  2498. for curr_animal = 1:length(bhv)
  2499. muscimol_animal_idx = ismember({muscimol.animal},bhv(curr_animal).animal);
  2500. if ~any(muscimol_animal_idx)
  2501. use_days{curr_animal} = true(length(bhv(curr_animal).day),1);
  2502. continue
  2503. end
  2504. muscimol_day_idx = datenum(bhv(curr_animal).day) >= ...
  2505. datenum(muscimol(muscimol_animal_idx).day(1));
  2506. use_days{curr_animal} = ~muscimol_day_idx;
  2507. end
  2508. max_days = max(cellfun(@sum,use_days));
  2509. % Get reaction/resampled alt reaction times for all regular days
  2510. % (exclude trials without alts: rare, from wheel click issues)
  2511. use_rxn = cellfun(@(x) cellfun(@(x) cellfun(@(x) ...
  2512. ~isempty(x),x),x,'uni',false),{bhv.alt_stim_move_t},'uni',false);
  2513. rxn_measured = cellfun(@(rxn,use_days,use_trials) ...
  2514. cellfun(@(rxn,use_trials) rxn(use_trials),rxn(use_days),use_trials(use_days),'uni',false), ...
  2515. {bhv.stim_move_t},use_days,use_rxn,'uni',false)';
  2516. n_rxn_altsample = 1000;
  2517. rxn_alt = cellfun(@(rxn,use_days,use_trials) ...
  2518. cellfun(@(rxn,use_trials) ...
  2519. cell2mat(cellfun(@(x) datasample(x,n_rxn_altsample)',rxn(use_trials),'uni',false)), ...
  2520. rxn(use_days),use_trials(use_days),'uni',false), ...
  2521. {bhv.alt_stim_move_t},use_days,use_rxn,'uni',false)';
  2522. % Concatenate and get indicies
  2523. rxn_measured_allcat = cell2mat(cellfun(@cell2mat,rxn_measured,'uni',false));
  2524. rxn_alt_allcat = cell2mat(cellfun(@cell2mat,rxn_alt,'uni',false));
  2525. animal_idx = cell2mat(cellfun(@(x,animal) repmat(animal,length(cell2mat(x)),1), ...
  2526. rxn_measured,num2cell(1:length(bhv))','uni',false));
  2527. day_idx = cell2mat(cellfun(@(x) cell2mat(cellfun(@(x,day) ...
  2528. repmat(day,length(x),1),x,num2cell(1:length(x))','uni',false)), ...
  2529. rxn_measured,'uni',false));
  2530. % Reaction time median: whole day
  2531. % (exclude too-fast rxn < 0.1)
  2532. rxn_measured_med = accumarray([day_idx,animal_idx], ...
  2533. rxn_measured_allcat.*AP_nanout(rxn_measured_allcat < 0.1), ...
  2534. [max_days,length(bhv)],@(x) nanmedian(x),NaN);
  2535. rxn_alt_med = cell2mat(permute(arrayfun(@(x) ...
  2536. accumarray([day_idx,animal_idx], ...
  2537. rxn_alt_allcat(:,x).*AP_nanout(rxn_alt_allcat(:,x) < 0.1), ...
  2538. [max_days,length(bhv)],@(x) nanmedian(x),NaN), ...
  2539. 1:n_rxn_altsample,'uni',false),[1,3,2]));
  2540. % Get average ROI activity
  2541. % Get indicies for averaging
  2542. % (adjust trial day to only include training days)
  2543. trial_day_training = trial_day - n_naive;
  2544. [trained_day_idx,t_idx,roi_idx] = ...
  2545. ndgrid(trial_day_training,1:length(t),1:n_rois);
  2546. [learned_day_idx,~,~] = ...
  2547. ndgrid(trial_learned_day_id,1:length(t),1:n_rois);
  2548. [animal_idx,~,~] = ...
  2549. ndgrid(trial_animal,1:length(t),1:n_rois);
  2550. [stim_idx,~,~] = ...
  2551. ndgrid(trial_stim_id,1:length(t),1:n_rois);
  2552. accum_idx = cat(4,trained_day_idx,learned_day_idx,t_idx,roi_idx,stim_idx,animal_idx);
  2553. use_trials_training = quiescent_trials & trial_day_training > 0;
  2554. roi_trainday_avg = accumarray( ...
  2555. reshape(accum_idx(use_trials_training,:,:,[1,3,4,5,6]),[],5), ...
  2556. reshape(fluor_roi_deconv(use_trials_training,:,:),[],1), ...
  2557. [max(trial_day_training),length(t),n_rois,length(stim_unique),length(animals)], ...
  2558. @nanmean,NaN('single'));
  2559. % Get ROI activity within stim window
  2560. use_t = t > 0 & t <= 0.2;
  2561. stim_roi_trainday_avg_tmax = squeeze(max(roi_trainday_avg(:,use_t,:,:,:),[],2));
  2562. % Plot activity against reaction times
  2563. plot_roi = 6;
  2564. plot_stim = 1;
  2565. plot_rxn = (nanmean(rxn_alt_med,3)-rxn_measured_med)./ ...
  2566. (nanmean(rxn_alt_med,3)+rxn_measured_med);
  2567. plot_act = permute(stim_roi_trainday_avg_tmax(:,plot_roi, ...
  2568. stim_unique == plot_stim,:),[1,4,2,3]);
  2569. animal_col = max(0,jet(length(animals))-0.2);
  2570. figure;
  2571. % (plot single mouse example - lines and scatter)
  2572. example_animal = 1;
  2573. subplot(1,3,1); hold on; axis square;
  2574. yyaxis left;plot(plot_rxn(:,example_animal),'k','linewidth',2);
  2575. axis tight;
  2576. ylabel('Reaction time idx');
  2577. yyaxis right;plot(plot_act(:,example_animal),'r','linewidth',2);
  2578. axis tight;
  2579. ylabel(wf_roi(plot_roi).area);
  2580. title(animals(example_animal));
  2581. xlabel('Day');
  2582. subplot(1,3,2); hold on; axis square;
  2583. plot(plot_rxn(:,example_animal),plot_act(:,example_animal), ...
  2584. '.-','MarkerSize',15,'color',animal_col(example_animal,:),'linewidth',2);
  2585. xlabel('Reaction time idx');
  2586. ylabel(wf_roi(plot_roi).area);
  2587. title(animals(example_animal));
  2588. % (plot all mice together)
  2589. subplot(1,3,3); hold on; axis square;
  2590. set(gca,'ColorOrder',animal_col);
  2591. plot(plot_rxn,plot_act,'.','MarkerSize',15);
  2592. xlabel({'Reaction time idx','(alt-meas/alt+meas)'})
  2593. ylabel(wf_roi(plot_roi).area);
  2594. axis tight;
  2595. xlim(xlim + 0.1*range(xlim).*[-1,1]);
  2596. ylim(ylim + 0.1*range(ylim).*[-1,1]);
  2597. % Plot all mice separately
  2598. figure; h = tiledlayout('flow');
  2599. for curr_animal = 1:length(animals)
  2600. nexttile;
  2601. yyaxis left;plot(plot_rxn(:,curr_animal),'k','linewidth',2);
  2602. axis tight; ylim(ylim + 0.1*range(ylim).*[-1,1]);
  2603. ylabel('Reaction time idx');
  2604. yyaxis right;plot(plot_act(:,curr_animal),'r','linewidth',2);
  2605. axis tight; ylim(ylim + 0.1*range(ylim).*[-1,1]);
  2606. ylabel(wf_roi(plot_roi).area);
  2607. title(animals(curr_animal));
  2608. xlabel('Day');
  2609. xlim(xlim+[-1,1]);
  2610. end
  2611. %% ITI turns: quantify frequency of turning with no stim
  2612. %% Naive ephys - plot probe position
  2613. animals = {'AP116','AP117','AP118','AP119'};
  2614. % Load CCF annotated volume
  2615. allen_atlas_path = fileparts(which('template_volume_10um.npy'));
  2616. av = readNPY([allen_atlas_path filesep 'annotation_volume_10um_by_index.npy']);
  2617. st = loadStructureTree([allen_atlas_path filesep 'structure_tree_safe_2017.csv']);
  2618. figure;
  2619. animal_col = repmat([0,0,0],length(animals),1);
  2620. % Set up 3D axes
  2621. ccf_3d_axes = subplot(1,4,1);
  2622. [~, brain_outline] = plotBrainGrid([],ccf_3d_axes);
  2623. set(ccf_3d_axes,'ZDir','reverse');
  2624. hold(ccf_3d_axes,'on');
  2625. axis vis3d equal off manual
  2626. view([-30,25]);
  2627. axis tight;
  2628. h = rotate3d(ccf_3d_axes);
  2629. h.Enable = 'on';
  2630. % Set up 2D axes
  2631. bregma_ccf = [540,44,570];
  2632. ccf_size = size(av);
  2633. ccf_axes = gobjects(3,1);
  2634. ccf_axes(1) = subplot(1,4,2,'YDir','reverse');
  2635. hold on; axis image off;
  2636. ccf_axes(2) = subplot(1,4,3,'YDir','reverse');
  2637. hold on; axis image off;
  2638. ccf_axes(3) = subplot(1,4,4,'YDir','reverse');
  2639. hold on; axis image off;
  2640. for curr_view = 1:3
  2641. curr_outline = bwboundaries(squeeze((max(av,[],curr_view)) > 1));
  2642. cellfun(@(x) plot(ccf_axes(curr_view),x(:,2),x(:,1),'k','linewidth',2),curr_outline)
  2643. curr_bregma = fliplr(bregma_ccf(setdiff(1:3,curr_view)));
  2644. plot(ccf_axes(curr_view),curr_bregma(1),curr_bregma(2),'rx');
  2645. curr_size = fliplr(ccf_size(setdiff(1:3,curr_view)));
  2646. xlim(ccf_axes(curr_view),[0,curr_size(1)]);
  2647. ylim(ccf_axes(curr_view),[0,curr_size(2)]);
  2648. end
  2649. linkaxes(ccf_axes);
  2650. % Plot specific areas
  2651. plot_structure_names = {'Secondary motor area', ...
  2652. 'Anterior cingulate area','Prelimbic area','Infralimbic area'};
  2653. plot_structure_colors = lines(length(plot_structure_names));
  2654. for plot_structure_name = plot_structure_names
  2655. plot_structure = find(strcmp(st.safe_name,plot_structure_name));
  2656. % Get all areas within and below the selected hierarchy level
  2657. plot_structure_id = st.structure_id_path{plot_structure};
  2658. plot_ccf_idx = find(cellfun(@(x) contains(x,plot_structure_id), ...
  2659. st.structure_id_path));
  2660. % plot the structure
  2661. slice_spacing = 5;
  2662. plot_structure_color = plot_structure_colors( ...
  2663. strcmp(plot_structure_name,plot_structure_names),:);
  2664. % Get structure volume
  2665. plot_ccf_volume = ismember(av(1:slice_spacing:end,1:slice_spacing:end,1:slice_spacing:end),plot_ccf_idx);
  2666. for curr_view = 1:3
  2667. curr_outline = bwboundaries(squeeze((max(plot_ccf_volume,[],curr_view))));
  2668. cellfun(@(x) plot(ccf_axes(curr_view),x(:,2)*slice_spacing, ...
  2669. x(:,1)*slice_spacing,'color',plot_structure_color,'linewidth',2),curr_outline)
  2670. end
  2671. end
  2672. % Plot probe locations
  2673. probe_coords_mean_all = nan(length(animals),3);
  2674. for curr_animal = 1:length(animals)
  2675. animal = animals{curr_animal};
  2676. % Load animal probe histology
  2677. [probe_ccf_fn,probe_ccf_fn_exists] = AP_cortexlab_filename(animal,[],[],'probe_ccf');
  2678. load(probe_ccf_fn);
  2679. % Get line of best fit through mean of marked points
  2680. probe_coords_mean = mean(probe_ccf.points,1);
  2681. % (store mean for plotting later)
  2682. probe_coords_mean_all(curr_animal,:) = probe_coords_mean;
  2683. xyz = bsxfun(@minus,probe_ccf.points,probe_coords_mean);
  2684. [~,~,V] = svd(xyz,0);
  2685. histology_probe_direction = V(:,1);
  2686. % (make sure the direction goes down in DV - flip if it's going up)
  2687. if histology_probe_direction(2) < 0
  2688. histology_probe_direction = -histology_probe_direction;
  2689. end
  2690. % Evaluate line of best fit (length of probe to deepest point)
  2691. [~,deepest_probe_idx] = max(probe_ccf.points(:,2));
  2692. probe_deepest_point = probe_ccf.points(deepest_probe_idx,:);
  2693. probe_deepest_point_com_dist = pdist2(probe_coords_mean,probe_deepest_point);
  2694. probe_length_ccf = 3840/10; % mm / ccf voxel size
  2695. probe_line_eval = probe_deepest_point_com_dist - [probe_length_ccf,0];
  2696. probe_line = (probe_line_eval'.*histology_probe_direction') + probe_coords_mean;
  2697. % Draw probe in 3D view
  2698. line(ccf_3d_axes,probe_line(:,1),probe_line(:,3),probe_line(:,2), ...
  2699. 'linewidth',2,'color',animal_col(curr_animal,:))
  2700. % Draw probes on coronal + saggital
  2701. line(ccf_axes(1),probe_line(:,3),probe_line(:,2),'linewidth',2,'color',animal_col(curr_animal,:));
  2702. line(ccf_axes(3),probe_line(:,2),probe_line(:,1),'linewidth',2,'color',animal_col(curr_animal,:));
  2703. % Draw probe mean on horizontal
  2704. plot(ccf_axes(2), probe_coords_mean(:,3),probe_coords_mean(:,1), ...
  2705. '.','MarkerSize',10,'color',animal_col(curr_animal,:));
  2706. drawnow
  2707. end
  2708. % Plot scalebar
  2709. scalebar_length = 1000/10; % um/voxel size
  2710. line(ccf_axes(3),[0,0],[0,scalebar_length],'color','m','linewidth',3);
  2711. %% Naive ephys - naive stim response
  2712. % Load data
  2713. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  2714. data_fn = 'trial_activity_passive_ephys_naive';
  2715. AP_load_trials_operant;
  2716. % Get animal and day index for each trial
  2717. trial_animal = cell2mat(arrayfun(@(x) ...
  2718. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  2719. [1:length(wheel_all)]','uni',false));
  2720. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  2721. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  2722. wheel_all,'uni',false));
  2723. trial_recording = cell2mat(cellfun(@(tr,day) ...
  2724. day*ones(size(tr,1),1), ...
  2725. cat(1,wheel_all{:}),num2cell(1:length(cat(1,wheel_all{:})))', ...
  2726. 'uni',false));
  2727. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  2728. % Get trials with movement during stim to exclude
  2729. quiescent_trials = ~any(abs(wheel_allcat(:,t >= 0 & t <= 0.5)) > 0,2);
  2730. % Get average response timecourses
  2731. stim_unique = unique(trial_stim_allcat);
  2732. [~,trial_stim_id] = ismember(trial_stim_allcat,stim_unique);
  2733. use_trials = quiescent_trials;
  2734. % (loop through cell types)
  2735. for curr_celltype = 1:size(mua_area_allcat,4)
  2736. [recording_idx,t_idx,area_idx] = ...
  2737. ndgrid(trial_recording(use_trials),1:length(t),1:length(mua_areas));
  2738. [stim_idx,~,~,] = ...
  2739. ndgrid(trial_stim_id(use_trials),1:length(t),1:length(mua_areas));
  2740. mua_recording_avg = accumarray([recording_idx(:),t_idx(:),stim_idx(:),area_idx(:)], ...
  2741. reshape(mua_area_allcat(use_trials,:,:,curr_celltype),[],1), ...
  2742. [length(trials_recording),length(t),length(stim_unique),length(mua_areas)], ...
  2743. @nanmean,NaN);
  2744. % Get DV position of each area in CCF for sorting
  2745. allen_atlas_path = fileparts(which('template_volume_10um.npy'));
  2746. av = readNPY([allen_atlas_path filesep 'annotation_volume_10um_by_index.npy']);
  2747. st = loadStructureTree([allen_atlas_path filesep 'structure_tree_safe_2017.csv']);
  2748. mua_areas_dvmin = nan(size(mua_areas));
  2749. for curr_area = mua_areas'
  2750. curr_structure_idx = find(strcmp(st.safe_name,curr_area));
  2751. curr_structure_id = st.structure_id_path{curr_structure_idx};
  2752. curr_ccf_idx = find(cellfun(@(x) contains(x,curr_structure_id), ...
  2753. st.structure_id_path));
  2754. slice_spacing = 5;
  2755. curr_ccf_volume = ...
  2756. ismember(av(1:slice_spacing:end, ...
  2757. 1:slice_spacing:end,1:slice_spacing:end),curr_ccf_idx);
  2758. curr_ccf_coronal_max = permute(max(curr_ccf_volume,[],1),[2,3,1]);
  2759. curr_min_dv = find(any(curr_ccf_coronal_max,2),1);
  2760. mua_areas_dvmin(strcmp(curr_area,mua_areas)) = curr_min_dv;
  2761. end
  2762. % (get areas to plot: anything present in all recordings)
  2763. [~,area_idx] = cellfun(@(x) ismember(x,mua_areas),mua_areas_cat,'uni',false);
  2764. area_recording_n = accumarray(cell2mat(area_idx),1);
  2765. plot_areas = find(area_recording_n == length(trials_recording));
  2766. [~,plot_area_sort_idx] = sort(mua_areas_dvmin(plot_areas));
  2767. % Plot stim overlaid
  2768. figure;
  2769. stim_color = [0,0,0.8;0.5,0.5,0.5;0.8,0,0];
  2770. h = tiledlayout(length(plot_areas),1);
  2771. for curr_area = plot_areas(plot_area_sort_idx)'
  2772. nexttile;
  2773. AP_errorfill(t', ...
  2774. squeeze(nanmean(mua_recording_avg(:,:,:,curr_area),1)), ...
  2775. squeeze(AP_sem(mua_recording_avg(:,:,:,curr_area),1)),stim_color);
  2776. yline(0);
  2777. ylabel(mua_areas(curr_area));
  2778. end
  2779. linkaxes(allchild(h),'xy');
  2780. % (shade stim area and put in back)
  2781. arrayfun(@(x) patch(x,[0,0.5,0.5,0], ...
  2782. reshape(repmat(ylim(x),2,1),[],1),[1,1,0.8], ...
  2783. 'linestyle','none'),allchild(h));
  2784. arrayfun(@(x) set(x,'children',circshift(get(x,'children'),-1)),allchild(h));
  2785. xlim([-0.2,0.7]);
  2786. x_scale = 0.2;
  2787. y_scale = 0.5;
  2788. AP_scalebar(x_scale,y_scale);
  2789. title(h,sprintf('Cell type %d',curr_celltype));
  2790. end
  2791. %% --> (USE THIS ALT) Recording locations in naive and trained
  2792. % Set animal groups (naive, trained)
  2793. animal_groups = {{'AP116','AP117','AP118','AP119'}, ...
  2794. {'AP100','AP101','AP104','AP105','AP106'}};
  2795. animal_group_col = [0.5,0.5,0.5;0,0,0];
  2796. % Load CCF annotated volume
  2797. allen_atlas_path = fileparts(which('template_volume_10um.npy'));
  2798. av = readNPY([allen_atlas_path filesep 'annotation_volume_10um_by_index.npy']);
  2799. st = loadStructureTree([allen_atlas_path filesep 'structure_tree_safe_2017.csv']);
  2800. % Set up 3D axes
  2801. figure;
  2802. ccf_3d_axes = axes;
  2803. [~, brain_outline] = plotBrainGrid([],ccf_3d_axes);
  2804. set(ccf_3d_axes,'ZDir','reverse');
  2805. hold(ccf_3d_axes,'on');
  2806. axis vis3d equal off manual
  2807. view([-30,25]);
  2808. axis tight;
  2809. h = rotate3d(ccf_3d_axes);
  2810. h.Enable = 'on';
  2811. % Set up 2D axes
  2812. figure;
  2813. bregma_ccf = [540,44,570];
  2814. ccf_size = size(av);
  2815. ccf_axes = gobjects(3,1);
  2816. ccf_axes(1) = subplot(1,3,1,'YDir','reverse');
  2817. hold on; axis image off;
  2818. ccf_axes(2) = subplot(1,3,2,'YDir','reverse');
  2819. hold on; axis image off;
  2820. ccf_axes(3) = subplot(1,3,3,'YDir','reverse');
  2821. hold on; axis image off;
  2822. for curr_view = 1:3
  2823. curr_outline = bwboundaries(squeeze((max(av,[],curr_view)) > 1));
  2824. cellfun(@(x) plot(ccf_axes(curr_view),x(:,2),x(:,1),'k','linewidth',2),curr_outline)
  2825. curr_bregma = fliplr(bregma_ccf(setdiff(1:3,curr_view)));
  2826. plot(ccf_axes(curr_view),curr_bregma(1),curr_bregma(2),'rx');
  2827. curr_size = fliplr(ccf_size(setdiff(1:3,curr_view)));
  2828. xlim(ccf_axes(curr_view),[0,curr_size(1)]);
  2829. ylim(ccf_axes(curr_view),[0,curr_size(2)]);
  2830. end
  2831. linkaxes(ccf_axes);
  2832. % Plot specific areas
  2833. plot_structure_names = {'Secondary motor area', ...
  2834. 'Anterior cingulate area','Prelimbic area','Infralimbic area'};
  2835. plot_structure_colors = lines(length(plot_structure_names));
  2836. for plot_structure_name = plot_structure_names
  2837. plot_structure = find(strcmp(st.safe_name,plot_structure_name));
  2838. % Get all areas within and below the selected hierarchy level
  2839. plot_structure_id = st.structure_id_path{plot_structure};
  2840. plot_ccf_idx = find(cellfun(@(x) contains(x,plot_structure_id), ...
  2841. st.structure_id_path));
  2842. % plot the structure
  2843. slice_spacing = 5;
  2844. plot_structure_color = plot_structure_colors( ...
  2845. strcmp(plot_structure_name,plot_structure_names),:);
  2846. % Get structure volume
  2847. plot_ccf_volume = ismember(av(1:slice_spacing:end,1:slice_spacing:end,1:slice_spacing:end),plot_ccf_idx);
  2848. for curr_view = 1:3
  2849. curr_outline = bwboundaries(squeeze((max(plot_ccf_volume,[],curr_view))));
  2850. cellfun(@(x) plot(ccf_axes(curr_view),x(:,2)*slice_spacing, ...
  2851. x(:,1)*slice_spacing,'color',plot_structure_color,'linewidth',2),curr_outline)
  2852. end
  2853. end
  2854. for animal_group = 1:length(animal_groups)
  2855. animals = animal_groups{animal_group};
  2856. animal_col = repmat(animal_group_col(animal_group,:),length(animals),1);
  2857. % Plot probe locations
  2858. probe_coords_mean_all = nan(length(animals),3);
  2859. for curr_animal = 1:length(animals)
  2860. animal = animals{curr_animal};
  2861. % Load animal probe histology
  2862. [probe_ccf_fn,probe_ccf_fn_exists] = AP_cortexlab_filename(animal,[],[],'probe_ccf');
  2863. load(probe_ccf_fn);
  2864. % Get line of best fit through mean of marked points
  2865. probe_coords_mean = mean(probe_ccf.points,1);
  2866. % (store mean for plotting later)
  2867. probe_coords_mean_all(curr_animal,:) = probe_coords_mean;
  2868. xyz = bsxfun(@minus,probe_ccf.points,probe_coords_mean);
  2869. [~,~,V] = svd(xyz,0);
  2870. histology_probe_direction = V(:,1);
  2871. % (make sure the direction goes down in DV - flip if it's going up)
  2872. if histology_probe_direction(2) < 0
  2873. histology_probe_direction = -histology_probe_direction;
  2874. end
  2875. % Evaluate line of best fit (length of probe to deepest point)
  2876. [~,deepest_probe_idx] = max(probe_ccf.points(:,2));
  2877. probe_deepest_point = probe_ccf.points(deepest_probe_idx,:);
  2878. probe_deepest_point_com_dist = pdist2(probe_coords_mean,probe_deepest_point);
  2879. probe_length_ccf = 3840/10; % mm / ccf voxel size
  2880. probe_line_eval = probe_deepest_point_com_dist - [probe_length_ccf,0];
  2881. probe_line = (probe_line_eval'.*histology_probe_direction') + probe_coords_mean;
  2882. % Draw probe in 3D view
  2883. line(ccf_3d_axes,probe_line(:,1),probe_line(:,3),probe_line(:,2), ...
  2884. 'linewidth',2,'color',animal_col(curr_animal,:))
  2885. % Draw probes on coronal + saggital
  2886. line(ccf_axes(1),probe_line(:,3),probe_line(:,2),'linewidth',2,'color',animal_col(curr_animal,:));
  2887. line(ccf_axes(3),probe_line(:,2),probe_line(:,1),'linewidth',2,'color',animal_col(curr_animal,:));
  2888. % Draw probe mean on horizontal
  2889. plot(ccf_axes(2), probe_coords_mean(:,3),probe_coords_mean(:,1), ...
  2890. '.','MarkerSize',10,'color',animal_col(curr_animal,:));
  2891. drawnow
  2892. end
  2893. end
  2894. % Plot scalebar
  2895. scalebar_length = 1000/10; % um/voxel size
  2896. line(ccf_axes(3),[0,0],[0,scalebar_length],'color','m','linewidth',3);
  2897. %% --> (USE THIS ALT) Naive and trained passive stim ephys
  2898. mua_stim_stage = cell(2,1);
  2899. for curr_stage = 1:2 % (naive, trained)
  2900. % Load data
  2901. trial_data_path = 'C:\Users\Andrew\OneDrive for Business\Documents\CarandiniHarrisLab\analysis\operant_learning\data';
  2902. switch curr_stage
  2903. case 1
  2904. data_fn = 'trial_activity_passive_ephys_naive';
  2905. case 2
  2906. data_fn = 'trial_activity_passive_ephys';
  2907. end
  2908. AP_load_trials_operant;
  2909. % Get animal and day index for each trial
  2910. trial_animal = cell2mat(arrayfun(@(x) ...
  2911. x*ones(size(vertcat(wheel_all{x}{:}),1),1), ...
  2912. [1:length(wheel_all)]','uni',false));
  2913. trial_day = cell2mat(cellfun(@(x) cell2mat(cellfun(@(curr_day,x) ...
  2914. curr_day*ones(size(x,1),1),num2cell(1:length(x))',x,'uni',false)), ...
  2915. wheel_all,'uni',false));
  2916. trial_recording = cell2mat(cellfun(@(tr,day) ...
  2917. day*ones(size(tr,1),1), ...
  2918. cat(1,wheel_all{:}),num2cell(1:length(cat(1,wheel_all{:})))', ...
  2919. 'uni',false));
  2920. trials_recording = cellfun(@(x) size(x,1),vertcat(wheel_all{:}));
  2921. % Get trials with movement during stim to exclude
  2922. quiescent_trials = ~any(abs(wheel_allcat(:,t >= 0 & t <= 0.5)) > 0,2);
  2923. % Get average response timecourses
  2924. stim_unique = unique(trial_stim_allcat);
  2925. [~,trial_stim_id] = ismember(trial_stim_allcat,stim_unique);
  2926. use_trials = quiescent_trials;
  2927. [recording_idx,t_idx,area_idx] = ...
  2928. ndgrid(trial_recording(use_trials),1:length(t),1:length(mua_areas));
  2929. [stim_idx,~,~,] = ...
  2930. ndgrid(trial_stim_id(use_trials),1:length(t),1:length(mua_areas));
  2931. mua_recording_avg = accumarray([recording_idx(:),t_idx(:),stim_idx(:),area_idx(:)], ...
  2932. reshape(mua_area_allcat(use_trials,:,:),[],1), ...
  2933. [length(trials_recording),length(t),length(stim_unique),length(mua_areas)], ...
  2934. @nanmean,NaN);
  2935. % Set areas and order to plot
  2936. % (used to do this programatically to be agnostic, but not necessary
  2937. % now so just hard-coding)
  2938. plot_areas = {'Secondary motor area', ...
  2939. 'Anterior cingulate area dorsal part', ...
  2940. 'Prelimbic area','Infralimbic area'};
  2941. [~,plot_areas_idx] = ismember(plot_areas,mua_areas);
  2942. % Store activity
  2943. mua_stim_stage{curr_stage} = mua_recording_avg(:,:,:,plot_areas_idx);
  2944. % Clear for next round
  2945. clearvars -except t plot_areas mua_stim_stage
  2946. end
  2947. % Plot stim overlaid
  2948. plot_stim = 3;
  2949. stage_cols = [0.5,0.5,0.5;0,0,0];
  2950. figure;
  2951. for curr_stage = 1:2
  2952. for curr_area = 1:length(plot_areas)
  2953. subplot(length(plot_areas),1,curr_area); hold on
  2954. AP_errorfill(t', ...
  2955. squeeze(nanmean(mua_stim_stage{curr_stage}(:,:,plot_stim,curr_area),1)), ...
  2956. squeeze(AP_sem(mua_stim_stage{curr_stage}(:,:,plot_stim,curr_area),1)), ...
  2957. stage_cols(curr_stage,:));
  2958. yline(0);xline(0);
  2959. ylabel(plot_areas{curr_area});
  2960. end
  2961. end
  2962. linkaxes(get(gcf,'Children'),'xy')

AP_operant_learning_figures_v4.m at commit f3bc71d, no license · at the source

Overview

Authors: A Lebedeva1, Y Wang2, L Funnell2, B Terry2, Y J Oh2, K Miller1,3,4, K D Harris2
ORCID iDs: K D Harris
  1. UCL Sainsbury Wellcome Centre, London, UK
  2. UCL Institute of Neurology, London, UK
  3. UCL Institute of Ophthalmology, London, UK
  4. Google DeepMind, London, UK
Institutions: Sainsbury Wellcome Centre (United Kingdom); University College London (United Kingdom); UCL Queen Square Institute of Neurology (United Kingdom); Google DeepMind (United Kingdom) (United Kingdom)
Journal: Nature communications, volume 17, issue 1, article 5715
Dates: received 18 November 2024; accepted 25 March 2026; published online 25 April 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-71664-w · PMID 42034646 · PMCID PMC13324276 · OpenAlex W4396638041
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: mouse (organism), systems (subfield)
Methods: Connectivity, Statistics, Machine learning, Single-unit activity, calcium imaging
Keywords: Neural circuits, Neural encoding
MeSH: Behavior, Animal*, Dorsolateral Prefrontal Cortex*, Prefrontal Cortex*, Animals, Choice Behavior, Cues, Learning, Male, Mice, Mice, Inbred C57BL, Motor Cortex, Neurons, Optogenetics, Reaction Time, Reward (* major topic)
Topic: Neurotransmitter Receptor Influence on Behavior (Cellular and Molecular Neuroscience, Neuroscience), according to OpenAlex
Funding: Wellcome Trust (223144, 694401, 205093); European Research Council (694401)
Citations: cited by 3 papers (Europe PMC); 82 references in the paper
Research resources: Ai32 × PV-Cre (Ai32 RRID:IMSR_JAX

Abstract

Perseveration – repeating one action when others would generate larger rewards – is a common behavior, but neither its purpose nor neuronal mechanisms are understood. Here we demonstrate a neural correlate and causal role of dorsal prefrontal cortex, specifically anterior secondary motor cortex (MOs) in perseveration in mice performing a dynamic reward learning task. An auditory go cue signaled mice to turn a wheel either left or right, with the reward probability of each action switching in blocks. Mice perseverated, gaining suboptimal reward, but were faster when making repeated choices. Neuropixels recordings found neurons whose activity correlated with perseveration and predicted rapid reaction times, almost exclusively in anterior MOs. Optogenetically inhibiting this region during the choice period reduced perseveration and slowed reactions. In contrast, inactivating medial prefrontal cortex at choice time had no effect, but inactivating it after reward delivery impaired learning. In this task, therefore, anterior MOs reflects a perseverative decision variable, and is necessary for mediating the effect of this decision variable on choice and reaction time.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 7 matches between paragraphs and lines of code.

petersaj/ap_scripts_cortexlab

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: f3bc71dc92236140a5f67b28d5b9f1098008a6a5, 2 July 2026
Languages: MATLAB (251), Python (1)
Size: 308 files, 252 scripts
Software Heritage: not archived
Found in: the text, “Secondary surgery for electrophysiological exper”
Holds: README, tests
Not found: license file, CITATION.cff, environment file, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
253 files

neurvanna/perseveration

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: cc7060cc238f062675880ee5354a2a39fe71dd8c, 25 June 2026
Languages: MATLAB (48), Python (1)
Size: 103 files, 49 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, tests
Not found: license file, CITATION.cff, environment file, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
50 files

Code availability

The code necessary to reproduce the figures may be found at https://github.com/neurvanna/perseveration/tree/main.

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 301 scripts, each with its path and the digest of its content;
  • 7 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Data availability

Source data are provided with this paper: 10.6084/m9.figshare.31231741.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 7 authors, 2 keywords, 15 MeSH terms, 2 funders, 75 references, 1 RRID.

Cite

This paper

Lebedeva, A., Wang, Y., Funnell, L., Terry, B., Oh, Y. J., Miller, K., & Harris, K. D. (2026). Dorsal prefrontal cortex drives perseverative behavior in mice. Nature communications, 17(1), 5715. https://doi.org/10.1038/s41467-026-71664-w

BibTeX

@article{lebedeva2026dorsal,
author = {Lebedeva, A and Wang, Y and Funnell, L and Terry, B and Oh, Y J and Miller, K and Harris, K D},
title = {{Dorsal prefrontal cortex drives perseverative behavior in mice}},
journal = {Nature communications},
year = {2026},
month = apr,
volume = {17},
number = {1},
pages = {5715},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-71664-w},
url = {https://doi.org/10.1038/s41467-026-71664-w},
pmid = {42034646},
pmcid = {PMC13324276}
}

RIS

TY - JOUR
AU - Lebedeva, A
AU - Wang, Y
AU - Funnell, L
AU - Terry, B
AU - Oh, Y J
AU - Miller, K
AU - Harris, K D
TI - Dorsal prefrontal cortex drives perseverative behavior in mice
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/04/25
VL - 17
IS - 1
SP - 5715
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-71664-w
UR - https://doi.org/10.1038/s41467-026-71664-w
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-71664-w",
"type": "article-journal",
"title": "Dorsal prefrontal cortex drives perseverative behavior in mice",
"container-title": "Nature communications",
"author": [
{
"family": "Lebedeva",
"given": "A"
},
{
"family": "Wang",
"given": "Y"
},
{
"family": "Funnell",
"given": "L"
},
{
"family": "Terry",
"given": "B"
},
{
"family": "Oh",
"given": "Y J"
},
{
"family": "Miller",
"given": "K"
},
{
"family": "Harris",
"given": "K D"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "5715",
"DOI": "10.1038/s41467-026-71664-w",
"PMID": "42034646",
"PMCID": "PMC13324276",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-71664-w",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
25
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41592-026-03076-z [code]
Neuropixels Opto: combining high-resolution electrophysiology and optogenetics.
Journal: Nature methods
In common: Kilosort, NumPy, systems, mouse, 8 references
[2] doi:10.1038/s41593-026-02232-0 [code]
Entorhinal cortex represents task-relevant remote locations independently of CA1.
Journal: Nature neuroscience
In common: Kilosort, Optimization Toolbox, scikit-image, 4 other tools, systems, mouse, 3 references
[3] doi:10.1016/j.patter.2026.101590 [code]
Density-based longitudinal neuron tracking in high-density electrophysiological recordings.
Journal: Patterns (New York, N.Y.)
In common: Kilosort, Optimization Toolbox, Parallel Computing Toolbox, 3 other tools, 3 references
[4] doi:10.1038/s41593-026-02255-7 [code]
Neural circuits encode prior knowledge of temporal statistics.
Journal: Nature neuroscience
In common: Open Ephys analysis tools, Optimization Toolbox, Parallel Computing Toolbox, 4 other tools, systems, mouse, 1 reference
[5] doi:10.1016/j.celrep.2026.117646 [code]
Medial entorhinal-hippocampal desynchronization parallels the emergence of memory impairment in a mouse model of Alzheimer's disease pathology.
Journal: Cell reports
In common: Optimization Toolbox, Parallel Computing Toolbox, scikit-image, 4 other tools, systems, mouse, 2 references
[6] doi:10.1038/s41467-026-73622-y [code]
Contextual gating of whisker-evoked responses by frontal cortex supports flexible decision making.
Journal: Nature communications
In common: Parallel Computing Toolbox, Image Processing Toolbox, Signal Processing Toolbox, 1 other tool, mouse, 5 references
[7] doi:10.1038/s41467-026-75347-4 [code]
Sleep reveals dynamics integrating and segregating movement and stimulus representations in V1.
Journal: Nature communications
In common: Optimization Toolbox, Parallel Computing Toolbox, scikit-image, 4 other tools, systems, mouse, 1 reference
[8] doi:10.64898/2026.03.06.710130 [code]
A flexible quality metric for electrophysiological recordings across brain regions and species
Journal: bioRxiv (preprint)
In common: Optimization Toolbox, Parallel Computing Toolbox, Signal Processing Toolbox, 2 other tools, 4 references
[9] doi:10.7554/elife.109717 [code]
Retrosplenial cortex enables context-dependent goal-directed sensorimotor transformation.
Journal: eLife
In common: Kilosort, scikit-image, Statistics and Machine Learning Toolbox, 1 other tool, systems, mouse, 3 references
[10] doi:10.1038/s41593-026-02258-4 [code]
Laminar organization of cellular microcircuits modulating human interictal epileptiform discharges.
Journal: Nature neuroscience
In common: Kilosort, Parallel Computing Toolbox, Image Processing Toolbox, 3 other tools, systems, 1 reference

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.