cortex-lab / Suite2P

Tools for processing 2P recordings
Other
121 stars 66 forks source link

merging dendrites #87

Open marius10p opened 7 years ago

marius10p commented 7 years ago

Several users would like Suite2p to merge together segments of dendrites from the same neuron.

marius10p commented 7 years ago

Suite2p is currently optimized for detecting localized ROIs. We think this makes sense also for dendrites. Take a look at the dendrites figure in the manuscript.

Think about what you are trying to achieve. Either you believe that 1) All pieces of a dendrite have the exact same signal, in which case any detected piece is sufficient for analysis. 2) There are interesting differences in the signal along a dendrite, in which case you want to keep different traces for different portions of the dendrite. 3) You actually really care about the spines, so again you don't want to over-merge together spines and dendrites, because you won't be able to look at activity differences between spines and dendrites.

In all cases, you might still want to run a simple clustering algorithm on the output of Suite2p, to detect which dendrite pieces belong together. That should be easy to do.

marius10p commented 7 years ago

I think any clustering algorithm should work fine for merging branches. I would suggest something very basic, like computing a correlation matrix of all activity traces, thresholding it, and finding all connected components in the thresholded correlation matrix. You could also add a distance dependence on this matrix, setting to 0 all pairs of ROIs that don't touch.

We should add something like this into the pipeline at some point. If someone else contributes it, that would be even better!

bill-connelly commented 7 years ago

Here is my attempt at merging ROIs. It's GUI based so just run it with join_axon() And use it to open a "_proc.mat" file (i.e. one that new_main() produces). It seems to work very well with data from population axon imaging, however, I am yet to use it on dendrites. If anyone uses it, I'd love to hear how it went.

join_axon.zip

EDIT: SEE BELOW FOR CORRECTED VERSION.

ghost commented 6 years ago

Hi Bill, Wow, thanks for taking the time to solve this issue! I'm having a little trouble getting it to run on my data however. I think there is a missing "imscale" function that I need. The join_axon() gui loads the proc.mat file fine, however it does not draw any of the grouped ROIs due to this error. I can click on each of the groups, but none of them is graphically displayed. Know of a fix for this?

Error while evaluating UIControl Callback

Undefined function or variable 'imscale'.

Error in join_axon/show_single_clusters (line 287)
        im(:,:,1) = imscale(data.dat.mimg(:,:,2));
bill-connelly commented 6 years ago

@RylanL I'm SO sorry. It's hard to keep track of what "custom" functions you call. I have attached a zip file with imscale and a newer version of join_axon. This version has a new "help me choose the R-squared" button that will show you two graphs (they take a few seconds to generate, so be patient).

The first graph shows you a graph of correlation coefficient versus the number of clusters created. In my hands, if there is a flat area on this graph, this is almost certainly where you want to set your correlation coefficient threshold.

The second graph shows you a plot of correlation coefficient versus a "cost-function", which represents how well the clustering is behaving. For clustering, the cost function will nearly always decrease with the number of clusters, but again, you should be looking for a flat region. This image shows a "representative" example. You can see it is suggesting that a good value for the correlation coefficient threshold is anywhere between ~0.2 and ~0.8.

image

I will say that you do not always get a flat region on these graphs. Sometimes it is very hard to decide whether a data series belongs with another cluster or not (Even you a human) so it is no surprise an algorithm struggles too. join_axon.zip

ghost commented 6 years ago

Thanks for the very quick fix! It works great for joining correlated ROIs now. The "help me choose R-squared" is also a very helpful addition since it gives me somewhere to start. I've noticed the results from the correlation coefficient versus cost-function can depend pretty highly on the Filter Width in Frames parameter (somewhat obviously when I think about it).

One thing that might help in deciding if a data series belongs to one cluster or not may be incorporating a distance dependence to the algorithm as Marius suggested. JoinAxon currently joins axons very well, but tends to also join very spatially distant axon segments that have similar tuning to a given stimulus. Based on prior knowledge of the biology, it is very unlikely that these far away segments belong to the same axon, even though they are highly correlated with other ROIs. Therefore, I'm wondering if having the user specify the maximum allowable distance for clustering two ROIS would produce better results. For example, if ROI 1 is highly correlated with ROI 2, but if the ROIs are greater than 100 pixels away (user defined), they will not be merged due to the spatial distance. If the user was extremely rigid about this, they could force only correlated ROIs to touch (0 pixel distance) to be joined. Thoughts?

bill-connelly commented 6 years ago

Based on prior knowledge of the biology, it is very unlikely that these far away segments belong to the same axon, even though they are highly correlated with other ROIs.

@RylanL I'm not disagreeing with you, maybe that is the case where you are looking, but are you SURE? In my data, there are ROIs on one side of my image that are basically perfectly correlated with ROIs on the other side (~100um away). I am extremely confident that they belong to the same axon. Indeed, I saw basically no correlation between the correlation coefficient and euclidean distance across all ROIs (there was a cluster of very near, very correlated ROIs, but after that, no correlation). Moreover, biologically speaking, most axons in the brain travel some significant distance (relative to soma size/dendrite spread) so I see no issue with the travelling across a 100, 200 or 300 um field of view.

I just happened to have this image, which is kind of an example:

image

Those two blue ROIs on the left are just waaaaay to correlated for that to be a coincidence, in my view.

The other reason I don't like using a distance cut off is that a priori, we know that clustering ROIs isn't going to be based on strict distance. That is to say, if we have a long thin ROI (like a dendrite/axon segment) chances are an ROI belonging to the same cell is going to be in the long direction of the ROI, and NOT in the thin direction (i.e. axons/dendrites generally are straight lines, locally). Now I COULD make it so it tries to work this in, by fitting something to the shape, or using the built in data that is in the stats structure,, but that sounds like a pain (anything involving fitting always is a bit sensitive in my view).

That said, I'm more than happy to include a distance weighting. I was thinking a circular 2D gaussian (rather than a hard cut off), and the user can set the sigma for the gaussian in pixels. However, there is no chance I'll get that to you before Tuesday/Wednesday. Let me know if that sounds like what you'd like, and I'll prioritize it for next week.

ghost commented 6 years ago

@bill-connelly That's a very solid point, especially for a field of view like the one you have. I think it's fairly reasonable to assume that they are the same axon if they are highly correlated and far away spatially, but this seems like it maybe should be an individual user's call. Merging axons solely on correlation comes with the assumption that two actually independent axon ROIs which respond very reliably to the same stimulus are not distinct and should be clustered together, solely because they are correlated. For the axons I'm studying, their activity is very infrequent except when a specific stimulus is presented. In the presence of a stimulus, most of the ROIs are highly co-active, resulting in a significant amount of joining of the ROIs. Relatively lower R-squared threshold values can result in merging of the vast majority of ROIs in the field of view for this reason. In my experiments, I also have a independent red fluorophore in a subpopulation of the GCaMP6 axons. This allows me to tell that that some of the merged ROIs are incorrectly merged when only correlation is considered (a 'red' GCaMP6 axon ROI shouldn't ever be merged with a GCaMP6-only, red-lacking ROI).

I think any user of should be cautious of using a strict distance cutoff for the reasons you mention, but it would be nice to have the distance weighting as an option that can be used in experiment-dependent manner. Your join_axon code is already super useful, but if you had time to add a spatial weighting that would be super helpful!

bill-connelly commented 6 years ago

Alright @RylanL I've added a distance dependence. Give it a try and tell me if you like it, or what you'd like changed. join_axon.zip

ghost commented 6 years ago

@bill-connelly Thanks for adding that so fast once again. I finally got a chance to test the distance dependence on some of my Suite2P-processed data. However, I'm finding that it imposes a pretty hard threshold on clustering of the axon ROIs. With a distance dependence of 0 and a R threshold that results in almost all ROIs in the field of being merged, bumping the distance dependence from 0 to 1 (or 0.5) causes all the ROIs to go from being grouped together, to being completely independent (not-grouped). This is likely because there is some multiple pixel spacing between my ROIs even when they are part of the same axonal process (perhaps a result from the axon dipping out of the Z-plane a bit for portions of its projection). Is there a way to make the distance dependence impose less of a hard threshold so I'm not left with all or none type situations like this?

bill-connelly commented 6 years ago

@RylanL I think you might be doing it wrong. With the distance dependence set to 0 you are turning off the distance dependence (i.e. it's like it was before), however, when you set the distance dependence to 1, you are saying that the gaussian weighting function has a standard deviation of 1 pixel (i.e. once you're 3 pixels away from the center of the ROI, you basically have a 0% chance of clustering something) So, if I understood your post, I would expect exactly what I think you're seeing. Try larger values, i.e. 10, 20 or 100 pixels. I set up an animation which shows you the size of the gaussian (that's what the green flash is).

Try some bigger values and see how it behaves. If it's still not working I'll have a look at it.

apacker83 commented 6 years ago

Hi Bill,

Thanks for the great code!

It looks like imscale may have come from GeoML: https://uk.mathworks.com/matlabcentral/fileexchange/21251-geoml?focused=5104132&tab=function Or, at least, that imscale worked for me.

This code is very useful overall though I think I have two issues, which may be related to my misunderstanding the correct usage: 1) I end up with 3 clusters: two are made up of ROIs I do want to be merged, and one is all the other ROIs. Is this the expected behaviour? From the help and reading here, it seems like I should just have the two clusters that are properly merged, perhaps? 2) When I try to load the ..._proc_clust.mat file back into the Suite2P GUI, I get an error. But I am not meant to be able to do that, am I?

Thanks again for the great code!

bill-connelly commented 6 years ago

Hi Adam,

No, I wrote imscale, it's in the other version above.

The number of merged ROIs just depends on the data and the threshold you set. There is no set number being produced. It's just clustering them based on the correlation coefficient. Try changing the threshold to get different results.

No, the files saved by my script are not supposed to be loaded by suite2p again. You create the ROIs with suite2p, cluster them with my script, and then take the data off for further analysis.

bill-connelly commented 6 years ago

Another updated version. This time you can zoom in on the DF/F traces more easily (as per user request). join_axon.zip