代码美化与良好的编程习惯养成

有一段时间没有写代码跑程序了

再来看看以前的东西,简直就是头大

于是用了大半天的时间,来搞代码美化并重新debug

总结了一些经验如下:

  • 好的工具很重要,我的用是sublime(Docblockr插件),快速插入函数注释
  • 明确函数名命名规则,驼峰命名法,前面是动作后面是对象,如findMaxima(寻找极大值点)
  • 明确变量命名规则,使用下划线如maxima_noise(注意从属关系)或驼峰命名法如nPoints
  • 代码模块清晰:先是程序说明,然后是全局参数(方便调试),然后是函数集,然后是debug区域

效果如下:

/*
 * ### 通用版暗场成像数据处理程序pHunter ###
 * 
 * Description:该程序可以对暗场细胞内纳米金纳米银成像结果进行分析,
 *              获得纳米粒子的位置,数量和聚集状态信息
 * Author: Xie.XD
 * Date: 2018-8-8
 * 
 * # 数据要求
 * 1. 暗场显微镜下同一视野,采集两张图像,先采集一张高曝光(>=50 ms),
 *    后采集一张低曝光(<=10 ms)
 * 2. 图像格式应当为(像素偏移4*4:4080*3072 pixels^2)
 * 3. 将同组实验采集到的多个视野的图片放到同一个文件夹下
 * 
 * # 数据输入
 * 1. 选择包含单个实验组的所有照片的文件夹
 * 2. 如果是从未分析过的数据,先调用divideFiles进行分组,则会打开high和low两个stack
 * 2. 单击高曝光(high)的图像,再调用readRoi圈选细胞roi
 * 
 * # 参数调试
 * 1. 选取细胞内少量粒子光斑,选择能容纳该粒子光斑的15*15矩形区域,获得单粒子截图
 * 2. 对粒子光斑判断结果进行校验,调整saturationT的值以达到较好识别效果
 * 3. 调试完成后,将debug开关全部改为false
 * 
 * # 结果导出
 * 1. roi记录保存为zip
 * 2. 单细胞统计数据打印在Log窗口
 */

/**
 * 重要的全局参数
 */

maxima_noise = 20;
brightnessT = 17;
saturationT = 180; //高曝光图像180,低曝光100
pixelCountRatio = 0.5;
debugging = newArray(false,false); //debug开关

/**
 * [findMaxima description]
 * 调用imageJ>Find Maxima寻找所有maxima点并返回其坐标
 * @param  noise int
 * @return       array
 */
function findMaxima(noise){
	run("Find Maxima...", "noise="+noise+" output=List");
	selectWindow("Results");
	num = nResults;
	loc = newArray(2*num);
	for (j=0;j<num;j++){
		loc[2*j] = getResult("X",j);
		loc[2*j+1] = getResult("Y",j);
	}
	run("Close"); 
	return loc;
}

/**
 * [chooseParticle description]
 * @return 返回鼠标选中点的坐标
 */
function chooseParticle(){
	leftButton = 16;
	flags = 0;
	while(flags&leftButton == 0) getCursorLoc(x,y,z,flags);
	showMessage("Mark Particle Center:"+x+","+y);
	ans = newArray(x,y);
	return ans;	
}

/**
 * [markParticle description]
 * @param  img  图像窗口句柄
 * @param  x    粒子横坐标
 * @param  y    粒子纵坐标
 * @param  type 粒子类型
 * @return      执行动作,在图像上做标记
 */
function markParticle(img,x,y,type){
	d = 7;
	selectWindow(img);
	if (type=="blue") setColor(0,0,255);
	else if (type=="green") setColor(0,255,0);
	else if (type=="yellow") setColor(255,255,0);
	else if (type=="noise") setColor(255,255,255);
	else setColor(255,0,255);
	fillRect(x+d,y,3,3);
}

/**
 * [cropParticle description]
 * @param  x [description]
 * @param  y [description]
 * @return   a 15*15 or smaller particle image
 */
function cropParticle(x,y){
	s = 7;
	w = getWidth();
	h = getHeight();
	while (x<s||y<s||x>w-s||y>h-s) s=s-1;
	makeRectangle(x-s,y-s,2*s+1,2*s+1);
 	run("Duplicate...","title=particle");
 	particle = getTitle();
 	return particle;
}

/**
 * [getParticleColor description]
 * @param  x [description]
 * @param  y [description]
 * @return   获得粒子光斑整体的颜色特征,返回hsb
 */
function getParticleColor(x,y){
	img = getTitle();
	particle = cropParticle(x,y);
	wp = getWidth();
	hp = getHeight();
	run("HSB Stack"); //将particle变成HSB stack
	
	setSlice(3);
	bri = getPixel(wp/2,hp/2); //亮度取中央

	hue = 0;
	sat = 0;
	briCount = 0+(1e-6);
	pixelCount = 0+(1e-6); //避免除以0的情况导致程序崩溃

	for(i=0;i<wp;i++){
		for(j=0;j<hp;j++){
			setSlice(3);
			b = getPixel(i,j);
			if(b>brightnessT){//只在亮的地方找
				setSlice(2);
				s = getPixel(i,j);
				briCount ++;
				if(s>saturationT){//只在颜色好辨别的地方找
					setSlice(1);
					h = getPixel(i,j);
					pixelCount ++;
					hue = hue+h;
					sat = sat+s;
				}
			}
		}
	}
	
	if (pixelCount/briCount>pixelCountRatio){//有颜色的占有亮度的较多才算
		hue = hue/pixelCount;
		sat = sat/pixelCount;		
	}
	else if (bri==255 && (pixelCount/briCount)>(pixelCountRatio-0.15)){ //中央过曝
		hue = hue/pixelCount;
		sat = sat/pixelCount;
	}
	else {
		hue = NaN;
		sat = NaN;	
	}
	HSB = newArray(hue,sat,bri);

	selectWindow(particle);
	close();
	selectWindow(img);
	
	return HSB;
}

/**
 * [judgeColor description]
 * 通过hue的值来判断颜色类型
 * @param  hue int
 * @return     string
 */
function judgeColor(hue){
	if (hue>0 && hue<15) ans = "red";
	else if (hue>15 && hue<=30) ans = "orange";
	else if (hue>30 && hue<=60) ans = "yellow";
	else if (hue>60 && hue<=120) ans = "green";
	else if (hue>=140 && hue<=190) ans = "blue";
	else if (hue>200 && hue<=220) ans = "purple";
	else ans = "noise";
	return ans;
}


/**
 * [getParticleType description]
 * @param  img [description]
 * @param  x   [description]
 * @param  y   [description]
 * @return     type string
 */
function getParticleType(img,x,y){
	selectWindow(img);
	hsb = getParticleColor(x,y);
	hue = hsb[0];
	sat = hsb[1];
	bri = hsb[2];
	if (bri==255){
		if (isNaN(hue)) type = "white";
		else type = judgeColor(hue);
	}
	else if (!isNaN(hue)) type = judgeColor(hue);
	else type = "noise";
	return type;
}

/**
 * debug测试区域
 */

if (debugging[0]){//单点函数测试
	showMessage("下面进行参数校正,请单击单个粒子光斑");
	img = getTitle();
	loc = chooseParticle();
	x = loc[0];
	y = loc[1];
	type = getParticleType(img,x,y);
	showMessage(type);
}

if (!debugging[0]){//增加细胞面积计算
	img = getTitle();
	if(getBoolean("请确认stack已打开并且roi管理器列表不为空!")){
		nCells = roiManager("count");
		setBatchMode(true);
		class_name = newArray("cell","blue","green","yellow","white");
		Array.print(class_name);
		for (k=0;k<nCells;k++){
			roiManager("Select", k);
			getStatistics(area);
			loc = findMaxima(maxima_noise);
			nPoints = lengthOf(loc)/2;
			class_count = newArray(5);
			class_count[0] = floor(area*pow(0.03578,2)); //修改cell ID为cell Area
			for(i=0;i<nPoints;i++){
				x = loc[2*i];
				y = loc[2*i+1];
				type = getParticleType(img,x,y);
				if (type=="blue") class_count[1]++;
				else if (type=="green") class_count[2]++;
				else if (type=="yellow" || type=="red" || type=="purple") class_count[3]++;
				else if (type=="white") class_count[4]++;
			}
			Array.print(class_count);
		}
		setBatchMode(false);
	}
}

猜你喜欢

转载自blog.csdn.net/sheldonxxd/article/details/81515914