/** * MRI Retina tool * * Measure the thickness of two structures in Optical coherence tomography images * of the retina * * written 2015 by Volker Baecker (INSERM) at Montpellier RIO Imaging (www.mri.cnrs.fr) */ var _IMAGE_WIDTH_IN_MM = 1.4; var _BOX_WIDTH = 0.2; var _BOX_X=0.15; var _NUMBER_OF_POINTS = 5; var _LINE_WIDTH = 0.02; var _MIN_HEIGHT_OVER_BACKGROUND_FACTOR = 2; var _WINDOW_WIDTH = 5; var _MIN_BELOW_MAX_FACTOR = 1.0; var _FILE_EXT = "BMP"; var _TITLE="measurements"; var OUTPUT_SUBFOLDER = "control" var _DEBUG = false; var _CORRECT = true; var _Y_MAX = 0.46; var _RANDOM_INITIALIZED = false; var _Y_DEFAULT = 0.35; var _COUNTER = 0; var _BACKGROUND; var _STD_DEV var _HEIGHT; var helpURL = "http://dev.mri.cnrs.fr/projects/imagej-macros/wiki/MRI_Retina_Tool"; macro "MRI Retina Tool Help [f1]" { showHelp(); } macro "MRI Retina Tool Help (f1) Action Tool - C000D00D01D02D03D0cD0dD0eD0fD10D11D1eD1fD20D2fD30D3fDc0DcfDd0DdeDdfDe0De1De2DedDeeDefDf0Df1Df2Df3DfcDfdDfeDffC787D76D78C555D05D09D60D6fD70D80D9fDebDf7Df8C898D86D8aC111D04D0bD12D1dD21D2eD40D4fDb0DbfDd1Df4DfbC888D23D26D2aD34D35D36D3bD43D46D4aD53D57D59D5aD62D6aD6bD89D8eD9aD9dD9eDaaDacDadDb6DbcDbdDccDd6Dd7Dd8De9C777D07D14D3cD3dD4dD51D56D5eD61D64D68D6cD6dD6eD71D72D73D75D7cD81D82D91DaeDb9DbaDc2Dc7Dc8Dc9DcaDcdDd3DdbDeaC999D18D28D37D38D47D93D96Da2Da6Da7Da8Db4Dc3Dd4Dd5De7De8C888D79D7aC676D06D08D1bD2cD44D45D54D55D65D66D67D74D77D87D88Da1C999D15D16D17D19D24D25D27D29D33D39D3aD42D48D49D52D85D92D94D95D97D98D99Da4Da5Da9Db2Db5Dc5De6C333D0aD13D1cD22D2dD31D3eD50D5fD90DafDc1DceDd2DddDf6Df9CaaaDa3Db3Dc4C888D1aD2bD32D4bD4cD58D5bD5cD5dD63D69D7bD7dD7eD83D84D8bD8cD8dD9bD9cDabDb7Db8DbbDc6DcbDd9DdaDe5C666D41D4eD7fD8fDb1DbeDdcDe4C222Da0De3DecDf5Dfa"{ showHelp(); } macro "measure image [f2]" { measureCurrentImage(); } macro "batch measure images [f3]" { runBatch(); } macro "edit regions [f4]" { editRegions(); } macro "re-measure regions [f5]" { remeasureRegions(); } macro "Measure Image (f2) Action Tool - C037T4d14m"{ measureCurrentImage(); } macro "Measure Image (f2) Action Tool Options" { Dialog.create("options of retina tools - measure image"); Dialog.addNumber("image width (mm): ", _IMAGE_WIDTH_IN_MM); Dialog.addNumber("width of region of interest [mm]: ", _BOX_WIDTH); Dialog.addNumber("x of region of interest [mm]: ", _BOX_X); Dialog.addNumber("nr. of measurement points: ", _NUMBER_OF_POINTS); Dialog.addNumber("line width (smoothing): ", _LINE_WIDTH); Dialog.addNumber("min. height over background [stdDev]: ", _MIN_HEIGHT_OVER_BACKGROUND_FACTOR); Dialog.addNumber("window width for local max. [pixel]", _WINDOW_WIDTH); Dialog.addNumber("min. depth below max [stdDev] ", _MIN_BELOW_MAX_FACTOR); Dialog.addString("title of measurements table: ", _TITLE); Dialog.addCheckbox("debug (shows plots)", _DEBUG); Dialog.show(); _IMAGE_WIDTH_IN_MM = Dialog.getNumber(); _BOX_WIDTH = Dialog.getNumber(); _BOX_X = Dialog.getNumber(); _NUMBER_OF_POINTS = Dialog.getNumber(); _LINE_WIDTH = Dialog.getNumber(); _MIN_HEIGHT_OVER_BACKGROUND_FACTOR = Dialog.getNumber(); _WINDOW_WIDTH = Dialog.getNumber(); _MIN_BELOW_MAX_FACTOR = Dialog.getNumber(); _TITLE = Dialog.getString(); _DEBUG = Dialog.getCheckbox(); } macro "Batch Measure Images (f3) Action Tool - C037T4d14b" { runBatch(); } macro "Batch Measure Images (f3) Action Tool Options" { Dialog.create("options of retina tools - batch"); Dialog.addString("file extension: ", _FILE_EXT); Dialog.addString("name of the output folder: ", OUTPUT_SUBFOLDER); Dialog.show(); _FILE_EXT = Dialog.getString(); OUTPUT_SUBFOLDER = Dialog.getString(); } macro "Edit Regions (f4) Action Tool - C037T4d14e" { editRegions(); } macro "Remeasure Regions (f5) Action Tool - C037T4d14r" { remeasureRegions(); } function showHelp() { run('URL...', 'url='+helpURL); } function initRandom() { if (_RANDOM_INITIALIZED) return; getDateAndTime(year, month, dayOfWeek, dayOfMonth, hour, minute, second, msec); random("seed", msec); for (i=0; i= _Y_MAX) { doCorrect(pointsX, pointsY, i); } } correctToNeighbors(pointsX, pointsY); } function doCorrect(pointsX, pointsY, nr) { yMax = _Y_MAX; toUnscaled(yMax); if (nr<((_NUMBER_OF_POINTS-1) / 2)) { doCorrectToTheRight(pointsX, pointsY, nr); } if (nr>((_NUMBER_OF_POINTS-1) / 2)) doCorrectToTheLeft(pointsX, pointsY, nr); if (nr==((_NUMBER_OF_POINTS-1) / 2)) { flip = random(); if (flip>0.5) doCorrectToTheRight(pointsX, pointsY, nr); else doCorrectToTheLeft(pointsX, pointsY, nr); if (pointsY[nr]>=yMax) { if (flip>0.5) doCorrectToTheLeft(pointsX, pointsY, nr); else doCorrectToTheRight(pointsX, pointsY, nr); } } } function correctToNeighbors(pointsX, pointsY) { yMax = _Y_MAX; toUnscaled(yMax); // If right and left ok interpolate for (i=1; i<_NUMBER_OF_POINTS-1; i++) { j = 2*_NUMBER_OF_POINTS-1-i; if (pointsY[j]>=yMax && pointsY[i-1]=0; i--) { j = 2*_NUMBER_OF_POINTS-1-i; if (pointsY[j]>=yMax && pointsY[i+1]=yMax && pointsY[i-1]=yMax) { for (i=0; i<_NUMBER_OF_POINTS; i++) { pointsX[i] = -1; pointsY[i] = -1; j = 2*_NUMBER_OF_POINTS-1-i; pointsX[j] = -1; pointsY[j] = -1; } } } function doCorrectToTheRight(pointsX, pointsY, nr) { yMax = _Y_MAX; toUnscaled(yMax); yValue = yMax; for(x=pointsX[nr]; x=yMax ; x++) { xs = x; toScaled(xs); selectImage(id); if (nr==0) { pointR = findBordersAt(xs+(_LINE_WIDTH/2), _LINE_WIDTH); } else { pointR = findBordersAt(xs-(_LINE_WIDTH/2), _LINE_WIDTH); } yValue = pointR[0]; if (yValuepointsX[nr-1] && yValue>=yMax ; x--) { xs = x; toScaled(xs); selectImage(id); pointR = findBordersAt(xs-(_LINE_WIDTH/2), _LINE_WIDTH); yValue = pointR[0]; if (yValue((_NUMBER_OF_POINTS-1) / 2)) if (pointsX[i] == pointsX[i-1]) len[i] = 0; } intDen = area * mean; result = "" + intDen + "\t"+ area + "\t"; for (i=0; i< _NUMBER_OF_POINTS; i++) { result += "" + len[i] + "\t"; } result += "" +mean + "\t" + std + "\t"; } else { len = newArray(_NUMBER_OF_POINTS); for (i=0; i<_NUMBER_OF_POINTS; i++) { len[i] = 0; } intDen = 0; result = "" + intDen + "\t"+ 0 + "\t"; for (i=0; i< _NUMBER_OF_POINTS; i++) { result += "" + len[i] + "\t"; } result += "" +0 + "\t" + 0 + "\t"; } return result; } function measureRight() { result = measureFrom((width/2) + _BOX_X); return result; } function measureLeft() { result = measureFrom((width/2) - _BOX_X-_BOX_WIDTH); return result; } function measureMeanBackground() { height = getHeight(); width = getWidth(); toScaled(width, height); param = "width="+_BOX_WIDTH+" height="+(height / 4)+" x="+((width/2) + _BOX_X) +" y=0 scaled"; run("Specify...", param); getStatistics(area, mean, min, max, std); run("Select None"); _BACKGROUND = mean; _STD_DEV = std; } function findNextMaximum(startPoint, minHeight, plot) { for(x=startPoint; xy || plot[x+i]>y) isMax=false; } if (isMax && y>minHeight) return x; } return 0; } function findNextMinimum(startPoint, minHeight, plot) { for(x=startPoint; x1) { y = plot[x]; yl = plot[x-1]; yr = plot[x+1]; if (y==value) { x2=x; y2 = plot[x2]; addOne = false; while(y2==y) { y2 = plot[x2]; addOne = true; x2--; } if (addOne) x2++; return x2; } if ((ylvalue) || (yl>value && yr