{
Point Counting/Stereology Macros 1.0
This file contains a set of simple Object Image point counting macros.  They are not particularly complex, but we have found them useful in our lab.  They are used to count the number of grid points that fall on brain matter in a mounted slide.  These counts are then used to calculate brain volumes in an Excel spreadsheet.  There are several things you should be aware of when using this macro:

o Run the 'Set Params' macro to configure the grid size.  If you do not set your own parameters, the default 50x50 pixel grid starting at (25,25) will be used.  It is not necessary to display the point grid to count, but it is certainly recommended. 

o The Count mamarks all grid points (whether or not the grid has been drawn) that fall on pixels with values greater than a user-specified threshold in the selected area. 

o It is wise to have a human check over the computer's count, since it is not always able to differentiate between interference and actual image.  In order to minimize the occurance of this sort of error the macro checks the average value of the pixels surrounding the selected pixel. 

o The point grid is drawn directly on the image, so it is advisable to work with a copy or to be sure not to save the image. 

o You must have an object file with points defined to use this macro.  Once one object file is open, it is not necessary to open a new one for every image.  These macros could be easily adapted to work without object files.

o There is a package of stereology grid macros by John Russ that could easily be used in conjunction with these macros. 

Thank you,  

Tony Capra  - 7/6/00 - Williams Lab - UT Health Science Center www.nervenet.org
}

Var                                                         {Global Variables for grid params}
  gridLen, gridStart: integer;

Macro 'Count/6';

VAR
	x, y, i, j, k, l, numPoints, maxX, maxY, roiTop, roiLeft, roiHeight, roiWidth, color, sum, thold, suggest: integer;
	
BEGIN
	GetPicSize(maxX,maxY);
	
	GetROI(roiTop,roiLeft,roiWidth,roiHeight);

{This bit o' code attempts to suggest a valid threshold... it is not particularly reliable.}
  suggest := 0;
  FOR k := ((roiTop + roiWidth)-1) to ((roiTop + roiWidth)+1) DO BEGIN
        FOR l := ((roiLeft + roiHeight)-1) to ((roiLeft + roiHeight)+1) DO BEGIN
          suggest:= suggest + GetPixel(k,l);        
        END;   
     END;
  suggest := suggest / 9;
  IF (suggest = 0) THEN BEGIN
     suggest := 1; END; 

 thold := GetNumber('Please enter a threshold value:', suggest,0);	

 IF (gridLen = 0) THEN BEGIN                                                     {Set defaults.}
    gridLen := 50;
    gridStart := 25;
 END; 
 
 FOR i := roiTop to (roiWidth + roiTop) DO                                 {Loop through the selected region}
		BEGIN
			FOR j := roiLeft to (roiHeight + roiLeft) DO
				BEGIN
     x := Trunc(((i)/gridLen)) * gridLen + gridStart;                   {Evaluate the (gridStart + gridLen*n)}
     y := Trunc(((j)/gridLen)) * gridLen + gridStart;                   {pixel.}
 
     sum := 0;
     FOR k := (x-1) to (x+1) DO BEGIN                                        {Find the average value of the 9} 
        FOR l := (y-1) to (y+1) DO BEGIN                                      {surrounding pixels.}
          sum:= sum + GetPixel(k,l);        
        END;   
     END; 
    	
     color := sum/9;
     ShowMessage('Color=', color, '  x= ',x, '  y= ',y);

					IF (color > thold) THEN BEGIN                                              {If the average is greater than the}                             
						numPoints:= numPoints + 1;                                              {threshold value mark the point.}
					
    	  SetMarker(x,y);

					END;
    j:=j+(gridLen - 1);
				END;	
		i:=i+(gridLen -1);		
		END;

  PutMessage('There are' ,numpoints, ' points in this region.');
  		
END;		

{This macro lets you to set the parameters used when drawing the point grid and counting.}
Macro 'Set Params';              
  Begin
    gridStart := GetNumber('Please enter a start point for the grid:', 25,0);     {Start coords.}
    gridLen := GetNumber('Enter the grid length:', 50,0);          {Set the size (in pixels) of each square                  
                                                                                              in the grid}
End;

{This macro draws the point grid. To change the size of the grid, run the Set Param macro first.}
Macro 'Point Grid';
  Var
     x,y, maxX, maxY, numPoints, pix: integer;
     size: real;
     units: string;
 BEGIN
      GetPicSize(maxX, maxY);

      SetPalette('Grayscale',1);
      SetForegroundColor(1);
     
      IF (gridLen = 0) THEN BEGIN                                                     {If no user-entered params, set} 
          gridLen := 50;                                                                     {default values}
          gridStart := 25;
      END; 
   
     Setlinewidth(1);                                                                       {Draw grid.}
     FOR x := gridStart TO maxX DO BEGIN
        FOR y:= gridStart TO (maxY - gridlen) DO BEGIN
            MoveTo (x-5, y);
						      LineTo (x-1, y);
					   	   MoveTo (x+1, y);
				   		   LineTo (x+5, y);
			   			   MoveTo (x, y-5);
		   				   LineTo (x, y-1);
		   				   MoveTo (x, y+1);
		   			   	LineTo (x, y+5);
            
            numPoints := numPoints + 1;
            y := y + (gridLen - 1); 
        END;
         x := x + (gridLen - 1); 
     END;
    
    GetScale(pix,units);                                                               {Print stats at bottom left.}
    MoveTo (5,maxY-6);       
    SetFont('Geneva');
    SetFontSize(10);
    Write('Total Points=',numPoints);
	   size:=(maxX*maxY)/(pix*pix);
	   Moveto (5,maxY-18);
    Write('Total Area=',size:10,' sq.',units);
END;

Macro 'Reset LUT';
BEGIN
    SetPalette('Grayscale',0);
END;