这里以提取一个视频中单分子荧光信号变化曲线为例,展示以前述ImageJ进阶教程的内容为基础的综合应用。
通常我们想提取一个单分子的荧光变化曲线,手动的做法是选中一个单分子区域后,使用 Image>Stacks>Plot Z-axis Profile 功能,然后就会出来一条曲线,然后保存数据,保存ROI。重复上述步骤若干次。
上述操作显然费时费力,而且选取的矩形框ROI很难保持一致。那么通过对进阶教程进行学习之后,这个分析过程是可以大幅度提速的。先确定思路:
-
做一个 Z Max project,确定所有单分子的 xy 坐标,可以用 Find Maxima 搞定
-
遍历每个单分子,选择一个固定大小的矩形ROI
-
滑动Slice,对ROI内的像素进行统计,包括最大值,最小值,均值,方差等等
-
将提取的数据保存到 Results 窗口,完成后可以选中强度和时间两列快速plot
最大强度投影
什么是最大强度投影?就是在指定 xy 坐标位置的像素,取所有z axis(或者时间点)上这个位置的像素的最大值。
为何要进行最大强度投影呢?因为有些单分子的信号,不是在第一帧就出现的。但是它总归会出现,而且信号强于背景,得看最大值。(反例,如果想看这个视野的背景,可以使用最小强度投影)
怎么做?ImageJ菜单栏直接点进去,Image>Stacks>Z Project.. 可以打开弹窗,选择 Max Intensity即可。
Find Maxima
在所得最大投影图像中,使用 Find Maxima 功能,找到所有的点并获取坐标。可以先手动 Find,然后开启预览,方便设置 Prominence:
由于Find Maxima 输出为 List 是保存到 Results 窗格中。为了方便,我们这里封装一个函数,把坐标返回到一个数组中,方便后面遍历:
function getParticleLocation(prominence){ /*基于FindMaxima方法寻找图像中的颗粒,并返回坐标数组*/ run("Find Maxima...", "prominence="+prominence+" strict exclude output=List"); N = nResults; locs = newArray(2*N); for(i=0; i<N; i++){ x = getResult("X",i); y = getResult("Y",i); locs[2*i] = x; locs[2*i+1] = y; } selectWindow("Results"); run("Close"); return locs;}制作矩形框并统计
获得点的坐标之后,我们接下来就是要进行自动选取和像素统计,这里可以先手动输入其中一个点的坐标,测试下这个主要的功能。
上图演示代码中简单介绍:
-
floor是对浮点值向下取整,比如 5.3 和 5.9 都会变成5。而 round 是对浮点值最近取整,0.5取1,0.49取0。这里使用 floor 或者 round 都可以,主要是获得绘制矩形ROI的起始坐标
-
使用 makeRectangle 制作矩形ROI,使用 getStatistics 进行像素统计
由于这是一个需要多次被调用的步骤,我们也可以封装成一个函数,方便调用,代码如下:
function rect_stat(x, y, s){ /* x,y 为输入的坐标, * s为正方形ROI边长,正方形ROI以x,y为中心 * 输入ROI像素统计结果,array(mean, min, max, std) */ x0 = floor(x-s/2); y0 = floor(y-s/2); makeRectangle(x0, y0, s, s); getStatistics(area, mean, min, max, std, histogram); res = newArray(4); res[0] = mean; res[1] = min; res[2] = max; res[3] = std; return res;}遍历stack完成数据提取
有了以上两个原子级别的函数,接下来我们就需要整合到整个处理流程中,完成每个单分子信号的数据提取。这里我们可以定义最初的整个 stack 作为原始输入,最后输出的是一个 Results 表格。表格中包含以下内容:
-
时间(t)
-
坐标(x,y)
-
强度(mean, min, max, std)
-
颗粒索引(pid),方便后续根据不同的颗粒进行分组
完整代码如下:
prominence = 350;box_size = 9;
mov = getTitle();run("Z Project...", "projection=[Max Intensity]");rename("maxproj");selectWindow("maxproj");locs = getParticleLocation(prominence);close();
selectWindow(mov);n_points = lengthOf(locs)/2;
for (k = 0; k <nSlices; k++) { t = k+1; setSlice(t); for (i = 0; i < n_points; i++) { x = locs[2*i]; y = locs[2*i+1]; res = rect_stat(x, y, box_size); mean = res[0]; min = res[1]; max = res[2]; std = res[3]; cid = k*n_points+i; setResult("t", cid, t); setResult("x", cid, x); setResult("y", cid, y); setResult("mean", cid, mean); setResult("min", cid, min); setResult("max", cid, max); setResult("std", cid, std); setResult("pid", cid, i); }}注意在ImageJ的代码编辑器中,上方主要逻辑代码和前面两个自定义函数需要放到一起。
点击图像 stack 创库,然后 run,就会自动统计并生成一个表格,如下所示:
这个表格相对复杂,如果想查看某个单分子的强度随时间变化曲线,可以保存表格,后续使用 python 或者 excel 按照 pid 进行分组然后作图查看。