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.