{Comments ************************ NIH-Image macro file ************************** ************************ for NIH-Image 1.6 ************************** © Thomas Seebacher Abteilung Zell- und Tumorbiologie Universität Konstanz Universitätsstr. 10 D-78464 Konstanz Germany ---------------------------------------------------------------------- This macro including manual and license information is also available by internet from http://www.uni-konstanz.de/tt/software/mwmacro.html or can be requested by E.Mail from Thomas.Seebacher@uni-konstanz.de ---------------------------------------------------------------------- This program estimates molecular weights of DNA restriction fragments or protein bands directly from scanned gel images.It can be used to calculate Mw pI values and spot intensities of 2D gels. It can also be used for Dot Blot, Slot Blot and other densitometric analysis tasks as well. Assumes a gel orientation from top to bottom for the MW separation Assumes a gel orientation from left to right for pI focussing direction First calibrate the gel with a set of known molecular weight standards. Start the first macro and for each reference band you want to include in the calibration curve locate the band (from top to bottom in descending order) with the cursor, click on it and enter the corresponding molecular weight in the displayed dialog box. Press the option (alt) key when finished. IMPORTANT! The line connecting the first and the last selected band defines the lane orientation. Many gel photographs were not strictly vertically aligned.I have included a correction for this misalignment.The lane orientation is defined by the coordinates of the first and last selected reference band. A correction angle is then calculated and used to correct all image coordinates so that all points which were perpendicular to the lane direction have the same molecular weight.The gel orientation should be from top to bottom for the molecular weight separation since the y coordinates were used for the calculation of molecular weights and x coordinates were used for the calculation of pI values. As default value Focusdirection:=90 is set in the prefs1 procedure settings and the focussing run is assumed to be 90 degrees rotated versus the Mw separation and the angle+90 degrees of the first dimension is used.Then 2D reference standards can be selected within the entire 2D gel (internal standards) but must be entered from left to right in strictly increasing or decreasing order. For any other value Focusdirection:=0 the first and the last selected pI reference define the gel orientation concerning the direction of the focussing run. For automatic particle detection and measurements set the lower and upper thresholds in the density slice mode with the LUT tool to discriminate particles. For more information please read the manual. ----------------------------------------------------------------------------- The excellent NIH-Image program is available by anonymous ftp from zippy.nimh.nih.gov/pub/nih-image or from http://rsb.info.nih.gov/nih-image and many mac mirror sites like nic.switch.ch. -----------------------------------------------------------------------------} {Start of the program © Version 16/9/96} {global vars} var x,y,m,npi,MWcalibrated,PIcalibrated:integer; {global vars} MW,Pi,alpha,alphapi:real; Lauffront,Focusdirection,Ball:integer; {Prefs1 sets some initial conditions minimal and maximal particle size 5,99999 pixels Rolling ball radius 35 only for the background subtraction in the mask image. For broader bands increase the radius Correction for difference center/leading edge of a band Lauffront=1 lower band boundary, 0=Center SetScale(0,'pixels') disables spatial calibration Focusdirection:=90 means the gel orientation is determined by the Mw calibration and the focussing run is 90 degrees different. For any other value the angle for the focussing run will be determined separately from the first and last selected pI standards} {Preferential settings can be changed here} procedure prefs1; begin Lauffront:=0; Focusdirection:=90; SetParticleSize(5,99999); Ball:=35; InvertY(0); {do not change} IncludeInteriorHoles(1); SetScale(0,'pixels'); end; {waits for mouse clicks during band selection} procedure click; begin; SetCursor('cross'); repeat {waiting for user action} until button OR KeyDown('option'); end; {Erases all flags but not the measurement registers} procedure eraseflags; begin MWcalibrated:=0; PIcalibrated:=0; rMean[1]:=0; rMean[2]:=0; end; procedure error1; begin; putMessage('Two different reference bands have the same y coordinate or the calibration data have been cleared'); eraseflags; exit; end; procedure error2; begin PutMessage('The gel needs to be calibrated first'); exit; end; procedure error3; begin PutMessage('You must enter at least 2 reference bands'); eraseflags; exit; end; procedure error4; begin PutMessage('The pI values exeed the allowed range between 0 and 14'); exit; end; procedure error5; begin PutMessage('Please reset all older pI calibration data before starting a new molecular weight calibration'); ShowMessage('I have tried to calculate pI values but the gel was not calibrated and the pI calibration flag was set from an earlier calibration. Please use the Reset macro to clear all older measurements data and try again'); exit; end; {Angle correction for the MW y coordinates} procedure transform; begin y:=y+(x-rX[1])*sin(alpha)/cos(alpha); end; {Angle correction for the pI x coordinates} procedure pitransform; begin x:=x+(y-rMajor[1])*sin(alphapi)/cos(alphapi); end; {Transforms the pI reference band x coordinates} procedure recalcpi; var i:integer; begin for i:=1 to rMean[2] do begin rMinor[i]:=rMinor[i]+(rMajor[i]-rMajor[1])*sin(alphapi)/cos(alphapi); end; {The angle corrected x coordinates of the pI reference bands are stored in the Minor array} end; {Transforms the MW reference band y coordinates} procedure recalc; var i:integer; begin for i:=1 to rMean[1] do begin rMin[i]:=rMin[i]+(rX[i]-rX[1])*sin(alpha)/cos(alpha); end; {The angle corrected y coordinates of the MW reference bands are stored in the Minor array} end; {calculates the MW for any x,y value} procedure MWFunction; var i,n:integer; begin n:=rMean[1]; {for angle correction of the current x} transform; if y<=rMin[1] then begin {above the first reference band}; if ((rMin[2]-rMin[1])=0) then error1; MW:=rLength[1]-(rLength[2]-rLength[1])*(rMin[1]-y)/(rMin[2]-rMin[1]); MW:=exp(MW); end; if y>=rMin[n] then begin {below the last reference band}; if ((rMin[n]-rMin[n-1])=0) then error1; MW:=rLength[n]+(rLength[n]-rLength[n-1])*(y-rMin[n])/(rMin[n]-rMin[n-1]); MW:=exp(MW); end; if (rMin[1]< y) AND (y < rMin[n]) then begin {between 2 reference bands} i:=0; {selects the index number of the two nearest reference bands}; repeat; i:=i+1; until rMin[i]>y; {then exit repeat} if ((rMin[i]-rMin[i-1])=0) then error1; MW:=rLength[i]-(rLength[i]-rLength[i-1])*(rMin[i]-y)/(rMin[i]-rMin[i-1]); MW:=exp(MW); end; end; {calculates the pI for any x,y value} procedure PIFunction; var i,npi:integer; begin if ((rMean[2]=0) AND (PiCalibrated=1)) then error5; npi:=rMean[2]; {for angle correction x} pitransform; if x<=rMinor[1] then begin {left of the first reference band}; if ((rMinor[2]-rMinor[1])=0) then error1; Pi:=rUser2[1]-(rUser2[2]-rUser2[1])*(rMinor[1]-x)/(rMinor[2]-rMinor[1]); end; if x>=rMinor[npi] then begin {right of the last reference band}; if ((rMinor[npi]-rMinor[npi-1])=0) then error1; Pi:=rUser2[npi]+(rUser2[npi]-rUser2[npi-1])*(x-rMinor[npi])/(rMinor[npi]-rMinor[npi-1]); end; if (rMinor[1]< x) AND (x < rMinor[npi]) then begin {between the reference bands} i:=0; {selects the index number of the two nearest reference bands}; repeat; i:=i+1; until rMinor[i]>x; {then exit repeat} if ((rMinor[i]-rMinor[i-1])=0) then error1; Pi:=rUser2[i]-(rUser2[i]-rUser2[i-1])*(rMinor[i]-x)/(rMinor[i]-rMinor[i-1]); end; if Pi<0 then Pi:=0; if Pi>14 then Pi:=14; end; {endlessloop for pI Interpolation exit by mouse click or alt key} procedure PInterpolate; var x1,y1,x2,y2:integer; begin SetOptions( 'X-Y Center,User1'); repeat; SetCursor('cross'); GetMouse(x,y); if PiCalibrated=1 then PIFunction; if PiCalibrated=0 then Pi:=0; GetMouse(x,y) if MWcalibrated=1 then MWFunction; if MwCalibrated=0 then MW:=0; SelectWindow('Info'); GetMouse(x1,y1); ShowMessage('press Option key to stop','\Press Shift to mark up bands','\','\X= ',x:6:0,'\Y= ',y1:6:0,'\pI= ',Pi:6:2,'\MW= ',MW:6:0); if ((MW=0) AND (pI=0)) then error2; if Keydown('shift') then begin Moveto(x1-2,y1+1); DrawText('*'); Moveto(x+2,y1); DrawText(MW:7:0); Moveto(x,y1+9); DrawText(Pi:7:2); end; wait(0.3); until (button OR KeyDown('option')); end; {endlessloop for MW Interpolation exit by mouse click or alt key} procedure Interpolate; var x1,y1:integer; begin SetOptions( 'X-Y Center,User1'); repeat; SetCursor('cross'); GetMouse(x,y); x1:=x; y1:=y; if MWcalibrated=1 then MWFunction; if MWcalibrated=0 then error2; SelectWindow('Info'); GetMouse(x1,y1); ShowMessage('press Option key to stop','\Press Shift to mark up bands','\','\X= ',x:6:0,'\Y= ',y1:6:0,'\MW= ',MW:6:0); wait(0.3); if Keydown('shift') then begin GetMouse(x1,y1); Moveto(x1-2,y1); LineTo(x1+2,y1); MoveTo(x1,y1-2); LineTo(x1,y1+2); Moveto(x1,y1); DrawText(MW:7:0); end; until KeyDown('option'); end; {Routine for the selection of x,y coordinates and pI of the reference bands} procedure Pistandards; var Pivalue:string; Pi:real; begin GetMouse(x,y); rMinor[i]:=x; {stores the x,y-coordinates of the pi reference bands in rMinor, rMajor array} rMajor[i]:=y; Pivalue:=GetString('Isoelectric point value = e.g. 7.5'); Pi:=StringToNum(Pivalue); if Pi>14 then error4; if Pi<0 then error4; rUser2[i]:=Pi; {stores the pI Values in rUser2 array} if i>rMean[1] then begin rUser1[i]:=0; end; end; {Routine for the selection of x,y coordinates and MW of the reference bands} procedure standards; var MWeight:string; MW:real; begin GetMouse(x,y); rX[m]:=x; {stores the y-coordinate of the reference band in rY array} rY[m]:=y; rMin[m]:=y; MWeight:=GetString('Molecular weight ='); MW:=StringToNum(MWeight); rUser1[m]:=MW; {stores the log(MW) of the reference bands in the rLength array} rLength[m]:=ln(MW); if PIcalibrated=0 then rUser2[m]:=0; {rUser2[m]:=0;} end; {MW semi-log Graph} procedure Calibrationgraph; var width,height,i,j:integer; scale:real; begin GetPicSize(width,height); SetNewSize(200,height); SetForeGroundColor(255); SetBackGroundColor(0); MakeNewWindow('Calibration curve'); Scale:=100/(rLength[1]-rLength[rMean[1]]); x:=(rLength[1]-rLength[rMean[1]])*Scale+50; MoveTo(x,rY[1]); for j:=1 to rMean[1] do begin x:=rX[j]; Y:=rY[j]; MWFunction; x:=(ln(MW)-rLength[rMean[1]])*Scale+50; Y:=rY[j]; LineTo(x,Y); MakeOvalRoi(x-3,y-3,6,6); SetForeGroundColor(255); SetBackGroundColor(0); Fill; KillRoi; MoveTo(5,Y); DrawText(MW:6:0); MoveTo(x,Y); end; end; Macro 'First calibrate the gel with MW standards [1]'; var pic,n:integer; nval:string begin prefs1; MWcalibrated:=0; SetUser1Label('MW'); SetUser2Label('Int.'); pic:=PidNumber; ResetCounter; rMean[1]:=0; SelectWindow('Info'); SelectPic(pic); n:=0; m:=1; repeat SetCounter(m); ShowMessage('Press option {alt} key to stop','\click on reference band# ',m); click; if (NOT KeyDown('option')) then begin standards; m:=m+1; end; SelectWindow(WindowTitle); until Keydown('option'); n:=m-1; rMean[1]:=n; { stores the number of reference bands in rMean[1]} if n<2 then error3; SetCursor('arrow'); if (rY[n]-rY[1])=0 then begin PutMessage('The gel orientation should be from top to bottom'); exit; end; alpha:=arctan((rX[n]-rX[1])/(rY[n]-rY[1])); {alpha= rotation angle } recalc; if rMean[1]>=rMean[2] then SetCounter(rMean[1]); MWcalibrated:=1; ShowMessage('Successfully finished gel MW calibration'); PutMessage('The molecular weight calibration included',rMean[1], ' standards'); end; Macro 'Measurement loop{press option key to stop} [2]'; begin; if MWcalibrated=0 then error2; SetCursor('cross'); repeat; Interpolate; until KeyDown('option'); end; Macro 'Measure the MW of selected bands [3]'; var pic1,nm,n:integer; begin if MWcalibrated=0 then error2; pic1:=PicNumber; if rMean[2]> rMean[1] then n:=rMean[2]; if rMean[2]<= rMean[1] then n:=rMean[1]; nm:=n+1; SelectWindow('Info'); SelectPic(pic1); repeat; SetCounter(nm); ShowMessage('Press Option {alt} key to stop','\For MW click on band of interest'); SetCursor('cross'); if (nm<>n+1) then ShowMessage('Press Option {alt} key to stop','\For MW click on band of interest','\X= ',x:6:0,'\Y= ',y:6:0,'\MW= ',MW:6:0,'\band #= ',rCount-n-1); Wait(1); click; GetMouse(x,y); rX[nm]:=x; rY[nm]:=y; MWFunction; rUser1[nm]:=MW; rUser2[nm]:=rCount-n; UpdateResults; nm:=nm+1; PutPixel(x,y,128); MoveTo(x-20,y-15); DrawText(MW:6:0); until KeyDown('option'); SetCounter(nm-2); UpdateResults; SetUser1Label('MW'); SetUser2Label('Nr.'); SetOptions( 'X-Y Center,User1,User2'); ShowResults; end; Macro '-)'; begin end; Macro 'pI calibration ..press option key to stop [F1]'; var i,pic:integer; begin SetScale(0,'pixels'); PIcalibrated:=0; rMean[2]:=0; npi:=0; i:=1; pic:=PidNumber; SelectWindow('Info'); SelectPic(pic); repeat if i>rMean[1] then SetCounter(i); ShowMessage('Press option {alt} key to stop','\click on pI reference band# ',i); click; if (NOT KeyDown('option')) then begin pistandards; i:=i+1; end; UpdateResults; SelectWindow(WindowTitle); until Keydown('option'); npi:=i-1; rMean[2]:=npi; { stores the number of pI reference bands in rMean[2]} if npi<2 then error3; SetCursor('arrow'); alphapi:=arctan((rMajor[npi]-rMajor[1])/(rMinor[npi]-rMinor[1])); {alphapi= rotation angle of the gel for pI values as calculated from the first and last reference maker. If Focusdirection:=90 is set in the prefs1 procedure the rotation angle of the gel as determined from the Mw calibration is applied for the corrections} if MWcalibrated=0 then Focusdirection:=0; if Focusdirection=90 then alphapi:=-alpha; recalcpi; PIcalibrated:=1; if (rMean[1]>=rMean[2]) then SetCounter(rMean[1]); if (rMean[1]Anfzaehler) then ShowMessage('Press Option {alt} key to stop','\For MW click on band of interest','\X= ',x:6:0,'\Y= ',y:6:0,'\pI= ',Pi:6:2,'\MW= ',MW:6:0,'\band #= ',rCount-Anfzaehler); Wait(1); click; GetMouse(x,y); rX[Zaehler]:=x; rY[Zaehler]:=y; if MWcalibrated=1 then MWFunction; if MWcalibrated=0 then MW:=0; rUser1[Zaehler]:=MW; x:=rX[Zaehler]; y:=rY[Zaehler]; if PiCalibrated=1 then Pifunction; if PiCalibrated=0 then Pi:=0; rUser2[Zaehler]:=Pi; if ((MW=0) AND (pI=0)) then error2; UpdateResults; Zaehler:=Zaehler+1; until KeyDown('option'); SetCounter(Zaehler-2); UpdateResults; SetUser1Label('MW'); SetUser2Label('pI'); SetOptions( 'X-Y Center,User1,User2'); ShowResults; end; Macro '(-' begin end; {calculates the y coordinates for a given MW value for the log paper graph} procedure yfunc; var yoff,yrange,width,height:integer; begin {Off = Beginn des Ursprungs; Yrange=350 Skalenbreite Pixels für Bereich rUser1(1)-rUser1(n) } GetPicSize(width,height); yoff:=height-50; Yrange:=height-100; y:=yoff-((ln(MW)-ln(rUser1[rMean[1]])))*Yrange/(ln(rUser1[1])-ln(rUser1[rMean[1]])); end; procedure Loggraph var stepsize,ymin,ymax,n,i:integer; yscale:real; width,height,inkcolor:integer; xbreit,yhoch:integer; xoff,yoff:integer; xscale,yscale:real; begin width:=500; height:=400; yoff:=50; xoff:=50; xbreit:=width-xoff; yhoch:=height-yoff; inkcolor:=128; {grau} SetNewSize(width,height); SetForeGroundColor(255); SetBackGroundColor(0); MakeNewWindow('Log paper graph'); SetFont('Monaco'); SetFontSize(9); SetLineWidth(2); {y- Achse} MoveTo(xoff-3,10+3); LineTo(xoff,10); MoveTo(xoff+3,10+3); LineTo(xoff,10); LineTo(xoff,yhoch+5); {X-Achse} MoveTo(xoff-5,yhoch); LineTo(xbreit,yhoch); LineTo(xbreit-3,yhoch+3); LineTo(xbreit,yhoch); LineTo(xbreit-3,yhoch-3); LineTo(xbreit,yhoch); SetLineWidth(1); ymin:=rUser1[rMean[1]]; ymax:=rUser1[1]; stepsize:=10; if ymin<100000 then stepsize:=10000; if ymin<10000 then stepsize:=1000; if ymin<1000 then stepsize:=100; if ymin<100 then stepsize:=10; x:=xoff; MW:=round((ymin/stepsize)+0.5)*stepsize-stepsize; {Gridlinien} repeat MW:=MW+stepsize; yfunc; {Gridlinecolor} SetForeGroundColor(inkcolor); MoveTo(xoff,y); LineTo(xbreit,y); MoveTo(5,y); SetForeGroundColor(255); DrawText(MW:6:0); If MW=100 then stepsize:=100; if MW=1000 then stepsize:=1000; if MW=10000 then stepsize:=10000; if MW=100000 then stepsize:=25000; until MW>ymax; n:=rMean[1]; {Farbe 128 =grau Linie + dots wenn schwarz gewuenscht auf 255 setzen} SetForeGroundColor(128); SetBackGroundColor(0); for i:=1 to n do begin MW:=rUser1[i]; yfunc; x:=(rY[i]-rY[1])+xoff; if i=1 then MoveTo(x,y); if i<>1 then LineTo(x,y); MoveTo(x+10,y-4); DrawText(rUser1[i]:6:0); MoveTo(x,y); MakeOvalRoi(x-3,y-3,6,6); Fill; KillRoi; end; SetForeGroundColor(255); for i:=1 to rMean[1] do begin x:=(rY[i]-rY[1])+xoff; y:=yhoch; {X-Achse Clips} SetLineWidth(1); MoveTo(x,y); LineTo(x,y+4); end; {Achsenbeschriftung} MoveTo((xbreit)/2,height-30); DrawText('y coordinates'); MoveTo(xoff-2,yhoch+15); DrawText('0'); MoveTo(5,25); DrawText('MW'); MoveTo(5,yhoch); DrawText(rUser1[rMean[1]]:6:0); SetFont('Monaco'); SetFontSize(9); if PiCalibrated=1 then begin xscale:=(xbreit-xoff)/(rMinor[rMean[2]]-rMinor[1]); yscale:=yhoch/14; x:=xoff; y:=yhoch-rUser2[1]*yscale; MoveTo(x,y); for i:=1 to rMean[2] do begin if (rMinor[rMean[2]]-rMinor[1])=0 then exit; x:=(rMinor[i]-rMinor[1])*xscale+xoff; y:=yhoch-rUser2[i]*yscale; LineTo(x,y); MakeOvalRoi(x-3,y-3,6,6); Fill; MoveTo(x+5,y+20); DrawText(rUser2[i]:2:2); MoveTo(x,y); end; end; end; Macro'Log-paper graph [5]'; var x,y,j:integer; begin if MWcalibrated=0 then error2; Loggraph; end; Macro 'Show calibration curve '; begin if MWcalibrated=0 then error2; Calibrationgraph; end; macro'-)' begin {Separating Menu bar line} end; macro 'Particle measurements [4]'; var counter,k,lower,upper,left,top,width,height,seltype:integer; begin if MWcalibrated=0 then error2; SetUser1Label('MW'); SetUser2Label('Int.'); SetOptions( 'X-Y Center,User1,User2'); if PiCalibrated=1 then SetOptions( 'X-Y Center,Max,User1,User2'); SetFont('Monaco'); SetFontSize(8); InvertY(0); counter:=rCount; GetRoi(left,top,width,height); if width=0 then begin {PutMessage('This macro requires a selection. Please select a lane first'); exit;} SelectAll; GetRoi(left,top,width,height); end; if width=0 then begin PutMessage('This macro requires a selection. Please activate an image and make a selection'); exit; end; seltype:=Get('RoiType'); if seltype>=6 then begin PutMessage('Line selections are not allowed'); exit; end; Copy; SetNewSize(width,height); MakeNewWindow('Particles'); Paste; SetDensitySlice(255,255); GetThresholds(upper,lower); AnalyzeParticles('label,outline,include'); Duplicate(WindowTitle); SetPicName('MW'); SetBackgroundColor(0); SelectAll; Clear; SetForeGroundColor(255); {For all found particles calculate the MW and Intensity} for k:=(counter+1) to rCount do begin x:=rX[k]; if width=0 then y:=rY[k]; if width<>0 then begin y:=rY[k]+top; {If a region was active,Y-coordinates have to be corrected} x:=rX[k]+left; end; {Partikelfront/Zentrumkorrektur} if Lauffront=1 then y:=y+rMinor[k]/2-1; MWFunction; rUser1[k]:=MW; rUser2[k]:=rMean[k]*rArea[k]; {Particle intensity without BKG subtraction= Area*MeanIntensity} If PIcalibrated=1 then begin if width=0 then begin y:=rY[k]; x:=rX[k]; PiFunction; rMax[k]:=Pi; rMin[k]:=0; end; if width<>0 then begin x:=rX[k]+left; y:=rY[k]+top; PiFunction; rMax[k]:=Pi; rMin[k]:=0; end; end; ShowMessage('Particle',k,y,MW); {Cross marks in the MW window and draws the MW values} SetLineWidth(1); MoveTo(rX[k]-2,rY[k]); LineTo(rX[k]+2,rY[k]); MoveTo(rX[k],rY[k]-2); LineTo(rX[k],rY[k]+2); MoveTo(rX[k]-20,rY[k]+10); SetForeGroundColor(255); DrawText(rUser1[k]:6:0); end; {end for} SetFont('Monaco'); SetFontSize(9); ShowMessage(lower,upper); ShowMessage('Particle analysis thresholds','\Upper threshold: ',upper,'\Lower threshold: ',lower,'\Change with LUT tool if required'); ShowResults; end; Macro 'Single band intensity measurement [6]'; var width,height,left,top:integer; begin InvertY(0); GetRoi(left,top,width,height); if width=0 then PutMessage('This macro requires a selection'); SetUser1Label('MW'); SetUser2Label('Int.'); SetOptions( 'Area,Mean,X-Y Center,User1,User2'); if PiCalibrated=1 then SetOptions( 'Area,Mean,X-Y Center,Max,User1,User2'); Measure; y:=rY[rCount]; x:=rX[rCount]; if MWcalibrated=1 then MWFunction; if MWcalibrated=0 then rUser1[rCount]:=0; if MWcalibrated=1 then rUser1[rCount]:=MW; rUser2[rCount]:=rArea[rCount]*rMean[rCount]; If PiCalibrated=1 then begin y:=rY[rCount]; x:=rX[rCount]; PiFunction; rMax[rCount]:=Pi; rMin[rCount]:=0; end; ShowResults; ShowMessage('!! No background correction !!','\ Be sure to subtract the mean BKG value from the image by subtraction','\ (Process Arithmetic menu)','\Otherwise the basic grey level','\is included in the measurement result','\\Intensity=',rUser2[rCount],'\MW= ',MW:6:0,'\pI= ',Pi:2:2); end; Macro'Create particle mask {for band detection} [0]'; var max,maxi,left,top,width,height,i,pic:integer; path:string; begin RequiresVersion(1.6); pic:=PicNumber; Duplicate(pic); SetPicName('Mask'); ReduceNoise; Smooth; {ball radius 35 may be varied according to band width} SubtractBackground('2D Rolling Ball(faster)',Ball); ShowMessage('Please locate the Hat(13x13) kernel'); path:=GetPath('startup'); {requires version 1.6 if you replace the upper line with the correct path like path:='Macintosh HD:NIH-Image:Kernels:Hat(13x13)' you may also use this macro with earlier versions} path:=concat(path,'Kernels:Hat(13x13)'); Convolve(path); SetDensitySlice(255,255); SelectAll; GetRoi(left,top,width,height); GetHistogramm(left+13,top+13,width-13,height-13); KillRoi; max:=0; maxi:=0; for i:=1 to 255 do begin if Histogram[i]>max then begin max:=Histogram[i]; maxi:=i; end; end; SetDensitySlice(maxi+5,255); ShowMessage('Bands should be visible in red','\ Change the settings with the LUT Tool if required'); Calibrate('uncalibrated'); SetScale(0,'pixels'); end; Macro 'Redirect measurements [7]'; var im,nm,upper,lower,left,top,width,height,i:integer; begin if nPics<>2 then begin putMessage('Only 2 Pictures should bo open'); exit; end; if Calibrated then begin PutMessage('Both images must have the same density or spatial calibration for parallel image analysis. To stop press the option key, to continue press the Shift key'); repeat ShowMessage('Press Option to stop','\Press Shift to continue'); if KeyDown('option') then exit; until Keydown('Shift'); end; ShowMessage('Reset measurements checkbox','\Analyze Particles must be off'); InvertY(0); SetUser1Label('MW'); SetUser2Label('Int.'); SetOptions( 'Area,Mean,X-Y Center,User1,User2'); If PiCalibrated=1 then SetOptions('X-Y Center,Max,User1,User2'); nm:=rCount; If ((MWcalibrated=1) OR (PiCalibrated=1)) then begin if rMean[2]> rMean[1] then nm:=rMean[2]; if rMean[2]<= rMean[1] then nm:=rMean[1]; end; SetCounter(nm); SetDensitySlice(255,255); GetThresholds(upper,lower); SetDensitySlice(upper,lower); Redirect(1); AnalyzeParticles('label,outline,include'); Redirect(0); GetRoi(left,top,width,height); for im:=nm+1 to rCount do begin x:=rX[im]; if width=0 then y:=rY[im]; if width<>0 then y:=rY[im]+top; {Partikelfront/Zentrumkorrektur} if Lauffront=1 then y:=y+rMinor[im]/2-1; if MWcalibrated=1 then MWFunction; if MWcalibrated=1 then rUser1[im]:=MW; if MWcalibrated=0 then rUser1[im]:=0; rUser2[im]:=rArea[im]*rMean[im]; If PIcalibrated=1 then begin if width=0 then begin y:=rY[im]; x:=rX[im]; PiFunction; rMax[im]:=Pi; rMin[im]:=0; end; if width<>0 then begin x:=rX[im]+left; y:=rY[im]+top; PiFunction; rMax[im]:=Pi; rMin[im]:=0; end; end; UpdateResults; end;{for im loop} If rUser1[rCount]=1 then PutMessage('The MW calibration was cleared by the Reset measurement counter optional setting in the Analyze Particles submenu. Disable the reset measurements counter checkbox'); SetDensitySlice(0,0); Duplicate(WindowTitle); SetPicName('MW'); SetBackgroundColor(0); SelectAll; Clear; SetForeGroundColor(255); {Draws the crosses and MWs in the MW window} for im:=nm+1 to rCount do begin SetLineWidth(1); MoveTo(rX[im]-2,rY[im]); LineTo(rX[im]+2,rY[im]); MoveTo(rX[im],rY[im]-2); LineTo(rX[im],rY[im]+2); SetForeGroundcolor(255); DrawText(rUser1[im]:6:0); end; ShowResults; end; Macro 'Single lane analysis {% of total} [8]'; var Pixsum,counter,upper,lower,k,left,top,width,height:integer; Wert:real; begin SetScale(0,'pixels'); SetUser1Label('MW'); SetUser2Label(' % '); SetOptions( 'Area,Mean,X-Y Center,User1,User2'); If PiCalibrated=1 then SetOptions('X-Y Center,Max,User1,User2'); SetFont('Monaco'); SetFontSize(8); InvertY(0); counter:=rCount+1; GetRoi(left,top,width,height); if width=0 then begin PutMessage('This macro requires a selection. Please select a lane first'); exit; end; Copy; SetNewSize(width,height); MakeNewWindow('Particles'); Paste; SetDensitySlice(255,255); GetThresholds(upper,lower); SelectAll; AnalyzeParticles('label,outline,include'); if MWcalibrated=1 then begin Duplicate(WindowTitle); SetPicName('MW'); SetBackgroundColor(0); SelectAll; Clear; SetForeGroundColor(255); end; {For all found particles calculate the MW and intensity} Pixsum:=0; for k:=counter to rCount do begin x:=rX[k]; if width=0 then y:=rY[k]; {Particle intensity without BKG subtraction= Area*MeanIntensity} rUser2[k]:=rMean[k]*rArea[k]; rAngle[k]:=rUser2[k]; ShowMessage('Partikel',k,y,MW); Pixsum:=Pixsum+rUser2[k]; if MWcalibrated<>0 then begin if width<>0 then begin y:=rY[k]+top; {If a region was active,Y-coordinates have to be corrected} x:=rX[k]+left; end; {Partikelfront/Zentrumkorrektur} if Lauffront=1 then y:=y+rMinor[k]/2-1; MWFunction; rUser1[k]:=MW; MoveTo(rX[k]-20,rY[k]); SetForeGroundcolor(255); DrawText(MW:6:0); end; if MWcalibrated=0 then rUser1[k]:=0; If PIcalibrated=1 then begin if width=0 then begin y:=rY[k]; x:=rX[k]; PiFunction; rMax[k]:=Pi; rMin[k]:=0; end; if width<>0 then begin x:=rX[k]+left; y:=rY[k]+top; PiFunction; rMax[k]:=Pi; rMin[k]:=0; end; end; end; {end for k} {% calculation} UpdateResults; For k:=counter to rCount do begin rUser2[k]:=rUser2[k]*100/Pixsum; end; SetFont('Monaco'); SetFontSize(9); ShowMessage('Particle analysis thresholds','\Upper threshold: ',upper,'\Lower threshold: ',lower,'\Change with LUT tool if required'); UpdateResults; ShowResults; end; Macro 'Redirected lane analysis {%} [F9]'; var Pixsum,counter,upper,lower,k,left,top,width,height:integer; Wert:real; begin SetScale(0,'pixels'); SetUser1Label('MW'); SetUser2Label(' % '); SetOptions( 'Area,Mean,X-Y Center,User1,User2'); If PiCalibrated=1 then SetOptions('X-Y Center,Max,User1,User2'); SetFont('Monaco'); SetFontSize(8); InvertY(0); counter:=rCount+1; GetRoi(left,top,width,height); if width=0 then begin PutMessage('This macro requires a selection. Please select a lane first'); exit; end; SetDensitySlice(255,255); GetThresholds(upper,lower); Redirect(1); {Measures the intensity in the original unmasked image} AnalyzeParticles('label,outline,include'); Redirect(0); {For all found particles calculates the MW and intensity} Pixsum:=0; for k:=counter to rCount do begin x:=rX[k]; {Particle intensity without BKG subtraction= Area*MeanIntensity} rUser2[k]:=rMean[k]*rArea[k]; rAngle[k]:=rUser2[k]; Pixsum:=Pixsum+rUser2[k]; if MWcalibrated<>0 then begin y:=rY[k]; x:=rX[k]; {Partikelfront/Zentrumkorrektur} if Lauffront=1 then y:=y+rMinor[k]/2-1; MWFunction; rUser1[k]:=MW; end; if MWcalibrated=0 then rUser1[k]:=0; If PIcalibrated=1 then begin x:=rX[k]; y:=rY[k]; PiFunction; rMax[k]:=Pi; rMin[k]:=0; end; end; {end for k} {% calculation} UpdateResults; SetForeGroundcolor(255); For k:=counter to rCount do begin rUser2[k]:=rUser2[k]*100/Pixsum; end; SetFont('Monaco'); SetFontSize(9); ShowMessage('Particle analysis thresholds','\Upper threshold: ',upper,'\Lower threshold: ',lower,'\Change with LUT tool if required'); UpdateResults; ShowResults; end; Macro 'Band comparison {first=100%} reset first! [9]'; var width,height,left,top,n,mean,min,max,mode:integer; begin if rCount=1 then ShowResults; if rCount<>1 then UpdateResults; SetScale(0,'pixels'); SetUser1Label('Intensity'); SetUser2Label('%'); SetOptions('Area,Mean,X-Y Center,User1,rUser2'); GetRoi(left,top,width,height); if width=0 then begin PutMessage('This macro requires a selection'); exit; end; Measure; GetResults(n,mean,mode,min,max); rUser2[1]:=100; MWcalibrated:=0; rUser1[rCount]:=rArea[rCount]*rMean[rCount]; rUser2[rCount]:=rUser1[rCount]/rUser1[1]*100; ShowMessage('!! No background correction !!','\ Be sure to subtract the mean BKG value from the image by subtraction','\ (Process Arithmetic menu)','\Otherwise the basic grey level','\is included in the measurement result','\ Modal Intensity= ',cValue(mode)); if rCount=1 then ShowResults; if rCount<>1 then UpdateResults; end; macro'(-' begin {Separating Menu bar line} end; Macro 'Clear measurement list [F5]'; begin if (rMean[1]>= rMean[2]) then SetCounter(rMean[1]); if (rMean[1]< rMean[2]) then SetCounter(rMean[2]); {Resets the measurement counter but does not clear the MW calibration data} end; Macro 'Reset to clear all data'; begin ResetCounter; eraseflags; end; Macro 'Remove spatial and density calibration'; begin Calibrate('uncalibrated'); SetScale(0,'pixels'); end; macro'(-'; begin {Separating Menu bar line} end; Macro 'Restore Region [F6]'; begin RestoreRoi; end; Macro 'Expand region [+]'; begin InsetRoi(-1); end; macro 'Shrink region [-]'; begin InsetRoi(1); end; macro 'UserLabels to default settings'; begin SetUser1Label('User1'); SetUser2Label('User2'); {Restores the old settings in the Result window and clears MW,Int.% labels} end;