Project

General

Profile

Files ยป root_tools.txt

support global scale - Volker Baecker, 03/25/2013 03:55 PM

 
/**
* root_tools
*
* The root tools help to efficiently measure the following characteristics of plant roots:
* - the angle of the opening of the whole root
* - the depth to which it goes down
* - the number of roots at 30 cm depth
* - the diameters of the roots at depth
*
* written 2013 by Volker Baecker (INSERM) at Montpellier RIO Imaging (www.mri.cnrs.fr)
*/

var helpURL = "http://dev.mri.cnrs.fr/wiki/imagej-macros/Root_Tools";

var KNOWN_DISTANCE = 40; // known distance for spatial calibration (there are 20mm between two nails)
var RADIUS=75; // radius of the circle drawn around the root point
var ROOT_POINT_LINE_WIDTH = 15; // line width of the circle drawn around the root point
var COLOR_ROOT_POINT = "red"; // color of the circle drawn around the root point
var COUNT_ROOT_DEPTH = 30; // depth from the root point at which the horizontal line is drawn. The number of roots will be counted at that depth
var HALF_LINE_WIDTH = 10; // half of the width of the line drawn at count root depth
var WIDTH_DEPTH = 8; // line width of the line drawn at count root depth
var COLOR_DEPTH = "cyan"; // color of the line drawn at count root depth
var DX_ANGLE = 300; // delta x for the angle tool that is added to the image
var DY_ANGLE = 600; // delta y for the angle tool that is added to the image
var ANGLE_COLOR = "red"; // the color for marking the measured angle
var ANGLE_LINE_WIDTH = 8; // the line width for marking the measured angle
var MEASURE_DEPTH_COLOR = "magenta"; // the color of the line indicating the max. depth to which the root goes down
var MEASURE_DEPTH_WIDTH = 8; // the line width of the line indicating the max. depth to which the root goes down
var ZOOM_RADIUS = 20; // radius of the region around the click that is copied and zoomed
var DIAMETER_COLOR = "yellow"; // color of the line indicating the measured root diameters
var DIAMETER_WIDTH = 2; // width of the line indicating the measured root diameters
var USE_GLOBAL_SCALE = true;
var rootX;
var rootY;
var deepX;
var deepY;
var UNIT = "mm";
var X1;
var X2;
var Y;
var MAX_ROOTS = 20;
var DIAMETERS = newArray(MAX_ROOTS);
var numberOfRootsAtThirty = 0;
var DEPTH = 0;
var ID = 0;
var ANGLE = 0;
var TITLE;
var NUMBER = 0;
var FOLDER;

macro "zoomIn [f1]" {
run("In [+]");
}

macro "zoomOut [f2]" {
run("Out [-]");
}

macro "Root Tools Help Action Tool- C134D01D04D06D11D1fD20D2fD3fDcfDd4Dd7De0De2De3De4De5De6De7Df2Df3Df4Df5Df6Df7Df9DfdC345D08D09D18D25D27D32D34D3aD42D43D5fD6dD92Da3Da5Dc5Dc8DdbC334D0fD12D19D30D3bD59D5aD69D6aDa2Da4DadDaeDafDb2Db3DbdDbeDc6Dd8DdeC666D53D54D62D77D7bD7cD7dD7eD91D94D95D9aD9bD9cD9fDa9DbaDcaDcbC234D02D03D05D07D0aD0bD10D2eD4aDb4DbfDceDd0Dd1Dd5Dd6DdfDe8De9DeaDebDecDeeDf8DfbC555D0eD1bD35D36D45D50D51D52D56D6fD7aD90D93D9dDa1Da6Db1Db7DbcDddC345D0cD15D1aD37D3dD40D5cDb5Db6Dc9DfeC777D1cD57D66D71D72D73D74D76D80D82D83D88D89D8aD8eD8fD97D98C234D00Dc4Dd3De1Df0Df1DfaDfcC445D17D29D2bD38D41D46D55D58D65D6bD6eD78D79D9eDa0DacDcdC335D13D14D16D1eD23D24D28D33D3eD4cD5eD68D6cDc7Dd2DefC666D1dD48D61D63D67D70D7fD96D99Da7Da8Db9DbbDccC234D21D2dD3cD4bD4fDc0Dc3Dd9DdaDedC556D0dD26D2aD39D44D47D60D64D75DaaDabDb8DdcC345D22D2cD31D49D4dD4eD5bD5dDb0Dc1Dc2C777D81D84D85D86D87D8bD8cD8dDff" {
run('URL...', 'url='+helpURL);
}

macro "Set Scale [f5]" {
setScale();
}

macro "Define Root Point [f6]" {
setTool("Define Root Point Tool");
}

macro "Angle [f7]" {
measureAngle();
}

macro "Measure Depth [f8]" {
setTool("Measure Depth Tool");
}

macro "Zoom Region [f9]" {
setTool("Zoom region Tool");
}

macro "Measure Diameter [f10]" {
measureDiameter();
}

macro "Write Report [f11]" {
writeReport();
}

macro "Set Scale Action Tool- C000T4b12s"{
setScale();
}

macro "Set Scale Action Tool Options" {
Dialog.create("Root Tools - Set Scale - Options");
Dialog.addNumber("known distance [cm]: ", KNOWN_DISTANCE);
Dialog.addCheckbox("use global scale", USE_GLOBAL_SCALE);
Dialog.show();
KNOWN_DISTANCE = Dialog.getNumber();
USE_GLOBAL_SCALE = Dialog.getCheckbox();
}

macro "Define Root Point Tool- C000T4b12r" {
getCursorLoc(x, y, z, flags);
ID = getImageID();
TITLE = getTitle();
FOLDER = getDirectory("image");
run("Remove Overlay");
rootX = x;
rootY = y;
setColor(COLOR_ROOT_POINT);
setLineWidth(ROOT_POINT_LINE_WIDTH);
Overlay.drawEllipse(rootX-RADIUS, rootY-RADIUS, 2*RADIUS+1, 2*RADIUS+1);
Overlay.show();
run("Select None");
lineAtThirtyCM();
angleSelection();
setTool("Angle tool");
}

macro "Define Root Point Tool Options" {
Dialog.create("Root Tools - Define Root Point - Options");
Dialog.addNumber("radius: ", RADIUS);
Dialog.addNumber("line width: ", ROOT_POINT_LINE_WIDTH);
Dialog.addString("root point color: ", COLOR_ROOT_POINT);
Dialog.addNumber("depth [cm]: ", COUNT_ROOT_DEPTH);
Dialog.addNumber("half of length [cm]: ", HALF_LINE_WIDTH);
Dialog.addNumber("line width for depth: ", WIDTH_DEPTH);
Dialog.addString("depth line color: ", COLOR_DEPTH);
Dialog.addNumber("dx angle: ", DX_ANGLE);
Dialog.addNumber("dy angle: ", DY_ANGLE);
Dialog.show();
RADIUS = Dialog.getNumber();
ROOT_POINT_LINE_WIDTH = Dialog.getNumber();
COLOR_ROOT_POINT = Dialog.getString();
COUNT_ROOT_DEPTH = Dialog.getNumber();
HALF_LINE_WIDTH = Dialog.getNumber();
WIDTH_DEPTH = Dialog.getNumber();
COLOR_DEPTH = Dialog.getString();
DX_ANGLE = Dialog.getNumber();
DY_ANGLE = Dialog.getNumber();
}

macro "Angle Action Tool- C000T4b12a" {
measureAngle();
}

macro "Angle Action Tool Options" {
Dialog.create("Root Tools - Angle - Options");
Dialog.addString("angle color: ", ANGLE_COLOR);
Dialog.addNumber("line width: ", ANGLE_LINE_WIDTH);
Dialog.show();
ANGLE_COLOR = Dialog.getString();
ANGLE_LINE_WIDTH = Dialog.getNumber();
}

macro "Measure Depth Tool- C000T4b12d" {
getCursorLoc(x, y, z, flags);
deepX = x;
deepY = y;
DEPTH = deepY - rootY;
toScaled(DEPTH);
setColor(MEASURE_DEPTH_COLOR);
setLineWidth(MEASURE_DEPTH_WIDTH);
Overlay.drawLine(rootX, rootY, rootX, deepY);
Overlay.drawLine(rootX, deepY, deepX, deepY);
Overlay.show();
run("Select None");
setTool("Zoom region Tool");
}

macro "Measure Depth Tool Options" {
Dialog.create("Root Tools - Measure Depth - Options");
Dialog.addString("line color: ", MEASURE_DEPTH_COLOR);
Dialog.addNumber("line width: ", MEASURE_DEPTH_WIDTH);
Dialog.show();
MEASURE_DEPTH_COLOR = Dialog.getString();
MEASURE_DEPTH_WIDTH = Dialog.getNumber();
}

macro "Zoom region Tool- C000T4b12z" {
title = getTitle();
getCursorLoc(x, y, z, flags);
makeRectangle(x-ZOOM_RADIUS, y-ZOOM_RADIUS, 2*ZOOM_RADIUS+1, 2*ZOOM_RADIUS+1);
run("Duplicate...", "title="+title+"box");
run("Remove Overlay");
run("In [+]");
run("In [+]");
run("In [+]");
run("In [+]");
run("In [+]");
run("In [+]");
setTool("line");
}

macro "Zoom region Tool Options" {
Dialog.create("Root Tools - Zoom region - Options");
Dialog.addNumber("radius ", ZOOM_RADIUS);
Dialog.show();
ZOOM_RADIUS = Dialog.getNumber();
}

macro "Measure diameter Action Tool- C000T4b12m" {
measureDiameter();
}

macro "Measure diameter Action Tool Options" {
Dialog.create("Root Tools - Measure diameter - Options");
Dialog.addString("line color: ", DIAMETER_COLOR);
Dialog.addNumber("line width", "DIAMETER_WIDTH);
Dialog.show();
DIAMETER_COLOR = Dialog.getString();
DIAMETER_WIDTH = Dialog.getNumber();
}

macro "Write report Action Tool- C000T4b12w" {
writeReport();
}

function lineAtThirtyCM() {
setColor(COLOR_DEPTH);
setLineWidth(WIDTH_DEPTH);
tenUnscaled = HALF_LINE_WIDTH;
toUnscaled(tenUnscaled);
thirtyUnscaled = COUNT_ROOT_DEPTH;
toUnscaled(thirtyUnscaled);
X1 = rootX - tenUnscaled;
X2 = rootX + tenUnscaled;
Y = rootY + thirtyUnscaled;
Overlay.drawLine(X1, Y, X2, Y);
Overlay.show();
}

function angleSelection() {
xCoords = newArray(3);
yCoords = newArray(3);
xCoords[0] = rootX - DX_ANGLE;
xCoords[1] = rootX;
xCoords[2] = rootX + DX_ANGLE;
yCoords[0] = rootY + DY_ANGLE;
yCoords[1] = rootY;
yCoords[2] = rootY + DY_ANGLE;
makeSelection("angle", xCoords, yCoords);
}

function setScale() {
getLine(x1, y1, x2, y2, lineWidth);
dx = x2-x1;
dy = y2-y1;
length = sqrt(dx*dx+dy*dy);
options = "distance=" + length+" known="+KNOWN_DISTANCE+" pixel=1 unit="+UNIT;
if (USE_GLOBAL_SCALE) options = options + " global";
run("Set Scale...", options);
run("Select None");
setTool("Define Root Point Tool");
}

function measureAngle() {
run("Measure");
ANGLE = getResult("Angle", nResults-1);
selectWindow("Results");
run("Close");
getSelectionCoordinates(xCoordinates, yCoordinates);
run("Select None");
setColor(ANGLE_COLOR);
setLineWidth(ANGLE_LINE_WIDTH);
Overlay.drawLine(xCoordinates[0], yCoordinates[0], xCoordinates[1], yCoordinates[1]);
Overlay.drawLine(xCoordinates[1], yCoordinates[1], xCoordinates[2], yCoordinates[2]);
Overlay.show();
setTool("Measure Depth Tool");
}

function measureDiameter() {
getLine(x1, y1, x2, y2, lineWidth);
dx = x2-x1;
dy = y2-y1;
length = sqrt(dx*dx+dy*dy);
toScaled(length);
DIAMETERS[numberOfRootsAtThirty++] = length;
close();
selectImage(ID);
getSelectionBounds(x, y, width, height);
run("Select None");
setColor(DIAMETER_COLOR);
setLineWidth(DIAMETER_WIDTH);
Overlay.drawLine(x+x1, y+y1, x+x2, y+y2);
Overlay.show();
setTool("Zoom region Tool");
}

function writeReport() {
NUMBER++;
getDateAndTime(year, month, dayOfWeek, dayOfMonth, hour, minute, second, msec);
title = "root measurements - " + year + "-" + month + "-" + dayOfMonth + ".txt";
ref = "[" + title + "]";
if (!isOpen(title)) {
run("Table...", "name="+ref+" width=250 height=600");
header = "\\Headings:" + "nr." + "\t" + "image" + "\t" + "root x" + "\t" + "root y" + "\t" + "angle" + "\t" + "depth" + "\t" + "nr at 30cm";
for (i=0; i<MAX_ROOTS; i++) {
header = header + "\t" + "d" + (i+1);
}
print(ref, header);
}
row = "" + NUMBER + "\t" + TITLE + "\t" + rootX + "\t" + rootY + "\t" + ANGLE + "\t" + DEPTH + "\t" + numberOfRootsAtThirty;
for (i=0; i<numberOfRootsAtThirty; i++) {
row = row + "\t" + DIAMETERS[i];
}
print(ref, row);
resetMeasurements();
if (!File.exists(FOLDER + "/" + "control/")) File.makeDirectory(FOLDER + "/" + "control/");
path = FOLDER + "/" + "control/" + TITLE;
saveAs("tiff", path);
Overlay.remove;
setTool("line");
}

function resetMeasurements() {
numberOfRootsAtThirty = 0;
DIAMETERS = newArray(MAX_ROOTS);
}
    (1-1/1)