Optimizing a motor position, while the MCA menu is active (P01)

Suppose the MCA widget is active and a motor position needs to be optimized regularily. The following script serves this purpose.

Here are some explanations. The tags, e.g. (1), can be found in the code.

 (1) The MCA toplevel widget is stored in $MCA::h{ w_top}. The Tk::Exists() function does what it says.
 (2) The symbol SIGNAL is evaluated to find a new maximum.
 (3) The function $MCA::h{ w_start}->invoke() acts, as if somebode pressed the Start button. Calling $MCA::h{ w_top}->update() updates the MCA widget (switches from Busy to Idle).
 (4) The loop over the motor positions.
 (5) This loop waits for wait_time seconds. The function Util::refresh() updates all Online -tki widgets and processes events. If the used pressed Stop, the symbol $Spectra::SYM{ flag_tki_stop} is set.

#!/bin/env perl
use Spectra; 
use Tk 800.000 ('Exists');
use strict; 

my $range = 0.002; 
my $np = 11;
my $mot = "exp_mot65"; 
my $delta = $range/($np - 1);  
my $wait_time = 10;

delete $Spectra::SYM{ flag_tki_stop}; 

my $flagWasBusy = 0; 
my $posOld = Spectra::gmup( $mot); 
my $status = 1;

Spectra::log( "McaOpt.pl: starting"); 

# (1)
# is the MCA menu active?
#
if( !Tk::Exists( $MCA::h{ w_top}))
{
	Spectra::error( "McaOpt.pl: MCA toplevel widget does not exist");
	goto finish;
}
# (2)
# we need the symbol signal (definition in exp_ini.exp):
# 
#   signal = [vfc(  EXP_C32,  EXP_T01,  0.1)]
#
if( !defined( $Spectra::SYM{ signal}))
{
	Spectra::error( "McaOpt.pl: symbol SIGNAl is not defined");
	$status = 0; 
	goto finish;	
}

#
# the loop
#
restart:
my $signalMax = -1;  
my $flagFoundMax = 0;
my $posMax = $posOld; 

# (3)
# w_start is a toggle widget
# 
if( $MCA::status_mca =~ /busy/i)
{
	Util::log("McaOpt.pl: pausing MCA operation"); 
	$MCA::h{ w_start}->invoke(); 
	$MCA::h{ w_top}->update();
	$MCA::h{ w_write}->invoke(); 		
	$flagWasBusy = 1;
}

# (4)
foreach my $i ( 0 .. $np)
{
	my $pos = $posOld - $range/2. + $i*$delta; 
	if( !Spectra::move( $mot => $pos))
	{
		Spectra::error(" McaOpt.pl: move was interrupted"); 
		$status = 0; 
		goto finish;
	}
	my $signal = Spectra::gra_decode_float( "signal");
	Util::log( "McaOpt.pl: pos $pos, signal $signal"); 
	if( $signal > $signalMax)
	{
		Util::log( "McaOpt.pl: new max signal at $pos, value $signal"); 
		$signalMax = $signal; 
		$posMax = $pos;
		$flagFoundMax = 1;
	}
}

if( $flagFoundMax)
{
	Spectra::log( "McaOpt.pl: moving to max $posMax"); 
	if( !Spectra::move( $mot => $posMax))
	{
		$status = 0; 
		goto finish;
	}
	my $signal = Spectra::gra_decode_float( "signal");
	Util::log( "McaOpt.pl: signal $signal"); 
}
else
{
	Spectra::log( "McaOpt.pl: no max found, moving to old position $posOld"); 
	if( !Spectra::move( $mot => $posOld))
	{
		$status = 0; 
		goto finish;
	}
}

if( $flagWasBusy)
{
	$MCA::h{ w_start}->invoke(); 
}

Util::log( "McaOpt.pl: waiting $wait_time s"); 

# (5)
for( my $t = 0; $t < $wait_time; $t += 0.5)
{
    select undef, undef, undef, 0.5;
    Util::refresh();
    if( $Spectra::SYM{ flag_tki_stop})
    {
		Util::log( "McaOpt.pl: interrupted, goto finish");
		goto finish;
    }
}

goto restart; 

finish:
Spectra::log( "McaOpt.pl: DONE"); 
	$status;