diff --git a/Emilio/AKK/compareMaxWithThresh.m b/Emilio/AKK/compareMaxWithThresh.m index 07971e8..611f7df 100644 --- a/Emilio/AKK/compareMaxWithThresh.m +++ b/Emilio/AKK/compareMaxWithThresh.m @@ -1,10 +1,9 @@ -function [moveFlag] = compareMaxWithThresh(mx, thCell) +function [moveFlag, thCell] = compareMaxWithThresh(mx, cmx) %COMPAREMAXWITHTHRESH compares each column of the maximum value per trial %per signal against a given threshold set. % Detailed explanation goes here, later %% -if isrow(mx) - mx = mx'; -end -moveFlag = mx > thCell{1}; +mdl = fit_poly( [1, 64], [double(cmx)/64, double(cmx)], 1 ); +thCell = { ( ( 1:64 )'.^[1,0] ) * mdl }; +moveFlag = mx(:) > thCell{1}(:)'; end diff --git a/Emilio/AKK/getMaxAbsPerTrial.m b/Emilio/AKK/getMaxAbsPerTrial.m index 10e4d56..08e1883 100644 --- a/Emilio/AKK/getMaxAbsPerTrial.m +++ b/Emilio/AKK/getMaxAbsPerTrial.m @@ -1,9 +1,11 @@ -function [mavpt] = getMaxAbsPerTrial(inStack, responseWindow, timeAxis) +function [mavpt, mxT, bl_lvl] = getMaxAbsPerTrial(inStack, ... + responseWindow, spontWindow, timeAxis) %GETMAXABSPERTRIAL gets as the name suggests, the maximum absolute %amplitude per trial in the given input stack % Detailed explanation goes here, later. %% +my_xor = @(x) xor( x(:,1), x(:,2) ); % Size of the stack: Number of signals (e.g. nose, left whisker), number of % time samples, and number of triggers (trials) [Nts, Ntg] = size(inStack); @@ -18,11 +20,14 @@ fprintf(1, "Please, verify they are the same size!\n"); return end -% Response period for all trials -responseFlags = timeAxis >= responseWindow; -responseFlags = xor(responseFlags(:,1), responseFlags(:,2)); - -mavpt = max(abs(inStack(responseFlags, :)-median(inStack,1))); -mavpt = mavpt(:); -end +% Response and spontaneous periods for all trials +responseFlags = my_xor( timeAxis(:) >= responseWindow ); +spontaneousFlags = my_xor( timeAxis(:) >= spontWindow ); +% mavpt = max(abs(inStack(responseFlags, :)-median(inStack,1))); +bl_lvl = median( inStack(spontaneousFlags,:), 1 ); +[mavpt, ps] = max( abs( inStack(responseFlags,:) - bl_lvl ) ); +% mavpt = arrayfun(@(mp, tr) ... +% inStack(find(responseFlags,1,'first')+mp-1, tr), ps(:), (1:Ntg)'); +mxT = timeAxis(ps+find(responseFlags,1,"first")-1); +end \ No newline at end of file diff --git a/Emilio/AKK/plotThetaProgress.m b/Emilio/AKK/plotThetaProgress.m index 8ed5997..68c3bb3 100644 --- a/Emilio/AKK/plotThetaProgress.m +++ b/Emilio/AKK/plotThetaProgress.m @@ -1,10 +1,25 @@ -function [probFigs] = plotThetaProgress(logMat, thSet, sNames) +function [probFigs] = plotThetaProgress(logMat, thSet, sNames, varargin) %UNTITLED3 Summary of this function goes here % Detailed explanation goes here %% +p = inputParser; + +addRequired(p, 'logMat', @(x) islogical(x{:})) +addRequired(p, 'thSet', @(x) isvector(x{:})) +addRequired(p, 'sNames', @(x) ~isempty(x)) +addParameter(p, 'showPlots', true, @(x) islogical(x) & numel(x) == 1) + +parse(p, logMat, thSet, sNames, varargin{:}) + +logMat = p.Results.logMat; +thSet = p.Results.thSet; +sNames = p.Results.sNames; +showPlots = p.Results.showPlots; + probFigs = gobjects(size(logMat,2),1); for cs = 1:size(logMat,2) - probFigs(cs) = figure; plot(thSet{cs}, sum(logMat{cs})/size(logMat{cs},1),... + probFigs(cs) = figure('Visible', showPlots); + plot(thSet{cs}, sum(logMat{cs})/size(logMat{cs},1),... "DisplayName", sNames(cs)) lgnd = legend("show"); set(lgnd, "Box", "off", "Location", "best"); ylabel("Trial proportion"); set(gca, "Box", "off", "Color", "none"); diff --git a/Emilio/FigureReconsA.m b/Emilio/FigureReconsA.m new file mode 100644 index 0000000..b022ecb --- /dev/null +++ b/Emilio/FigureReconsA.m @@ -0,0 +1,68 @@ +data_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch18_ephys\MC\GADi43\240227_C+F_2200"; +load( fullfile( data_path, "Regression CW-800.00-800.00ms " + ... + "DW-100.00-100.00 BZ5.00.mat"), 'DX', 'mdlAll_ind', 'params') +load( fullfile( data_path, "ephys_E1", ... + "GADi43_C+F_2200 RW20.00-200.00 SW-300.00--120.00 " + ... + "VW-300.00-400.00 ms PuffAll (unfiltered) RelSpkTms.mat"), ... + 'relativeSpkTmsStruct' ) +fnOpts = {'UniformOutput', false}; +vec2trials = @(x) reshape( x, params.Nb, params.Nr, params.Ns ); +bpn_abb = {'SWM', 'SWF', 'NWM', 'NWF', 'WA', 'S', 'N', 'RS'}; +m = 1e-3; k = 1e3; +nox = @(x) set( get( x, 'XAxis' ), 'Visible', 'off' ); +lnOpts = {'Marker', '|', 'MarkerSize', 12, 'LineStyle', 'none', 'Color', 'k'}; +%% Auxiliary variables for decisions and plotting +rel_win = params.relative_window; +bin_size = params.bin_size; + +mdl_mu = squeeze( mean( mdlAll_ind, 2 ) ); +y_trials = vec2trials( DX{1} ); +y_pred = DX{2} * mdl_mu; +y_ptrials = vec2trials( y_pred ); +trial_tx = (rel_win(1) + bin_size/2):bin_size:(rel_win(2) - bin_size/2); + +SSEt = squeeze( sum( ( y_trials - y_ptrials ).^2, 1 ) ); +SSTt = squeeze( sum( ( y_trials - mean( y_trials, 1 ) ).^2, 1 ) ); +r_sq_trials = 1 - (SSEt./SSTt); + +% Decide based on which trial has the highest R²: trial 6, NWM (3) +[~, ord] = sort( r_sq_trials, "descend" ); +rst = relativeSpkTmsStruct(1).SpikeTimes; +%% +f = figure( "Color", "w" ); t = createtiles( f, 4, 1 ); +ax = gobjects( 3, 1 ); + +ax(1) = nexttile( t ); +line( ax(1), k*trial_tx, y_trials(:,6,3), 'LineWidth', 2, 'Color', 0.15*ones(1,3) ) +cleanAxis(ax(1)); nox(ax(1)); +yticklabels( ax(1), yticks(ax(1))-90 ) +ylabel( ax(1), 'Angle [°]'); ytickangle( ax(1), 90 ) + +ax(2) = nexttile( t, [2,1] ); hold( ax(2), "on" ) +Nu = size( rst, 1 ); +Npu = 15; +if Npu > Nu + Npu = Nu; +end +ct = 1; +for cu = round(linspace(1, Nu, Npu)) + if cu > Nu + break + end + rst_aux = rst{cu,6}; + line( ax(2), k*rst_aux, ct+zeros( size( rst_aux, 2 ), 1 ), lnOpts{:} ) + ct = ct + 1; +end +nox(ax(2)); cleanAxis(ax(2)); +ylabel(ax(2), 'Units'); ytickangle( ax(2), 90 ) + +ax(3) = nexttile( t ); +line( ax(3), k*trial_tx, y_ptrials(:,6,3), 'LineWidth', 2, 'Color', [0,0.6,0] ) +cleanAxis(ax(3)); +yticklabels( ax(3), yticks(ax(3))-90 ) +ylabel( ax(3), 'Angle [°]'); ytickangle( ax(3), 90 ) +set( ax, 'TickDir', 'out' ) +linkaxes( ax, 'x'); xlim( ax(3), [-200, 400] ) +xlabel( ax(3), 'Time [ms]' ) + +xline( ax(3), -200:20:400, 'Color', 0.5*ones(1,3) ) diff --git a/Emilio/Habituation_prep_4_R.m b/Emilio/Habituation_prep_4_R.m new file mode 100644 index 0000000..a12f42a --- /dev/null +++ b/Emilio/Habituation_prep_4_R.m @@ -0,0 +1,16 @@ +miceArray = []; +for cm = 1:numel(resTable) + [Np, Ns] = size(resTable{cm}.BehaviourIndices); + sess_id = repmat(1:Ns, Np, 1); sess_id = sess_id(:); + mouse_id = cm + zeros(Np*Ns, 1); + puff_strength = ... + cellfun(@(f) textscan(f, "%fbars"), ... + resTable{cm}.Properties.RowNames); + if any(cellfun(@isempty, puff_strength)) + puff_strength{cellfun(@isempty, puff_strength)} = -1; + end + puff_strength = repmat(cat(1, puff_strength{:}), Ns, 1); + bi_values = resTable{cm}.BehaviourIndices(:); + miceArray = [miceArray; + mouse_id, sess_id, puff_strength, bi_values]; +end \ No newline at end of file diff --git a/Emilio/MC_summary.m b/Emilio/MC_summary.m new file mode 100644 index 0000000..eba8049 --- /dev/null +++ b/Emilio/MC_summary.m @@ -0,0 +1,48 @@ +getMI = @(a, c) (c - a) ./ (a + c); +getRC = @(a, c) (c - a) ./ c; +normDist = makedist("Normal", "mu", 0, "sigma", 0.075); + +singFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "single", ... + m.Sessions), mice, fnOpts{:}); +behTable = arrayfun(@(m, f) {m.Sessions(f{:}).DataTable}, mice, singFlag, ... + fnOpts{:}); + +behMI = cellfun(@(m) cellfun(@(t) arrayfun(@(c) ... + getMI(t{1,"BehaviourIndices"}, t{c,"BehaviourIndices"}), ... + 2:size(t,1)), ... + m, fnOpts{:}), ... + behTable, fnOpts{:}); + +behMI = cellfun(@(m) cat(1, m{:}), behMI, fnOpts{:}); + +behRC = cellfun(@(m) cellfun(@(t) arrayfun(@(c) ... + getRC(t{1,"BehaviourIndices"}, t{c,"BehaviourIndices"}), ... + 2:size(t,1)), ... + m, fnOpts{:}), ... + behTable, fnOpts{:}); + +behRC = cellfun(@(m) cat(1, m{:}), behRC, fnOpts{:}); +%% +figure; boxplot([cat(1, behMI{1:2}); padarray(behMI{3}, [0,2], nan, "both")], ... + "Notch", "on"); hold on +title('Modulation index on behaviour index for MC\rightarrowSC excitation') +for cm = 1:3 + auxBMI = padarray(behMI{cm}, [0,(6 - size(behMI{cm},2))/2], nan, "both"); + xpos = reshape(repmat(1:size(auxBMI,2), size(auxBMI, 1 ) , 1 ) + ... + random(normDist, size( auxBMI ) ), [], 1); + scatter(xpos, auxBMI(:), "filled") +end +yline(0, 'k:') +xticklabels(condNames{1}{1}(2:end)) +ylabel('MI(BI)'); xlabel('Conditions') +set(gca, 'Box', 'off', 'Color', 'none') +ylim([-1,1]) +%% +figure; boxplot(cat(1, behMI{4:6}), "Notch", "on"); hold on +title('Modulation index on behaviour index for MC\rightarrowSC inhibition') +for cm = 4:6 + scatter(ones(size(behMI{cm}))+random(normDist, size(behMI{cm})), ... + behMI{cm}, "filled") +end +xticklabels(condNames{4}{1}(2)) +yline(0, 'k:'); set(gca, 'Box', 'off', 'Color', 'none') diff --git a/Emilio/MUA_LFP_estimation.m b/Emilio/MUA_LFP_estimation.m new file mode 100644 index 0000000..04772bc --- /dev/null +++ b/Emilio/MUA_LFP_estimation.m @@ -0,0 +1,139 @@ +base_path = "Z:\PainData\Corrected_Channel_Map\"; +exp_paths = base_path + ["L6\Cortex\20.8.21\KS2", ... + "L6\Cortex\26.8.21", ... + "Dual\L6_VPL\S1\Nblocks0\th10_2\AUC0pt7\Lambda10", ... + "L6\Cortex\m8", ... + "L6\Cortex\27.8.21"]; +anaesthesia_states = cell(size(exp_paths)); +fullpath = @(f) fullfile(f.folder,f.name); +load_data = @(f) load(fullpath(f)); +%% +for ce = 1:numel(exp_paths) + data_dir = exp_paths(ce); + spike_file = dir(fullfile(data_dir,"*All_all_channels_clean.mat")); + if numel(spike_file)~=1 + spike_file = dir(fullfile(data_dir, "*all_channels_clean.mat")); + end + load(fullpath(spike_file)); + + cond_file = dir(fullfile(data_dir,'*analysis.mat')); + load(fullpath(cond_file)) + Ns = numel(Triggers.Laser); + exp_duration = Ns/fs; + unit_flag = sum([sortedData{:,3}] == [1;2]) > 0; + spike_times = sortedData(unit_flag,2); + all_spikes = cat(1, spike_times{:}); + + bin_files = dir(fullfile(data_dir,'*.bin')); + %{ + if numel(bin_files)>=1 + bin_files = bin_files([bin_files.bytes]==max([bin_files.bytes])); + exp_duration = (bin_files.bytes/(64*2))/fs; + else + exp_duration = max(all_spikes)*1.001; + end + %} + fr_per_unit = cellfun(@(x) numel(x)/exp_duration, spike_times); + %% + th = 0; + bin_size = 0.1; + bins = 0:bin_size:exp_duration; + centres = mean([bins(1:end-1);bins(2:end)]); + + muah = histcounts(all_spikes, bins); + [b1,a1] = butter(3,[0.8,1.8]*2*bin_size,'bandpass'); + [blow, alow] = butter(2,[0.0005, 0.01]*2*bin_size,'bandpass'); + bouts = filtfilt(b1, a1, muah); + pad_size = ceil(1000/bin_size); % 1000 seconds + extra_bout = padarray(bouts(:), pad_size, "symmetric", "pre"); + brain_state = filtfilt(blow, alow, abs(extra_bout)); + brain_state(1:pad_size) = []; + anaesthesia_states{ce} = brain_state; + %% + + sync_flag = zscore(brain_state)>th; + anaObj = StepWaveform(sync_flag,1/bin_size); + anaObj.MinIEI = 1; + oo_ana_triggers = anaObj.Triggers*bin_size; + tx = ((1:Ns)-0.5)/fs; + ana_signal = false(1,Ns); + for cr = 1:size(oo_ana_triggers,1) + ana_signal = ana_signal | ... + (tx>=oo_ana_triggers(cr,1) & tx<=oo_ana_triggers(cr,2)); + end + Triggers.Anaesthesia = ana_signal; + cons_cond = contains({Conditions.name}, 'block', 'IgnoreCase', true); + sync_flag = cell(sum(cons_cond),1); + ii = 1; + for ccond = find(cons_cond) + trig_times = Conditions(ccond).Triggers/fs; + sync_state = any(trig_times(:,1) >= oo_ana_triggers(:,1)' & ... + trig_times(:,1) < oo_ana_triggers(:,2)', 2); + sync_flag{ii} = sync_state; + ii = ii + 1; + end + save(fullpath(cond_file), 'sync_flag', 'Triggers', '-append') + %% + f = figure('PaperSize', [21, 14.8], 'Units', 'centimeters', ... + 'Position', [2 2 21 14.8]); + t = createtiles(f,1,5); + axs(1) = nexttile(t,1,[1,4]); + plot(axs(1), centres, muah, 'Color', (2/3)*ones(1,3), ... + 'DisplayName', 'MUA histogram'); + ylabel(axs(1),'MUA counts') + yyaxis(axs(1), "right"); + plot(axs(1), centres, zscore(brain_state), 'k','LineWidth', 2, ... + 'DisplayName', 'LFP estimation'); + ylabel(axs(1), '1\ Hz envelope', 'Interpreter', 'latex') + y = axs(1).YLim; + y2 = repmat(y(:), [1,size(oo_ana_triggers,1)]); + y2 = padarray(y2,2,"symmetric","post"); + x = padarray(oo_ana_triggers,[0,1],"symmetric","both")'; + patch(axs(1),x,y2,ones(size(x)), 'EdgeColor', 'none', ... + 'FaceColor', 'b', 'FaceAlpha', 0.15, ... + 'DisplayName', 'Synchronised state') + legend(axs(1), 'Box', 'off', 'Color', 'none', 'Location', 'best', ... + 'AutoUpdate', 'off') + yline(axs(1), th, 'k--', 'LineWidth', 1) + xlabel(axs(1), 'Time [s]'); axs(1).YAxis(2).Color=0.15*ones(1,3); + xlim(axs(1),[0,exp_duration]) + + axs(2) = nexttile(t); + jit_width = 0.33; + sc = scatter(axs(2), rand(numel(spike_times),1) * jit_width + ... + 1-(jit_width/2), fr_per_unit, 'k.', 'MarkerEdgeAlpha', 0.75, ... + 'displayname', 'Unit fr'); + hold(axs(2),"on") + boxchart(axs(2),ones(size(fr_per_unit)),fr_per_unit,"Notch","on", ... + "BoxEdgeColor","k","BoxFaceColor","none","MarkerStyle","none") + ln = plot(axs(2),[1,1]+[-1, 1]*jit_width, mean(fr_per_unit)*[1,1], "b", ... + "LineWidth", 1.5, "DisplayName", ... + sprintf("Mean %.2g Hz", mean(fr_per_unit))); + ylabel(axs(2), 'Firing rate [Hz]') + legend(axs(2), [sc,ln],'Box', 'off', 'Color', 'none', ... + 'Location', 'best', 'AutoUpdate', 'off') + set(get(axs(2),"XAxis"),"Visible", "off") + set(axs,"TickDir","out") + cleanAxis(axs); + title(t,data_dir,"interpreter","none") + %% + saveFigure(f, fullfile(data_dir,'LFP estimation and fr'), ... + true, false) + close(f) + clearvars -except exp_paths ce anaesthesia_states fullpath load_data +end + +%% +prop_th = 1/2; +nas = cellfun(@(x) zscore(x), anaesthesia_states, 'UniformOutput', false); +ths = -3.5:0.01:3.5; +props = zeros(numel(ths), numel(nas)); +ii = 1; +for cth = ths + prop = cellfun(@(x) sum(x>cth)/numel(x), nas); + props(ii,:) = prop; + ii = ii + 1; +end + +opt_th = props>(prop_th*0.99) & props <(prop_th*1.01); +th = mean(ths(any(opt_th,2))); \ No newline at end of file diff --git a/Emilio/PSTH_percluster_pertrial.m b/Emilio/PSTH_percluster_pertrial.m new file mode 100644 index 0000000..5089e27 --- /dev/null +++ b/Emilio/PSTH_percluster_pertrial.m @@ -0,0 +1,25 @@ +histOpts2 = {'BinLimits', [0,0.3], 'BinWidth', 1e-3, 'Normalization', ... + 'probability'}; +binSizes = logspace(-4,-2,100); +b_var = zeros(ceil(diff(histOpts2{2})/histOpts2{4}),length(binSizes),'single'); +ii = 1; +for bz = binSizes + binSize = bz; vw = configStructure.Viewing_window_s; + histOpts = {'BinLimits', vw, 'BinWidth', binSize, ... + 'Normalization', 'count'}; + fnOpts = {'UniformOutput', false}; + psth_u = arrayfun(@(v) cellfun(@(u) histcounts(u, histOpts{:}), ... + relativeSpkTmsStruct(1).SpikeTimes(v,:), fnOpts{:}), ... + 1:size(relativeSpkTmsStruct(1).SpikeTimes,1), fnOpts{:}); + psth_u = cellfun(@(x) cat(1, x{:}), psth_u, fnOpts{:}); + psth_u = cat(3, psth_u{:}); + + %mdl_psth_tx = fit_poly([1,size(psth_u, 2)], vw + [1,-1]*binSize/2, 1); + %psth_tx = ( ( 1:size(psth_u, 2) )'.^[1,0] ) * mdl_psth_tx; + %plot(psth_tx, mean(psth_u, [1,3])) + b_var(:,ii) = histcounts(mean(psth_u, [1,3]), histOpts2{:}); + ii = ii + 1; + % figure; imagesc( psth_tx, [], psth_u) +end +figure; imagesc(1:length(binSizes), histOpts2{2}, log10(b_var+1e-6)) +axis xy; colormap(inferno) \ No newline at end of file diff --git a/Emilio/Plot_fst_and_BIestimations.m b/Emilio/Plot_fst_and_BIestimations.m new file mode 100644 index 0000000..ebee0ed --- /dev/null +++ b/Emilio/Plot_fst_and_BIestimations.m @@ -0,0 +1,37 @@ +jitDist = makedist("Normal", "mu", 0, "sigma", 0.1); +vw = [-10, 50]*1e-3; binSize = 5e-4; +histOpts = {'BinLimits', vw, 'BinWidth', binSize, ... + 'Normalization', 'probability'}; +uH = arrayfun(@(c) ... + arrayfun(@(u) ... + histcounts( (params.alpha(:,u,c) + params.g(:,c))*fs_scale + fs_centre, ... + histOpts{:} ), 1:Ncl, fnOpts{:}), 1:Ncond, fnOpts{:}); +uH = cellfun(@(c) cat(1, c{:}), uH, fnOpts{:}); +uH = cat(3, uH{:}); + +[Ncl, Nt, Ncond] = size(uH); + +mdl = fit_poly([1,Nt], vw + [1,-1]*(binSize/2), 1); +tx = ( (1:Nt)'.^[1,0] ) * mdl; + +clrMap = [zeros(1,3); inferno(5)]; +for cu = 1:Ncl + figure; + contour(ones(Nt,1)*(1:6), tx * ones(1,Ncond), squeeze(uH(cu,:,:)), 5); + colormap(inferno(10)) + hold on; + plot(1:6, ... + squeeze(mean( params.alpha(:,cu,:) + reshape(params.g,2e3,1,6), 1 ) ) * ... + fs_scale + fs_centre, "k", "LineWidth", 2) + + arrayfun(@(c) scatter( c+random( jitDist, ... + size([firstSpkStruct(c).FirstSpikeTimes{cu,:}]) ), ... + ... + [firstSpkStruct(c).FirstSpikeTimes{cu,:}], ... + "MarkerEdgeColor","k", "MarkerFaceColor",clrMap(c,:), ... + "MarkerFaceAlpha",0.5), 1:Ncond) + ylim([0,50]*1e-3); set(gca, "Box", "off", "Color", "none"); + yticklabels(yticks*1e3); ylabel('Latency [ms]') + xticks(1:Ncond); xticklabels(string({relativeSpkTmsStruct.name})) + set(get(gca, "YAxis"), "Scale", "log") +end \ No newline at end of file diff --git a/Emilio/Plot_rasters_dirty.m b/Emilio/Plot_rasters_dirty.m new file mode 100644 index 0000000..fc315be --- /dev/null +++ b/Emilio/Plot_rasters_dirty.m @@ -0,0 +1,36 @@ + +figure; hold on +Nu = size(relativeSpkTmsStruct(1).SpikeTimes, 1); +clrMap = hsv(Nu); +for ccond = 1:length(relativeSpkTmsStruct) + for cu = 15 + for ct = 1:size(relativeSpkTmsStruct(ccond).SpikeTimes, 2) + spks_cu_ct = [relativeSpkTmsStruct(ccond).SpikeTimes{cu, ct}]'; + tid = repmat(ct, length(spks_cu_ct), 1); + cid = repmat(cu, length(spks_cu_ct), 1); + scatter3( spks_cu_ct, tid, cid, [], ... + 'MarkerFaceColor', clrMap(cu,:), 'MarkerEdgeColor', 'none', ... + 'MarkerFaceAlpha', 3/4) + end + end +end + +%% +clrMap = [zeros(1,3); lines(length(relativeSpkTmsStruct)-1)]; +cu = 18; +figure; hold on +tc = 1; +for ccond = 1:3 + for ctr = 1:size(relativeSpkTmsStruct(ccond).SpikeTimes, 2) + cspks = relativeSpkTmsStruct(ccond).SpikeTimes{cu,ctr}; + if ~isempty(cspks) + line(cspks, tc, 'Marker', 'o', ... + 'MarkerEdgeColor', 'none', ... + 'MarkerFaceColor', clrMap(ccond,:)) + end + tc = tc + 1; + end +end +yticks(Na/2 + cumsum([0, Na(1:end-1)])); +yticklabels({relativeSpkTmsStruct.name}) +ylim([0, sum(Na)+1]) \ No newline at end of file diff --git a/Emilio/Reg_vs_RST.m b/Emilio/Reg_vs_RST.m new file mode 100644 index 0000000..f327b0e --- /dev/null +++ b/Emilio/Reg_vs_RST.m @@ -0,0 +1,137 @@ +mID = 1; +Nm = numel( reg_mice ); +Ns = sum( arrayfun(@(m) numel( m.Sessions ), reg_mice ) ); +rst_reg_dt = zeros( Ns, 5 ); +rsq_dt = zeros( Ns, 10 ); +regMiceNames = [reg_mice.Name]'; +rstMiceNames = [rst_mice.Name]'; +cr = 1; +for cm = 1:numel(reg_mice) + sID = 1; + for cs = 1:numel(reg_mice(cm).Sessions) + dt = rst_mice(cm).Sessions(cs).DataTable; + rst_reg_dt(cr,:) = [cm, cs, dt.NUnits, dt.Proportion]; + dt = reg_mice(cm).Sessions(cs).DataTable; + rsq_dt(cr,:) = [cm, cs, dt.R_squared]; + cr = cr + 1; + end +end + +%% + +f = figure( "Color", "w" ); +createtiles = @(f,r,c) tiledlayout( f, r, c, 'TileSpacing', 'Compact', ... + 'Padding', 'tight'); +cleanAxis = @(x) set( x, "Box", "off", "Color", "none" ); +t = createtiles( f, 3, 1 ); + +ax = gobjects(3, 1); pl = ax; +clrMap = [0,0,0; 0.45*ones(1,3); 0,0,0]; +x = 0:0.05:0.8; +samples = [1e4, 1]; +ylbls = ["Recorded units", "Responsive 20 - 50 ms", "Responsive 50 - 200 ms"]; +for cp = 1:3 + ax(cp) = nexttile( t ); + pl(cp) = plot( ax(cp), rsq_dt(:,3), rst_reg_dt(:,2+cp), 'Marker', '.', ... + 'Color', clrMap(cp,:), 'MarkerSize', 16, 'LineStyle', 'none' ); + cleanAxis( ax(cp) ); + ylabel( ax(cp), ylbls(cp) ); + ft = fitlm( rsq_dt(:,3), rst_reg_dt(:, 2+cp ), 'poly1' ); + cCI = coefCI( ft ); sig = (ft.Coefficients{:,"Estimate"} - cCI(:,1))/2; + slope = makedist( "Normal", "mu", ft.Coefficients{"x1","Estimate"}, ... + "sigma", sig(2) ); + intercept = makedist( "Normal", "mu", ... + ft.Coefficients{"(Intercept)","Estimate"}, "sigma", sig(1) ); + y = random( slope, samples ) * x + random( intercept, samples ); + CI = quantile( y, [0.025, 0.975], 1 ); + hold( ax(cp), 'on' ); lobjs = line( x, CI', 'Color', 0.35*ones(1,3), ... + 'LineStyle', '--' ); + lobjs(1) = []; + lobjs = cat(1, lobjs, line( x, predict( ft, x' ), 'Color', 0.35*ones(1,3) )); + legend( lobjs, {'CI 95%', sprintf('Fit %.3f r^2', ... + ft.Rsquared.Ordinary)}, Box="off", Color='none', Location='best' ); +end +xlabel( ax(cp), "R^2_{SWM}" ) +set( ax, 'TickDir', 'out' ) +arrayfun(@(x) set( get( x, 'XAxis' ), 'Visible', 'off' ), ax(1:2) ) +%% +Bsel = 1; +Nex = 3; +f = figure("Color", "w" ); +t = createtiles( f, Nex+2, 1 ); + +getSEM = @(x) [mean( x, 2 ), std( x, 1, 2 )./sqrt( size( x, 2 ) )]; +mat2ptch = @(x) [x(1:end,:)*[1;1]; x(end:-1:1,:)*[1;-1]]; +phOpts = {'EdgeColor', 'none', 'FaceAlpha', 0.25, 'FaceColor'}; + +clrMap = brighten( blues(2), -0.8 ); +ax = gobjects( Nex+1, 1 ); +[~, ord] = sort( rmse_ltrials, "ascend" ); +cpi = 1; +for cp = ord(1:round(end/Nex):end) + ax(cpi) = nexttile( t ); + set( ax(cpi), 'NextPlot', 'add' ); cleanAxis( ax(cpi) ); + line( ax(cpi), tr_tx, squeeze( y_ltrials(:,cp,Bsel) ), 'Color', 0.15*ones(1,3), 'LineWidth', 0.5 ) + line( ax(cpi), tr_tx, squeeze( y_lptrials(:,cp,Bsel) ), 'Color', 0.55*ones(1,3), 'LineWidth', 0.5 ) + yticklabels( ax(cpi), yticks(ax(cpi)) - 90) + ax(cpi).YTickLabelRotation = 90; + set( get( ax(cpi), 'XAxis' ), 'Visible', 'off' ) + cpi = cpi + 1; +end +ax(cpi) = nexttile( t, [2, 1] ); +cleanAxis( ax(cpi) ) +sem_lshadow = getSEM( y_ltrials ); +sem_lpshadow = getSEM( y_lptrials ); +line(ax(cpi), tr_tx, squeeze( mean( y_ltrials(:,:,Bsel), 2 ) ), 'LineWidth', 2, 'Color', clrMap(1,:) ) +line(ax(cpi), tr_tx, squeeze( mean( y_lptrials(:,:,Bsel), 2 ) ), 'LineWidth', 2, 'Color', clrMap(2,:) ) +patch( ax(cpi), [tr_tx(:); flip( tr_tx(:) )], mat2ptch( sem_lshadow(:,:,Bsel) ), 1, phOpts{:}, clrMap(1,:) ) +patch( ax(cpi), [tr_tx(:); flip( tr_tx(:) )], mat2ptch( sem_lpshadow(:,:,Bsel) ), 1, phOpts{:}, clrMap(2,:) ) +yticklabels( ax(cpi), yticks(ax(cpi)) - 90); ylabel( ax(cpi), 'Angle [°]') +xticklabels( ax(cpi), xticks( ax(cpi) )*1e3 ); +xlabel(ax(cpi), 'Time [ms]') +legend( ax(cpi), flip({'Predicted', 'Observed'}), 'Box', 'off', 'Color', 'none', ... + 'Location', 'best', 'AutoUpdate', 'off' ); +set( ax, 'TickDir', 'out' ) +xline(ax(cpi), 0, 'k--') +xline( ax(cpi), [-0.1, 0.2], 'b') + +saveFigure( f, fullfile( "Z:\Emilio\SuperiorColliculusExperiments\" + ... + "Roller\Batch7_ephys\MC\GADi52\220808_C+F_2100\ephys_E1\Figures", ... + "Example reconstruction laser" ), true, false ) + +%% +f = figure("Color", "w"); +t = createtiles( f, 3, 1); +my_xor = @(x) xor( x(:,1), x(:,2) ); +lnOpts = {'LineStyle', 'none', 'Marker', '|', 'Color', 0.15*ones(1,3)}; +tlSelect = 9; +vWin = [-0.3,0.5]; +[~, ord2] = sort( cellfun(@(x) size(x, 1), spike_times ), "descend" ); +cni = 1; + +ax = gobjects( 2, 1 ); +ax(1) = nexttile( t, [2, 1] ); cleanAxis( ax(1) ); ylabel( ax(1), 'Units') +for cn = ord2(1:round(end/30):end)' + spkIdx = my_xor( spike_times{cn} > time_limits(tlSelect,:) ); + line( spike_times{cn}(spkIdx), cni+zeros(sum(spkIdx),1), lnOpts{:} ) + cni = cni + 1; +end +set( get( ax(1), 'XAxis' ), 'Visible', 'off' ) +bin_size = 0.02; +ax(2) = nexttile(t); +behIdx = my_xor( btx > time_limits(tlSelect,:) ); +line(ax(2), btx(behIdx), behSignals( behIdx, 1 ) ) +linkaxes( ax, 'x' ) +xline(ax(2), time_limits(tlSelect,1)+(bin_size/2):bin_size: ... + time_limits(tlSelect,2)-(bin_size/2), 'LineWidth', 0.1, 'Color', 0.5*ones(1,3) ) +xlim( ax(2), mean(time_limits(tlSelect,:)) + vWin) +xline( ax(2), mean( time_limits(tlSelect,:)), 'k--' ) +set( ax, 'TickDir', 'out' ) +xtv = mean( time_limits(tlSelect,:) ) + vWin; +xticks( ax(2), xtv(1):0.1:xtv(2) ); xlabel( ax(2), 'Time [ms]' ) +xticklabels( ax(2), round( ( xticks( ax(2) ) - xtv(1) + vWin(1) ) *1e3 ) ) +yticklabels( ax(2), yticks(ax(2)) - 90); ylabel( ax(2), 'Angle [°]') + +saveFigure( f, fullfile( "Z:\Emilio\SuperiorColliculusExperiments\" + ... + "Roller\Batch7_ephys\MC\GADi52\220808_C+F_2100\ephys_E1\Figures", ... + "Regression method" ), true, false ) \ No newline at end of file diff --git a/Emilio/Rescue_trig.m b/Emilio/Rescue_trig.m new file mode 100644 index 0000000..37910c3 --- /dev/null +++ b/Emilio/Rescue_trig.m @@ -0,0 +1,7 @@ +for ct = lSub(lSub(:,1) > 1e3*fs,:)' + trig(2,ct(1):ct(2)) = trig(2, ct(1):ct(2)) + 2^15 - 230; +end +%% +for ct = (Conditions(2).Triggers(Conditions(2).Triggers(:,1)>expSamples(1),:) - expSamples(1))' + trig(2,ct(1):ct(2)) = trig(2, ct(1):ct(2)) + int16(2^15 - 230); +end \ No newline at end of file diff --git a/Emilio/Spike_times_for_R.m b/Emilio/Spike_times_for_R.m new file mode 100644 index 0000000..f27e458 --- /dev/null +++ b/Emilio/Spike_times_for_R.m @@ -0,0 +1,31 @@ +fnOpts = {'UniformOutput', false}; +% N_spikes_pcond = arrayfun(@(c) sum(arrayfun(@(u) ... +% numel([relativeSpkTmsStruct(c).SpikeTimes{u,:}]), ... +% 1:size(relativeSpkTmsStruct(c).SpikeTimes,1))), ... +% 1:length(relativeSpkTmsStruct)); +N_spikes_ptrial_u25 = arrayfun(@(c) cellfun(@(ut) numel(ut), ... + relativeSpkTmsStruct(c).SpikeTimes(25,:)), ... + 1:length(relativeSpkTmsStruct), fnOpts{:}); +% (Neuron), condition, trial, spike time. No neuron information now because +% trying only with unit X (25). +unit_spike_times = zeros(sum([N_spikes_ptrial_u25{:}]), 3); + +dat_i = 1; dat_j = 1; +for ccond = 1:length(relativeSpkTmsStruct) + for cu = 25 + cond_id = repmat(ccond, sum(N_spikes_ptrial_u25{ccond}), 1); + for ctr = 1:size(relativeSpkTmsStruct(ccond).SpikeTimes,2) + if N_spikes_ptrial_u25{ccond}(ctr) + trial_id = repmat(ctr, N_spikes_ptrial_u25{ccond}(ctr), 1); + curr_i = dat_i:N_spikes_ptrial_u25{ccond}(ctr)+dat_i-1; + unit_spike_times(curr_i,2:3) = [trial_id, ... + relativeSpkTmsStruct(ccond).SpikeTimes{cu,ctr}']; + dat_i = dat_i + N_spikes_ptrial_u25{ccond}(ctr); + else + continue + end + end + unit_spike_times(dat_j:sum(N_spikes_ptrial_u25{ccond})+dat_j-1,1) = ... + cond_id; dat_j = dat_j + sum(N_spikes_ptrial_u25{ccond}); + end +end \ No newline at end of file diff --git a/Emilio/Spontaneous_eOPN3_Figure3.m b/Emilio/Spontaneous_eOPN3_Figure3.m new file mode 100644 index 0000000..b911509 --- /dev/null +++ b/Emilio/Spontaneous_eOPN3_Figure3.m @@ -0,0 +1,124 @@ +%% +fnOpts = {'UniformOutput', false}; +my_xor = @(x) xor( x(:,1), x(:,2) ); +ovwFlag = false; + +getMI = @(x,d) diff(x, 1, d)./sum(x, d).*(sum(x,d)>0) + (1.*(sum(x,d)==0 | sum(x,d)< 1e-12)); +% getMI = @(ctr, cnd) (cnd - ctr) ./ ( (cnd + ctr).*((cnd + ctr)>0) + (1.*((cnd + ctr)==0 | (cnd + ctr)<1e-9) )); +load(['C:\Users\jefe_\seadrive_root\Emilio U\Für meine Gruppen\GDrive ' ... + 'GrohLab\Projects\00 SC\SC Behaviour\Figures\Figure 3\Matlab ' ... + 'figures\Data\Spontaneous FR.mat']) +expandName = @(x) fullfile( x.folder, x.name ); + +sessions_per_mouse = arrayfun(@(x) dir( fullfile( expandName( x ) ) ), ... + animalFolders, fnOpts{:} ); +sessions_per_mouse = cellfun(@(x) x([x.isdir] & ... + ~ismember( {x.name}, {'.','..'} )), sessions_per_mouse, fnOpts{:} ); +Nsess = sum( cellfun(@numel, sessions_per_mouse ) ); +% 1. Mouse and session number, 2. spike count per spontaneous window, 3. +% spontaneous window limits, 4. firing frequency per window per unit, 5. +% treatment start, 6. conditions indicator, 7. median firing rate per unit, +% 8. p-value of modulation index +results = cell(Nsess, 8 ); +cr = 1; +for ca = 1:numel(animalFolders) + fprintf(1, 'Animal: %s\n', animalFolders(ca).name ) + sessions = sessions_per_mouse{ca}; + ce = 1; + for cs = 1:numel(sessions) + results{cr,1} = [ca,cs]; + fprintf(1, 'Session: %s\n', sessions(cs).name ); + spkFN = dir( fullfile( expandName( sessions(cs) ), 'ephys*', ... + '*spike_times.mat' ) ); + anFN = dir( fullfile( expandName( sessions(cs) ), '*', ... + '*analysis.mat' ) ); + if ~isempty( spkFN ) + load( expandName(spkFN ) ) + else + fprintf(1, "%s: ", sessions(cs).name ) + fprintf(1, 'No spike_times file found!\n') + fprintf(1, 'Skipping!\n') + continue + end + if ~isempty( anFN ) + load( expandName(anFN ), 'Conditions', 'fs' ) + else + fprintf(1, "%s: ", sessions(cs).name ) + fprintf(1, 'No analysis file found!\n') + fprintf(1, 'Skipping!\n') + continue + end + FigureDir = fullfile( spkFN.folder, "Figures" ); + Nu = numel( spike_times ); + Topn = Conditions(2).Triggers(1,1)/fs; + Texp = Conditions(4).Triggers(end,2)/fs; + allTrigs = sortrows( cat(1, Conditions(2:4).Triggers ), 1, "ascend" ); + + lmts = [[0; allTrigs(:,2)/fs + 0.2], [allTrigs(:,1)/fs;Texp]]; + lmts(diff( lmts, 1, 2 ) < 0,:) = []; + + treat_sub = find( lmts(:,1) < Topn, 1, "last" ); + Nt = size(lmts, 1); + Nsp = cellfun(@(u) arrayfun(@(t) sum( my_xor( u < lmts(t,:) ) ), ... + 1:size( lmts, 1 ) ), spike_times, fnOpts{:} ); + Nsp = cat( 1, Nsp{:} ); + + fr_sp = Nsp ./ diff( lmts, 1, 2 )'; + + cndID = [ones( 1, treat_sub), 1+ones(1, Nt-treat_sub)]; + cndID = repmat( cndID, Nu, 1 ); + + medFr = arrayfun(@(c) median( fr_sp(:,cndID(1,:)==c), 2 ), 1:2, fnOpts{:} ); + medFr = cat(2, medFr{:}); + + medMI = getMI( medFr, 2 ); + p = signrank( medMI ); + + results(cr,2:8) = {Nsp, ... Spike cound per window per unit + lmts, ... Window limits + fr_sp, ... Firing rate per unit per window + treat_sub, ... Subscript when treatment started + cndID(1,:), ... Condition membership indicator + medFr, ... Median firing rate per unit over each condition windows + [p, median( medMI( ~isnan( medMI ) ) )] }; % p-value and median MI for all units per condition. + cr = cr + 1; + %% + + f = figure("Color", "w"); t = createtiles( f, 1, 4 ); + ax(1) = nexttile(t,[1,3]); + + loglog(ax(1), medFr(:,1), medFr(:,2), "k." ); + hold(ax(1), 'on'); line(ax(1), xlim, xlim, 'Color', 'k', 'LineStyle', ':' ) + xticklabels(ax(1), xticks(ax(1)) ); yticklabels(ax(1), yticks(ax(1)) ) + xlabel(ax(1), 'Control [Hz]', 'interpreter', 'latex' ); + ylabel(ax(1), 'eOPN3 [Hz]', 'interpreter', 'latex' ) + axis( ax(1), 'square' ) + ytickangle(ax(1), 90 ) + + ax(2) = nexttile(t); + boxchart(ax(2), getMI(medFr, 2), 'Notch', 'on', ... + 'BoxFaceColor', 0.15*ones(1,3), 'JitterOutliers', 'on', ... + 'MarkerStyle', '.', 'MarkerColor', 0.15*ones(1,3) ) + text( ax(2), 1, -1.1, sprintf("$p=%.3g$", p), 'Interpreter', 'latex', ... + "HorizontalAlignment", "center" ) + ylabel(ax(2), 'Decrease $\leftarrow$ Modulation index $\rightarrow$ Increase', ... + 'Interpreter', 'latex' ) + yline( ax(2) , 0, 'k:' ) + disappearAxis(ax(2)) + ylim( ax(2), [-1,1] ) + cleanAxis(ax); + set( ax, 'TickDir', 'out' ) + set( f, 'UserData', {cndID(1,:), medFr, medMI, p} ) + title(t, 'Spontaneous firing rate per unit', 'interpreter', 'latex') + saveFigure(f, fullfile( FigureDir, 'Spontaneous firing rate pre and post eOPN3' ), true, ovwFlag ) + end + close all + fprintf(1, 'Complete!\n' ) +end +%% +results( all( cellfun(@isempty, results ), 2 ), : ) = []; +rTable = cell2table( results, "VariableNames", {'ID', 'SpikeCounts', 'SpontaneousWindows', ... + 'FR', 'TreatmentStart', 'ConditionID', 'MedianFR_pu', 'p_MedianTot'} ); +save( "c:\Users\jefe_\seadrive_root\Emilio U\Für meine Gruppen\GDrive " + ... + "GrohLab\Projects\00 SC\SC Behaviour\Figures\Figure 3\Matlab " + ... + "figures\Data\Spontaneous FR.mat", "rTable", "animalFolders" ) \ No newline at end of file diff --git a/Emilio/Synchrony.m b/Emilio/Synchrony.m new file mode 100644 index 0000000..4579228 --- /dev/null +++ b/Emilio/Synchrony.m @@ -0,0 +1,26 @@ +time_scale = 2.5e-3; delta_t = 5e-4; synchTrial = []; + +for ccond = 1:length(relativeSpkTmsStruct) + for ctr = 1:size(relativeSpkTmsStruct(ccond).SpikeTimes,2) + spks_in_trial = [relativeSpkTmsStruct(ccond).SpikeTimes{:,ctr}]; + c_end = vw(1) + time_scale; c_init = vw(1); + while c_end <= vw(2) + spks_in_cons = spks_in_trial(spks_in_trial > c_init & ... + spks_in_trial < c_end); + if ~isempty(spks_in_cons) && numel(spks_in_cons) > 1 + dm = pdist([spks_in_cons(:)], "euclidean"); + if numel(dm) > 1 + lnorm_fit = fitdist(dm(:), "Normal"); + synchTrial = [synchTrial; ccond, ctr, ... + mean([c_init, c_end]), ... + log(lnorm_fit.ParameterValues(1))]; + else + synchTrial = [synchTrial; ccond, ctr, ... + mean([c_init, c_end]), log(dm(:))]; + end + end + c_init = c_init + delta_t; + c_end = c_end + delta_t; + end + end +end \ No newline at end of file diff --git a/Emilio/Unit_localozation.m b/Emilio/Unit_localozation.m new file mode 100644 index 0000000..83439ec --- /dev/null +++ b/Emilio/Unit_localozation.m @@ -0,0 +1,46 @@ + +[pg_centered, xy_centre, xy_scale] = zscore( [xcoords, ycoords] ); +[ptp_centered, ptp_centre, ptp_scale] = zscore( ptp, 0, 'all' ); + + +tic +% Create optimization variables +theta_hat = optimvar("theta_hat",1,4,"LowerBound",-10,"UpperBound",10); + +% Set initial starting point for the solver +initialPoint.theta_hat = theta; + +% Create problem +problem = optimproblem; + +% Define problem objective +problem.Objective = fcn2optimexpr(@objectiveFcn,theta_hat,ptp_centered,... + pg_centered); + +% Display problem information +show(problem); + +% Solve problem +[solution,objectiveValue,reasonSolverStopped] = solve(problem,initialPoint); + +% Display results +disp(solution) +disp(reasonSolverStopped) +disp(objectiveValue) +toc + +function objective = objectiveFcn(theta_hat, ptp_centered, pg_centered) +% This function should return a scalar representing an optimization objective. + +% Example: Concession stand profit +% revenue = 3*soda + 5*popcorn + 2*candy; +% cost = 1*soda + 2*popcorn + 0.75*candy; +% objective = revenue - cost; % profit + +% Edit the lines below with your calculations. +for c = 1:size( ptp_centered, 2 ) + objective = sum( ( ptp_centered(:,c) - ... + ( theta_hat(1)./ sqrt( sum( (pg_centered - theta_hat([2,3])).^2, 2 ) + ... + theta_hat(4).^2 ) ) ).^2, 'all' ); +end +end \ No newline at end of file diff --git a/Emilio/aux_space.m b/Emilio/aux_space.m new file mode 100644 index 0000000..68d18e5 --- /dev/null +++ b/Emilio/aux_space.m @@ -0,0 +1,129 @@ +aux_mat = zeros( sum( any( ~isnan( PTX_mat(:,[2,3],:) ), 1 ), 'all' ), 2 ); +cm = 1; +for cm2 = 1:size( PTX_mat, 3 ) + dat_flag = any( ~isnan( PTX_mat(:,[2,3],cm2) ), 1 ); + if any( dat_flag ) + dat_flag2 = any( ~isnan( PTX_mat(:,[2,3],cm2) ), 2 ) ; + aux_mat(cm,:) = PTX_mat(dat_flag2,[true, dat_flag],cm2); + cm=cm+1; + end +end +%% +fowFlag = false; +batch_dir = fullfile( "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch6_beh+Muscimol" ); +exp_dirs = dir( fullfile( batch_dir, "Musc", "*", "*" ) ); +exp_dirs( any( string( {exp_dirs.name} ) == ["."; ".."], 1 ) ) = []; +get_full_path = @(x) fullfile( x.folder, x.name); +m = 1e-3; +for cep = 1:numel(exp_dirs) + exp_path = get_full_path( exp_dirs(cep) ); + eph_path = dir( fullfile( exp_path, "ephys*" ) ); + eph_path( ~[eph_path.isdir] ) = []; + beh_path = fullfile( exp_path, "Behaviour" ); + + if ~isempty( eph_path ) + eph_path = get_full_path( eph_path ); + figure_path = fullfile( eph_path, "Figures" ); + af_path = dir( fullfile( eph_path , "*analysis.mat" ) ); + af_path = get_full_path( af_path ); + elseif exist( beh_path, "dir" ) + af_path = get_full_path( dir( fullfile( beh_path, "*analysis.mat") ) ); + figure_path = fullfile( beh_path, "Figures" ); + else + beh_path = exp_path; + af_path = get_full_path( dir( fullfile( beh_path, "*analysis.mat") ) ); + figure_path = fullfile( beh_path, "Figures" ); + end + + [~, af_name] = fileparts( af_path ); + expName = extractBefore(af_name, "analysis"); + load( af_path, "Conditions", "fs") + + fnOpts = {'UniformOutput', false}; + axOpts = {'Box','off','Color','none'}; + lgOpts = cat( 2, axOpts{1:2}, {'Location','best'} ); + + ldFlag = false; + try + load( get_full_path( dir( fullfile( beh_path, "RollerSpeed*.mat" ) ) ), "fr") + catch + ldFlag = true; + end + + ctrl_cond = contains( {Conditions.name}, "Control puff", "IgnoreCase", true ); + ptx_cond = contains( {Conditions.name}, 'musc', 'IgnoreCase', true ); + if sum(ptx_cond)==0 + fprintf(1, 'Did not find PTX condition!! Continuing!!') + fprintf(1, '%s', exp_path ) + continue + end + consCond = find( or(ctrl_cond, ptx_cond) ); + Nccond = length( consCond ); + prmSubs = nchoosek( 1:Nccond, 2 ); + + pairedStimFlags = arrayfun(@(c) any( ... + Conditions(1).Triggers(:,1) == ... + reshape( Conditions(c).Triggers(:,1), 1, [] ), 2 ), consCond, fnOpts{:} ); + pairedStimFlags = cat( 2, pairedStimFlags{:} ); + + consCondNames = string( { Conditions( consCond ).name } ); + + [behRes, behFig_path, behData, aInfo] = analyseBehaviour( beh_path, ... + "ConditionsNames", cellstr( consCondNames ), ... + "PairedFlags", pairedStimFlags, ... + "FigureDirectory", figure_path, ... + "ResponseWindow", [25, 350] * m, ... + "ViewingWindow", [-450, 500] * m, ... + "figOverWrite", fowFlag ); + + if ~exist( "fr", "var" ) && ldFlag + try + load( get_full_path( dir( fullfile( beh_path, "RollerSpeed*.mat" ) ) ), "fr") + catch + load( fullfile( beh_path, 'RollerFrameRate.mat' ), 'fr' ) + end + ldFlag = false; + end + + [pAreas, ~, behAreaFig] = createBehaviourIndex(behRes); + behMeasures = string({behAreaFig.Name}); + biFigPttrn = behMeasures+"%s"; + biFigPttrn = arrayfun(@(s) sprintf(s, sprintf(" %s (%%.3f)", ... + consCondNames ) ), biFigPttrn ); + + for it = 1:numel(behMeasures) + behRes = arrayfun(@(bs, ba) setfield( bs, ... + strrep( behMeasures(it), " ", "_" ), ba), behRes(:), pAreas(:,it) ); + end + + arrayfun(@(f) set( f, 'UserData', behRes ), behAreaFig ); + + biFN = arrayfun(@(s) sprintf( biFigPttrn(s), pAreas(:,s) ), 1:numel(behMeasures) ); + + arrayfun(@(f, fn) saveFigure(f, fullfile(behFig_path, fn), true, fowFlag), ... + behAreaFig(:), biFN(:) ); + + close all +end + +%% +% batch_dir = fullfile( "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch13_beh" ); +% ss_fp = dir( fullfile( batch_dir, "PTX\WT*\*PTX\Behaviour\BehaviourResults*.mat" ) ); +batch_dir = fullfile( "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch12_ephys.e" ); +ss_fp = dir( fullfile( batch_dir, 'MC', 'vGlut*', '*PTX*', '*', 'BehaviourResults V-0.45 - 0.50 s R25.00 - 350.00 ms.mat' ) ); +Nf = numel( ss_fp ); +bl_changes = zeros( Nf, 8 ); +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +for cf = 1:Nf + load( get_full_path( ss_fp(cf) ), "behRes" ) + c_idx = contains( {behRes.ConditionName}, 'control puff', 'IgnoreCase', true ); + p_idx = contains( {behRes.ConditionName}, 'ptx', 'IgnoreCase', true ); + c = {behRes(c_idx).Results.Baseline}; + c = cat( 1, c{:} ); + t = {behRes(p_idx).Results.Baseline}; + t = cat( 1, t{:} ); + [cz, centre, scale] = zscore( c , 0, 2 ); + bl_changes(cf,:) = median( my_zscore( t, centre, scale ), 2 ) - ... + median( cz, 2 ); +end +bs_n = string( {behRes(1).Results.BehSigName} ); diff --git a/Emilio/compareR2_preVSpost_reconstruction.m b/Emilio/compareR2_preVSpost_reconstruction.m new file mode 100644 index 0000000..a36fa21 --- /dev/null +++ b/Emilio/compareR2_preVSpost_reconstruction.m @@ -0,0 +1,176 @@ +%% +expandName = @(x) fullfile( x.folder, x.name ); +roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +%% +% mice_results = "Z:\Emilio\SuperiorColliculusExperiments\Roller\PoolFigures\MC-iegRNs"; +mice_results = fullfile(roller_path, "PoolFigures/MC-iegRNs/iRNs"); +% pool_fig_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller\PoolFigures\MC-iegRNs\iRNs"; +pool_fig_path = mice_results; +r2_fp = dir( fullfile( mice_results,'*_gof.mat') ); +load( expandName( r2_fp ), 'mice' ) +%% +cellcat = @(x,d) cat( d, x{:} ); +bp_names = ["Stim-whisker mean", "Stim-whisker fan arc", ... + "Nonstim-whisker mean", "Nonstim-whisker fan arc", ... + "Interwhisker arc", "Symmetry", "Nose", "Roller speed"]; + +%% +Nm = numel( mice ); % Numer of mice +Nspm = arrayfun(@(x) numel( x.Sessions ), mice ); % Number of sessions per mouse +Nexp = sum( Nspm ); +r2_res_c = zeros( 3, 8, Nexp ); +r2_res_l = zeros( 3, 8, Nexp ); +ce = 1; +mouseID = zeros( Nexp, 1 ); +sessID = zeros( Nexp, 1 ); +for cm = 1:Nm + for cs = 1:Nspm(cm) + dt = mice(cm).Sessions(cs).DataTable; + r2 = dt.R_2_p_L; + r2_res_c(:,:,ce) = r2{1}; + r2_res_l(:,:,ce) = r2{2}; + mouseID(ce) = cm; + sessID(ce) = cs; + ce = ce + 1; + end +end +[Nep, Ns] = size( r2_res_c, [1,2] ); + +%% Control pre- and post-stimulus +% fnOpts = {'UniformOutput', false}; +tocol = @(x) x(:); +% r2_mean_c = cellcat( arrayfun(@(x) mean( r2_res_c(:,:,mouseID==x), 3 ), ... +% 1:Nm, fnOpts{:} ), 3 ); +% r2_mean_l = cellcat( arrayfun(@(x) mean( r2_res_l(:,:,mouseID==x), 3 ), ... +% 1:Nm, fnOpts{:} ), 3 ); +r2_mean_c = r2_res_c; r2_mean_l = r2_res_l; +%% +f = figure("Color", "w"); t = createtiles( f, 1, 1); +ax = nexttile( t ); +% bpID = repmat( ones( Nep, 1 ) * (1:Ns), 1, 1, Nm); +% preVSpostID = repmat( (1:Nep)' * ones( 1, Ns ), 1, 1, Nm ); +bpID = repmat( ones( Nep-1, 1 ) * (1:Ns), 1, 1, Nexp ); +preVSpostID = repmat( (1:Nep-1)' * ones( 1, Ns ), 1, 1, Nexp ); +% boxchart( ax, bpID(:), tocol( r2_mean_c ), 'GroupByColor', preVSpostID(:), ... +% 'Notch', 'on' ) +boxchart( ax, bpID(:), tocol( r2_mean_c(2:3,:,:) ), ... + 'GroupByColor', preVSpostID(:), 'Notch', 'on' ) +xline( ax, (1:Ns-1) + 1/2, '--', 'Color', 0.45*ones(1,3) ); +% legend( {'Overall', 'Pre', 'Post'}, "Box", "off", "Color", "none", ... +% "Location", "best", "AutoUpdate", "off" ) +legend( {'Pre', 'Post'}, "Box", "off", "Color", "none", ... + "Location", "best", "AutoUpdate", "off" ) +cleanAxis( ax ); ytickangle( ax, 90 ); set( ax, 'TickDir', 'out' ); +ylabel( ax, 'R²' ) +xticks( ax, 1:Ns ); xticklabels( ax, bp_names ); +xlim( ax, [1,Ns] + [-1,1]/2 ); +ylim( ax, [0, 1] ) +set( f, 'UserData', {r2_mean_c, bpID, preVSpostID, mouseID, sessID} ) +title( ax, 'Reconstruction R² for overall, pre-, and post-stimulus' ) + +%% Stats tests +p = arrayfun(@(x) signrank( squeeze( r2_mean_c(2,x,:) ), ... + squeeze( r2_mean_c(3,x,:) ) ), 1:Ns ); +fnOpts = {'UniformOutput', false}; +txOpts = {'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom'}; +astk = sum( p < [0.05, 0.01, 0.001]' ); +x = (1:Ns) + [-1;1]/4; +y = [1;1] * max( r2_mean_c(2:3,:,:), [], [3,1] ) * 1.05; +line( ax, x, y, 'Color', 'k' ) +txt = [arrayfun( @(a) replace( join( repmat("\ast", 1, a) ), " ", "" ), astk, fnOpts{:} ); +arrayfun(@(h) sprintf( "$p=%.3f$", h) , p)]; +%txt = arrayfun(@(s) replace( join( txt(:,s) ), " ", ""), 1:Ns ); +text( ax, mean( x, 1 ), y(1,:)+0.035, txt(1,:), txOpts{:}, "FontSize", 10 ) +text( ax, mean( x, 1 ), y(1,:), txt(2,:), txOpts{:}, "FontSize", 8, ... + "Interpreter", "latex" ) +%% +saveFigure( f, fullfile( pool_fig_path, ... + "Reconstruction R² overall, pre and post" ), true, true ) + +%% Laser ON out and in laser stimulation +% r2_mean_c = cellcat( arrayfun(@(x) mean( r2_res_c(:,:,mouseID==x), 3 ), ... +% 1:Nm, fnOpts{:} ), 3 ); +% r2_mean_l = cellcat( arrayfun(@(x) mean( r2_res_l(:,:,mouseID==x), 3 ), ... +% 1:Nm, fnOpts{:} ), 3 ); +% r2_mean_c = r2_res_c; r2_mean_l = r2_res_l; +f = figure("Color", "w"); t = createtiles( f, 1, 1); +ax = nexttile( t ); +% bpID = repmat( ones( Nep, 1 ) * (1:Ns), 1, 1, Nm); +% preVSpostID = repmat( (1:Nep)' * ones( 1, Ns ), 1, 1, Nm ); +bpID = repmat( ones( Nep-1, 1 ) * (1:Ns), 1, 1, Nexp ); +preVSpostID = repmat( (1:Nep-1)' * ones( 1, Ns ), 1, 1, Nexp ); +% boxchart( ax, bpID(:), tocol( r2_mean_c ), 'GroupByColor', preVSpostID(:), ... +% 'Notch', 'on' ) +boxchart( ax, bpID(:), tocol( r2_mean_l(2:3,:,:) ), ... + 'GroupByColor', preVSpostID(:), 'Notch', 'on' ) +xline( ax, (1:Ns-1) + 1/2, '--', 'Color', 0.45*ones(1,3) ); +% legend( {'Overall', 'Pre', 'Post'}, "Box", "off", "Color", "none", ... +% "Location", "best", "AutoUpdate", "off" ) +legend( {'Pre', 'Post'}, "Box", "off", "Color", "none", ... + "Location", "best", "AutoUpdate", "off" ) +cleanAxis( ax ); ytickangle( ax, 90 ); set( ax, 'TickDir', 'out' ); +ylabel( ax, 'R²' ) +xticks( ax, 1:Ns ); xticklabels( ax, bp_names ); +xlim( ax, [1,Ns] + [-1,1]/2 ); +ylim( ax, [0, 1] ) +set( f, 'UserData', {r2_mean_l, bpID, preVSpostID, mouseID, sessID} ) +title( ax, 'Reconstruction R² for overall, pre-, and post-stimulus' ) +%% +p = arrayfun(@(x) signrank( squeeze( r2_mean_l(2,x,:) ), ... + squeeze( r2_mean_l(3,x,:) ) ), 1:Ns ); +fnOpts = {'UniformOutput', false}; +txOpts = {'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom'}; +astk = sum( p < [0.05, 0.01, 0.001]' ); +x = (1:Ns) + [-1;1]/4; +y = [1;1] * max( r2_mean_l(2:3,:,:), [], [3,1] ) * 1.05; +line( ax, x, y, 'Color', 'k' ) +txt = [arrayfun( @(a) replace( join( repmat("\ast", 1, a) ), " ", "" ), astk, fnOpts{:} ); +arrayfun(@(h) sprintf( "$p=%.3f$", h) , p)]; +%txt = arrayfun(@(s) replace( join( txt(:,s) ), " ", ""), 1:Ns ); +text( ax, mean( x, 1 ), y(1,:)+0.035, txt(1,:), txOpts{:}, "FontSize", 10 ) +text( ax, mean( x, 1 ), y(1,:), txt(2,:), txOpts{:}, "FontSize", 8, ... + "Interpreter", "latex" ) + +%% Laser OFF vs Laser ON comparison +% r2_mean_c = cellcat( arrayfun(@(x) mean( r2_res_c(:,:,mouseID==x), 3 ), ... +% 1:Nm, fnOpts{:} ), 3 ); +% r2_mean_l = cellcat( arrayfun(@(x) mean( r2_res_l(:,:,mouseID==x), 3 ), ... +% 1:Nm, fnOpts{:} ), 3 ); +% r2_mean_c = r2_res_c; r2_mean_l = r2_res_l; +f = figure("Color", "w"); t = createtiles( f, 1, 1); +ax = nexttile( t ); +% bpID = repmat( ones( Nep, 1 ) * (1:Ns), 1, 1, Nm); +% preVSpostID = repmat( (1:Nep)' * ones( 1, Ns ), 1, 1, Nm ); +bpID = repmat( ones( Nep-1, 1 ) * (1:Ns), 1, 1, Nexp ); +preVSpostID = repmat( (1:Nep-1)' * ones( 1, Ns ), 1, 1, Nexp ); +% boxchart( ax, bpID(:), tocol( r2_mean_c ), 'GroupByColor', preVSpostID(:), ... +% 'Notch', 'on' ) +boxchart( ax, bpID(:), tocol( cat( 1, r2_mean_c(1,:,:), r2_mean_l(1,:,:) ) ), ... + 'GroupByColor', preVSpostID(:), 'Notch', 'on' ) +xline( ax, (1:Ns-1) + 1/2, '--', 'Color', 0.45*ones(1,3) ); +% legend( {'Overall', 'Pre', 'Post'}, "Box", "off", "Color", "none", ... +% "Location", "best", "AutoUpdate", "off" ) +legend( {'Laser OFF', 'Laser ON'}, "Box", "off", "Color", "none", ... + "Location", "best", "AutoUpdate", "off" ) +cleanAxis( ax ); ytickangle( ax, 90 ); set( ax, 'TickDir', 'out' ); +ylabel( ax, 'R²' ) +xticks( ax, 1:Ns ); xticklabels( ax, bp_names ); +xlim( ax, [1,Ns] + [-1,1]/2 ); +ylim( ax, [-1, 1] ) +set( f, 'UserData', {r2_mean_c, r2_mean_l, bpID, preVSpostID, mouseID, sessID} ) +title( ax, 'Reconstruction R² for overall, pre-, and post-stimulus for BC→iRNs' ) +%% +p = arrayfun(@(x) signrank( squeeze( r2_mean_c(1,x,:) ), ... + squeeze( r2_mean_l(1,x,:) ) ), 1:Ns ); +fnOpts = {'UniformOutput', false}; +txOpts = {'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom'}; +astk = sum( p < [0.05, 0.01, 0.001]' ); +x = (1:Ns) + [-1;1]/4; +y = [1;1] * max( cat(1, r2_mean_l(1,:,:), r2_mean_c(1,:,:) ), [], [3,1] ) * 1.05; +line( ax, x, y, 'Color', 'k' ) +txt = [arrayfun( @(a) replace( join( repmat("\ast", 1, a) ), " ", "" ), astk, fnOpts{:} ); +arrayfun(@(h) sprintf( "$p=%.2g$", h) , p)]; +%txt = arrayfun(@(s) replace( join( txt(:,s) ), " ", ""), 1:Ns ); +text( ax, mean( x, 1 ), y(1,:)*1.1, txt(1,:), txOpts{:}, "FontSize", 10 ) +text( ax, mean( x, 1 ), y(1,:), txt(2,:), txOpts{:}, "FontSize", 8, ... + "Interpreter", "latex" ) \ No newline at end of file diff --git a/Emilio/computeEphMI.m b/Emilio/computeEphMI.m new file mode 100644 index 0000000..e633978 --- /dev/null +++ b/Emilio/computeEphMI.m @@ -0,0 +1,50 @@ +fnOpts = {'UniformOutput', false}; +tocol = @(x) x(:); +my_cat = @(x,d) cat( d, x{:} ); +getMI = @(x,d) diff( x, 1, d ) ./ sum( x, d ); + +mi_lp = squeeze( getMI( lp_mu, 2 ) )'; +popMImean_lp = [mean( mi_lp(:, tx < 0.05), 2, "omitmissing"), ... + mean( mi_lp(:, tx >= 0.05), 2, "omitmissing")]; + +mi_lpu = cell( size( lPSTH ) ); +uMiMatMean = zeros( sum( cellfun(@(x) size( x, 1), lPSTH ) ), 3 ); +uMiMatMed = uMiMatMean; +ridx = cumsum( cellfun(@(x) size( x, 1), lPSTH ) ); +r = 1; +for cs = 1:numel( lPSTH ) + mi_lpu{cs} = getMI( lPSTH{cs}, 3 ); + uMiMatMean(r:ridx(cs),:) = [repmat( cs, size( mi_lpu{cs}, 1 ), 1 ), ... + mean( mi_lpu{cs}(:, tx < 0.05), 2, "omitmissing" ), ... + mean( mi_lpu{cs}(:, tx >= 0.05), 2, "omitmissing" )]; + % uMiMatMed(r:ridx(cs),:) = [repmat( cs, size( mi_lpu{cs}, 1 ), 1 ), ... + % median( mi_lpu{cs}(:, tx < 0.05), 2, "omitmissing" ), ... + % median( mi_lpu{cs}(:, tx >= 0.05, "omitmissing" ), 2)]; + r = 1 + ridx(cs); +end + +popMImedian = my_cat( arrayfun( @(s) ... + median( uMiMatMean( uMiMatMean(:,1) == s, [2,3] ), 1, "omitmissing" ), ... + unique( uMiMatMean(:,1) ), fnOpts{:} ), 1 ); +popMImean = my_cat( arrayfun( @(s) ... + mean( uMiMatMean( uMiMatMean(:,1) == s, [2,3] ), 1, "omitmissing" ), ... + unique( uMiMatMean(:,1) ), fnOpts{:} ), 1 ); + +figure; +subplot(1,5,[1,4]) +boxchart( tocol( repmat( uMiMatMean(:,1), 2, 1) ), ... + tocol( uMiMatMean(:,[2,3]) ), "Notch", "on", ... + "GroupByColor", tocol( ones( size( uMiMatMean, 1), 1) * (1:2) ) ); +xlim( [0, numel(lPSTH)] + 0.5 ) +yline( 0, 'k--'); set( gca, "Box", "off", "Color", "none" ) +subplot(1,5,5) +boxchart(popMImean, 'Notch', 'on' ) +yline( 0, 'k--'); set( gca, "Box", "off", "Color", "none" ) + +figure; boxchart( popMImean_lp, 'Notch', 'on' ); +yline( 0, 'k--'); set( gca, "Box", "off", "Color", "none" ) + +figure; smth = 0.015; +daviolinplot( uMiMatMean(:,[2,3]), 'groups', tocol( ones( size( uMiMatMean, 1), 1 ) * (1:2) ), ... + 'violinalpha', 0.5, 'smoothing', smth, ... 'jitter', 2, ... + 'color', [0,0.51,1] ); \ No newline at end of file diff --git a/Emilio/ephysBehaviourRegression.m b/Emilio/ephysBehaviourRegression.m new file mode 100644 index 0000000..15fb03a --- /dev/null +++ b/Emilio/ephysBehaviourRegression.m @@ -0,0 +1,353 @@ +%{ +res_gof = zeros( 15, 1 ); +% feps = zeros( 15, 1 ); +parfor ii = 1:15 + trainIdx = training( cvpart, ii ); + testIdx = test( cvpart, ii ); + Xtrain = gpuArray( X( any( tr_ID == diag( trainIdx * (1:Nr) )', 2 ), : ) ); + Ytrain = gpuArray( y( any( tr_ID == diag( trainIdx * (1:Nr) )', 2 ), 1 ) ); + Xtest = gpuArray( X( any( tr_ID == diag( testIdx * (1:Nr) )', 2 ), : ) ); + Ytest = gpuArray( y( any( tr_ID == diag( testIdx * (1:Nr) )', 2 ), 1 ) ); + + mdl = fitglm( Xtrain, Ytrain, 'linear', 'Distribution', 'Normal' ); + y_pred = feval( mdl, Xtest ); + res_gof(ii) = goodnessOfFit( Ytest, y_pred, 'MSE' ); + % feps(ii) = loss( mdl, Xtest, Ytest ); +end +%} +%% +fnOpts = {'UniformOutput', false}; +tocol = @(x) x(:); +getAbsPath = @(x) string( fullfile( x.folder, x.name ) ); +roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +data_path = fullfile( roller_path, "Batch16_ephys/MC/GADi35/231204_C+F_2450"); +eph_path = dir( fullfile( data_path, "ephys*" ) ); +if ~isempty( eph_path ) + eph_path = getAbsPath( eph_path ); +else + fprintf(1, 'No ephys folder found!\n') + return +end +beh_path = fullfile( data_path, "Behaviour" ); + +beh_pttrns = ["RollerSpeed*.mat", "BehaviourSignals*.mat"]; +bfs_paths = arrayfun(@(pt) dir( fullfile( beh_path, pt) ), beh_pttrns ); +if any( ~arrayfun(@(x) exist( getAbsPath(x), "file" ), bfs_paths ) ) + fprintf(1, 'Not all necessary behaviour files exist!\n') + return +end +for x=bfs_paths, load( getAbsPath( x ) ), end + +eph_pttrns = ["*_Spike_Times.mat", "*analysis.mat"]; +efs_paths = arrayfun(@(pt) dir( fullfile( eph_path, pt) ), eph_pttrns ); +if any( ~arrayfun(@(x) exist( getAbsPath(x), "file" ), efs_paths ) ) + fprintf(1, 'Not all necessary ephys files exist!\n') + return +end +for x=efs_paths, load( getAbsPath( x ) ), end + +stop_time = length( Triggers.Whisker )/ fs; +bp_names = ["Stim-whisker mean", "Stim-whisker fan arc", ... + "Nonstim-whisker mean", "Nonstim-whisker fan arc", ... + "Interwhisker arc", "Symmetry", "Nose", "Roller speed"]; + +analysis_pttrn = "CW%.2f-%.2fms DW%.2f-%.2f BZ%.2f"; +%% +behSignals = [behDLCSignals, vf]; +mdl_btx = fit_poly( [1, size( behSignals, 1 )], [0, size( behSignals, 1 )/fr] + [1,-1] * (1/fr), 1 ); +btx = (1:size( behSignals, 1 ))'.^[1,0] * mdl_btx; +my_xor = @(x) xor( x(:,1), x(:,2) ); +my_cat = @(x,d) cat( d, x{:} ); + +m = 1e-3; +rel_win = [-1, 1]*0.8; +del_win = [-100, 100]*m; +bin_size = 10*m; + +Nb = ceil( diff( rel_win )/ bin_size ); +% Nb = ceil( diff( time_limits ) / bin_size ); +Nu = numel( spike_times ); +% cons_time = my_xor( btx > time_limits ); +Ns = size( behSignals, 2 ); +wtx = (del_win(1) + bin_size/2):bin_size:(del_win(2) - bin_size/2); +ttx = (rel_win(1) + bin_size/2):bin_size:(rel_win(2) - bin_size/2); +%% +bin_edges = 0:bin_size:stop_time; +bin_centres = mean( [bin_edges(1:end-1); bin_edges(2:end)] ); +Ntb = length( bin_centres ); +hstOpts = {'Normalization', 'countdensity'}; +binned_spikes = cellfun(@(s) histcounts( s, bin_edges, hstOpts{:}), ... + spike_times, fnOpts{:} ); +binned_spikes = cat( 1, binned_spikes{:} ); + +binned_beh = zeros( Ntb, Ns ); +parfor b = 1:Ntb + idx = my_xor( btx(:) < bin_edges(b:b+1) ); + binned_beh(b,:) = mean( behSignals( idx , : ), 1 ); +end + +%% Design matrix for a set of trials (Control) +ctrl_sub = ismember( string( {Conditions.name} ), "Control Puff" ); +time_limits = Conditions(ctrl_sub).Triggers(:,1)./fs + rel_win; +Nr = size( time_limits, 1 ); +Nd = ceil( diff( del_win ) / bin_size ); +auX = zeros( Nb*Nr, Nu, Nd ); + +cwin = arrayfun(@(x) linspace( time_limits(x,1) + (bin_size/2), ... + time_limits(x,2) - (bin_size/2), Nb )', (1:Nr)', fnOpts{:} ); +cwin = cat( 1, cwin{:} ); + +bin_ax = cwin + linspace( del_win(1)+(bin_size/2), ... + del_win(2)-(bin_size/2), Nd ); +% tr_ID = ceil( ( 1:(Nr*Nb) )' / Nb ); +parfor r = 1:(Nr*Nb) + tempC = my_cat( arrayfun( @(u) interp1( bin_centres, binned_spikes(u,:), ... + bin_ax(r,:) ), 1:Nu, fnOpts{:} ), 1); + auX( r, :, :) = tempC; +end + +X = reshape( auX, Nb*Nr, Nu*Nd ); clearvars auX; +Xp = [ ones( Nb*Nr, 1), X]; + +%% Multivariate regression response matrix +%X2 = [ ones( Nb*Nr, 1), X]; +%lmObjs = cell( Ns, 1 ); +y = zeros( Nb*Nr, Ns); +for r = 1:Nr + idx = (r-1)*Nb + (1:Nb); + aux = arrayfun(@(s) interp1( bin_centres, binned_beh(:,s), ... + (1:Nb)'*bin_size + time_limits(r,1) ), (1:Ns), fnOpts{:} ); + aux = cat( 2, aux{:} ); + y(idx,:) = aux; +end +%{ +%% Linear regression using fitlm +cvk = 15; +tr_ID = tocol( ones( Nb, 1 ) * (1:Nr) ); +rmse1v = zeros( cvk , 1 ); mdl1v = cell( size( rmse1v ) ); +Nk = round( Nr*0.15 ); +parfor ii = 1:cvk + testTrials = sort( randperm( Nr, Nk ) ); + trainingTrials = setdiff( 1:Nr, testTrials ); + trainingIdx = any( tr_ID == trainingTrials(:)', 2 ); + testIdx = ~trainingIdx; + + mdl1v{ii} = fitlm( X(trainingIdx,:), y(trainingIdx,1) ); + y_pred = predict( mdl1v{ii}, X(testIdx,:) ); + rmse1v(ii) = sqrt( mean( ( y(testIdx,1) - y_pred ).^2 ) ); +end + +[~, min_error] = min(rmse1v); +y_1_pred = predict( mdl1v{min_error}, X ); + +y_1 = reshape( y(:,1), Nb, Nr ); +y_1_pred = reshape( y_1_pred, Nb, Nr ); + +%% Linear regression using ridge regularisation +cvk = 15; Nlambda = 64; +tr_ID = tocol( ones( Nb, 1 ) * (1:Nr) ); +rmse1v = zeros( cvk , Nlambda ); +mdl1v = zeros( size(X,2)+1, Nlambda, cvk ); +Nk = round( Nr*0.15 ); +lambdas = logspace( 3, 8, Nlambda); +parfor ii = 1:cvk + testTrials = sort( randperm( Nr, Nk ) ); + trainingTrials = setdiff( 1:Nr, testTrials ); + trainingIdx = any( tr_ID == trainingTrials(:)', 2 ); + testIdx = ~trainingIdx; + + Xtrain = [ones( sum( trainingIdx ), 1 ), X(trainingIdx,:)]; + Xtest = [ones( sum( testIdx ), 1 ), X(testIdx,:)]; + % theta_0 = ( X2' * X2 ) \ ( X2' * y(trainingIdx,1) ) ; + mdl1v(:,:,ii) = ridge( y(trainingIdx,1), Xtrain, lambdas ); + y_pred = Xtest * mdl1v(:,:,ii); + rmse1v(ii,:) = sqrt( mean( ( y(testIdx,1) - y_pred ).^2 ) ); +end + +%} +%% Linear regression for all behavioural signals using matrix multiplication +cvk = 15; +tr_ID = tocol( ones( Nb, 1 ) * (1:Nr) ); +rmseAll_ind = zeros( cvk, Ns ); +mdlAll_ind = zeros( size(X,2)+1, cvk, Ns ); +Nk = round( Nr*0.15 ); idxs = zeros( cvk, Nk ); +parfor ii = 1:cvk + testTrials = sort( randperm( Nr, Nk ) ); + idxs(ii,:) = testTrials; + trainingTrials = setdiff( 1:Nr, testTrials ); + trainingIdx = any( tr_ID == trainingTrials, 2 ); + testIdx = ~trainingIdx; + + Xtrain = Xp(trainingIdx,:); Xtest = Xp(testIdx,:); + for cb = 1:Ns + ytrain = y(trainingIdx, cb); ytest = y(testIdx, cb); + mdlAll_ind(:,ii,cb) = ( Xtrain' * Xtrain ) \ ( Xtrain' * ytrain ) ; + %mdl1v(:,:,ii) = ridge( y(trainingIdx,1), Xtrain, lambdas ); + y_pred = Xtest * mdlAll_ind(:,ii,cb); + rmseAll_ind(ii,cb) = sqrt( mean( ( ytest - y_pred ).^2 ) ); + end +end +analysis_key = sprintf( analysis_pttrn, rel_win/m, del_win/m, bin_size/m ); +save( fullfile( data_path, join( ["Regression", analysis_key + ".mat"] ) ), ... + "mdlAll_ind", "DX", "params", "-v7.3" ) +%% Weight matrices +createtiles = @(f,nr,nc) tiledlayout( f, nr, nc, ... + 'TileSpacing', 'Compact', 'Padding', 'tight'); +cleanAxis = @(x) set( x, "Box", "off", "Color", "none" ); +figWeight = figure('Color', 'w'); t = createtiles( figWeight, 2, 4 ); +mdlAll_ind_norm = [mdlAll_ind(1,:,:); + mdlAll_ind(2:end,:,:) ./ vecnorm( mdlAll_ind(2:end,:,:), 2, 1 )]; +mdl_mu = squeeze( mean( mdlAll_ind_norm, 2 ) ); +for cb = 1:Ns + ax = nexttile(t); + imagesc( ax, wtx/m, [], reshape( mdl_mu(2:end,cb), Nu, Nd ) ) + cleanAxis( ax ); yticks( ax, 1:Nu ); title( ax, bp_names( cb ) ); + colormap( traffic ); clim( 1.3*max(abs(mdl_mu(2:end,cb)))*[-1,1] ) + cbObj = colorbar( 'Box', 'off', 'AxisLocation', 'out', ... + 'TickDirection', 'out', 'Location', 'northoutside' ); +end +xlabel(ax, 'Time [ms]'); axs = findobj( t, "Type", "Axes" ); +ylabel( axs(end), 'Units' ) +title( t, 'Regression weights' ) +arrayfun(@(x) set( get( x, "YAxis" ), "Visible", "off" ), ... + axs(setdiff( 1:Ns, [4,8] )) ) +arrayfun(@(x) set( get( x, "XAxis" ), "Visible", "off" ), axs(5:8) ) + +saveFigure( figWeight, fullfile( eph_path, "Figures", ... + sprintf( "Regression weights CW%.2f-%.2fms DW%.2f-%.2f BZ%.2f", ... + rel_win/m, del_win/m, bin_size/m ) ), true ) +%% Reconstruction error (trial-wise) + +%% Total error per body part +errFig = figure("color", "w"); t = createtiles( errFig, 1, 1 ); +ax = nexttile(t); +gray15pc = 0.15*ones(1,3); +boxchart(ax, rmseAll_ind./range(y) , 'Notch', 'on', ... + 'BoxFaceColor', gray15pc, 'JitterOutliers', 'on', ... + 'MarkerStyle', '.', 'MarkerColor', gray15pc ); +xticklabels( ax, bp_names ); cleanAxis( ax ); +ylabel( ax, 'Normalised error' ) +title( ax, sprintf( '%d-kfold cross-validated error', cvk ) ) + +saveFigure( errFig, fullfile( eph_path, "Figures", ... + join( [sprintf( "%d-fold cv error", cvk ), analysis_key] ) ), true ) + +%% Delay +delay_sub = cellfun(@(x) ~isempty(x), regexp( string( {Conditions.name} ), ... + 'Delay \d\.\d+\ss\s\+\sL' ) ); + +time_limits = Conditions(delay_sub).Triggers(:,1)./fs + rel_win; +Nr = size( time_limits, 1 ); +Nd = ceil( diff( del_win ) / bin_size ); +auX = zeros( Nb*Nr, Nu, Nd ); + +cwin = arrayfun(@(x) linspace( time_limits(x,1) + (bin_size/2), ... + time_limits(x,2) - (bin_size/2), Nb )', (1:Nr)', fnOpts{:} ); +cwin = cat( 1, cwin{:} ); + +bin_ax = cwin + linspace( del_win(1)+(bin_size/2), ... + del_win(2)-(bin_size/2), Nd ); +% tr_ID = ceil( ( 1:(Nr*Nb) )' / Nb ); +parfor r = 1:(Nr*Nb) + tempC = my_cat( arrayfun( @(u) interp1( bin_centres, binned_spikes(u,:), ... + bin_ax(r,:) ), 1:Nu, fnOpts{:} ), 1); + auX( r, :, :) = tempC; +end + +X = reshape( auX, Nb*Nr, Nu*Nd ); clearvars auX; +Xl = [ ones( Nb*Nr, 1), X]; + +%{ +%% Multiple output linear regression +cvk = 15; +Nk = round( Nr*0.15 ); +rmse = zeros( cvk , Ns ); +mdl = zeros( size( X, 2 )+Ns, size( y, 2 ), cvk ); +idxs = zeros( cvk, Nk ); %[zy, y_mu, y_sig] = zscore(y, 0, 1); +X2 = [[eye(Ns); zeros( size(X,1) - Ns, Ns )], X]; +for ii = 1:cvk + fprintf(1, 'K:%d\n', ii) + testTrials = sort( randperm( Nr, Nk ) ); + idxs(ii,:) = testTrials; + trainingTrials = setdiff( 1:Nr, testTrials ); + trainingIdx = any( tr_ID == trainingTrials, 2 ); + testIdx = ~trainingIdx; + + mdl(:,:,ii) = mvregress( gpuArray( X2(trainingIdx,:) ), ... + gpuArray( y(trainingIdx,:) ) ); + y_pred = X2(testIdx,:) * mdl(:,:,ii); + rmse(ii,:) = sqrt( mean( ( y(testIdx,:) - y_pred ).^2 ) ); +end + +[~, min_error] = min(rmse,[],1); +y_all_pred = X2 * squeeze( mean( mdl, 3 ) ); + +y_trials = reshape( y, Nb, Nr, Ns ); +y_all_pred = reshape( y_all_pred, Nb, Nr, Ns ); + +%% Training + +ho_trials = randperm( Nr, round( Nr*0.1 ) ); +testIdx = any( tr_ID == sort(ho_trials), 2 ); +cv_kf = cvpartition( tr_ID( ~testIdx ), "KFold", 15 ); + +Xtrain = X(~testIdx, :); ytrain = y(~testIdx,1); + +[mdl, fitInfo] = lassoglm( X(~testIdx,:), y(~testIdx,1), 'normal', ... + 'CV', cv_kf, 'Lambda', logspace( -5, 3, 64 ), ... + 'Options', statset('UseParallel', true ), ... + 'Alpha', eps ); + +w_vec = [fitInfo.Intercept(fitInfo.IndexMinDeviance); + mdl(:,fitInfo.IndexMinDeviance)]; +y_pred = glmval( w_vec, X, "identity" ); +y_pred = reshape( y_pred, Nb, Nr ); +clrMap = [0.15*ones(1,3); 0.85,0.51,0.15 ]; +figure; lObj = line( 1:(Nb*numel( ho_trials )), [y(testIdx,1), y_pred(:)] ); +arrayfun(@(ii,x) set( x, 'Color', clrMap(ii,:) ), (1:numel(lObj))', lObj(:) ) + +createtiles = @(f,nr,nc) tiledlayout( f, nr, nc, ... + 'TileSpacing', 'Compact', 'Padding', 'tight'); +cleanAxis = @(x) set( x, "Box", "off", "Color", "none" ); + +fig = figure( 'Color', 'w' ); t = createtiles( fig, 10, 2); +nexttile([8, 1]); +imagesc( ttx, [], y_1' - 90); colormap(inferno) +xline(0, 'LineStyle', '--', 'Color', 0.85*ones(1,3) ) +nexttile([8, 1]); +imagesc( ttx, [], y_pred' - 90); colormap(inferno) +set( get( gca, 'YAxis' ), 'Visible', 'off' ) +nexttile(t); +line( ttx, mean( y_1, 2 ) - 90, 'Color', 0.15*ones(1,3), 'LineWidth', 1.5 ) +nexttile(t); +line( ttx, mean( y_pred, 2 ) - 90, 'Color', [0.85, 0.51, 0.15] , 'LineWidth', 1.5 ) +axs = get( t, "Children" ); +linkaxes( axs, 'x') +xlim(ttx([1,end])) +arrayfun(@(x) set( get( x, "XAxis" ), "Visible", "off" ), axs(3:4) ) +arrayfun(@(x) xticklabels( x, xticks(x) / m ), axs(1:2) ) + +rmse = mean( ( y_1 - y_pred ).^2, 1 ); + + +wtx = (del_win(1) + bin_size/2):bin_size:(del_win(2) - bin_size/2); +ttx = (rel_win(1) + bin_size/2):bin_size:(rel_win(2) - bin_size/2); + +figure; imagesc( wtx, [], reshape( w_vec(2:end), Nd, Nu )' ) + +%% Design matrix for the whole experiment +Nb = ceil( diff( bin_edges([1,end]) )/ bin_size ); +auX = zeros( Nb, Nu, Nd ); +parfor b = 1:Nb + cwin = bin_centres(b) + del_win; + bin_ax = linspace( cwin(1), cwin(2), Nd ); + tempC = arrayfun(@(u) interp1( bin_centres, binned_spikes(u,:), ... + bin_ax ), 1:Nu, fnOpts{:} ); + tempC = cat( 1, tempC{:} ); + tempC( isnan(tempC) ) = 0; + auX( b, :, :) = tempC; +end +X = reshape( auX, [], Nu*Nd ); +X2 = [ ones( Nb*Nr, 1), X]; +Xa = X2; +%} diff --git a/Emilio/ephysVSai.m b/Emilio/ephysVSai.m new file mode 100644 index 0000000..71f34fa --- /dev/null +++ b/Emilio/ephysVSai.m @@ -0,0 +1,284 @@ +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +cond_exp = {'^Delay\s\d[.]\d{3}\s\w\s[+]\sL[0-9.]', ... iRNs + '^Delay\s\d[.]\d{3}\s\w'}; % Continuous +cond_sel = 2; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +owfFlag = false; +m = 1e-3; k = 1e3; + +cellcat = @(x,d) cat( d, x{:} ); +tocol = @(x) x(:); +getMI = @(x,d) diff(x, 1, d) ./ ... + sum(x, d).*(sum(x,d)>0) + (1.*(sum(x,d)==0 | sum(x,d)< 1e-12)); +% total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); + +% exclude_names = {'GADi13', 'GADi15', 'GADi53'}; +exclude_names = { }; +vWin = [-300, 400]*m; +% iRN_mice = dir( "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch*\MC\GADi*" ); +iRN_mice = dir( "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch*\eOPN3\*" ); +iRN_mice = iRN_mice( ~cellfun('isempty', regexp({iRN_mice.name}, '^\w{2}\d{2}' ) ) ); +animalFolders = arrayfun(@(f) string( expandName( f ) ), iRN_mice(:)); +exclude_flags = contains( animalFolders, exclude_names ); +animalFolders = animalFolders( ~exclude_flags ); +%% +% asPaths = arrayfun(@(a) dir( fullfile( a, '*F*', 'ephys*', 'cluster_info.tsv' ) ), ... +% animalFolders, fnOpts{:} ); +asPaths = arrayfun(@(a) dir( fullfile( a, '*', 'ephys*', 'cluster_info.tsv' ) ), ... + animalFolders, fnOpts{:} ); +bad_flag = cellfun(@(x) contains( {x.folder}, 'bad' ), asPaths, fnOpts{:} ); +notF_flag = cellfun(@(x) contains( {x.folder}, 'f' ), asPaths, fnOpts{:} ); +asPaths = cellfun(@(a,f,w) a(~f&~w), asPaths, bad_flag, notF_flag, fnOpts{:} ); +empty_flag = cellfun('isempty', asPaths ); +asPaths = asPaths(~empty_flag); animalFolders = animalFolders(~empty_flag); +clInfo = cellfun(@(a) arrayfun(@(s) getClusterInfo( expandName( s ) ), ... + a, fnOpts{:} ), asPaths, fnOpts{:} ); + +%% +Nu = cellfun(@(x) cellfun(@(y) sum( y.ActiveUnit ), x ), clInfo, fnOpts{:} ); +low_unit_flag = cellfun(@(x) x < 10, Nu, fnOpts{:} ); +low_unit_animal = cellfun(@(x) all(x < 10), Nu ); +asPaths = cellfun(@(a,f) a(~f), asPaths, low_unit_flag , fnOpts{:} ); +animalFolders = animalFolders( ~low_unit_animal ); +clInfo = cellfun(@(a,f) a(~f), clInfo, low_unit_flag , fnOpts{:} ); +Nm = numel( clInfo ); +Nu = cellfun(@(a,f) a(~f), Nu, low_unit_flag , fnOpts{:} ); +% clInfo = arrayfun(@(x) getClusterInfo( expandName( ... +% dir( fullfile( x, '*F*', 'ephys*', 'cluster_info.tsv' ) ) ) ), animalFolders, ... +% fnOpts{:}); +%% Pooling ephys and behaviour +% Initialising +Nspm = cellfun("size", clInfo, 1 ); % Number of sessions per mouse +Nexp = sum( Nspm ); +Nu_all = cat( 1, Nu{:} ); +Nuinit = cumsum( [1; Nu_all(1:end-1) ] ); +Nuend = cumsum( Nu_all ); +PSTHall_mu = zeros( 700, sum( Nu_all ), 2 ); +brAll = []; +PSTHall = cell( Nexp, 2 ); +uSig = cell( Nexp, 1 ); uID = uSig; +uMod = uSig; +uMI = uSig; ce = 1; +%% +rstVars2load = {'relativeSpkTmsStruct', 'configStructure'}; +afVars2load = {'Conditions', 'fs'}; +for ca = 1:Nm + for cs = 1:Nspm(ca) + data_dir = string( getParentDir( asPaths{ca}(cs).folder, 1 ) ); + % condStruct = load( expandName( dir( fullfile( data_dir, "*\*analysis.mat" ) ) ), afVars2load{:} ); + rstPath = dir( fullfile( data_dir, "*", "*RW20.00-200.00*(unfiltered) RelSpkTms.mat" ) ); + brPath = dir( fullfile( data_dir, "*","BehaviourResult*.mat" ) ); + mfPath = dir( fullfile( data_dir, "ephys*", "Results", "Res VW* RW20.00-200.00 ms SW*PuffAll.mat") ); + brVars2load = 'behRes'; + if isempty( brPath ) + brPath = dir( fullfile( data_dir, "*\Simple summary.mat" ) ); + brVars2load = 'summStruct'; + end + brStruct = load( expandName( brPath ), brVars2load ); + behRes = brStruct.(brVars2load); + ctrlSub = ismember( string( {behRes.ConditionName} ), 'Control Puff' ); + % cf_flags = regexp( string( {behRes.ConditionName} ), {'Control Puff', ... + % 'Delay\s\d[.]\d{3}\s\w\s[+]\sL[0-9.]'} ); + % cf_flags = contains( string( {behRes.ConditionName} ), 'Control Puff'); + cf_flags = regexp( string( {behRes.ConditionName} ), ... + cond_exp{cond_sel} ); + cf_flags = ctrlSub | ~cellfun( 'isempty', cf_flags ); + + brAll = cat( 1, brAll, behRes(cf_flags) ); + if ~isempty(rstPath) || isscalar( rstPath ) + rstCont = load( expandName( rstPath ), rstVars2load{:} ); + else + fprintf(1, 'Either empty or more than 1 file found!\n'); + disp( {rstPath.name} ) + continue + end + mftype = 1; + mfVars2load = {'Results', 'gclID', 'Counts', 'configStructure'}; + if isempty( mfPath ) + fprintf( 1, 'Res file not found!\n') + mfPath = dir( fullfile( data_dir, "ephys*", "Results", "Map*.mat") ); + mfVars2load = {'keyCell', 'resMap'}; + if isempty( mfPath ) + fprintf( 1, 'Unable to load unit response information!\n') + disp( mfPath ) + continue + end + mftype = 2; + end + mfStruct = load( expandName( mfPath ), mfVars2load{:} ); + if mftype == 1 + Results = mfStruct.Results; + % Taking only control and laser frequency + cnfStruct = mfStruct.configStructure; + Nccond = numel( cnfStruct.ConsideredConditions ); + valid_cond_subs = 1:Nccond; + ctrlSub = ismember( cnfStruct.ConsideredConditions, 'Control Puff' ); + cf_flags = regexp( cnfStruct.ConsideredConditions, ... + cond_exp{cond_sel} ); + cf_flags = ctrlSub | ~cellfun( 'isempty', cf_flags ); + valid_cond_subs = valid_cond_subs( cf_flags ); + cmbSubs = cellcat(arrayfun(@(x) sscanf( x.Combination, '%d %d'), ... + Results , fnOpts{:} ), 2 ); + configFlag = cmbSubs(1,:) == cmbSubs(2,:) & ... + any(cmbSubs(1,:) == valid_cond_subs(:), 1); + cond_ordr = cmbSubs( 1, configFlag ); + gclID = mfStruct.gclID; + + Counts = mfStruct.Counts; + Counts = arrayfun(@(c) squeeze( mean( cellcat( Counts(c,:), 3 ), 2 ) ), ... + valid_cond_subs, fnOpts{:} ); + % configFlag = cellfun(@(x) ~isempty(x), regexp( {Results.Combination}, ... + % '1\s1\ssignrank', 'ignorecase' ) ); + sig_aux = arrayfun(@(x) x.Activity(1).Pvalues, Results(configFlag), fnOpts{:} ); + mod_aux = arrayfun(@(x) x.Activity(1).Direction, Results(configFlag), fnOpts{:} ); + mi_aux = cellfun(@(x) getMI( x, 2 ), Counts, fnOpts{:} ); + uSig{ce} = cellcat( sig_aux(cond_ordr), 2); + uMod{ce} = cellcat( mod_aux(cond_ordr), 2); + uMI{ce} = cellcat( mod_aux(cond_ordr), 2 ); + uID{ce} = gclID; + else + resMap = mfStruct.resMap; keyCell = mfStruct.keyCell; + configFlag = contains( keyCell(:,1), 'RW20.00-200.00' ) & ... + contains( keyCell(:,4), 'Control Puff' ); + if sum( configFlag ) ~= 1 + fprintf( 1, 'Cannot process this keycell... \n') + disp( keyCell ) + end + uSig{ce} = resMap( keyCell{configFlag,:} ); + uMod{ce} = zeros( Nu(ca), 1 ); uMI{ca} = uMod{ca}; + uID{ce} = clInfo{ca}{clInfo{ca}.ActiveUnit==1, "cluster_id" }; + end + rstStruct = rstCont.relativeSpkTmsStruct; + confStruct = rstCont.configStructure; + % Conditions = condStruct.Conditions; + % fs = condStruct.fs; + if any( confStruct.Viewing_window_s ~= vWin ) + confStruct.Viewing_window_s = vWin; + end + [PSTH, trial_tx, Na] = getPSTH_perU_perT( ... + rstStruct(valid_cond_subs), confStruct ); + a = Nuinit(ce); b = Nuend(ce); + idx = a:b; + PSTHall_mu(:,idx,:) = cellcat( cellfun(@(x) squeeze( mean( x, 1 ) ), ... + PSTH, fnOpts{:} ), 3 ); + PSTHall(ce,:) = PSTH; + ce = ce + 1; + end +end +clearvars PSTH brStruct ctrlSub rstStruct confStruct brPath brVars2load ... + rstCont a b idx; +ai_pt = arrayfun(@(s) getAIperTrial( s ), brAll, fnOpts{:} ); + +%% Sliding window analysis for behaviour correlation +% Idea is to slide a time window per unit per trial for getting an R² +slid_win_length = 20*m; time_slide = 5*m; +time_init = -50*m; time_stop = 400*m; +Nrs = (time_stop - time_init - slid_win_length) / time_slide; +r_squared = cell( Nexp, 1 ); +Nt = cellfun( "size", PSTHall, 1 ); +parfor cexp = 1:Nexp + r_squared{cexp} = zeros( Nu_all(cexp), Nrs, 2 ); + for cu = 1:Nu_all(cexp) + aux_rs = zeros(1, Nrs, 2 ); + for ct = 1:2 + cw = time_init + [0, slid_win_length]; + ci = 1; + aux_trial = cellcat( arrayfun(@(t) conv( PSTHall{cexp,ct}(t, :, cu ), ... + gausswin( 5 ), "same" ), 1:Nt(cexp,ct), 'UniformOutput', false ), 1 ); + while cw(2) <= time_stop + act_mu = mean( aux_trial(:, my_xor( trial_tx < cw ) ) , 2 ); + if ( sum( act_mu == 0 ) / numel(act_mu ) ) < 0.4 + aux_mdl = fitlm( zscore( act_mu )', zscore( ai_pt{cexp,ct} )', 'poly1' ); + aux_rs(1,ci,ct) = aux_mdl.Rsquared.Ordinary; + end + cw = cw + time_slide; ci = ci + 1; + end + end + r_squared{cexp}(cu,:,:) = aux_rs; + end +end +% r_squared_cat = cat( 1, r_squared{:} ); +%% Time resolved boxplots for all experiments +td = 30; +slid_win_length = td*m; time_slide = td*m; +time_init = -160*m; time_stop = 400*m; +Nrs = floor( (time_stop - time_init - slid_win_length) / time_slide ); +r_squared_pexp = zeros( Nexp, Nrs, 2 ); +parfor cexp = 1:Nexp + for ct = 1:2 + cw = time_init + [0, slid_win_length]; + for ci = 1:Nrs + act_mu = mean( PSTHall{cexp,ct}(:, my_xor( trial_tx < cw ),: ) , [2,3] ); + aux_mdl = fitlm( zscore( act_mu )', zscore( ai_pt{cexp,ct} )', 'poly1' ); + r_squared_pexp(cexp,ci,ct) = aux_mdl.Rsquared.Ordinary; + cw = cw + time_slide; + end + end +end +aux_mdl = fit_poly( [1,Nrs], [time_init, time_init + Nrs*slid_win_length] ... + + (slid_win_length/2)*[1,-1], 1 ); +b_tx = ( ( 1:Nrs )'.^[1,0] ) * aux_mdl; +% r_squared_cat = cat( 1, r_squared_pexp{:} ); +%% +bxOpts = {'JitterOutliers', 'on', 'MarkerStyle', '.', 'MarkerColor', 'k',... + 'BoxFaceColor', 'k', 'BoxWidth', k*(time_slide)/2, ... + 'Notch', 'off' }; +ttl = ["Laser OFF", "Laser ON"]; +f = figure('Color', 'w'); t = createtiles(f, 2, 2); +ax = gobjects( 3, 1 ); +for ct = 1:2 + ax(ct) = nexttile( t ); + boxchart(ax(ct), tocol( ones(Nexp,1)*b_tx' * k ), ... + tocol(r_squared_pexp(:,:,ct)), bxOpts{:} ) + hold( ax(ct), 'on'); + line(ax(ct), k*b_tx, median( r_squared_pexp(:,:,ct), 1 ), 'Color', 'k', ... + 'LineWidth', 2 ) + xline( ax(ct), [0,50,200], 'r--') + xlabel( ax(ct), 'Time [ms]' ) + xlim( ax(ct), k*(b_tx([1,end]) + [-1;1]*slid_win_length/2) ) + if ct ~=2 + ylabel( ax(ct), 'R² per window' ) + else + set( get( ax(ct), 'YAxis'), 'Visible', 'off' ) + end + cleanAxis( ax(ct) ); + title( ax(ct), ttl(ct) ) + +end +ct = ct + 1; +title( t, sprintf('Time-resolved_{%d ms} R² population (per experiment, eOPN3)', td ) ) +ax(ct) = nexttile( t, [1,2] ); +lObjs = line( ax(ct), b_tx*k, squeeze( median( r_squared_pexp, 1 ) ) ); +legend( lObjs, ttl, 'Color', 'none', 'Box', 'off', 'Location', 'best'); +xlabel( ax(ct), 'Time [ms]' ) +ylabel( ax(ct), 'R²' ) +ytickangle( ax, 90 ) +set( ax, 'TickDir', 'out' ) +linkaxes(ax, 'x'); linkaxes( ax(1:2), 'y' ) + +%% +% Comparing conditions agains each other +p_cond_per_window = arrayfun(@(x) signrank( ... + squeeze( r_squared_pexp(:,x,1) ), ... + squeeze( r_squared_pexp(:,x,2) ) ), ... + 1:Nrs ); +p_th = [0.05; 0.01; 0.001]; +astk = sum( p_cond_per_window < p_th ); +text( ax(ct), b_tx*k, max( median( r_squared_pexp ), [], 3 ) * 1.15, ... + cellfun(@(x) join(x), arrayfun(@(x) repmat( "\ast", 1, x ), astk, fnOpts{:} ) ), ... + "HorizontalAlignment", "center", "VerticalAlignment", "middle", "FontSize", 17 ) +%% Statistics on the time-resolved R² +tbl2 = cell(2, 1 ); +for ct = 1:2 + [p, tbl, stats] = kruskalwallis( squeeze(r_squared_pexp(:,:,ct) ), ... + string( b_tx(:) * k ) ); + figure; tbl2{ct} = multcompare( stats ); + sum( tbl2{ct}(:,end) < 0.05 ) +end diff --git a/Emilio/first_spike_4_R.m b/Emilio/first_spike_4_R.m new file mode 100644 index 0000000..d78cc60 --- /dev/null +++ b/Emilio/first_spike_4_R.m @@ -0,0 +1,18 @@ +fnOpts = {'UniformOutput', false}; +Ns_puc = arrayfun(@(c) ... + arrayfun(@(u) ... + cellfun(@(t) all([~isempty(t), t>0, t<0.05]), ... + firstSpkStruct(c).FirstSpikeTimes(u,:)), ... + 1:size(firstSpkStruct(c).FirstSpikeTimes, 1), fnOpts{:}), ... + 1:length(firstSpkStruct), fnOpts{:}); + +fs_puc = arrayfun(@(c) ... + arrayfun(@(u) ... + [repmat(c, sum(Ns_puc{c}{u}), 1), ... + repmat(u, sum(Ns_puc{c}{u}), 1), ... + [firstSpkStruct(c).FirstSpikeTimes{u,Ns_puc{c}{u}}]'], ... + 1:size(firstSpkStruct(c).FirstSpikeTimes, 1), fnOpts{:}), ... + 1:length(firstSpkStruct), fnOpts{:}); + +fs_puc = cellfun(@(c) cat(1, c{ cellfun(@(c2) ~isempty(c2),c) }), fs_puc, fnOpts{:}); +fs_puc = cat(1, fs_puc{:}); \ No newline at end of file diff --git a/Emilio/helix_BehReconstruct.sh b/Emilio/helix_BehReconstruct.sh new file mode 100644 index 0000000..ebad542 --- /dev/null +++ b/Emilio/helix_BehReconstruct.sh @@ -0,0 +1,9 @@ +#!/bin/bash +#SBATCH --partition=cpu-single +#SBATCH --ntasks=32 +#SBATCH --time=24:00:00 +#SBATCH --mem=128gb + +module load math/matlab/R2023a + +matlab -nodisplay -r poolEphBeh_regression > results.out 2>&1 \ No newline at end of file diff --git a/Emilio/homogenise_images_4_sharcq.m b/Emilio/homogenise_images_4_sharcq.m new file mode 100644 index 0000000..565a978 --- /dev/null +++ b/Emilio/homogenise_images_4_sharcq.m @@ -0,0 +1,39 @@ + +fullpath = @(x) fullfile(x.folder, x.name); +get_img_size = @(x) [x.getTag("ImageWidth"), x.getTag("ImageLength")]; +fnOpts = {'UniformOutput', false}; +ideal_prop = 57/40; + + +img_dir = fullfile("Z:\Leonie\AC\M68\M68 fit"); +original_resolution = 1.15; +desired_resolution = 10; +homogenised_img_folder = fullfile(img_dir, 'Homogenised and downsampled'); +if ~exist(homogenised_img_folder,"dir") + mkdir(homogenised_img_folder) +end +scaling_factor = original_resolution/desired_resolution; + +img_paths = dir(fullfile(img_dir, "*Merged_overlay.tif")); +roi_paths = dir(fullfile(img_dir, "*Merged_overlay.csv")); +t_objs = arrayfun(@(x) Tiff(fullpath(x), 'r'), img_paths); +img_size = arrayfun(@(x) get_img_size(x), t_objs, fnOpts{:}); +arrayfun(@(x) x.close, t_objs); +img_size = cat(1, img_size{:}); +img_prop = img_size(:,1)./img_size(:,2); +final_sz = ceil(max(img_size(:,1)) * [1, (1/ideal_prop)]); +for ci = 1:numel(img_paths) + shift_px = [floor((final_sz([2,1]) - img_size(ci,[2,1]))/2)]; + img = imread(fullpath(img_paths(ci))); + img2 = padarray(img, [shift_px, 0], 0, 'both'); + img2 = imresize(img2, scaling_factor); + img2 = img2(1:800,1:1140,:); + roi_table = readtable(fullpath(roi_paths(ci)), ... + 'Delimiter',',','VariableNamingRule','preserve'); + roi_table{:,{'X','Y'}} = round((roi_table{:,{'X','Y'}} + ... + shift_px([2,1]))*scaling_factor); + imwrite(img2,fullfile(homogenised_img_folder, ... + img_paths(ci).name),'tif', 'WriteMode', 'overwrite') + writetable(roi_table,fullfile(homogenised_img_folder, ... + roi_paths(ci).name),'WriteVariableNames',true) +end \ No newline at end of file diff --git a/Emilio/iegRNs_AmplitudeIndexPool.m b/Emilio/iegRNs_AmplitudeIndexPool.m new file mode 100644 index 0000000..6abc3ca --- /dev/null +++ b/Emilio/iegRNs_AmplitudeIndexPool.m @@ -0,0 +1,138 @@ +roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +bp_paths = dir( fullfile( roller_path, "\Batch*\Batch*_BehaviourIndex.mat" ) ); +bodypart_names = string( {bp_paths.name} )'; +b_num = regexp( bodypart_names, '\d+', 'match' ); +b_num = cat(1, b_num{:} ); b_num = str2double( b_num ); +expandPath = @(x) fullfile( x.folder, x.name); +fnOpts = {'UniformOutput', false}; + +mc_subs = [1, 2, 7, 8, 10, 12, 15, 16, 18]; +bc_subs = [1, 2, 19]; +bs_subs = 2; +mt_subs = [11, 14, 17]; + +exp_type_subs_cell = {mc_subs, bc_subs, bs_subs, mt_subs}; +% clearvars *_subs -except exp_type_subs_cell + +mice_bulk = arrayfun( @(x) load( expandPath( x ), "mice" ), ... + bp_paths ); +mice_exp_sub = cellfun(@(x) any(b_num == x, 2), exp_type_subs_cell, ... + fnOpts{:} ); + +summMice = cellfun(@(x) summariseMiceBeh( cat(1, mice_bulk(x).mice ) ), ... + mice_exp_sub, fnOpts{:} ); +%% +fnOpts = {'UniformOutput', false}; +exp_subtype = {'iRNs', 'eRNs', 'RNs'}; +% exp_subtype = {'terminal inhib'}; +name_keys = {'GADi', {'GADe', 'vGlut'}, 'WTg'}; +% name_keys = {'GADi', 'vGlut', 'WTg'}; +% name_keys = {'GADi', 'GADe', 'WTg'}; +% name_keys = {{'Rb', 'WT'}}; +bodypart_names = ["Stim-whisker mean", "Stim-whisker fan arc", ... + "Nonstim-whisker mean", "Nonstim-whisker fan arc", "Interwhisk arc", ... + "Symmetry", "Nose", "Roller speed"]; +signTh = [0.001, 0.01, 0.05, 0.1]; +createtiles = @(f,nr,nc) tiledlayout( f, nr, nc, ... + 'TileSpacing', 'Compact', 'Padding', 'tight'); +bxOpts = cellstr(["Notch", "on", "JitterOutliers", "on", ... + "BoxFaceColor", "k", 'MarkerStyle', '.', 'MarkerColor', 'k']); +txOpts = {'HorizontalAlignment','left','VerticalAlignment', 'middle', ... + 'Rotation', 90, 'Interpreter', 'latex'}; +cleanAxis = @(x) set( x, "Box", "off", "Color", "none" ); +fig_path = fullfile( ... + "Z:\Emilio\SuperiorColliculusExperiments\Roller\PoolFigures" ); +% load( fullfile( fig_path, "MC, BC, BS, MCterminals pool.mat" ), "summMice" ); + +expMice = summMice{1}(3); +ovwtFlag = false; +% xLabels = ["Control", "C100", "F100"]; +xLabels = ["Control", "C30", "F30", "C100", "F100", ... + "C400", "F400", "C600", "Musc", "Musc" ]; +% xLabels = ["Control", "C30", "F30", "C100", "F100", ... +% "C400", "F400", "Dead", "PTX", "PTX" ]; +exp_subtype_flags = cellfun(@(x) contains( expMice.MiceNames, x ), ... + name_keys, fnOpts{:} ); +exclude_names = {'GADi13', 'GADi15', 'GADi53'}; +exclude_mice = contains(expMice.MiceNames, exclude_names); +exp_subtype_flags = cat( 2, exp_subtype_flags{:} ); +figs = gobjects( numel( exp_subtype ), 1 ); +% exp_type = join( ['MC-', expMice.ExperimentalGroup] ); +exp_type = expMice.ExperimentalGroup; +%% +for cest = 1:numel(exp_subtype) + cons_mice = exp_subtype_flags(:,cest) & ~exclude_mice; + exp_subtype_flags(:,cest) = exp_subtype_flags(:,cest) & ~exclude_mice; + if sum( cons_mice ) + + figs(cest) = figure( "Color", "w" ); + % t = createtiles( figs(cest), 2, 1 ); ax = nexttile(t); + t = createtiles( figs(cest), 1, 1 ); ax = nexttile(t); + aux = squeeze( mean( expMice.AmplitudeIndex(:,:, ... + cons_mice), 1, "omitmissing" ) )'; + boxchart( ax, aux, bxOpts{:} ); + ylabel( ax, 'Amplitude index' ); xticklabels( ax, xLabels ); + ylim(ax, [0,1]); cleanAxis(ax); %ax.XAxis.Visible = "off"; + p = arrayfun(@(x) signrank( aux(:,1), aux(:,x) ), 2:size(aux,2), ... + "ErrorHandler", @(s,a) nan(1) ); + mark_flag = p(:) < signTh; + text( ax, 2:size(aux,2), 1.15*max( aux(:,2:end), [], 1 ), ... + arrayfun(@(x) sprintf("$$p=%.3g$$", x), p(:) ), txOpts{:} ) + xticklabels( xLabels ); + + % ax = nexttile(t); + % aux = squeeze( mean( expMice.TrialProportions(:,:, ... + % cons_mice), 1, "omitmissing" ) )'; + % boxchart(ax, aux, bxOpts{:} ); + % ylabel( ax, 'Trial proportions' ) + % xticklabels( xLabels ); ylim([0,2]); cleanAxis( ax ); + % p = arrayfun(@(x) signrank( aux(:,1), aux(:,x) ), 2:size(aux,2), ... + % "ErrorHandler", @(s,a) nan(1) ); + % text(ax, 2:size(aux,2), 1.15*max( aux(:,2:end), [], 1 ), ... + % arrayfun(@(x) sprintf("$$p=%.3f$$", x), p(:) ), txOpts{:} ) + title(t, sprintf( "%s Area/%s", exp_type, exp_subtype{cest} ) ) + + % for cbp = 1:numel(bodypart_names) + % % fig = figure("Color", "w"); t2 = createtiles( fig, 2, 1 ); + % fig = figure("Color", "w"); t2 = createtiles( fig, 1, 1 ); + % ax = nexttile(t2); + % aux = squeeze( mean( expMice.PolygonUnfoldAmplIndx(:,:, ... + % cbp, cons_mice), 2, "omitmissing" ) )'; + % boxchart( ax, aux, bxOpts{:} ); + % ylabel( ax, 'Amplitude index' ); xticklabels( ax, xLabels ); + % ylim(ax, [0,1]); cleanAxis(ax); ax.XAxis.Visible = "off"; + % p = arrayfun(@(x) signrank( aux(:,1), aux(:,x) ), 2:size(aux,2), ... + % "ErrorHandler", @(s,a) nan(1) ); + % text( 2:size(aux,2), 1.15*max( aux(:,2:end), [], 1 ), ... + % arrayfun(@(x) sprintf("$$p=%.3f$$", x), p(:) ), txOpts{:} ) + + % ax = nexttile(t2); + % aux = squeeze( mean( expMice.PolygonUnfoldTrialProp(:,:, ... + % cbp, cons_mice), 2, "omitmissing" ) )'; + % boxchart(ax, aux, bxOpts{:} ); + % ylabel( ax, 'Trial proportions' ) + % xticklabels( xLabels ); ylim([0,2]); cleanAxis( ax ); + % p = arrayfun(@(x) signrank( aux(:,1), aux(:,x) ), 2:size(aux,2), ... + % "ErrorHandler", @(s,a) nan(1) ); + % text( 2:size(aux,2), 1.15*max( aux(:,2:end), [], 1 ), ... + % arrayfun(@(x) sprintf("$$p=%.3f$$", x), p(:) ), txOpts{:} ) + % title(t2, sprintf( "%s/%s", bodypart_names(cbp), exp_subtype{cest} ) ) + + % saveFigure( fig, fullfile( fig_path, join( [bodypart_names(cbp), ... + % exp_type, exp_subtype{cest}, "all mice pool" ] ) ), ... + % true, ovwtFlag ) + % saveFigure( fig, fullfile( fig_path, join( [bodypart_names(cbp), ... + % exp_type, exp_subtype{cest}, sum( cons_mice ) ] ) ), ... + % true, ovwtFlag ) + % end + end +end + +% arrayfun(@(f) saveFigure( figs(f), fullfile( fig_path, ... +% join( ["Areas", exp_type, exp_subtype{f}, "all mice pool"] ) ), true, ovwtFlag ), ... +% find( arrayfun(@(f) ~isa( f, 'matlab.graphics.GraphicsPlaceholder'), figs ) ) ); + +% arrayfun(@(f) saveFigure( figs(f), fullfile( fig_path, ... +% join( ["Areas", exp_type, exp_subtype{f}, ... +% sum( exp_subtype_flags(:,f) ) ] ) ), true, ovwtFlag ), ... +% find( arrayfun(@(f) ~isa( f, 'matlab.graphics.GraphicsPlaceholder'), figs ) ) ); \ No newline at end of file diff --git a/Emilio/jitt_reorganise_counts.m b/Emilio/jitt_reorganise_counts.m new file mode 100644 index 0000000..19aed14 --- /dev/null +++ b/Emilio/jitt_reorganise_counts.m @@ -0,0 +1,13 @@ +cfg_struct = configStructure; +cfg_struct.Viewing_window_s = [-0.3,0.2]; +[PSTHpupt, psthTx, n_trials] = getPSTH_perU_perT( ... + relativeSpkTmsStruct, cfg_struct); +n_conditions = numel(PSTHpupt); +n_elements = cellfun(@(x) numel(x), PSTHpupt); +condition_names = {'laser1ms','laser10ms','laser50ms',... + 'laser100ms','laser200ms','whisker'}; +for ccond = 1:n_conditions + [n_bins, n_neurons] = size(PSTHpupt{ccond},[2,3]); + + +end \ No newline at end of file diff --git a/Emilio/logreg.m b/Emilio/logreg.m new file mode 100644 index 0000000..28af697 --- /dev/null +++ b/Emilio/logreg.m @@ -0,0 +1,4 @@ +function y_hat = logreg(Xtrain, ytrain, Xtest) +mdl = lassoglm( Xtrain, ytrain, 'Distribution', 'binomial', 'Link', 'logit' ); +y_hat = predict(mdl, Xtest); +end \ No newline at end of file diff --git a/Emilio/mice_struct_to_table.m b/Emilio/mice_struct_to_table.m new file mode 100644 index 0000000..8020e8d --- /dev/null +++ b/Emilio/mice_struct_to_table.m @@ -0,0 +1,17 @@ +fnOpts = { 'UniformOutput', false }; +Ni = arrayfun(@(m) arrayfun(@(s) size( s.Intensities, 1 ), m.Sessions ), ... + mice, fnOpts{:} ); +Nr = sum( cat( 1, Ni{:} ) ); +hab_table = zeros( Nr, 12 ); +cr = 1; +for cm = 1:numel(mice) + for cs = 1:numel(mice(cm).Sessions) + Nism = size( mice(cm).Sessions(cs).Intensities, 1 ); + idxs = (0:Nism-1) + cr; + hab_table(idxs, 1:2) = repmat( [cm,cs], Nism, 1 ); + hab_table(idxs, 3:4) = [mice(cm).Sessions(cs).Intensities, ... + mice(cm).Sessions(cs).BehIndex]; + hab_table(idxs, 5:end) = mice(cm).Sessions(cs).MaxVals; + cr = cr + Nism; + end +end \ No newline at end of file diff --git a/Emilio/muscimol_analysis.m b/Emilio/muscimol_analysis.m new file mode 100644 index 0000000..0c1fecc --- /dev/null +++ b/Emilio/muscimol_analysis.m @@ -0,0 +1,28 @@ +fullName = @(x) string(fullfile(x.folder, x.name)); +fnOpts = {'UniformOutput', false}; +%% +expDir = "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch2_ephys\MC\WT13\211119_C"; +behDirs = dir(fullfile(expDir, "Beh*")); behDir = fullName(behDirs); +%% +ephDirs = dir(fullfile(expDir, "ephys_*")); ephDir = fullName(ephDirs); +condFiles = dir(fullfile(ephDir, "*analysis.mat")); +load(fullName(condFiles), "Conditions", "fs") +%% +ccSub = find(arrayfun(@(c) contains(c.name, ["Control Puff", "PTX","Death"], ... + "IgnoreCase", true), Conditions)); + +pairedStim = arrayfun(@(x) Conditions(1).Triggers(:,1) == ... + Conditions(x).Triggers(:,1)', ccSub, fnOpts{:}); +pairedStim = cellfun(@(x) any(x, 2), pairedStim, fnOpts{:}); +pairedStim = cat(2, pairedStim{:}); +consCondNames = arrayfun(@(x) string(x.name), Conditions(ccSub)); +%% +[behRes, behFigDir] = analyseBehaviour(behDir, 'PairedFlags', pairedStim, ... + 'ConditionsNames', cellstr(consCondNames)); +biFigPttrn = "BehIndex%s"; +biFigPttrn = sprintf(biFigPttrn, sprintf(" %s (%%.3f)", consCondNames)); +[pAreas, ~, behAreaFig] = createBehaviourIndex(behRes); +behRes = arrayfun(@(bs, ba) setfield(bs,'BehIndex', ba), behRes, pAreas); +set(behAreaFig, 'UserData', behRes) +biFN = sprintf(biFigPttrn, pAreas); +saveFigure(behAreaFig, fullfile(behFigDir, biFN), true); \ No newline at end of file diff --git a/Emilio/neg_log_lik_lnp.m b/Emilio/neg_log_lik_lnp.m new file mode 100644 index 0000000..63adce3 --- /dev/null +++ b/Emilio/neg_log_lik_lnp.m @@ -0,0 +1,5 @@ +function nllik = neg_log_lik_lnp(theta, X, y) +lambda = exp( X * theta ); +log_lik = y' * log( lambda ) - sum( lambda ); +nllik = -log_lik; +end \ No newline at end of file diff --git a/Emilio/parfor_tryout.m b/Emilio/parfor_tryout.m new file mode 100644 index 0000000..65c5112 --- /dev/null +++ b/Emilio/parfor_tryout.m @@ -0,0 +1,19 @@ +Npr = 1000; +for cl = 1:find(wruIdx) + auxSubs = arrayfun(@(x) randperm(NnzvPcl(cl)), 1:Npr, 'UniformOutput', false); + auxSpks = cellfun(@(s) round(cumsum(ISIVals{cl}(s))*fs), auxSubs, 'UniformOutput', false); + rndStack = getStacks(false, Conditions(chCond).Triggers, onOffStr,... + timeLapse, fs, fs, cat(2, spkSubs{cl}, auxSpks)); + rndStack(2,:,:) = []; + rst2 = arrayfun(@(x) getRasterFromStack(rndStack, ~delayFlags(:,x), ... + [false; true(Npr-2,1)], timeLapse, fs, true, true), ... + 1:size(delayFlags,2), 'UniformOutput', false); + [C, bE] = arrayfun(@(c) histcounts([rst2{1}{c,:}], 'BinWidth', ... + binSz, 'BinLimits', timeLapse), 1:size(rst2{1},1), ... + 'UniformOutput', false); + bE = bE{1}; Ctot = cat(1, C{:}); bC = mean([bE(1:end-1);bE(2:end)]); + P = arrayfun(@(x) fitdist(Ctot(2:end,x), 'Poisson'), 1:size(Ctot,2)); + lambdas = arrayfun(@(x) x.lambda, P); + PI = arrayfun(@(x) x.paramci, P, 'UniformOutput', false); PI = cat(2, PI{:}); + figure; plot(bC, Ctot') +end \ No newline at end of file diff --git a/Emilio/poolBehIndices.m b/Emilio/poolBehIndices.m new file mode 100644 index 0000000..65f95fe --- /dev/null +++ b/Emilio/poolBehIndices.m @@ -0,0 +1,285 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[A-Z][a-z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +behFF = "Beh V-0.45 - 0.50 s R25.00 - 350.00 ms"; +tblOpts = {'VariableNames', {'Conditions', 'Trial_and_Amp_Indices', 'PolygonUnfold','BaselineL2'}}; +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +tocol = @(x) x(:); +%% Assuming 1 level of animal organisation i.e. +% BatchX/FolderA/Animal001 +% BatchX/FolderB/Animal002 +batchDir = fullfile( "Z:\Emilio\SuperiorColliculusExperiments", ... + "Roller", "Mock" ); +%Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch15_ephys + +childFolders = dir(batchDir); + +pointFlag = arrayfun(@(x) any(strcmpi(x.name, {'.','..'})), childFolders); +fileFlag = ~[childFolders.isdir]'; +childFolders(pointFlag | fileFlag) = []; +animalFolders = arrayfun(@(d) recursiveFolderSearch(expandName(d), ... + rsOpts{:}), childFolders, fnOpts{:}); animalFolders = cat(1, animalFolders{:}); +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; +for cad = animalFolders(:)' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders); + sessOrgDirs(contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:})) = []; + behFigDir = arrayfun(@(d) recursiveFolderSearch(expandName(d), ... + behFF), childFolders, fnOpts{:}); behFigDir = cat(1, behFigDir{:}); + aiIdxFiles = arrayfun(@(d) dir(fullfile(d, "Amplitude index*.fig")), ... + behFigDir, fnOpts{:}); aiIdxFiles = cat(1, aiIdxFiles{:}); + if isempty(aiIdxFiles) + fprintf(1, 'No behaviour analysis done! Skipping %s!\n', curDir) + continue + end + aiIdxFig = arrayfun(@(x) openfig(expandName(x), 'invisible'), ... + aiIdxFiles); behRes = arrayfun(@(x) get(x, 'UserData'), ... + aiIdxFig, fnOpts{:}); arrayfun(@close, aiIdxFig) + condNames = cellfun(@(x) arrayfun(@(y) string(y.ConditionName), x), ... + behRes, fnOpts{:}); + behIdx = cellfun(@(x) arrayfun(@(y) [y.Trial_proportion, ... + y.Amplitude_index], x, fnOpts{:} ), behRes, fnOpts{:} ); + pol_unfold = cellfun(@(x) arrayfun(@(y) ... + [ reshape( [y.Results.MovProbability], [], 1 ), ... + reshape( [y.Results.AmplitudeIndex], [], 1 ) ], ... + x, fnOpts{:} ), behRes, fnOpts{:} ); + + % Assuming first condition as control!! + [~, mu_c, sig_c] = cellfun(@(c) arrayfun(@(bp) ... + zscore( bp.Baseline_L2 ), ... + c(1).Results, fnOpts{:} ), ... + behRes , fnOpts{:}); + + Nconds = cellfun(@numel, behRes ); + Nbr = numel( behRes ); + bDist = cell( Nbr, 1 ); + + for cc = 1:Nbr + for ccond = 1:Nconds(cc) + for cbp = 1:numel( behRes{cc}(ccond).Results ) + bDist{cc}(cbp, ccond) = fitdist( my_zscore( ... + behRes{cc}(ccond).Results(cbp).Baseline_L2, ... + mu_c{cc}{cbp}, sig_c{cc}{cbp} ), "Kernel", ... + "Kernel", "normal" ); + end + end + end + prmSubs = arrayfun(@(x) nchoosek(1:x,2), Nconds , fnOpts{:} ); + Ncombs = cellfun(@(pr) size( pr, 1 ), prmSubs ); + Nbs = cellfun(@(d) size( d, 1), bDist ); + tvd = cell( Nbr, 1); + for cc = 1:Nbr + if Nconds(cc) > 1 + tvd{cc} = zeros( Nbs(cc), Ncombs(cc) ); + for cr = 1:Ncombs(cc) + ps = prmSubs{cc}(cr,:); + for cbp = 1:Nbs(cc) + tvd{cc}(cbp, cr) = total_var_dist( bDist{cc}(cbp, ps) ); + end + end + else + fprintf(1, 'Unsure what to do\n') + end + end + brSz = cellfun(@numel, behRes); c = 1; Nbix = numel(brSz); + sessType = 'single'; + if Nbix == 1 + behIdx = behIdx{:}; + pol_unfold = pol_unfold{:}; + bDist = bDist{:}'; + dataTable = table( tocol( [condNames{:}] ), ... + cat( 1, behIdx{:} ), pol_unfold(:), bDist, tblOpts{:}); + elseif Nbix > 1 + % We need to check where are all of these different + % measurements are coming from. + sessType = 'multi'; + if numel(sessOrgDirs) == Nbix + % Same folders and measurements. Ideal situation for + % several measurements. + dataTable = table(condNames, behIdx, pol_unfold, bDist, tblOpts{:}, ... + 'RowNames', sessOrgDirs); + else + dataTable = table(condNames, behIdx, pol_unfold,bDist, tblOpts{:}); + end + end + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + end +end +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; +btchName = regexp( batchDir, 'Batch\d+','match' ); +behFP = fullfile( batchDir, btchName+"_BehaviourIndex.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +save(behFP, "mice", svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) +%{ +%% multiple +jittDist = makedist('Normal', 'mu', 0, 'sigma', 1/9); +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +habTable = arrayfun(@(m, f) {m.Sessions(f{:}).DataTable}, mice, habFlag, ... + fnOpts{:}); +pBehIdx = cellfun(@(x) cellfun(@(y) cell2mat(y.BehaviourIndices), x, ... + fnOpts{:}), habTable, fnOpts{:}); +Ncc = cellfun(@(x) cellfun(@(y) numel(y), x), pBehIdx, fnOpts{:}); +rSz = cellfun(@(x) max(cellfun(@(y) numel(y), x)), pBehIdx); +cSz = cellfun(@numel, pBehIdx); +resBehIdx = arrayfun(@(x,y) nan(x,y), rSz, cSz, fnOpts{:}); +resTable = cell(numel(mice), 1); Nm = numel(mice); +mNames = arrayfun(@(m) m.Name, mice); clrMap = roma(Nm); +habFig = figure('Name', 'Intensity v.s. index', 'Color', 'w'); +ax = axes('Parent', habFig, 'Color', 'none', 'Box', 'off', 'NextPlot', 'add'); +x = []; y = []; +for m = 1:Nm + mxSub = find(Ncc{m} == rSz(m), 1, "first"); + for ci = 1:cSz(m) + endS = numel(pBehIdx{m}{ci}); + resBehIdx{m}(1:endS,ci) = pBehIdx{m}{ci}; + end + resTable{m} = table(resBehIdx{m}, ... + 'RowNames', mice(m).Sessions(mxSub).DataTable.Row, ... + 'VariableNames', "BehaviourIndices"); + x = [x; reshape(ones(rSz(m), cSz(m)).*(1:rSz(m))', [], 1)]; + y = [y; resTable{m}.BehaviourIndices(:)]; + %scatter(ax, ones(cSz(m),rSz(m)).*(1:rSz(m)) + ... + scatter(ax, (1:rSz(m)) + random(jittDist, [1,rSz(m)]), ... + mean(resTable{m}.BehaviourIndices,2,'omitnan')', [], clrMap(m,:), ... + "filled", "MarkerFaceAlpha", 0.5) +end +xticks(ax, 1:max(rSz)); + +lgObj = legend(ax, mNames); +set(lgObj, "Box", 'off', 'Color', 'none', 'Location', 'best', 'AutoUpdate', 'off') + +%% single +singFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "single", ... + m.Sessions), mice, fnOpts{:}); +behTable = arrayfun(@(m, f) {m.Sessions(f{:}).DataTable}, mice, singFlag, ... + fnOpts{:}); behTable = arrayfun(@(t) cat(1, t{:}{:}), behTable, fnOpts{:}); +behTable = cat(1, behTable{:}); +ctrl = behTable{behTable.Conditions == "Control Puff", "BehaviourIndices"}; +ptx = behTable{behTable.Conditions == "PTX", "BehaviourIndices"}; +figure; scatter(ones(size(ptx, 1),2).*[1,2], [ctrl, ptx]) +hold on; plot(ones(2,size(ptx, 1)).*[1;2], [ctrl, ptx]', 'k:') +behTable = [behTable; mice(5).Sessions(2).DataTable] +ctrl = behTable{behTable.Conditions == "Control Puff", "BehaviourIndices"} +ptx = behTable{behTable.Conditions == "PTX", "BehaviourIndices"} +figure; scatter(ones(size(ptx, 1),2).*[1,2], [ctrl, ptx]) +hold on; plot(ones(2,size(ptx, 1)).*[1;2], [ctrl, ptx]', 'k:') +ptx = behTable{contains(behTable.Conditions, "PTX"), "BehaviourIndices"} +figure; scatter(ones(size(ptx, 1),2).*[1,2], [ctrl, ptx]) +xlim([0,3]) +xticks(1:2) +hold on; plot(ones(2,size(ptx, 1)).*[1;2], [ctrl, ptx]', 'k:') +[p, h] = ranksum(ctrl, ptx) +[p, h] = ranksum(ctrl(setdiff(1:6,3)), ptx(setdiff(1:6,3))) +koFlag = true(size(ctrl)); +koFlag(3) = false; +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag)) +[ctrl, ptx] +[ctrl, ptx, koFlag] +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag), "tail", "right") +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag), "tail", "left") +[p, h] = ranksum(ctrl, ptx, "tail", "left") +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag), "tail", "left") +ylim([0,1]) +ylabel('Behaviour index') +xticks(1:2) +xticklabels({'Control', 'PTX'}) +hold on; plot([1,2], max([ctrl, ptx], [], "all")*([1,1]+0.1), 'k') +text(1.5, max([ctrl, ptx],[], "all")*1.1, '\ast', "HorizontalAlignment", 'center', "VerticalAlignment", "bottom") +title(["PTX [60 \muM] in SC";"Significance: left tail"]) +configureFigureToPDF(gcf) +figure; scatter(ones(sum(koFlag),2).*[1,2], [ctrl(koFlag), ptx(koFlag)]) +hold on; plot([1,2], max([ctrl(koFlag), ptx(koFlag)], [], "all")*([1,1]+0.1), 'k') +hold on; plot(ones(2,sum(koFlag)).*[1;2], [ctrl(koFlag), ptx(koFlag)]', 'k:') +xlim([0,3]) +xticks(1:2) +xticklabels({'Control', 'PTX'}) +ylim([0,1]) +ylabel('Behaviour index') +title(["PTX [60 \muM] in SC";"Significance: left tail"]) +configureFigureToPDF(gcf) +saveFigure(gcf, fullfile("Z:\Emilio\SuperiorColliculusExperiments\Roller\GenFigures", "PTX effect"), true); +text(1.5, max([ctrl, ptx],[], "all")*1.1, '\ast', "HorizontalAlignment", 'center', "VerticalAlignment", "bottom") +%% +muscFlag = arrayfun(@(m) arrayfun(@(s) cellfun(@(c) ... + any(contains(c, 'musc', ctOpts{:}),2), s.DataTable.Conditions), ... + m.Sessions, fnOpts{:}), mice, fnOpts{:}); +sessFlag = cellfun(@(f) cellfun(@any, f), muscFlag, fnOpts{:}); +behTable2 = arrayfun(@(m, f1) m.Sessions(f1{:}).DataTable, ... + mice, sessFlag, fnOpts{:}); +multFlag = cellfun(@(t) ~isstring(t.Conditions), behTable2); +behTableM = cellfun(@(t, f, s) t(f{s},:), behTable2(multFlag), ... + muscFlag(multFlag), sessFlag(multFlag), fnOpts{:}); +behTableM = cellfun(@(t) table(t.Conditions{:}(:), t.BehaviourIndices{:}(:), ... + 'VariableNames', t.Properties.VariableNames), behTableM, fnOpts{:}); +behTable2 = cat(1, behTableM{:}, behTable2{~multFlag}); + +dateFlag = arrayfun(@(m) arrayfun(@(s) ~contains(fieldnames(s), 'Date'), ... + m.Sessions, fnOpts{:}), mice, fnOpts{:}); +mCatg = arrayfun(@(mn) categorical(regexp(mn.Name, '[A-Za-z]{2}', ... + 'match')), mice); +Nfn = cellfun(@(x) cellfun(@sum, x), dateFlag, fnOpts{:}); +values = arrayfun(@(m) arrayfun(@(s) struct2cell(s), m.Sessions, ... + fnOpts{:}), mice, fnOpts{:}); +%} \ No newline at end of file diff --git a/Emilio/poolEphBeh_recon_and_gof.m b/Emilio/poolEphBeh_recon_and_gof.m new file mode 100644 index 0000000..94026f4 --- /dev/null +++ b/Emilio/poolEphBeh_recon_and_gof.m @@ -0,0 +1,180 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +% my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +% getMI = @(x,d) diff(x, 1, d)./sum(x, d); +% total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +getRMSE = @( r, x, d ) sqrt( mean( ( r - x ).^2, d, "omitmissing" ) ); +tocol = @(x) x(:); +m = 1e-3; +exclude_names = {'GADi13', 'GADi15', 'GADi53'}; + +if ~strcmp( computer, 'PCWIN64') + home_path = '/gpfs/bwfor/home/hd/hd_hd/hd_bf154/'; + repo_paths = cellfun(@(x) char( fullfile( home_path, x) ), ... + {'NeuroNetzAnalysis', 'AuxiliaryFuncs', 'Scripts'}, fnOpts{:} ); + cellfun(@(x) addpath( genpath( x ) ), repo_paths ) + roller_path = "/mnt/sds-hd/sd19b001/Emilio/SuperiorColliculusExperiments/Roller"; +else + roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +end + +params = struct( 'relative_window', [-1,1]*800*m, 'delay_window', ... + [-1,1]*100*m, 'bin_size', 5*m, 'kfold', 20 ); +Nbins = diff(params.relative_window)/params.bin_size; +time_mdl = fit_poly( [1,Nbins], params.relative_window + ... + [1,-1]*(params.bin_size/2), 1 ); +tx = ( ( 1:Nbins)'.^[1,0] ) * time_mdl; +sponFlags = tx < 0; +laserFlags = my_xor(tx < [-0.1, 0.2]); +getTimeBoAT = @(s,f,p) reshape( s(f,:,:), size(s,2) * sum( f ), p.Ns ); + +struct_search = "MC"; % or "MC" "eOPN3" "ChR2" "BC" +selCondition = "freq"; % or "freq" "cont" Continuous or frquency +extra_id = "iRNs"; % "iRNs" "eRNs" "RNs" "" +mouse_line = "GADi"; % "GADi" "Rb" "vGlut" "" +verb = true; % verbose +iRN_mice = dir( fullfile( roller_path, "Batch*", struct_search, mouse_line+"*" ) ); +iRN_mice = iRN_mice( [iRN_mice.isdir] & ... + ~arrayfun(@(x) any( ismember({'.','..'}, x.name ) ), iRN_mice )' ); +animalFolders = arrayfun(@(f) string( expandName( f ) ), iRN_mice(:)); +exclude_flags = contains( animalFolders, exclude_names ); +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; lp_mu = []; lPSTH = []; +sessType = 'single'; +for cad = tocol(animalFolders(~exclude_flags))' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + fprintf(1, 'Mouse %s ', currMouse) + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders ); + sessOrgDirs( ~contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:}) ) = []; + if isempty(sessOrgDirs) + continue + end + data_path = curDir; + fprintf(1, ', Session %s\n', currSess ) + rfpStruct = dir( fullfile( data_path, "Regression " + ... + "CW-800.00-800.00ms DW-100.00-100.00 BZ5.00.mat" ) ); + if ~isempty(rfpStruct) + try + load( expandName( rfpStruct ), "mdlAll_ind", "DX", "params" ) + mdl = mdlAll_ind; + catch ME + display(ME.message) + continue + end + if isempty(DX) || (sum( isnan(mdl), "all" ) / numel(mdl) ) > 0.05 || ... + any( cellfun(@isempty, DX) ) || numel(DX)~= 4 + continue + end + else + fprintf(1, 'No Regression file...\n') + continue + end + %% + mdl_mu = squeeze( mean( mdl, 2 ) ); + y_trials = reshape( DX{1}, params.Nb, params.Nr, params.Ns ); + y_pred = DX{2} * mdl_mu; + y_ptrials = reshape( y_pred, params.Nb, params.Nr, params.Ns ); + + r_sq_trials = goodnessFit2( y_trials, y_ptrials, 1 ); + r_sq = goodnessFit2( DX{1}, y_pred, 1 ); + + y_trials_pre = getTimeBoAT(y_trials, sponFlags, params); + y_ptrials_pre = getTimeBoAT(y_ptrials, sponFlags, params); + r_sq_pre = goodnessFit2(y_trials_pre, y_ptrials_pre, 1); + + y_trials_post = getTimeBoAT( y_trials, ~sponFlags, params ); + y_ptrials_post = getTimeBoAT( y_ptrials, ~sponFlags, params ); + r_sq_post = goodnessFit2(y_trials_post, y_ptrials_post, 1); + + y_lpred = DX{3} * mdl_mu; + y_lptrials = reshape( y_lpred, params.Nb, [], params.Ns ); + y_ltrials = reshape( DX{4}, size( y_lptrials ) ); + + r_sq_l = goodnessFit2( DX{4}, y_lpred, 1 ); + + y_trials_pre = getTimeBoAT(y_ltrials, laserFlags, params); + y_ptrials_pre = getTimeBoAT(y_lptrials, laserFlags, params); + r_sq_lpre = goodnessFit2(y_trials_pre, y_ptrials_pre, 1); + + y_trials_post = getTimeBoAT( y_ltrials, ~laserFlags, params ); + y_ptrials_post = getTimeBoAT( y_lptrials, ~laserFlags, params ); + r_sq_lpost = goodnessFit2(y_trials_post, y_ptrials_post, 1); + + rmse_laser = getRMSE( DX{4}, y_lpred, 1 ); + + dataTable = table( {[r_sq;r_sq_pre;r_sq_post],[r_sq_l;r_sq_lpre;r_sq_lpost]}, ... + {r_sq_trials}, {params.fit_error}, ... + rmse_laser, 'VariableNames', {'R_2_p_L', 'R_squared_trials', ... + 'RMSE_c', 'RMSE_l'} ); + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + close all + end +end +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; + +behFP = fullfile( roller_path, struct_search + extra_id + ... + "_gof.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +save(behFP, "mice", svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) diff --git a/Emilio/poolEphBeh_reconstruction.m b/Emilio/poolEphBeh_reconstruction.m new file mode 100644 index 0000000..41a30d5 --- /dev/null +++ b/Emilio/poolEphBeh_reconstruction.m @@ -0,0 +1,149 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +% my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +% getMI = @(x,d) diff(x, 1, d)./sum(x, d); +% total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +getRMSE = @( r, x, d ) sqrt( mean( ( r - x ).^2, d, "omitmissing" ) ); +tocol = @(x) x(:); +m = 1e-3; +exclude_names = {'GADi13', 'GADi15', 'GADi53'}; + +params = struct( 'relative_window', [-1,1]*800*m, 'delay_window', ... + [-1,1]*100*m, 'bin_size', 5*m, 'kfold', 20 ); + +pc = parcluster('local'); +if ~strcmp( computer, 'PCWIN64') + home_path = '/gpfs/bwfor/home/hd/hd_hd/hd_bf154/'; + repo_paths = cellfun(@(x) char( fullfile( home_path, x) ), ... + {'NeuroNetzAnalysis', 'AuxiliaryFuncs', 'Scripts'}, fnOpts{:} ); + cellfun(@(x) addpath( genpath( x ) ), repo_paths ) + roller_path = "/mnt/sds-hd/sd19b001/Emilio/SuperiorColliculusExperiments/Roller"; +else + roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +end + +[~, ofgOpts] = checkSystem4Figures(); +ovwFlag = true; + +iRN_mice = dir( fullfile( roller_path, "Batch*", "MC", "GADi*" ) ); +animalFolders = arrayfun(@(f) string( expandName( f ) ), iRN_mice(:)); +exclude_flags = contains( animalFolders, exclude_names ); +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; lp_mu = []; lPSTH = []; +sessType = 'single'; +for cad = tocol(animalFolders(~exclude_flags))' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + fprintf(1, 'Mouse %s ', currMouse) + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders ); + sessOrgDirs( ~contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:}) ) = []; + if isempty(sessOrgDirs) + continue + end + data_path = curDir; + fprintf(1, ', Session %s\n', currSess ) + fig_path = dir( fullfile( data_path, 'ephys*', 'Fig*') ); + if isempty( fig_path ) + fig_path = data_path; + else + fig_path = expandName( fig_path ); + end + aiFN = fullfile( fig_path, 'Amplitude index model'); + if ~exist( [aiFN, '.fig'], 'file' ) || ovwFlag + try + [results, f] = AnBeh_Bypass(data_path, [25, 350]*m); + catch ME + fprintf(1, 'Regression ongoing...\n') + DX = cell(4,1); + try + parpool( pc ); + catch + end + % [~, ~, DX] = regressEphysVSBehaviour( data_path, params ); + if ~all( cellfun(@isempty, DX ) ) + [results, f] = AnBeh_Bypass(data_path, [25, 350]*m ); + else + display(ME.message) + continue + end + end + saveFigure( f, [aiFN, '.fig'], true, ovwFlag ) + else + f = openfig( [aiFN, '.fig'], ofgOpts{:} ); + results = get( f, 'UserData' ); + end + + dataTable = table( {results.AmplitudeIndex_pbp}, ... + results.AmplitudeIndex, results.AI_perCond(:)', ... + 'VariableNames', {'AI_pbp', 'AmplitudeIndex','Names'} ); + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + close all + end +end +close all +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; + +behFP = fullfile( roller_path, "MCiRNs_reconstruction_sm.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +save(behFP, "mice", svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) diff --git a/Emilio/poolEphBeh_regression.m b/Emilio/poolEphBeh_regression.m new file mode 100644 index 0000000..244a999 --- /dev/null +++ b/Emilio/poolEphBeh_regression.m @@ -0,0 +1,179 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +% my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +% getMI = @(x,d) diff(x, 1, d)./sum(x, d); +% total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +getRMSE = @( r, x, d ) sqrt( mean( ( r - x ).^2, d, "omitmissing" ) ); +tocol = @(x) x(:); +m = 1e-3; +exclude_names = {'GADi13', 'GADi15', 'GADi53'}; +%% +if ~strcmp( computer, 'PCWIN64') + home_path = '/gpfs/bwfor/home/hd/hd_hd/hd_bf154/'; + repo_paths = cellfun(@(x) char( fullfile( home_path, x) ), ... + {'NeuroNetzAnalysis', 'AuxiliaryFuncs', 'Scripts'}, fnOpts{:} ); + cellfun(@(x) addpath( genpath( x ) ), repo_paths ) + roller_path = "/mnt/sds-hd/sd19b001/Emilio/SuperiorColliculusExperiments/Roller"; +else + roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +end +%% +params = struct( 'relative_window', [-1,1]*800*m, 'delay_window', ... + [-1,1]*100*m, 'bin_size', 5*m, 'kfold', 20 ); +Nbins = diff(params.relative_window)/params.bin_size; +time_mdl = fit_poly( [1,Nbins], params.relative_window + ... + [1,-1]*(params.bin_size/2), 1 ); +tx = ( ( 1:Nbins)'.^[1,0] ) * time_mdl; +sponFlags = tx < 0; +getTimeBoAT = @(s,f,p) reshape( s(f,:,:), size(s,2) * sum( f ), p.Ns ); +%% +pc = parcluster('local'); + +try + parpool( pc ); +catch +end +%% +struct_search = "BC"; % or "MC" "eOPN3" "ChR2" "BC" +selCondition = "freq"; % or "freq" "cont" Continuous or frquency +extra_id = "iRNs"; % "iRNs" "eRNs" "RNs" "" +mouse_line = "GADi"; % "GADi" "Rb" "vGlut" "" +verb = true; % verbose +iRN_mice = dir( fullfile( roller_path, "Batch*", struct_search, mouse_line+"*" ) ); +iRN_mice = iRN_mice( [iRN_mice.isdir] & ... + ~arrayfun(@(x) any( ismember({'.','..'}, x.name ) ), iRN_mice )' ); +animalFolders = arrayfun(@(f) string( expandName( f ) ), iRN_mice(:)); +exclude_flags = contains( animalFolders, exclude_names ); +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; lp_mu = []; lPSTH = []; +sessType = 'single'; +for cad = tocol(animalFolders(~exclude_flags))' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + fprintf(1, 'Mouse %s ', currMouse) + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders ); + sessOrgDirs( ~contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:}) ) = []; + if isempty(sessOrgDirs) + continue + end + data_path = curDir; + fprintf(1, ', Session %s\n', currSess ) + try + [mdl, params, DX] = regressEphysVSBehaviour( data_path, params, ... + 'Condition', selCondition, 'Verbose', verb ); + catch ME + display(ME.message) + continue + end + if isempty(DX) || (sum( isnan(mdl), "all" ) / numel(mdl) ) > 0.05 || ... + any( cellfun(@isempty, DX) ) + continue + end + %% + mdl_mu = squeeze( mean( mdl, 2 ) ); + y_trials = reshape( DX{1}, params.Nb, params.Nr, params.Ns ); + y_pred = DX{2} * mdl_mu; + y_ptrials = reshape( y_pred, params.Nb, params.Nr, params.Ns ); + + r_sq_trials = goodnessFit2( y_trials, y_ptrials, 1 ); + r_sq = goodnessFit2( DX{1}, y_pred, 1 ); + + y_trials_pre = getTimeBoAT(y_trials, sponFlags, params); + y_ptrials_pre = getTimeBoAT(y_ptrials, sponFlags, params); + r_sq_pre = goodnessFit2(y_trials_pre, y_ptrials_pre, 1); + + y_trials_post = getTimeBoAT( y_trials, ~sponFlags, params ); + y_ptrials_post = getTimeBoAT( y_ptrials, ~sponFlags, params ); + r_sq_post = goodnessFit2(y_trials_post, y_ptrials_post, 1); + + y_lpred = DX{3} * mdl_mu; + y_lptrials = reshape( y_lpred, params.Nb, [], params.Ns ); + y_ltrials = reshape( DX{4}, size( y_lptrials ) ); + + r_sq_l = goodnessFit2( DX{4}, y_lpred, 1 ); + + y_trials_pre = getTimeBoAT(y_ltrials, sponFlags, params); + y_ptrials_pre = getTimeBoAT(y_lptrials, sponFlags, params); + r_sq_lpre = goodnessFit2(y_trials_pre, y_ptrials_pre, 1); + + y_trials_post = getTimeBoAT( y_ltrials, ~sponFlags, params ); + y_ptrials_post = getTimeBoAT( y_lptrials, ~sponFlags, params ); + r_sq_lpost = goodnessFit2(y_trials_post, y_ptrials_post, 1); + + rmse_laser = getRMSE( DX{4}, y_lpred, 1 ); + + dataTable = table( {[r_sq;r_sq_pre;r_sq_post],[r_sq_l;r_sq_lpre;r_sq_lpost]}, ... + {r_sq_trials}, {params.fit_error}, ... + rmse_laser, 'VariableNames', {'R_2_p_L', 'R_squared_trials', ... + 'RMSE_c', 'RMSE_l'} ); + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + close all + end +end +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; + +behFP = fullfile( roller_path, struct_search + extra_id + ... + "_reconstruction_sm.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +save(behFP, "mice", svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) diff --git a/Emilio/poolEphMI.m b/Emilio/poolEphMI.m new file mode 100644 index 0000000..f4733e8 --- /dev/null +++ b/Emilio/poolEphMI.m @@ -0,0 +1,233 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +getMI = @(x,d) diff(x, 1, d)./sum(x, d); +total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +tocol = @(x) x(:); +%% Assuming 1 level of animal organisation i.e. +% BatchX/FolderA/Animal001 +% BatchX/FolderB/Animal002 +batchDir = fullfile( "Z:\Emilio\SuperiorColliculusExperiments", ... + "Roller", "Batch17_ephys.MC"); +%Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch15_ephys + +childFolders = dir(batchDir); + +pointFlag = arrayfun(@(x) any(strcmpi(x.name, {'.','..'})), childFolders); +fileFlag = ~[childFolders.isdir]'; +childFolders(pointFlag | fileFlag) = []; +animalFolders = arrayfun(@(d) recursiveFolderSearch(expandName(d), ... + rsOpts{:}), childFolders, fnOpts{:}); animalFolders = cat(1, animalFolders{:}); +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; lp_mu = []; lPSTH = []; +var2save = {'mice', 'lp_mu', 'lPSTH'}; +for cad = tocol(animalFolders)' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders); + sessOrgDirs(contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:})) = []; + miFigDir = arrayfun(@(d) recursiveFolderSearch(expandName(d), ... + ephFF, 'SearchType', 'expression'), childFolders, fnOpts{:}); + miFigDir = cat(1, miFigDir{:}); + miIdxFiles = arrayfun(@(d) dir( fullfile( d, ... + "LogPSTH_Structure*.mat" ) ), miFigDir, fnOpts{:} ); + miIdxFiles = cat( 1, miIdxFiles{:} ); + if isempty(miIdxFiles) + fprintf(1, 'No ephys analysis done! Skipping %s!\n', curDir) + continue + end + % miIdxStr = arrayfun(@(x) load( expandName(x), 'logPSTH' ), miIdxFiles); + load( expandName(miIdxFiles), 'logPSTH' ); + lPSTH = cat( 1, lPSTH, {logPSTH.LogPSTH} ); + lp_mu = cat( 3, lp_mu, squeeze( mean( ... + logPSTH.LogPSTH(:,:,logPSTH.indexMIComparison) ) ) ); + muMI = getMI( lp_mu(:,:,end), 2 ); muMI(isnan( muMI )) = 0; + bmot_MI = mean( muMI( ~(logPSTH.TimeAxis < 5e-2) ) ); + sens_MI = mean( muMI( logPSTH.TimeAxis < 5e-2) ); + miVal = [sens_MI, bmot_MI]; + condNames = logPSTH.ConditionNames( logPSTH.indexMIComparison ); + condNames = join([condNames(1), "v", condNames(2)]); + + sessType = 'single'; + dataTable = table( condNames, miVal, tblOpts{:} ); + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + end +end +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; +btchName = regexp( batchDir, 'Batch\d+','match' ); +behFP = fullfile( batchDir, btchName+"_EphMI_sm.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +save(behFP, var2save{:}, svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) + +%% multiple +jittDist = makedist('Normal', 'mu', 0, 'sigma', 1/9); +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +habTable = arrayfun(@(m, f) {m.Sessions(f{:}).DataTable}, mice, habFlag, ... + fnOpts{:}); +pBehIdx = cellfun(@(x) cellfun(@(y) cell2mat(y.Trial_and_Amp_Indices{end}), x, ... + fnOpts{:}), habTable, fnOpts{:}); +Ncc = cellfun(@(x) cellfun(@(y) numel(y), x), pBehIdx, fnOpts{:}); +rSz = cellfun(@(x) max(cellfun(@(y) numel(y), x)), pBehIdx); +cSz = cellfun(@numel, pBehIdx); +resBehIdx = arrayfun(@(x,y) nan(x,y), rSz, cSz, fnOpts{:}); +resTable = cell(numel(mice), 1); Nm = numel(mice); +mNames = arrayfun(@(m) m.Name, mice); clrMap = roma(Nm); +habFig = figure('Name', 'Intensity v.s. index', 'Color', 'w'); +ax = axes('Parent', habFig, 'Color', 'none', 'Box', 'off', 'NextPlot', 'add'); +x = []; y = []; +for m = 1:Nm + mxSub = find(Ncc{m} == rSz(m), 1, "first"); + for ci = 1:cSz(m) + endS = numel(pBehIdx{m}{ci}); + resBehIdx{m}(1:endS,ci) = pBehIdx{m}{ci}; + end + resTable{m} = table(resBehIdx{m}, ... + 'RowNames', mice(m).Sessions(mxSub).DataTable.Row, ... + 'VariableNames', "BehaviourIndices"); + x = [x; reshape(ones(rSz(m), cSz(m)).*(1:rSz(m))', [], 1)]; + y = [y; resTable{m}.BehaviourIndices(:)]; + %scatter(ax, ones(cSz(m),rSz(m)).*(1:rSz(m)) + ... + scatter(ax, (1:rSz(m)) + random(jittDist, [1,rSz(m)]), ... + mean(resTable{m}.BehaviourIndices,2,'omitnan')', [], clrMap(m,:), ... + "filled", "MarkerFaceAlpha", 0.5) +end +xticks(ax, 1:max(rSz)); + +lgObj = legend(ax, mNames); +set(lgObj, "Box", 'off', 'Color', 'none', 'Location', 'best', 'AutoUpdate', 'off') +%{ +%% single +singFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "single", ... + m.Sessions), mice, fnOpts{:}); +behTable = arrayfun(@(m, f) {m.Sessions(f{:}).DataTable}, mice, singFlag, ... + fnOpts{:}); behTable = arrayfun(@(t) cat(1, t{:}{:}), behTable, fnOpts{:}); +behTable = cat(1, behTable{:}); +ctrl = behTable{behTable.Conditions == "Control Puff", "BehaviourIndices"}; +ptx = behTable{behTable.Conditions == "PTX", "BehaviourIndices"}; +figure; scatter(ones(size(ptx, 1),2).*[1,2], [ctrl, ptx]) +hold on; plot(ones(2,size(ptx, 1)).*[1;2], [ctrl, ptx]', 'k:') +behTable = [behTable; mice(5).Sessions(2).DataTable] +ctrl = behTable{behTable.Conditions == "Control Puff", "BehaviourIndices"} +ptx = behTable{behTable.Conditions == "PTX", "BehaviourIndices"} +figure; scatter(ones(size(ptx, 1),2).*[1,2], [ctrl, ptx]) +hold on; plot(ones(2,size(ptx, 1)).*[1;2], [ctrl, ptx]', 'k:') +ptx = behTable{contains(behTable.Conditions, "PTX"), "BehaviourIndices"} +figure; scatter(ones(size(ptx, 1),2).*[1,2], [ctrl, ptx]) +xlim([0,3]) +xticks(1:2) +hold on; plot(ones(2,size(ptx, 1)).*[1;2], [ctrl, ptx]', 'k:') +[p, h] = ranksum(ctrl, ptx) +[p, h] = ranksum(ctrl(setdiff(1:6,3)), ptx(setdiff(1:6,3))) +koFlag = true(size(ctrl)); +koFlag(3) = false; +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag)) +[ctrl, ptx] +[ctrl, ptx, koFlag] +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag), "tail", "right") +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag), "tail", "left") +[p, h] = ranksum(ctrl, ptx, "tail", "left") +[p, h] = ranksum(ctrl(koFlag), ptx(koFlag), "tail", "left") +ylim([0,1]) +ylabel('Behaviour index') +xticks(1:2) +xticklabels({'Control', 'PTX'}) +hold on; plot([1,2], max([ctrl, ptx], [], "all")*([1,1]+0.1), 'k') +text(1.5, max([ctrl, ptx],[], "all")*1.1, '\ast', "HorizontalAlignment", 'center', "VerticalAlignment", "bottom") +title(["PTX [60 \muM] in SC";"Significance: left tail"]) +configureFigureToPDF(gcf) +figure; scatter(ones(sum(koFlag),2).*[1,2], [ctrl(koFlag), ptx(koFlag)]) +hold on; plot([1,2], max([ctrl(koFlag), ptx(koFlag)], [], "all")*([1,1]+0.1), 'k') +hold on; plot(ones(2,sum(koFlag)).*[1;2], [ctrl(koFlag), ptx(koFlag)]', 'k:') +xlim([0,3]) +xticks(1:2) +xticklabels({'Control', 'PTX'}) +ylim([0,1]) +ylabel('Behaviour index') +title(["PTX [60 \muM] in SC";"Significance: left tail"]) +configureFigureToPDF(gcf) +saveFigure(gcf, fullfile("Z:\Emilio\SuperiorColliculusExperiments\Roller\GenFigures", "PTX effect"), true); +text(1.5, max([ctrl, ptx],[], "all")*1.1, '\ast', "HorizontalAlignment", 'center', "VerticalAlignment", "bottom") +%% +muscFlag = arrayfun(@(m) arrayfun(@(s) cellfun(@(c) ... + any(contains(c, 'musc', ctOpts{:}),2), s.DataTable.Conditions), ... + m.Sessions, fnOpts{:}), mice, fnOpts{:}); +sessFlag = cellfun(@(f) cellfun(@any, f), muscFlag, fnOpts{:}); +behTable2 = arrayfun(@(m, f1) m.Sessions(f1{:}).DataTable, ... + mice, sessFlag, fnOpts{:}); +multFlag = cellfun(@(t) ~isstring(t.Conditions), behTable2); +behTableM = cellfun(@(t, f, s) t(f{s},:), behTable2(multFlag), ... + muscFlag(multFlag), sessFlag(multFlag), fnOpts{:}); +behTableM = cellfun(@(t) table(t.Conditions{:}(:), t.BehaviourIndices{:}(:), ... + 'VariableNames', t.Properties.VariableNames), behTableM, fnOpts{:}); +behTable2 = cat(1, behTableM{:}, behTable2{~multFlag}); + +dateFlag = arrayfun(@(m) arrayfun(@(s) ~contains(fieldnames(s), 'Date'), ... + m.Sessions, fnOpts{:}), mice, fnOpts{:}); +mCatg = arrayfun(@(mn) categorical(regexp(mn.Name, '[A-Za-z]{2}', ... + 'match')), mice); +Nfn = cellfun(@(x) cellfun(@sum, x), dateFlag, fnOpts{:}); +values = arrayfun(@(m) arrayfun(@(s) struct2cell(s), m.Sessions, ... + fnOpts{:}), mice, fnOpts{:}); +%} \ No newline at end of file diff --git a/Emilio/poolEphMI_iRNs.m b/Emilio/poolEphMI_iRNs.m new file mode 100644 index 0000000..b28c167 --- /dev/null +++ b/Emilio/poolEphMI_iRNs.m @@ -0,0 +1,113 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +getMI = @(x,d) diff(x, 1, d)./sum(x, d); +total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +tocol = @(x) x(:); + +exclude_names = {'GADi13', 'GADi15', 'GADi53'}; + +iRN_mice = dir( "Z:\Emilio\SuperiorColliculusExperiments\Roller\Batch*\MC\GADi*" ); +animalFolders = arrayfun(@(f) string( expandName( f ) ), iRN_mice(:)); +exclude_flags = contains( animalFolders, exclude_names ); + +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; lp_mu = []; lPSTH = []; +for cad = tocol(animalFolders(~exclude_flags))' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders); + sessOrgDirs(contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:})) = []; + miFigDir = arrayfun(@(d) recursiveFolderSearch(expandName(d), ... + ephFF, 'SearchType', 'expression'), childFolders, fnOpts{:}); + miFigDir = cat(1, miFigDir{:}); + miIdxFiles = arrayfun(@(d) dir( fullfile( d, ... + "LogPSTH_Structure*.mat" ) ), miFigDir, fnOpts{:} ); + miIdxFiles = cat( 1, miIdxFiles{:} ); + if isempty(miIdxFiles) + fprintf(1, 'No ephys analysis done! Skipping %s!\n', curDir) + continue + end + % miIdxStr = arrayfun(@(x) load( expandName(x), 'logPSTH' ), miIdxFiles); + load( expandName(miIdxFiles), 'logPSTH' ); + lPSTH = cat( 1, lPSTH, {logPSTH.LogPSTH} ); + lp_mu = cat( 3, lp_mu, squeeze( mean( ... + logPSTH.LogPSTH(:,:,logPSTH.indexMIComparison) ) ) ); + muMI = getMI( lp_mu(:,:,end), 2 ); muMI(isnan( muMI )) = 0; + bmot_MI = mean( muMI( ~(logPSTH.TimeAxis < 5e-2) ) ); + sens_MI = mean( muMI( logPSTH.TimeAxis < 5e-2) ); + miVal = [sens_MI, bmot_MI]; + condNames = logPSTH.ConditionNames( logPSTH.indexMIComparison ); + condNames = join([condNames(1), "v", condNames(2)]); + + sessType = 'single'; + dataTable = table( condNames, miVal, tblOpts{:} ); + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + end +end +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; + +behFP = fullfile( "Z:\Emilio\SuperiorColliculusExperiments\Roller", "MCiRNs_EphMI_sm.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +% save(behFP, "mice", svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) diff --git a/Emilio/poolRespUnitProp.m b/Emilio/poolRespUnitProp.m new file mode 100644 index 0000000..39449d0 --- /dev/null +++ b/Emilio/poolRespUnitProp.m @@ -0,0 +1,151 @@ +%#ok<*AGROW,*SAGROW> +%% Auxiliary variables and functions +fnOpts = {'UniformOutput', false}; +expandName = @(x) fullfile(x.folder, x.name); +animalPattern = '[a-zA-Z]+\d{1,}'; +rsOpts = {animalPattern, 'SearchType', 'expression'}; +ctOpts = {'IgnoreCase', true}; +lsOpts = {'L\d+.\d+', 'match'}; +ephFF = 'Ephys VW(-?\d+\.\d+)-(\d+\.\d+) RW20.00-200.00 SW(-?\d+\.\d+)-(-?\d+\.\d+)'; +tblOpts = {'VariableNames', {'Conditions', 'MI'}}; +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); +getMI = @(x,d) diff(x, 1, d)./sum(x, d); +total_var_dist = @(dmat) integral( @(x) abs( pdf( dmat(1), x ) - pdf( dmat(2), x ) ), -5, 5 ); +tocol = @(x) x(:); +my_xor = @(x) xor( x(:,1), x(:,2) ); +m = 1e-3; +exclude_names = {'GADi13', 'GADi15', 'GADi53'}; + +params = struct( 'relative_window', [-1,1]*800*m, 'delay_window', ... + [-1,1]*100*m, 'bin_size', 5*m, 'kfold', 20 ); + +pc = parcluster('local'); +if ~strcmp( computer, 'PCWIN64') + home_path = '/gpfs/bwfor/home/hd/hd_hd/hd_bf154/'; + repo_paths = cellfun(@(x) char( fullfile( home_path, x) ), ... + {'NeuroNetzAnalysis', 'AuxiliaryFuncs', 'Scripts'}, fnOpts{:} ); + cellfun(@(x) addpath( genpath( x ) ), repo_paths ) + roller_path = "/mnt/sds-hd/sd19b001/Emilio/SuperiorColliculusExperiments/Roller"; +else + roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +end +try + parpool( pc ); +catch + fprintf(1, 'Parallel pool already running ;-)\n') +end + +iRN_mice = dir( fullfile( roller_path, "Batch*", "MC", "GADi*" ) ); +animalFolders = arrayfun(@(f) string( expandName( f ) ), iRN_mice(:)); +exclude_flags = contains( animalFolders, exclude_names ); +%% Looping animals +oldMouse = ""; +mc = 0; mice = []; lp_mu = []; lPSTH = []; +sessType = 'single'; +for cad = tocol(animalFolders(~exclude_flags))' + [structPath, currMouse] = fileparts(cad); + [~, structName] = fileparts(structPath); + if string(oldMouse) ~= string(currMouse) + oldMouse = currMouse; + mice = [mice; struct('Name', currMouse, 'Sessions',[], ... + 'Structure', structName)]; + mc = mc + 1; + sc = 0; oldSess = ""; oldDepth = ""; + end + fprintf(1, 'Mouse %s', currMouse) + sessDirs = getSubFolds(cad); + % Just date sessions + onlyDateSessFlag = arrayfun(@(x) string(regexp(x.name, '[0-9]{6}', ... + 'match')), sessDirs, fnOpts{:}); + sessDirs(cellfun(@isempty, onlyDateSessFlag)) = []; + for csd = sessDirs(:)' + curDir = expandName(csd); + sessDateDepth = regexp(csd.name, '(\d{6}).*_(\d{4})?', 'tokens', 'once'); + if ~isempty( sessDateDepth ) + currSess = sessDateDepth{1}; + if isempty( sessDateDepth{2} ) + depthSess = ''; + else + depthSess = sessDateDepth{2}; + end + else + currSess = regexp(csd.name, '(\d{6})', 'tokens', 'once'); + depthSess = ''; + if isempty(currSess) + fprintf( 1, '\n' ) + fprintf( 1, "Unable to get session date and depth\n" ); + fprintf( 1, "Skipping: %s %s\n", currMouse, csd.name ) + continue + end + end + fprintf(1, ', Session %s\n', currSess ) + childFolders = getSubFolds(curDir); + sessOrgDirs = arrayfun(@(d) string(d.name), childFolders ); + sessOrgDirs( ~contains(sessOrgDirs, {'behaviour', 'ephys', ... + 'figures', 'opto'}, ctOpts{:}) ) = []; + if isempty(sessOrgDirs) + continue + end + data_path = curDir; + + mapFile = dir( fullfile( curDir, "ephys*", "Results", "Map *.mat" ) ); + rstFile = dir( fullfile( curDir, "ephys*", "*RW20.00-200.00*.mat" ) ); + rstFile( ~contains({rstFile.name}, 'PuffAll (unfiltered)') ) = []; + if numel( mapFile ) ~= 1 + fprintf(1, '%s\ndoesn''t have result map... skipping...\n', curDir ) + continue + end + if numel( rstFile ) ~= 1 + fprintf(1, '%s\ndoesn''t have relative spikes... skipping...\n', curDir ) + continue + end + % load( expandName(mapFile), 'keyCell', 'resMap' ) + load( expandName(rstFile), 'relativeSpkTmsStruct' ) + Ncl = size( relativeSpkTmsStruct(1).SpikeTimes, 1 ); + Na = arrayfun(@(x) size( x.SpikeTimes, 2 ), relativeSpkTmsStruct); + respWins = [20, 50; 50, 200]*1e-3; + sponWins = -flip( respWins, 2 ) - 0.1; + + countSpks = @(win) arrayfun(@(c) arrayfun(@(t) ... + sum( my_xor( tocol(relativeSpkTmsStruct(1).SpikeTimes{c,t}) > ... + win ) ), 1:Na(1) ), (1:Ncl)', fnOpts{:} ); + rCounts = cellfun(@(x) cat( 1, x{:}), arrayfun(@(x) ... + countSpks(respWins(x,:)), 1:2, fnOpts{:} ), fnOpts{:} ); + sCounts = cellfun(@(x) cat( 1, x{:}), arrayfun(@(x) ... + countSpks(sponWins(x,:)), 1:2, fnOpts{:} ), fnOpts{:} ); + testPairedMedians = @(x,y) arrayfun(@(u) signrank( ... + tocol( x(u,:) ), tocol( y(u,:) ) ), (1:Ncl)' ) < 0.05; + h = cellfun( @(x,y) testPairedMedians(x,y), sCounts, rCounts, ... + fnOpts{:} ); h = cat( 2, h{:} ); + + dataTable = table( Ncl, Na(1), sum(h), sum(h)/Ncl, ... + 'VariableNames', ["NUnits", "NTrials", ... + "Modulated_sens_motr", "Proportion"] ); + if ( string(oldSess) ~= string(currSess) ) || ... + ( string(oldDepth) ~= string(depthSess) ) + oldSess = currSess; + oldDepth = depthSess; + auxStruct = struct('Date', currSess, ... + 'DataTable', dataTable, 'Type', sessType, ... + 'Depth', depthSess); + if ~isfield(mice, 'Sessions') + mice(mc).Sessions = auxStruct; + else + mice(mc).Sessions = [mice(mc).Sessions; auxStruct]; + end + sc = sc + 1; + end + clearvars rCounts sCounts h relativeSpkTmsStruct + end +end +mice( arrayfun(@(x) isempty(x.Sessions), mice) ) = []; + +behFP = fullfile( roller_path, "MCiRNs_respUnitProp.mat" ); +svOpts = {'-mat'}; +if exist(behFP, "file") + svOpts = {'-append'}; +end +save(behFP, "mice", svOpts{:}) +habFlag = arrayfun(@(m) arrayfun(@(s) string(s.Type) == "multi", ... + m.Sessions), mice, fnOpts{:}); +cat( 1, habFlag{:} ) diff --git a/Emilio/popPolygon.m b/Emilio/popPolygon.m new file mode 100644 index 0000000..70355ef --- /dev/null +++ b/Emilio/popPolygon.m @@ -0,0 +1,61 @@ +% iRNs +expMice = summMice{1}(3); +aux = expMice.PolygonUnfoldAmplIndx([1,5],:,:,cons_mice); +% cons_mice comes from the iegRNs_AmplitudeIndexPool.m script + +% eOPN3 +% expMice = summMice{4}(2); +% aux = expMice.PolygonUnfoldAmplIndx([1,8],:,:,:); +%% +vaxOpts = cellstr( ["HorizontalAlignment", "center", ... + "VerticalAlignment", "baseline", "Rotation"] ); +med_AI_pbp = squeeze( median( aux, 2, "omitmissing" ) ); +med_AI_all = median( med_AI_pbp, 3, "omitmissing" ); +clrMap = [0.15*ones(1,3); 0, 0.51, 1]; +Nb = 8; +bodypart_names = ["Stim-whisker mean", "Stim-whisker fan arc", ... + "Nonstim-whisker mean", "Nonstim-whisker fan arc", "Interwhisk arc", ... + "Symmetry", "Nose", "Roller speed"]; + +iqr_AI = quantile( med_AI_pbp, [1,3]/4, 3 ); + +[f, z_axis, poly_coords] = createPolarPlotPolygons( med_AI_all' ); +iqr_coords = iqr_AI .* reshape(z_axis,1,[],1); +[pchObj, ax] = plotPolygons( poly_coords, f, 'clrMap', clrMap ); + +z_rot = exp( 1i*pi/32 ); +% Dots by the polygon +arrayfun(@(c,z) line( real( poly_coords(:,c) * z)', ... + imag( poly_coords(:,c) * z )', 'LineStyle', 'none', ... + 'Marker', '.', 'Color', clrMap(c,:), 'MarkerSize', 20 ), ... + 1:2, [z_rot, z_rot'] ) +set( gca, 'Box', 'off', 'Color', 'none', "Visible", "off" ); +% Lines for IQR +% arrayfun(@(x,z) line( squeeze( real( iqr_coords(:,:,x) * z ) )', ... +% squeeze( imag( iqr_coords(:,:,x) * z ) )', 'LineWidth', 2, ... +% 'Color', clrMap(x,:) ), 1:2, [z_rot, z_rot'] ) +arrayfun(@(x,z) line( squeeze( real( iqr_coords(x,:,:) * z ) )', ... + squeeze( imag( iqr_coords(x,:,:) * z ) )', 'LineWidth', 2, ... + 'Color', clrMap(x,:) ), 1:2, [z_rot, z_rot'] ) +% text(ax, 0.25:0.25:1, zeros(1,4), string( ( 1:4 )'/4 ), ... +% "HorizontalAlignment", "left", "VerticalAlignment", "cap" ) +title('Population Polygons for MC\rightarrowiRNs' ) +legend( findobj( gca, 'Type', 'Patch' ), {'Laser OFF', 'Laser ON'}, ... + "Location", "best", "Color", "none", "Box", "off" ) +p = arrayfun(@(b) signrank( squeeze( med_AI_pbp(1,b,:) ), ... + squeeze( med_AI_pbp(2,b,:) ) ), 1:8 ); +% arrayfun(@(v, y) text( real( 1.25*poly_coords(1,v) ), ... +% imag( 1.25*poly_coords(1,v) ), repmat( '\ast', 1, sum( p(v) < ... +% [0.05, 0.01, 0.001] ) ), "HorizontalAlignment", "center", ... +% "Rotation", y, "VerticalAlignment", "baseline"), 1:8, ... +% (180*angle( transp(z_axis) )/pi) - 90 ); +arrayfun(@(v, y) text( real( 1.25 * max( poly_coords(v,:) ) ), ... + imag( 1.25 * max( poly_coords(v,:) ) ), sprintf("$p=%.3g$", p(v) ), ... + "HorizontalAlignment", "center", "Rotation", y, ... + "VerticalAlignment", "baseline", "Interpreter", "latex"), 1:8, ... + (180*angle( transp(z_axis) )/pi) - 90 ); + + +arrayfun(@(v,b,y) text( real( z_axis(v) ), ... + imag( z_axis(v) ), b, vaxOpts{:}, y ), 1:8, bodypart_names, ... + (180*angle( transp(z_axis) )/pi) - 90 ) \ No newline at end of file diff --git a/Emilio/remove_artifact.m b/Emilio/remove_artifact.m new file mode 100644 index 0000000..707dd41 --- /dev/null +++ b/Emilio/remove_artifact.m @@ -0,0 +1,19 @@ +trig_samples = 5; +Nts = 2*trig_samples + 1; +trig_offset_win = (-trig_samples:trig_samples); +random_triggers = sort( randsample(length(laser_triggers), samples) ); +for cchan = 1:64 + for crt = 1:length(laser_triggers) + artif_win = laser_triggers(crt) + trig_offset_win; + segm = double( data( cchan, artif_win ) ); + correction = segm(1) * ((Nts:-1:1)/(Nts+1)) + ... + segm(end) * ((1:Nts)/(Nts+1)) + ... + rand(1, Nts)*5 - 2.5; + + artif_diff = (correction - segm).^2; + corr_fin = (1 - artif_diff/max(artif_diff)).^3; + segm2 = segm.*corr_fin + (1-corr_fin).*correction; + segm = int16(round(segm2)); + data(cchan, artif_win) = segm; + end +end \ No newline at end of file diff --git a/GatherAI_reconstruction.m b/GatherAI_reconstruction.m new file mode 100644 index 0000000..b8abb14 --- /dev/null +++ b/GatherAI_reconstruction.m @@ -0,0 +1,15 @@ +Nm = numel(mice); +Ns = arrayfun(@(m) numel( m.Sessions ), mice ); +aiPop = zeros( sum( Ns ), 4 ); +aiPbp = zeros( sum( Ns ), 8, 2 ); +aiPbp2 = zeros( 8, 2, sum( Ns ) ); +cr = 1; +for cm = 1:Nm + for cs = 1:Ns(cm) + dt = mice(cm).Sessions(cs).DataTable; + aiPop(cr,:) = [cm, cs, dt.AmplitudeIndex]; + aiPbp(cr,:,:) = reshape( dt.AI_pbp{:}, 1, [], 2 ); + aiPbp2(:,:,cr) = dt.AI_pbp{:}; + cr = cr + 1; + end +end \ No newline at end of file diff --git a/James/BehaviourAnalysis_James.m b/James/BehaviourAnalysis_James.m new file mode 100644 index 0000000..5e9cd07 --- /dev/null +++ b/James/BehaviourAnalysis_James.m @@ -0,0 +1,455 @@ +%% Analysing behaviour alone + +%roller_path = "Z:\Emilio\SuperiorColliculusExperiments\Roller"; +% exp_path = ... +% fullfile( roller_path, "Batch2_ephys/MC/GADi18/211205_C_2450" ); +exp_path = fullfile( "Z:\James\Learning Experiments\28-11-24_AM\m1" ); +% exp_path = ... +% fullfile( roller_path, "behavior/" ); +% Figure overwrite flag +fowFlag = false; +% Annonymus function +expandPath = @(x) fullfile( x.folder, x.name); +% Milli factor +m = 1e-3; +% Looks in the experiment path for objects called ephys* (* is a wild card) +eph_path = dir( fullfile( exp_path, "ephys*" ) ); +% Delete everything that is not a folder +eph_path( ~[eph_path.isdir] ) = []; +% Looking folder 'Behaviour' +beh_path = fullfile( exp_path, "Behaviour" ); +% If the ephys path is empty, look for *analysis.mat file in the behaviour +% folder. +if ~isempty( eph_path ) + eph_path = expandPath( eph_path ); + figure_path = fullfile( eph_path, "Figures" ); + af_path = dir( fullfile( eph_path , "*analysis.mat" ) ); + af_path = expandPath( af_path ); +elseif exist( beh_path, "dir" ) + af_path = expandPath( dir( fullfile( beh_path, "*analysis.mat") ) ); + figure_path = fullfile( beh_path, "Figures" ); +else + % If there is no organisation in the folders, look for the file in the + % 'root' folder a.k.a. experiment folder. Then give up. + beh_path = exp_path; + af_path = expandPath( dir( fullfile( beh_path, "*analysis.mat") ) ); + figure_path = fullfile( beh_path, "Figures" ); +end + +[~, af_name] = fileparts( af_path ); +expName = extractBefore(af_name, "analysis"); +load( af_path, "Conditions", "fs") + +fnOpts = {'UniformOutput', false}; +axOpts = {'Box','off','Color','none'}; +lgOpts = cat( 2, axOpts{1:2}, {'Location','best'} ); + +open Conditions +ldFlag = false; +try + load( expandPath( dir( fullfile( beh_path, "RollerSpeed*.mat" ) ) ), "fr") +catch + ldFlag = true; +end + +%% Run independently +% User input!! +consCond = 1; +Nccond = length( consCond ); +%prmSubs = nchoosek( 1:Nccond, 2 ); + +% pairedStimFlags = arrayfun(@(c) any( ... +% Conditions(1).Triggers(:,1) == ... +% reshape( Conditions(c).Triggers(:,1), 1, [] ), 2 ), consCond, fnOpts{:} ); +% pairedStimFlags = cat( 2, pairedStimFlags{:} ); + +consCondNames = string( { Conditions( consCond ).name } ); + +% [behRes, behFig_path, behData, aInfo] = analyseBehaviour( beh_path, ... +% "ConditionsNames", cellstr( consCondNames ), ... +% "PairedFlags", pairedStimFlags, ... +% "FigureDirectory", figure_path, ... +% "ResponseWindow", [25, 350] * m, ... +% "ViewingWindow", [-450, 500] * m, ... +% "figOverWrite", fowFlag ); +[behRes, behFig_path, behData, aInfo] = analyseBehaviour( beh_path, ... + "ConditionsNames", cellstr( consCondNames ), ... + "FigureDirectory", figure_path, ... + "ResponseWindow", [25, 350] * m, ... + "ViewingWindow", [-450, 500] * m, ... + "figOverWrite", fowFlag ); + +if ldFlag + load( expandPath( dir( fullfile( beh_path, "RollerSpeed*.mat" ) ) ), "fr") +end +[Ns, Nt, Nb] = size( behData.Data ); + +vwin = sscanf( aInfo.VieWin, "V%f - %f s")'; +mdlt = fit_poly( [1, Ns], vwin + [1,-1] * (1/(2 * fr) ), 1 ); +txb = ( (1:Ns)'.^[1,0] ) * mdlt; +behNames = string( { behRes(1).Results.BehSigName } ); + +%% Normalised amplitud by absolute maximum +rollYL = ""; +rsFlag = false; +if contains( behNames, "Roller speed", "IgnoreCase", true) + rollYL = "Roller speed [cm/s]"; + rsFlag = true; +end +yLabels = [repmat("Angle [°]", 1, Nb-rsFlag), rollYL]; +sym_flag = contains( behNames, "symmetry", "IgnoreCase", true ); +yLabels(sym_flag) = "Symmetry [a.u.]"; +yLabels(~strlength(yLabels)) = []; +cbLabels = strings(Nb, 2); +cbLabels([1,3],:) = repmat(["Retract", "Protract"],2,1); +cbLabels([2,4,5],:) = repmat(["Closed", "Opened"],3,1); +cbLabels(6,:) = ["Away", "Puff"]; +cbLabels(7,:) = ["Puff", "Away"]; +cbLabels(8,:) = ["Backward", "Forward"]; +screen_size = get(0, 'ScreenSize' ); +pxHeight = screen_size(4)*0.7; +lowBound = screen_size(4)*1/5; + +possCols = [2,3,5]; +Ncols = possCols( find( mod( Nb, possCols ) == 0, 1, 'first' ) ); +if isempty( Ncols ) + Ncols = 2; +end +Nrows = ceil( Nb / Ncols ); + +% newAx = @(f) subplot( Nrows, Ncols, ix, "NextPlot", "add", "Parent", f ); + +% createtiles = @(f) tiledlayout( f, Nrows, Ncols, ... + % 'TileSpacing', 'Compact', 'Padding', 'tight'); + +isendrow = @(ix) ( (ix/Ncols) + 1) > Nrows; + +newFigure = @(x,y,fn) figure( "Color", "w", "Position", ... + [x, y, pxHeight/sqrt(2), pxHeight], "Name", fn ); + +fig = newFigure(0, lowBound, ""); + +t = createtiles( fig, Nrows, Ncols ); +for cbi = 1:Nb + ax = nexttile(t); + auxStack = squeeze( behData.Data(:,:,cbi) )'; + if cbi ~= 6 + auxStack = ( auxStack - median( auxStack, 2) ); + auxStack = auxStack ./ max( abs( auxStack ), [], 2 ); + end + imagesc( ax, txb*1e3, [], auxStack ); xline(ax, 0, 'k'); + xline( ax, [20, 120], 'LineWidth', 1, 'Color', 'b') + title( ax, behNames(cbi) ) + if mod( cbi, Ncols ) == 1 + ylabel(ax, 'Trials'); + else + ax.YAxis.Visible = 'off'; + end + if isendrow( cbi ) + xlabel(ax, 'Time [ms]'); + else + ax.XAxis.Visible = 'off'; + end + set( ax, axOpts{:} ) + + cb = colorbar(ax, "Box", "off", "Location", "west"); + cb.Ticks = [min(auxStack(:)), max(auxStack(:))] * 0.85; + cb.Label.String = yLabels(cbi); + cb.TickLabels = cellstr(cbLabels(cbi,:)); + cb.TickDirection = "none"; +end +axis( findobj( fig, "Type", "Axes" ), ... + [1e3*txb([1,end])', [1,Nt] + [-1,1]*(1/2)] ) +%cb.TickLabels = {'Backward', 'Forward'}; +linkaxes( findobj(fig, "Type", "Axes"), "xy") + +saveFigure(fig, fullfile( behFig_path, ... + "All trials all body parts normalised" ), true, fowFlag) + +clearvars auxStack + +%% L-norms and derivative +my_zscore = @(x, m, s) ( x - m ) ./ ( s .* (s~=0) + 1 .* (s==0) ); + +respWin = sscanf( aInfo.Evoked, "R%f - %f ms")' * 1e-3; +% respWin = [30, 400]*1e-3; +sponWin = -flip(respWin); +n = getHesseLineForm([1,0]); + +% Spontaneous window +sponFlag = txb > sponWin; +sponFlag = xor( sponFlag(:,1), sponFlag(:,2) ); + +% Responsive window +respWin_aux = respWin; +if respWin(1) < 0.12 + respWin_aux = respWin + 0.1; +end + +if respWin_aux(2) > vwin(2) + respWin_aux(2) = vwin(2); +end +respWin = [repmat(respWin_aux,2,1); repmat( respWin, Nb-2, 1)]; + +evokFlags = arrayfun(@(x) txb > respWin(x,:), 1:Nb, fnOpts{:} ); +evokFlags = cellfun(@(x) xor(x(:,1), x(:,2) ), evokFlags, fnOpts{:} ); +evokFlags = cat( 2, evokFlags{:} ); + +myNorm = @(x, l) vecnorm(x, l, 1); +funcs = {@(x) x, @(x) diff(x, 1, 1) }; +app = [ repmat("", 1,Nb); repmat( "diff", 1, Nb) ]; + +Nfgs = numel(funcs); +figs = gobjects(Nfgs, 2); + +for l = [1, 2, inf] + + for cf = 1:Nfgs + figs(cf, 1) = newFigure(0, lowBound, ""); + %figure( "Color", "w", "Position", ... + % [0, 20, pxHeight/sqrt(2), pxHeight] ); + figs(cf, 2) = newFigure(pxHeight/sqrt(2), lowBound, "");... figure( "Color", "w", "Position", ... + %[pxHeight/sqrt(2), 20, pxHeight/sqrt(2), pxHeight] ); + t1 = createtiles( figs(cf, 1) ); + t2 = createtiles( figs(cf, 2) ); + for cb = 1:Nb + + ax = nexttile(t1); + if cb == 1 + ylabel(ax, 'Evoked') + elseif cb == Nb + xlabel(ax, 'Spontaneous') + lgObj = legend( ax, scObj, consCondNames, lgOpts{:}, ... + "AutoUpdate", "off" ); + end + + aux_x = myNorm( funcs{cf}(behData.Data( sponFlag, :, cb ) ), l ); + aux_y = myNorm( funcs{cf}( ... + behData.Data( evokFlags(:, cb), :, cb ) ), l ); + + scObj = arrayfun(@(c) line(ax, aux_x(pairedStimFlags(:,c)), ... + aux_y(pairedStimFlags(:,c)), "LineStyle", "none", ... + "Marker", "." ), 1:Nccond); + + title(ax, join( [sprintf("L%d", l), behNames(cb), ... + app(cf,cb)] ) ); + set( get(ax, "XAxis"), "Scale", "log"); + set( get(ax, "YAxis"), "Scale", "log") + line(ax, xlim(ax), xlim(ax), "LineStyle", "--", ... + "Color", 0.45*ones(1,3) ); + xticklabels( ax, xticks(ax) ); + yticklabels( ax, yticks(ax) ); + % text( ax, aux_x, aux_y, num2str( (1:Nt)' ), ... + % 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle') + set(ax, axOpts{:}, "XGrid", "on", "YGrid", "on") + Dyx = [aux_x(:), aux_y(:)] * n; + % [~, d_centre, d_scale] = zscore( double( Dyx(pairedStimFlags(:,1)) ) ); + + ax = nexttile(t2); + % boxchart(ax, pairedStimFlags * (1:Nccond)', Dyx, "Notch", "on" ) + trFlag = any( pairedStimFlags, 2 ); + boxchart( ax, pairedStimFlags(trFlag,:) * (1:Nccond)', ... + Dyx(trFlag), "Notch", "on", "JitterOutliers", "on", ... + "MarkerStyle", "." ) + % yyaxis(ax, "right"); line( ax, pairedStimFlags * (1:Nccond)', ... + % my_zscore(Dyx, d_centre, d_scale), "LineStyle", "none") + % yyaxis(ax, "left"); + yline( ax, 0, 'k' ) + title(ax, join( [sprintf("L%d", l), ... + behNames(cb), app(cf,cb)] ) ); + set( ax, axOpts{:} ); % set( ax.YAxis, "Scale", "log" ) + xticks(ax, 1:Nccond ); + if isendrow( cb ) + xticklabels( ax, consCondNames ) + else + ax.XAxis.Visible = 'off'; + end + + end + saveFigure( figs(cf, 1), fullfile(behFig_path, ... + join([sprintf("L%d norm", l), app(cf,1)]) ), true, fowFlag ) + + saveFigure( figs(cf, 2), fullfile(behFig_path, ... + regexprep( join( [sprintf( "L%d norm", l ), app(cf,2), ... + "boxplots"] ), ' +', ' ' ) ), true, fowFlag ) + end + clearvars aux_* ax figs +end + +%% Weigthed mean +sponWeight = (1:sum(sponFlag))/sum(1:sum(sponFlag)); +ln1 = log10( 1:sum(evokFlags(:,1)) ); +ln2 = sum( evokFlags(:,1) ):-1:1; +evokWeight = ln1 .* ln2; evokWeight = evokWeight / sum( evokWeight ); + +clrMap = lines(Nccond); + +xPos = (0:2)*pxHeight/sqrt(2); +Na = sum( pairedStimFlags ); +figs = gobjects( 3, 1 ); +ts = figs; +figNames = ["Weighted mean"; "Line distance boxplots"; + "Vector magnitude boxplots"]; + +for cf = 1:numel(figs) + figs(cf) = newFigure( xPos(cf), lowBound, figNames(cf) ); + ts(cf) = createtiles( figs( cf ) ); +end + + +for cb = 1:Nb + w_smu = reshape( sponWeight * behData.Data(sponFlag,:,cb), [], 1 ); + + w_emu = reshape( evokWeight * behData.Data( ... + evokFlags(:,cb), :, cb ), [], 1 ); + + + ax = nexttile( ts(1) ); set(ax, 'NextPlot', 'add' ); + scObj = arrayfun(@(c) scatter(ax, w_smu(pairedStimFlags(:,c)), ... + w_emu(pairedStimFlags(:,c)), '.', "MarkerEdgeColor", clrMap(c,:) ), ... + 1:Nccond); + + if cb == Nb + xlabel( ax, 'Spontaneous', 'FontSize', 8 ); + legend( ax, scObj, consCondNames, lgOpts{:}, "AutoUpdate", "off"); + elseif cb == 1 + ylabel( ax, 'Evoked', 'FontSize', 8 ); + end + + title(ax, behNames(cb) ); + set( ax, axOpts{:}, "XAxisLocation", "origin", ... + "YAxisLocation", "origin" ); grid( ax, "on" ); %axis( ax, 'square' ) + line(ax, xlim(ax), xlim(ax), 'LineStyle', '--', 'Color', 0.45*ones(1,3)) + + ax = nexttile( ts(2) ); set(ax, 'NextPlot', 'add' ); + + bxObj = boxchart(ax, pairedStimFlags(trFlag,:) * (1:Nccond)', ... + [w_smu(trFlag), w_emu(trFlag)] * n, ... + "Notch", "on", "JitterOutlier", "on", "MarkerStyle", ".", ... + "Boxfacecolor", "k", "Markercolor", "k" ); + + if cb == Nb + legend( ax, bxObj, '$\vec{x} \cdot n + d$', ... + 'Interpreter' ,'latex' , lgOpts{:}, "AutoUpdate", "off" ); + elseif cb == 1 + ylabel( ax, 'Distance from line' ) + end + + xticks( ax, 1:Nccond ); + if isendrow(cb) + xticklabels( ax, consCondNames ) + else + ax.XAxis.Visible = 'off'; + end + + title(ax, behNames(cb) ); + set( ax, axOpts{:} ); yline( ax, 0, 'Color', 0.75*ones(1,3), ... + 'LineWidth', 1/3); + + ax = nexttile( ts(3) ); set(ax, 'NextPlot', 'add' ); + bxObj = boxchart(ax, pairedStimFlags(trFlag,:) * (1:Nccond)', ... + vecnorm( [w_smu(trFlag), w_emu(trFlag)], 2, 2 ), ... + "Notch", "on", "JitterOutlier", "on", "MarkerStyle", "." ); + if cb == Nb + legend( ax, bxObj, 'L-2 norm', ... + lgOpts{:}, "AutoUpdate", "off", "interpreter", "latex" ); + elseif cb == 1 + ylabel( ax, 'Distance from origin' ) + end + + xticks( ax, 1:Nccond ); + if isendrow(cb) + xticklabels( ax, consCondNames ) + else + ax.XAxis.Visible = 'off'; + end + + title(ax, behNames(cb) ); %axis( ax, 'square' ) + set( ax, axOpts{:} ); + + for cc = 1:Nccond + behRes(cc).Results(cb).Puff_Effect = ... + [w_smu( pairedStimFlags(:,cc) ), ... + w_emu( pairedStimFlags(:,cc) )] * n; + behRes(cc).Results(cb).Baseline_L2 = ... + vecnorm( [w_smu( pairedStimFlags(:,cc) ), ... + w_emu( pairedStimFlags(:,cc) )], 2, 2); + end +end + +wmFigNames = ["Weighted mean scatter"; ... + "Line distance boxplots"; ... + "Origin distance"]; + +arrayfun(@(x, f) saveFigure( x, fullfile( behFig_path, f ), true, fowFlag), ... + figs(:), wmFigNames(:)) + +clearvars ax figs + +%% Amplitude index and trial proportion + +if ~exist( "fr", "var" ) && ldFlag + load( expandPath( dir( fullfile( beh_path, "RollerSpeed*.mat" ) ) ), "fr") + ldFlag = false; +end + +[pAreas, ~, behAreaFig] = createBehaviourIndex(behRes); +behMeasures = string({behAreaFig.Name}); +biFigPttrn = behMeasures+"%s"; +biFigPttrn = arrayfun(@(s) sprintf(s, sprintf(" %s (%%.3f)", ... + consCondNames ) ), biFigPttrn ); + +for it = 1:numel(behMeasures) + behRes = arrayfun(@(bs, ba) setfield( bs, ... + strrep( behMeasures(it), " ", "_" ), ba), behRes(:), pAreas(:,it) ); +end + +arrayfun(@(f) set( f, 'UserData', behRes ), behAreaFig ); + +biFN = arrayfun(@(s) sprintf( biFigPttrn(s), pAreas(:,s) ), 1:numel(behMeasures) ); + +arrayfun(@(f, fn) saveFigure(f, fullfile(behFig_path, fn), true, fowFlag), ... + behAreaFig(:), biFN(:) ); + + + +%% Count figure +trMvFlag = arrayfun(@(cr) behRes(1).Results(cr).MovStrucure.MovmentFlags, ... + 1:size(behRes(1).Results,2), fnOpts{:}); trMvFlag = cat(3, trMvFlag{:}); +BIscaleMat = sum(trMvFlag,3); +BIscale = arrayfun(@(cc) BIscaleMat(pairedStimFlags(:,cc), cc), 1:Nccond, ... + fnOpts{:}); +hstOpts = {'BinMethod', 'integers', 'BinLimits', [0,Nb] + [-1,1]/2}; +[hg, hg_bin] = cellfun(@(c) histcounts(c, hstOpts{:}), ... + BIscale, fnOpts{:}); +hg = cat(1, hg{:}); hg_bin = cat(1, hg_bin{:}); + +% [p_amp, h_amp] = ranksum(cat(1, zamp{1,:}), cat(1, zamp{2,:})); + +clrMap = lines(Nccond); +countFig = figure; ax(1) = subplot(10,1,1:8); +bar(ax(1), (0:Nb)', (hg./sum(hg,2))', 'EdgeColor', 'none'); hold on; +poaDist = cellfun(@(bi) fitdist(bi,"Poisson"), BIscale); +ylim(ax(1), [0,1]); set(ax(1), axOpts{:}); +legend(ax(1), consCondNames, 'AutoUpdate','off', lgOpts{:}) +lmbdaHeight = 0.95-(0.15/Nccond)*(0:Nccond-1); +arrayfun(@(pd) scatter(ax(1), poaDist(pd).lambda, lmbdaHeight(pd), '|',... + 'MarkerEdgeColor', clrMap(pd,:)), 1:Nccond) +arrayfun(@(pd) line(ax(1), paramci(poaDist(pd)), ... + lmbdaHeight([pd,pd]), 'Color', clrMap(pd,:), ... + 'Marker', '|'), 1:Nccond) +[p, chiVal] = arrayfun(@(ps) chi2test(hg(prmSubs(ps,:), :)), ... + 1:size(prmSubs,1)); +ax(2) = subplot(10,1,9:10); +signBeh = arrayfun(@(x) sprintf("%s vs %s p=%.3f", ... + consCondNames(prmSubs(x,:)), p(x)), 1:size(prmSubs,1)); +text(ax(2), 0, -0.3, sprintf('%s vs. %s P=%.3f\n', ... + [consCondNames(prmSubs), string(p(:))]')) +set(ax(2), 'Visible', 'off') +set(countFig, 'UserData', {signBeh, p}) +title(ax(1), strrep(expName, '_',' ')); xlabel(ax(1),'Moving body parts') +ylabel(ax(1),'Trial proportion') +countFigName = sprintf("Count distributions P%s", ... + sprintf(" %.3f", p(:))); + +saveFigure(countFig, fullfile(behFig_path, countFigName), true, fowFlag); \ No newline at end of file diff --git a/James/script_learning_experiments.m b/James/script_learning_experiments.m new file mode 100644 index 0000000..610f909 --- /dev/null +++ b/James/script_learning_experiments.m @@ -0,0 +1,98 @@ +%% Call function + +dt= datetime(2024,11,25); + +dt.Format = 'd-MM-yy'; + +daytime = ["AM","PM"]; + +mice_number= ["m1", ... + "m2", ... + "m3", ... + "m4", ... + "m5", ... + "m6"]; + +data_path = "Z:\James\Learning Experiments"; +% HPC snipet +if ~strcmp( computer, 'PCWIN64' ) + + fnOpts = {'UniformOutput', false}; + unpackCell = @(x) x{:}; + home_path = '/gpfs/bwfor/home/hd/hd_hd/hd_bf154/'; + repo_paths = cellfun(@(x) char( fullfile( home_path, x) ), ... + {'NeuroNetzAnalysis', 'AuxiliaryFuncs', 'Scripts'}, fnOpts{:} ); + sf_repo_paths = cellfun(@(x) genpath(x), repo_paths, fnOpts{:} ); + addpath( sf_repo_paths{:} ); + data_path = '/mnt/sds-hd/sd19b001/James/Learning Experiments'; + +end + +ss_means = NaN(24,6,8); +ss_max = NaN(6,8); + +expandName = @(x) fullfile( x.folder, x.name ); + +for h = 0:11 + for x = 1:2 + for m = 1:6 + ss_Data = fullfile( data_path, ... + sprintf( "%s_%s", string(dt+h), daytime(x) ), ... + mice_number(m), "Simple summary.mat" ); + ss_Path = fullfile(data_path, ... + sprintf("%s_%s",string(dt+h),daytime(x)), ... + mice_number(m) ); + try + load(ss_Data) + catch + try + ss_Data = dir( fullfile(ss_Path, 'BehaviourResults*.mat') ); + load( expandName( ss_Data ), 'behRes' ) + summStruct = behRes; + catch + rec_file = dir(fullfile(ss_Path, 'Recording*.bin')); + fID = fopen( expandName( rec_file ) , 'w' ); + fwrite( fID, [], 'int16' ); + fclose(fID); + + prepare64ChanBin4KS( ss_Path, 'BinFileName', ... + sprintf("%s_%s_%s",mice_number(m),string(dt+h),daytime(x)), ... + 'AllBinFiles', true, 'Overwrite', true ); + + pgObj = ProtocolGetter(ss_Path); + pgObj.getConditionSignals; + pgObj.getSignalEdges; + pgObj.getFrequencyEdges(0.8); + pgObj.pairStimulus(0.2); + pgObj.saveConditions; + + try + [summStruct, behFig_path, behData, aInfo] = analyseBehaviour( ss_Path, ... + "ConditionsNames", "Puff", ... + "ResponseWindow", [25, 350] * 1e-3, ... + "ViewingWindow", [-450, 500] * 1e-3, ... + "figOverWrite", false, ... + "showPlots", false ); + + close all; + catch ME + disp( ME.message ) + disp( ME.identifier ) + disp( ME.cause ) + fprintf( 1, ['Debugging necessary perhaps?\n',... + 'Will continue with the loop...\n'] ) + continue; + end + end + end + r = ((x-1)*12)+(h+1); + N_att = numel(summStruct.Results); + ss_means(r,m,1:N_att) = mean(cat(1,summStruct.Results.MaxValuePerTrial),2); + if h == 0 && x==1 + ss_max(m,1:N_att) = max(cat(1,summStruct.Results.MaxValuePerTrial),[],2); + end + end + end +end + +save( fullfile( data_path, 'AmplitudeIndices.mat' ), 'ss_max', "ss_means" ) diff --git a/Jesus/DE_Jittering.m b/Jesus/DE_Jittering.m index ea56989..d69d275 100644 --- a/Jesus/DE_Jittering.m +++ b/Jesus/DE_Jittering.m @@ -9,9 +9,9 @@ end %% Loading data % Creating the figure directory -figureDir = fullfile(dataDir,'Figures\'); -if ~exist(figureDir, "dir") - if ~mkdir(figureDir) +FigureDir = fullfile(dataDir,'Figures\'); +if ~exist(FigureDir, "dir") + if ~mkdir(FigureDir) error("Could not create figure directory!\n") end end @@ -31,7 +31,14 @@ end fnOpts = {'UniformOutput', false}; axOpts = {'Box','off','Color','none'}; +ofgOpts = {'new', 'visible'}; spk_file_vars = {'spike_times','gclID','Nt','Ns','goods'}; +owFlag = false; +figOpts = {'Visible','on'}; +if ~strcmp( computer, 'PCWIN64' ) + figOpts(2) = {'off'}; + ofgOpts(2) = {'invisible'}; +end %% Constructing the helper 'global' variables spkPttrn = "%s_Spike_Times.mat"; @@ -42,9 +49,9 @@ % Total duration of the recording Nt = Ns/fs; % Useless clusters (labeled as noise or they have very low firing rate) - badsIdx = cellfun(@(x) x==3,sortedData(:,3)); + badsIdx = cellfun(@(x) x==3, sortedData(:,3) ); bads = find(badsIdx); - totSpkCount = cellfun(@numel,sortedData(:,2)); + totSpkCount = cellfun( @numel, sortedData(:,2) ); clusterSpikeRate = totSpkCount/Nt; silentUnits = clusterSpikeRate < 0.1; bads = union(bads,find(silentUnits)); @@ -98,13 +105,13 @@ isiFile = fullfile(dataDir,[expName,'_ISIvars.mat']); if ~exist(isiFile,'file') spkSubs2 = cellfun(@(x) round(x.*fs), sortedData(goods,2),... - 'UniformOutput', false); + fnOpts{:}); ISIVals = cellfun(@(x) [x(1)/fs; diff(x)/fs], spkSubs2,... - 'UniformOutput', 0); + fnOpts{:}); NnzvPcl = cellfun(@numel,ISIVals); Nnzv = sum(NnzvPcl); rows = cell2mat(arrayfun(@(x,y) repmat(x,y,1), (1:Ncl)', NnzvPcl,... - 'UniformOutput', 0)); + fnOpts{:})); cols = cell2mat(spkSubs2); vals = cell2mat(ISIVals); try @@ -200,7 +207,8 @@ [chCond, iOk] = listdlg('ListString',condNames,'SelectionMode','single',... 'PromptString',... 'Choose the condition which has all whisker triggers: (one condition)',... - 'InitialValue', find(condGuess), 'ListSize', [350, numel(condNames)*16]); + 'InitialValue', find(condGuess,1,"first"), 'ListSize', ... + [350, numel(condNames)*16]); if ~iOk fprintf(1,'Cancelling...\n') return @@ -239,7 +247,7 @@ O_key = sprintf('%s', onOffStr); currentMapKey = {RW_key, SW_key, C_key, CC_key, O_key}; VW_key = sprintf("VW%.2f-%.2f", timeLapse*1e3); - BZ_key = sprintf("BZ%.3f",binSz*1e3); + BZ_key = sprintf("BZ%.2f",binSz*1e3); %% Appending the new pc to the array and saving configStructure = [configStructure, struct('Experiment', ... fullfile(dataDir,expName), 'Viewing_window_s', timeLapse, ... @@ -278,7 +286,20 @@ O_key = sprintf('%s', onOffStr); currentMapKey = {RW_key, SW_key, C_key, CC_key, O_key}; VW_key = sprintf("VW%.2f-%.2f", timeLapse*1e3); - BZ_key = sprintf("BZ%.3f",binSz*1e3); + BZ_key = sprintf("BZ%.2f",binSz*1e3); +end +%% Creating ephys figure folder +subFigDir = sprintf("Ephys %s %s %s", VW_key, RW_key, SW_key); +subFigDir = fullfile(FigureDir, subFigDir); +ephFigDir = subFigDir; +metaNameFlag = false; +if ~exist(subFigDir, "dir") + if ~mkdir(subFigDir) + fprintf(1, "Couldn't create %s!\n", subFigDir) + fprintf(1, "Keeping metadata in figure file names.\n") + metaNameFlag = true; + ephFigDir = FigureDir; + end end %% Constructing the stack out of the user's choice % discStack - dicrete stack has a logical nature @@ -338,29 +359,54 @@ timeFlags = [sponActStackIdx;respActStackIdx]; % Time window delta_t = diff(responseWindow); -% Statistical tests -[Results, Counts] = statTests(discStack, delayFlags, timeFlags); -indCondSubs = cumsum(Nccond:-1:1); -% Plotting statistical tests -[Figs, Results] = scatterSignificance(Results, Counts, consCondNames,... - delta_t, gclID); -configureFigureToPDF(Figs); -stFigBasename = fullfile(figureDir,[expName,' ']); -stFigSubfix = sprintf(' Stat RW%.1f-%.1fms SW%.1f-%.1fms',... - responseWindow*1e3, spontaneousWindow*1e3); -ccn = 1; +% Results directory. Not the best name, but works for now... +resDir = fullfile(dataDir, 'Results'); +if ~exist(resDir, 'dir') + if ~mkdir(resDir) + fprintf(1, "There was an issue creating %s!\n", resDir) + fprintf(1, "Saving results in main directory") + resDir = dataDir; + end +end +resPttrn = 'Res VW%.2f-%.2f ms %s ms %s ms %s.mat'; +resFN = sprintf(resPttrn, timeLapse*1e3, RW_key, SW_key, C_key); +resFP = fullfile(resDir, resFN); -for cc = 1:numel(Figs) - if ~ismember(cc, indCondSubs) - altCondNames = strsplit(Figs(cc).Children(2).Title.String,': '); - altCondNames = altCondNames{2}; - else - altCondNames = consCondNames{ccn}; - ccn = ccn + 1; +% Statistical scatter figure names +stFigSubfix = ""; +if metaNameFlag + stFigSubfix = stFigSubfix + " " + RW_key + " " + SW_key; +end + +cmbSubs = 0; snglSubs = 1; +cmpCondNames = string(consCondNames(:)); prmSubs = ones(1,2); +if Nccond > 1 + prmSubs = nchoosek(1:Nccond,2); Nsf = size(prmSubs,1) + Nccond; + snglSubs = cumsum(Nccond:-1:1); cmbSubs = setdiff(1:Nsf, snglSubs); + cmpCondNames = cat(1, cmpCondNames, arrayfun(@(x) ... + consCondNames(prmSubs(x,1)) + " vs. " + ... + consCondNames(prmSubs(x,2)), (1:size(prmSubs, 1))')); +end +stFigFN = fullfile(ephFigDir, "Stat " + cmpCondNames + stFigSubfix); +if cmbSubs + cmpCondNames_aux([snglSubs, cmbSubs]) = stFigFN; + stFigFN = cmpCondNames_aux; +end + +if exist(resFP,"file") && all(arrayfun(@(x) exist(x, "file"), stFigFN + ".fig")) + load(resFP, "Results", "Counts") + arrayfun(@(x) openfig(x + ".fig", ofgOpts{:}), stFigFN) +else + % Statistical tests + [Results, Counts] = statTests(discStack, delayFlags, timeFlags); + % Plotting statistical tests + [Figs, Results] = scatterSignificance(Results, Counts, consCondNames,... + delta_t, gclID); configureFigureToPDF(Figs); + parfor cf = 1:numel(Figs) + saveFigure( Figs(cf), stFigFN(cf), true, owFlag ) end - stFigName = [stFigBasename, altCondNames, stFigSubfix]; - saveFigure(Figs(cc), stFigName) + save(resFP, "Results", "Counts", "configStructure", "gclID") end [rclIdx, H, zH] = getSignificantFlags(Results); Htc = sum(H,2); @@ -370,18 +416,9 @@ end wruIdx = all(H(:,CtrlCond),2); Nwru = nnz(wruIdx); - -%% Results directory fprintf('%d responding clusters:\n', Nwru); fprintf('- %s\n',gclID{wruIdx}) -resDir = fullfile(dataDir, 'Results'); -if ~exist(resDir, 'dir') - if ~mkdir(resDir) - fprintf(1, "There was an issue creating %s!\n", resDir) - fprintf(1, "Saving results in main directory") - resDir = dataDir; - end -end + %% Map prototype mapPttrn = "Map %s.mat"; resMap_path = fullfile(resDir, sprintf(mapPttrn, expName)); @@ -415,22 +452,13 @@ save(resMap_path, "resMap", "keyCell") end - -%% Saving statistical results -% Not the best name, but works for now... -resPttrn = 'Res VW%.2f-%.2f ms %s ms %s ms %s.mat'; -resFN = sprintf(resPttrn, timeLapse*1e3, RW_key, SW_key, C_key); -resFP = fullfile(resDir, resFN); -if ~exist(resFP, "file") - save(resFP, "Results", "Counts", "configStructure", "gclID") -end %% Filter question filterIdx = true(Ne,1); ansFilt = questdlg('Would you like to filter for significance?','Filter',... 'Yes','No','Yes'); -filtStr = 'unfiltered'; +filtStr = 'unfiltered'; filtFlag = false; if strcmp(ansFilt,'Yes') - filterIdx = [true; wruIdx]; + filterIdx = [true; wruIdx]; filtFlag = true; filtStr = 'filtered'; end %% Getting the relative spike times for the whisker responsive units (wru) @@ -440,31 +468,32 @@ % cellLogicalIndexing = @(x,idx) x(idx); isWithinResponsiveWindow =... @(x) x > responseWindow(1) & x < responseWindow(2); - -rst = arrayfun(@(x) getRasterFromStack(discStack, ~delayFlags(:,x), ... - filterIdx(3:end), timeLapse, fs, true, true), 1:size(delayFlags,2), ... - fnOpts{:}); -relativeSpkTmsStruct = struct('name', cellstr(consCondNames), ... - 'SpikeTimes', rst); -firstSpkStruct = getFirstSpikeInfo(relativeSpkTmsStruct, configStructure); -relSpkFileName =... - sprintf('%s RW%.2f - %.2f ms SW%.2f - %.2f ms VW%.2f - %.2f ms %s (%s) exportSpkTms.mat',... - expName, responseWindow*1e3, spontaneousWindow*1e3,... - timeLapse*1e3, Conditions(chCond).name, filtStr); -% Spontaneous firing rates -Texp = Ns/fs; -trainDuration = 1; -AllTriggs = unique(cat(1, Conditions.Triggers), 'rows', 'sorted'); -[spFr, ~, SpSpks, spIsi] = getSpontFireFreq(spkSubs, AllTriggs,... - [0, Texp], fs, trainDuration + delta_t + responseWindow(1)); -SpontaneousStruct = struct('Spikes', SpSpks, 'FR', ... - arrayfun(@(x) {x}, spFr), 'ISI', spIsi); -if ~exist(relSpkFileName,'file') - save(fullfile(dataDir, relSpkFileName), 'relativeSpkTmsStruct',... - 'configStructure', 'firstSpkStruct', 'SpontaneousStruct') -elseif all(~contains(who(matfile(fullfile(dataDir, relSpkFileName))), ... - 'SpontaneousStruct')) - save(fullfile(dataDir, relSpkFileName), 'SpontaneousStruct', '-append') +relSpkFN = string(expName) + " " + RW_key + " " + SW_key + " " + ... + VW_key + " ms " + C_key + " (" + string(filtStr) + ") RelSpkTms.mat"; +consVars = {'relativeSpkTmsStruct', 'firstSpkStruct', ... + 'SpontaneousStruct', 'configStructure'}; +rspMF = matfile(fullfile(dataDir, relSpkFN)); + +if ~exist( fullfile( dataDir, relSpkFN ),'file') || ... + any(~contains(who(rspMF), consVars)) + rst = arrayfun(@(x) getRasterFromStack(discStack, ~delayFlags(:,x), ... + [false; filterIdx(2:end)], timeLapse, fs, true, true), ... + 1:size(delayFlags,2), fnOpts{:}); + relativeSpkTmsStruct = struct('name', cellstr(consCondNames), ... + 'SpikeTimes', rst); + firstSpkStruct = getFirstSpikeInfo(relativeSpkTmsStruct, configStructure); + + % Spontaneous firing rates + Texp = Ns/fs; + trainDuration = 1; + AllTriggs = unique(cat(1, Conditions.Triggers), 'rows', 'sorted'); + [spFr, ~, SpSpks, spIsi] = getSpontFireFreq(spkSubs, AllTriggs,... + [0, Texp], fs, trainDuration + delta_t + responseWindow(1)); + SpontaneousStruct = struct('Spikes', SpSpks, 'FR', ... + arrayfun(@(x) {x}, spFr), 'ISI', spIsi); + save(fullfile(dataDir, relSpkFN), consVars{:}) +else + load(fullfile(dataDir, relSpkFN), consVars{1:3}) end %% Ordering PSTH @@ -494,86 +523,140 @@ end %% Plot PSTH -goodsIdx = logical(clInfo.ActiveUnit); if exist('Triggers', 'var') csNames = fieldnames(Triggers); end Nbn = diff(timeLapse)/binSz; -if (Nbn - round(Nbn)) ~= 0 - Nbn = ceil(Nbn); +if (Nbn - round( Nbn )) ~= 0 + Nbn = ceil( Nbn ); end -PSTH = zeros(nnz(filterIdx) - 1, Nbn, Nccond); -psthTx = (0:Nbn-1) * binSz + timeLapse(1); -psthFigs = gobjects(Nccond,1); + +%psthTx = (0:Nbn-1) * binSz + timeLapse(1); Ntc = size(cst,2); -for ccond = 1:Nccond - figFileName =... - sprintf("%s %s VW%.1f-%.1f B%.1f %s %s ms %sset %s (%s)",... - expName, consCondNames{ccond}, timeLapse*1e3, binSz*1e3,... - RW_key, SW_key, onOffStr, orderedStr, filtStr); - [PSTH(:,:,ccond), trig, sweeps] = getPSTH(discStack(filterIdx,:,:),timeLapse,... - ~delayFlags(:,ccond),binSz,fs); +psthFN = "PSTH " + consCondNames(:) + " " + BZ_key + " " + string(orderedStr); +if filtFlag + psthFN = psthFN + " " + filtStr; +end +% PSTH construction +psthFP = fullfile(ephFigDir, psthFN); +if any(arrayfun(@(x) ~exist(x+".fig","file"), psthFP)) + % [PSTH, trig] = arrayfun(@(x) getPSTH(discStack(filterIdx,:,:), ... + % timeLapse, ~delayFlags(:,x), binSz, fs), 1:Nccond, fnOpts{:}); if exist('cst', 'var') && ~isempty(cst) - stims = mean(cst(:,:,delayFlags(:,ccond)),3); - stims = stims - median(stims,2); - for cs = 1:size(stims,1) - if abs(log10(var(stims(cs,:),[],2))) < 13 - [m,b] = lineariz(stims(cs,:),1,0); - stims(cs,:) = m*stims(cs,:) + b; - else - stims(cs,:) = zeros(1,Ntc); - end - end + % Take into account covariance for signals. + stims = arrayfun(@(x) mean(cst(:,:,delayFlags(:,x)),3), 1:Nccond, ... + fnOpts{:}); stims = cellfun(@(x) zscore(x, 0, 'all'), stims, fnOpts{:}); else - stims = zeros(1, Ntc); + stims = repmat({zeros(1,Ntc)}, Nccond, 1); + end + psthFigs = gobjects( numel(psthFP), 1 ); + auxID = pclID(ordSubs); auxStack = discStack(filterIdx,:,:); + PSTH = cell(Nccond,1); trig = PSTH; + try + parfor cf = 1:Nccond + % for cf = 1:Nccond + [PSTH{cf}, trig{cf}] = getPSTH(auxStack, timeLapse, ... + ~delayFlags(:,cf), binSz, fs); + psthFigs(cf) = plotClusterReactivity(PSTH{cf}(ordSubs,:), trig{cf},... + Na(cf), timeLapse, binSz, [consCondNames(cf); auxID], strrep(expName,'_',' '), ... + stims{cf}, csNames); + ylabel(psthFigs(cf).Children(end), ... + [psthFigs(cf).Children(end).YLabel.String, ... + sprintf('^{%s}',orderedStr)]) + set( psthFigs(cf), 'UserData', PSTH{cf} ) + saveFigure( psthFigs(cf), psthFP(cf), true, owFlag ); + end + catch + fprintf(1, 'Not enough memory to run PSTH building in parallel!\n') + for cf = 1:Nccond + % for cf = 1:Nccond + [PSTH{cf}, trig{cf}] = getPSTH(auxStack, timeLapse, ... + ~delayFlags(:,cf), binSz, fs); + psthFigs(cf) = plotClusterReactivity(PSTH{cf}(ordSubs,:), trig{cf},... + Na(cf), timeLapse, binSz, [consCondNames(cf); auxID], strrep(expName,'_',' '), ... + stims{cf}, csNames); + ylabel(psthFigs(cf).Children(end), ... + [psthFigs(cf).Children(end).YLabel.String, ... + sprintf('^{%s}',orderedStr)]) + set( psthFigs(cf), 'UserData', PSTH{cf} ) + end + parfor cf = 1:Nccond + saveFigure( psthFigs(cf), psthFP(cf), true, owFlag ); + end + end +else + psthFigs = arrayfun(@(f) openfig(f + ".fig", ofgOpts{:} ), psthFP); + PSTH = arrayfun(@(f) get( f, 'UserData' ), psthFigs, fnOpts{:} ); + if all(cellfun(@(c)isempty(c),PSTH)) + [PSTH, trig] = arrayfun(@(x) getPSTH(discStack(filterIdx,:,:), ... + timeLapse, ~delayFlags(:,x), binSz, fs), 1:Nccond, fnOpts{:}); end - psthFigs(ccond) = plotClusterReactivity(PSTH(ordSubs,:,ccond), trig,... - sweeps, timeLapse, binSz, [consCondNames(ccond); pclID(ordSubs)],... - strrep(expName,'_',' '), stims, csNames); - psthFigs(ccond).Children(end).YLabel.String =... - [psthFigs(ccond).Children(end).YLabel.String,... - sprintf('^{%s}',orderedStr)]; - figFilePath = fullfile(figureDir, figFileName); - saveFigure(psthFigs(ccond), figFilePath); end -[ppFig, PSTHall] = compareCondPSTHs(PSTH, Na, binSz, timeLapse, ... - consCondNames); -ephysPttrn = 'Z-score all-units PSTH %s VW%.2f - %.2f ms Ntrials%s'; +% Z-score PSTH for all units +ephysPttrn = 'Z-score all-units PSTH %s Ntrials%s.fig'; ephysName = sprintf(ephysPttrn, sprintf('%s ', consCondNames{:}), ... - timeLapse*1e3, sprintf(' %d', Na)); -ephysFile = fullfile(figureDir, ephysName); + sprintf(' %d', Na)); +ephysFile = fullfile(ephFigDir, ephysName); if ~exist(ephysFile, 'file') - saveFigure(ppFig, ephysFile, 1); + [ppFig, PSTHall] = compareCondPSTHs(cat(3,PSTH{:}), Na, binSz, ... + timeLapse, consCondNames); + saveFigure(ppFig, ephysFile, 1, owFlag ); +else + openfig( ephysFile, ofgOpts{:} ); end -clearvars ppFig ephysPttrn ephysName ephysFile -%% Log PSTH -- Generalise this part!! +clearvars ppFig ephysPttrn ephysName ephysFile aux* +%% Log PSTH Nbin = 64; ncl = size(relativeSpkTmsStruct(1).SpikeTimes,1); logPSTH = getLogTimePSTH(relativeSpkTmsStruct, true(ncl,1),... 'tmWin', responseWindow, 'Offset', 2.5e-3, 'Nbin', Nbin,... 'normalization', 'fr'); -logFigs = plotLogPSTH(logPSTH); -% Saving the figures -lpFigName = sprintf('%s Log-likePSTH %s %d-conditions RW%.1f-%.1f ms NB%d (%s)',... - expName, logPSTH.Normalization, Nccond, responseWindow*1e3, Nbin, filtStr); -saveFigure(logFigs(1), fullfile(figureDir, lpFigName), true, true) -if numel(logFigs) > 1 - lmiFigName = sprintf('%s LogMI %d-conditions RW%.1f-%.1f ms NB%d (%s)',... - expName, Nccond, responseWindow*1e3, Nbin, filtStr); - saveFigure(logFigs(2), fullfile(figureDir, lmiFigName), true, true) - popEffects = logFigs(2).UserData; vrs = fieldnames(matfile(resFP)); - MIStruct = struct('ConditionNames', consCondNames, ... - 'MI', arrayfun(@(x) struct('Comparative', ... - string(consCondNames(popEffects(x,1)))+" vs "+... - string(consCondNames(popEffects(x,2))), 'Value', popEffects(x,3)), ... - 1:size(popEffects,1), fnOpts{:})); - if ~any(ismember(vrs,'MIStruct')) - fprintf(1,'Adding "MIStruct" to %s\n', resFN) - save(resFP, 'MIStruct','-append') +lpFN = sprintf("Log-likePSTH %s %d-conditions NB%d",... + logPSTH.Normalization, Nccond, Nbin); +%% Saving Log PSTH figures +if Nccond > 1 + lmiFN = sprintf("LogMI %d-conditions NB%d", Nccond, Nbin); + lmiFP = fullfile(ephFigDir, lmiFN); +end +if filtFlag + lpFN = lpFN + " (" + filtStr + ")"; + if Nccond > 1 + lmiFP = lmiFP + " (" + filtStr + ")"; + end +end +lpFP = fullfile(ephFigDir, lpFN); +if ~exist(lpFP+".fig", "file") || owFlag + logFigs = plotLogPSTH(logPSTH); saveFigure(logFigs(1), lpFP, true, owFlag ) + if numel(logFigs) > 1 + popEffects = logFigs(2).UserData; + MIStruct = struct('ConditionNames', consCondNames, ... + 'MI', arrayfun(@(x) struct('Comparative', ... + string(popEffects{x,1})+" vs "+... + string(popEffects{x,2}), 'Value', popEffects{x,3}), ... + 1:size(popEffects,1), fnOpts{:})); + set( logFigs(2), 'UserData', MIStruct ); + saveFigure(logFigs(2), lmiFP, true, owFlag ) + vrs = who(matfile(resFP)); + if ~any(ismember(vrs,'MIStruct')) + fprintf(1,'Adding "MIStruct" to %s\n', resFN) + save(resFP, 'MIStruct','-append') + end + end +else + logFigs = openfig(lpFP+".fig", ofgOpts{:} ); + load(resFP, "MIstruct") + if Nccond > 1 + logFigs(2) = openfig(lmiFP+".fig", ofgOpts{:} ); end end - +%% Save log MI results +logRF = fullfile( ephFigDir, ... + sprintf( "LogPSTH_Structure %s %d-conditions NB%d", ... + logPSTH.Normalization, Nccond, Nbin ) ); +if ~exist( logRF, 'file' ) + save( logRF, "logPSTH" ) +end %% Cluster population proportions % Responsive and unresponsive cells, significantly potentiated or depressed % and unmodulated. @@ -613,35 +696,35 @@ %% Plot proportional pies clrMap = lines(2); clrMap([3,4],:) = [0.65;0.8].*ones(2,3); % Responsive and non responsive clusters -respFig = figure("Color", "w"); +respFig = figure( "Color", "w", figOpts{:} ); pie([Ntn-Nrn, Nrn], [0, 1], {'Unresponsive', 'Responsive'}); pObj = findobj(respFig, "Type", "Patch"); arrayfun(@(x) set(x, "EdgeColor", "none"), pObj); arrayfun(@(x) set(pObj(x), "FaceColor", clrMap(x+2,:)), 1:length(pObj)) -propPieFileName = fullfile(figureDir,... - sprintf("Whisker responsive proportion pie RW%.1f - %.1f ms (%dC, %dR)",... - responseWindow*1e3, [Ntn-Nrn, Nrn])); -saveFigure(respFig, propPieFileName, 1); +propPieFileName = fullfile(ephFigDir,... + sprintf("Whisker responsive proportion pie %s (%dC, %dR)",... + C_key, [Ntn-Nrn, Nrn])); +saveFigure(respFig, propPieFileName, 1, owFlag ); % Potentiated, depressed and unmodulated clusters pie if Nccond == 2 - potFig = figure("Color", "w"); + potFig = figure("Color", "w", figOpts{:} ); pie([Nrn - Nrsn, Nrsp, Nrsn - Nrsp], [0, 1, 1], {'Non-modulated', ... 'Potentiated', 'Depressed'}); % set(potFig, axOpts{:}) pObj = findobj(potFig, "Type", "Patch"); arrayfun(@(x) set(x, "EdgeColor", "none"), pObj); arrayfun(@(x) set(pObj(x), "FaceColor", clrMap(x,:)), 1:length(pObj)) - modPropPieFigFileName = fullfile(figureDir,... - sprintf("Modulation proportions pie RW%.1f - %.1f ms (%dR, %dP, %dD)",... - responseWindow*1e3, Nrn - Nrsn, Nrsp, Nrsn - Nrsp)); - saveFigure(potFig, modPropPieFigFileName, 1) + modPropPieFigFileName = fullfile(ephFigDir,... + sprintf("Modulation proportions pie %s (%dR, %dP, %dD)",... + C_key, Nrn - Nrsn, Nrsp, Nrsn - Nrsp)); + saveFigure(potFig, modPropPieFigFileName, 1, owFlag ) % Modulation index histogram - MIFig = figure; histogram(MIspon, hsOpts{:}, "Spontaneous"); hold on; + MIFig = figure( figOpts{:} ); histogram(MIspon, hsOpts{:}, "Spontaneous"); hold on; histogram(MIevok, hsOpts{:}, "Evoked"); set(gca, axOpts{:}); title("Modulation index distribution"); xlabel("MI"); ylabel("Cluster proportion"); lgnd = legend("show"); set(lgnd, "Box", "off", "Location", "best") - saveFigure(MIFig, fullfile(figureDir,... - "Modulation index dist evoked & after induction"), 1) + saveFigure(MIFig, fullfile(ephFigDir,... + "Modulation index dist evoked & after induction "+C_key), 1, owFlag ) end %% Get significantly different clusters gcans = questdlg(['Do you want to get the waveforms from the',... @@ -656,29 +739,6 @@ fprintf(1, 'You can always get the waveforms later\n') end -%% Addition mean signals to the Conditions variable (Unused) -%{ -if ~isfield(Conditions,'Stimulus') ||... - any(arrayfun(@(x) isempty(x.Stimulus), Conditions(consideredConditions))) - fprintf(1,'Writting the stimulus raw signal into Conditions variable:\n') - whFlag = contains(trigNames, whStim, 'IgnoreCase', 1); - lrFlag = contains(trigNames, cxStim, 'IgnoreCase', 1); - cdel = 1; - for cc = consideredConditions - fprintf(1,'- %s\n', Conditions(cc).name) - Conditions(cc).Stimulus = struct(... - 'Mechanical',reshape(mean(cst(whFlag,:,delayFlags(:,cdel)),3),... - 1,Nt),'Laser',reshape(mean(cst(lrFlag,:,delayFlags(:,cdel)),3),... - 1,Nt),'TimeAxis',(0:Nt-1)/fs + timeLapse(1)); - cdel = cdel + 1; - end - save(fullfile(dataDir,[expName,'analysis.mat']),'Conditions','-append') -end -%} - -%% Standard Deviations of First Spikes After Each Trigger per Unit -% firstSpikes(relativeSpkTmsStruct, gclID, dataDir); - %% Rasters from interesting clusters rasAns = questdlg('Plot rasters?','Raster plot','Yes','No','Yes'); if strcmpi(rasAns,'Yes') @@ -727,7 +787,7 @@ clSub = clSub(rasOrd(rasIdx)); clSel = clSel(rasOrd(rasOrd ~= 0)); Nma = min(Na(rasCondSel)); - rasFig = figure; + rasFig = figure( figOpts{:} ); Nrcond = length(rasCond); ax = gobjects(Nrcond*Nrcl,1); timeFlags = all([tx(:) >= timeLapse(1), tx(:) <= timeLapse(2)],2); @@ -771,9 +831,9 @@ rasFigName = sprintf('%s R-%scl_%sVW%.1f-%.1f ms', expName,... sprintf('%s ', rasCondNames{:}), sprintf('%s ', pclID{clSel}),... timeLapse*1e3); - rasFigPath = fullfile(figureDir, rasFigName); + rasFigPath = fullfile(ephFigDir, rasFigName); arrayfun(@(x) set(x,'Color','none'), ax); - saveFigure(rasFig, rasFigPath, 1); + saveFigure(rasFig, rasFigPath, 1, owFlag ); clearvars ax rasFig end %% Response speed characterization @@ -782,7 +842,7 @@ % Window defined by the response in the population PSTH % twIdx = btx >= 2e-3 & btx <= 30e-3; % respTmWin = [2, 30]*1e-3; -[mdls, r2, qVals, qDiff] = exponentialSpread(PSTH(:,:,1), btx, responseWindow); +[mdls, r2, qVals, qDiff] = exponentialSpread(PSTH{1}, btx, responseWindow); mdls(mdls(:,2) == 0, 2) = 1; %% Cross-correlations ccrAns = questdlg(['Get cross-correlograms?',... @@ -813,7 +873,7 @@ % Arranging the auto-correlograms out of the cross-correlograms into a % single matrix try - acorrs = cellfun(@(x) x(1,:), corrs, 'UniformOutput', 0); + acorrs = cellfun(@(x) x(1,:), corrs, fnOpts{:} ); catch fprintf(1, 'No correlograms in the workspace!\n') end @@ -852,7 +912,7 @@ pointFlag = arrayfun(@(x) any(strcmpi(x.name, {'.','..'})), flds); flds(pointFlag) = []; behFoldFlag = arrayfun(@(x) any(strcmpi(x.name, 'Behaviour')), flds); -possNames = ["P", "L"]; +possNames = ["P", "L"]; m = 1e-3; if any(behFoldFlag) && sum(behFoldFlag) == 1 % If only one folder named Behaviour exists, chances are that this is % an awake experiment. @@ -860,289 +920,77 @@ fprintf(1, "Found %s!\n", behDir) answ = questdlg('Analyse behaviour?','Behaviour','Yes','No','Yes'); if strcmpi(answ,'Yes') + lgOpts = [axOpts(:)', {'Location'}, {'best'}]; + hstOpts = {'BinMethod', 'integers', 'BinLimits', [-0.5,4.5]}; behChCond = cellfun(@(x) contains(Conditions(chCond).name, x), ... {["Piezo", "Puff"];["Laser","Light"]}); - analyseBehaviour(behDir, 'Condition', possNames(behChCond), ... - 'PairedFlags', delayFlags, 'FigureDirectory', figureDir, ... - 'ConditionsNames', cellstr(consCondNames)); - end -end -%{ - -afPttrn = "ArduinoTriggers*.mat"; -rfPttrn = "RollerSpeed*.mat"; -axOpts = {'Box','off','Color','none'}; -lgOpts = cat(2, axOpts{1:2}, {'Location','best'}); -flds = dir(getParentDir(dataDir,1)); -pointFlag = arrayfun(@(x) any(strcmpi(x.name, {'.','..'})), flds); -flds(pointFlag) = []; -behFoldFlag = arrayfun(@(x) any(strcmpi(x.name, 'Behaviour')), flds); -if any(behFoldFlag) && sum(behFoldFlag) == 1 - % If only one folder named Behaviour exists, chances are that this is - % an awake experiment. - behDir = fullfile(flds(behFoldFlag).folder,flds(behFoldFlag).name); - fprintf(1, "Found %s!\n", behDir) - promptStrings = {'Viewing window (time lapse) [s]:','Response window [s]'}; - defInputs = {'-0.25, 0.5', '0.005, 0.4'}; - answ = inputdlg(promptStrings,'Behaviour parameters', [1, 30], defInputs); - if isempty(answ) - fprintf(1,'Cancelling...\n') - return - else - bvWin = str2num(answ{1}); %#ok<*ST2NM> - if numel(bvWin) ~= 2 - bvWin = str2num(inputdlg('Please provide the time window [s]:',... - 'Time window',[1, 30], '-0.1, 0.1')); - if isnan(bvWin) || isempty(bvWin) - fprintf(1,'Cancelling...') - return - end + delayFlags = arrayfun(@(x) any( Conditions(chCond).Triggers(:,1) == ... + Conditions(x).Triggers(:,1)', 2 ), consCondSubs, fnOpts{:} ); + delayFlags = cat(2, delayFlags{:}); + [behRes, behFig_path, behData, aInfo] = analyseBehaviour( behDir, ... + "Condition", possNames(behChCond), ... + "ConditionsNames", cellstr( consCondNames ), ... + "PairedFlags", delayFlags, ... + "FigureDirectory", FigureDir, ... + "ResponseWindow", [25, 350] * m, ... + "ViewingWindow", [-450, 500] * m, ... + "figOverWrite", owFlag ); + + [pAreas, ~, behAreaFig] = createBehaviourIndex(behRes); + behMeasures = string({behAreaFig.Name}); + biFigPttrn = behMeasures+"%s"; + biFigPttrn = arrayfun(@(s) sprintf(s, sprintf(" %s (%%.3f)", ... + consCondNames ) ), biFigPttrn ); + + for it = 1:numel(behMeasures) + behRes = arrayfun(@(bs, ba) setfield( bs, ... + strrep( behMeasures(it), " ", "_" ), ba), behRes(:), pAreas(:,it) ); end - brWin = str2num(answ{2}); - end - if isempty(dir(fullfile(behDir, afPttrn))) - readAndCorrectArdTrigs(behDir); - end - - fprintf(1,'Time window: %.2f - %.2f ms\n',bvWin*1e3) - fprintf(1,'Response window: %.2f - %.2f ms\n',brWin*1e3) - % Roller speed - rfFiles = dir(fullfile(behDir, rfPttrn)); - if isempty(rfFiles) - [~, vf, rollTx, fr, Texp] = createRollerSpeed(behDir); - rfFiles = dir(fullfile(behDir, rfPttrn)); - end - if numel(rfFiles) == 1 - rfName = fullfile(rfFiles.folder, rfFiles.name); - load(rfName) - try - % Encoder steps Radius^2 - en2cm = ((2*pi)/((2^15)-1))*((14.85/2)^2)*rollFs; - fr = rollFs; - catch - try - % Encoder steps Radius^2 - en2cm = ((2*pi)/((2^15)-1))*((14.85/2)^2)*fr; - catch - en2cm = ((2*pi)/((2^15)-1))*((14.85/2)^2)*fsRoll; - fr = fsRoll; - end - end - end - % Triggers - getFilePath = @(x) fullfile(x.folder, x.name); - atVar = {'atTimes', 'atNames', 'itTimes', 'itNames'}; - afFiles = dir(fullfile(behDir,afPttrn)); - if ~isempty(afFiles) - atV = arrayfun(@(x) load(getFilePath(x), atVar{:}), afFiles); - Nrecs = length(atV); - atT = arrayfun(@(x, z) cellfun(@(y, a) y+a, ... - x.atTimes, repmat(z,1,length(x.atTimes)), fnOpts{:}), atV', ... - num2cell([0, Texp(1:end-1)]), fnOpts{:}); - trig_per_recording = cellfun(@(x) size(x,2), atT); - [max_trigs, record_most_trigs] = max(trig_per_recording); - record_trig_cont_ID = arrayfun(@(x) ... - contains(atV(record_most_trigs).atNames, x.atNames), ... - atV(1:Nrecs), fnOpts{:}); outCell = cell(Nrecs, max_trigs); - for cr = 1:Nrecs - outCell(cr,record_trig_cont_ID{cr}) = atT{cr}; - end - atTimes = arrayfun(@(x) cat(1, outCell{:,x}), 1:size(outCell,2), ... - fnOpts{:}); - atNames = atV(1).atNames; - end - - lSub = arrayfun(@(x) contains(Conditions(chCond).name, x), atNames); - [~, vStack] = getStacks(false, round(atTimes{lSub} * fr), 'on', bvWin,... - fr, fr, [], vf*en2cm); [~, Nbt, Nba] = size(vStack); - tmdl = fit_poly([1,Nbt], bvWin, 1); - behTx = ((1:Nbt)'.^[1,0])*tmdl; - % Spontaneous flag - bsFlag = behTx <= 0; brFlag = behTx < brWin; - brFlag = xor(brFlag(:,1),brFlag(:,2)); - sSig = squeeze(std(vStack(:,bsFlag,:), [], 2)); - sMed = squeeze(median(vStack(:,bsFlag,:), 2)); - tMed = squeeze(median(vStack, 2)); - - % A bit arbitrary threshold, but enough to remove running trials - sigTh = 2.5; sMedTh = 0.2; tMedTh = 1; - thrshStr = sprintf("TH s%.2f sp_m%.2f t_m%.2f", sigTh, sMedTh, tMedTh); - excFlag = sSig > sigTh | abs(sMed) > sMedTh | abs(tMed) > tMedTh; - ptOpts = {"Color", 0.7*ones(1,3), "LineWidth", 0.2;... - "Color", "k", "LineWidth", 1.5}; - spTh = {0.1:0.1:3}; % Speed threshold - gp = zeros(Nccond, 1, 'single'); - rsPttrn = "%s roller speed VW%.2f - %.2f s RM%.2f - %.2f ms EX%d %s"; - pfPttrn = "%s move probability %.2f RW%.2f - %.2f ms EX%d %s"; - rsSgnls = cell(Nccond, 1); mvFlags = cell(Nccond,1); mvpt = mvFlags; - qSgnls = rsSgnls; - mat2ptch = @(x) [x(1:end,:)*[1;1]; x(end:-1:1,:)*[1;-1]]; - getThreshCross = @(x) sum(x)/size(x,1); - xdf = arrayfun(@(x) ~excFlag & delayFlags(:,x), 1:Nccond, ... - fnOpts{:}); xdf = cat(2, xdf{:}); - - for ccond = 1:Nccond - sIdx = xdf(:,ccond); - % % Plot speed signals - fig = figure("Color", "w"); - Nex = sum(xor(sIdx, delayFlags(:,ccond))); - rsFigName = sprintf(rsPttrn,consCondNames{ccond}, bvWin,... - brWin*1e3, Nex, thrshStr); - % Plot all trials - plot(behTx, squeeze(vStack(:,:,sIdx)), ptOpts{1,:}); hold on; - % Plot mean of trials - % Standard deviation - %rsSgnls{ccond} = [squeeze(mean(vStack(:,:,sIdx),3))',... - %squeeze(std(vStack(:,:,sIdx),1,3))']; - % S.E.M. - rsSgnls{ccond} = [squeeze(mean(vStack(:,:,sIdx),3))',... - squeeze(std(vStack(:,:,sIdx),1,3))'./sqrt(sum(sIdx))]; - qSgnls{ccond} = squeeze(quantile(vStack(:,:,sIdx),3,3)); - lObj = plot(behTx, rsSgnls{ccond}(:,1), ptOpts{2,:}); - lgnd = legend(lObj,string(consCondNames{ccond})); - set(lgnd, "Box", "off", "Location", "best") - set(gca, axOpts{:}) - title(['Roller speed ',consCondNames{ccond}]) - xlabel("Time [s]"); ylabel("Roller speed [cm/s]"); xlim(bvWin) - saveFigure(fig, fullfile(figureDir, rsFigName), 1) - % Probability plots - mvpt{ccond} = getMaxAbsPerTrial(squeeze(vStack(:,:,sIdx)), ... - brWin, behTx); - mvFlags{ccond} = compareMaxWithThresh(mvpt{ccond}, spTh); - gp(ccond) = getAUC(mvFlags{ccond}); - pfName = sprintf(pfPttrn, consCondNames{ccond}, gp(ccond),... - brWin*1e3, Nex, thrshStr); - fig = plotThetaProgress(mvFlags(ccond), spTh,... - string(consCondNames{ccond})); - xlabel("Roller speed \theta [cm/s]"); - title(sprintf("Trial proportion crossing \\theta: %.3f", gp(ccond))) - saveFigure(fig, fullfile(figureDir, pfName), 1) - end - clMap = lines(Nccond); - phOpts = {'EdgeColor', 'none', 'FaceAlpha', 0.25, 'FaceColor'}; - % Plotting mean speed signals together - fig = figure("Color", "w"); axs = axes("Parent", fig, "NextPlot", "add"); - arrayfun(@(x) patch(axs, behTx([1:end, end:-1:1]),... - mat2ptch(rsSgnls{x}), 1, phOpts{:}, clMap(x,:)), 1:Nccond); hold on - lObj = arrayfun(@(x) plot(axs, behTx, rsSgnls{x}(:,1), "Color", clMap(x,:),... - "LineWidth", 1.5, "DisplayName", consCondNames{x}), 1:Nccond); - xlabel(axs, "Time [s]"); xlim(axs, bvWin); ylabel(axs, "Roller speed [cm/s]") - set(axs, axOpts{:}); title(axs, "Roller speed for all conditions") - lgnd = legend(axs, lObj); set(lgnd, lgOpts{:}) - rsPttrn = "Mean roller speed %s VW%.2f - %.2f s RM%.2f - %.2f ms EX%s %s SEM"; - Nex = Na - sum(xdf); - rsFigName = sprintf(rsPttrn, sprintf('%s ', consCondNames{:}), bvWin,... - brWin*1e3, sprintf('%d ', Nex), thrshStr); - saveFigure(fig, fullfile(figureDir, rsFigName), 1) - % Plotting median speed signals together - q2patch = @(x) [x(:,1);x(end:-1:1,3)]; - fig = figure("Color", "w"); axs = axes("Parent", fig, "NextPlot", "add"); - arrayfun(@(x) patch(axs, behTx([1:end, end:-1:1]),... - q2patch(qSgnls{x}), 1, phOpts{:}, clMap(x,:)), 1:Nccond); hold on - lObj = arrayfun(@(x) plot(axs, behTx, qSgnls{x}(:,2), "Color", clMap(x,:),... - "LineWidth", 1.5, "DisplayName", consCondNames{x}), 1:Nccond); - xlabel(axs, "Time [s]"); xlim(axs, bvWin); ylabel(axs, "Roller speed [cm/s]") - set(axs, axOpts{:}); title(axs, "Roller speed for all conditions") - lgnd = legend(axs, lObj); set(lgnd, lgOpts{:}) - rsPttrn = "Median roller speed %s VW%.2f - %.2f s RM%.2f - %.2f ms EX%s %s IQR"; - rsFigName = sprintf(rsPttrn, sprintf('%s ', consCondNames{:}), bvWin,... - brWin*1e3, sprintf('%d ', Nex), thrshStr); - saveFigure(fig, fullfile(figureDir, rsFigName), 1) - - % Plotting movement threshold crossings - fig = figure("Color", "w"); axs = axes("Parent", fig, "NextPlot", "add"); - mvSgnls = cellfun(getThreshCross, mvFlags, fnOpts{:}); - mvSgnls = cat(1, mvSgnls{:}); mvSgnls = mvSgnls'; - plot(axs, spTh{1}, mvSgnls); - ccnGP = cellfun(@(x, y) [x, sprintf(' AUC%.3f',y)], consCondNames', ... - num2cell(gp), fnOpts{:}); - lgnd = legend(axs, ccnGP); set(axs, axOpts{:}) - set(lgnd, lgOpts{:}); ylim(axs, [0,1]) - xlabel(axs, "Roller speed \theta [cm/s]"); ylabel(axs, "Trial proportion") - title(axs, "Trial proportion crossing \theta") - pfPttrn = "Move probability %sRW%.2f - %.2f ms %s"; - pfName = sprintf(pfPttrn, sprintf('%s ', ccnGP{:}), brWin*1e3, thrshStr); - saveFigure(fig, fullfile(figureDir, pfName), 1) - - % Plotting maximum speed for all considered trials - fig = figure; axs = axes('Parent', fig, 'NextPlot', 'add'); - arrayfun(@(x) boxchart(x*ones(size(mvpt{x},1),1), mvpt{x}, 'Notch', 'on'), ... - 1:size(mvpt,1)) - xticks(axs, 1:size(mvpt,1)); xticklabels(axs, consCondNames) - try - ylim(axs, [0, round(1.05*(max(cellfun(@(x) quantile(x, 0.75) + ... - 1.5*iqr(x), mvpt))),1)]); - catch - ylim(axs, 'auto') - end - ylabel(axs, "Roller speed [cm/s]") - arrayfun(@(x) text(x, median(mvpt{x}), sprintf("%.2f",median(mvpt{x})), ... - "HorizontalAlignment", "center", "VerticalAlignment", "bottom"), ... - 1:Nccond, fnOpts{:}); - title(axs, "Roller speed distribution") - rsdPttrn = "Roller speed dist %sVW%.2f - %.2f ms RM%.2f - %.2f ms EX%s%s"; - rsdFigName = sprintf(rsdPttrn, sprintf('%s ', consCondNames{:}), bvWin*1e3,... - brWin*1e3, sprintf('%d ', Nex), thrshStr); - saveFigure(fig, fullfile(figureDir, rsdFigName), 1) - - % Tests for movement - prms = nchoosek(1:Nccond,2); - getDistTravel = @(x) squeeze(sum(abs(vStack(:,brFlag,xdf(:,x))),2)); - dstTrav = arrayfun(getDistTravel, 1:Nccond, fnOpts{:}); - [pd, hd, statsd] = arrayfun(@(x) ranksum(dstTrav{prms(x,1)}, ... - dstTrav{prms(x,2)}), 1:size(prms,1), fnOpts{:}); - [pm, hm, statsm] = arrayfun(@(x) ranksum(mvpt{prms(x,1)}, ... - mvpt{prms(x,2)}), 1:size(prms,1), fnOpts{:}); - resPttrn = "Results %s%sVW%.2f - %.2f ms RW%.2f - %.2f ms EX%s%s.mat"; - resName = sprintf(resPttrn, sprintf("%d ", hd{:}), ... - sprintf('%s ',consCondNames{:}), bvWin*1e3, brWin*1e3, ... - sprintf('%d ', Nex), thrshStr); - save(fullfile(behDir, resName), "gp", "dstTrav", "ccnGP", "mvpt", "xdf", ... - "vStack", "spTh", "sigTh", "sMedTh", "tMedTh", "brWin", "bvWin", "prms") - - % Behaviour signals - behResBase = "BehaveSignals"; - expDate = getDates(string(rfFiles.name), "RollerSpeed"); - behResName = sprintf("%s%s.mat",behResBase, expDate); - behResPath = fullfile(behDir, behResName); - if ~exist(behResName,'file') - timeAxis_speed = (0:length(vf)-1)'/fr; - time_drift_mdl = fit_poly(atTimes{lSub}, Conditions(chCond).Triggers(:,1)/fs, 1); - timeAxis_speed_corrected = timeAxis_speed.^[1,0] * time_drift_mdl; - timeAxis_speed = (0:1/fr:timeAxis_speed_corrected(end))'; - vels = interp1(timeAxis_speed_corrected, vf*en2cm, timeAxis_speed); - save(behResPath, "vels", "timeAxis_speed", "fr") - - dlcFiles = dir(fullfile(behDir, "*filtered.csv")); - dlcFile = []; - if ~isempty(dlcFiles) - if numel(dlcFiles)==1 - dlcFile = dlcFiles.name; - end - else - dlcFiles = dir(fullfile(behDir, "roller*DLC_resnet50_AwakenSCJul20shuffle1_1030000.csv")); - if ~isempty(dlcFiles) - if numel(dlcFiles) == 1 - dlcFile = dlcFiles.name; - end - else - fprintf(1, "No DLC applied on the videos yet!\n") - fprintf(1, "Unable to get behavioural signals!\n") - end - end - if ~isempty(dlcFile) - dlcTable = readDLCData(fullfile(behDir, dlcFile)); - [a_bodyParts, refStruct] = getBehaviourSignals(dlcTable); - nose = a_bodyParts{:,"nose"} - mean(a_bodyParts{:,"nose"}); - % Right whiskers - rw = mean(a_bodyParts{:,{'rw1', 'rw2', 'rw3', 'rw4'}}, 2); - rw = rw - mean(rw); - % Left whiskers - lw = mean(a_bodyParts{:,{'lw1', 'lw2', 'lw3', 'lw4'}},2); - lw = lw - mean(lw); - save(behResPath,"rw","lw","nose","-append") - end - end -end -%} \ No newline at end of file + arrayfun(@(f) set( f, 'UserData', behRes ), behAreaFig ); + + biFN = arrayfun(@(s) sprintf( biFigPttrn(s), pAreas(:,s) ), 1:numel(behMeasures) ); + + % trMvFlag = arrayfun(@(cr) behRes(1).Results(cr).MovStrucure.MovmentFlags, ... + % 1:size(behRes(1).Results,2), fnOpts{:}); trMvFlag = cat(3, trMvFlag{:}); + % BIscaleMat = sum(trMvFlag,3); + % BIscale = arrayfun(@(cc) BIscaleMat(delayFlags(:,cc), cc), 1:Nccond, ... + % fnOpts{:}); + % [hg, hg_bin] = cellfun(@(c) histcounts(c, hstOpts{:}), ... + % BIscale, fnOpts{:}); + % hg = cat(1, hg{:}); hg_bin = cat(1, hg_bin{:}); + + + % [p_amp, h_amp] = ranksum(cat(1, zamp{1,:}), cat(1, zamp{2,:})); + %% + % clrMap = lines(Nccond); + % countFig = figure( figOpts{:} ); ax(1) = subplot(10,1,1:8); + % bar(ax(1), (0:4)', (hg./sum(hg,2))', 'EdgeColor', 'none'); hold on; + % poaDist = cellfun(@(bi) fitdist(bi,"Poisson"), BIscale); + % ylim(ax(1), [0,1]); set(ax(1), axOpts{:}); + % legend(ax(1), consCondNames, 'AutoUpdate','off', lgOpts{:}) + % lmbdaHeight = 0.95-(0.15/Nccond)*(0:Nccond-1); + % arrayfun(@(pd) scatter(ax(1), poaDist(pd).lambda, lmbdaHeight(pd), '|',... + % 'MarkerEdgeColor', clrMap(pd,:)), 1:Nccond) + % arrayfun(@(pd) line(ax(1), paramci(poaDist(pd)), ... + % lmbdaHeight([pd,pd]), 'Color', clrMap(pd,:), ... + % 'Marker', '|'), 1:Nccond) + % [p, chiVal] = arrayfun(@(ps) chi2test(hg(prmSubs(ps,:), :)), ... + % 1:size(prmSubs,1)); + % ax(2) = subplot(10,1,9:10); + % signBeh = arrayfun(@(x) sprintf("%s vs %s p=%.3f", ... + % consCondNames(prmSubs(x,:)), p(x)), 1:size(prmSubs,1)); + % text(ax(2), 0, -0.3, sprintf('%s vs. %s P=%.3f\n', ... + % [consCondNames(prmSubs), string(p(:))]')) + % set(ax(2), 'Visible', 'off') + % set(countFig, 'UserData', {signBeh, p}) + % title(ax(1), strrep(expName, '_',' ')); xlabel(ax(1),'Moving body parts') + % ylabel(ax(1),'Trial proportion') + % countFigName = sprintf("Count distributions P%s", ... + % sprintf(" %.3f", p(:))); + %% + arrayfun(@(f, fn) saveFigure(f, fullfile(behFig_path, fn), true, owFlag), ... + behAreaFig(:), biFN(:) ); + % saveFigure(countFig, fullfile(behFig_path, countFigName), true, owFlag ); + end +end \ No newline at end of file diff --git a/Jesus/arrayfun_examples_sum_mean.m b/Jesus/arrayfun_examples_sum_mean.m new file mode 100644 index 0000000..2a721fc --- /dev/null +++ b/Jesus/arrayfun_examples_sum_mean.m @@ -0,0 +1,515 @@ +% introduction to anonymous functions + + out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1)), 1:size(x,2),'UniformOutput',false) + out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1), 'UniformOutput', false), 1:size(x,2), 'UniformOutput', false) + + +out = cat(1, out{:}); +out + +out = + + 2 3 4 5 6 7 8 9 10 11 + 3 4 5 6 7 8 9 10 11 12 + 4 5 6 7 8 9 10 11 12 13 + 5 6 7 8 9 10 11 12 13 14 + 6 7 8 9 10 11 12 13 14 15 + 7 8 9 10 11 12 13 14 15 16 + 8 9 10 11 12 13 14 15 16 17 + 9 10 11 12 13 14 15 16 17 18 + 10 11 12 13 14 15 16 17 18 19 + 11 12 13 14 15 16 17 18 19 20 + 12 13 14 15 16 17 18 19 20 21 + 13 14 15 16 17 18 19 20 21 22 + +out = arrayfun(@(var2) arrayfun(@(var1) var1 + var2, 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); +out = arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); + arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); +x + +x(:,:,1) = + + 43 54 78 52 26 92 18 27 65 46 59 55 + 10 66 43 95 23 1 73 77 68 67 55 65 + 60 41 10 64 67 47 48 19 64 78 87 55 + 48 82 27 96 85 43 16 29 95 36 27 73 + 70 72 16 25 35 47 35 10 21 67 32 53 + 70 97 29 68 79 78 61 58 71 42 12 100 + 64 54 45 29 68 33 20 69 24 85 94 22 + 4 33 53 68 1 79 74 55 12 84 65 11 + 7 11 46 70 61 48 25 43 61 26 48 11 + 32 62 88 7 39 4 92 65 46 62 64 7 + + +x(:,:,2) = + + 41 70 35 74 83 80 52 54 86 62 74 77 + 45 10 15 40 43 95 89 9 57 99 59 59 + 37 53 59 69 89 33 59 12 93 53 25 93 + 77 54 27 71 40 68 16 14 70 48 67 59 + 63 87 5 45 77 44 20 68 59 81 9 2 + 78 49 76 2 40 84 41 50 82 23 63 13 + 94 40 25 34 81 77 75 19 88 50 67 87 + 98 68 45 43 76 17 83 50 99 91 73 49 + 20 75 69 28 38 87 79 15 1 58 90 85 + 14 53 36 20 22 99 32 6 87 85 99 21 + + +x(:,:,3) = + + 56 15 13 95 74 14 56 99 18 92 90 46 + 63 19 50 9 7 4 86 54 36 11 8 11 + 4 5 86 11 87 94 35 71 6 75 25 100 + 62 64 88 15 94 31 45 100 53 74 6 34 + 37 29 28 17 99 30 6 29 34 57 45 30 + 5 54 21 63 86 34 18 42 18 19 2 7 + 49 70 57 58 79 47 67 47 21 60 90 30 + 20 50 65 6 52 65 34 77 91 30 20 5 + 13 54 42 94 18 3 90 82 68 14 10 51 + 21 45 21 73 40 85 12 11 47 22 31 77 + +arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); +out = arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); +out = arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); +out = arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false); +out = arrayfun(@(var2) arrayfun(@(var1) x(var1) + x(var2), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false) + +out = + + 1×12 cell array + + Columns 1 through 7 + + {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} + + Columns 8 through 12 + + {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} + +out = arrayfun(@(var2) arrayfun(@(var1) mean(x(var1,var2,:),3), 1:size(x,1)), 1:size(x,2), 'UniformOutput', false) + +out = + + 1×12 cell array + + Columns 1 through 7 + + {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} + + Columns 8 through 12 + + {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} + +out = cat(1, out{:}); +out = cat(1, out{:}) +Brace indexing is not supported for variables of this type. + +out + +out = + + 46.6667 39.3333 33.6667 62.3333 56.6667 51.0000 69.0000 40.6667 13.3333 22.3333 + 46.3333 31.6667 33.0000 66.6667 62.6667 66.6667 54.6667 50.3333 46.6667 53.3333 + 42.0000 36.0000 51.6667 47.3333 16.3333 42.0000 42.3333 54.3333 52.3333 48.3333 + 73.6667 48.0000 48.0000 60.6667 29.0000 44.3333 40.3333 39.0000 64.0000 33.3333 + 61.0000 24.3333 81.0000 73.0000 70.3333 68.3333 76.0000 43.0000 39.0000 33.6667 + 62.0000 33.3333 58.0000 47.3333 40.3333 65.3333 52.3333 53.6667 46.0000 62.6667 + 42.0000 82.6667 47.3333 25.6667 20.3333 40.0000 54.0000 63.6667 64.6667 45.3333 + 60.0000 46.6667 34.0000 47.6667 35.6667 50.0000 45.0000 60.6667 46.6667 27.3333 + 56.3333 53.6667 54.3333 72.6667 38.0000 57.0000 44.3333 67.3333 43.3333 60.0000 + 66.6667 59.0000 68.6667 52.6667 68.3333 28.0000 65.0000 68.3333 32.6667 56.3333 + 74.3333 40.6667 45.6667 33.3333 28.6667 25.6667 83.6667 52.6667 49.3333 64.6667 + 59.3333 45.0000 82.6667 55.3333 28.3333 40.0000 46.3333 21.6667 49.0000 35.0000 + +x + +x(:,:,1) = + + 43 54 78 52 26 92 18 27 65 46 59 55 + 10 66 43 95 23 1 73 77 68 67 55 65 + 60 41 10 64 67 47 48 19 64 78 87 55 + 48 82 27 96 85 43 16 29 95 36 27 73 + 70 72 16 25 35 47 35 10 21 67 32 53 + 70 97 29 68 79 78 61 58 71 42 12 100 + 64 54 45 29 68 33 20 69 24 85 94 22 + 4 33 53 68 1 79 74 55 12 84 65 11 + 7 11 46 70 61 48 25 43 61 26 48 11 + 32 62 88 7 39 4 92 65 46 62 64 7 + + +x(:,:,2) = + + 41 70 35 74 83 80 52 54 86 62 74 77 + 45 10 15 40 43 95 89 9 57 99 59 59 + 37 53 59 69 89 33 59 12 93 53 25 93 + 77 54 27 71 40 68 16 14 70 48 67 59 + 63 87 5 45 77 44 20 68 59 81 9 2 + 78 49 76 2 40 84 41 50 82 23 63 13 + 94 40 25 34 81 77 75 19 88 50 67 87 + 98 68 45 43 76 17 83 50 99 91 73 49 + 20 75 69 28 38 87 79 15 1 58 90 85 + 14 53 36 20 22 99 32 6 87 85 99 21 + + +x(:,:,3) = + + 56 15 13 95 74 14 56 99 18 92 90 46 + 63 19 50 9 7 4 86 54 36 11 8 11 + 4 5 86 11 87 94 35 71 6 75 25 100 + 62 64 88 15 94 31 45 100 53 74 6 34 + 37 29 28 17 99 30 6 29 34 57 45 30 + 5 54 21 63 86 34 18 42 18 19 2 7 + 49 70 57 58 79 47 67 47 21 60 90 30 + 20 50 65 6 52 65 34 77 91 30 20 5 + 13 54 42 94 18 3 90 82 68 14 10 51 + 21 45 21 73 40 85 12 11 47 22 31 77 + +x>50 + + 10×12×3 logical array + +ans(:,:,1) = + + 0 1 1 1 0 1 0 0 1 0 1 1 + 0 1 0 1 0 0 1 1 1 1 1 1 + 1 0 0 1 1 0 0 0 1 1 1 1 + 0 1 0 1 1 0 0 0 1 0 0 1 + 1 1 0 0 0 0 0 0 0 1 0 1 + 1 1 0 1 1 1 1 1 1 0 0 1 + 1 1 0 0 1 0 0 1 0 1 1 0 + 0 0 1 1 0 1 1 1 0 1 1 0 + 0 0 0 1 1 0 0 0 1 0 0 0 + 0 1 1 0 0 0 1 1 0 1 1 0 + + +ans(:,:,2) = + + 0 1 0 1 1 1 1 1 1 1 1 1 + 0 0 0 0 0 1 1 0 1 1 1 1 + 0 1 1 1 1 0 1 0 1 1 0 1 + 1 1 0 1 0 1 0 0 1 0 1 1 + 1 1 0 0 1 0 0 1 1 1 0 0 + 1 0 1 0 0 1 0 0 1 0 1 0 + 1 0 0 0 1 1 1 0 1 0 1 1 + 1 1 0 0 1 0 1 0 1 1 1 0 + 0 1 1 0 0 1 1 0 0 1 1 1 + 0 1 0 0 0 1 0 0 1 1 1 0 + + +ans(:,:,3) = + + 1 0 0 1 1 0 1 1 0 1 1 0 + 1 0 0 0 0 0 1 1 0 0 0 0 + 0 0 1 0 1 1 0 1 0 1 0 1 + 1 1 1 0 1 0 0 1 1 1 0 0 + 0 0 0 0 1 0 0 0 0 1 0 0 + 0 1 0 1 1 0 0 0 0 0 0 0 + 0 1 1 1 1 0 1 0 0 1 1 0 + 0 0 1 0 1 1 0 1 1 0 0 0 + 0 1 0 1 0 0 1 1 1 0 0 1 + 0 0 0 1 0 1 0 0 0 0 0 1 + +arrayfun(@(varEm) varEm>50, x(:,:,:)) + + 10×12×3 logical array + +ans(:,:,1) = + + 0 1 1 1 0 1 0 0 1 0 1 1 + 0 1 0 1 0 0 1 1 1 1 1 1 + 1 0 0 1 1 0 0 0 1 1 1 1 + 0 1 0 1 1 0 0 0 1 0 0 1 + 1 1 0 0 0 0 0 0 0 1 0 1 + 1 1 0 1 1 1 1 1 1 0 0 1 + 1 1 0 0 1 0 0 1 0 1 1 0 + 0 0 1 1 0 1 1 1 0 1 1 0 + 0 0 0 1 1 0 0 0 1 0 0 0 + 0 1 1 0 0 0 1 1 0 1 1 0 + + +ans(:,:,2) = + + 0 1 0 1 1 1 1 1 1 1 1 1 + 0 0 0 0 0 1 1 0 1 1 1 1 + 0 1 1 1 1 0 1 0 1 1 0 1 + 1 1 0 1 0 1 0 0 1 0 1 1 + 1 1 0 0 1 0 0 1 1 1 0 0 + 1 0 1 0 0 1 0 0 1 0 1 0 + 1 0 0 0 1 1 1 0 1 0 1 1 + 1 1 0 0 1 0 1 0 1 1 1 0 + 0 1 1 0 0 1 1 0 0 1 1 1 + 0 1 0 0 0 1 0 0 1 1 1 0 + + +ans(:,:,3) = + + 1 0 0 1 1 0 1 1 0 1 1 0 + 1 0 0 0 0 0 1 1 0 0 0 0 + 0 0 1 0 1 1 0 1 0 1 0 1 + 1 1 1 0 1 0 0 1 1 1 0 0 + 0 0 0 0 1 0 0 0 0 1 0 0 + 0 1 0 1 1 0 0 0 0 0 0 0 + 0 1 1 1 1 0 1 0 0 1 1 0 + 0 0 1 0 1 1 0 1 1 0 0 0 + 0 1 0 1 0 0 1 1 1 0 0 1 + 0 0 0 1 0 1 0 0 0 0 0 1 + +out = arrayfun(@(var2) arrayfun(@(var1) x(var1,var2,:) > 50, 1:size(x,1)), 1:size(x,2), 'UniformOutput', false) +Error using arrayfun +Non-scalar in Uniform output, at index 1, output 1. +Set 'UniformOutput' to false. + +Error in (var2)arrayfun(@(var1)x(var1,var2,:)>50,1:size(x,1)) + +out = arrayfun(@(var2) arrayfun(@(var1) x(var1,var2,:) > 50, 1:size(x,1), 'UniformOutput', false), 1:size(x,2), 'UniformOutput', false) + +out = + + 1×12 cell array + + Columns 1 through 8 + + {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} + + Columns 9 through 12 + + {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} + +out = cat(1, out{:}) + +out = + + 12×10 cell array + + Columns 1 through 6 + + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + + Columns 7 through 10 + + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} {1×1×3 logical} + +x + +x(:,:,1) = + + 43 54 78 52 26 92 18 27 65 46 59 55 + 10 66 43 95 23 1 73 77 68 67 55 65 + 60 41 10 64 67 47 48 19 64 78 87 55 + 48 82 27 96 85 43 16 29 95 36 27 73 + 70 72 16 25 35 47 35 10 21 67 32 53 + 70 97 29 68 79 78 61 58 71 42 12 100 + 64 54 45 29 68 33 20 69 24 85 94 22 + 4 33 53 68 1 79 74 55 12 84 65 11 + 7 11 46 70 61 48 25 43 61 26 48 11 + 32 62 88 7 39 4 92 65 46 62 64 7 + + +x(:,:,2) = + + 41 70 35 74 83 80 52 54 86 62 74 77 + 45 10 15 40 43 95 89 9 57 99 59 59 + 37 53 59 69 89 33 59 12 93 53 25 93 + 77 54 27 71 40 68 16 14 70 48 67 59 + 63 87 5 45 77 44 20 68 59 81 9 2 + 78 49 76 2 40 84 41 50 82 23 63 13 + 94 40 25 34 81 77 75 19 88 50 67 87 + 98 68 45 43 76 17 83 50 99 91 73 49 + 20 75 69 28 38 87 79 15 1 58 90 85 + 14 53 36 20 22 99 32 6 87 85 99 21 + + +x(:,:,3) = + + 56 15 13 95 74 14 56 99 18 92 90 46 + 63 19 50 9 7 4 86 54 36 11 8 11 + 4 5 86 11 87 94 35 71 6 75 25 100 + 62 64 88 15 94 31 45 100 53 74 6 34 + 37 29 28 17 99 30 6 29 34 57 45 30 + 5 54 21 63 86 34 18 42 18 19 2 7 + 49 70 57 58 79 47 67 47 21 60 90 30 + 20 50 65 6 52 65 34 77 91 30 20 5 + 13 54 42 94 18 3 90 82 68 14 10 51 + 21 45 21 73 40 85 12 11 47 22 31 77 + +x=randi(100,10,12,5) + +x(:,:,1) = + + 64 75 70 55 69 75 79 49 12 11 68 10 + 9 2 56 49 14 24 37 16 79 94 43 1 + 9 5 40 90 73 74 21 79 30 19 46 43 + 78 67 7 80 12 98 9 11 61 27 61 66 + 91 61 79 74 12 87 78 30 97 80 6 73 + 54 53 34 6 65 9 21 24 44 49 32 54 + 11 73 61 8 33 37 39 54 70 77 78 11 + 83 71 75 9 66 37 56 10 76 40 70 64 + 34 79 11 80 75 69 23 41 44 28 13 13 + 30 29 13 95 59 60 65 11 66 4 14 14 + + +x(:,:,2) = + + 10 56 99 16 60 13 76 17 81 3 76 32 + 15 19 18 39 34 3 75 67 75 93 23 82 + 17 22 26 17 30 30 75 90 13 66 7 79 + 20 8 40 76 46 32 11 52 53 94 77 86 + 32 92 8 88 43 66 69 71 33 17 68 51 + 32 71 69 36 36 96 47 16 55 93 72 64 + 22 56 41 69 56 94 22 96 40 80 65 96 + 26 32 99 30 75 46 10 55 42 58 42 45 + 90 17 41 54 43 25 83 68 19 45 40 7 + 71 63 63 84 43 77 18 4 26 26 82 87 + + +x(:,:,3) = + + 64 19 23 63 28 99 14 95 42 36 79 23 + 36 73 38 3 25 7 22 68 61 98 70 27 + 100 38 9 92 46 94 19 99 76 35 1 68 + 23 85 65 81 23 2 5 77 59 89 85 48 + 66 74 19 75 81 69 11 34 56 46 93 63 + 61 58 5 82 99 79 62 67 59 42 78 24 + 39 18 73 39 3 54 94 25 52 22 5 18 + 15 96 35 62 54 89 36 30 9 13 38 83 + 3 27 67 58 9 90 42 69 72 31 71 77 + 43 93 39 54 81 63 99 53 100 73 73 94 + + +x(:,:,4) = + + 11 32 51 72 84 50 29 72 51 59 41 94 + 19 18 44 62 33 70 24 86 49 68 13 40 + 10 34 100 35 56 98 72 29 88 37 27 5 + 49 22 82 94 98 33 63 74 36 63 26 35 + 20 52 49 13 55 84 60 14 45 82 34 74 + 90 91 90 74 34 74 67 84 97 2 16 80 + 10 63 14 65 62 96 5 14 5 9 35 55 + 5 11 40 84 37 4 35 59 98 98 13 69 + 56 40 93 40 76 36 46 37 19 66 89 90 + 78 6 92 75 42 67 25 81 67 24 10 6 + + +x(:,:,5) = + + 31 29 51 3 95 83 41 39 46 28 58 12 + 5 55 65 56 55 85 67 46 21 72 33 82 + 20 99 31 31 73 38 94 25 90 29 46 33 + 73 72 14 94 58 60 82 79 77 90 72 25 + 73 84 48 99 3 88 49 89 89 83 89 35 + 88 44 37 29 45 94 76 92 29 40 73 38 + 59 48 79 81 65 67 42 56 68 50 2 55 + 8 57 79 90 53 21 98 60 67 70 68 57 + 93 27 67 60 38 66 99 15 13 84 44 40 + 81 75 14 89 94 8 87 90 41 61 44 40 + +out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1), 'UniformOutput', false), 1:size(x,2), 'UniformOutput', false) + +out = + + 1×12 cell array + + {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} {1×10 cell} + +out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1)), 1:size(x,2)) +Error using arrayfun +Non-scalar in Uniform output, at index 1, output 1. +Set 'UniformOutput' to false. + +out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1)), 1:size(x,2),'UniformOutput',false) + +out = + + 1×12 cell array + + {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} + +out = cat(2, out{:}) + +out = + + Columns 1 through 35 + + 159 50 129 174 230 203 109 106 130 154 123 130 142 224 219 155 139 224 133 197 144 159 80 86 146 76 213 189 145 66 121 108 213 255 248 + + Columns 36 through 70 + + 117 128 161 198 238 192 94 192 93 96 209 101 173 122 234 257 116 206 160 244 182 158 147 225 131 134 126 134 96 138 159 175 190 164 251 + + Columns 71 through 105 + + 183 130 203 167 153 183 135 100 125 154 100 161 196 197 242 132 190 152 129 207 75 264 83 206 209 131 149 123 143 138 205 146 93 218 188 + + Columns 106 through 120 + + 183 85 176 128 131 45 110 144 139 171 116 84 204 130 148 + +out = cat(1, out{:}) +Brace indexing is not supported for variables of this type. + +out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1)), 1:size(x,2),'UniformOutput',false) + +out = + + 1×12 cell array + + {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} {1×10 double} + +out = cat(1, out{:}) + +out = + + 159 50 129 174 230 203 109 106 130 154 + 123 130 142 224 219 155 139 224 133 197 + 144 159 80 86 146 76 213 189 145 66 + 121 108 213 255 248 117 128 161 198 238 + 192 94 192 93 96 209 101 173 122 234 + 257 116 206 160 244 182 158 147 225 131 + 134 126 134 96 138 159 175 190 164 251 + 183 130 203 167 153 183 135 100 125 154 + 100 161 196 197 242 132 190 152 129 207 + 75 264 83 206 209 131 149 123 143 138 + 205 146 93 218 188 183 85 176 128 131 + 45 110 144 139 171 116 84 204 130 148 + +size(out) + +ans = + + 12 10 + +size(x) + +ans = + + 10 12 5 + +size(out) + +ans = + + 12 10 + +out = arrayfun(@(var2) arrayfun(@(var1) sum(x(var1,var2,1:2:end),3), 1:size(x,1), 'UniformOutput', false), 1:size(x,2), 'UniformOutput', false) \ No newline at end of file diff --git a/Jesus/chiCuadrado.m b/Jesus/chiCuadrado.m index 7e9bceb..c138bfb 100644 --- a/Jesus/chiCuadrado.m +++ b/Jesus/chiCuadrado.m @@ -1,5 +1,5 @@ tbl = [68, 33, 217;... - 33, 35, 180]; + 33, 35, 180]; sumCol = sum(tbl)'; sumFil = sum(tbl,2)'; multSum = (sumCol * sumFil)'; diff --git a/Jesus/whiskerScBehavior.m b/Jesus/whiskerScBehavior.m index 455959a..dfa2afc 100644 --- a/Jesus/whiskerScBehavior.m +++ b/Jesus/whiskerScBehavior.m @@ -20,7 +20,7 @@ zz=[AsocPos1 AsocPos1]; zsczz(1:size(AsocPos1,1),i)=AsocPos1;%zscore(AsocPos1); AsocPosAll(:,i)=AsocPos1; -sp=[deeplabcut.speed deeplabcut.speed]; +%sp=[deeplabcut.speed deeplabcut.speed]; %idj1=AsocPos1>2; end figure diff --git a/Ross/PoolDifMech.m b/Ross/PoolDifMech.m new file mode 100644 index 0000000..7cd4456 --- /dev/null +++ b/Ross/PoolDifMech.m @@ -0,0 +1,1223 @@ +%% PoolDifMech + +clear +close all +clc +%% +dataDirs = { + '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\1.8.22\KS3__Nblocks2__9_9__0pt9__20\' + '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\4.8.22\KS3__Nblocks2__9_9__0pt9__20\' + '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\8.8.22\DifMech\VPL_E1_KS3__Nblocks2__9_9__0pt9__20\' + }; + +selUnitDirs = { + '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\1.8.22\KS3__Nblocks2__9_9__0pt9__20\m51_ECE_Processing_-10-to-10\PopulationAnalysis\SelectedUnitData.mat' + '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\4.8.22\KS3__Nblocks2__9_9__0pt9__20\m50_ECE_Processing_-10-to-10\PopulationAnalysis\SelectedUnitData.mat' + '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\8.8.22\DifMech\VPL_E1_KS3__Nblocks2__9_9__0pt9__20\m53_VPL_E1_DifMech_ECE_Processing_-10-to-10\PopulationAnalysis\SelectedUnitData.mat' + }; + +figureDir = '\\lsdf02.urz.uni-heidelberg.de\sd19b001\PainData\Corrected_Channel_Map\VPL\DifMechPooled'; +%% variables to be collected + +discStacks = false(0); +csts = []; +Data = []; +sortedDatapooled = []; +goodspooled = []; +%% collecting trial numbers early +chCond = 1; +nExpts = size(dataDirs, 1); +trialnumbers = []; +for cexpt = 1:nExpts + dataDir = dataDirs{cexpt}; + Conditions = dir([dataDir, '*analysis*.mat']); + [r, ~] = size(Conditions); + if r ~= 1 + fprintf(['multiple or no analysis files in directory...\n' ... + 'choose one \n']) + return + end + load([dataDir, Conditions.name]); + trialnumbers = [trialnumbers, size(Conditions(1).Triggers,chCond)]; +end + +constrials = min(trialnumbers); +%% User controlling variables +% Time lapse, bin size, and spontaneous and response windows +promptStrings = {'Viewing window (time lapse) [s]:','Response window [s]',... + 'Bin size [s]:'}; +defInputs = {'-2, 6', '0.1, 3', '0.05'}; +answ = inputdlg(promptStrings,'Inputs', [1, 30],defInputs); +if isempty(answ) + fprintf(1,'Cancelling...\n'); + return +else + timeLapse = str2num(answ{1}); %#ok<*ST2NM> + if numel(timeLapse) ~= 2 + timeLapse = str2num(inputdlg('Please provide the time window [s]:',... + 'Time window',[1, 30], '-0.1, 0.1')); + if isnan(timeLapse) || isempty(timeLapse) + fprintf(1,'Cancelling...') + return + end + end + responseWindow = str2num(answ{2}); + binSz = str2double(answ(3)); +end +fprintf(1,'Time window: %.2f - %.2f ms\n',timeLapse(1)*1e3, timeLapse(2)*1e3) +fprintf(1,'Response window: %.2f - %.2f ms\n',responseWindow(1)*1e3, responseWindow(2)*1e3) +fprintf(1,'Bin size: %.3f ms\n', binSz*1e3) +sponAns = questdlg('Mirror the spontaneous window?','Spontaneous window',... + 'Yes','No','Yes'); +spontaneousWindow = -flip(responseWindow); +if strcmpi(sponAns,'No') + spontPrompt = "Time before the trigger in [s] (e.g. -0.8, -0.6 s)"; + sponDef = string(sprintf('%.3f, %.3f',spontaneousWindow(1),... + spontaneousWindow(2))); + sponStr = inputdlg(spontPrompt, 'Inputs',[1,30],sponDef); + if ~isempty(sponStr) + spontAux = str2num(sponStr{1}); + if length(spontAux) ~= 2 || spontAux(1) > spontAux(2) || ... + spontAux(1) < timeLapse(1) + fprintf(1, 'The given input was not valid.\n') + fprintf(1, 'Keeping the mirror version!\n') + else + spontaneousWindow = spontAux; + end + end +end +fprintf(1,'Spontaneous window: %.2f to %.2f ms before the trigger\n',... + spontaneousWindow(1)*1e3, spontaneousWindow(2)*1e3) + + + + +%% loading variables for a given experiment - Starting the for-loop + +for cexpt = 1:nExpts + dataDir = dataDirs{cexpt}; + selUnits = selUnitDirs{cexpt}; + + Conditions = dir([dataDir, '*analysis*.mat']); + [r, ~] = size(Conditions); + if r ~= 1 + fprintf(['multiple or no analysis files in directory...\n' ... + 'choose one \n']) + return + end + load([dataDir, Conditions.name]); + + % homogenising trial numbers + Conditions(chCond).Triggers = Conditions(chCond).Triggers(1:constrials,:); + + + sortedData = dir([dataDir, '*all_channels*.mat']); + [r, ~] = size(sortedData); + if r ~= 1 + fprintf(['multiple or no all_channels files in directory...\n' ... + 'choose one \n']) + return + end + load([dataDir, sortedData.name]); + + clInfo = getClusterInfo([dataDir filesep 'cluster_info.tsv']); + + if any(ismember(clInfo.Properties.VariableNames,'ActiveUnit')) + clInfo = removevars(clInfo, 'ActiveUnit'); + end + + + expID = dir([dataDir, '*expParams*.mat']); + [r, ~] = size(expID); + if r ~= 1 + fprintf(['multiple or no expParams files in directory...\n']) + return + end + load([dataDir, expID.name], 'expID'); + + load(selUnits, 'unit_ids') + + + %% renaming units to avoid confusion + + + for i = 1:length(sortedData) + sortedData{i,1} = [expID, '_unit_', sortedData{i,1}]; + end + + for i = 1:height(clInfo) + clInfo.id{i,1} = [expID, '_unit_', clInfo.id{i,1}]; + clInfo.Properties.RowNames{i,1} = clInfo.id{i,1}; + end + + for i = 1:length(unit_ids) + unit_ids{i} = [expID, '_unit_', unit_ids{i,1}]; + end + + + + %% global variables + + goods = find(ismember(sortedData(:,1), unit_ids)); + + Triggers.MechStim = Triggers.MechStim * -1; + + % Number of total samples + Ns = min(structfun(@numel,Triggers)); + % Total duration of the recording + Nt = Ns/fs; + + gclID = sortedData(goods,1); + % Logical spike trace for the first good cluster + spkLog = StepWaveform.subs2idx(round(sortedData{goods(1),2}*fs),Ns); + % Subscript column vectors for the rest good clusters + spkSubs = cellfun(@(x) round(x.*fs),sortedData(goods,2),... + 'UniformOutput',false); + % Number of good clusters + Ncl = numel(goods); + % Redefining the stimulus signals from the low amplitude to logical values + whStim = {'piezo','whisker','mech','audio'}; + cxStim = {'laser','light'}; + lfpRec = {'lfp','s1','cortex','s1lfp'}; + trigNames = fieldnames(Triggers); + numTrigNames = numel(trigNames); + ctn = 1; + continuousSignals = cell(numTrigNames,1); + continuousNameSub = zeros(size(trigNames)); + while ctn <= numTrigNames + if contains(trigNames{ctn},whStim,'IgnoreCase',true) + continuousSignals{ctn} = Triggers.(trigNames{ctn}); + continuousNameSub(ctn) = ctn; + end + if contains(trigNames{ctn},cxStim,'IgnoreCase',true) + continuousSignals{ctn} = Triggers.(trigNames{ctn}); + continuousNameSub(ctn) = ctn; + end + if contains(trigNames{ctn},lfpRec,'IgnoreCase',true) + continuousSignals{ctn} = Triggers.(trigNames{ctn}); + continuousNameSub(ctn) = ctn; + end + ctn = ctn + 1; + end + continuousSignals(continuousNameSub == 0) = []; + continuousNameSub(continuousNameSub == 0) = []; + trigNames = trigNames(continuousNameSub); + + + + Data = [Data; clInfo(:,1:12)]; + + %% Constructing the stack out of the user's choice + + + onOffStr = 'on'; + + % discStack - dicrete stack has a logical nature + % cst - continuous stack has a numerical nature + % Both of these stacks have the same number of time samples and trigger + % points. They differ only in the number of considered events. + + [~, cst] = getStacks(false,Conditions(chCond).Triggers,onOffStr,... + timeLapse,fs,fs,spkSubs,continuousSignals); + if cexpt == 1 + nTriggerscst = size(cst, 1); + end + + + + while size(cst, 1) > nTriggerscst + cst(end,:,:) = []; + end + + + + + while size(cst, 1) < nTriggerscst + csts(end,:,:) = []; + end + + discStack = getStacks(false,Conditions(chCond).Triggers,onOffStr,... + timeLapse,fs,fs,spkSubs,continuousSignals); + if cexpt == 1 + discStack(2,:,:) = []; + else + discStack(1:2,:,:) = []; + end + + %% concatenating important variables across expts + + tic + discStacks = cat(1, discStacks, discStack); + toc + csts = cat(1, csts, cst); + + + goodsoffset = size(sortedDatapooled,1); + goodspooled = cat(1, goodspooled, goods + goodsoffset); + + sortedDatapooled = cat(1, sortedDatapooled, sortedData); + +end +%% +discStack = discStacks; clear discStacks +cst = [mean(csts([1,3,5],:,:)); mean(csts([2,4,6],:,:))]; clear csts +sortedData = sortedDatapooled; clear sortedDatapooled +goods = goodspooled; clear goodspooled +[Ne, Nt, NTa] = size(discStack); +Ncl = numel(goods); +% Computing the time axis for the stack +tx = (0:Nt - 1)/fs + timeLapse(1); + +condNames = arrayfun(@(x) x.name,Conditions,'UniformOutput',false); +consideredConditions = find(~ismember(1:length(Conditions), chCond)); +Nccond = length(consideredConditions); +%% Boolean flags +delayFlags = false(NTa,Nccond); +counter2 = 1; +for ccond = consideredConditions + delayFlags(:,counter2) = ismember(Conditions(chCond).Triggers(:,1),... + Conditions(ccond).Triggers(:,1)); + counter2 = counter2 + 1; +end +Na = sum(delayFlags,1); + +%% Computing which units/clusters/putative neurons respond to the stimulus +% Logical indices for fetching the stack values +gclID = sortedData(goods,1); +expName = 'pooled'; +sponActStackIdx = tx >= spontaneousWindow(1) & tx <= spontaneousWindow(2); +respActStackIdx = tx >= responseWindow(1) & tx <= responseWindow(2); +% The spontaneous activity of all the clusters, which are allocated from +% the second until one before the last row, during the defined spontaneous +% time window, and the whisker control condition. + +timeFlags = [sponActStackIdx;respActStackIdx]; +% Time window +delta_t = diff(responseWindow); +% Statistical tests +[Results, Counts] = statTests(discStack, delayFlags, timeFlags); + +indCondSubs = cumsum(Nccond:-1:1); +consCondNames = condNames(consideredConditions); +% Plotting statistical tests +[Figs, Results] = scatterSignificance(Results, Counts,... + consCondNames, delta_t, sortedData(goods,1)); +configureFigureToPDF(Figs); +stFigBasename = fullfile(figureDir,[expName,' ']); +stFigSubfix = sprintf(' Stat RW%.1f-%.1fms SW%.1f-%.1fms',... + responseWindow(1)*1e3, responseWindow(2)*1e3, spontaneousWindow(1)*1e3,... + spontaneousWindow(2)*1e3); +ccn = 1; +%for cc = indCondSubs +for cc = 1:numel(Figs) + if ~ismember(cc, indCondSubs) + altCondNames = strsplit(Figs(cc).Children(2).Title.String,': '); + altCondNames = altCondNames{2}; + else + altCondNames = consCondNames{ccn}; + ccn = ccn + 1; + end + stFigName = [stFigBasename, altCondNames, stFigSubfix]; + % if ~exist([stFigName,'.pdf'],'file') || ~exist([stFigName,'.emf'],'file') + % print(Figs(cc),[stFigName,'.pdf'],'-dpdf','-fillpage') + % print(Figs(cc),[stFigName,'.emf'],'-dmeta') + % end + savefig(Figs(cc),fullfile(figureDir, [altCondNames, stFigSubfix '.fig'])); +end + +H = cell2mat(cellfun(@(x) x.Pvalues,... + arrayfun(@(x) x.Activity, Results(indCondSubs), 'UniformOutput', 0),... + 'UniformOutput', 0)) < 0.05; + +Htc = sum(H,2); +CtrlCond = contains(consCondNames,'control','IgnoreCase',true); +if ~nnz(CtrlCond) + CtrlCond = true(size(H,2),1); +end +wruIdx = any(H(:,CtrlCond),2); +Nwru = nnz(wruIdx); + +fprintf('%d responding clusters:\n', Nwru); +fprintf('- %s\n',gclID{wruIdx}) + +%% Addition mean signals to the Conditions variable +if ~isfield(Conditions,'Stimulus') ||... + any(arrayfun(@(x) isempty(x.Stimulus), Conditions(consideredConditions))) + fprintf(1,'Writting the stimulus raw signal into Conditions variable:\n') + whFlag = contains(trigNames, whStim, 'IgnoreCase', 1); + lrFlag = contains(trigNames, cxStim, 'IgnoreCase', 1); + cdel = 1; + for cc = consideredConditions + fprintf(1,'- %s\n', Conditions(cc).name) + Conditions(cc).Stimulus = struct(... + 'Mechanical',reshape(mean(cst((1),:,delayFlags(:,cdel)),3),... + 1,Nt),... + 'MechPressure',reshape(mean(cst((2),:,delayFlags(:,cdel)),3),... + 1,Nt),'TimeAxis',(0:Nt-1)/fs + timeLapse(1)); + cdel = cdel + 1; + end + %save(fullfile(dataDir,[expName,'_analysis.mat']),'Conditions','-append') +end + + +%% Filter question +filterIdx = true(Ne,1); +ansFilt = questdlg('Would you like to filter for significance?','Filter',... + 'Yes','No','Yes'); +filtStr = 'unfiltered'; +if strcmp(ansFilt,'Yes') + filterIdx = [true; wruIdx]; + filtStr = 'Filtered'; +end +%ruIdx = wruIdx; + + +%% Ordering PSTH + +orderedStr = 'ID ordered'; +dans = questdlg('Do you want to order the PSTH other than by IDs?',... + 'Order', 'Yes', 'No', 'No'); +ordSubs = 1:nnz(filterIdx(2:Ncl+1)); +pclID = gclID(filterIdx(2:end)); +if strcmp(dans, 'Yes') + % if ~exist('clInfo','var') + % clInfo = getClusterInfo(fullfile(dataDir,'cluster_info.tsv')); + % end + % varClass = varfun(@class,clInfo,'OutputFormat','cell'); + [ordSel, iOk] = listdlg('ListString', Data.Properties.VariableNames,... + 'SelectionMode', 'multiple'); + orderedStr = []; + ordVar = Data.Properties.VariableNames(ordSel); + for cvar = 1:numel(ordVar) + orderedStr = [orderedStr, sprintf('%s ',ordVar{cvar})]; %#ok + end + orderedStr = [orderedStr, 'ordered']; + + if ~strcmp(ordVar,'id') + [~,ordSubs] = sortrows(Data(pclID,:),ordVar, 'ascend'); + end +end +%% Plot PSTH +% goodsIdx = logical(clInfo.ActiveUnit); +csNames = fieldnames(Triggers); +while size(csNames,1) > size(cst) + csNames(end) = []; +end + +Nbn = diff(timeLapse)/binSz; +if (Nbn - round(Nbn)) ~= 0 + Nbn = ceil(Nbn); +end +PSTH = zeros(nnz(filterIdx) - 1, Nbn, Nccond); +psthFigs = gobjects(Nccond,1); +for ccond = 1:Nccond + figFileName = sprintf('%s %s VW%.1f-%.1f ms B%.1f ms RW%.1f-%.1f ms SW%.1f-%.1f ms %sset %s (%s)',... + expName, Conditions(consideredConditions(ccond)).name, timeLapse*1e3,... + binSz*1e3, responseWindow*1e3, spontaneousWindow*1e3, onOffStr,... + orderedStr, filtStr); + [PSTH(:,:,ccond), trig, sweeps] = getPSTH(discStack(filterIdx,:,:),timeLapse,... + ~delayFlags(:,ccond),binSz,fs); + stims = mean(cst(:,:,delayFlags(:,ccond)),3); + stims = stims - median(stims,2); + for cs = 1:size(stims,1) + if abs(log10(var(stims(cs,:),[],2))) < 15 + [m,b] = lineariz(stims(cs,:),1,0); + stims(cs,:) = m*stims(cs,:) + b; + else + stims(cs,:) = zeros(1,Nt); + end + end + psthFigs(ccond) = plotClusterReactivity(PSTH(ordSubs,:,ccond),trig,sweeps,timeLapse,binSz,... + [{Conditions(consideredConditions(ccond)).name};... + pclID(ordSubs)],... + strrep(expName,'_','\_'),... + stims, csNames); + configureFigureToPDF(psthFigs(ccond)); + psthFigs(ccond).Children(end).YLabel.String =... + [psthFigs(ccond).Children(end).YLabel.String,... + sprintf('^{%s}',orderedStr)]; + % if ~exist([figFileName,'.pdf'], 'file') + % print(psthFigs(ccond), fullfile(figureDir,[figFileName, '.pdf']),... + % '-dpdf','-fillpage') + % end + % if ~exist([figFileName,'.emf'], 'file') + % print(psthFigs(ccond), fullfile(figureDir,[figFileName, '.emf']),... + % '-dmeta') + % end + +end +% for a = 1:length(consideredConditions) +% savefig(figure(a), fullfile(figureDir, [consCondNames{a}, '_filtered_PSTH_0.001binSz.fig'])); +% end + + +%% Getting cluster info and adding variables to table + +ActiveUnit = false(height(Data),1); +Data = addvars(Data,ActiveUnit,'NewVariableNames','ActiveUnit','After','id'); +Data{goods, 'ActiveUnit'} = true; + +window = diff(responseWindow); + +for a = 1: length(consCondNames) + Data{Data.ActiveUnit == true,[consCondNames{1,a}, '_Rate_Spont']} = mean(Counts{a,1}')'/window; + Data{Data.ActiveUnit == true,[consCondNames{1,a}, '_Rate_Evoked']} = mean(Counts{a,2}')'/window; +end + + +% Significant mechanical responses per condition +b = length(consCondNames); +for a = 1 : length(consCondNames) + Data{Data.ActiveUnit == true,[consCondNames{1,a}, '_R']} = Results(b).Activity(1).Pvalues < 0.05; + b = b + length(consCondNames) - a; +end + +% Comparing Across Conditions (i.e. manipulation effect on spontaneous and evoked activity) +% RAM: comment to explain what you are doing +sZ = size(Counts); +d = length(consCondNames); +e = 1; +f = length(consCondNames); +for a = 1:length(consCondNames) - 1 + for b = (a + 1): length(consCondNames) + + for c = 1: sZ(1,2) + Data{Data.ActiveUnit == true,[consCondNames{1,a},'_vs_',consCondNames{1,b}, '_', Results(e).Activity(c).Type, '_Response']} = Results(e).Activity(c).Pvalues < 0.05; + %RAM example + %myString = [consCondNames{1,a},'_vs_',consCondNames{1,b}, '_', Results(e).Activity(c).Type, '_Response']; + %clInfo{clInfo.ActiveUnit == true,myString} = Results(e).Activity(c).Pvalues < 0.05; + + end + + e = e + 1; + + if e == f + e = e + 1; + end + end + d = d - 1; + f = f + d; +end +writeClusterInfo(Data, fullfile(figureDir,'cluster_info_TonicResponses.tsv')); + +%% Rasters +% DE_Jittering needs to be unfiltered for significance for this to work! +csNames = fieldnames(Triggers); +% csNames = csNames(2:end); +IDs = csNames; +trigTX = linspace(timeLapse(1),timeLapse(2),size(trig,2)); + +rasterDir = fullfile(figureDir,'Rasters\'); +if ~mkdir(rasterDir) + fprintf(1,'There was an issue with the figure folder...\n'); +end + + +Power = NaN(length(consCondNames),1); +for cc = 1:length(consCondNames) + + mWfind = strfind(consCondNames{cc}, 'mW'); + + pwr = consCondNames{cc}(mWfind-2:mWfind+1); + if isnan(pwr) + pwrMissing = true; + elseif contains(pwr, '.') + pwr = consCondNames{cc}(mWfind-3:mWfind+1); + elseif contains(pwr, '_') || contains(pwr, ' ') + pwr = pwr(2:end); + end + pwr = str2double(pwr(1:end-2)); + Power(cc) = pwr; +end +pwrs = unique(Power); + +med = 0.2; +low = 0.4; +high = 0; +colours = ones(1,3); +colours(1:4,:) = med; colours(5:8,:) = low; colours(9:10,:) = high; + +for a = 1%:length(pwrs) + pwr = pwrs(a); + % MchTblInd = ['Mech_Control_', num2str(pwr), 'mW_MR']; + % LasTblInd = [20,21,22];%['Laser_Control_', num2str(pwr), 'mW_LR']; + % MchCondControl = ['Mech_Control_', num2str(pwr), 'mW']; + % LasCondControl = ['Laser_Control_', num2str(pwr), 'mW']; + % MchLasCond = ['Mech_Laser_', num2str(pwr), 'mW']; + % EffectTblInd = ['Mech_Control_', num2str(pwr), 'mW_vs_Mech_Laser_', num2str(pwr), 'mW_Evoked_Response']; + % TblInd = find(clInfo.ActiveUnit); % ATM this only makes rasters that show sig control mech response + % clIDind = clInfo.id(TblInd); + % pwrInd = Power == pwr; + clIDind = Data.id(Data.Mech_Low_R); + lngth = length(clIDind); + for a = 1:lngth + rng('default'); + cl = clIDind(a); + clSel = find(ismember(pclID, cl)); + % if chCond == 1 + % rasCondSel = find(ismember(consCondNames, MchCondControl) | ismember(consCondNames, MchLasCond)); + % label = 'Mech'; + % else + % rasCondSel = find(ismember(consCondNames, LasCondControl) | ismember(consCondNames, MchLasCond)); + % label = 'Laser'; + % end + rasCondSel = [1 2 3]; + rasCond = consideredConditions(rasCondSel); + rasCondNames = consCondNames(rasCondSel); + Nrcl = numel(clSel); + % Reorganize the rasters in the required order. + clSub = find(ismember(gclID, pclID(clSel)))+1; + [rasIdx, rasOrd] = ismember(pclID(ordSubs), pclID(clSel)); + clSub = clSub(rasOrd(rasIdx)); + clSel = clSel(rasOrd(rasOrd ~= 0)); + Nma = min(Na(rasCondSel)); + rasFig = figure; + columns = length(pwrs); + Nrcond = length(rasCond); + ax = gobjects(4*Nrcond*Nrcl,1); + lidx = 1; + for cc = 1:length(rasCond) + % Equalize trial number + trigSubset = sort(randsample(Na(rasCondSel(cc)),Nma)); + tLoc = find(delayFlags(:,rasCondSel(cc))); + tSubs = tLoc(trigSubset); + % Trigger subset for stimulation shading + trigAlSubs = Conditions(rasCond(cc)).Triggers(trigSubset,:); + timeDur = round(diff(trigAlSubs, 1, 2)/fs, 3); + trigChange = find(diff(timeDur) ~= 0); + for ccl = 1:Nrcl + + stims = mean(cst(:,:,delayFlags(:,rasCondSel(cc))),3); + % stims = stims([2,3],:); + + stims = stims - median(stims,2); + + + + for cs = 2 %for cs = 1:size(stims,1) + if abs(log10(var(stims(cs,:),[],2))) < 13 + [m,b] = lineariz(stims(cs,:),1,0); + stims(cs,:) = m*stims(cs,:) + b; + else + stims(cs,:) = zeros(1,Nt); + end + end + + [r,c] = size(stims); + + if r < c + stims = stims'; + stmClr = zeros(r, 3); + + end + + + + + for cs = 2 %for cs = 1:size(stims,1) + if stims(1,cs) > 0.5 + stim = ones(size(stims(:,cs)))-stims(:,cs); + else + stim = stims(:,cs); + end + % dP=[0; diff(stim)]; + stim = smooth(stim,10); + ax(lidx) = subplot(4*Nrcond, Nrcl, lidx); + if exist('IDs','var') + plot(trigTX,stim, 'LineStyle','-','LineWidth', 1,... + 'DisplayName', IDs{cs}, 'Color', stmClr(cs,:)) + % P = stim'; %ax(lidx).Children.YData; + % dP = [0 diff(P)]; + % dP = smooth(dP,100); + % dP = dP-mean(dP(1:100));dP=dP/max(dP); + % + % yyaxis right + % plot(trigTX, dP, 'LineStyle','-','LineWidth', 1,... + % 'DisplayName', IDs{cs}, 'Color', stmClr(cs,:)) + else + plot(trigTX,stim,'LineStyle','-','LineWidth',1, 'Color', stmClr(cs,:)) + + % P = ax(lidx).Children.YData; + % dP = [0 diff(P)]; + % dP = smooth(dP,100); + % dP = dP-mean(dP(1:100));dP=dP/max(dP); + % yyaxis right + % plot(trigTX, dP, 'LineStyle','-','LineWidth', 1,... + % 'DisplayName', IDs{cs}, 'Color', stmClr(cs,:)) + end + ax(lidx).Visible = 'off'; + + + % ax2.Children(1).Color = defineColorForStimuli(IDs(cs)); + + if cs == 1 + ax2.NextPlot = 'add'; + end + + end + % ax = gca; + % + % + % % ax.YAxis(2).Limits = [0.015, 1]; + % % ax.YAxis(2).Visible = 'off'; + % ax.FontName ='Arial'; + % ax.FontSize = 12; + + % f=get(gca,'Children'); + % legend(f) + % + lidx = lidx + 1; + + + % lidx = ccl + (cc - 1) * Nrcl; + ax(lidx) = subplot(4*Nrcond, Nrcl, lidx:lidx+2); % subplot( Nrcl, Nrcond, lidx); % to plot the other way around + title(ax(lidx),sprintf(rasCondNames{cc}), 'Interpreter', 'none') % ,pclID{clSel(ccl)} + plotRasterFromStack(discStack([1,clSub(ccl)],:,tSubs),... + timeLapse, fs,'',ax(lidx)); + % plotRasterFromStack(discStack([1,clSub(ccl)],:,tSubs),... + % timeLapse, fs,'',colours(lidx,:),ax(lidx)); + ax(lidx).YAxisLocation = 'origin';ax(lidx).YAxis.TickValues = Nma; + ax(lidx).YAxis.Label.String = 'Trials'; + % ax(lidx).YAxis.Label.Position =... + % [timeLapse(1)-timeLapse(1)*0.65, Nma,0]; + % ax(lidx).XAxis.TickLabels =... + % cellfun(@(x) (x)*1e3, ax(lidx).XAxis.TickValues,... + % 'UniformOutput', 0); + xlabel(ax(lidx), 'Time [s]') + initSub = 0; + optsRect = {'EdgeColor','none','FaceColor','none'}; + for ctr = 1:numel(trigChange) + rectangle('Position',[0, initSub,... + timeDur(trigChange(ctr)), trigChange(ctr)],optsRect{:}) + initSub = trigChange(ctr); + end + rectangle('Position', [0, initSub, timeDur(Nma),... + Nma - initSub],optsRect{:}) + + % ax(lidx).XAxis.Visible = 'off'; + ax(lidx).YAxis.Visible = 'off'; + stims = mean(cst(:,:,delayFlags(:,rasCondSel(cc))),3); + % stims = stims([2,3],:); + + stims = stims - median(stims,2); + + + + for cs = 2 %for cs = 1:size(stims,1) + if abs(log10(var(stims(cs,:),[],2))) < 13 + [m,b] = lineariz(stims(cs,:),1,0); + stims(cs,:) = m*stims(cs,:) + b; + else + stims(cs,:) = zeros(1,Nt); + end + end + + [r,c] = size(stims); + + if r < c + stims = stims'; + stmClr = zeros(r, 3); + + end + + % stmClr =[ 1 0 0 0.25; 0 1 1 0.25]; + + + + lidx = lidx + 3; + + + end + end + + + + + + rasConds = rasCondNames{1}; + if length(rasCondNames) > 1 + for r = 2:length(rasCondNames) + rasConds = [rasConds, '+', rasCondNames{r}]; + end + end + + + ax(2).Title.Color = colours(2,:); + ax(6).Title.Color = colours(6,:); + ax(10).Title.Color = colours(10,:); + ax(1).Children.Color = colours(1,:); + ax(5).Children.Color = colours(5,:); + ax(9).Children.Color = colours(9,:); + + + linkaxes(ax,'x') + rasFigName = ['Unit_', cell2mat(cl), '_', ]; + rasFig.Name = [rasFigName, '_', num2str(pwr), 'mW']; + configureFigureToPDF (rasFig); + set(rasFig, 'Position', get(0, 'ScreenSize')/2); + saveas(rasFig,fullfile(rasterDir, [rasFigName,'_',rasConds,'_', num2str(timeLapse(1)), '_to_', num2str(timeLapse(2)),'.emf'])); + %savefig(rasFig,fullfile(rasterDir, [rasFigName, ' ', num2str(pwr), 'mW.fig'])); + savefig(rasFig,fullfile(rasterDir, [rasFigName,'_',rasConds, '.fig'])); + end +end + + +%% print mech responses to pdf +targetdir = [figureDir filesep 'difMech']; %put all individual pdfs here, replace blocking with whatever makes sense +mergedir=print_all_figs(targetdir,'-dpdf'); %print all open figures to pdf +cd(figureDir) +merge_PDF_dir(mergedir) %merge all single figure pdfs to one large pdf, in this directory + + +%% Ordering PSTH +filterIdx = [true; ismember(gclID, Data.id(Data.Mech_Low_R))]; +orderedStr = 'ID ordered'; +ordSubs = 1:nnz(filterIdx(2:Ncl+1)); +pclID = gclID(filterIdx(2:end)); + + + + +%% PSTHs for comparisons +binSz = 0.5; +% goodsIdx = logical(clInfo.ActiveUnit); +csNames = fieldnames(Triggers); +while size(csNames,1) > size(cst) + csNames(end) = []; +end + +Nbn = diff(timeLapse)/binSz; +if (Nbn - round(Nbn)) ~= 0 + Nbn = ceil(Nbn); +end +PSTH = zeros(nnz(filterIdx) - 1, Nbn, Nccond); +psthFigs = gobjects(Nccond,1); +for ccond = 1:Nccond + figFileName = sprintf('%s %s VW%.1f-%.1f ms B%.1f ms RW%.1f-%.1f ms SW%.1f-%.1f ms %sset %s (%s)',... + expName, Conditions(consideredConditions(ccond)).name, timeLapse*1e3,... + binSz*1e3, responseWindow*1e3, spontaneousWindow*1e3, onOffStr,... + orderedStr, filtStr); + [PSTH(:,:,ccond), trig, sweeps] = getPSTH(discStack(filterIdx,:,:),timeLapse,... + ~delayFlags(:,ccond),binSz,fs); + stims = mean(cst(:,:,delayFlags(:,ccond)),3); + stims = stims - median(stims,2); + for cs = 1:size(stims,1) + if abs(log10(var(stims(cs,:),[],2))) < 13 + [m,b] = lineariz(stims(cs,:),1,0); + stims(cs,:) = m*stims(cs,:) + b; + else + stims(cs,:) = zeros(1,Nt); + end + end + PSTH = PSTH./binSz/sum(delayFlags(:,1)); + +end + +%% +for unit = 1:size(PSTH, 1) + figure('Name',['unit_', pclID{unit}], 'Color', 'white') + hold on + for ccond = 1:length(consideredConditions) + plot(PSTH(unit,:,ccond)); + end + ax = gca; + legend(consCondNames); + ax.XTickLabel = ax.XTick*binSz-2; + +end + + +%% PopPSTH By Group +colours = [0,0,0.75; 0, 0.75, 0; 0.75, 0, 0.75]; +figure('Name','DifMech_PopPSTH', 'Color','white'); hold on +[Ncl, Npt, Nconds] = size(PSTH); +psthTX = linspace(timeLapse(1),timeLapse(2),Npt); +trigTX = linspace(timeLapse(1),timeLapse(2),size(trig,2)); +for ccond = 1:length(consideredConditions) + + + medPSTH = median(sum(PSTH(:,1:40,ccond),1,'omitnan')/(Ncl * sweeps * binSz)); + popPSTH = sum(PSTH(:,:,ccond),1,'omitnan')/(Ncl * sweeps * binSz); + % popPSTH = popPSTH-medPSTH; + popPSTH = smooth(popPSTH, 5); + plot(psthTX,popPSTH, 'LineWidth',1.5, 'Color',colours(ccond,:)); + + +end +leg = legend; +leg.String = consCondNames; +leg.Box = 'off'; +leg.FontName = 'Arial'; +ax = gca; +ax.FontSize = 25; +leg.Location = 'northeast'; +ax.XTickLabel = ax.XTick*binSz-2; + +%% Absolute Pressure Difference Comparison +trigTX = linspace(timeLapse(1),timeLapse(2),size(trig,2)); +colours = [0,0,0.75; 0, 0.75, 0; 0.75, 0, 0.75]; +cs = 2; +stims = mean(cst,3); +[m,b] = lineariz(stims(cs,:),1,0); +stims(cs,:) = m*stims(cs,:) + b; +% figure('Color','white', 'Name', 'AvPressure'); +% plot(stims(cs,:)) + +figure('Color','white', 'Name', 'Pressures'); + +hold on + +for ccond = 1:Nccond + stims = mean(cst(:,:,delayFlags(:,ccond)),3); + if abs(log10(var(stims(cs,:),[],2))) < 15 + stims(cs,:) = m*stims(cs,:) + b; + stims(cs,:) = stims(cs,:) - min(stims(cs,:)); + + stims(cs,:) = smooth(stims(cs,:),10^4); + else + stims(cs,:) = zeros(1,Nt); + end + plot(trigTX, stims(cs,:), 'Color',colours(ccond,:), 'LineWidth',2) +end + +leg = legend; +leg.String = consCondNames; +leg.Box = 'off'; +leg.FontName = 'Arial'; +ax = gca; +ax.FontSize = 25; +leg.Location = 'northeast'; + +%% Delta Pressure Difference Comparison + +colours = [0,0,0.75; 0, 0.75, 0; 0.75, 0, 0.75]; +cs = 2; +stims = mean(cst,3); +[m,b] = lineariz(stims(cs,:),1,0); +stims(cs,:) = m*stims(cs,:) + b; +% figure('Color','white', 'Name', 'AvPressure'); +% plot(stims(cs,:)) + +figure('Color','white', 'Name', '\Delta Pressures'); + +hold on + +for ccond = 1:Nccond + stims = mean(cst(:,:,delayFlags(:,ccond)),3); + if abs(log10(var(stims(cs,:),[],2))) < 15 + stims(cs,:) = m*stims(cs,:) + b; + stims(cs,:) = stims(cs,:) - min(stims(cs,:)); + + stims(cs,:) = smooth(stims(cs,:),10^4); + else + stims(cs,:) = zeros(1,Nt); + end + stim = diff(stims(cs,:)); + stim = smooth(stim, 10^4); + plot(stim, 'color', colours(ccond,:), 'LineWidth', 1.25); +end +fig = gcf; +ax = gca; +ax.FontName = 'Arial'; +ax.FontSize = 25; + +%% Rasters + +csNames = fieldnames(Triggers); +% csNames = csNames(2:end); +IDs = csNames; +trigTX = linspace(timeLapse(1),timeLapse(2),size(trig,2)); + + +rasterDir = fullfile(figureDir,'Rasters\'); +if ~mkdir(rasterDir) + fprintf(1,'There was an issue with the figure folder...\n'); +end + +colours = [0,0,0.75; 0, 0.25, 0; 0.5, 0, 0.5]; +cs = 2; + +clIDind = pclID; +lngth = length(clIDind); +for a = 1:lngth + rng('default'); + cl = clIDind(a); + clSel = find(ismember(pclID, cl)); + % if chCond == 1 + % rasCondSel = find(ismember(consCondNames, MchCondControl) | ismember(consCondNames, MchLasCond)); + % label = 'Mech'; + % else + % rasCondSel = find(ismember(consCondNames, LasCondControl) | ismember(consCondNames, MchLasCond)); + % label = 'Laser'; + % end + rasCondSel = [1 2 3]; + rasCond = consideredConditions(rasCondSel); + rasCondNames = consCondNames(rasCondSel); + Nrcl = numel(clSel); + % Reorganize the rasters in the required order. + clSub = find(ismember(gclID, pclID(clSel)))+1; + [rasIdx, rasOrd] = ismember(pclID(ordSubs), pclID(clSel)); + clSub = clSub(rasOrd(rasIdx)); + clSel = clSel(rasOrd(rasOrd ~= 0)); + Nma = min(Na(rasCondSel)); + rasFig = figure('Color','white'); + Nrcond = length(rasCond); + ax = gobjects(4*Nrcond*Nrcl,1); + lidx = 1; + for cc = 1:length(rasCond) + % Equalize trial number + trigSubset = sort(randsample(Na(rasCondSel(cc)),Nma)); + tLoc = find(delayFlags(:,rasCondSel(cc))); + tSubs = tLoc(trigSubset); + % Trigger subset for stimulation shading + trigAlSubs = Conditions(rasCond(cc)).Triggers(trigSubset,:); + timeDur = round(diff(trigAlSubs, 1, 2)/fs, 3); + trigChange = find(diff(timeDur) ~= 0); + + for ccl = 1:Nrcl + ax(lidx) = subplot(6*Nrcond, Nrcl, lidx:lidx+1); + % subplot( Nrcl, Nrcond, lidx); % to plot the other way around + % title(ax(lidx),sprintf(rasCondNames{cc}), 'Interpreter', 'none') % ,pclID{clSel(ccl)} + + plotRasterFromStack(discStack([1,clSub(ccl)],:,tSubs),... + timeLapse, fs,'',ax(lidx)); + ax(lidx).YAxisLocation = 'origin';ax(lidx).YAxis.TickValues = Nma; + ax(lidx).YAxis.Label.String = 'Trials'; + + xlabel(ax(lidx), 'Time [s]') + initSub = 0; + optsRect = {'EdgeColor','none','FaceColor','none'}; + for ctr = 1:numel(trigChange) + rectangle('Position',[0, initSub,... + timeDur(trigChange(ctr)), trigChange(ctr)],optsRect{:}) + initSub = trigChange(ctr); + end + rectangle('Position', [0, initSub, timeDur(Nma),... + Nma - initSub],optsRect{:}) + + ax(lidx).XAxis.Visible = 'off'; + ax(lidx).YAxis.Visible = 'off'; + + lidx = lidx + 2; + + + + + ax(lidx) = subplot(6*Nrcond, Nrcl, lidx:lidx+3); + stims = mean(cst(:,:,delayFlags(:,rasCondSel(cc))),3); + if abs(log10(var(stims(cs,:),[],2))) < 15 + stims(cs,:) = m*stims(cs,:) + b; + stims(cs,:) = stims(cs,:) - min(stims(cs,:)); + + stims(cs,:) = smooth(stims(cs,:),10^4); + else + stims(cs,:) = zeros(1,Nt); + end + stim = [0, diff(stims(cs,:))]; + stim = smooth(stim, 10^4); + % stim = stim - min(stim); + + yyaxis right + plot(trigTX,stim, 'Color',colours(rasCondSel(cc),:), 'LineWidth',1.5) + ylim([-10^-4, 10^-4]); + + + + yyaxis left + if exist('IDs','var') + area(trigTX,stims(cs,:), 'FaceColor', [0.75,0.75,0.75], 'LineStyle','none') + + + else + area(trigTX,stim(cs,:), 'FaceColor', [0.75,0.75,0.75], 'LineStyle','none') + + end + ax(lidx).Visible = 'off'; + ylim([-1,1]); + + + + if cs == 1 + ax2.NextPlot = 'add'; + end + + end + + + + + + + + + + + + lidx = lidx + 4; + + + end + + + + + + + rasConds = rasCondNames{1}; + if length(rasCondNames) > 1 + for r = 2:length(rasCondNames) + rasConds = [rasConds, '+', rasCondNames{r}]; + end + end + + + + + + linkaxes(ax,'x') + rasFigName = ['Unit_', cell2mat(cl), '_', ]; + rasFig.Name = rasFigName; + configureFigureToPDF (rasFig); + saveas(rasFig,fullfile(rasterDir, [rasFigName,'_',rasConds,'_', num2str(timeLapse(1)), '_to_', num2str(timeLapse(2)),'.emf'])); + %savefig(rasFig,fullfile(rasterDir, [rasFigName, ' ', num2str(pwr), 'mW.fig'])); + savefig(rasFig,fullfile(rasterDir, [rasFigName,'_',rasConds, '.fig'])); +end +%% Pressures vs PopPSTHs +colours = [0,0,0.75; 0, 0.25, 0; 0.5, 0, 0.5]; +[Ncl, Npt, Nconds] = size(PSTH); +psthTX = linspace(timeLapse(1),timeLapse(2),Npt); +cs = 2; +lidx = 1; +fig = figure('Color','white', 'Name', 'PopPSTHwithPressures'); +for ccond = 1:length(consideredConditions) + ax(lidx) = subplot(6*Nccond, 1, lidx:lidx+1); + medPSTH = median(sum(PSTH(:,1:40,ccond),1,'omitnan')/(Ncl * sweeps * binSz)); + popPSTH = sum(PSTH(:,:,ccond),1,'omitnan')/(Ncl * sweeps * binSz); + % popPSTH = popPSTH-medPSTH; + popPSTH = smooth(popPSTH, 5); + plot(psthTX,popPSTH, 'LineWidth',1.5, 'Color',colours(ccond,:)) + ylim([ax(lidx).YLim(1), 4]); + + ax(lidx).XAxis.Visible = 'off'; + + + + + lidx = lidx + 2; + + ax(lidx) = subplot(6*Nccond, 1, lidx:lidx+3); + stims = mean(cst(:,:,delayFlags(:,ccond)),3); + if abs(log10(var(stims(cs,:),[],2))) < 15 + stims(cs,:) = m*stims(cs,:) + b; + stims(cs,:) = stims(cs,:) - min(stims(cs,:)); + + stims(cs,:) = smooth(stims(cs,:),10^4); + else + stims(cs,:) = zeros(1,Nt); + end + stim = [0, diff(stims(cs,:))]; + stim = smooth(stim, 10^4); + % stim = stim - min(stim); + + yyaxis right + plot(trigTX,stim, 'Color',[0,0,0], 'LineWidth',1.5) + ylim([-10^-4, 10^-4]); + + + + yyaxis left + if exist('IDs','var') + area(trigTX,stims(cs,:), 'FaceColor', [0.75,0.75,0.75], 'LineStyle','none') + + + else + area(trigTX,stim(cs,:), 'FaceColor', [0.75,0.75,0.75], 'LineStyle','none') + + end + ax(lidx).Visible = 'off'; + ylim([-1,1]); + + + + + + + + + + + + + + + + + + lidx = lidx + 4; + + +end + + +%% Abs pressure vs PopPTH overlay + +%% Absolute Pressure Difference Comparison +trigTX = linspace(timeLapse(1),timeLapse(2),size(trig,2)); +pressurecolours = [0.8,0.8,0.8; 0.7, 0.7, 0.7; 0.9, 0.9, 0.9]; + +cs = 2; +stims = mean(cst,3); +[m,b] = lineariz(stims(cs,:),1,0); +stims(cs,:) = m*stims(cs,:) + b; +colours = [0,0,0.75; 0, 0.25, 0; 0.5, 0, 0.5]; +[Ncl, Npt, Nconds] = size(PSTH); +psthTX = linspace(timeLapse(1),timeLapse(2),Npt); + +fig = figure('Color','white', 'Name', 'Pressures'); + +yyaxis right + +hold on + +for ccond = [3, 1, 2] + stims = mean(cst(:,:,delayFlags(:,ccond)),3); + if abs(log10(var(stims(cs,:),[],2))) < 15 + stims(cs,:) = m*stims(cs,:) + b; + stims(cs,:) = stims(cs,:) - min(stims(cs,:)); + + stims(cs,:) = smooth(stims(cs,:),10^4); + else + stims(cs,:) = zeros(1,Nt); + end + area(trigTX,stims(cs,:), 'FaceColor', pressurecolours(ccond,:), 'LineStyle','none') +end + + + +yyaxis left +hold on + +for ccond = 1:length(consideredConditions) + medPSTH = median(sum(PSTH(:,1:40,ccond),1,'omitnan')/(Ncl * sweeps * binSz)); + popPSTH = sum(PSTH(:,:,ccond),1,'omitnan')/(Ncl * sweeps * binSz); + % popPSTH = popPSTH-medPSTH; + popPSTH = smooth(popPSTH, 5); + plot(psthTX,popPSTH, 'LineWidth',2, 'Color',colours(ccond,:), 'LineStyle', '-') +end + + +leg = legend; +leg.String = [consCondNames{3}, consCondNames{1}, consCondNames{2}, consCondNames]; +leg.Box = 'off'; +leg.FontName = 'Arial'; +ax = gca; +ax.XLabel.String = 'Time [secs]'; +ax.YAxis(2).Visible = 'off'; +ax.YAxis(1).Label.String = 'Spike Frequency[Hz]'; +ax.FontSize = 25; +leg.Location = 'northeast'; +set(gca, 'SortMethod', 'depth'); + +configureFigureToPDF (fig); +saveas(fig,fullfile(figureDir, 'MechPressure+PopPSTHs.emf')); +savefig(fig,fullfile(figureDir, 'MechPressure+PopPSTHs.fig')); \ No newline at end of file diff --git a/Ross/getBurstingMeasuresMUA.m b/Ross/getBurstingMeasuresMUA.m new file mode 100644 index 0000000..60c676d --- /dev/null +++ b/Ross/getBurstingMeasuresMUA.m @@ -0,0 +1,142 @@ +% function [burstSpkFreq, burstCF, nBursts, nSpikes, eventRatio] = getBurstingMeasuresMUA(UnitID, SpikeTrains, TrialStarts, TimeBefore, TimeAfter, Condition) + +%% + +%% Picking out the desired units +if ~exist("spkSubs") + ind = ismember(sortedData(:,1), gclID); + Spikes = cellfun(@(x) round(x.*fs),sortedData(ind,2),... + 'UniformOutput',false); +else + Spikes = spkSubs; +end + + +%% Parameters + +minSpksperBurst = 2; +Traincutoff = 40 * 10^-3; +ISIcutoff = 6 * 10^-3; +nSpkscutoff = 5; + +timeBeforesecs = 2.25; +timeAftersecs = 2.25; + +consconds = [20, 22, 25]; + + +%% Triggered Spike Times + + +conscondnames = {Conditions(consconds).name}; + +Triggers = {Conditions(consconds).Triggers}; +timeBefore = timeBeforesecs*fs; +timeAfter = timeAftersecs*fs; + +for t = 1:length(Triggers) + triggers = Triggers{t}(:,1); + +spont_window = [triggers-timeBefore, triggers-0.01]; +ev_window = [triggers+0.01, triggers+timeAfter]; + +consSpks = cell(length(Spikes), 2); + +for cu = 1:length(Spikes) + spks = Spikes{cu}; + sp_spks = []; + ev_spks = []; + for ct = 1:length(triggers) + sp_spks = [sp_spks; spks(spks > spont_window(ct,1) & spks < spont_window(ct,2))]; + ev_spks = [ev_spks; spks(spks > ev_window(ct,1) & spks < ev_window(ct,2))]; + end + consSpks{cu,1} = sp_spks; + consSpks{cu,2} = ev_spks; +end + + +%% Spont and Evoked Bursting Measures +% burstSpkFreq = cell(size(consSpks)); +burstCF = cell(size(consSpks)); % no. of spikes belonging to bursts / total spikes +nBursts = cell(size(consSpks)); % no. of bursts +nSpikes = cell(size(consSpks)); % no. of total spikes +bursteventRatio = cell(size(consSpks)); % no. of burst events + + + + +refperiod = 0.001; + +for cu = 1:length(Spikes) + for ct = 1:2 + spks = consSpks{cu,ct}; + if isempty(spks) +% burstSpkFreq{cu,ct} = 0; + burstCF{cu,ct} = 0; + nBursts{cu,ct} = 0; + nSpikes{cu,ct} = 0; + bursteventRatio{cu,ct} = 0; + else + + dim=size(spks); if dim(2)>dim(1),spks=spks';end %consistent column of spike times. + if spks(1) == round(spks(1)) + spks = spks/fs; + end + spks(diff(spks) < refperiod) = []; + ISIs = diff(spks); + Events = [1; find(ISIs > ISIcutoff)]; + Events=unique(Events); + + + + c = 1; + Bursts = []; + for a = 1:length(Events) - 1 + current = Events(a); next = Events(a+1); + if sum(ISIs(current:next-1)) <= Traincutoff && next-current-minSpksperBurst >= 0 && next-current <= nSpkscutoff-1 % min number of spikes per burst has to be greater than 1 + Bursts{c} = (spks(current+1:next)); + c = c + 1; + end + end + current = Events(end); + + if sum(ISIs(current:end)) <= Traincutoff && next-current-minSpksperBurst >= 0 && next-current <= nSpkscutoff-1 % min number of spikes per burst has to be greater than 1 + Bursts{c} = (ISIs(current:end)); + end + if isempty(Bursts) + nBursts{cu,ct} = 0; +% burstSpkFreq{cu,ct} = zeros(10,1); + burstCF{cu,ct} = 0; + bursteventRatio{cu,ct} = 0; + else + nBursts{cu,ct} = length(Bursts); + + bursteventRatio{cu,ct} = length(Bursts)/(length(Events)); + + burstSpikes = cat(1, Bursts{:}); + burstCF{cu,ct} = length(burstSpikes)/length(spks); + + burstSz = zeros(size(Bursts))'; + for a = 1:length(Bursts) + burstSz(a,1) = numel(Bursts{a}); + end +% burstSpkFreq = zeros(10,1); + for a = 1: 10 +% burstSpkFreq(a,1) = sum(burstSz == a); + end + end + nSpikes{cu,ct} = length(spks); + + end + + + + end +end +TriggeredBursts(t).ConditionName = conscondnames{t}; +TriggeredBursts(t).burstCF = burstCF; +TriggeredBursts(t).bursteventRatio = bursteventRatio; +TriggeredBursts(t).nBursts = nBursts; +TriggeredBursts(t).nSpikes = nSpikes; + +end