macro 'Make Movie to DiskÉ'; { Captures images at a specified rate and saves them to disk. Select an area of interest within the Camera window before starting. Abort at any time by pressing the mouse button. } var nFrames,n,Left,Top,Width,Height:integer; interval,EndTicks,secs:integer; FirstTime:boolean; begin GetRoi(Left,Top,Width,Height); if width=0 then begin PutMessage('First select the area of interest in the Camera window.'); exit; end; nFrames:=GetNumber('Number of Frames?',10); secs:=GetNumber ('Interval Between Frames (seconds)?',60.0); interval:=round(secs*60); FirstTime:=true; for n:=1 to nFrames do begin StopCapturing; beep; MakeRoi(Left,Top,Width,Height); SaveAs('Frame ',n); if FirstTime then begin EndTicks:=TickCount+interval; FirstTime:=false; end; if button then begin StopCapturing; exit; end; StartCapturing; while TickCount < EndTicks do begin secs:=(EndTicks - TickCount) div 60; ShowMessage(n:1, '/', nFrames,' ', secs:4) end; EndTicks:=EndTicks+interval; end; StopCapturing; end; macro 'Capture Averaged to StackÉ'; var x,y,i,s,f,t,width,height:integer; camera, stack, avg, nFrames:integer; begin nFrames:=GetNumber('Number of frames to capture:', 10); SelectWindow('Camera'); camera:=PidNumber; GetRoi(x,y,width,height); if width=0 then begin PutMessage('Rectangular selection required.'); exit; end; SetNewSize(width,height); MakeNewStack('Stack'); stack:=PidNumber; s:=TickCount; for i:= 1 to nFrames do begin ChoosePic(Camera); MakeRoi(x,y,width,height); AverageFrames; RestoreRoi; Copy; ChoosePic(stack); if i>1 then AddSlice; Paste; end; f:=TickCount; KillRoi; SelectSlice(1); t:=(f-s)/60; ShowMessage('Time = ', t:1:2, ' seconds'); exit; AverageSlices; avg:=PidNumber; SelectPic(stack); Dispose; SelectPic(avg); end; procedure PlotFrameIntervals(nFrames: integer); var xmin,xmax,ymin,ymax,i,xscale,yscale,yscale2:real; width,height,margin,pwidth,pheight:integer; x,y,pbottom,yinc:integer; minInterval,maxInterval,offset:real; interval,reqInterval,avgInterval,ElapsedTime:real; TotalTime:real; begin RequiresVersion(1.58); SaveState; margin:=40; width:=500; height:=300; ymin:=999999; ymax:=-999999; ElapsedTime := PlotData[nFrames]; reqInterval := PlotData[nFrames+1]; avgInterval := ElapsedTime / (nFrames -1); TotalTime := avgInterval * nFrames; for i:=1 to nFrames -1 do begin interval := PlotData[i+1]-PlotData[i]; if intervalymax then ymax:=interval; end; minInterval:=ymin; maxInterval:=ymax; ymin:=0; xmin:=1; xmax:=nFrames-1; SetNewSize(width,height); SetForeground(255); SetBackground(0); MakeNewWindow('Frame Intervals (seconds)'); pwidth:=width-margin-130; pheight:=height-2*margin; pbottom:=margin+pheight; xscale:=pwidth/xmax; yscale:=pheight/ymax; yscale2:=pheight/(PlotData[nFrames]); SetForeground(255); SetBackground(0); SetLineWidth(1); for i:=2 to nFrames do begin interval := PlotData[i]-PlotData[i-1]; x:=margin+(i-1)*xscale; y:=pbottom-interval*yscale; MoveTo(x, pBottom); LineTo(x,y); MoveTo(margin+(i-2)*xscale, pBottom-(PlotData[i-1])*yscale2); LineTo(margin+(i-1)*xscale, pBottom-(PlotData[i])*yscale2); end; KillRoi; MoveTo(margin, margin); LineTo(margin, margin+pheight); LineTo(margin+pwidth, margin+pheight); SetFont('Geneva'); SetFontSize(9); SetText('Right Justified'); MoveTo(margin-2, margin+pheight-5); writeln(ymin:1:3); MoveTo(margin-2, margin); writeln(ymax:1:3); SetText('Left Justified'); x := margin+pwidth+10; y := margin; yinc := 12; MoveTo(x, y); writeln('frames=', nFrames:1); y := y+yinc; MoveTo(x, y); writeln('expected time=', nFrames*reqInterval:1:4); y := y+yinc; MoveTo(x, y); writeln('actual time=', TotalTime:1:4); y := y+yinc; MoveTo(x, y); writeln('req. interval=', reqInterval:1:4); y := y+yinc; MoveTo(x, y); writeln('avg interval=', avgInterval:1:4); y := y+yinc; MoveTo(x, y); writeln('min interval=', minInterval:1:4); y := y+yinc; MoveTo(x, y); writeln('max interval=', maxInterval:1:4); y := y+yinc; MoveTo(x, y); if reqInterval <> 0.0 then writeln('expected rate=', 1/reqInterval:1:3,' fps'); y := y+yinc; MoveTo(x, y); writeln('actual rate=', (nFrames)/TotalTime:1:3,' fps'); RestoreState; end; macro 'Make Movie and Plot Intervals [M]'; var i, nFrames, x, y, w, h: integer; avgInterval: real; begin GetRoi(x, y, w, h); if w = 0 then begin PutMessage('Selection Required.'); exit; end; MakeMovie('dialog, time-stamp', -1, -1); nFrames := PlotData[0]; PlotFrameIntervals(nFrames); end; Macro 'Frame Rate vs. Frame Size'; var n, i, width, height,w,h:integer; TextWidth, TextHeight: integer; avgFrameInterval: real; begin RequiresVersion(1.61); n := 50; TextWidth := 150; TextHeight := 400; StartCapturing; GetPicSize(width, height); SaveState; SetFont('Monaco'); SetFontSize(9); NewTextWindow('Rate vs. Size', TextWidth, TextHeight); MoveWindow(get('ScreenWidth') - TextWidth - 10, 50); for i := 1 to n do begin SelectWindow('Camera'); w := round(width*(i/n)); h := round(height*(i/n)); w := w - (w mod 4); h := h - (h mod 4); MakeRoi(0, 0, w, h); MakeMovie('blind', 10, 0); avgFrameInterval := GetSliceSpacing; Dispose; SelectWindow('Rate vs. Size'); writeln(i:3, avgFrameInterval:6:3, ' ', w:1:0, 'x', h:1:0); end; RestoreState; end; macro 'Projection Example'; begin SetProjection('Initial Angle', 0); SetProjection('Total Rotation', 360); SetProjection('Rotation Increment', 30); SetDensitySlice(0, 254); {sets transparency bounds} SetProjection('Surface Opacity', 50); SetProjection('Surface Depth-Cueing', 50); SetProjection('Interior Depth-Cueing', 50); SetProjection('Save Projections', false); SetProjection('Minimize Size', true); SetProjection('Y-Axis'); SetProjection('Brightest Point'); Project; {Dialog is not displayed} end. macro '(-' begin end; macro 'Average of Stack...'; var i, j, nFrames, srcStack, dstStack: integer; n, stack, width, height: integer; begin RequiresVersion(1.62); if nSlices=0 then exit('Stack required.'); SaveState; GetPicSize(width, height); nFrames := getNumber('Number of Frames to Average:', 10, 0); n := nSlices div nFrames; if n = 0 then exit; srcStack := PidNumber; SetNewSize(width,height); MakeNewStack(WindowTitle, ' (Averaged)'); dstStack := PidNumber; ChoosePic(srcStack); for i := 1 to n do begin SelectSlice(1); AverageSlices(1, nFrames); SelectAll; Copy; Dispose; ChoosePic(dstStack); if i>1 then AddSlice; Paste; ChoosePic(srcStack); for j := 1 to nFrames do begin SelectSlice(1); DeleteSlice; end; end; SelectPic(srcStack); dispose; RestoreState; end; macro 'Running Average of Stack...'; var i, nFrames: integer; begin RequiresVersion(1.62); if nSlices=0 then exit('Stack required.'); nFrames := getNumber('Number of Frames to Average:', 10, 0); for i := 1 to nSlices - nFrames + 1 do begin SelectSlice(i); AverageSlices(i, nFrames); SelectAll; Copy; Dispose; Paste; end; end; procedure DeInterlace(OddSlice: boolean); { If OddSlice is true, each even line is replaced by the adjacent odd line, otherwise each odd line is replaced by the adjacent even line. } var i,width,height,row1,row2:integer; begin GetPicSize(width,height); if OddSlice then begin i := 1; while i < (height - 2) do begin GetRow(0, i, width); PutRow(0, i - 1, width); i := i + 2; end; end else begin i := 0; while i < (height - 1) do begin GetRow(0, i, width); PutRow(0, i + 1, width); i := i + 2; end; end; end; macro 'De-interlace Stack'; {Converts 30fps movies to 60 fields per second.} var i, width, height:integer; begin RequiresVersion(1.61); if nSlices=0 then exit('Stack required.'); i:=nSlices; GetPicSize(width,height); if (i * width * height) > get('freemem') then exit('There is not enough free RAM to de-interlace this stack.'); repeat SelectSlice(i); SelectAll; Copy; AddSlice; Paste; i:=i - 1; until i = 0; KillRoi; for i := 1 to nSlices do begin SelectSlice(i); DeInterlace(odd(i)); end; end; macro 'Add Timestamps to Stack...'; {By Steve Potter (spotter@gg.caltech.edu). Adds a timestamp to each frame of a stack of time-lapse images.} var i,j,k,interval, frameNumber, hours, minutes, seconds, xpos, ypos, colon1pos, colon2pos, ones, tens: integer; militaryTime, printSeconds: boolean; StartTime, name, textStamp,tempStr, hourStr, minStr, secStr, AMPMstr, timeStr, oneStr, tenStr: string; begin if nSlices=0 then begin PutMessage('Stack required.'); exit end; ShowMessage('Time Stamps:\\Make sure you have already selected the desired font, fontsize, and drawcolor.\Use AM or PM if 12-h clock is desired, e.g. "3:07 PM". Use two colons if you wish to display seconds, e.g. "3:07:22 PM".\The point you click will be the upper-left corner of the time-stamp.'); interval:=GetNumber('Time interval (seconds): ',300); StartTime:=GetString('Enter the start time. ','0:00:00'); MilitaryTime:=true; AMPMstr:=''; if (pos('AM',StartTime)<>0) then MilitaryTime:=false; if (pos('AM',StartTime)<>0) then AMPMstr:=' AM'; if (pos('PM',StartTime)<>0) then MilitaryTime:=false; if (pos('PM',StartTime)<>0) then AMPMstr:=' PM'; hourStr:=StartTime; colon1pos:=pos(':', StartTime); Delete(hourStr,colon1pos, 10); {get rid of everything but the hours} hours:=StringToNum(hourStr); minStr:=StartTime; Delete(minStr, 1, colon1pos); {remove the hours} colon2pos:=pos(':',minStr); if (colon2pos<>0) then printSeconds:=true else printSeconds:=false; Delete(minStr,3, 7); {get rid of everything but the minutes} minutes:=StringToNum(minStr); seconds:=0; If printSeconds then begin secStr:=StartTime; Delete(secStr,1, colon2pos); Delete(secStr,3, 5); {get rid of all but the seconds} seconds:=StringToNum(secStr); end; frameNumber:=GetNumber('Enter the number of the first frame:',1); name:=GetString('Enter your name or initials: '); textStamp:=GetString('Date, experimental conditions, etc.: ',''); PutMessage('Click at desired text location...'); SelectSlice(1); repeat GetMouse(xpos,ypos); until Button; For i:=1 to nSlices do begin SelectSlice(i); MoveTo(xpos,ypos); ones:=minutes mod 10; oneStr:=chr(ones+48); {48 is the ASCII value of the character 0} tens:=minutes div 10; tenStr:=chr(tens+48); minStr:=concat(tenStr, oneStr); {it is a shame I cant find a num-2-string function!} if printSeconds then begin ones:=seconds mod 10; oneStr:=chr(ones+48); {48 is the ASCII value of the character 0} tens:=seconds div 10; tenStr:=chr(tens+48); secStr:=concat(tenStr, oneStr); end; timeStr:=concat(hours,':',minStr); if printSeconds then timeStr:=concat(timeStr, ':',secStr); Writeln(textStamp,' ',name); Write(frameNumber, ' ',timeStr, AMPMstr); frameNumber:=frameNumber+1; seconds:=seconds+interval; minutes:=minutes+(seconds div 60); seconds:=seconds mod 60; hours:=hours +(minutes div 60); minutes:=minutes mod 60; if militaryTime then if (hours>24) then hours:=hours-24; if ((not(militaryTime)) AND (hours>11)) then begin if (AMPMstr=' AM') then AMPMstr:= ' PM'; if (AMPMstr=' PM') then AMPMstr:= ' AM'; end; if ((not(militaryTime)) AND (hours>12)) then hours:=hours-12; end; end; {Time Stamps...}