#pragma rtGlobals=1 // Use modern global access method. // JFT - 8-24-12 // Fixed annotation on MSD plot in CreateTirfGraphs() // Had previously forgotten the factor of 2 in calculating the diffusion constant // // JFT - 7-30-12 // Edited MSD and restime fit parameters in CreateTirfGraphs() // // NTU 5-1-14 // Added a bootstrap analysis for restime1 to get a more reliable estimate of error // Method 1: // Resample restime1 with replacement, 1000 iterations, N = V_npnts // Performs Gaussian fit to the distribution of means, reports Mean +/- SD // Method 2 (currently inactive): // Resample restime1 without replacement, 1000 iterations, N = V_npnts/2 // Performs Gaussian fit to the distribution of means, reports Mean +/- SD //-------------------------------------------------------------------------------------------------------------------// macro setupTIRFanalysis() variable/G EventNumber,TotalEvents EventNumber = 0 // global variable specifying which event we're looking at now TotalEvents = filenum[numpnts(filenum)-1] + 1 // global variable specifying total number of events in raw data waves NewPanel/W=(1050,50,1290,355) as "TIRF Analysis" // left,top,right,bottom? ModifyPanel cbRGB=(52224,52224,0) // funky yellow background color Button Starter pos={70,30},size={100,30},proc=StartButton,title="Start Analysis", win=Panel0 Button MarkUnloaded pos={15,65},size={100,30},proc=MarkUnloadedButton,title="Unused 1",win=Panel0 Button CheckUnloaded pos={125,65},size={100,30},proc=CheckUnloadedButton,title="Unused 2",win=Panel0 Button MarkEvent pos={15,100},size={100,30},proc=EventButton,title="Unused 3", win=Panel0 Button CheckEvent pos={125,100},size={100,30},proc=CheckButton,title="Check Event",win=Panel0 Button CheckPrev pos={15,135},size={100,30},proc=CheckPrevButton,title="Check Previous",win=Panel0 Button CheckNext pos={125,135},size={100,30},proc=CheckNextButton,title="Check Next",win=Panel0 SetVariable setvar0 pos={30,170},size={180,30},title="Current Event",value= EventNumber,win=Panel0 Button MarkBleach pos={15,195},size={100,30},proc=MarkBleachButton,title="Mark Bleach",win=Panel0 Button RemBleach pos={125,195},size={100,30},proc=RemBleachButton,title="Remove Bleach",win=Panel0 Button MatchCurs pos={70,230}, size={100,30}, proc= MatchCursButton,title="Match Cursors",win=Panel0 PopupMenu TermTypeM mode=1, pos={25,265}, size={200,30}, proc=TermTypeMenu,title="Unused 5",win=Panel0, value="other;detach;rescue" SetDrawEnv textrgb= (0,0,0),fsize=14,fstyle=1 // black text DrawText 70,20,"TIRF Analysis" end //----------------------------------------------------------------------------------------------------------------------------// // All the control functions for the Analysis Panel are below. // Since buttons have to call functions, but all the code is in macros, these just call the macros! Function StartButton(ctrlName) : ButtonControl String ctrlName Execute "StartTIRFanalysis()" End Function MarkUnloadedButton(ctrlName) : ButtonControl String ctrlName //Execute "MarkUnloaded()" End Function CheckUnloadedButton(ctrlName) : ButtonControl String ctrlName //Execute "CheckUnloaded()" End Function EventButton(ctrlName) : ButtonControl String ctrlName //Execute "MarkEvent()" End Function CheckButton(ctrlName) : ButtonControl String ctrlName Execute "CheckEvent()" End Function CheckPrevButton(ctrlName) : ButtonControl String ctrlName Execute "CheckPrevious()" End Function CheckNextButton(ctrlName) : ButtonControl String ctrlName Execute "CheckNext()" End Function MarkBleachButton(ctrlName) : ButtonControl String ctrlName //Execute "MarkCatast()" End Function RemBleachButton(ctrlName) : ButtonControl String ctrlName //Execute "RemoveCatast()" End Function MatchCursButton(ctrlName) : ButtonControl String ctrlName //Execute "MatchCursors()" End Function TermTypeMenu(ctrlName,popNum,popStr) : PopupMenuControl String ctrlName Variable popNum String popStr String dummystring = "SetTermType("+num2str(popNum)+")" //Execute dummystring End //-------------------------------------------------------------------------------------------------------------------// proc StartTIRFanalysis() silent 1 pauseupdate variable i=0,lowp,hip make/o/n=0 cfrm,cbr,cbk // waves for the current trace (frame, brtness, bkgnd) make/o/n=0 ckx,cky,ckx_rot,cky_rot,cmx,cmy,cmx_rot,cmy_rot // waves for current position traces, also after rotation make/o/n=(TotalEvents) StartTime,BleachTime,EndTime,restime // waves for the beginning, end, and photobleach times for each event make/o/n=(TotalEvents) br1,br2,bk,fn,dcm,dck// waves for other information about each event // note "br1" and "br2" are mean brightnesses before and after bleach mark, "bk" is mean background // "dcm" and "dck" refer to diffusion coefficients obtained from movie tracks and kymo tracks make/O/N=2 vline,vlinet // wave for displaying vertical lines on graphs vline[0]=0; vline[1]=40000000; vlinet[0]=0; vlinet[1]=0 make/O/N=2 hline,hlinet // wave for displaying horizontal lines on graphs hline[0]=0; hline[1]=0; hlinet[0]=0; hlinet[1]=2000000 do // initialize findvalue /V=(i) filenum // finds point number at beginning of event i lowp=V_value // stores point number at beginning of event i StartTime[i] = frame(lowp) // stores corresponding frame number (time) BleachTime[i] = NaN // will store frame number of bleach after user selects findvalue /V=(i+1) filenum // finds point number at beginning of event i+1 if(V_value!=-1) // if found hip=V_value-1 // store point number at end of event i else // we're at the last event hip=numpnts(filenum)-1 // store last point number endif EndTime[i] = frame(hip) // store corresponding frame number (time) wavestats /q/r=[lowp,hip] brtness // get stats between lowp and hip br1[i] = V_avg // store avg brtness before bleach br2[i] = NaN // will store avg brtness after bleach wavestats /q/r=[lowp,hip] bkgnd bk[i] = V_avg // store avg bkgnd fn[i] = filenum(lowp) // store filenum identifier i+=1 while (i= 0)) // if you're not trying to check an event that doesn't exist extract/o frame,cfrm,(filenum==EventNumber) extract/o brtness,cbr,(filenum==EventNumber) extract/o bkgnd,cbk,(filenum==EventNumber) extract/o xmov,cmx,(filenum==EventNumber) extract/o ymov,cmy,(filenum==EventNumber) extract/o xkymo,ckx,(filenum==EventNumber) extract/o ykymo,cky,(filenum==EventNumber) // what is correct direction along which to calculate 1D diffusion constant? curvefit/q line ckx /x=cky /d // fit line to xpos vs ypos xslope=w_coef[1] // slope of xpos vs ypos fit curvefit/q line cky /x=ckx /d // fit line to ypos vs xpos yslope=w_coef[1] // slope of ypos vs xpos fit if( (abs(yslope)<=abs(xslope))||(numtype(xslope)!=0) ) // if shallower on y vs x angle=-180*atan(yslope)/pi else // shallower on x vs y angle=180*atan(xslope)/pi-90 endif duplicate/o ckx,ckx_rot // D coeff calculations using kymotrack data duplicate/o cky,cky_rot ckx_rot=rotX(ckx,cky,angle) // rotate so most of the motion is along x' axis cky_rot=rotY(ckx,cky,angle) dum=ckx_rot[0] // shift so starting position is at origin ckx_rot-=dum dum=cky_rot[0] cky_rot-=dum duplicate/o cmx,cmx_rot // D coeff calculations using movietrack data duplicate/o cmy,cmy_rot cmx_rot=rotX(cmx,cmy,angle) // rotate so most of the motion is along x' axis cmy_rot=rotY(cmx,cmy,angle) dum=cmx_rot[0] // shift so starting position is at origin cmx_rot-=dum dum=cmy_rot[0] cmy_rot-=dum sequentialize("cfrm","cmx_rot") // pads cmx_rot with NaNs wherever frames are skipped in cfrm duplicate/o w_out,cmx_rot sequentialize("cfrm","ckx_rot") duplicate/o w_out,ckx_rot findvalue /V=(StartTime[EventNumber]) cfrm // finds point number of starttime startp=V_value findvalue /V=(EndTime[EventNumber]) cfrm // finds point number of endtime endp=V_value bleacht=BleachTime[EventNumber] wavestats /q ckx xmin=V_min xmax=V_max xcntr=(V_min+V_max)/2 halfwidth=(V_max-V_min)/2 wavestats /q cky ymin=V_min ymax=V_max ycntr=(V_min+V_max)/2 if(halfwidth<(V_max-V_min)/2) halfwidth=(V_max-V_min)/2 endif UpdateDisplay(startp,bleacht,endp,xcntr,ycntr,halfwidth) // resets plot limits, cursors, etc else // if you're trying to check an event that doesn't exist print "Event number "+num2str(EventNumber)+" does not exist" endif end //-------------------------------------------------------------------------------------------------------------------// proc CheckPrevious() silent 1 pauseupdate UpdateStoredVals() EventNumber-=1 if(EventNumber<0) EventNumber=TotalEvents-1 endif CheckEvent() end //-------------------------------------------------------------------------------------------------------------------// proc CheckNext() silent 1 pauseupdate UpdateStoredVals() EventNumber+=1 if(EventNumber>=TotalEvents) EventNumber=0 endif CheckEvent() end //-------------------------------------------------------------------------------------------------------------------// proc UpdateDisplay(startp,bleacht,endp,xcntr,ycntr,halfwidth) variable startp,bleacht,endp,xcntr,ycntr,halfwidth dowindow/F 'tracedisplay' wavestats/q cbr variable dummy=(V_max-V_min)/3 setaxis left (V_min-dummy),(V_max+dummy) wavestats/q cfrm setaxis bottom (V_min),(V_max) cursor /p A cbr startp cursor /p B cbr endp if(numtype(bleacht)==0) // if bleacht is a normal number modifygraph offset(vline)={(bleacht),0} else modifygraph offset(vline)={0,0} endif // dowindow/f 'xyplot' // setaxis bottom (xcntr-1.2*halfwidth),(xcntr+1.2*halfwidth) // setaxis left (ycntr-1.2*halfwidth),(ycntr+1.2*halfwidth) // // dowindow/f 'yxplot' // setaxis bottom (ycntr-1.2*halfwidth),(ycntr+1.2*halfwidth) // setaxis left (xcntr-1.2*halfwidth),(xcntr+1.2*halfwidth) // dowindow/f 'rotxyplot' // setaxis bottom (-3*halfwidth),(3*halfwidth) // setaxis left (-3*halfwidth),(3*halfwidth) end //-------------------------------------------------------------------------------------------------------------------// proc UpdateStoredVals() variable lowt,hit,bleacht,lowp,hip,bleachp dowindow/F 'tracedisplay' lowt = min(hcsr(A),hcsr(B)) // get times marked by cursors and vline hit = max(hcsr(A),hcsr(B)) bleacht = getoffset(vline,0,0) print bleacht lowp = min(pcsr(A),pcsr(B)) // get point numbers (indices) marked by cursors and vline hip = max(pcsr(A),pcsr(B)) findlevel /q cfrm bleacht bleachp = ceil(V_LevelX) // this will give index of first point after marked bleach time StartTime[EventNumber] = lowt EndTime[EventNumber] = hit if( (bleacht>lowt) && (bleachtstarttime+mint)) // st0 will contain stepsizes from single-bleach traces duplicate/o br1,temp temp-=br2 extract/o temp,st1,((numtype(br2)==0)&&(endtime>starttime+mint)) // st1 will contain stepsizes from first bleach in double-bleach traces duplicate/o br2,temp temp-=bk extract/o temp,st2,((numtype(br2)==0)&&(endtime>starttime+mint)) // st2 will contain stepsizes from second bleach in double-bleach traces duplicate/o st0,stall concatenatewaves(stall,st1) concatenatewaves(stall,st2) // stall will contain all the stepsizes duplicate/o Endtime,temp temp-=StartTime extract/o temp,bl0,(numtype(BleachTime)!=0) // bl0 will contain bleach time from single-bleach traces duplicate/o BleachTime,temp temp-=StartTime extract/o temp,bl1,(numtype(BleachTime)==0) // bl1 will contain bleach time from first bleach in double-bleach traces duplicate/o EndTime,temp temp-=BleachTime extract/o temp,bl2,(numtype(BleachTime)==0) // bl2 will contain bleach time from second bleach in double-bleach traces duplicate/o bl0,blall concatenatewaves(blall,bl1) // blall will contain all the bleach times concatenatewaves(blall,bl2) end //-------------------------------------------------------------------------------------------------------------------// // finds skipped frames in time wave and creates new version of data wave, called "w_out", which // includes NaN values whereever a frame was skipped proc sequentialize(timews,dataws) string timews,dataws // string names for the data wave that will be sequentialized based on gaps in the time wave variable j,k duplicate/o $(timews),inc duplicate/o inc,newtw duplicate/o $(dataws),w_out differentiate /ep=1 /meth=1 /p inc extract/o/indx inc,pinc,inc != 1 // extracts point numbers preceding any skipped frames (where inc is >1) if (numpnts(pinc) != 0) // if there are some missing points j=numpnts(pinc)-1 // initialize index j with the last gap do // loop to cycle through all gaps insertpoints (pinc[j]+1),(inc[pinc[j]]-1),w_out,newtw k=0 do // loop to cycle through all points within a single gap w_out[k+pinc[j]+1] = NaN newtw[k+pinc[j]+1] = $(timews)[pinc[j]]+k+1 k += 1 // increment k for next point while (k < (inc[pinc[j]]-1)) j-=1 // decrement k for next gap while (j>=0) endif killwaves inc,newtw // these were just used temporarily end //-------------------------------------------------------------------------------------------------------------------// macro createTIRFgraphs() silent 1 pauseupdate variable ibmin = 0 // min bin for brightness histo variable ibmax = 50000 // max bin for brightness histo variable ibw = 1000 // bin width for brightness histo variable rtmin = 0 // min bin for residence time histo variable rtmax = 30 // max bin for residence time histo variable rtw = 1 // bin width for residence time histo variable rfit_min = 1 // min point for fit to residence time histo variable rfit_max = 20 // max min point for fit to residence time histo variable msdfit_min = 0 // min point for fit to msd plot variable msdfit_max = 4 // max point for fit to msd plot if (exists("msd_avg1")) DoWindow msd if (V_flag == 1) DoWindow/K msd endif Display msd_avg1 vs tm ModifyGraph mode=3,marker=8,rgb(msd_avg1)=(0,15872,65280) ErrorBars msd_avg1 Y,wave=(msd_avg_sem1,msd_avg_sem1) Label bottom "Time (s)" Label left "Squared Displacement (\\F'Symbol'm\\F'Arial'm\\S2\\M)";DelayUpdate CurveFit/Q line msd_avg1[msdfit_min,msdfit_max] /X=tm /D ModifyGraph lstyle(fit_msd_avg1)=3 TextBox/C/N=text0/F=0/A=MC "D = "+num2str(W_coef[1]/2)+ " ± "+num2str(W_sigma[1]/2)+"\\F'Symbol'm\\F'Arial'm\\S2\\Ms\S-1\M" DoWindow/C msd endif if (exists("Dt1")) DoWindow Dtd if (V_flag == 1) DoWindow/K Dtd endif Display Dt1 vs duration1 ModifyGraph mode=3,marker=8,rgb=(65280,0,0) ModifyGraph log(bottom)=1 Label bottom "Event Duration (s)" Label left "Diffusion Coefficient (\\F'Symbol'm\\F'Arial'm\\S2\\M/s)" DoWindow/C Dtd DoWindow Dtb if (V_flag == 1) DoWindow/K Dtb endif Display Dt1 vs initbright Label bottom "Initial Brightness (AU)" Label left "Diffusion Coefficient (\\F'Symbol'm\\F'Arial'm\\S2\\M/s)" ModifyGraph mode=3,marker=8,rgb=(0,0,65280) DoWindow/C Dtb endif if (exists("initialbrightness")) DoWindow IB if (V_flag == 1) DoWindow/K IB endif Make/N=(round((ibmax-ibmin)/ibw))/O initialbrightness_Hist;DelayUpdate Histogram/B={ibmin,ibw,round((ibmax-ibmin)/ibw)} initialbrightness,initialbrightness_Hist Display initialbrightness_Hist ModifyGraph mode=6 Label bottom "Initial Brightness (AU)" Label left "Counts";DelayUpdate make/O/N=2, vlinex, vliney wavestats/Q initialbrightness_Hist vliney[0] = 0 vliney[1] = V_max wavestats/Q initialbrightness vlinex = V_avg AppendToGraph vliney vs vlinex ModifyGraph lstyle(vliney)=3,rgb(vliney)=(0,0,0) Make/D/N=3/O W_coef W_coef[0] = {vliney[1],V_avg,V_sdev} FuncFit/Q JoshGaus W_coef initialbrightness_Hist /I=1 /D ModifyGraph lstyle(fit_initialbrightness_Hist)=3;DelayUpdate ModifyGraph rgb(fit_initialbrightness_Hist)=(0,0,0) ModifyGraph offset(fit_initialbrightness_Hist)={ibw/2,0} wavestats/Q initialbrightness TextBox/C/N=text0/F=0/A=MC "N = "+num2str(V_npnts)+"\rB\Bavg\M = "+num2str(V_avg)+ " ± "+num2str(V_sdev)+" AU\rB\Bgaussian\M = "+num2str(W_coef[1]+(ibw/2))+ " ± "+num2str(W_coef[2])+ " AU" DoWindow/C IB endif if (exists("restime")) DoWindow Rt if (V_flag == 1) DoWindow/K Rt endif Duplicate/O restime, restime1 restime1 /=10 Make/N=(round((rtmax-rtmin)/rtw))/O restime1_Hist;DelayUpdate Histogram/B={rtmin,rtw,round((rtmax-rtmin)/rtw)} restime1,restime1_Hist Display restime1_Hist ModifyGraph mode=6 ModifyGraph log(left)=1 wavestats/Q restime1_Hist SetAxis left 1, V_max Label bottom "Residence Time (s)" Label left "Counts";DelayUpdate K0 = 0; CurveFit/H="100"/Q exp_XOffset restime1_Hist[rfit_min,rfit_max] /D ModifyGraph lstyle(fit_restime1_Hist)=3,rgb(fit_restime1_Hist)=(0,0,0) ModifyGraph offset(fit_restime1_Hist)={(rtw/2),0} wavestats/Q restime TextBox/C/N=text0/F=0/A=MC "N = "+num2str(V_npnts)+"\rk\Boff\M = "+num2str(1/(W_coef[2]))+ " ± "+num2str((1/(W_coef[2]))*(W_sigma[2]/W_coef[2]))+" s\S-1\M" DoWindow/C Rt endif end //-------------------------------------------------------------------------------------------------------------------// macro restimebootstrap() silent 1 pauseupdate variable i=0 make/O/N=1000 restime1_bsavg wavestats/Q restime1 statsresample/N=(V_npnts) /ws=2/ITER=1000 restime1 do restime1_bsavg[i] = M_WaveStatsSamples[3][i] i+=1 while (i<1000) wavestats/Q restime1_bsavg Make/N=(V_max*20)/O restime1_bsavg_Hist Histogram/B={0,0.1,V_max*20} restime1_bsavg,restime1_bsavg_Hist Make/D/N=3/O W_coef W_coef[0] = {V_npnts/2,V_avg,V_sdev} FuncFit/Q/NTHR=0 JoshGaus W_coef restime1_bsavg_Hist /D Display restime1_bsavg_Hist, fit_restime1_bsavg_Hist ModifyGraph rgb=(0,0,0),mode(restime1_bsavg_Hist)=6 ModifyGraph lstyle(fit_restime1_bsavg_Hist)=3 printf "Mean residence time +/- SD: %.1f", W_coef[1] printf " +/- %.1f", W_coef[2] print " seconds" end //-------------------------------------------------------------------------------------------------------------------// Function getRandomPoints() wavestats/Q restime1 Variable numPoints=V_npnts/2 // the number of points you want at the output Make/O/N=(numPnts(restime1)) tmpWaveN=enoise(1) Duplicate/O restime1, randomOrderWave Sort tmpWaveN,randomOrderWave Redimension/N=(numPoints) randomOrderWave KillWaves/Z tmpWaveN End //-------------------------------------------------------------------------------------------------------------------// // macro restimebootstrap2() // silent 1 // pauseupdate // variable i=0 // make/O/N=1000 restime1_bs2avg // do // getRandomPoints() // wavestats/Q randomOrderWave // restime1_bs2avg[i]=V_avg // i+=1 // while (i<1000) // wavestats/Q restime1_bsavg // Make/N=(V_max*20)/O restime1_bsavg_Hist // Histogram/B={0,0.1,V_max*20} restime1_bsavg,restime1_bsavg_Hist // Make/D/N=3/O W_coef // W_coef[0] = {V_npnts/2,V_avg,V_sdev} // FuncFit/Q/NTHR=0 JoshGaus W_coef restime1_bsavg_Hist /D // Display restime1_bs2avg_Hist, fit_restime1_bs2avg_Hist // ModifyGraph rgb=(0,0,0),mode(restime1_bs2avg_Hist)=6 // ModifyGraph lstyle(fit_restime1_bs2avg_Hist)=3 // printf "Mean residence time +/- SD: %.1f", W_coef[1] // printf " +/- %.1f", W_coef[2] // print " seconds" // end