bahanonu / ciatah

CIAtah (pronounced cheetah): a software package for calcium imaging analysis of one- and two-photon imaging datasets. Documentation: https://git.io/ciatah_docs. Formerly known as calciumImagingAnalysis (ciapkg).
https://git.io/ciatah_docs
MIT License
80 stars 20 forks source link

extracted peaks #116

Open hsw28 opened 1 year ago

hsw28 commented 1 year ago

Hi, I remember reading something in a readme a while ago that there is a more exact way to get peak times than using extractedPeaks, but for the life of me I cannot find it anymore. Is it deprecated?

Thank you!

bahanonu commented 1 year ago

Yep! Alternative peak-finding using ciapkg.signal_processing.computeSignalPeaks, see https://github.com/bahanonu/ciatah/blob/master/+ciapkg/+signal_processing/computeSignalPeaks.m.

Example usage on CNMF-e output loaded into Matlab, e.g.

% signalPeaks: [nSignals frame] matrix. Binary matrix with 1 = peaks, 0 = non-peaks.
% signalPeaksArray: {1 nSignals} cell array. Each cell contains [1 nPeaks] vector that stores the frame locations of each peak.
% numStdsForThresh: number of standard deviations above the threshold to count as spike
% minTimeBtEvents: minimum number of time units (e.g. frames) between events.
% detectMethod:  detect on differential/1st derivative ('diff') or raw ('raw') trace.
% medianFilterLength: number of frames to calculate rolling median filter, correct for baseline drift over time.

[signalPeaks, signalPeaksArray] = ciapkg.signal_processing.computeSignalPeaks(cnmfeAnalysisOutput.extractedSignals,...
'numStdsForThresh',2,'minTimeBtEvents',8,'detectMethod','raw','medianFilterLength',100);

If you want to view the found peaks overlayed on each cell's trace quickly in a GUI, can set the makePlots to 1, e.g.

[signalPeaks, signalPeaksArray] = ciapkg.signal_processing.computeSignalPeaks(cnmfeAnalysisOutput.extractedSignals,...
'makePlots',1,...
'numStdsForThresh',2,'minTimeBtEvents',8,'detectMethod','raw','medianFilterLength',100);

image

Alternatively can load the cell extraction images/signals directly from MAT or NWB format into variables (for any cell extraction from CIAtah) using ciapkg.io.loadSignalExtraction, e.g.

cellExtractPath = 'PATH\TO\_cnmfeAnalysis.mat';

[cImages,cSignals,~,~,cSignals2] = ciapkg.io.loadSignalExtraction(cellExtractPath);

[signalPeaks, signalPeaksArray] = ciapkg.signal_processing.computeSignalPeaks(cSignals,...
'numStdsForThresh',2,'minTimeBtEvents',8,'detectMethod','raw','medianFilterLength',100);

I'll add a separate page in the CIAtah docs (https://git.io/ciatah_docs) on this.

hmfeng commented 1 year ago

Hi @bahanonu , can you please explain more about this method? Why this computeSignalPeaks is more exact than the extracedPeaks generated by CNMFE? It looks that CNMFE uses deconvolution algorithm to compute the spikes from raw calcium trace. Did computeSignalPeaks also employ this deconvolution method? In my case, I want to see the spatial tuning of my neurons but it seems the computeSignalPeaks gives me much less spikes which brings difficulty in calculating the spatial encoding properties of the neurons.

Thank you!

bahanonu commented 1 year ago

@hmfeng Will get back with a description in a moment, can you provide example traces where you ran ciapkg.signal_processing.computeSignalPeaks along with the exact calls/code you used? As the input parameters can have an impact on peaks identified.

bahanonu commented 1 year ago

@hmfeng We describe the general method for that function's peak finding in the supplemental of the Corder/Ahanonu, 2019 paper, see https://www.science.org/action/downloadSupplement?doi=10.1126%2Fscience.aap8586&file=aap8586_corder_sm.pdf#page=9. Can also run on the raw trace instead of dx/dt.

See below, I'll also double check the current function as I might have updated it since then (e.g. flag to adjust peak locations to max [esp. if using 1st derivative], etc.).

image

bahanonu commented 1 year ago

Also, it is worth looking at Cascade:

If using with 1p data, see https://github.com/HelmchenLabSoftware/Cascade#can-i-use-cascade-as-well-for-endoscopic-1p-calcium-imaging-data.

hmfeng commented 1 year ago

@hmfeng Will get back with a description in a moment, can you provide example traces where you ran ciapkg.signal_processing.computeSignalPeaks along with the exact calls/code you used? As the input parameters can have an impact on peaks identified.

I use the following command to compute peaks with ciatah function:

[signalPeaks, signalPeaksArray] = ciapkg.signal_processing.computeSignalPeaks(cnmfeAnalysisOutput.extractedSignals(:,1:4500),'numStdsForThresh',2.5,'minTimeBtEvents',0,'detectMethod','raw','medianFilterLength',100); % I set minTimebtEvents to 0 here just for more spikes

I compared the spikes generated by this computeSignalPeaks function and the extractedPeaks from cnmfe output dataset (only keep events with amplitude larger than 2.5*std of whole trace of this signal), as shown in below picture:

computed vs extracted peaks

hmfeng commented 1 year ago

@hmfeng We describe the general method for that function's peak finding in the supplemental of the Corder/Ahanonu, 2019 paper, see https://www.science.org/action/downloadSupplement?doi=10.1126%2Fscience.aap8586&file=aap8586_corder_sm.pdf#page=9. Can also run on the raw trace instead of dx/dt.

See below, I'll also double check the current function as I might have updated it since then (e.g. flag to adjust peak locations to max [esp. if using 1st derivative], etc.).

image

Thank you! Actually I did refer the detailed description you mentioned in this paper as my starting point of peak extraction.

bahanonu commented 1 year ago

@hmfeng Will get back with a description in a moment, can you provide example traces where you ran ciapkg.signal_processing.computeSignalPeaks along with the exact calls/code you used? As the input parameters can have an impact on peaks identified.

I use the following command to compute peaks with ciatah function:

[signalPeaks, signalPeaksArray] = ciapkg.signal_processing.computeSignalPeaks(cnmfeAnalysisOutput.extractedSignals(:,1:4500),'numStdsForThresh',2.5,'minTimeBtEvents',0,'detectMethod','raw','medianFilterLength',100); % I set minTimebtEvents to 0 here just for more spikes

I compared the spikes generated by this computeSignalPeaks function and the extractedPeaks from cnmfe output dataset (only keep events with amplitude larger than 2.5*std of whole trace of this signal), as shown in below picture:

computed vs extracted peaks

Thanks, could you send over the MAT-file with the traces and cnmfe event times? Want to get a sense for whether there are actually smaller events in some of the cases where it looks like multi-events are annotated by cnmfe during the transient rise (see below).

image

hmfeng commented 1 year ago

@bahanonu sorry for the late reply. Here is the share link to the zipped data file: https://drive.google.com/file/d/1Eftew6uN-Sm8szWTbBB0g4PboxmfDNyL/view?usp=share_link The cnmfeAnalysisoutput is the raw output and the ManualSort is the sorted tag. The trace I show in this post is from cell index 4. Thank you!

bahanonu commented 1 year ago

@hmfeng Thanks for sending the data.

Took a look at the CNMF vs. computeSignalPeaks identified transients (I change following params from your values: numStdsForThresh=1.5 and medianFilterLength=5). Looks like the CNMF events are potentially detecting noise or are also indicating "events" at each point along the rise of a given transient.

image

For example, see zoom in on the below transients where computeSignalPeaks correctly identifies the peaks but CNMF events include those along with "events" during the rise of the transient. This depends on whether you believe you can make claims about those events on the rise (e.g. are part of the burst producing the rise/transient) or if you only want to make claims based on the transient peak and amplitude. image

image

Also, given how densely packed your cells appear to be (what region is this? CA1?), it is possible the sub-0.01 transients are actually cross-talk. I would go to cell #4 using CIAtah's computeManualSortSignals module (see https://bahanonu.github.io/ciatah/pipeline_detailed_signal_sorting_manual/) with the movie loaded so that you can check whether those smaller transients are real (you can adjust computeSignalPeaks threshold to detect those as well).

image

If you send the movie, I can take a quick look at this in terms of false positives/negatives.

hmfeng commented 11 months ago

@bahanonu Thank you so much! I found the extractedPeaks generated from cnmfe is not the real 'peaks' we are talking about. They are the 'inferred spikes' come from an algorithm OASIS (https://github.com/zhoupc/CNMF_E/tree/master/OASIS_matlab). I found many recent papers just use this inferred spikes as the quantitative measurement of the neuronal activity, especially when they are doing the place cell analysis (e.g. https://www.nature.com/articles/s41467-022-34114-x).

bahanonu commented 11 months ago

@hmfeng Sure thing! Let me know if have any follow-up questions.

And that's correct, if I'm using CNMF-e I often will use the extractedSignalsEst instead of extractedSignals (within cnmfeAnalysisOutput) as depending on the situation a closer estimate of fluorescence can be more useful (even if the denoised/deconvolved OASIS traces look "nicer").