Missing abort button (Ctrl-C didn't work either) when running a for loop

Hi,

I implemented a looping function includes some Igor function and some XOPs. The purpose is to digitize a signal for a given amount of time, repeat it for N times and average them. I was glad to finally have everything working together, but then I realized that the abort button (bottom right of Igor Pro 8 main window) didn't show up. I also tried Ctrl-C and it didn't stop the routine either.

It will be important to be able to stop it as sometimes with an error we could have made a loop too long. What could be the cause?
The code is rather long and includes lots of subroutines that uses XOP and hardware, I would like to post the useful parts if any of them may indicate something, please kindly let me know.

Thanks in advance.

Attached is the main routine for ref (some trimming applied):

Function UpdateButtonMPVTProc(ba) : ButtonControl
	STRUCT WMButtonAction &ba

	
	switch( ba.eventCode )
		case 2: // mouse up
			string cfolder,path
			cfolder = GetDataFolder(1)			//store the current data folder
	
	
			variable AVG_POW = 1  //Set this variable to 1 if you want to average the Power directly in addition to average the quadratures.
			
			path = "root:panels:"
			SetDataFolder $path
			SVAR ActivePanel
			if (!(stringmatch(ActivePanel,"MagPhaseVsTime")))
				ActivateMPVT()
			endif
			
			path = "root:panels:MagPhaseVsTime:"
			SetDataFolder $path
			SVAR SGname,DIGname
			NVAR SampPerSeg,NumSeg,NumTrig,NumSamples,Division,Smoothing,AutoSave,RepFreq
		
			//S: no longer used, DIGid is a software id now.
			NVAR SGid,DIGid,SampFreq
	
			path = "root:panels:MagPhaseVsTime:"
			SetDataFolder $path
	
			variable check_freq,error
			//make sure the sampling frequency is correct
			//S: Now we simply abort the routine if this fails, as we should not arbitarily modify the SampFreq
			SampFreq = RepFreq*SampPerSeg
			check_freq = DigitizerGet(DIGid,DIG_IF_FS)
			if (abs(SampFreq-check_freq) > 1)
				abort "Measurement sampling frequency does not equal instrument's sampling frequency."
			endif
			Button/z UpdateButtonMPVT,title="Running",win = MagPhaseVsTime
		
			//S: about waves handling, note that the raw data should anyway first go to the GageRM instrument folder; 
			//only the final I/Q data should be transferred to the measurement folder. These final IQ data should be the input wave
			//for the GPU DDC function to avoid the need of copying them around.
	
			Make/N=(NumSamples)/O Idata,Qdata			// Create wave of the right length (filled with zeros)
			Make/N=(SampPerSeg)/O Im,Qm,Iavg=0,Qavg=0,mag,phase	
			SetScale/p x 0,(1/SampFreq),"s", mag,phase				// Set the scale to seconds
			// arm trigger and capture first set of data
			
			if (AVG_POW)
				Make/N=(NumSamples)/O PowData
				Make/N=(SampPerSeg)/O Powm,PowAvg=0
				SetScale/p x 0,(1/SampFreq),"s", PowData,Powm,PowAvg		
			endif

			//S: Now level correct is a constant given by what one wants. If one wants the voltage to appear in I/Q, applies only the VoltLevelCorrect;
			//If one wants to follow the old convention of PXI, applies both (sum them in log scale) 			
			variable LevelCorrect = 10*log(GageRM_DDC_VoltLevelCorrect)+GageRM_DDC_PowerLevelCorrect
//			LevelCorrect = DigitizerGet(DIGid,DIG_LEVEL_CORRECT)
			LevelCorrect = 10^(LevelCorrect/10)  //convert level correct from dBm correction to Watts correction
			
			//Due to the passivity of PXDAC, now it should be reset before any arming routine of the digitizers
			if(stringmatch(whichInstrument(SGid),"PXDAC"))
				PXDAC_Reset(whichInstrument(SGid))
				endif
			
			error = DigitizerTrigger(DIGid,DIG_TRIG_ARM,NumSamples)
//			if (error)
//				print "Digitizer Trigger arm failed"
//				print DigitizerError(DIGid)
//			endif
			
			variable Time1,Time2
			variable m,n,CaptComp
			for (m=1;m<=NumTrig;m+=1)				//This loop covers the number of triggers
				
				Button/z UpdateButtonMPVT,title=num2str(m),win = MagPhaseVsTime
				
				//This loop checks that the dig capture is complete before looping back to where the mu freq is changed.
				do
					CaptComp = DigitizerGet(DIGid,DIG_CAPT_COMPLETE)
					if (!CaptComp)
						WaitTicks(5)
					endif
				while (!CaptComp)
				
				//Time1 = stopMStimer(-2)
				
				//S: Here the deal, we need to split the old DigitizerCapture function into two parts, as now 1. the data transfer from digitizer to host is done as the capture finishes
				//2. The anaylysis routine should include the data processing part by the GPU in order to better overlap the capture time and processing time
				//I am keeping the DigitizerCapture as the function name for use with GPU-host transfer/analysis, and a new function called DigitizerTransfer is made.
				
				//S: This function will now assume the capture has finished, and it will attempt to transfer the data located in the digitizer back to the host memory.
				DigitizerTransfer(DIGid)
				

				
				if (m<NumTrig)	// arm trigger and start capture of next data while we process the last
					//Due to the passivity of PXDAC, now it should be reset before any arming routine of the digitizers
					if(stringmatch(whichInstrument(SGid),"PXDAC"))
						PXDAC_Reset(whichInstrument(SGid))
						endif

				endif
				
				//DIG_GPU_DDC means using GPU to perform the DDC
				error = DigitizerCapture(DIGid,DIG_GPU_DDC,Idata,Qdata)

				DigitizerFold(Im,Idata)
				DigitizerFold(Qm,Qdata)
				
				
				// Average different triggers and compute mag and phase
				FastOp Iavg = ((m-1)/m)*Iavg+(1/m)*Im
				FastOp Qavg = ((m-1)/m)*Qavg+(1/m)*Qm
			 	mag = sqrt(Iavg^2+Qavg^2)
			 	phase = atan2(Qavg,Iavg)*180/pi
			 	Duplicate/O mag,mag_smth
			 	Duplicate/O phase,phase_smth
			 	if (Smoothing > 0)
			 		Smooth (Smoothing), mag_smth,phase_smth
			 	endif
			 	
			 	if (AVG_POW)
					//FastOP PowData = Idata*Idata + Qdata*Qdata
					FastOP PowData = (LevelCorrect)*Idata*Idata + (LevelCorrect)*Qdata*Qdata
					DigitizerFold(Powm,PowData)
					FastOp PowAvg = ((m-1)/m)*PowAvg+(1/m)*Powm
					Duplicate/O PowAvg,Pow_smth
					if (Smoothing > 0)
			 			Smooth (Smoothing), Pow_smth
			 		endif
			 		
				endif
				
				//print SqeezingFigure(Idata,Qdata)
			 	
			 	DoUpdate
			endfor

		
			Button/z UpdateButtonMPVT,title="Update",win = MagPhaseVsTime
			
			
			
			SetDataFolder $cfolder			//restore the data folder
			break
	endswitch

	return 0
End

 

Strangely, it comes back after I have restarted Igor. The button still appear/disappears, but if I click there it works to stop the loop. A bit intermittent at the moment.

Igor has a delay between when you start the function and when the Abort button is displayed. Under some circumstances, that delay is set pretty long. I think one such circumstance is a button action procedure- that is because at the same time that the Abort button is shown, the beachball cursor is also shown, and that's usually annoying with a control action.

In Igor 8, I made it possible to abort using the keyboard even before the Abort button is displayed. But the keys for aborting are not Ctrl+C. You have a choice of Shift+Esc or Ctrl+Break. Break is also sometimes called Pause. Those key combinations should abort your function more or less immediately.

In reply to by johnweeks

johnweeks wrote:

Igor has a delay between when you start the function and when the Abort button is displayed. Under some circumstances, that delay is set pretty long. I think one such circumstance is a button action procedure- that is because at the same time that the Abort button is shown, the beachball cursor is also shown, and that's usually annoying with a control action.

In Igor 8, I made it possible to abort using the keyboard even before the Abort button is displayed. But the keys for aborting are not Ctrl+C. You have a choice of Shift+Esc or Ctrl+Break. Break is also sometimes called Pause. Those key combinations should abort your function more or less immediately.

 

Thanks, it works now to abort with Shift+Esc, even when the abort button is not shown.