/* INSTRUCTIONS Macro for object volume estimation using exhaustive serial sections. It needs an image stack, it will not work on a single image. A grid of evenly-spaced points is displayed on cross-sections at a user-specified z-interval and the user counts how many points fall within each structure of interest. An algorithm then calculates an approximate volume for each structure. This macro is based on Cavalieri principle. Upon running the macro the user must specify several parameters in the [Cavalieri estimator] window, including the number of points to be displayed per slice, the stack slice thickness, the number of objects being analysed and the z-interval of slices to display. Once parameters are set the user then assigns each object a name associated with a specific counter (starting from Counter 0). The current selected counter can be changed by double-clicking on the [Multi-Point Tool] in the Image J menu and selecting from the ‘Counter’ drop down menu. The user-assigned object names for each counter can be viewed in the [Cavalieri estimator parameters for stack] window. To begin counting, the user simply clicks on each cross that falls within the object of interest whilst the corresponding counter is selected. Mistakenly placed points can be undone by Alt-clicking the point in question. Click on each cross that falls within the objects being analysed in every displayed slice before pressing the [OK] button housed on the appropriately titled grey pop-up window. The Macro will then display the resulting volume information in the [Cavalieri estimator parameters for stack] window. As a rule of thumb, the total number of points counted for each object in an image stack should be no more than 100-200 due to diminishing returns in accuracy. Set the parameters in the [Cavalieri estimator] window to reflect this by making sure that there are an appropriate number of crosses displayed and that there is a sufficient interval between the slices which are to be analysed. The appearance of the displayed crosses can also be changed. If no image stack is open when the macro is run then the user will be asked to open an example stack from ImageJ – mri-stack.tif. For analysis of this stack the default parameters should be left unchanged. A good practice exercise is to estimate the volume of both eyeballs. Consider not only the vitreous body (dark) but also the sclera (the dense outer layer of the eyeball) and the eye front chamber limited by the cornea. As a rough guide, the human eyeball is on average around 6cm in volume. Many thanks to Tobias Starborg and David Smith who helped in testing and improving this macro. Version: 1.2 Date: 28/11/2018 Author: Aleksandr Mironov amj-box@mail.ru */ requires("1.52i"); //help html = "" +"

Cavalieri volume estimator

" +"Macro for object volume estimation using exhaustive serial sections.
" +"It needs an image stack, it will not work on a single image.
" +"A grid of evenly-spaced points is displayed on cross-sections at
" +"a user-specified z-interval and the user counts how many points
" +"fall within each structure of interest. An algorithm then calculates
" +"an approximate volume for each structure. This macro is based on
" +"Cavalieri principle.


" +"How to work with this macro

" +"1) Specify parameters in [Cavalieri estimator] dialog:
" +"    - appearance of displayed points
" +"    - number of points per slice
" +"    - number of objects being analysed
" +"    - original z-interval between slices
" +"    - stack reslicing option

" +"2) Assign each object a name associated with a specific counter
" +"   (starting from Counter 0)

" +"3) To count - click on each cross within object of interest

" +"4) Double click on [Multi-Point Tool] in the Image J menu and
" +"    select a counter for the next object from drop down menu

" +"5) After counting is done press [OK] on grey pop-up window

" +"6) Macro displays results in
" +"   [Cavalieri estimator parameters for stack] window

" +"Mistakenly placed points can be undone by Alt-clicking the point.
" +"As a rule of thumb, the total number of points counted for each object in an
" +"image stack should be no more than 100-200 due to diminishing returns in
" +"accuracy. Cavalieri estimator needs at minimum 7-8 slices per object to be efficient.

" +"If no image stack is open when the macro is run then the user will be
" +"asked to open an example stack from ImageJ - mri-stack.tif. For analysis of
" +"this stack the default parameters should be left unchanged. A good practice
" +"exercise is to estimate the volume of both eyeballs. Consider not only the
" +"vitreous body (dark) but also the sclera (the dense outer layer of the eyeball)
" +"and the eye front chamber limited by the cornea. As a rough guide, the
" +"human eyeball is on average around 6cm3 in volume.

" +"Many thanks to Tobias Starborg and David Smith who helped in testing
" +"and improving this macro.

" //Open stack check if (nImages==0) { Dialog.create("Stack for counting"); Dialog.addMessage("No open stacks detected"); Dialog.addChoice("Do you want to open example stack?", newArray("yes", "no")); Dialog.addHelp(html); Dialog.show(); ImgChk = Dialog.getChoice(); if (ImgChk == "yes") { MRI_instr(); MRI_set(); } } //Get stack parameters getDimensions(width, height, channels, slices, frames); getVoxelSize(VxWidth, VxHeight, VxDepth, unit); name = getTitle(); shortside = minOf(width, height); if (slices<2) { exit("This macro needs an image stack!"); } //Setting counting parameters Dialog.create("Cavalieri estimator"); Dialog.addMessage("Counting grid parameters:"); Dialog.addChoice("Points color:", newArray("red", "cyan", "magenta", "blue", "yellow", "orange", "green", "black", "white"));//choice1 Dialog.addChoice("Points type:", newArray("crosshair", "circle", "dot", "hybrid"));//choice2 Dialog.addChoice("Points size:", newArray("tiny", "small", "medium", "large", "extra large"));//choice3 Dialog.addNumber("Points number:", 30,0,2,"within short side");//number1 Dialog.addCheckbox("New Overlay", true);//check1 Dialog.addCheckbox("Random Offset", true);//check2 Dialog.addMessage("_______________________________________"); Dialog.addMessage("Do not forget to [Set Scale] for correct results!"); Dialog.addMessage("_______________________________________"); Dialog.addMessage("Stack parameters:"); Dialog.addNumber("Number of objects to count ", 2);//number 2 Dialog.addNumber("Original stack slice thickness ", 0.4,3,6," "+unit);//number 3 Dialog.addMessage("Active stack can be resliced using the next line. \nPlease, make sure that "+slices+" slices in your stack \nare divisible by selected number"); Dialog.addNumber("Count points on every ", 1,0,3,"slice");//number4 Dialog.addHelp(html); Dialog.show(); //Counting parameters new = Dialog.getCheckbox();//check1 if (new == true) Overlay.remove; offset = Dialog.getCheckbox();//check2 color = Dialog.getChoice();//choice1 type = Dialog.getChoice();//choice2 size = Dialog.getChoice();//choice3 number = Dialog.getNumber();//number1 ObjNmb = Dialog.getNumber();//number 2 SlcThk = Dialog.getNumber();//number3 reslice = Dialog.getNumber();//number4 VxDepth = SlcThk; setVoxelSize(VxWidth, VxHeight, VxDepth, unit); tile = shortside/number; PntNmb = round(width/tile*height/tile); PntArea = width*height*VxWidth*VxHeight/PntNmb; //reslicing if too many slices if (reslice>1) { newVxSize = reslice*VxDepth; run("Reslice Z", "new=newVxSize"); close(name); rename(name); setVoxelSize(VxWidth, VxHeight, newVxSize, unit); getVoxelSize(VxWidth, VxHeight, VxDepth, unit); getDimensions(width, height, channels, slices, frames); } run("Maximize"); //Naming counters Dialog.create("Names for Counters"); for (i=0;i1500) run("In [+]"); rename("Instructions for mri-stack"); //Printing instructions run("RGB Color"); setLocation(0, 0); setColor("green"); setFont("SansSerif", 20, "antialiased"); drawString("Instructions for MRI stack example:", 5, 150); setFont("SansSerif", 14, "antialiased"); setColor("cyan"); drawString("- Use default counting parameters", 5, 190); drawString("- Name 2 counters for eyeballs", 5, 220); drawString("- Count points hitting eyeballs on relevant slices", 5, 250); drawString("- Change counters by double click on", 5, 280); drawString(" [Multipoint Tool] in ImageJ Menu", 5, 310); drawString("- Eyeball structures are shown in red circle", 5, 340); drawString("- Eyeball volume should be about 6cm3", 5, 370); setColor("yellow"); drawString("Use 'Help' button in dialog to see full instructions", 5, 420); //Identifying eyeball setColor("red"); drawOval(220, 47, 65, 65); //Making Multipoint Tool Icon setColor("white"); drawRect(278,258,30,30); setColor("black"); drawRect(279,259,28,28); setColor(180, 180, 180); fillRect(280, 260, 26, 26); xcross = newArray(286,286,284,288,287,287,285,289,294,294,292,296,295,295,293,297,300,300,298,302); ycross = newArray(266,270,268,268,275,279,277,277,264,268,266,266,274,278,276,276,268,272,270,270); xpoints = newArray(286,294,287,295,300); ypoints = newArray(268,266,277,276,270); xarrow = newArray(300,304,301,303,302,302); yarrow = newArray(280,280,281,281,282,282); setColor("black"); for (i=0; i<20; i++) { j=i+1; drawLine(xcross[i], ycross[i], xcross[j], ycross[j]); i=i+1; } setColor("yellow"); for (i=0; i<5; i++) { drawLine(xpoints[i], ypoints[i], xpoints[i], ypoints[i]); } setColor(150, 0, 0); for (i=0; i<6; i++) { j=i+1; drawLine(xarrow[i], yarrow[i], xarrow[j], yarrow[j]); i=i+1; } run("Select None"); }