# # Copyright 2000, 2001 (c) Pointwise, Inc. # All rights reserved. # ############################################################################### ## ## DomainDiagnose.glf ## ## Script with Tk interface to diagnose all enabled domains in the system and ## write a written report. ## ############################################################################### # package require PWI_Glyph 1.1 global DomainDiagnoseArray catch { set scriptDir [file dirname [info script]] set logoFile [file join $scriptDir pwiLogo.glf] source $logoFile } namespace eval ::DomainDiagnose { # # buildGui - build all the widgets # proc buildGui { } { global DomainDiagnoseArray # Title bar wm title . "Domain Diagnostics" set DomainDiagnoseArray(top) [frame .top] set f [frame $DomainDiagnoseArray(top).titleFrame] pack $f -side top -fill x -pady 5 set l [label $f.label -text "Domain Diagnostics" -justify center] set font [$l cget -font] set fontFamily [font actual $font -family] set fontSize [font actual $font -size] set bigLabelFont [font create -family $fontFamily -weight bold \ -size [expr {2 * $fontSize}]] $l configure -font $bigLabelFont set regLabelFont [font create -family $fontFamily -weight bold \ -size [expr {int(1.25 * $fontSize)}]] pack $l -side top set f [frame $DomainDiagnoseArray(top).hr1 -height 2 -relief sunken \ -borderwidth 1] pack $f -side top -fill x -expand TRUE set DomainDiagnoseArray(gridFrame) \ [frame $DomainDiagnoseArray(top).gridFrame] # Create the columns of functions, min range values, and max range values set togCol 0 set minCol 1 set maxCol 2 set row 0 set l [label "$DomainDiagnoseArray(gridFrame).funcLabel" -text "Function" \ -justify center -font $regLabelFont] grid $l -column $togCol -row $row -sticky ew set l [label "$DomainDiagnoseArray(gridFrame).minLabel" -text "Min Range" \ -justify center -font $regLabelFont] grid $l -column $minCol -row $row -sticky ew set l [label "$DomainDiagnoseArray(gridFrame).maxLabel" -text "Max Range" \ -justify center -font $regLabelFont] grid $l -column $maxCol -row $row -sticky ew incr row foreach func $DomainDiagnoseArray(functions) { if {$DomainDiagnoseArray(${func}_Enabled)} { set state "normal" } else { set state "disabled" set DomainDiagnoseArray(${func}_On) 0 set DomainDiagnoseArray(${func}_Min) {} set DomainDiagnoseArray(${func}_Max) {} } if {$DomainDiagnoseArray(${func}_On)} { set entryState "normal" } else { set entryState "disabled" } # Toggle button set name "$DomainDiagnoseArray(gridFrame).tb_$func" set text "$DomainDiagnoseArray(${func}_Label)" set tb [checkbutton $name -indicatoron TRUE -state $state \ -variable DomainDiagnoseArray(${func}_On) -text $text \ -command [list ::DomainDiagnose::toggleCB $func]] grid $tb -column $togCol -row $row -sticky w # Min range set name "$DomainDiagnoseArray(gridFrame).min_$func" set e [entry $name -state $state \ -textvariable DomainDiagnoseArray(${func}_Min) \ -validate all -vcmd [list ::DomainDiagnose::validateCB $func "Min" %P]] setEntryState $e $entryState grid $e -column $minCol -row $row -sticky ew # Max range set name "$DomainDiagnoseArray(gridFrame).max_$func" set e [entry $name -state $state \ -textvariable DomainDiagnoseArray(${func}_Max) \ -validate all -vcmd [list ::DomainDiagnose::validateCB $func "Max" %P]] setEntryState $e $entryState grid $e -column $maxCol -row $row -sticky ew incr row } grid columnconfigure $DomainDiagnoseArray(gridFrame) $minCol -weight 1 grid columnconfigure $DomainDiagnoseArray(gridFrame) $maxCol -weight 1 pack $DomainDiagnoseArray(gridFrame) -side top -fill x -expand FALSE -padx 5 \ -pady 5 # Another separator set f [frame $DomainDiagnoseArray(top).hr2 -height 2 -relief sunken \ -borderwidth 1] pack $f -side top -fill x -expand FALSE # Buttons for controlling the output destination set outputFrame [frame $DomainDiagnoseArray(top).outputFrame] set l [label $outputFrame.l -text "Output:" -justify center] pack $l -side left -fill y -expand FALSE set DomainDiagnoseArray(output) "stdout" set rb [radiobutton $outputFrame.rb1 -indicatoron TRUE -value "stdout" \ -text "Console" -variable DomainDiagnoseArray(output) \ -command ::DomainDiagnose::changeOutputCB] pack $rb -side left -fill y -expand FALSE set rb [radiobutton $outputFrame.rb2 -indicatoron TRUE -value "file" \ -text "File" -variable DomainDiagnoseArray(output) \ -command ::DomainDiagnose::changeOutputCB] pack $rb -side left -fill y -expand FALSE set DomainDiagnoseArray(filenameEntry) [entry "$outputFrame.e" \ -state "disabled" -width 30 -textvariable DomainDiagnoseArray(filename)] pack $DomainDiagnoseArray(filenameEntry) -side left -fill x -expand TRUE \ -padx 3 set DomainDiagnoseArray(browseButton) [button "$outputFrame.b" \ -state "disabled" -text "..." -command ::DomainDiagnose::outputBrowserCB] pack $DomainDiagnoseArray(browseButton) -side left -fill none -expand FALSE setEntryState $DomainDiagnoseArray(filenameEntry) "disabled" pack $outputFrame -side top -fill x -expand TRUE -padx 5 -pady 5 # Another separator set f [frame $DomainDiagnoseArray(top).hr3 -height 2 -relief sunken \ -borderwidth 1] pack $f -side top -fill x -expand FALSE # Create the bottom buttons set f [frame $DomainDiagnoseArray(top).cmdFrame] set DomainDiagnoseArray(runButton) [button $f.run -width 8 -text "Run" \ -command [list ::DomainDiagnose::runCB]] pack $DomainDiagnoseArray(runButton) -side right -padx 5 set b [button $f.cancel -width 8 -text "Cancel" \ -command [list ::DomainDiagnose::cancelCB]] pack $b -side right -padx 5 if {![catch {pwiLogoCreate $f.logo 1} b]} { $b configure -bd 0 -relief flat pack $b -side left -padx 5 } pack $f -side top -fill x -expand FALSE -pady 5 pack $DomainDiagnoseArray(top) -expand TRUE -fill both updateRunStatus # Center the window ::tk::PlaceWindow . widget set w [winfo reqwidth $DomainDiagnoseArray(top)] set h [winfo reqheight $DomainDiagnoseArray(top)] wm resizable . 1 0 wm minsize . $w $h } # # showError - show an error message in a pop-up window # proc showError { msg title } { tk_messageBox -message $msg -title $title -type ok -icon error } # # printHeader - print a pretty header # proc printHeader { fd title } { set l [string length $title] set div [string repeat {=} 79] puts $fd "\n${div}" puts $fd "[string repeat { } [expr {int(40 - 0.5 * $l)}]]${title}" puts $fd "${div}\n" } # # diagnoseRange - crunch out a particular function for each domain # proc diagnoseRange { fd func } { global DomainDiagnoseArray printHeader $fd $DomainDiagnoseArray(${func}_Label) set nameLen 10 set headTextFmt "%-${nameLen}s%13s%13s%13s%10s%10s%10s" set headFmt "%-${nameLen}s%13s%13s%13s%10s%10s%10s" set dataFmt "%-${nameLen}s%13g%13g%13g%10d%10d%10d" set longFmt "%-s\n[string repeat { } ${nameLen}]%13g%13g%13g%10d%10d%10d" set hash [string repeat {-} 9] set minValue $DomainDiagnoseArray(${func}_Min) set maxValue $DomainDiagnoseArray(${func}_Max) # puts $fd [string repeat "123456789|" 8] set rangeArgs [list] if {![string equal "" $minValue]} { lappend rangeArgs -min $minValue } else { set minValue "n/a" } puts $fd "Minimum Range Value: $minValue" if {![string equal "" $maxValue]} { lappend rangeArgs -max $maxValue } else { set maxValue "n/a" } puts $fd "Maximum Range Value: $maxValue\n" puts $fd [format $headTextFmt "Domain" "Min" "Avg" "Max" \ "Below" "In Range" "Above"] set hashDiv [format $headFmt [string repeat {-} $nameLen] $hash $hash $hash \ $hash $hash $hash] puts $fd $hashDiv set count 0 # # Make a list of all domains; Get the total number of domains # set AllDoms [gg::domGetAll] set numDoms [llength $AllDoms] # # Set each domain identifier equal to a variable that can be output with its range data; # Run each domain through domExamine for chosen diagnostics; # for {set domain 1} {$domain <= $numDoms} {incr domain} { set dName [gg::domGetByNum $domain] if {[string length $dName] > ${nameLen}} { set fmt $longFmt } else { set fmt $dataFmt set dNameEval $dName set cmd [list gg::domExamine $dNameEval data $func] foreach arg $rangeArgs { lappend cmd $arg } eval $cmd } puts $fd [format $fmt $dName \ $data(valueMin) $data(valueAvg) $data(valueMax) \ $data(belowRange) $data(inRange) $data(aboveRange)] # Add up the totals set numCells [expr {$data(belowRange) + $data(inRange) + $data(aboveRange)}] if {0 == $count} { set total(min) $data(valueMin) set total(max) $data(valueMax) set total(num) $numCells set total(avg) [expr {$data(valueAvg) * $numCells}] set total(low) $data(belowRange) set total(mid) $data(inRange) set total(upp) $data(aboveRange) } else { if {$data(valueMin) < $total(min)} { set total(min) $data(valueMin) } if {$data(valueMax) > $total(max)} { set total(max) $data(valueMax) } set total(num) [expr {$total(num) + $numCells}] set total(avg) [expr {$total(avg) + ($data(valueAvg) * $numCells)}] set total(low) [expr {$total(low) + $data(belowRange)}] set total(mid) [expr {$total(mid) + $data(inRange)}] set total(upp) [expr {$total(upp) + $data(aboveRange)}] } incr count update idletasks } set total(avg) [expr {$total(avg) / $total(num)}] puts $fd $hashDiv puts $fd [format $dataFmt "Total" \ $total(min) $total(avg) $total(max) \ $total(low) $total(mid) $total(upp)] puts $fd "\n" } # # run - do the crunching # proc run { } { global DomainDiagnoseArray if {[string equal $DomainDiagnoseArray(output) "file"]} { if {[catch {open $DomainDiagnoseArray(filename) "w"} fd]} { showError $fd "Opening File" return } } else { set fd "stdout" } set title "Domain Diagnostics" set l [string length $title] set div1 [string repeat {*} 79] set div2 "**[string repeat { } 75]**" puts $fd "\n\n${div1}\n${div1}\n${div2}" set leadSp [expr {int(38 - 0.5 * $l)}] set trailSp [expr {75 - $l - $leadSp}] puts $fd "**[string repeat { } $leadSp]${title}[string repeat { } $trailSp]**" puts $fd "${div2}\n${div1}\n${div1}\n\n" foreach func $DomainDiagnoseArray(functions) { if {$DomainDiagnoseArray(${func}_On)} { $DomainDiagnoseArray(${func}_Evaluator) $fd $func } } if {[string equal $DomainDiagnoseArray(output) "file"]} { catch {file close $fd} } } # # runCB - callback for the run button # proc runCB { } { . configure -cursor watch update run exit } # # outputBrowserCB - callback for launching the file browser # proc outputBrowserCB { } { global DomainDiagnoseArray set types { {{Text Files} {.txt} } {{Log Files} {.log} } {{All Files} * } } set cmd [list tk_getSaveFile -title {Select Diagnostics Output File} \ -filetypes $types] set filename $DomainDiagnoseArray(filename) if {![string equal "" $filename]} { catch { set dir [file dirname $filename] if {![string equal "" $dir]} { lappend cmd -initialdir $dir } } catch { set name [file tail $filename] if {![string equal "" $name]} { lappend cmd -initialfile $name } } catch { set ext [file extension $filename] if {![string equal "" $ext]} { lappend cmd -defaultextension $ext } } } else { lappend cmd -defaultextension ".txt" } set filename [eval $cmd] if {![string equal "" $filename]} { set DomainDiagnoseArray(filename) $filename } } # # changeOutputCB - callback for changing the output type # proc changeOutputCB { } { global DomainDiagnoseArray if {[string equal "file" $DomainDiagnoseArray(output)]} { set state "normal" } else { set state "disabled" } setEntryState $DomainDiagnoseArray(filenameEntry) $state $DomainDiagnoseArray(browseButton) configure -state $state } # # cancelCB - callback for the cancel button # proc cancelCB { } { # Should only be called from GUI ::exit } # # setEntryState - controls the appearance of entry widgets # proc setEntryState { entry state } { set grey "#e0e0e0" set font "#000000" set error "#ffc0c0" set normal "#ffffff" switch -exact -- $state { "disabled" { $entry configure -background $grey -foreground $grey -state $state } "normal" { $entry configure -background $normal -foreground $font -state $state } default { $entry configure -background $error -foreground $font -state "normal" } } } # # toggleCB - callback for toggle buttons # proc toggleCB { func } { global DomainDiagnoseArray if {$DomainDiagnoseArray(${func}_On)} { set state "normal" checkRange $func "Min" $DomainDiagnoseArray(${func}_Min) } else { set state "disabled" setEntryState "$DomainDiagnoseArray(gridFrame).min_$func" "disabled" setEntryState "$DomainDiagnoseArray(gridFrame).max_$func" "disabled" set DomainDiagnoseArray(${func}_RangeValid) 1 } set minButton "$DomainDiagnoseArray(gridFrame).min_$func" set maxButton "$DomainDiagnoseArray(gridFrame).max_$func" $minButton configure -state $state $maxButton configure -state $state updateRunStatus } # # checkRange - check the min and max range values for validity # proc checkRange { func end newValue } { global DomainDiagnoseArray if {0 == $DomainDiagnoseArray(${func}_MinValid) || \ 0 == $DomainDiagnoseArray(${func}_MaxValid)} { set value 0 } else { if {[string equal $end "Max"]} { set minValue $DomainDiagnoseArray(${func}_Min) set maxValue $newValue } else { set minValue $newValue set maxValue $DomainDiagnoseArray(${func}_Max) } if {[string equal "" $minValue] || [string equal "" $maxValue]} { set value 1 } elseif {$minValue <= $maxValue} { set value 1 } else { set value 0 } } set DomainDiagnoseArray(${func}_RangeValid) $value set minButton "$DomainDiagnoseArray(gridFrame).min_$func" set maxButton "$DomainDiagnoseArray(gridFrame).max_$func" if {0 == $value} { setEntryState $minButton "error" setEntryState $maxButton "error" } else { setEntryState $minButton "normal" setEntryState $maxButton "normal" } return $value } # # validateCB - callback for changes to range text entry widgets # proc validateCB { func end newValue } { global DomainDiagnoseArray if {[string is double $newValue]} { set valid 1 } else { set valid 0 } set DomainDiagnoseArray(${func}_${end}Valid) $valid set rangeValid [checkRange $func $end $newValue] updateRunStatus return TRUE } # # updateRunStatus - sets the state of the run button # proc updateRunStatus { } { global DomainDiagnoseArray set activeFuncs 0 set state "normal" foreach func $DomainDiagnoseArray(functions) { if {$DomainDiagnoseArray(${func}_On)} { if {0 == $DomainDiagnoseArray(${func}_RangeValid)} { set state "disabled" break } incr activeFuncs } } if {0 == $activeFuncs} { set state "disabled" } $DomainDiagnoseArray(runButton) configure -state $state } # # setArray - conditionally sets an array element # proc setArray { arrayName overwrite element value } { upvar $arrayName a if {$overwrite || ![info exists a($element)]} { set a($element) $value } } # # init - initializes the DomainDiagnoseArray structure # proc init { } { global DomainDiagnoseArray set funcList [list] set labelList [list] set typeList [list] set evalList [list] foreach entry { {I_SIZE "I Size" "STRUCT" "diagnoseRange" } {J_SIZE "J Size" "STRUCT" "diagnoseRange" } {K_SIZE "K Size" "STRUCT" "diagnoseRange" } {AREA "AREA" "ANY" "diagnoseRange" } {I_RATIO "I Ratio" "STRUCT" "diagnoseRange" } {J_RATIO "J Ratio" "STRUCT" "diagnoseRange" } {K_RATIO "K Ratio" "STRUCT" "diagnoseRange" } {ASPECT_RATIO "Aspect Ratio" "ANY" "diagnoseRange" } {I_SMOOTHNESS "I Smoothness" "STRUCT" "diagnoseRange" } {J_SMOOTHNESS "J Smoothness" "STRUCT" "diagnoseRange" } {K_SMOOTHNESS "K Smoothness" "STRUCT" "diagnoseRange" } {MIN_ALPHA_SKEWNESS "Min Alpha Skewness" "ANY" "diagnoseRange" } {MAX_ALPHA_SKEWNESS "Max Alpha Skewness" "ANY" "diagnoseRange" } {EQUI_ANGLE_SKEWNESS "Equi-angle Skewness" "ANY" "diagnoseRange" } } { foreach {function label type evaluator} $entry {break} lappend funcList $function lappend labelList $label lappend typeList $type lappend evalList $evaluator } setArray DomainDiagnoseArray TRUE "functions" $funcList foreach function $DomainDiagnoseArray(functions) \ label $labelList type $typeList evaluator $evalList { setArray DomainDiagnoseArray TRUE "${function}_Label" $label setArray DomainDiagnoseArray TRUE "${function}_Evaluator" $evaluator setArray DomainDiagnoseArray TRUE "${function}_Type" $type setArray DomainDiagnoseArray TRUE "${function}_MinValid" 1 setArray DomainDiagnoseArray TRUE "${function}_MaxValid" 1 setArray DomainDiagnoseArray TRUE "${function}_RangeValid" 1 setArray DomainDiagnoseArray FALSE "${function}_On" 0 setArray DomainDiagnoseArray FALSE "${function}_Enabled" 1 setArray DomainDiagnoseArray FALSE "${function}_Min" {} setArray DomainDiagnoseArray FALSE "${function}_Max" {} setArray DomainDiagnoseArray FALSE "filename" "" } } # # prepare - disabled invalid functions based on present domain types # proc prepare { } { global DomainDiagnoseArray set haveStructured 0 set haveUnstructured 0 foreach domain $::DomainDiagnose::domains { gg::domReport $domain data STRUCTURE if {[string equal $data(type) "UNSTRUCTURED"]} { set haveUnstructured 1 } elseif {[string equal $data(type) "STRUCTURED"]} { set haveStructured 1 } if {$haveUnstructured && $haveStructured} { break } } if {$haveUnstructured} { foreach func $DomainDiagnoseArray(functions) { if {[string equal $DomainDiagnoseArray(${func}_Type) "STRUCT"]} { set DomainDiagnoseArray(${func}_Enabled) 0 } } } if {$haveStructured} { foreach func $DomainDiagnoseArray(functions) { if {[string equal $DomainDiagnoseArray(${func}_Type) "UNSTRUCT"]} { set DomainDiagnoseArray(${func}_Enabled) 0 } } } } # Get the list of enabled domains set domains [list] foreach domain [gg::domGetAll] { if {[gg::domEnable $domain]} { lappend domains $domain } } set numDomains [llength $domains] }; # End of namespace ::DomainDiagnose gg::tkLoad if {0 == $::DomainDiagnose::numDomains} { wm withdraw . update idletasks ::DomainDiagnose::showError "No enabled domains are present." \ "Domain Diagnose" exit } else { ::DomainDiagnose::init ::DomainDiagnose::prepare ::DomainDiagnose::buildGui gg::tkLoop } gg::tkLoop # # DISCLAIMER: # TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, POINTWISE DISCLAIMS # ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED # TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE, WITH REGARD TO THIS SCRIPT. TO THE MAXIMUM EXTENT PERMITTED BY # APPLICABLE LAW, IN NO EVENT SHALL POINTWISE BE LIABLE TO ANY PARTY FOR # ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER # (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS # INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR # INABILITY TO USE THIS SCRIPT EVEN IF POINTWISE HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES AND REGARDLESS OF THE FAULT OR NEGLIGENCE OF # POINTWISE. #