% Program by N.R. Chevalier, re-commented 23/10/2025 
% Outputs maps & average Ca2+ event number, frequency, width, intensity ratio
% To be used downtream of the ImageJ Macro "Batch_calcium_analysis"
% If you use it please cite the reference paper :
% "Endothelin 3 and T-type Ca2+ channels drive enteric neural crest cell calcium activity, contractility and migration" N.R. Chevalier et al., 2023


% INPUT: 

% The ImageJ macro "Batch_calcium_analysis" generates data in an output folder.
% Place yourself in this output folder and simply run this Matlab script.
% It will take the ImageJ output data as input. 

% OUTPUT:

% A folder containing heat maps of frequency, width and intensity ratio
% An excel "results" table with video name, # of active ROIs, # of events,
% ENCC area (in mm²), total time of the video (in seconds), calcium
% activity (in events/min/mm²), frequency (cpm), width (sec), intensity
% ratio (dimensionless), average calcium (arbitrary unit), Bernsen number
% for the threshold (only to check for potential problems in thresholding).

% EXPLANATION OF THE CODE:

% Matrix "a" is the the result of the multi-measure from the original fluorescence video.
% Matrix "b" is the result of the multi-measure from the same, but thresholded video.
% The Matrix "b" needed to be inputed in an older version of the program to correct for z-drift of the sample during the experiment.
% In this version we consider Matrix b = Matrix a

% Standard grid size for analysis

X=45;  
Y=61;  
XY=2745;  

% Parameters below have been optimized for E11.5 mouse GCamp spontaneous
% calcium flashes on our microscope

acq_frequency=1; % acquisition rate of the movie, in Hz
minpkp=2; % minimal peak prominence for calcium flash identification :; typically 1 for gdnf-collagen gel exp, 3 for ENCCs in gut
minpkw=3*acq_frequency; % minimal peak width for calcium flash identification
maxpkw=50*acq_frequency; % max peak width for calcium flash identification
minpkd=3*acq_frequency; % minimal time between two peaks 


% These parameters are only useful in an older version that corrected for
% z-drift during the experiment

th_i=30; % Threshold intensity (8-bit) as from which the box is considered active at a given time 
th_et=60; % Only considers ROIS that are in focus (active) more than 60 sec



%OUTPUT

T{1,1}='Video Name'
T{1,2}='Active ROI #';
T{1,3}='Event #';
T{1,4}='ENCC Area (mm²)';
T{1,5}='Total Time (sec)';
T{1,6}='Surface Frequency (#/mm²/min)';
T{1,7}='Frequency (cpm)';
T{1,8}='Width (sec)';
T{1,9}='IntensityRatio';
T{1,10}='AverageCalcium (8 bit)'
T{1,11}='Bernsen Nbr'

%truc = strings(1, 8);
%T = [table(strings(1,9)), array2table(truc)];
%T.Properties.VariableNames = {'VideoName', ...
 %   'ActiveROIs', 'Events', 'ENCCArea', 'TotalTime', ...
 %   'SurfaceFrequency', 'Frequency', ' Width', ' IntensityRatio'};


% READ ALL CSV FILES IN A FOLDER

currentdirectory = pwd;

myfiles = dir(currentdirectory); % specify folder here
filenames={myfiles(:).name}';
csvfiles=filenames(endsWith(filenames,'.csv'));
txtfiles=filenames(endsWith(filenames,'.txt'));


mkdir maps;

for k=1:length(csvfiles)
    
    a=readtable(csvfiles{k}); 
    a=table2array(a); % converts data to matrix
    %a(:,1)=[]; % delete first column if importing from Fiji
    total_time=size(a,1)/acq_frequency % total time of video , in sec.

    for i=1:size(a,2) % loop over each ROI in grid

        smoothi=smooth(a(:,i)); % smoothing of the intensity data

        [pks,locs,widths,proms]=findpeaks (smoothi,'MinPeakProminence',minpkp,'MinPeakWidth',minpkw,'MaxPeakWidth',maxpkw,'MinPeakDistance',minpkd,'Annotate','extents');

        % UNCOMMENT TO ADJUST THRESHOLDING PARAMS to see individual (box per box) peak finder results
%          if length(pks)>=1
%          findpeaks(smoothi,'MinPeakProminence',minpkp,'MinPeakWidth',minpkw,'MaxPeakWidth',maxpkw,'MinPeakDistance',minpkd,'Annotate','extents')
%          pause
%          end
        % END OF UNCOMMENT   

        % find m n coordinates of box i
        m=fix((i-1)/X)+1;
        n=rem(i-1,X)+1;
        
        % fill data tables
        events_all(m,n)=length(pks);%  number of calcium events
        freq_all(m,n)=length(pks)/(total_time/60); % in cpm
        widths_all(m,n)=mean(widths)/acq_frequency; % in seconds
        ratio_all(m,n)=mean(pks./(pks-proms)); % ratio signal over background

        clear pks locs widths proms

    end

    % compute average over ROIS that are non-zero

    events_all_sum=0;
    freq_all_sum=0;
    widths_all_sum=0;
    ratio_all_sum=0;
    active_ROI_flash=0;

    for m=1:Y
        for n=1:X
                if events_all(m,n)>0
                    events_all_sum=events_all_sum+events_all(m,n);
                    active_ROI_flash=active_ROI_flash+1;   % sum of active ROIs with at least one event
                    freq_all_sum=freq_all_sum+freq_all(m,n);  
                    widths_all_sum=widths_all_sum+widths_all(m,n);
                    ratio_all_sum=ratio_all_sum+ratio_all(m,n);
                end
        end
    end
    
    freq_all_avg=freq_all_sum/active_ROI_flash   
    widths_all_avg=widths_all_sum/active_ROI_flash
    ratio_all_avg=ratio_all_sum/active_ROI_flash

    % extract the area of enccs & average calcium & bersen parameter 1 from the .txt file 
    
    b=readtable(txtfiles{k});
    enccarea=b{1,2}/255*697781.76*1e-6 ; % in mm² , 697781.76 is the area of the whole x10 image in um²
    avg_calcium=b{2,2}/b{1,2}*255;
    bernsen=b{3,2};
 

  
    
    
    
    % fill results table 
    
    T{k+1,1}=csvfiles{k};
    T{k+1,2}=active_ROI_flash;
    T{k+1,3}=events_all_sum;
    T{k+1,4}=enccarea;
    T{k+1,5}=total_time;
    T{k+1,6}=events_all_sum/enccarea/(total_time/60);
    T{k+1,7}=freq_all_avg;
    T{k+1,8}=widths_all_avg;
    T{k+1,9}=ratio_all_avg;
    T{k+1,10}=avg_calcium;
    T{k+1,11}=bernsen;
    %T.Properties.VariableNames = {'VideoName', ...
    %'ActiveROIs', 'Events', 'ENCCArea', 'TotalTime', ...
    %'SurfaceFrequency', 'Frequency', ' Width', ' IntensityRatio'};

    % output maps
    %x = [5 8];
    %y = [3 6]; 

    subplot(1,3,1)
    imagesc(freq_all)
    axis equal
    xlim([0 X]);
    ylim([0 Y]);
    colorbar
    title('Frequency (cpm)')
    
    subplot(1,3,2)
    imagesc(widths_all)   
    axis equal
    xlim([0 X]);
    ylim([0 Y]);
    colorbar
    title('Width (sec)')
    
    subplot(1,3,3)
    imagesc(ratio_all)    
    axis equal
    xlim([0 X]);
    ylim([0 Y]);
    colorbar
    title('Intensity ratio')

    % save figure
    csvname=erase(csvfiles{k},".csv");
    figurename1=strcat(csvname,'.fig'); 
    figurename2=strcat(csvname,'.jpeg'); 
    path=strcat(currentdirectory,'\maps\',csvname);
    %fullname=strcat('D:\Neural Crest\24-11-20 E11p5 TTX 2 guts\output saved\maps\', csvname);
    f = gcf;
    saveas(gcf,path,'jpeg');
    saveas(gcf,figurename1);
    
    


    clearvars a smoothi

end

% output results as excel sheet

xlswrite('results.xlsx',T)

clearvars



