
proc APSMpxPTBMatrixInfo {} {
    return "This procedure measures the PTB response matrix in the horizontal plane, calculates the inverse matrix, and gives the user a choice to install this inverse matrix as the matrix for the xPTB controllaw."
}

proc APSMpxPTBMatrix {args} {
    global status

    APSStrictParseArguments {}

# the final result (.def and inverse matrix file) go in the resultsDir
# the temporary results go the dataDir.
    set resultsDir /home/helios/oagData/controllaw/PTB/PTBonly
    set dataDir $resultsDir/measurement
    set installName xPTB.matrix
    set beamline PTB
    set beamlineFile $dataDir/${beamline}.beamline
    set plane H
    set matrix R12
    set templateFile $dataDir/${beamline}:${plane}Template.exp
    set actuatorList {}
    # default for filterColumns in procedure formMatrix is "*:*P*"
    set filterColumns "$beamline:*P${plane}*"

    cd $dataDir

    # Setting up experiment parameters
    set halfRange 1.0
    set points 5
    set postChange 2.5
    set intermeasurement 0.5
    set average 25
    set checkResults 1
    set promptExperiments 0
    set useSeptum None
    set useCorrectors 1

    APSMpStep init -promptDialog APSMpxPTBMatrixInitDialog -vars {halfRange points postChange intermeasurement average checkResults filterColumns promptExperiments useSeptum useCorrectors}

    set paramString ""
    foreach param {halfRange points postChange intermeasurement average checkResults filterColumns promptExperiments useSeptum useCorrectors} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction \
             -procedure APSMpxPTBMatrix \
             -action initialize \
             -state ok \
             -parameters $paramString}

    if $useCorrectors {
        set corrList {H1 H2 H3 H4}
        eval lappend actuatorList [APSAffix $corrList -prefix ${beamline}:]
    }
    if ![llength $actuatorList] {
        APSMpReturn error "No actuators chosen"
    }

    # this procedure establishes some default variables and arrays for parameters.
    set parameterList {PV halfRange points postChange intermeasurement average}
    APSMpRespMatrixSetParameterDefaults \
      -parameterList $parameterList \
      -halfRange $halfRange \
      -points $points \
      -postChange $postChange \
      -intermeasurement $intermeasurement \
      -average $average
    foreach actuator $actuatorList {
        if {[lsearch -exact [list B:ES2 B:ES1] $actuator]!=-1} {
            # this procedure must be preceded by APSMpRespMatrixSetParameterDefaults
            # in order for the arguments to be recognized.
            APSMpRespMatrixSetActuatorParameters \
              -actuator $actuator \
              -PV ${actuator}:VoltageSetSendAO \
              -halfRange 2.5 
        } else {
            APSMpRespMatrixSetActuatorParameters \
              -actuator $actuator \
              -PV ${actuator}:CurrentAO 
        }
    }
    #  bad equipment to remove from lists
    set badActuators ""
    set badBpms ""

    # put pre-execution commands here
    # such as reseting the time-outs for the pulsed magnets.
    APSMpStep PreExecutionCommands

    # take data
    APSMpStep SDDSExperimentCommands
    # send a list of one actuator at a time so that the data can be reviewed
    # and restarted at every step
    foreach actuator $actuatorList {
        if {!$promptExperiments || [APSYesNoPopUp "Do experiment on $actuator"]} {
            lappend actuatorUsedList $actuator
            set repeatExpt 1
            while {$repeatExpt} {
                APSMpRespMatrixDoExperiment -actuatorList $actuator -templateFile $templateFile
                catch {eval exec rm [glob *~]}
                set repeatExpt 0
                if $checkResults {
                    eval exec sddsplot -col=$actuator,(*) $actuator.sdds \
                      -grap=sym,conn,sca=3 -sep &
                    if {[APSYesNoPopUp "Retake data? (wait for plot to appear)"]} {
                        APSMpRespMatrixSetActuatorParametersByDialog .dialog -actuator $actuator
                        set repeatExpt 1
                    }
                }
            }
        }
    }
    
    # put post-execution commands here
    APSMpStep PostExecutionCommands

    APSMpStep CombiningResults
    set fileList [eval glob [APSAffix $actuatorUsedList -suffix .def]]
    catch {eval exec sddscombine $fileList -pipe=output -merge -overWrite \
             | sddssort -pipe=input ${beamline}.${plane}.def -col=ControlName  -unique}
    catch {eval exec rm $fileList}
    
    APSMpStep CalculatingSlopes -proc "APSMpRespMatrixCalcSlopes"
    APSMpRespMatrixCalcSlopes -actuatorList $actuatorUsedList 

    APSMpStep FormingMatrix -proc "APSMpRespMatrixFormMatrix"
    APSMpRespMatrixFormMatrix -actuatorList $actuatorUsedList -badBpms $badBpms \
      -badActuators $badActuators \
      -outFile ${beamline}.${matrix} -beamlineFile $beamlineFile -filterColumns $filterColumns

    APSMpStep CalculatingInverse -proc "CalculatingInverse"
    APSMpRespMatrixCalcInverse -inFile ${beamline}.${matrix} -outFile ${beamline}.Inv${matrix} -minimum 0.1

    APSMpStep InstallMatrix -proc "InstallMatrix"
    APSMpRespMatrixInstallDialog .install -fileName ${beamline}.Inv${matrix} \
      -installName $installName -installDir $resultsDir

    APSMpReturn ok
}


# Note: by convention, this procedure has only one argument. It provides the
#    parent frame into which you should pack all widgets.
proc    APSMpxPTBMatrixInitDialog {frame} {
  # Note: this dialog procedure has access only to those variables explicitly
  #    passed in via the -vars option of APSMpStep. You can access them here
  #    as elements of the following global array (which always has the same
  #    name as the machine procedure itself.
  global APSMpxPTBMatrix
  label $frame.label -text "Enter default values for sddsexperiment"
  pack $frame.label
  APSLabeledEntry .le1 -parent $frame -label "half range" -textVariable \
    APSMpxPTBMatrix(halfRange)
  APSLabeledEntry .le2 -parent $frame -label "no. points" -textVariable \
    APSMpxPTBMatrix(points)
  APSLabeledEntry .le3 -parent $frame -label "post change pause" -textVariable \
    APSMpxPTBMatrix(postChange)
  APSLabeledEntry .le4a -parent $frame -label "filter for bpm names" -textVariable \
    APSMpxPTBMatrix(filterColumns)
  APSLabeledEntry .le4b -parent $frame -label "intermeasurement pause" -textVariable \
    APSMpxPTBMatrix(intermeasurement)
  APSLabeledEntry .le5 -parent $frame -label "no. average" -textVariable \
    APSMpxPTBMatrix(average)
  APSRadioButtonFrame .rb6 -parent $frame -label "Prompt for each experiment?" \
    -variable APSMpxPTBMatrix(promptExperiments) -buttonList {Yes No} -valueList {1 0} \
    -orientation horizontal 
  APSRadioButtonFrame .rb7 -parent $frame -label "Check results?" -variable \
    APSMpxPTBMatrix(checkResults) -buttonList {Yes No} -valueList {1 0} \
    -orientation horizontal 
  APSRadioButtonFrame .rb8 -parent $frame -label "Use correctors: " -variable \
    APSMpxPTBMatrix(useCorrectors) -buttonList {Yes No} -valueList {1 0} \
    -orientation horizontal
}

proc APSMpyPTBMatrixInfo {} {
    return "This procedure measures the PTB response matrix in the vertical plane, calculates the inverse matrix, and gives the user a choice to install this inverse matrix as the matrix for the yPTB controllaw."
}

proc APSMpyPTBMatrix {args} {
    global status

    APSStrictParseArguments {}

    # the final result (.def and inverse matrix file) go in the resultsDir
    # the temporary results go the dataDir.
    set resultsDir /home/helios/oagData/controllaw/PTB/PTBonly
    set dataDir $resultsDir/measurement
    set installName yPTB.matrix
    set beamline PTB
    set beamlineFile $dataDir/${beamline}.beamline
    set plane V
    set matrix R34
    set templateFile $dataDir/${beamline}:${plane}Template.exp
    set actuatorList {V2 V3 V4}
    set actuatorList [APSAffix $actuatorList -prefix ${beamline}:]
    # default for filterColumns in procedure formMatrix is "*:*P*"
    set filterColumns "$beamline:*P${plane}*"

    cd $dataDir

    # Setting up experiment parameters
    set halfRange 1.0
    set points 5
    set postChange 2.5
    set intermeasurement 0.5
    set average 25
    set checkResults 1
    set promptExperiments 0
    APSMpStep init -promptDialog APSMpyPTBMatrixInitDialog -vars {halfRange points postChange intermeasurement average checkResults filterColumns promptExperiments}

    set paramString ""
    foreach param {halfRange points postChange intermeasurement average checkResults filterColumns promptExperiments} {
        append paramString "$param=\"[set $param]\" "
    }
    catch {APSLogScriptAction \
             -procedure APSMpyPTBMatrix \
             -action initialize \
             -state ok \
             -parameters $paramString}

# this procedure establishes some default variables and arrays for parameters.
    set parameterList {PV halfRange points postChange intermeasurement average}
    APSMpRespMatrixSetParameterDefaults \
      -parameterList $parameterList \
      -halfRange $halfRange \
      -points $points \
      -postChange $postChange \
      -intermeasurement $intermeasurement \
      -average $average
    foreach actuator $actuatorList {
# this procedure must be preceded by APSMpRespMatrixSetParameterDefaults
# in order for the arguments to be recognized.
        APSMpRespMatrixSetActuatorParameters \
          -actuator $actuator \
          -PV ${actuator}:CurrentAO 
    }
    #  bad equipment to remove from lists
    set badActuators ""
    set badBpms ""

    # put pre-execution commands here
    # such as reseting the time-outs for the pulsed magnets.
    APSMpStep PreExecutionCommands

    # take data
    APSMpStep SDDSExperimentCommands
    # send a list of one actuator at a time so that the data can be reviewed
    # and restarted at every step
    foreach actuator $actuatorList {
        if {!$promptExperiments || [APSYesNoPopUp "Do experiment on $actuator"]} {
            set repeatExpt 1
            while {$repeatExpt} {
                lappend actuatorUsedList $actuator
                set repeatExpt 0
                APSMpRespMatrixDoExperiment -actuatorList $actuator -templateFile $templateFile
                catch {eval exec rm [glob *~]}
                if $checkResults {
                    eval exec sddsplot -col=$actuator,(*) $actuator.sdds \
                      -grap=sym,conn,sca=3 -sep &
                    if {[APSYesNoPopUp "Retake data? (wait for plot to appear)"]} {
                        APSMpRespMatrixSetActuatorParametersByDialog .dialog -actuator $actuator
                        set repeatExpt 1
                    }
                }
            }
        }
    }
    
    # put post-execution commands here
    APSMpStep PostExecutionCommands

    APSMpStep CombiningResults
    set fileList [eval glob [APSAffix $actuatorUsedList -suffix .def]]
    catch {eval exec sddscombine $fileList -pipe=output -merge -overWrite \
             | sddssort -pipe=input ${beamline}.${plane}.def -col=ControlName  -unique }
    catch {eval exec rm $fileList}

    APSMpStep CalculatingSlopes -proc "APSMpRespMatrixCalcSlopes"
    APSMpRespMatrixCalcSlopes -actuatorList $actuatorUsedList 

    APSMpStep FormingMatrix -proc "APSMpRespMatrixFormMatrix"
    APSMpRespMatrixFormMatrix -actuatorList $actuatorUsedList \
      -badBpms $badBpms -badActuators $badActuators \
      -outFile ${beamline}.${matrix} -beamlineFile $beamlineFile -filterColumns $filterColumns

    APSMpStep CalculatingInverse -proc "APSMpRespMatrixCalcInverse"
    APSMpRespMatrixCalcInverse -inFile ${beamline}.${matrix} -outFile ${beamline}.Inv${matrix} -minimum 0.1

    APSMpStep InstallMatrix -proc "APSMpRespMatrixInstallDialog"
    APSMpRespMatrixInstallDialog .install -fileName ${beamline}.Inv${matrix} \
      -installName $installName -installDir $resultsDir

    APSMpReturn ok
}


# Note: by convention, this procedure has only one argument. It provides the
#    parent frame into which you should pack all widgets.
proc    APSMpyPTBMatrixInitDialog {frame} {
  # Note: this dialog procedure has access only to those variables explicitly
  #    passed in via the -vars option of APSMpStep. You can access them here
  #    as elements of the following global array (which always has the same
  #    name as the machine procedure itself.
  global APSMpyPTBMatrix
  label $frame.label -text "Enter default values for sddsexperiment"
  pack $frame.label
  APSLabeledEntry .le1 -parent $frame -label "half range" -textVariable \
    APSMpyPTBMatrix(halfRange)
  APSLabeledEntry .le2 -parent $frame -label "no. points" -textVariable \
    APSMpyPTBMatrix(points)
  APSLabeledEntry .le3 -parent $frame -label "post change pause" -textVariable \
    APSMpyPTBMatrix(postChange)
  APSLabeledEntry .le4a -parent $frame -label "filter for bpm names" -textVariable \
    APSMpyPTBMatrix(filterColumns)
  APSLabeledEntry .le4b -parent $frame -label "intermeasurement pause" -textVariable \
    APSMpyPTBMatrix(intermeasurement)
  APSLabeledEntry .le5 -parent $frame -label "no. average" -textVariable \
    APSMpyPTBMatrix(average)
  APSRadioButtonFrame .rb6 -parent $frame -label "Prompt for each experiment?" \
    -variable APSMpyPTBMatrix(promptExperiments) -buttonList {Yes No} -valueList {1 0} \
    -orientation horizontal 
  APSRadioButtonFrame .rb7 -parent $frame -label "Check results?" -variable \
    APSMpyPTBMatrix(checkResults) -buttonList {Yes No} -valueList {1 0} \
    -orientation horizontal 
}
