{version 2.3w, a macro suite for use with NIH Image. some macros (FixLUT, CropAndScale-Fast, and Rotate) and other code (CheckForStack and CheckForSelection) scavenged and adapted from those supplied with NIH Image, the rest written by kurt i. anderson} var {Biorad file Globals} textfile:string; fileselected:boolean; {3D Stack Viewing Globals} nframes:integer; nstacks:integer; actualstack:integer; actualframe:integer; framesep,stacksep:integer; {Stack Editing Globals} source,target:string; sourcePid, targetPid: real; from,til,sep:integer; left,top,width,height:integer; targetfrom:integer; od:boolean; {ROI Globals} RoiLeft,RoiTop,roiwidth,roiheight:integer; roitype:integer; rtypestring:string; {Reslice Pair Globals} pairthere:boolean; pairPIDone:real; pairPIDtwo:real; procedure CheckForStack; begin if nPics=0 then begin PutMessage('This macro requires a stack.'); exit; end; if nSlices=0 then begin PutMessage('This window is not a stack.'); exit; end; end; procedure CheckForSelection; var RoiLeft,RoiTop,RoiWidth,RoiHeight,x1,y1,x2,y2,LineWidth:integer; begin GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight); GetLine(x1,y1,x2,y2,LineWidth); if (RoiWidth=0) or (x1>=0) then begin PutMessage('Please make a rectangular selection.'); exit; end; end; procedure LoadStack; var width,height:integer; begin CheckForStack; GetPicSize(width,height); nstacks:=GetNumber('how many levels?',2); nframes:=nSlices/nstacks; if trunc(nSlices/nstacks)<>(nSlices/nStacks) then begin PutMessage('This stack doesnt divide evenly by ',nstacks,' levels'); exit; end; SelectSlice(1); actualstack:=1; actualframe:=1; if framesep=0 then framesep:=1; if stacksep=0 then stacksep:=1; end; procedure CheckLoad; begin if nSlices<>nframes*nstacks then LoadStack; {begin PutMessage('not the right stack for current settings'); exit; end;} end; procedure CropAndScale(fast:boolean; angle:real); var i,OldStack,NewStack:integer; RoiLeft,RoiTop,RoiWidth,RoiHeight:integer; N,NewWidth:integer; ScaleFactor:real; OneToOne:boolean; begin SaveState; OldStack:=PicNumber; N:=nSlices; ScaleFactor:=GetNumber('Scale factor(0.05..25):',1.0); OneToOne:=ScaleFactor=1.0; GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight); NewWidth:=round(RoiWidth*ScaleFactor); if odd(NewWidth) then begin NewWidth:=NewWidth-1; ScaleFactor:=NewWidth/RoiWidth; end; SetNewSize(RoiWidth*ScaleFactor,RoiHeight*ScaleFactor); MakeNewStack('Stack'); NewStack:=PicNumber; if not OneToOne then begin if fast then SetScaling('Nearest; Create New Window') else SetScaling('Bilinear; Create New Window'); end; SelectPic(OldStack); for i:= 1 to N do begin SelectSlice(1); if OneToOne and (angle=0.0) then Duplicate('Temp') else ScaleAndRotate(ScaleFactor,ScaleFactor,angle); SelectAll; Copy; SelectPic(NewStack); if i<>1 then AddSlice; Paste; SelectPic(nPics); Dispose; {Temp} SelectPic(OldStack); DeleteSlice; end; Dispose; {OldStack} RestoreState; end; Macro 'About Leapstack [A]'; begin NewTextWindow('About Leapstack'); Writeln('about Leapstack 991218'); Writeln('this is a macro for manipulating and viewing multiple stacks, such as a time course of Z-sections or a multi channel movie consisting of a phase contrast and two fluorescent channels.'); Writeln; Writeln('1. open all of the channels you wish to view.'); Writeln('2. use *Make Meta-Stack [=]* to combine them into one big stack.'); Writeln('3. save the final product.'); Writeln('4. navigate through the stack using keystroke commands, which are designed for use with a keypad.'); Writeln; Writeln('after opening an old meta-stack, use *Load Meta-Stack [0]* and enter the number of levels or channels.'); Writeln('if memory is tight, make a new meta-stack [N] with enough frames for all of the levels/channels, then open, paste [P], and close the individual channels consecutively.'); Writeln('use *Set Step* to step through the stack by more than one frame at a time.'); Writeln('kurt i. anderson'); Writeln('.'); Writeln('Note: some of the code has been borrowed, and/or modified from the stack macro suite included with NIH Image.'); Writeln('Long Live NIH Image!'); Writeln(';-)'); end; Macro '(-'; begin end; Macro 'Make Meta-Stack [=]'; var width,height,i,j:integer; begin CheckForStack; GetPicSize(width,height); nframes:=nSlices; nstacks:=nPics; SetNewSize(width,height); MakeNewStack('target'); for i:=1 to ((nstacks)*nframes-1) do AddSlice; for j:=1 to (nstacks) do begin ChoosePic(j); SelectAll; for i:=1 to nframes do begin ChoosePic(j); ChooseSlice(i); Copy; ChoosePic(nPics); ChooseSlice(((j-1)*nframes)+i); Paste; end; end; SelectSlice(1); KillROI; actualstack:=1; actualframe:=1; if framesep=0 then framesep:=1; if stacksep=0 then stacksep:=1; end; Macro 'Load Meta-Stack [0]'; var width,height:integer; begin LoadStack; end; Macro 'Set X Step [X]'; begin framesep:=GetNumber('step laterally by n frames:',framesep); end; Macro 'Set Y Step [Y]'; begin stacksep:=GetNumber('step vertically by n stacks:',stacksep); end; Macro 'Play Sideways [*]'; var i,j:integer; delay:real; begin CheckLoad; actualstack:=GetNumber('animate which level?',actualstack); delay:=GetNumber('time delay?',delay); for j:=1 to 100 do begin for i:=1 to trunc(nframes/framesep) do begin SelectSlice((actualstack-1)*nframes+(i*framesep)); Wait(delay); end; end; end; Macro 'Step Forward [6]'; begin CheckLoad; if actualframe+framesep<=nframes then actualframe:=actualframe+framesep else actualframe:=framesep-(nframes-actualframe); SelectSlice((actualstack-1)*nframes+actualframe); ShowMessage('l-r: ',actualframe,'\u-d: 'actualstack); end; Macro 'Step Back [4]'; begin CheckLoad; if actualframe-framesep>=1 then actualframe:=actualframe-framesep else actualframe:=nframes-(framesep-actualframe); SelectSlice((actualstack-1)*nframes+actualframe); ShowMessage('l-r: ',actualframe,'\u-d: 'actualstack); end; Macro 'Step Up [8]'; begin CheckLoad; if actualstack+stacksep<=nstacks then actualstack:=actualstack+stacksep else actualstack:=stacksep-(nstacks-actualstack); SelectSlice((actualstack-1)*nframes+actualframe); ShowMessage('l-r: ',actualframe,'\u-d: 'actualstack); end; Macro 'Step Down [2]'; begin CheckLoad; if actualstack-stacksep>=1 then actualstack:=actualstack-stacksep else actualstack:=nstacks-(stacksep-actualstack); SelectSlice((actualstack-1)*nframes+actualframe); ShowMessage('l-r: ',actualframe,'\u-d: 'actualstack); end; Macro 'First of Level [1]'; begin CheckLoad; actualframe:=1; SelectSlice((actualstack-1)*nframes+1); ShowMessage('l-r: ',actualframe,'\u-d: 'actualstack); end; Macro 'Last of Level [3]'; begin CheckLoad; actualframe:=(nframes); SelectSlice(actualstack*nframes); ShowMessage('l-r: ',actualframe,'\u-d: 'actualstack); end; Macro 'First Slice [ ]'; begin CheckForStack; SelectSlice(1); end; Macro 'Last Slice [M]'; begin CheckForStack; SelectSlice(nSlices); end; Macro '(-'; begin end; Macro 'New Stack [N]'; var string1:string; i,slices:integer; begin GetPicSize(width,height); sourcepid:=PidNumber; string1:=GetString('new stack name','target'); SetBackgroundColor(0); slices:=GetNumber('slices', 2*nSlices); SetNewSize(width,height); MakeNewStack(string1); MoveWindow(350,256); for i:=1 to (slices-1) do AddSlice; SelectPic(sourcepid); end; Macro 'Paste Stack [P]'; var i,j,sep:integer; begin od:= not od; SelectAll; source:=GetString('source stack',WindowTitle); if 0<>pos('01.PIC',WindowTitle) then targetfrom:=0*nSlices+1; if 0<>pos('02.PIC',WindowTitle) then targetfrom:=1*nSlices+1; if 0<>pos('03.PIC',WindowTitle) then targetfrom:=2*nSlices+1; SelectWindow(source); sourcePid:=PidNumber; from:=1; til:=nSlices; sep:=1; target:=GetString('target stack','target'); SelectWindow(target); targetPid:=PidNumber; left:=0; top:=0; if od then targetfrom:=GetNumber('start with target slice number', 1) else targetfrom:=GetNumber('start with target slice number',targetfrom); if targetfrom=0 then targetfrom:=1; ChoosePic(sourcePid); ChooseSlice(from); CheckForSelection; GetROI(roileft,roitop, width, height); Copy; ChoosePic(targetPid); ChooseSlice(targetfrom); MakeROI(left, top, width, height); Paste; i:=from+sep; j:=targetfrom+1; repeat ChoosePic(sourcePid); ChooseSlice(i); Copy; ChoosePic(targetPid); ChooseSlice(j); Paste; j:=j+1; i:=i+sep; until i>til; end; Macro 'DeleteSlices [D]'; var i,ndelete:integer; first:integer; begin CheckForStack; first:=GetNumber('where to start',first); ndelete:=GetNumber('how many slices to delete',ndelete); if ndelete=0 then ndelete:=(nSlices-first+1); SelectSlice(first+ndelete-1); for i:=1 to ndelete do DeleteSlice; end; end; macro 'Fix LUT [L]'; var i,slices:integer; begin CheckForStack; source:=WindowTitle; slices:=nSlices; Duplicate('Temp'); for i:= 1 to slices do begin SelectWindow(source); SelectSlice(i); ApplyLut; SelectPic(nPics); if i<>slices then PropagateLut; end; SelectPic(nPics); Dispose; end; macro 'Crop and Scale-FastÉ[F6]'; begin CheckForStack; CheckForSelection; CropAndScale(true, 0); end; macro 'RotateÉ'; var angle:real; begin CheckForStack; CheckForSelection; angle:=GetNumber('Angle(-180.0¡..180.0¡):',45.0); CropAndScale(false, angle); end; Macro '(-'; begin end; Macro 'Make ROI [R]'; begin left:=GetNumber('left corner',left); top:=GetNumber('top corner',top); width:=GetNumber('width', width); height:=GetNumber('height', height); MakeRoi(left,top,width,height); end; Macro 'Make Oval ROI [O]'; begin left:=GetNumber('left corner',left); top:=GetNumber('top corner',top); width:=GetNumber('width', width); height:=GetNumber('height', height); MakeOvalRoi(left,top,width,height); end; Macro 'Get ROI from screen [G]'; begin GetRoi(left,top,width,height); roitype:=Get('RoiType'); if roitype=1 then rtypestring:='rectangle'; if roitype=2 then rtypestring:='oval'; if (roitype>=3) and (roitype<6) then rtypestring:='sorry dude \i dont do funny shapes'; if roitype=6 then rtypestring:='sorry dude \i cant do straight lines'; if roitype>=7 then rtypestring:='sorry dude \i dont do funny shapes'; ShowMessage('left: ',left,'\top: ',top,'\width: ',width,'\height:',height,'\',rtypestring); end; Macro 'ROI from Memory [H]'; begin if roitype=1 then MakeRoi(left,top,width,height); if roitype=2 then MakeOvalRoi(left,top,width,height); end; Macro '(-'; begin end; Macro 'Last Window [F14]'; begin if PicNumber>1 then SelectPic(PicNumber-1) else SelectPic(nPics); end; Macro 'Next Window [F15]'; begin if nPics>PicNumber then SelectPic(PicNumber+1) else SelectPic(1); end; Macro '(-'; begin end; Macro 'Reslice Stack [C]'; var i,width,height,space: integer; source: string; sourcePID,targetPID:real; begin CheckForStack; source:=GetString('source',WindowTitle); space:=GetNumber('slice spacing?',space); SetSliceSpacing(space); SelectWindow(source); sourcePid:=PidNumber; GetPicSize(width,height); SetNewSize(height,nSlices*space); MakeNewStack('target'); SelectWindow('target'); targetPID:=PIDNumber; for i:=0 to (width-1) do begin ChoosePic(sourcePID); MakeLineROI(i,0,i,height); Reslice; SelectAll; Copy; Dispose; ChoosePic(targetPID); if i<>0 then AddSlice; Paste; end; end; Macro 'Set Reslice Pair [U]'; var one,two:string; begin one:=GetString('step through stack',WindowTitle); SelectWindow(one); pairPIDone:=PIDNumber; NextWindow; two:=GetSTring('reference image',WindowTitle); SelectWindow(two); pairPIDtwo:=PIDNumber; pairthere:=true; end; Macro 'Reslice Pair UP [I]'; var i,width,height:integer; begin if pairthere then begin SelectPic(pairPIDone); if (SliceNumber+1)<=nSlices then ChooseSlice(SliceNumber+1) else ChooseSlice(1); i:=SliceNumber; SelectPic(pairPIDtwo); GetPicSize(width,height); MakeLineRoi(i-1,0,i-1,height); end; end; Macro 'Reslice Pair DOWN [J]'; var i,width,height:integer; begin if pairthere then begin SelectPic(pairPIDone); if (SliceNumber-1)>=1 then ChooseSlice(SliceNumber-1) else ChooseSlice(nSlices); i:=SliceNumber; SelectPic(pairPIDtwo); GetPicSize(width,height); MakeLineRoi(i-1,0,i-1,height); end; end;