#pragma rtGlobals=1 // Use modern global access method. menu "eFish" "Process file", efProcessOneFile() "Batch process files/2", efGetFilesToProcess() "-" "Load .eod .dmf .rms files/1", efLoadSingleFloatFiles() "Save .eod .dmf .rms waves", efSaveWaves() "-" "Remove playback", efGetFilesForSubtraction() "-" "Settings/3", eFishSettings() end //------------------------------------------------------------ Function CheckeFishGlobals() String dfSav= GetDataFolder(1) // Save data folder String theDF= "root:eFish" NewDataFolder/O/S $theDF if( (exists("GraphWidth") == 0) || (exists("GraphHeight") == 0) || (exists("LoadEOD") == 0)) Variable/G GraphWidth = 7,GraphHeight=6, LoadEOD=1 endif if( (exists("LowHz") == 0) || (exists("HighHz") == 0) || (exists("WindowDur") == 0) || (exists("OutputInterval") == 0) ) Variable/G LowHz = 500,HighHz=5000,WindowDur=0.006, OutputInterval=0.002 endif if( (exists("OverlapPercent") == 0) || (exists("dBthreshold") == 0) ) Variable/G OverlapPercent, dBthreshold=-94 endif NVAR WindowDur=root:eFish:WindowDur, OutputInterval=root:eFish:OutputInterval NVAR OverlapPercent=root:eFish:OverlapPercent OverlapPercent=(1-(OutputInterval/WindowDur))*100 if( (exists("LogToNotebook") == 0) || (exists("CountChirps") == 0) || (exists("ListBoxSelection") == 0) ) Variable/G LogToNotebook = 0, CountChirps=0, ListBoxSelection=1 endif if( (exists("LoadWAVFiles") == 0) || (exists("CurrChirpNum") == 0) ) Variable/G LoadWAVFiles = 0, CurrChirpNum=0 endif if( (exists("ChirpHzThresh") == 0) || (exists("minChirpDur") == 0) || (exists("minIntervalDur") == 0)|| (exists("BaselineDur") == 0)) Variable/G ChirpHzThresh = 3, minChirpDur=10, minIntervalDur=100, BaselineDur=5 endif if( (exists("NewStatsThresh") == 0) || (exists("AdjustHzThresh") == 0) ) Variable/G NewStatsThresh = 3, AdjustHzThresh=1 endif if( (exists("MaxChirpDur") == 0) || (exists("MaxDurSkip") == 0)) Variable/G MaxChirpDur = 30, MaxDurSkip=10 endif if( (waveexists(ChirpOnsetsStr) == 0) || (waveexists(ChirpOffsetsStr) == 0) || (waveexists(ChirpBaselineHzStr) == 0) ) String/G ChirpOnsetsStr, ChirpOffsetsStr, ChirpBaselineHzStr endif if( (waveexists(ChirpOnsets) == 0) || (waveexists(ChirpOffsets) == 0) || (waveexists(ChirpBaselineHz) == 0) ) Make/O/N=9999 ChirpOnsets, ChirpOffsets, ChirpBaselineHz endif if( (exists("NumChirpsFoundStr") == 0) || (exists("CurrFileName") == 0)) String/G NumChirpsFoundStr = "", CurrFileName="" endif SetDataFolder dfSav // Return to data folder End //------------------------------------------------------------ Function efGetFilesToProcess() CheckeFishGlobals() String ListOfFiles, FilePathName, FileName, FilePath Variable refNum NVAR LoadWAVFiles=root:eFish:LoadWAVFiles if(LoadWAVFiles) Open/D/R/M="Select one file to get list of files"/T=".wav" refNum if(strlen(S_fileName)<=0) return 0 endif FilePathName=S_fileName FileName = StringFromList(ItemsInList(FilePathName,":")-1, FilePathName, ":") FilePath=RemoveFromList(FileName, FilePathName, ":") NewPath/C/O/Q LoadPath, FilePath NewPath/C/O/Q SavePath, FilePath+"OutputFiles" ListOfFiles = IndexedFile(LoadPath,-1,".wav") else Open/D/R/M="Select one file to get list of files"/T=".ibw" refNum if(strlen(S_fileName)<=0) return 0 endif FilePathName=S_fileName FileName = StringFromList(ItemsInList(FilePathName,":")-1, FilePathName, ":") FilePath=RemoveFromList(FileName, FilePathName, ":") NewPath/C/O/Q LoadPath, FilePath NewPath/C/O/Q SavePath, FilePath+"OutputFiles" ListOfFiles = IndexedFile(LoadPath,-1,".ibw") endif eFShowFileList(ListOfFiles) End //------------------------------------------------------------ Function efShowFileList(ListOfFiles) String ListOfFiles DoWindow PrintList // Remember window position if the window exists if(V_flag) GetWindow PrintList wsize DoWindow/K PrintList NewPanel /K=1 /W=(V_left,V_top,V_right,V_bottom) as"Print List" else DoWindow/K PrintList NewPanel/K=1 /W=(550,45,800,455) as "Print List" endif DoWindow/C PrintList Variable rows = ItemsInList(ListOfFiles) Make/O/T/N=(rows,1) root:PrintListWave Make/O/N=(rows,1) root:WaveOfFilesSel Wave/T PrintListWave=root:PrintListWave Wave WaveOfFilesSel=root:WaveOfFilesSel; WaveOfFilesSel=1 variable i, numlist for(i=0;istrlen(BaseName)-6;i-=1) if(stringmatch(BaseName[i,i], ".")==1) BaseName[i,strlen(BaseName)]="" break endif endfor Variable SRate=1/deltax(InputSound) // Prompt for Pitch estimation variables or get variables from the Spectrogram settings dialog NVAR LowHz=root:eFish:LowHz, HighHz=root:eFish:HighHz NVAR WindowDur=root:eFish:WindowDur, OutputInterval=root:eFish:OutputInterval NVAR OverlapPercent=root:eFish:OverlapPercent, dBthreshold=root:eFish:dBthreshold //if(PromptSettings) // prompt WindowDur, "Window duration (sec.):" // prompt OverlapPercent, "Overlap (%; default for "+num2str(OutputInterval)+" interval)" // prompt dBthreshold, "Threshold (dB):" // prompt LowHz, "Lowest frequency (Hz):" // prompt HighHz, "Highest frequency (Hz):" // doprompt "Autocorrelation", WindowDur, OverlapPercent, dBthreshold, LowHz, HighHz // if(V_Flag) // return 0 // endif //endif WaveStats/Q InputSound Variable thresholdRMS=V_max*(10^(dBthreshold/20)) Variable Overlap=OverlapPercent/100 Variable WindowPnts=WindowDur*Srate, MinAccurateHz=(1/WindowDur)*3, SeriousErrors=0, PotentialErrors=0 variable SegStep = max(ceil((WindowPnts)*(1-Overlap)),1) variable NumSegs = max(floor(numpnts(InputSound)/SegStep)-1,1) // Make Window and wave for holding running segments Make/D/O/N=(WindowPnts) Win, Seg SetScale/P x 0,1/SRate,"sec", Win, Seg Win=1; Seg=1 // Get the Autocorrelation of the Window Hanning Win Correlate Win, Win // Make ""Corr_*" wave Make/D/O/N=(NumSegs) $"root:"+PossiblyQuoteName(BaseName+".dmf") Wave HzOut=$"root:"+PossiblyQuoteName(BaseName+".dmf") Make/D/O/N=(NumSegs) $"root:"+PossiblyQuoteName(BaseName+".rms") Wave RMSOut=$"root:"+PossiblyQuoteName(BaseName+".rms") HzOut=NaN; RMSOut=NaN MakeEFGraph(InputSound, HzOut, RMSOut, nameofwave(InputSound), 0) //SetScale/P x leftx(InputSound), OutputInterval,"sec", HzOut, RMSOut SetScale/I x leftx(InputSound), pnt2x(InputSound,numpnts(InputSound)-1),"sec", HzOut, RMSOut SetScale d 0,0,"Hz", HzOut SetScale d 0,0,"V", RMSOut Variable RMS //Variable/G Progress, root:BSoundGlobals:ProgressStopCtrl for(i=0;i0 && AutoOut[f+1]-AutoOut[f]<0 && AutoOut[f]-AutoOut[f-2]>0 && AutoOut[f]-AutoOut[f+2]>0) firstPnt=f-2 lastPnt=f+2 break endif endfor // interpolate and get location (time) of first peak duplicate/O/R=[firstPnt,lastPnt] AutoOut, Int if(lastPnt-firstPnt >=3) execute "Interpolate/T=3/N=1000/F=1/Y=int_SS int" wave int_SS=root:int_SS WaveStats/Q int_SS peak=V_maxloc if(peak<(1/LowHz) && peak>(1/HighHz) ) if(peak<(1/MinAccurateHz)) HzOut[i]=1/peak else HzOut[i]=1/peak PotentialErrors+=0 endif else HzOut[i]=NaN endif RMSOut[i]=RMS else HzOut[i]=NaN RMSOut[i]=RMS SeriousErrors+=1 endif endif //threshold if(mod(i, 500)==0) doupdate endif endfor KillWaves/Z Seg,Win,Int,int_SS,AutoOut, AOT //,InputSound if(PotentialErrors>=1 || SeriousErrors>=1) String AlertStr if(PotentialErrors>=1 && SeriousErrors<=1) SPrintf AlertStr, "%g potential error(s) were reported. Window length should be longer than %g to find peaks below %g Hz", PotentialErrors, WindowDur, (1/WindowDur)*3 else SPrintf AlertStr, "%g serious undersampling(s) were reported. Window length should be longer than %g to find peaks below %g Hz", SeriousErrors, WindowDur, (1/WindowDur)*3 endif if(PotentialErrors>=1 && SeriousErrors>=1) SPrintf AlertStr, "%g serious undersampling(s) and %g potential error(s) were reported. Window length should be longer than %g to find peaks below %g Hz," SeriousErrors, PotentialErrors, WindowDur, (1/WindowDur)*3 endif //DoAlert 0, AlertStr Print AlertStr endif // Write files efSaveSingleFloat32bit(InputSound, HzOut, RMSOut) SetDataFolder dfSav return 0 End //-------------------------------------------------------------------------- Function MakeEFGraph(EOD, DF, RMS, CurrentFile, analysis) Wave EOD, DF, RMS String CurrentFile Variable analysis SVAR ChirpOnsetsStr=root:eFish:ChirpOnsetsStr, ChirpOffsetsStr=root:eFish:ChirpOffsetsStr SVAR ChirpBaselineHzStr=root:eFish:ChirpBaselineHzStr NVAR GraphHeight=root:eFish:GraphHeight, GraphWidth=root:eFish:GraphWidth ChirpOnsetsStr="all;"; ChirpOffsetsStr=""; ChirpBaselineHzStr="" SVAR NumChirpsFoundStr=root:eFish:NumChirpsFoundStr NumChirpsFoundStr="0" String DFstr=PossiblyQuoteName(NameOfWave(DF)), RMSstr=PossiblyQuoteName(NameOfWave(RMS)) DoWindow/K eFish Display/K=1/I/W=(0.2,0.5,GraphWidth+0.2,GraphHeight+0.5)/L=LeftHz DF as CurrentFile;delayupdate DoWindow/C eFish;delayupdate SetWindow eFish note=CurrentFile ;delayupdate SetWindow eFish, hook=eFWindowEvent2;DelayUpdate NVAR LoadEOD=root:eFish:LoadEOD if(LoadEOD) String EODstr=PossiblyQuoteName(NameOfWave(EOD)) AppendToGraph/L=LeftRMS EOD;delayupdate ModifyGraph rgb($EODstr)=(48059,48059,48059);delayupdate endif AppendToGraph/L=LeftRMS RMS;delayupdate ModifyGraph margin(left)=50;delayupdate ModifyGraph lSize=0.5;delayupdate ModifyGraph rgb($DFstr)=(1,3,39321),rgb($RMSstr)=(1,3,39321);delayupdate ModifyGraph tick=2;delayupdate ModifyGraph fSize=12;delayupdate ModifyGraph highTrip(LeftHz)=999,highTrip(LeftRMS)=999;delayupdate ModifyGraph standoff(LeftHz)=0,standoff(LeftRMS)=0;delayupdate ModifyGraph lblPos(LeftHz)=50,lblPos(LeftRMS)=50;delayupdate ModifyGraph freePos(LeftHz)={0,bottom};delayupdate ModifyGraph freePos(LeftRMS)={0,bottom};delayupdate ModifyGraph axisEnab(LeftHz)={0.53,1};delayupdate ModifyGraph axisEnab(LeftRMS)={0,0.47};delayupdate SetAxis LeftRMS 0,7.1 ;delayupdate Label LeftHz "frequency (\\U)";delayupdate Label LeftRMS "amplitude (\\U)";delayupdate Label bottom "time (\\U)";delayupdate analysis=1 if(analysis) ControlBar 28;delayupdate Button CountChirps pos={10,3},title="Count", proc=CountChirpsProc;delayupdate SetVariable NumChirps pos={65,7},size={35,15},frame=0,title=" ",value= root:eFish:NumChirpsFoundStr;delayupdate PopupMenu ChirpListPopUp pos={100,3}, title="go",mode=0,proc=ChirpNumProc,value=#root:eFish:ChirpOnsetsStr;delayupdate Button LastFile pos={147,3},size={20,20},proc=efNextFileProc,title="-" Button NextFile pos={170,3},size={20,20},proc=efNextFileProc,title="+" ValDisplay ChirpNum pos={194,6},size={33,20},value=#root:eFish:CurrChirpNum Button Play pos={235,3},size={50,20},proc=efPlayProc,title="Play" Button Stop pos={290,3},size={50,20},proc=efPlayProc,title="Stop" Button GetStats pos={355,3},size={80,20},proc=efStatsProc,title="Get Stats" endif doupdate NVAR CurrChirpNum=root:eFish:CurrChirpNum; CurrChirpNum=1 NVAR CountChirps=root:eFish:CountChirps, LogToNotebook=root:eFish:LogToNotebook if(CountChirps) CountChirpsProc("CountChirps") if(LogToNotebook) efStatsProc("GetStats") endif endif End Function efNextFileProc(ctrlName) : ButtonControl String ctrlName SVAR ChirpOnsetsStr=root:eFish:ChirpOnsetsStr if(ItemsInlist(ChirpOnsetsStr)<=1) Print "No chirps counted" return 0 endif GetWindow $WinName(0,1) note String Name=S_Value SetDataFolder root: Wave DMF=$Name+".dmf" NVAR CurrChirpNum=root:eFish:CurrChirpNum if(stringmatch(ctrlName, "NextFile")) CurrChirpNum+=1 else CurrChirpNum-=1 endif SVAR ChirpOnsetsStr=root:eFish:ChirpOnsetsStr, ChirpOffsetsStr=root:eFish:ChirpOffsetsStr Variable NumChirps=ItemsInList(ChirpOnsetsStr)-2 if(CurrChirpNum>NumChirps+1) CurrChirpNum=1 // skip "all;..." endif if(CurrChirpNum<1) // skip "all;..." CurrChirpNum=NumChirps+1 endif Variable Onset=str2num(stringfromlist(CurrChirpNum, ChirpOnsetsStr)) Variable Offset=str2num(stringfromlist(CurrChirpNum-1, ChirpOffsetsStr)) Onset=Onset-(max(Offset-Onset,0.5)) Offset=Offset+(max(Offset-Onset,0.5)) SetAxis bottom max(Onset, leftx(DMF)), min(Offset, pnt2x(DMF,numpnts(DMF)-1) ) WaveStats/Q/R=(Onset, Offset) DMF SetAxis LeftHz V_min,V_max End Function eFWindowEvent2(infoStr) String infoStr String event= StringByKey("EVENT",infoStr) String graphName String TraceList = TraceNameList("",";",1) if(stringmatch(event,"kill")) DoWindow/K $StringByKey("WINDOW",infoStr) NVAR AutoKill=root:eFish:AutoKill if(1) eFKillCurrentWaves2(TraceList) endif endif return 0 End Function eFKillCurrentWaves2(TraceList) String TraceList variable i, loc String currWave for(i=0; i RightSel) // Make sure Left is Left... temp = RightSel RightSel =LeftSel LeftSel = temp endif Duplicate/O/R=(LeftSel,RightSel) $NameOfSound, tempWave else // Duplicate whole wave for playing GetAxis/Q bottom Duplicate/O/R=(V_min,V_max) $NameOfSound, tempWave endif endif tempWave *= 32767/10 Redimension/W tempWave Playsound/A=1 tempWave Killwaves tempWave else // "Stop" Make/O/w/N=2 Dummy SetScale/P x 0,1/44100,"", Dummy PlaySound/A=2 Dummy KillWaves Dummy endif End //-------------------------------------------------------------------------- Function ChirpNumProc(ctrlName,popNum,popStr) : PopupMenuControl String ctrlName Variable popNum String popStr GetWindow $WinName(0,1) note String Name=S_Value SetDataFolder root: Wave DMF=$Name+".dmf" if(stringmatch(popStr, "all")) SetAxis/A bottom SetAxis/A LeftHz return 0 endif SVAR ChirpOnsetsStr=root:eFish:ChirpOnsetsStr, ChirpOffsetsStr=root:eFish:ChirpOffsetsStr NVAR CurrChirpNum=root:eFish:CurrChirpNum CurrChirpNum=popNum-1//; Print CurrChirpNum Variable Onset=str2num(stringfromlist(popNum-1, ChirpOnsetsStr)) Variable Offset=str2num(stringfromlist(popNum-2, ChirpOffsetsStr)) Onset=Onset-(max(Offset-Onset,0.5)) Offset=Offset+(max(Offset-Onset,0.5)) SetAxis bottom max(Onset, leftx(DMF)), min(Offset, pnt2x(DMF,numpnts(DMF)-1) ) WaveStats/Q/R=(Onset, Offset) DMF SetAxis LeftHz V_min,V_max End //-------------------------------------------------------------------------- Function efSaveSingleFloat32bit(W, DF, RMS) Wave W, DF, RMS Variable refNum, dx, lx // Get base name for output files String BaseName=NameOfWave(W), str Variable i for(i=strlen(BaseName)-1;i>strlen(BaseName)-6;i-=1) if(stringmatch(BaseName[i,i], ".")==1) BaseName[i,strlen(BaseName)]="" break endif endfor // Write EOD wave Open/P=SavePath refNum as BaseName+".eod" if(refNum==0) return 0 endif str=""; str=PadString(str, 1024, 0) FBinWrite/B=3 refNum, str FSetPos refNum, 0 str="Fish" FBinWrite/B=3 refNum, str dx=leftx(W) FBinWrite/B=3/F=4 refNum, lx dx=deltax(W) FBinWrite/B=3/F=4 refNum, dx FSetPos refNum, 1024 FBinWrite/B=3/F=4 refNum, W Close refNum // Write dominant frequency wave Open/P=SavePath refNum as BaseName+".dmf" if(refNum==0) return 0 endif str=""; str=PadString(str, 1024, 0) FBinWrite/B=3 refNum, str FSetPos refNum, 0 str="Fish" FBinWrite/B=3 refNum, str dx=leftx(DF) FBinWrite/B=3/F=4 refNum, lx dx=deltax(DF) FBinWrite/B=3/F=4 refNum, dx FSetPos refNum, 1024 FBinWrite/B=3/F=4 refNum, DF Close refNum // Write dominant frequency wave Open/P=SavePath refNum as BaseName+".rms" if(refNum==0) return 0 endif str=""; str=PadString(str, 1024, 0) FBinWrite/B=3 refNum, str FSetPos refNum, 0 str="Fish" FBinWrite/B=3 refNum, str dx=leftx(RMS) FBinWrite/B=3/F=4 refNum, lx dx=deltax(RMS) FBinWrite/B=3/F=4 refNum, dx FSetPos refNum, 1024 FBinWrite/B=3/F=4 refNum, RMS Close refNum End //-------------------------------------------------------------------- Function efLoadSingleFloatFiles() CheckeFishGlobals() Variable refNum Open/R/Z=0/M="Open an .eod, .dmf or .rms file"/T="????" refNum String FilePathName=S_Filename if(refNum==0) return 0 endif Close refNum String FileName = StringFromList(ItemsInList(FilePathName,":")-1, FilePathName, ":") String FilePath=RemoveFromList(FileName, FilePathName, ":") NewPath/O/Q LoadPath, FilePath PathInfo/S LoadPath String BaseName=FileName, SignalFilePath Variable i for(i=strlen(BaseName)-1;i>strlen(BaseName)-6;i-=1) if(stringmatch(BaseName[i,i], ".")==1) BaseName[i,strlen(BaseName)]="" break endif endfor String FileType=" " Variable dx=0, lx=0 String/G gfileName="" NVAR LoadEOD=root:eFish:LoadEOD if(LoadEOD) String/G gfileName=BaseName+".eod" Open/R/Z=0/P=LoadPath/M="Open .eod file"/T="????" refNum as gfileName SignalFilePath=S_Filename if(refNum==0) return 0 endif FileType=" " FBinRead/B=3 refNum, FileType FBinRead/B=3/F=4 refNum, lx FBinRead/B=3/F=4 refNum, dx Close refNum Execute "GBLoadWave/Q/B/T={2,2}/S=1024/W=1/P=LoadPath gfileName" SetScale/P x lx,dx,"sec", wave0 if(WaveExists($gfileName)) killWaves/Z $gfileName endif rename wave0, $gfileName SetScale d 0,0,"V", $BaseName+".eod" endif gfileName=BaseName+".dmf" Open/R/Z=0/P=LoadPath/M="Open .dmf file"/T="????" refNum as gfileName SignalFilePath=S_Filename if(refNum==0) return 0 endif FileType=" " FBinRead/B=3 refNum, FileType FBinRead/B=3/F=4 refNum, lx FBinRead/B=3/F=4 refNum, dx Close refNum Execute "GBLoadWave/Q/B/T={2,2}/S=1024/W=1/P=LoadPath gfileName" SetScale/P x lx,dx,"sec", wave0 if(WaveExists($gfileName)) DoWindow/K eFish killWaves/Z $gfileName endif rename wave0, $gfileName SetScale d 0,0,"Hz", $BaseName+".dmf" NVAR WindowDur=root:eFish:WindowDur, OutputInterval=root:eFish:OutputInterval NVAR OverlapPercent=root:eFish:OverlapPercent //OutputInterval=dx //OverlapPercent=(1-(OutputInterval/WindowDur))*100 gfileName=BaseName+".rms" Open/R/Z=0/P=LoadPath/M="Open .rms file"/T="????" refNum as gfileName SignalFilePath=S_Filename if(refNum==0) return 0 endif FileType=" " FBinRead/B=3 refNum, FileType FBinRead/B=3/F=4 refNum, lx FBinRead/B=3/F=4 refNum, dx Close refNum Execute "GBLoadWave/Q/B/T={2,2}/S=1024/W=1/P=LoadPath gfileName" SetScale/P x lx,dx,"sec", wave0 if(WaveExists($gfileName)) DoWindow/K eFish killWaves/Z $gfileName endif rename wave0, $gfileName SetScale d 0,0,"V", $BaseName+".rms" KillStrings/Z gfileName MakeEFGraph($BaseName+".eod", $BaseName+".dmf", $BaseName+".rms", BaseName, 1) End //------------------------------------------------------------ Window eFishSettings() : Panel CheckeFishGlobals() PauseUpdate; Silent 1 // building window... DoWindow eFishSettings // Remember window position if the window exists if(V_flag) GetWindow eFishSettings wsize DoWindow/K eFishSettings NewPanel /K=1 /W=(V_left,V_top,V_right,V_bottom) as "Settings" else DoWindow/K eFishSettings NewPanel/K=1/W=(462,80,690,670) as "Settings" endif DoWindow/C eFishSettings CheckBox loadWAVs pos={50,5},title="load WAV files (vs. ibw)", variable=root:eFish:LoadWAVFiles SetDrawEnv fsize= 10 DrawText 80,45,"Remove playback" DrawLine 12,47,210,47 CheckBox SubtractPlayback pos={27,50},size={100,14},title="List box selection", variable=root:eFish:ListBoxSelection SetDrawEnv fsize= 10 DrawText 50,90,"Autocorrelation variables" DrawLine 12,90,210,90 SetVariable HighHz,pos={36,100},size={168,15}, bodyWidth=60, title="High frequency (Hz)" SetVariable HighHz,limits={1,130000,500},value= root:eFish:HighHz SetVariable LowHz,pos={39,121},size={165,15},bodyWidth=60, title="Low frequency (Hz)" SetVariable LowHz,limits={1,130000,500},value= root:eFish:LowHz SetVariable WindowDur,pos={22,150},size={180,15},bodyWidth=60, title="Window duration (sec.)" SetVariable WindowDur,limits={1e-05,1,0.001},proc=SetOverlap,value= root:eFish:WindowDur SetVariable OutputInterval,pos={28,171},size={175,15},bodyWidth=60, title="Output interval (sec.)" SetVariable OutputInterval,limits={1e-05,1,0.001},proc=SetOverlap,value= root:eFish:OutputInterval SetVariable OverLap,pos={62,200},size={140,15},bodyWidth=60, title="Overlap (%)" SetVariable OverLap,limits={0,99,5},proc=SetOutputInterval,value= root:eFish:OverlapPercent SetVariable Threshold,pos={50,229},size={150,15},bodyWidth=60, title="Threshold (dB)" SetVariable Threshold,limits={-99,99,3},value= root:eFish:dBthreshold SetDrawEnv fsize= 10 DrawText 80,270,"Graph Settings" DrawLine 12,271,210,271 CheckBox LoadEOD pos={25,280},size={100,14},title="Load EOD", variable=root:eFish:LoadEOD SetVariable GraphWidth,pos={110,280},size={90,15},bodyWidth=60, title="Width" SetVariable GraphWidth,limits={1,50,1},value= root:eFish:GraphWidth SetVariable GraphHeight,pos={108,300},size={92,15},bodyWidth=60, title="Height" SetVariable GraphHeight,limits={1,50,1},value= root:eFish:GraphHeight SetDrawEnv fsize= 10 DrawText 80,340,"Chirp Count" DrawLine 12,341,210,341 CheckBox Count pos={25,348},size={100,14},title="Count chirps automatically", variable=root:eFish:CountChirps SetVariable ChirpHzThresh,pos={50,375},size={152,15},bodyWidth=60,title="Chirp thresh. (Hz)" SetVariable ChirpHzThresh,limits={0.5,50,0.5},value= root:eFish:ChirpHzThresh SetVariable minChirpDur,pos={42,400},size={160,15},bodyWidth=60,title="Min. chirp dur. (ms)" SetVariable minChirpDur,limits={1,1000,1},value= root:eFish:minChirpDur SetVariable maxIntervalDur,pos={27,420},size={175,15},bodyWidth=60,title="Min. interval dur. (ms)" SetVariable maxIntervalDur,limits={1,10000,1},value= root:eFish:minIntervalDur SetVariable MaxChirpDur,pos={45,445},size={157,15},bodyWidth=60,title="Max. chirp dur. (S)" SetVariable MaxChirpDur,limits={1,1000,1},value= root:eFish:MaxChirpDur SetVariable MaxDurSkip,pos={62,465},size={140,15},bodyWidth=60,title="Advance time (S)" SetVariable MaxDurSkip,limits={0.01,10000,1},value= root:eFish:MaxDurSkip SetVariable BaselineDur,pos={47,490},size={155,15},bodyWidth=60,title="Baseline dur. (sec.)" SetVariable BaselineDur,limits={0.01,60,1},value= root:eFish:BaselineDur SetDrawEnv fsize= 10 DrawText 80,530,"Chirp Statistics" DrawLine 12,531,210, 531 CheckBox LogToNotebook pos={25,538},size={100,14},title="write stats automatically" , variable=root:eFish:LogToNotebook CheckBox SubtractHz pos={25,560},size={100,14},title="Stats thresh.", variable=root:eFish:AdjustHzThresh SetVariable NewStatsThresh,pos={35,560},size={157,15},bodyWidth=50,title="(Hz)" SetVariable NewStatsThresh,limits={1,1000,1},value= root:eFish:NewStatsThresh Button TestStatsThresh pos={200,557}, size={15,20},title="a", proc=TestStatsThreshProc EndMacro //------------------------------------------------------------ Function TestStatsThreshProc(ctrlName) : ButtonControl String ctrlName AdjustHzThreshForStats() End Function SetOverlap(ctrlName,varNum,varStr,varName) : SetVariableControl String ctrlName Variable varNum String varStr String varName NVAR WindowDur=root:eFish:WindowDur, OutputInterval=root:eFish:OutputInterval NVAR OverlapPercent=root:eFish:OverlapPercent OverlapPercent=(1-(OutputInterval/WindowDur))*100 End Function SetOutputInterval(ctrlName,varNum,varStr,varName) : SetVariableControl String ctrlName Variable varNum String varStr String varName NVAR WindowDur=root:eFish:WindowDur, OutputInterval=root:eFish:OutputInterval NVAR OverlapPercent=root:eFish:OverlapPercent OutputInterval=(1-(OverlapPercent/100))*WindowDur End //------------------------------------------------------------------------------- Function CountChirpsProc(ctrlName) : ButtonControl String ctrlName GetWindow $WinName(0,1) note String Name=S_Value SetDataFolder root: Wave DMF=$Name+".dmf" Wave ChirpOnsets=root:eFish:ChirpOnsets, ChirpOffsets=root:eFish:ChirpOffsets, ChirpBaselineHz=root:eFish:ChirpBaselineHz Redimension/N=9999 ChirpOnsets, ChirpOffsets, ChirpBaselineHz ChirpOnsets=0; ChirpOffsets=0; ChirpBaselineHz=0 NVAR HzThesh=root:eFish:ChirpHzThresh, BaselineDur=root:eFish:BaselineDur NVAR minChirpDur=root:eFish:minChirpDur, minIntervalDur=root:eFish:minIntervalDur NVAR MaxChirpDur=root:eFish:MaxChirpDur, MaxDurSkip=root:eFish:MaxDurSkip Variable dx=deltax(DMF) Variable BaselineCalcPnts=round(BaselineDur/dx) Variable minChirpDurPnts=round((minChirpDur/1000)/dx) Variable minIntervalPnts=round((minIntervalDur/1000)/dx) Variable i, j, k, c=0, BaselineHz, GetBaseLine=0 Variable ChirpOnset, ChirpTerm Variable StartPnt=0, StopPnt=numpnts(DMF) GetMarquee bottom if(V_flag) StartPnt=x2pnt(DMF, V_left); StopPnt=x2pnt(DMF, V_right) endif BaselineHz=efMode(DMF, StartPnt-(BaselineCalcPnts/2), StartPnt+(BaselineCalcPnts/2)) for(i=StartPnt; i<=StopPnt; i+=1) // get running BaselineHz using mode as we go if(mod(i, BaselineCalcPnts)==0 || GetBaseLine) BaselineHz=efMode(DMF, i, i+BaselineCalcPnts) //Print BaselineHz GetBaseLine=0 endif if(DMF[i]>=BaselineHz+HzThesh) ChirpOnset=(i-1)*dx for(j=i;j<=StopPnt; j+=1) if(DMF[j]<=BaselineHz+HzThesh) // check duration of chirp interval for(k=j;k<=j+minIntervalPnts; k+=1) if(DMF[k]>=BaselineHz+HzThesh) j=k break endif endfor if(j!=k) break endif endif endfor if((j-i) > minChirpDurPnts) ChirpTerm=(j)*dx //check to see if chirp exceeds maximum length if(ChirpTerm-ChirpOnset > MaxChirpDur) i=x2pnt(DMF, ChirpOnset+MaxDurSkip) GetBaseLine=1 else ChirpOnsets[c]=ChirpOnset ChirpOffsets[c]=ChirpTerm ChirpBaselineHz[c]=BaselineHz+HzThesh c+=1 i=j+1 GetBaseLine=1 endif endif endif endfor deletepoints c, 9999-c, ChirpOnsets, ChirpOffsets, ChirpBaselineHz String TraceList=TraceNameList("",";",1) if(strsearch(TraceList, "ChirpBaselineHz", 0)>0) RemoveFromGraph ChirpBaselineHz,ChirpBaselineHz#1 endif AppendToGraph/L=LeftHz ChirpBaselineHz vs ChirpOnsets AppendToGraph/L=LeftHz ChirpBaselineHz vs ChirpOffsets ModifyGraph mode(ChirpBaselineHz)=3,marker(ChirpBaselineHz)=9, msize(ChirpBaselineHz)=5 ModifyGraph mode(ChirpBaselineHz#1)=3,marker(ChirpBaselineHz#1)=9, msize(ChirpBaselineHz#1)=5 SVAR NumChirpsFoundStr=root:eFish:NumChirpsFoundStr NumChirpsFoundStr=num2str(numpnts(ChirpBaselineHz)) SVAR ChirpOnsetsStr=root:eFish:ChirpOnsetsStr, ChirpOffsetsStr=root:eFish:ChirpOffsetsStr SVAR ChirpBaselineHzStr=root:eFish:ChirpBaselineHzStr ChirpOnsetsStr="all;"; ChirpOffsetsStr=""; ChirpBaselineHzStr="" for(i=0;i (ChirpBaselineHz[i]-ChirpHzThresh)+NewStatsThresh && mA=maxAdjustment) Print "Unable to adjust threshold for stats at "+num2str(ChirpOnsets[i])+"!!" endif ChirpOnsets[i]=pnt2x(DMF, LeftPnt) RightPnt=x2pnt(DMF, ChirpOffsets[i]) mA=0 do RightPnt+=1 mA+=1 //Printf "%g, %g\r", DMF[RightPnt], (ChirpBaselineHz[i]-ChirpHzThresh)+NewStatsThresh while(DMF[RightPnt] > (ChirpBaselineHz[i]-ChirpHzThresh)+NewStatsThresh && mA=maxAdjustment) Print "Unable to adjust threshold for stats at "+num2str(ChirpOnsets[i])+"!!" endif ChirpOffsets[i]=pnt2x(DMF, RightPnt) ChirpBaselineHz[i]=(ChirpBaselineHz[i]-ChirpHzThresh)+NewStatsThresh endfor End //------------------------------------------------------------------------------ Function efStatsProc(ctrlName) : ButtonControl String ctrlName NVAR AdjustHzThresh=root:eFish:AdjustHzThresh if(AdjustHzThresh) AdjustHzThreshForStats() endif GetWindow $WinName(0,1) note String Name=S_Value SetDataFolder root: Wave DMF=$Name+".dmf" Wave EOD=$Name+".eod" Wave RMS=$Name+".rms" Variable StartX=leftx(DMF), StopX=pnt2x(DMF,numpnts(DMF)-1) GetMarquee bottom if(V_flag) StartX=V_left; StopX=V_right endif Wave ChirpOffsets=root:eFish:ChirpOffsets, ChirpOnsets=root:eFish:ChirpOnsets, ChirpBaselineHz=root:eFish:ChirpBaselineHz NVAR ChirpHzThresh=root:eFish:ChirpHzThresh Variable i, StartPnt, StopPnt for(i=0; i=StartX && ChirpOnsets[i]<=StopX) WaveStats/Q/R=(ChirpOnsets[i], ChirpOffsets[i]) DMF //Printf "%s, %g, %g, %g, %g, %g, %g, %g, %g, ", Name, ChirpOnsets[i], ChirpOffsets[i], ChirpOffsets[i]-ChirpOnsets[i], V_avg, V_sdev, V_max, V_min, V_max-V_min String NoteBookWinList = WinList("*", ";","WIN:16") if(strsearch(NoteBookWinList, "eFishNotebook", 0)<0) DoAlert 1, "Create a new eFish Data Log?" if(V_flag == 1) NEWefMakeNewDataLog() // Make a new notebook else return 0 endif endif String nbNum = "eFishNotebook" String DataLogString1, DataLogString2, DataLogString3 SPrintf DataLogString1, "%s\t%g\t%g\t%g\t%g\t", Name, ChirpOnsets[i], ChirpOffsets[i], ChirpOffsets[i]-ChirpOnsets[i], V_maxloc SPrintf DataLogString2, "%g\t%g\t%g\t%g\t%g\t%g\t", ChirpBaselineHz[i]-ChirpHzThresh, ChirpHzThresh, V_Max, V_Min,V_Max-(ChirpBaselineHz[i]-ChirpHzThresh), V_Min-(ChirpBaselineHz[i]-ChirpHzThresh) Notebook $nbNum text=DataLogString1+DataLogString2 if(WaveExists(EOD)==1) WaveStats/Q/R=(ChirpOnsets[i], ChirpOffsets[i]) EOD //Printf "%g, %g, %g\r", V_rms, V_max, V_min SPrintf DataLogString3, "%g\t%g\t%g\r", V_rms, V_max, V_min Notebook $nbNum text=DataLogString3 else SPrintf DataLogString3, "\r" Notebook $nbNum text=DataLogString3 endif endif endfor End //------------------------------------------------------------ Function NEWefMakeNewDataLog() // Create an eFish data log String nbNum = "eFishNotebook" NewNotebook/N=$nbNum/F=0/V=1/K=0/W=(5,40,505,335) as "eFish chirp data Log" Notebook $nbNum defaultTab=72, statusWidth=238, pageMargins={72,72,72,72} Notebook $nbNum font="Geneva", fSize=10, fStyle=0, textRGB=(0,0,0) Notebook $nbNum text="eFish chirp data log created on " + date() + " at " + time() + "\r" Notebook $nbNum text="FileName\tStartTime\tEndTime\tDuration\tPeakTime\tBaselineHz\tHzThresh\tMaxHz\tMinHz\tPosHzDev\tNegHzDev\tRMS\tMaxAmp\tMinAmp\r" End //------------------------------------------------------------ Function MarqueeFishStats() : GraphMarquee GetWindow $WinName(0,1) note String Name=S_Value SetDataFolder root: Wave DMF=$Name+".dmf" Wave EOD=$Name+".eod" Wave RMS=$Name+".rms" Variable StartX=leftx(DMF), StopX=pnt2x(DMF,numpnts(DMF)-1) GetMarquee bottom if(V_flag) StartX=V_left; StopX=V_right endif Wave ChirpOffsets=root:eFish:ChirpOffsets, ChirpOnsets=root:eFish:ChirpOnsets, ChirpBaselineHz=root:eFish:ChirpBaselineHz NVAR ChirpHzThresh=root:eFish:ChirpHzThresh WaveStats/Q/R=(StartX, StopX) DMF //Printf "%s, %g, %g, %g, %g, %g, %g, %g, %g, ", Name, ChirpOnsets[i], ChirpOffsets[i], ChirpOffsets[i]-ChirpOnsets[i], V_avg, V_sdev, V_max, V_min, V_max-V_min String NoteBookWinList = WinList("*", ";","WIN:16") if(strsearch(NoteBookWinList, "eFishNotebook", 0)<0) DoAlert 1, "Create a new eFish Data Log?" if(V_flag == 1) NEWefMakeNewDataLog() // Make a new notebook else return 0 endif endif Variable BaselineHz=efMode(DMF, max(0,x2pnt(DMF, StartX-1)), min(x2pnt(DMF, StopX+1), numpnts(DMF)) ) // Get baseline Hz from marquee selection String nbNum = "eFishNotebook" String DataLogString1, DataLogString2, DataLogString3 SPrintf DataLogString1, "%s\t%g\t%g\t%g\t%g\t", Name, StartX, StopX, StopX-StartX, V_maxloc SPrintf DataLogString2, "%g\t%g\t%g\t%g\t%g\t%g\t", BaselineHz-ChirpHzThresh, ChirpHzThresh, V_Max, V_Min,V_Max-(BaselineHz-ChirpHzThresh), V_Min-(BaselineHz-ChirpHzThresh) Notebook $nbNum text=DataLogString1+DataLogString2 if(WaveExists(EOD)==1) WaveStats/Q/R=(StartX, StopX) EOD //Printf "%g, %g, %g\r", V_rms, V_max, V_min SPrintf DataLogString3, "%g\t%g\t%g\r", V_rms, V_max, V_min Notebook $nbNum text=DataLogString3 else SPrintf DataLogString3, "\r" Notebook $nbNum text=DataLogString3 endif End //------------------------------------------------------------ Function efSaveWaves() GetWindow $WinName(0,1) note String Name=S_Value // Get base name for output files String BaseName=Name Variable i for(i=strlen(BaseName)-1;i>strlen(BaseName)-6;i-=1) if(stringmatch(BaseName[i,i], ".")==1) BaseName[i,strlen(BaseName)]="" break endif endfor SetDataFolder root: Wave DMF=$BaseName+".dmf" Wave EOD=$BaseName+".eod" Wave RMS=$BaseName+".rms" NewPath/O/Q/M="Choose the folder where .eod, .dmf and .rms files will be saved." SavePath PathInfo/S SavePath efSaveSingleFloat32bit(EOD, DMF, RMS) End //------------------------------------------------------------ Function RemovePlayback() : GraphMarquee RemovePlaybackProc("") End //------------------------------------------------------------ Function SaveEODProc(ctrlName) : ButtonControl String ctrlName SetDataFolder root: GetWindow $WinName(0,1) note String Name=S_Value PathInfo/S SavePath String FilePath=S_path Wave W=$Name NVAR LoadWAVFiles=root:eFish:LoadWAVFiles String SaveName if(LoadWAVFiles) W*=32767 // Save EOD file if(stringmatch(Name[strlen(Name)-4], ".")) SaveName=Name SaveName[strlen(Name)-4]="pbr" Print SaveName endif string Platform = IgorInfo(2) // use when platform related issues arise if(stringmatch(Platform, "Macintosh")) Execute "SndSaveAIFF/B=16/I/Q "+PossiblyQuoteName(Name) +" as \""+FilePath+SaveName+"\"" else Execute "SaveWAVfile/B=16/O/I/Q "+PossiblyQuoteName(Name) + " as \""+FilePath+SaveName+"\"" endif else if(stringmatch(Name[strlen(Name)-4], ".")) SaveName=Name SaveName[strlen(Name)-4]="pbr" else SaveName=Name+"pbr.ibw" endif Duplicate/O $Name, Wave0 Save/C Wave0 as SaveName Killwaves/Z root:Wave0 endif End //--------------------------------------------------------- Function RemovePlaybackProc(ctrlName) : ButtonControl String ctrlName SetDataFolder root: GetWindow $WinName(0,1) note String Name=S_Value Wave Wav=$Name Wave PBWav=PBWav Variable leftXWavPnt, rightXWavPnt, EvenPoints Variable leftWavPnt, rightWavPnt // Get wave selection GetMarquee bottom if(V_Flag) Duplicate/O/R=(V_left, V_right) Wav, WavFFT else DoAlert 1, "You should really use a marquee selection over a few seconds where there are no chirps! Continue with the whole wave?" if(V_flag==2) return 0 endif Duplicate/O Wav, WavFFT endif leftXWavPnt=V_left; rightXWavPnt=V_right leftWavPnt=x2pnt(Wav, leftXWavPnt); rightWavPnt=x2pnt(Wav, rightXWavPnt) EvenPoints=2* floor(numpnts(WavFFT)/2) if(numpnts(WavFFT)!=EvenPoints) redimension/n = (EvenPoints) WavFFT // "Odd # of points in waveform. Last point deleted" endif FFT WavFFT Redimension/R WavFFT WavFFT = sqrt(magsqr(WavFFT)) WavFFT/=numpnts(WavFFT) WavFFT = 20*log(WavFFT/0.00002) WaveStats/Q WavFFT Variable PntsInAvgCycle=ceil( (1/DeltaX(Wav))/V_maxloc)+5 // Prompt for initial setting (can speed up search for optimum scaling factor) Variable InitialScaling=1, InitialPntShift=0 Prompt InitialScaling,"initial scaling factor (decimal)" Prompt InitialPntShift,"Points to shift playback wave (approx. phase)" DoPrompt "Initial playback wave scaling/shifting", InitialScaling, InitialPntShift // Get initial waves for setting initial conditions Duplicate/O/R=[leftWavPnt, rightWavPnt] Wav, WavTemp, AdjustedWav Duplicate/O/R=[leftWavPnt, rightWavPnt] PBWav, PBWavTemp // adjust initial values entered at user prompts PBWavTemp*=InitialScaling if(InitialPntShift>0) insertpoints 0, InitialPntShift, PBWavTemp else if(InitialPntShift<0) deletepoints 0, -InitialPntShift, PBWavTemp endif endif WaveStats/Q/R=[leftWavPnt, rightWavPnt] Wav Variable LastPP=V_max-V_min, MaxY=V_max, MinY=V_max-V_sdev Variable MaxIterations=5000, ScaleDirection=1, NumFlipFlops=0 Variable/G root:eFish:Scale=1.01, root:eFish:PhasePnt, root:eFish:Output NVAR Scale=root:eFish:Scale, PhasePnt=root:eFish:PhasePnt, Output=root:eFish:Output // determine if scaling needs to be adjusted up or down WaveStats/Q AdjustedWav LastPP=(V_max-V_min) Variable/g root:eFish:OriginalExcursion=LastPP PBWavTemp*=Scale AdjustedWav=WavTemp-PBWavTemp WaveStats/Q AdjustedWav if((V_max-V_min) < LastPP) //if scaling up reduces excursion ScaleDirection=1 else ScaleDirection=0 endif // Make display -- primarily for aesthetic reasons. DoWindow/K Calculating Display/K=1/W=(20,20,420,270) WavTemp as "Calculating" DoWindow/C Calculating AppendToGraph AdjustedWav ModifyGraph rgb(WavTemp)=(1,9611,39321),rgb(AdjustedWav)=(0,39321,0) SetAxis left, MinY, MaxY ControlBar 25 ValDisplay Scale win=Calculating, pos={10,5}, size={80,20},title=" Scale:",value=#root:eFish:Scale ValDisplay Phase win=Calculating, pos={100,5}, size={80,20},title="\"Phase\":",value=#root:eFish:PhasePnt ValDisplay Output win=Calculating, pos={200,5}, size={90,20},title="Result:", value=#root:eFish:Output ValDisplay Original win=Calculating, pos={300,5}, size={50,20},title="", value=#root:eFish:OriginalExcursion // Look for optimum number of points to skip (only way I know how to adjust "phase" without interpolating) Variable BestPnt=0, LowestExc=65536 for(PhasePnt=-PntsInAvgCycle;PhasePnt<=PntsInAvgCycle;PhasePnt+=1) // get new waves from Wav Duplicate/O/R=[leftWavPnt, rightWavPnt] Wav, WavTemp, AdjustedWav Duplicate/O/R=[leftWavPnt, rightWavPnt] PBWav, PBWavTemp // adjust initial values entered at user prompts PBWavTemp*=InitialScaling if(InitialPntShift>0) insertpoints 0, InitialPntShift, PBWavTemp else if(InitialPntShift<0) deletepoints 0, -InitialPntShift, PBWavTemp endif endif if(PhasePnt>0) insertpoints 0, PhasePnt, PBWavTemp else if(PhasePnt<0) deletepoints 0, -PhasePnt, PBWavTemp endif endif AdjustedWav=WavTemp-PBWavTemp WaveStats/Q AdjustedWav Output=(V_max-V_min) If( (V_max-V_min) < LowestExc) //if this excursion is smaller than any previous excursion LowestExc=(V_max-V_min) BestPnt=PhasePnt endif doupdate endfor PhasePnt=BestPnt // set PhasePnt (#in display) to the best point at end of loop // Update Wave with "phase shift" determined above -- this may also be for aesthetic purposes? Duplicate/O/R=[leftWavPnt, rightWavPnt] Wav, WavTemp, AdjustedWav Duplicate/O/R=[leftWavPnt, rightWavPnt] PBWav, PBWavTemp // adjust initial values entered at user prompts PBWavTemp*=InitialScaling if(InitialPntShift>0) insertpoints 0, InitialPntShift, PBWavTemp else if(InitialPntShift<0) deletepoints 0, -InitialPntShift, PBWavTemp endif endif if(BestPnt>0) insertpoints 0, BestPnt, PBWavTemp else if(BestPnt<0) deletepoints 0, -BestPnt, PBWavTemp endif endif // Look for optimum scaling factor Variable scaleAdj, i for(scaleAdj=0.01;scaleAdj>0.00001;scaleAdj/=10) if(ScaleDirection) Scale-=scaleAdj*10 else Scale+=scaleAdj*10 endif for(i=0;i<=MaxIterations;i+=1) // get new waves from Wav Duplicate/O/R=[leftWavPnt, rightWavPnt] Wav, WavTemp, AdjustedWav Duplicate/O/R=[leftWavPnt, rightWavPnt] PBWav, PBWavTemp PBWavTemp*=InitialScaling // initial scaling if(InitialPntShift>0) // initial phase shift insertpoints 0, InitialPntShift, PBWavTemp else if(InitialPntShift<0) deletepoints 0, -InitialPntShift, PBWavTemp endif endif if(BestPnt>0) // phase shift determined above insertpoints 0, BestPnt, PBWavTemp else if(BestPnt<0) deletepoints 0, -BestPnt, PBWavTemp endif endif // update on this iteration PBWavTemp*=Scale AdjustedWav=WavTemp-PBWavTemp WaveStats/Q AdjustedWav Output=(V_max-V_min) doupdate if((V_max-V_min) > LastPP) //if current scaling factor increases excursion NumFlipFlops+=1 if(ScaleDirection) ScaleDirection=0 else ScaleDirection=1 endif if(NumFlipFlops>=10) // shift slightly if(ScaleDirection) Scale-=scaleAdj/10 else Scale+=scaleAdj/10 endif //Print ">10 flip-flops" LastPP=(V_max-V_min) break // break if scaling direction flip-flops 10 times without breaking otherwise endif endif if(ScaleDirection) Scale+=scaleAdj//0.001 else Scale-=scaleAdj//0.001 endif if(abs(LastPP-(V_max-V_min))<=1 && scaleAdj==0.00001) // if close enough to last excursion +- 1 point LastPP=(V_max-V_min) break else LastPP=(V_max-V_min) endif endfor endfor doupdate // Ask if user want to apply values to the original playback wave? String AlertMessage SPrintF AlertMessage, "Apply %g scaling and shift by %g points?", Scale, BestPnt DoAlert 1, AlertMessage if(V_flag==1) // adjust initial values entered at user prompts PBWav*=InitialScaling PBWav*=Scale // adjust initial values entered at user prompts if(InitialPntShift>0) // initial phase shift insertpoints 0, InitialPntShift, PBWavTemp else if(InitialPntShift<0) deletepoints 0, -InitialPntShift, PBWavTemp endif endif if(BestPnt>0) insertpoints 0, BestPnt, PBWav else if(BestPnt<0) deletepoints 0, -BestPnt, PBWav endif endif Wav=Wav-PBWav endif DoWindow/K Calculating Killwaves root:AdjustedWav,root:WavTemp,root:PBWavTemp, root:WavFFT KillVariables root:eFish:Scale, root:eFish:PhasePnt End //------------------------------------------------------------ Function efPlotwPlayBack(ctrlName) : ButtonControl String ctrlName SVAR CurrFileName=root:eFish:CurrFileName String FileName=CurrFileName PathInfo/S LoadPAth String FilePath=S_path SVAR CurrFileName=root:eFish:CurrFileName NVAR LoadWAVFiles=root:eFish:LoadWAVFiles DoWindow/K EODPB if(LoadWAVFiles) // load file string Platform = IgorInfo(2) // use when platform related issues arise if(stringmatch(Platform, "Macintosh")) String/G gNameStr=FilePath+CurrFileName Print gNameStr Execute "SndLoadWave/O/Q WAVLoaded0, gNameStr" KillStrings gNameStr SVAR S_fileName=root:S_fileName if(strlen(S_fileName)<1) Killwaves WAVLoaded0 return 0 endif else String/G gNameStr=FilePath+CurrFileName Execute "LoadWAVfile/Q/C/F=0/A=WAVLoaded gNameStr" KillStrings gNameStr SVAR S_fileName=root:S_fileName if(strlen(S_fileName)<1) Killwaves WAVLoaded0 return 0 endif endif Wave WAVLoaded0=WAVLoaded0 if(wavetype(WAVLoaded0) %& 0x01) // if file is stereo (loaded as a complex wave) Make/W/O/N=(numpnts(WAVLoaded0)) PBWav copyscales WAVLoaded0, PBWav PBWav=imag(WAVLoaded0) Redimension/R PBWav Redimension/D PBWav // redimension wave to double precision floating point PBWav/=32767 SetScale d 0,0,"V", PBWav Redimension/R WAVLoaded0 // convert complex wave to real (i.e., remove imaginary part - remove right channel) else DoAlert 0, "File does not appear to be stereo (does not include a playback wave in the right channel)" return 0 endif Redimension/D WAVLoaded0 // redimension wave to double precision floating point SetScale d 0,0,"V", WAVLoaded0 SetScale/P x leftx(WAVLoaded0)*deltax(WAVLoaded0),deltax(WAVLoaded0),"sec", WAVLoaded0 WAVLoaded0/=32767 if(WaveExists($FileName)) killWaves/Z $FileName endif Rename WAVLoaded0, $FileName else FileName=efLoad_ibw_file(FilePath+CurrFileName) String StimWaveName=FileName[0,strlen(FileName)-4]+"stim" KillWaves/Z PBWav Rename $StimWaveName, PBWav endif DoWindow/K EODPB Display/K=1/W=(5,44,495,274) $FileName as FileName//"EOD and playback waves" DoWindow/C EODPB SetWindow EODPB note=FileName ;delayupdate SetWindow EODPB, hook=eFWindowEvent2;DelayUpdate AppendToGraph/L=leftPB PBWav ModifyGraph margin(left)=54 ModifyGraph rgb=(1,3,39321) ModifyGraph lblPos(left)=50,lblPos(leftPB)=50 ModifyGraph freePos(leftPB)={0,bottom} ModifyGraph axisEnab(left)={0.52,1} ModifyGraph axisEnab(leftPB)={0,0.48} ModifyGraph lowTrip(leftPB)=1 Label left "EOD (\\U)" Label bottom "time (\\U)" Label leftPB "playback (\\U)" ControlBar 30 Button Calculate pos={150,5},size={80,20},title="Calculate", proc=RemovePlaybackProc Button SaveEOD pos={250,5},size={80,20},title="Save EOD", proc=SaveEODProc return 0 End //------------------------------------------------------------ Function efGetFilesForSubtraction() CheckeFishGlobals() String ListOfFiles NVAR LoadWAVFiles=root:eFish:LoadWAVFiles Variable refNum String FilePathName, FileName, FilePath if(LoadWAVFiles) Open/D/R/M="Select one file to get list of files"/T=".wav" refNum if(strlen(S_fileName)<=0) return 0 endif FilePathName=S_fileName FileName = StringFromList(ItemsInList(FilePathName,":")-1, FilePathName, ":") FilePath=RemoveFromList(FileName, FilePathName, ":") NewPath/C/O/Q LoadPath, FilePath NewPath/C/O/Q SavePath, FilePath ListOfFiles = IndexedFile(LoadPath,-1,".wav") else Open/D/R/M="Select one file to get list of files"/T=".ibw" refNum if(strlen(S_fileName)<=0) return 0 endif FilePathName=S_fileName FileName = StringFromList(ItemsInList(FilePathName,":")-1, FilePathName, ":") FilePath=RemoveFromList(FileName, FilePathName, ":") NewPath/C/O/Q LoadPath, FilePath NewPath/C/O/Q SavePath, FilePath ListOfFiles = IndexedFile(LoadPath,-1,".ibw") Variable i String CurrStr for(i=0;i