{*****************************************************************************} {*****************************************************************************} {This macro acquires and evaluates pictures for the Comet (Single cell electrophoresis) assay. Is measures the tail length and the tail moment} {It may be redistributed under the terms of the GNU License (see the LICENSE file.} {If you publish work utilizing this macro you are required to cite: C. Helma and M. Uhl, A public domain image analysis progam for the single cell gel electrophoresis (comet) assay, submitted to Mutation Research 1999} {*****************************************************************************} {Definition of global variables} var counter: integer; {counts the number of measurements} threshold: integer; {this value discriminates the comet from the background} uthreshold: integer; {only for administration} ImageLength: integer; Comety: integer; {y-coordinate for the comet center} CometLeft: integer; {x-coordinate for the left edge of the comet} CometRight: integer; {x-coordinate for the right edge of the comet} CometHeight: integer; {height of the comet} TotalArea: integer; {area of the comet} TotalInt: integer; {mean intensity of the comet} TotalDNA: integer; {DNA of the comet} Max: integer; {maximum intensity of the comet == approx. head center} left: integer; {intermediate variables for } top: integer; {ROI measurements} width: integer; height: integer; Headx: integer; {x-coordinate for the head center} Heady: integer; {y-coordinate for the head center} HeadDiameter: integer; TailLength: integer; HeadArea: integer; HeadInt: integer; {mean head intensity} HeadDNA: integer; {DNA in the head} TailArea: integer; TailDNA: integer; {DNA in the tail} TailDNAPr: real; {Percentage DNA in the tail} TailMoment: real; maxArea: integer; {intermediate variable for the location of the heads center} n,i,imax: integer; {counters} CometTop: integer; {y-coordinate of the comet top} Data: string; {name of the data window} CodeNr: integer; {code nr for the current measurement} {****************************Added by Tom Morton 1/19/00 *******************} FolderName: String: {Folder Name to save text file} {***************************End Add ********************************************} {*****************************************************************************} macro 'Capture a new picture [C]'; begin SetVideo('Highlight'); {Set basic properties} SetPalette('Greyscale',1); SetFont('Courier'); SetFontSize(12); DisposeAll; {Get rid of all existing Image windows} {Create a new Data window if it is the first measurement:} if counter = 0 then begin CodeNr:= GetNumber('Please enter the code number:', CodeNr, 0); Data:= concat(CodeNr); {********************** Added by Tom Morton 1/19/00 *********************} FolderName:=' '; {***************************** End Add *************************************} NewTextWindow(Data,10,10); Writeln ('MeasNr CodeNr Comet Area Mean Comet Int. Head Area Mean Head Int. Tail Length Tail Moment'); counter:=1; end; StartCapturing; end; {*****************************************************************************} macro 'Acquire an image [A]'; begin Capture; SetPicName('Image'); ResetCounter; InvertY(false); Filter('smooth'); {You may have to experiment with filter settings} Invert; {Necessary to obtain dark comets on bright background} {Set the threshold to default values if it is not already set} if threshold=0 then threshold:=80; {Adjust the default threshold for *your* system !!} SetThreshold(threshold); SelectTool('wand'); {Select correct tool and window} SelectWindow('Image'); end; {*****************************************************************************} macro 'Acquire an image from a file [F]'; begin DisposeAll; Open(''); {Change to "Import('File Name')" if you have to import a file} SetPicName('Image'); {Create a new Data window if it is the first measurement:} if counter = 0 then begin CodeNr:= GetNumber('Please enter the code number:', CodeNr, 0); Data:= concat(CodeNr); {********************** Added by Tom Morton 1/19/00 *********************} FolderName:=' '; {***************************** End Add *************************************} NewTextWindow(Data,10,10); Writeln ('MeasNr CodeNr Comet Area Mean Comet Int. Head Area Mean Head Int. Tail Length Tail Moment'); counter:=1; end; {Go back to the Image window} SelectWindow('Image'); ResetCounter; InvertY(false); Filter('smooth'); {You may have to experiment with filter settings} Invert; {Necessary to obtain dark comets on bright background} {Set the threshold to default values if it is not already set} if threshold=0 then threshold:=80; {Adjust the default threshold for *your* system !!} SetThreshold(threshold); SelectTool('wand'); {Select correct tool and window} SelectWindow('Image'); end; {*****************************************************************************} macro 'Measure a selected Comet [M]'; begin { SetPrecision(8);} SetScale(0,'pixel'); {SetScale(1.95,'µm');} {Set *your* pixel:µm ratio} SetOptions('Area,Mean,Min/Max,X-Y Center,Int.Den'); GetThresholds(threshold,uthreshold); {Remove all pictures except 'Image'} n:= PicNumber; for i:=1 to nPics do begin SelectPic(i); if (PicNumbern) then Dispose; end; SelectWindow('Image'); {Measure the whole area and DNA content} Copy; Clear; {************** Added By Tom Morton 1/19/00 ***************} SetNewSize(640, 480); {************** End Add ***************************************} MakeNewWindow('Measure'); Paste; {Move the selected comet to a separate window} GetRoi(left,top,width,height); {************** Added by Tom Morton 1/19/00 ***************} SetNewSize(width, height); MakeNewWindow('Temp'); Paste; SelectWindow('Measure'); {************** End Add *************************************} CometLeft:=left; CometRight:=CometLeft+width; CometTop:=top; CometHeight:=height; Comety:=top+height/2; ImageLength:=width; Measure; TotalArea:= rArea[rCount]; TotalInt:= rMean[rCount]; TotalDNA:= TotalArea*TotalInt; Max:= rMax[rCount]; {Locate the center of the head} SelectAll; MakeROI(CometLeft,CometTop,ImageLength,CometHeight); SetThreshold(0.8*Max); {Locate the area of maximum intensity} AnalyzeParticles('Reset'); {********************* Added by Tom Morton 1/19/00 *************} SelectWindow('Temp'); SelectAll; Copy; Dispose; SelectWindow('Measure'); Paste; KillRoi; {**************************** End Add ******************************} {Find the largest Particle, which should be the Head} imax:=1; if rCount>1 then begin maxArea:=0; for i:=1 to rCount do begin if rArea[i]>maxArea then begin maxArea:=rArea[i]; imax:=i; end; end; end; Headx:=rX[imax]; Heady:= Comety; HeadDiameter:= (Headx - CometLeft)*2*0.8; {reduce the head diameter by the empirically derived value 0.8 (adjust if necessary), otherwise the head would begin *exactly* at the left end of the comet and cover a much too large area} TailLength:= CometRight - Headx - HeadDiameter/2; {Removes negative Tail Length, just for safety} if TailLength<0 then TailLength:=0; {Mark and measure the head} MakeOvalRoi(CometLeft+HeadDiameter*0.1,Heady-HeadDiameter/2,HeadDiameter,HeadDiameter); Measure; HeadArea:= rArea[rCount]; HeadInt:= rMean[rCount]; HeadDNA:= rArea[rCount]*rMean[rCount]; {Compute tail parameters} TailArea:= TotalArea-HeadArea; TailDNA:= TotalDNA-HeadDNA; TailDNAPr:= TailDNA/(HeadDNA+TailDNA)*100; TailMoment:= TailDNAPr*TailLength; {Mark the measurement points} SelectWindow('Measure'); DrawBoundary; {Display the results} SetForegroundColour(255); MoveTo(2,10); Writeln('STATUS:'); Writeln(' No Code'); Writeln(counter:3,CodeNr:8); Writeln(''); Writeln('RESULTS:'); Writeln('Tail Length % Migrated DNA Tail Moment'); Writeln(TailLength:11:0,TailDNAPr:16:1,TailMoment:13:2); Writeln(''); Writeln('Type "K" to keep the measurement'); Writeln('Type "D" to discard this measurement and make a new one'); Writeln(''); end; {*****************************************************************************} macro 'Keep the Data [K]'; begin {****************************** Changed by Tom Morton 1/19/00 ********************} if (FolderName=' ') then begin FolderName:=GetString('What folder to save the measurement file: ', 'C:\Temp\'); SelectWindow(Data); Data:=concat(FolderName, Data); end else begin SelectWindow(Data); {Write results into the data window} end; {************************************** End Change **********************************} Writeln(counter:3,CodeNr:8,TotalArea:11:0,TotalInt:16:2,HeadArea:11:0,HeadInt:16:2,TailLength:13:2,TailMoment:14:2); counter:=counter+1; {Increase the measurement counter} {*********************** Changed by Tom Morton 1/19/00 ****************} SaveAs(Data); {**************************** End Change ********************************} if counter>50 then begin {Remind the user to start with a new slide} PutMessage('You have already more than 50 measurements.\Type "E" to enter the code for a new slide.'); end; {************* Removed by Tom Morton 1/19/00 ************ Data:=WindowTitle; ********************** End Remove ************************} SelectWindow('Image'); {Switch back to the Image window} DrawBoundary; end; {*****************************************************************************} macro 'Discard this measurement and make a new one [D]'; begin SelectWindow('Image'); {Switch back to the Image window} DrawBoundary; end; {*****************************************************************************} macro 'Enter new code number [E]'; begin SelectWindow(Data); Close; CodeNr:= GetNumber('Please enter the new code number:', CodeNr, 0); Data:= concat(CodeNr); NewTextWindow(Data,10,10); Writeln ('MeasNr CodeNr Comet Area Mean Comet Int. Head Area Mean Head Int. Tail Length Tail Moment'); counter:=1; end; {*****************************************************************************} macro 'Quit [Q]'; begin DisposeAll; SelectWindow(Data); Close; CodeNr := 0 ; counter := 0; Exit; end; {*****************************************************************************} {*****************************************************************************}