#!/bin/sh  
# \
exec oagwish "$0" "$@"

#called by Bunch Purity Operation script (SRBPDSetup)

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSStandardSetup

set CVSRevisionAuthor "\$Revision: 1.2 $ \$Author: soliday $"

set args $argv
set mainDir /home/helios/oagData/sr/bunchPurity
set rootname ""
set runControlPV APS:RunControlSlot3RC
#automatical scan with 1 hour interval
set interval 1
set help 0
set usage {usage: BunchPurityAutoScan -mainDir <string> -interval <hours> -rootname <string> -runControlPV <pvname> -help <0|1>}
APSParseArguments {mainDir interval runControlPV rootname help}

if $help {
    puts stderr $usage
    exit
}
if {![string length $rootname] || ![string length $mainDir] || ![string length $runControlPV] \
      || !$interval } {
    puts stderr "Wrong Arguments passed:\n$usage\n"
    exit
}

wm withdraw .
APSSCRDefineVariables
proc CheckRunControlStatus {args} {
    global runControlPV AutoScanRunning
    if [catch {exec cavget -list=$runControlPV.RUN -pend=10} AutoScanRunning] {
        return -code error "Problem in getting runcontrol $runControlPV status: $running"
    } 
    if  {$AutoScanRunning=="?"} {
        return -code error "Channel Access error in getting runcontrol $runControlPV status"
    }
}
proc ShutdownSystem {args} {
    set description "Unknown"
    APSStrictParseArguments {description}
    
    global runControlPV
    catch {APSRunControlExit}
    bell
   # puts stderr "Bunch purity scan aborted!"
    if [catch {exec cavput -list=$runControlPV.ABRT=1 -blunderAhead} result] {
      return -code error $result
    }
    after 2000
}

proc PingRunControl {args} {
    global runControlPV
    catch {APSRunControlPing} status
    switch $status {
        RUNCONTROL_OK {}
        RUNCONTROL_ABORT {
            return -code error "Auto-scan is aborted."
        }
        RUNCONTROL_TIMEOUT -
        RUNCONTROL_ERROR {
            return -code err "Unable to ping runcontrol record of $runControlPV: $status."
        }
    }
}
proc MoveDetectorMotor {args} {
    set xDetector 45
    set yDetector 25
    set retries 80
    set tolerance 0.01
    set timeout 10
    APSStrictParseArguments {xDetector yDetector tolerance retries timeout}
    
    puts stderr "Moving the detector to (x = $xDetector mm, y= $yDetector mm) ..."
    
    if [catch {exec cavput -list=S36AM:BP:APDxMT.VAL=$xDetector,S36AM:BP:APDyMT.VAL=$yDetector \
                 -pend=30} result] {
        return -code error $result
    }
    while {$retries>0} {
        set stoptime [expr [clock seconds] + 1]
        while {[clock seconds]<$stoptime} {
            if [catch {PingRunControl} result] {
                return -code error $result
            }
        }
        if [catch {exec cavget -list=S36AM:BP:APD -list=x,y -list=MT.DMOV -pend=30} statusList] {
            return -code error $statusList
        }
        set xStatus [lindex $statusList 0]
        set yStatus [lindex $statusList 1]
        if {($xStatus == 1) && ($yStatus == 1)} {return}
        incr retries -1
    }
    if [catch {exec cavget -list=S36AM:BP:APD -list=x,y -list=MT.DMOV -pend=30} statusList] {
        return -code error $statusList
    }
    set xStatus [lindex $statusList 0]
    set yStatus [lindex $statusList 1]
    if {($xStatus == 1) && ($yStatus == 1)} {return}
    return -code error "Dector motors are not the correct position yet! Abort auto-scan ..."
}

proc OpenShutters {args} {
    if [catch {exec cavput -list=S35ID:PS2OpenC.VAL=1 -pend=30} result] {
        return -code error $result
    }
    # Watch shutter status
    for {set istep 1} {$istep <= 6} {incr istep} {
        set timeout [expr [clock seconds]+1]
        while {[clock seconds]<$timeout} {
            if [catch {PingRunControl} result] {
                return -code error "Error occurred during opening shutters: $result"
            }
        }
        if [catch {exec cavget -list=EPS:35:ID:PS2:POSITION -pend=30} ps2Status] {
            return -code error $ps2Status
        }
    	if {$ps2Status == "Open"} {
            return 0
    	}
    }
    if [catch {exec cavget -list=EPS:35:ID:PS2:POSITION -pend=30} ps2Status] {
        return -code error $ps2Status
    }
    if {$ps2Status != "Open"} {
        return -code error "Can not open Shutters (PS2/SS), abort auto-scan..."
    }
}

proc CloseShutters {args} {
    
    if [catch {exec cavput -list=S35ID:PS2CloseC.VAL=1 -pend=30} result] {
        return -code error $result
    }
    for {set istep 1} {$istep <= 6} {incr istep} {
        set timeout [expr [clock seconds]+1]
        while {[clock seconds]<$timeout} {
            if [catch {PingRunControl} result] {
                return -code error "Error occurred during closing shutters: $result"
            }
        }
        if [catch {exec cavget -list=EPS:35:ID:PS2:POSITION -pend=30} ps2Status] {
            return -code error $ps2Status
        }
    	if {$ps2Status == "Closed"} {
            return
    	}
    }
    if [catch {exec cavget -list=EPS:35:ID:PS2:POSITION -pend=30} ps2Status] {
        return -code error $ps2Status
    }
    if {$ps2Status != "Closed"} {
        return -code error "Shutters can not be closed, abort auto-scan..."
    }
}

proc StartMCA {args} {
    #wait for 350 seconds
    # start Multi-Channel Analyzer
    if [catch {exec cavput -list=S36AM:BP:scaler.CONT=1,S36AM:BP:mcaStart.VAL=0,S36AM:BP:mca.ERAS=1,S36AM:BP:mca.STRT=1 -pend=30} result] {
        return -code error $result
    }
    
    if [catch {exec cavget -list=S36AM:BP:mca.PLTM -pend=30} livetimeSet] {
	return -code error $livetimeSet
    }
    puts stderr "taking data (wait for $livetimeSet seconds)..."
    while { 1 } {
        if [catch {PingRunControl} result] {
            return -code error "Error occurred during acquring waveform data: $result"
        }
	if [catch {exec cavget -list=S36AM:BP:mca.ELTM -pend=30} livetime] {
	    return -code error $livetime
	}
	if {$livetime==$livetimeSet} {break}
        set timeout [expr [clock seconds] +1]
        while {[clock seconds]<$timeout} {
            if [catch {PingRunControl} result] {
                return -code error "Error occurred during acquring waveform data: $result"
            }
        }
    }
}

proc StartAutoScan {} {
    global runControlPV AutoScanRunning apsRunControlInitialized rootname
    set AutoScanRunning 0
    #1. check if auto-scan is running
    if [catch {CheckRunControlStatus} result] {
        return -code error "BunchPuriytAutoScan can not start: $result"
    }
    if $AutoScanRunning {
        set answer [APSMultipleChoice [APSUniqueName .] \
                      -question "Bunch purity auto-scan has been started, Kill and Continue or quit to check the auto-scan control?" -returnList {Kill-And-Contiune Quit} \
                      -labelList {Kill-And-Continue Quit} ]
        if {$answer=="Quit"} {
            puts stderr "Bunch purity auto-scan has been started, current auto-scan quited."
            exit
        }
        #abort runcontrol
        ShutdownSystem
    }
    #2. initialize new run-control
    set apsRunControlInitialized 0
    bell
    bell
    #clear runcontrol record
    if [catch {exec cavput -list=$runControlPV.CLR=1 -pend=10} result] {
        return -code error $result
    }
    if [catch {APSRunControlInit -pv $runControlPV \
                 -description "Bunch Purity Auto Scan" \
                 -timeout 6000} result] {
        return -code error "Unable to initialize runcontrol for auto-scan, the record may not be cleared, press clear button in the medm screen to clear the record and restart: $result"
    }
    if [catch {exec cavput "-list=$runControlPV.MSG=rootname: $rootname" -pend=10} result] {
        return -code error $result
    }
    #3. move detector motors
   # if [catch {MoveDetectorMotor} result] {
   #     return -code error $result
  #  }
}

proc CheckDetectorPosition {args} {
    set tolerance 0.01
    set xDetector 45
    set yDetector 25
    APSParseArguments {tolerance xDetector yDetector} 
    
    set setValues [list $xDetector $yDetector]
    
    if [catch {exec cavget -list=S36AM:BP:APD -list=x,y -list=MT.RBV -pend=30} readbackValues] {
        return -code error $readbackValues
    }
    foreach set $setValues readback $readbackValues {
        if {$readback=="?"} {
            return -code error "Unable to read detector positions!"
        }
        set diff [expr abs($set-$readback)]
        if {$diff>$tolerance} {
            return -code error "The detector motors are not in the desired position!"
        }
    }
}


#this procedure only read the waveforms and writes to a file
proc SaveData {args} {
    global mainDir rootname interval timeout
    set timeout [expr [clock seconds] + $interval*3600]
    set directory $mainDir/[clock format [clock seconds] -format "%Y-%m%d"]
    if ![file exist $directory] {
        exec mkdir $directory
        #exec setfacl -m mask:rwx $directory
        #exec setFACL-oagPlus emery,borland,shang,oag,bxyang,sr,asdops $directory
    }
    set file ${rootname}-[clock format [clock seconds] -format %Y-%m%d.%H:%M:%S]
    set tmpfile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID 1 -fileList $tmpfile
    if [catch {exec sddswmonitor $tmpfile -pv=S36AM:BP:mca.VAL} result] {
        return -code error"Error in reading waveform data: $result\nAuto-scan is aborted"
    }
    if [catch {exec sddsprocess $tmpfile $directory/$file \
                 -process=S36AM:BP:mca.VAL,max,S36AM:BP:mca.VAL_Max \
                 "-define=col,S36AM:BP:mca.VALNorm,S36AM:BP:mca.VAL S36AM:BP:mca.VAL_Max 1e-6 + /" } result] {
        return -code error "Error in processing data file: $result"
    }
    exec chmod a+w $directory/$file
    bell
    puts stderr "Data saved in $directory/$file"
}
proc TakeData {args} {
    global mainDir rootname
    
    #1. check if shutter is open
    if [catch {exec cavget -list=EPS:35:ID:PS2:POSITION -pend=10} result] {
        return -code error $result
    }
    if [string compare $result "Open"] {
        APSSound -type alert -volume 100 -iterations 3
        return -code error "The shutter is not open, please check the status and start auto-scan again."
        set answer [APSMultipleChoice [APSUniqueName .] \
                      -question "Shutter is not open, open it and continue taking data or quit?" \
                      -returnList {Open-And-Contiune Quit} \
                      -labelList {open-And-Continue Quit} ]
        switch $answer {
            Quit {
                return -code error "The shutter is not open, quit auto-scan!"
            }
            Open-And-Continue {
                puts stderr "Open shutters ..."
                if [catch {OpenShutters} result] {
                    return -code error $result
                }
            }
        }
    }
    #2. move motor in
    puts stderr "Move dector in ..."
    if [catch {MoveDetectorMotor -xDetector 45 -yDetector 25} result] {
        return -code error $result
    }
    #3. check motor position
    puts stderr "check dectector position..."
    if [catch {CheckDetectorPosition -xDetector 45 -yDetector 25} result] {
        return -code error $result
    }
    
    #4. start mca
    puts stderr "start MCA and acquire waveform ..."
    if [catch {StartMCA} result] {
        return -code error $result
    }
    #5.save data to file
    puts stderr "Writing to file ..."
    if [catch {SaveData} result] {
        return -code error $result
    }
    #6. move detector out
    puts stderr "Move detector out..."
    if [catch {MoveDetectorMotor -xDetector 0 -yDetector 0} result] {
        return -code error $result
    }
    # check motor position
    puts stderr "check dectector position..."
    if [catch {CheckDetectorPosition -xDetector 0 -yDetector 0} result] {
        return -code error $result
    }
}

#execution starts here

puts stderr "Start auto-scan ..."
if [catch {StartAutoScan} result] {
    puts stderr "Can not start auto-scan: $result"
    ShutdownSystem
    exit
}
puts stderr "Taking data ..."
while {1} {
    if [catch {PingRunControl} result] {
        puts stderr $result
        exit
    }
    #set timeout [expr [clock seconds] + $interval*3600]
    if [catch {TakeData} result] {
        puts stderr $result
        #abort runcontrol
        #APSAbortSRControllaw -runControlPV $runControlPV
        #exec cawait -waitfor=$runControlPV.RUN,equal=0
        ShutdownSystem
        exit
    }
    #wait for an interval before starting next data-taking
    
    while {[clock seconds]<$timeout} {
        if [catch {PingRunControl} result] {
            puts stderr $result
            exit
        }
    }
    puts stderr "\n starts a new run..."
}

exit
