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

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)]
APSDebugPath

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

set IDSector 1
set IDSelectionChanged 0
set minDCCT 98
set maxDCCT 100
set userBeamModeOnly 1
set planesToPlot xy
set minGap 0
set maxGap 50
set gapToFilterOn DS

proc APSLoadFileCacheTable {args} {
    set fileName ""
    set arrayRoot ""
    APSStrictParseArguments {fileName arrayRoot} 
    if {![string length $fileName] || ![file exists $fileName]} {
        return 0
    }
    if [catch {sdds load $fileName cacheData} result] {
        return -code error "Couldn't load $fileName"
    }
    if {[lsearch -exact $cacheData(ColumnNames) FileName]==-1 || \
          [lsearch -exact $cacheData(ColumnNames) Tag]==-1 || \
          [lsearch -exact $cacheData(ColumnNames) SourceFiles]==-1} {
        return -code error "Cache file $fileName does't have the right data ($cacheData(ColumnNames))."
    }
    set fileNameList [lindex $cacheData(Column.FileName) 0]
    set tagList [lindex $cacheData(Column.Tag) 0]
    set sourceFilesList [lindex $cacheData(Column.SourceFiles) 0]
    global ${arrayRoot}FileName ${arrayRoot}SourceFiles
    foreach fileName $fileNameList \
      tag $tagList \
      sourceFiles $sourceFilesList {
          if ![file exists $fileName] continue
          set ${arrayRoot}FileName($tag) $fileName
          set ${arrayRoot}SourceFiles($tag) $sourceFiles
      }
    return [llength [array names ${arrayRoot}SourceFiles]]
}

proc APSSaveFileCacheTable {args} {
    set fileName ""
    set arrayRoot ""
    APSStrictParseArguments {fileName arrayRoot} 
    APSSetVarAndUpdate status "Saving file cache to $fileName"
    if {![string length $fileName]} {
        return 0
    }
    global ${arrayRoot}FileName ${arrayRoot}SourceFiles
    set cacheData(ColumnNames) "FileName Tag SourceFiles" 
    foreach tag [array names ${arrayRoot}FileName] {
        if ![file exists [set ${arrayRoot}FileName($tag)]] continue
        lappend tagList $tag 
        lappend fileNameList [set ${arrayRoot}FileName($tag)]
        lappend sourceFilesList [set ${arrayRoot}SourceFiles($tag)]
    }
    set cacheData(Column.Tag) [list $tagList]
    set cacheData(Column.FileName) [list $fileNameList]
    set cacheData(Column.SourceFiles) [list $sourceFilesList]
    if [catch {sdds save $fileName cacheData} result] {
        return -code error "$result"
    }
}

proc DisplayCacheData {} {
    global IDFileName IDSourceFiles
 
    set itemList ""
    foreach tag [array names IDFileName] {
        if ![file exists $IDFileName($tag)] continue
        set dataList [split $tag \;]
        set ID [lindex $dataList 0]
        set timeList [split [lindex $dataList 1] ,]
        set startTime "[lindex $timeList 0]/[lindex $timeList 1]/[lindex $timeList 2]@[lindex $timeList 3]"
        set timeList [split [lindex $dataList 2] ,]
        set endTime "[lindex $timeList 0]/[lindex $timeList 1]/[lindex $timeList 2]@[lindex $timeList 3]"
        set minDCCT [lindex $dataList 3]
        set maxDCCT [lindex $dataList 4]
        set minGap [lindex $dataList 5]
        set maxGap [lindex $dataList 6]
        if  [lindex $dataList 7] {
            set userBeamMode user
        } else {
            set userBeamMode any
        }
        lappend itemList \
          "ID[format %02ld $ID] $startTime->$endTime \[$minDCCT, $maxDCCT]mA  \[$minGap,$maxGap]mm  $userBeamMode mode"
        lappend tagList $tag
    }
    if [llength $itemList]==0 {
        APSSetVarAndUpdate status "No cached data."
        return
    }
    set tagChosen [APSChooseItemFromList -name "Cached File Choice" \
                     -itemList $itemList -returnList $tagList \
                     -returnIndices 0 -multiItem 0]
    if ![string length $tagChosen] return
    SetParametersUsingTag -tag [string trim $tagChosen \{\}]
    APSSetVarAndUpdate status "Cache file selected."
}

proc SetParametersUsingTag {args} {
    set tag ""
    APSStrictParseArguments {tag}

    global StartYear StartMonth StartDay StartHour
    global EndYear EndMonth EndDay EndHour
    global IDSector minDCCT maxDCCT userBeamModeOnly minGap maxGap

    set dataList [split $tag \;]
    set IDSector [lindex $dataList 0]

    set timeList [split [lindex $dataList 1] ,]
    set StartYear [lindex $timeList 0]
    set StartMonth [lindex $timeList 1]
    set StartDay [lindex $timeList 2]
    set StartHour [lindex $timeList 3]

    set timeList [split [lindex $dataList 2] ,]
    set EndYear [lindex $timeList 0]
    set EndMonth [lindex $timeList 1]
    set EndDay [lindex $timeList 2]
    set EndHour [lindex $timeList 3]

    set minDCCT [lindex $dataList 3]
    set maxDCCT [lindex $dataList 4]
    set minGap [lindex $dataList 5]
    set maxGap [lindex $dataList 6]
    set userBeamModeOnly [lindex $dataList 7]
}

proc GetBPMPositionData {} {
    global OAGGlobal
    set positionFile $OAGGlobal(SRLatticesDirectory)/scripts/SRBPMPosition.xref 
    global BPMPosition
    if [catch {sdds load $positionFile BPMPositionData} result] {
        APSSetVarAndUpdate status "$result"
    }
    if {[lsearch -exact $BPMPositionData(ColumnNames) s]==-1 || \
          [lsearch -exact $BPMPositionData(ColumnNames) BPMName]==-1} {
        APSSetVarAndUpdate status "Data missing from $positionFile!"
        return
    }
    foreach bpm [lindex $BPMPositionData(Column.BPMName) 0] \
      s [lindex $BPMPositionData(Column.s) 0] {
          set BPMPosition($bpm) $s
      }
}

proc MakeBPMDataChoiceFrame {widget args} {
    set parent .
    set gridPack ""
    APSStrictParseArguments {parent gridPack}

    APSFrame $widget -parent $parent -relief flat -label "" -gridPack $gridPack
    set parent $parent$widget.frame
    APSCheckButtonFrame .cb -parent $parent -label "RF BPM Data To Plot" \
      -orientation horizontal \
      -allNone 1 -buttonList {ErrorCC AdjustedCC SetpointAO OffsetAO} \
      -variableList {doErrorCC doAdjustedCC doSetpointAO doOffsetAO}
    APSRadioButtonFrame .rb -parent $parent -label "Display Slopes from RF BPM Data" \
      -variable doRFBPMSlopes -buttonList "Yes No" -valueList "1 0" -orientation horizontal \
      -contextHelp "Choose whether to include plots of slopes computed from the selected RF BPM data."
    global doErrorCC doAdjustedCC doSetpointAO doRFBPMSlopes doOffsetAO
    set doAdjustedCC 1
    set doRFBPMSlopes 0
    set doErrorCC 0
    set doSetpointAO 0
    set doOffsetAO 0
}

proc MakeDateTimeFrame {widget args} {
    set parent .
    set rootname ""
    set gridPack ""
    APSStrictParseArguments {parent rootname glitchMode gridPack}
    set label "Date/Time Range of Interest"

    APSFrame $widget -parent $parent -label $label -gridPack $gridPack
    set w $parent$widget.frame

    APSDateTimeAdjEntry .startDate -parent $w \
      -yearVariable ${rootname}StartYear \
      -monthVariable ${rootname}StartMonth \
      -dayVariable ${rootname}StartDay \
      -hourVariable ${rootname}StartHour \
      -label "Start (year, month, day, hour): " -defaultHour 0 \
      -command ResetDataFileList -buttonSize small
    APSDateTimeAdjEntry .endDate -parent $w \
      -yearVariable ${rootname}EndYear \
      -monthVariable ${rootname}EndMonth \
      -dayVariable ${rootname}EndDay \
      -hourVariable ${rootname}EndHour \
      -label "End (year, month, day, hour):   " -defaultHour 24 \
      -command ResetDataFileList -buttonSize small

    SetDateTimeToToday -rootname ${rootname}Start -hour 0
    SetDateTimeToToday -rootname ${rootname}End  -hour 24
}

proc SetDateTimeToToday {args} {
    set rootname ""
    set hour 0
    ResetDataFileList
    APSStrictParseArguments {rootname hour}

    global ${rootname}Month ${rootname}Year ${rootname}Day ${rootname}Hour
    
    APSDateBreakDown -dayVariable ${rootname}Day -yearVariable ${rootname}Year \
      -monthVariable ${rootname}Month -twoDigitYear 0 -leadingZeros 0
    set ${rootname}Hour $hour
}

proc ResetDataFileList {} {
    global dataFileList  dataFileListIsOld
    set dataFileList ""
    set dataFileListIsOld 1
}

proc MakeIDChoiceFrame {widget args} {
    global IDSector
    set parent ""
    set gridPack ""
    APSParseArguments {parent gridPack}

    set sectorList [APSIDSectorList]
    APSRadioButtonFrame $widget -parent $parent -gridPack $gridPack \
      -label "ID Selection" -limitPerRow 5 -orientation vertical \
      -buttonList $sectorList -valueList $sectorList \
      -variable IDSector -commandList \
      [APSReplicateItem -item NewIDSelected -number [llength $sectorList]] \
      -contextHelp \
      "Selected the ID for which you would like to see data."
}

proc NewIDSelected {} {
    global IDSelectionChanged
    set IDSelectionChanged 1
}

proc MakeCorrChoiceFrame {widget args} {
    set parent ""
    set gridPack ""
    APSParseArguments {parent gridPack}

    APSFrame $widget -parent $parent -gridPack "$gridPack" -label "Correctors" 
    set w $parent$widget.frame

    APSCheckButtonFrame .hcb -parent $w -label "Horizontal" \
      -orientation horizontal -buttonList "A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1" \
      -variableList {doAH1 doAH2 doAH3 doAH4 doBH4 doBH3 doBH2 doBH1} -allNone 1
    global doAH2 doBH2
    set doBH2 1
    set doAH2 1
    APSCheckButtonFrame .vcb -parent $w -label "Vertical  " \
      -orientation horizontal -buttonList "A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1" \
      -variableList {doAV1 doAV2 doAV3 doAV4 doBV4 doBV3 doBV2 doBV1} -allNone 1
    global doAV2 doBV3
    set doAV2 1
    set doBV3 1
}

proc MakeFilterFrame {widget args} {
    global minDCCT maxDCCT userBeamModeOnly
    set parent ""
    set gridPack ""
    APSStrictParseArguments {parent gridPack}

    APSFrame $widget -parent $parent -gridPack $gridPack -label "Filters" 
    set w $parent$widget.frame
    APSLabeledEntryFrame .dcct -parent $w -gridPack "-row 0 -column 0" -label "Current (min, max mA): " \
      -variableList {minDCCT maxDCCT} -width 6 -orientation horizontal \
      -contextHelp "Enter the minimum and maximum values for the DCCT.  If the values are equal, no filter is applied."
    APSRadioButtonFrame .userbeam -parent $w -gridPack "-row 1 -column 0" -label "User beam mode only: " \
      -buttonList {Yes No} -valueList {1 0} -orientation horizontal -variable userBeamModeOnly \
      -contextHelp "Choose whether to show only data from user beam time or not."
    APSRadioButtonFrame .planes -parent $w -gridPack "-row 2 -column 0" -label "Planes: " \
      -buttonList {both x y} -valueList {xy x y} -orientation horizontal -variable planesToPlot
    APSRadioButtonFrame .usds -parent $w -gridPack "-row 3 -column 0" -label "AverageGap: " \
      -buttonList {US DS} -valueList {US DS} -orientation horizontal -variable gapToFilterOn
    APSLabeledEntryFrame .gap -parent $w -gridPack "-row 4 -column 0" -label "Gap (min, max mm): " \
      -variableList {minGap maxGap} -width 6 -orientation horizontal \
      -contextHelp "Enter the minimum and maximum values for ID gap.  If the values are equal, no filter is applied."
}

proc MakeIDPlots {args} {
    global StartYear StartMonth StartDay StartHour OAGGlobal
    global EndYear EndMonth EndDay EndHour
    global IDSector minDCCT maxDCCT userBeamModeOnly minGap maxGap
    global BPMPosition planesToPlot
    global plotDevice printerName labelSizeOption env userPlotOptions
    global sameScalesOption layoutOption
    global doAH1 doAH2 doAH3 doAH4 doBH4 doBH3 doBH2 doBH1
    global doAV1 doAV2 doAV3 doAV4 doBV4 doBV3 doBV2 doBV1
    global cacheFile IDFileName IDSourceFiles
    global doAdjustedCC doSetpointAO doErrorCC doRFBPMSlopes doOffsetAO
    global IDbeamlineLength

    set plotType ""
    APSStrictParseArguments {plotType} 

    set timeLabel "Time span: $StartYear/$StartMonth/$StartDay@$StartHour to $EndYear/$EndMonth/$EndDay@$EndHour"
    foreach item {Start End} {
        if [catch {APSConvertTimeToHours [set ${item}Hour]} hour] {
            APSSetVarAndUpdate status "Invalid [string tolower $item]ing hour: [set ${item}Hour]"
            return
        }
        set [string tolower $item]Time \
          [exec timeconvert \
             -breakDown=year=[set ${item}Year],month=[set ${item}Month],day=[set ${item}Day],hour=$hour]
        set ${item}DateList [APSFormatDate -year [set ${item}Year] \
                               -month [set ${item}Month] -day [set ${item}Day] -dateFormat list] 
    }
    
    if $startTime>=$endTime {
        APSSetVarAndUpdate status "Start time must be prior to end time."
        return
    }
    
    APSSetVarAndUpdate status "Working [clock format [clock seconds]]..."

    set BP0Name S${IDSector}B:P0
    set BP1Name S${IDSector}B:P1
    set AP0Name S[expr $IDSector+1]A:P0
    set AP1Name S[expr $IDSector+1]A:P1
    set P0Distance [expr $BPMPosition($AP0Name)-$BPMPosition($BP0Name)]
    set P1Distance [expr $BPMPosition($AP1Name)-$BPMPosition($BP1Name)]
    set filterArgs -filter=column,TimeOfDay,0,24
    lappend filterArgs -filter=column,Time,$startTime,$endTime
    if $minDCCT<$maxDCCT {
        lappend filterArgs -filter=column,S35DCCT,$minDCCT,$maxDCCT
    }
    if $userBeamModeOnly {
        lappend filterArgs -filter=column,SRDesiredMode,0.9,2.1
    }

    lappend IDBPMList S${IDSector}B:P0*
    lappend IDBPMList S[expr $IDSector+1]A:P0*
    lappend IDBPMList S${IDSector}B:P1*
    lappend IDBPMList S[expr $IDSector+1]A:P1*

    set CorrToIncludeList ""
    set CorrChosenList ""
    set HCorrChosenList ""
    set VCorrChosenList ""
    foreach side {B A} {
        set sector $IDSector
        if [string compare $side A]==0 {
            set sector [expr $IDSector+1]
        }
        foreach plane {H V} {
            foreach num {1 2 3 4} {
                # correctors to include in file
                lappend CorrToIncludeList S${sector}${side}:${plane}${num}:CurrentAI
                if [set do${side}${plane}$num] {
                    # correctors chosen, plus separate H/V lists
                    lappend CorrChosenList S${sector}${side}:${plane}${num}:CurrentAI
                    lappend ${plane}CorrChosenList S${sector}${side}:${plane}${num}:CurrentAI
                }
            }
        }
    }

    if [expr $minGap>=$maxGap] {
        set minGap 0
        set maxGap 0
    }
    set tag "$IDSector;$StartYear,$StartMonth,$StartDay,$StartHour;$EndYear,$EndMonth,$EndDay,$EndHour;$minDCCT;$maxDCCT;$minGap;$maxGap;$userBeamModeOnly"
    set IDSector2 [format %02ld $IDSector]
    set fileName ""
    if [lsearch -exact [array names IDFileName] $tag]!=-1 {
        set fileName $IDFileName($tag)
        set sourceFileList $IDSourceFiles($tag)
        if [string length $fileName] {
            if ![file exists $fileName] {
                set fileName ""
            } else {
                set mtime0 [file mtime $fileName]
                foreach source [split $sourceFileList ,] {
                    if [file mtime $source]>$mtime0 {
                        file delete $fileName
                        set fileName ""
                        break
                    }
                }
            }
        }
    }
    if ![string length $fileName] {
        set dataFileList \
          [APSFindFilesBetweenDates -tailsOnly 0 \
               -rootname srBPMAve- -directory /home/helios/oagData/logging/srBPMAve \
             -startDateList $StartDateList -endDateList $EndDateList \
            ]
        set corrDataFileList \
          [APSFindFilesBetweenDates -tailsOnly 0 \
               -rootname SRDCPS-HVD- -directory /home/helios/oagData/logging/SRDCPS-HVD \
             -startDateList $StartDateList -endDateList $EndDateList \
            ]
        set IDDataFileList \
          [APSFindFilesBetweenDates -tailsOnly 0 \
               -rootname IDs- -directory /home/helios/oagData/monitoring/IDs \
             -startDateList $StartDateList -endDateList $EndDateList \
            ]
        APSSetVarAndUpdate status "[llength $dataFileList]+[llength $corrDataFileList]+[llength $IDDataFileList] files found"
        if ![llength $dataFileList] return
        
        set xAdjSuf :mswAve:x:AdjustedCC
        set yAdjSuf :mswAve:y:AdjustedCC
        set xErrSuf :mswAve:x:ErrorCC
        set yErrSuf :mswAve:y:ErrorCC
        set xSPSuf :ms:x:SetpointAO
        set ySPSuf :ms:y:SetpointAO
        set xOffSuf :ms:x:OffsetAO
        set yOffSuf :ms:y:OffsetAO
        set tmpFile /tmp/[APSTmpString]
        APSAddToTempFileList $tmpFile $tmpFile.ID $tmpFile.cor
        if [catch \
              {eval exec sddscombine $dataFileList -merge \
                 -retain=column,Time,TimeOfDay,[join $IDBPMList ,],S35DCCT,SRDesiredMode -pipe=out \
                 | sddsprocess -pipe=in $tmpFile $filterArgs \
                 -define=parameter,P0Distance,$P0Distance \
                 -define=parameter,P1Distance,$P1Distance \
                 {"-define=column,P0:x:AdjustedCC:Slope,$AP0Name$xAdjSuf $BP0Name$xAdjSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:x:AdjustedCC:Slope,$AP1Name$xAdjSuf $BP1Name$xAdjSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:y:AdjustedCC:Slope,$AP0Name$yAdjSuf $BP0Name$yAdjSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:y:AdjustedCC:Slope,$AP1Name$yAdjSuf $BP1Name$yAdjSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:x:SetpointAO:Slope,$AP0Name$xSPSuf $BP0Name$xSPSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:x:SetpointAO:Slope,$AP1Name$xSPSuf $BP1Name$xSPSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:y:SetpointAO:Slope,$AP0Name$ySPSuf $BP0Name$ySPSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:y:SetpointAO:Slope,$AP1Name$ySPSuf $BP1Name$ySPSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:x:OffsetAO:Slope,$AP0Name$xOffSuf $BP0Name$xOffSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:x:OffsetAO:Slope,$AP1Name$xOffSuf $BP1Name$xOffSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:y:OffsetAO:Slope,$AP0Name$yOffSuf $BP0Name$yOffSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:y:OffsetAO:Slope,$AP1Name$yOffSuf $BP1Name$yOffSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:x:Slope,$AP0Name:mswAve:x $BP0Name:mswAve:x - P0Distance /,units=mrad"} \
                 {"-define=column,P1:x:Slope,$AP1Name:mswAve:x $BP1Name:mswAve:x - P1Distance /,units=mrad"} \
                 {"-define=column,P0:y:Slope,$AP0Name:mswAve:y $BP0Name:mswAve:y - P0Distance /,units=mrad"} \
                 {"-define=column,P1:y:Slope,$AP1Name:mswAve:y $BP1Name:mswAve:y - P1Distance /,units=mrad"} \
                 {"-define=column,P0:x:ErrorCC:Slope,$AP0Name$xErrSuf $BP0Name$xErrSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:x:ErrorCC:Slope,$AP1Name$xErrSuf $BP1Name$xErrSuf - P1Distance /,units=mrad"} \
                 {"-define=column,P0:y:ErrorCC:Slope,$AP0Name$yErrSuf $BP0Name$yErrSuf - P0Distance /,units=mrad"} \
                 {"-define=column,P1:y:ErrorCC:Slope,$AP1Name$yErrSuf $BP1Name$yErrSuf - P1Distance /,units=mrad"} } \
              result] {
            return -code error "Error combining BPM data files: $result"
        }
        if [catch {eval exec sddscombine $corrDataFileList -pipe=out -merge \
                     -retain=column,Time,TimeOfDay,[join $CorrToIncludeList ,] \
                     | sddsprocess -pipe -filter=column,TimeOfDay,0,24 \
                     | sddsinterp -pipe=in $tmpFile.cor \
                     -fileValues=$tmpFile,column=Time -columns=Time,S*} result] {
            return -code error "Corrector data processing error: $result"
        }
        if [catch {eval exec sddscombine $IDDataFileList -pipe=out -merge \
                     -retain=column,Time,TimeOfDay,ID${IDSector2}* \
                     | sddsprocess -pipe -filter=column,TimeOfDay,0,24 \
                     | sddsinterp -pipe=in $tmpFile.ID \
                     -fileValues=$tmpFile,column=Time -columns=Time,ID*} result] {
            return -code error "ID data processing error: $result"
        }
        if $minGap!=$maxGap {
            global gapToFilterOn
            lappend gapFilterArgList -filter=col,ID${IDSector2}${gapToFilterOn}AverageGap,$minGap,$maxGap $tmpFile.all
        } else {
            set gapFilterArgList $tmpFile.all
        }
        if [catch {eval exec sddsxref $tmpFile $tmpFile.cor -pipe=out -take=* \
                     | sddsxref -pipe $tmpFile.ID -take=* \
                     | sddsprocess -pipe=in $gapFilterArgList} result] {
            APSSetVarAndUpdate status "Final data processing error: Try expanding Gap range."
            return -code error "Final data processing error: Try expanding Gap range: $result"
        }
        set fileName $tmpFile.all
        set IDFileName($tag) $fileName
        set IDSourceFiles($tag) [join [concat $dataFileList $corrDataFileList $IDDataFileList] ,]
        APSSaveFileCacheTable -fileName $cacheFile -arrayRoot ID
        APSDeleteTempFiles
    }

    if [string compare $plotType quickSDDSplot]==0 {
        exec quickSDDSplot -dataFileList $fileName -message "Launched by SRFillToFillAtIDs" &
        APSSetVarAndUpdate status "quickSDDSplot launched"
        return
    }
    if [string compare $plotType export]==0 {
        exec sddsExportData -dataFileList $fileName -message "Launched by SRFillToFillAtIDs" &
        APSSetVarAndUpdate status "sddsExportData launched"
        return
    }
    
    set endArg ""
    if [string compare $plotDevice motif]!=0 {
        set endArg "| lpr -P$printerName"
    }
    set beginArgs $sameScalesOption
    lappend beginArgs -layout=$layoutOption

    if $userBeamModeOnly {
        set mode user
    } else {
        set mode any
    }

    # BPM plots vs time 
    if [lsearch -exact [list AllTime BPMTime] $plotType]!=-1 {
        set columnArgs ""
        foreach plane {x y} {
            if [string first $plane $planesToPlot]!=-1 {
                set bpmList ""
                foreach type {ErrorCC AdjustedCC SetpointAO OffsetAO} {
                    if [set do$type] {
                        lappend bpmList *${plane}:$type
                        if $doRFBPMSlopes {
                            lappend bpmList *${plane}:${type}*Slope*
                        }
                    }
                }
                if [llength $bpmList] {
                    lappend columnArgs -column=Time,([join $bpmList ,])
                    lappend columnArgs -mode=y=offset
                }
            }
        }
        if ![llength $columnArgs] {
            APSSetVarAndUpdate status "Nothing selected for BPM plots vs time."
        } else {
            lappend beginArgs -graph=dot -separate 
            if [string length [string trim $userPlotOptions]] {
                eval lappend beginArgs [string trim $userPlotOptions]
            }
            APSExecLog .plotWindow -width 60 \
              -unixCommand \
              "sddsplot \
              {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap\] mm in $mode mode} \
              -device=$plotDevice $fileName -ticks=xtime \
              $beginArgs \
              $columnArgs \
              -column=Time,S35DCCT -omnipresent -graph=dots,type=1,subtype=1 -yscale=id=DCCT $endArg"
            wm withdraw .plotWindow
        }
    }

    set beginArgs $sameScalesOption
    lappend beginArgs -layout=$layoutOption
    if [string length [string trim $userPlotOptions]] {
        eval lappend beginArgs [string trim $userPlotOptions]
    }

    # Corrector plots vs time
    if [lsearch -exact [list AllTime CorrTime] $plotType]!=-1 {
        set columnArgs ""
        foreach plane {x y} direction {H V} {
            if [string first $plane $planesToPlot]!=-1 {
                if [llength ${direction}CorrChosenList] {
                    lappend columnArgs -column=Time,([join [set ${direction}CorrChosenList] ,])
                    lappend columnArgs -mode=y=offset
                }
            }
        }
        if ![llength $columnArgs] {
            APSSetVarAndUpdate status "Nothing chosen for corrector plots vs time."
        } else {
            APSExecLog .plotWindow -width 60 \
              -unixCommand \
              "sddsplot -graph=dots -sever=xgap=-1.5 \
              {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap] mm in $mode mode} \
              -device=$plotDevice $fileName -ticks=xtime \
              $beginArgs -separate \
              $columnArgs \
              -column=Time,S35DCCT -omnipresent -graph=dots,type=1,subtype=1 -yscale=id=DCCT $endArg"
            wm withdraw .plotWindow
        }
    } 

    # ID data vs time.
    if [lsearch -exact [list IDData AllTime] $plotType]!=-1 {
        APSExecLog .plotWindow -width 60 \
          -unixCommand \
          "sddsplot -graph=dots -separate -ticks=xtime \
          {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap] mm in $mode mode} \
          -device=$plotDevice $fileName $beginArgs \
          -column=Time,ID${IDSector2}* \
          -column=Time,S35DCCT -omnipresent -graph=dots,type=1,subtype=1 -yscale=id=DCCT $endArg"
        wm withdraw .plotWindow
    }
    

   # BPM/Corrector scatter plots
    if [lsearch -exact [list AllScatter BPM-CorrScatter] $plotType]!=-1 {
        set columnArgs ""
        if [string first x $planesToPlot]!=-1 {
            lappend columnArgs -column=ID${IDSector2}HorizontalAngle,([join $HCorrChosenList ,])
        }
        if [string first y $planesToPlot]!=-1 {
            lappend columnArgs -column=ID${IDSector2}VerticalAngle,([join $VCorrChosenList ,])
        }
        if ![llength $columnArgs] {
            APSSetVarAndUpdate status "No data chosen for bpm/corrector scatter plots."
        } else {
            APSExecLog .plotWindow -width 60 \
              -unixCommand "sddsplot -graph=dot -separate \
          {-title=$timeLabel} \
          {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap] mm in $mode mode} \
          -device=$plotDevice $fileName $beginArgs \
          $columnArgs $endArg"
            wm withdraw .plotWindow
        }
    }

    # BPM/BPM Scatter plots
    if [lsearch -exact [list AllScatter BPM-BPMScatter] $plotType]!=-1 {
        set columnArgs ""
        set hvPlane Horizontal
        foreach plane {x y} {
            if [string first $plane $planesToPlot]!=-1 {
                foreach type [list AdjustedCC ErrorCC SetpointAO OffsetAO] {
                    if [set do$type] {
                        lappend columnArgs -column=ID${IDSector2}${hvPlane}Angle,*$plane:$type
                        if $doRFBPMSlopes {
                            lappend columnArgs -column=ID${IDSector2}${hvPlane}Angle,*$plane:$type*Slope
                        }
                    }
                }
            }
            set hvPlane Vertical
        }
        if ![llength $columnArgs] {
            APSSetVarAndUpdate status "No data chosen for BPM/BPM Scatter Plots"
        } else {
            APSExecLog .plotWindow -width 60 \
              -unixCommand \
              "sddsplot -graph=dot -separate \
              {-title=$timeLabel} \
              {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap] mm in $mode mode} \
              -device=$plotDevice $fileName $beginArgs $columnArgs $endArg"
            wm withdraw .plotWindow
        }
    }

    # Current Scatter plots
    if [lsearch -exact [list AllScatter CurrentScatter] $plotType]!=-1 {
        set columnArgs ""
        set hvPlane Horizontal
        set HV H
        foreach plane {x y} {
            if [string first $plane $planesToPlot]!=-1 {
                lappend columnArgs -column=S35DCCT,([join [set ${HV}CorrChosenList] ,])
                foreach type [list AdjustedCC ErrorCC SetpointAO OffsetAO] {
                    if [set do$type] {
                        lappend columnArgs -column=S35DCCT,*$plane:$type
                        if $doRFBPMSlopes {
                            lappend columnArgs -column=S35DCCT,*$plane:$type*Slope
                        }
                    }
                }
                lappend columnArgs -column=S35DCCT,*${hvPlane}Angle
            }
            set hvPlane Vertical
            set HV V
        }
        if ![llength $columnArgs] {
        } else {
            APSExecLog .plotWindow -width 60 \
              -unixCommand "sddsplot -graph=dot -separate \
          {-title=$timeLabel} \
          {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap] mm in $mode mode} \
          -device=$plotDevice $fileName $beginArgs $columnArgs $endArg"
            wm withdraw .plotWindow
        }
    }

    APSSetVarAndUpdate status "Plots launched [clock format [clock seconds]]."
    # printouts
    if [lsearch -exact [list BPMStats XBPMStats] $plotType]!=-1 {
        set collFile [file rootname $fileName].coll
        set startTime [file rootname $fileName].startTime
        # following the principle of not repeating the processing if the file
        # is already created, presumably from a cached file originally.
        if ![file exists $collFile] {
            if [catch {exec sddsbreak $fileName -pipe=out \
                         -increaseof=S35DCCT \
                         | sddsprocess -pipe \
                         -proc=Time,first,StartData \
                         -proc=Time,last,EndData \
                         -proc=S35DCCT,spread,S35DCCTSpread \
                         -proc=S35DCCT,average,S35DCCTAve \
                         -proc=S35DCCT,count,Count \
                         -proc=S*:mswAve:?:*,average,%sAve \
                         -proc=P*Slope,average,%sAve \
                         -proc=ID*Position?,average,%sAve \
                         -proc=ID*Angle,average,%sAve \
                         -proc=S*:mswAve:?:*,spread,%sSpread \
                         -proc=P*Slope,spread,%sSpread \
                         -proc=ID*Position?,spread,%sSpread \
                         -proc=ID*Angle,spread,%sSpread \
                         | sddsprocess -pipe \
                         -filter=para,Count,0,2,! \
                         | tee [file rootname $fileName].break \
                         | sddscollapse -pipe \
                         | sddsconvert -pipe=in $collFile \
                         -editname=col,*Ave,e3b%/Ave// \
                         -rename=col,StartData=Time \
                     } results] {
                return -code error "BPM data processing error: $results"
            }
            if [catch {exec sddsconvert [file rootname $fileName].break \
                         $startTime \
                         -dele=col,* -retain=para,StartData \
                         -rename=para,StartData=Time \
                     } results] {
                return -code error "BPM data processing error: $results"
            }
        }
        # calculating the spread over all fills.
        set statsFile [file rootname $fileName].stats
        if ![file exists $statsFile] {
            if [catch {exec sddsprocess $collFile -pipe=out \
                         -proc=S*:mswAve:?:*CC,spread,%sSpread \
                         -proc=ID*Position?,spread,%sSpread \
                         -proc=S*:mswAve:?:*CC,standarddeviation,%sRms \
                         -proc=ID*Position?,standarddeviation,%sRms \
                         | sddscollapse -pipe \
                         | sddscollect -pipe -noWarning \
                         -collect=suffix=Spread \
                         -collect=suffix=Rms \
                         | sddsprocess -pipe \
                         -convertUnits=col,Spread,\$gm\$rm,mm,1e3 \
                         -convertUnits=col,Rms,\$gm\$rm,mm,1e3 \
                         -edit=col,Plane,Rootname,3Z:fD \
                         -edit=col,Type,Rootname,4Z: \
                         | sddssort -pipe=in $statsFile \
                         -col=Plane -col=Type -col=Rootname \
                     } results] {
                return -code error "BPM data processing error: $results"
            }
        }
    }
    if [lsearch -exact [list BPMStats] $plotType]!=-1 {
        # calculating the orbit changes at each fill.
        foreach coord {x y} {
            set ${coord}ChangeFile [file rootname $fileName].${coord}changes
            set ${coord}ChangeFile1 [file rootname $fileName].${coord}changes1
            if ![file exists [subst \$${coord}ChangeFile]] {
                if [catch {exec sddsconvert $collFile -pipe=out \
                             -retain=col,Time,*mswAve:${coord}:AdjustedCC \
                             -dele=para,* \
                             | sddsprocess -pipe \
                             -proc=*mswAve:${coord}:AdjustedCC,first,%sFirst \
                             | sddsprocess -pipe \
                             "-redefine=col,%s,%s %sFirst -,select=*mswAve:${coord}:AdjustedCC" \
                             | sddscollect -pipe \
                             -collect=suffix=:mswAve:${coord}:AdjustedCC \
                             | sddsxref -pipe -noWarning -reuse=page \
                             $OAGGlobal(SRLatticesDirectory)/scripts/SRBPMPosition.xref \
                             -match=Rootname=ElementName -take=s \
                             | sddsprocess -pipe \
                             -proc=s,average,sAve \
                             "-redef=col,s,s sAve -" \
                             | sddspfit -pipe \
                             -col=s,:mswAve:${coord}:AdjustedCC \
                             -terms=2 -generateSigmas \
                             | sddsxref -pipe=in  $startTime [subst \$${coord}ChangeFile] \
                             -transfer=para,Time \
                         } results] {
                    return -code error "BPM data processing error: $results"
                }
            }
            if ![file exists [subst \$${coord}ChangeFile1]] {
                if [catch {exec sddscollapse [subst \$${coord}ChangeFile] -pipe=out \
                             | sddsxref -pipe $startTime -transfer=para,Time \
                             | sddsprocess -pipe=in [subst \$${coord}ChangeFile1] \
                             "-redef=col,Position,Intercept 1e3 *,symbol=Position,units=\$gm\$rm" \
                             "-redef=col,PositionSigma,InterceptSigma 1e3 *,symbol=PositionSigma,units=\$gm\$rm" \
                             "-redef=col,Angle,Slope 1e3 *,symbol=Angle,units=\$gm\$rrad" \
                             "-redef=col,AngleSigma,SlopeSigma 1e3 *,symbol=AngleSigma,units=\$gm\$rrad" \
                             "-def=col,FinalPosition,Position Angle $IDbeamlineLength($IDSector) * +,units=\$gm\$rm" \
                             "-def=col,FinalPositionSigma,PositionSigma sqr AngleSigma $IDbeamlineLength($IDSector) * sqr + sqrt,units=\$gm\$rm" \
                         } results] {
                    return -code error "BPM data processing error: $results"
                }
            }
        }

        APSExecLog .plotWindow -width 60 \
          -name "Statistics over all fills" \
          -unixCommand \
          "sddsplot \
          {-topline=Data for ID$IDSector with \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap\] mm in $mode mode} \
          -device=$plotDevice $collFile -ticks=xtime \
          $beginArgs -separate \
          -col=Time,S*:mswAve:x:AdjustedCC,%sSpread -graph=errorbar \
          -col=Time,S*:mswAve:x:ErrorCC,%sSpread -graph=errorbar \
          -col=Time,S*:mswAve:y:AdjustedCC,%sSpread -graph=errorbar \
          -col=Time,S*:mswAve:y:ErrorCC,%sSpread -graph=errorbar \
          -col=Time,P*x*Slope,%sSpread -graph=errorbar \
          -col=Time,P*y*Slope,%sSpread -graph=errorbar \
          -col=Time,ID*HorizontalPosition?,%sSpread -graph=errorbar \
          -col=Time,ID*VerticalPosition?,%sSpread -graph=errorbar \
          $endArg"
        wm withdraw .plotWindow
        APSExecLog .printWindow -width 60 \
          -unixCommand \
          "sddsprintout $statsFile -col=(Rootname,Spread,Rms) -format=string=%35s,double=%6.1f"
        
        APSExecLog .plotWindow -width 60 \
          -name "Fit line to orbit changes for each fill" \
          -unixCommand \
          "sddsplot \
          $beginArgs \
          -same -sep=pages -split=pages -group=pages \
          -col=s,:mswAve:x:AdjustedCC -grap=sym,sca=3 $xChangeFile \
          {-topline=Line fit through ID$IDSector x BPMs \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap\] mm in $mode mode} \
          -col=s,:mswAve:x:AdjustedCCFit -grap=line,type=1 $xChangeFile \
          -endPanel \ 
          -col=s,:mswAve:y:AdjustedCC -grap=sym,sca=3 $yChangeFile \
         {-topline=Line fit through ID$IDSector y BPMs \[$minDCCT\\\,$maxDCCT] mA and gap \[$minGap\\\,$maxGap\] mm in $mode mode} \
          -col=s,:mswAve:y:AdjustedCCFit -grap=line,type=1 $yChangeFile \
          $endArg"
        wm withdraw .plotWindow

        APSExecLog .plotWindow -width 60 \
          -name "Fit line to orbit changes for each fill" \
          -unixCommand \
          "sddsplot \
          $beginArgs \
          {-topline=Source point x-coordinate changes from ID$IDSector RF bpms} \
 -axes \
          $xChangeFile1 \
          -col=Position,Angle,PositionSigma,AngleSigma -grap=errorbar,subtype=1\
          -col=Position,Angle,PositionSigma,AngleSigma -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Position,PositionSigma -tick=xtime -grap=errorbar,subtype=1\
          -col=Time,Position,PositionSigma -tick=xtime -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Angle,AngleSigma -tick=xtime -grap=errorbar,subtype=1 \
          -col=Time,Angle,AngleSigma -tick=xtime -grap=sym,sca=3,subtype=1 \
          -endPanel \
          -col=Time,FinalPosition,FinalPositionSigma -tick=xtime -grap=errorbar,subtype=1 \
          -col=Time,FinalPosition,FinalPositionSigma -tick=xtime -grap=sym,sca=3,subtype=1 \
          $endArg"
        wm withdraw .plotWindow
        APSExecLog .plotWindow -width 60 \
          -name "Fit line to orbit changes for each fill" \
          -unixCommand \
          "sddsplot \
          $beginArgs \
          {-topline=Source point y-coordinate changes from ID$IDSector RF bpms} \
 -axes \
          $yChangeFile1 \
          -col=Position,Angle,PositionSigma,AngleSigma -grap=errorbar,subtype=1\
          -col=Position,Angle,PositionSigma,AngleSigma -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Position,PositionSigma -tick=xtime -grap=errorbar,subtype=1\
          -col=Time,Position,PositionSigma -tick=xtime -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Angle,AngleSigma -tick=xtime -grap=errorbar,subtype=1 \
          -col=Time,Angle,AngleSigma -tick=xtime -grap=sym,sca=3,subtype=1 \
          -endPanel \
          -col=Time,FinalPosition,FinalPositionSigma -tick=xtime -grap=errorbar,subtype=1 \
          -col=Time,FinalPosition,FinalPositionSigma -tick=xtime -grap=sym,sca=3,subtype=1 \
          $endArg"
        wm withdraw .plotWindow
    }        
    if [lsearch -exact [list XBPMStats] $plotType]!=-1 {
        # calculating the orbit changes at each fill.
        set XBPM1distance 16.330
        set XBPM2distance 20.068
        set collFile [file rootname $fileName].coll
        foreach coord {Horizontal Vertical} {
            set ${coord}ChangeFile [file rootname $fileName].${coord}Changes
            if ![file exists [subst \$${coord}ChangeFile]] {
                if [catch {exec sddsconvert $collFile -pipe=out \
                             -retain=col,Time,*${coord}Position* \
                             -dele=para,* \
                             | sddsprocess -pipe \
                             -proc=*${coord}Position*,first,%sFirst \
                             | sddsprocess -pipe=in [subst \$${coord}ChangeFile] \
                             "-redefine=col,%s,%s %sFirst -,select=*${coord}Position*" \
                             "-def=col,Angle,ID${IDSector2}${coord}Position2 ID${IDSector2}${coord}Position1 - $XBPM2distance $XBPM1distance - / 1000 *,units=\$gm\$rmrad" \
                             "-def=col,Position,ID${IDSector2}${coord}Position1 1000 * Angle $XBPM1distance * -,units=\$gm\$rm" \
                             "-def=col,FinalPosition,Position Angle $IDbeamlineLength($IDSector) * +,units=\$gm\$rm" \
                         } results] {
                    return -code error "XBPMStats data processing error: $results"
                }
            }
        }
        APSExecLog .plotWindow -width 60 \
          -name "Source point changes for each fill" \
          -unixCommand \
          "sddsplot \
          $beginArgs \
          {-topline=Source point x-coordinate changes from ID$IDSector Xray bpms} \
 -axes \
          $HorizontalChangeFile \
          -col=Position,Angle -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Position -tick=xtime -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Angle -tick=xtime -grap=sym,sca=3,subtype=1 \
          -endPanel \
          -col=Time,FinalPosition -tick=xtime -grap=sym,sca=3,subtype=1 \
          $endArg"
        wm withdraw .plotWindow
        APSExecLog .plotWindow -width 60 \
          -name "Fit line to orbit changes for each fill" \
          -unixCommand \
          "sddsplot \
          $beginArgs \
          {-topline=Source point y-coordinate changes from ID$IDSector Xray bpms} \
 -axes \
          $VerticalChangeFile \
          -col=Position,Angle -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Position -tick=xtime -grap=sym,sca=3,subtype=1\
          -endPanel \
          -col=Time,Angle -tick=xtime -grap=sym,sca=3,subtype=1 \
          -endPanel \
          -col=Time,FinalPosition -tick=xtime -grap=sym,sca=3,subtype=1 \
          $endArg"
        wm withdraw .plotWindow
    }
}

proc SetBeamlineLength {} {
    global IDbeamlineLength
    foreach ID [APSIDSectorList] {
        set IDbeamlineLength($ID) 30
        if {$ID == 17} {
            set IDbeamlineLength($ID) 63 
        }
    }
}


proc MakeButtonFrame {widget args} {
    set parent ""
    set gridPack ""
    APSStrictParseArguments {parent gridPack}
    
    APSFrame $widget -parent $parent -label "Make Plots" -gridPack $gridPack

    APSButton .run0 -parent $parent$widget.frame -text "Time" -command "MakeIDPlots -plotType AllTime" \
      -gridPack "-column 0 -row 0 -sticky nw " \
      -contextHelp "Combines the three buttons on the right."
    APSButton .run1 -parent $parent$widget.frame -text "BPM vs Time" -command "MakeIDPlots -plotType BPMTime" \
      -gridPack "-column 1 -row 0 -sticky nw "
    APSButton .run2 -parent $parent$widget.frame -text "Corr. vs Time" -command "MakeIDPlots -plotType CorrTime" \
      -gridPack "-column 2 -row 0 -sticky nw "
    APSButton .run21 -parent $parent$widget.frame -text "ID data vs Time" \
      -command "MakeIDPlots -plotType IDData" \
      -gridPack "-column 3 -row 0 -sticky nw "
    APSButton .run3 -parent $parent$widget.frame -text "Scatter" \
      -command "MakeIDPlots -plotType AllScatter" \
      -gridPack "-column 0 -row 1 -sticky nw " \
      -contextHelp "Combines the three buttons on the right."
    APSButton .run4 -parent $parent$widget.frame -text "BPM/Corr. Scatter" \
      -command "MakeIDPlots -plotType BPM-CorrScatter" \
      -gridPack "-column 1 -row 1 -sticky nw "
    APSButton .run5 -parent $parent$widget.frame -text "BPM/BPM Scatter" \
      -command "MakeIDPlots -plotType BPM-BPMScatter" \
      -gridPack "-column 2 -row 1 -sticky nw "
    APSButton .run6 -parent $parent$widget.frame -text "Current Scatter" \
      -command "MakeIDPlots -plotType CurrentScatter" \
      -gridPack "-column 3 -row 1 -sticky nw "
    APSButton .run7 -parent $parent$widget.frame -text "Show plot command" \
      -command "catch {wm deiconify .plotWindow}" -gridPack "-column 0 -row 2 -sticky nw"
    APSButton .run8 -parent $parent$widget.frame -text "quickSDDSplot ..." \
      -command "MakeIDPlots -plotType quickSDDSplot" -gridPack "-column 1 -row 2 -sticky nw"
    APSButton .run9 -parent $parent$widget.frame -text "Export..." \
      -command "MakeIDPlots -plotType export" -gridPack "-column 2 -row 2 -sticky nw"
    APSButton .run10 -parent $parent$widget.frame -text "Pick from cache..." \
      -command DisplayCacheData -gridPack "-column 3 -row 2 -sticky nw" \
      -contextHelp "Reads from cache data file (~/.SRFillToFillAtIDs.cache), and allows the selection of already-processed data files residing in the /tmp directory. Widgets are updated when selecting a cache file."
    APSButton .run11 -parent $parent$widget.frame -text "BPM stats" \
      -command "MakeIDPlots -plotType BPMStats" -gridPack "-column 0 -row 3 -sticky nw" \
      -contextHelp "Plots the average bpm readbacks for each fill with error bars, and prints out statistics over all fills."
    APSButton .run12 -parent $parent$widget.frame -text "Xray BPM stats" \
      -command "MakeIDPlots -plotType XBPMStats" -gridPack "-column 1 -row 3 -sticky nw" \
      -contextHelp "Plots the average Xray bpm readbacks for each fill with error bars, and prints out statistics over all fills."
}

proc MakePlotControls {widget args} {
    global plotDevice printerName labelSizeOption env userPlotOptions
    global sameScalesOption layoutOption
    set layoutOption 1,1
    set sameScalesOption ""
    set plotDevice motif
    set labelSizeOption -labelsize=0.03
    set userPlotOptions ""
    if [info exists env(PRINTER)] {
        set printerName $env(PRINTER)
    } else {
        set printerName mcr1
    }

    set gridPack ""
    set parent "" 
    APSStrictParseArguments {parent gridPack}

    APSFrame $widget -parent $parent -label "Plot controls" -gridPack $gridPack
    set parent $parent$widget.frame

    APSRadioButtonFrame .device  -parent ${parent} -gridPack "-column 0 -row 0 -sticky nw" \
      -label Device -orientation horizontal -limitPerRow 2 \
      -variable plotDevice \
      -buttonList {X-windows "B&W PS" "Color PS" "Color PS on Black"} \
      -valueList {motif postscript cpostscript cpostscript,onblack} \
      -contextHelp "Choose the plotting device.  Postscript is for delivery to a printer only."
    APSLabeledEntry .printer -parent ${parent} -gridPack "-column 1 -row 0 -sticky nw" \
        -label "Printer: " -textVariable printerName -width 10
    APSRadioButtonFrame .labelsize -parent ${parent} -gridPack "-column 0 -row 1 -sticky nw" \
        -label "Label size" -orientation horizontal -variable labelSizeOption \
        -buttonList {normal +15% +30% +45% +60%} \
        -valueList {-labelsize=0.03 -labelsize=0.0345 -labelsize=0.039 -labelsize=0.0435 -labelsize=0.048} \
        -contextHelp "For layouts with many panels, the labels may be hard to read.  You can increase the size of the labels using these options."
            
    APSRadioButtonFrame .samescales -parent $parent -gridPack "-column 1 -row 1 -sticky nw" \
      -label "Same scales" -orientation horizontal -variable sameScalesOption \
      -buttonList {Yes No} -valueList {-samescales=y,global ""}
    APSRadioButtonFrame .layout -parent $parent -gridPack "-column 0 -row 4 -sticky nw" \
      -label "Layout" -orientation horizontal -variable layoutOption \
      -buttonList {1x1 1x2 2x1 2x2 2x3 3x2 3x3} \
      -valueList {1,1 1,2 2,1 2,2 2,3 3,2 3,3}
    APSLabeledEntry .extra -parent $parent -gridPack "-column 0 -row 6 -columnspan 2 -sticky w" \
      -label "Extra options: " -textVariable userPlotOptions -width 60 \
      -contextHelp "Enter sddsplot options to be used for plotting."
}
APSApplication . -name SRFillToFillAtIDs 
set status ""
APSScrolledStatus .status -parent .userFrame -textVariable status -width 80 -height 4 \
    -withButtons 1 -packOption "-fill x -expand true" 
APSFrame .gridFrame -parent .userFrame -label "" -relief flat
set w .userFrame.gridFrame.frame
MakeIDChoiceFrame .id -parent $w -gridPack "-column 0 -row 0 -sticky n"
MakeFilterFrame .filter -parent $w -gridPack "-column 1 -row 0 -sticky n"
MakeCorrChoiceFrame .corr -parent $w -gridPack "-column 0 -row 1 -columnspan 2"
MakeDateTimeFrame .datetime -parent $w -gridPack "-column 0 -row 2 -columnspan 2"
MakePlotControls .plotcon -parent $w -gridPack "-column 0 -row 3 -columnspan 2"
MakeBPMDataChoiceFrame .bpm -parent $w -gridPack "-column 0 -row 4 -columnspan 2"
MakeButtonFrame .buttons -parent $w -gridPack "-column 0 -row 5 -columnspan 2"
GetBPMPositionData
SetBeamlineLength
APSDialogBox .plotWindow -name "Plot Command Execution" -packOption "-noPack 1"
APSScrolledText .text -parent .plotWindow.userFrame -width 60 -height 10
wm withdraw .plotWindow

set cacheFile $env(HOME)/.SRFillToFillAtIDs.cache
set status "Cached files: [APSLoadFileCacheTable -fileName $cacheFile -arrayRoot ID]"
