diff options
Diffstat (limited to 'ds9/library/analysis.tcl')
-rw-r--r-- | ds9/library/analysis.tcl | 1958 |
1 files changed, 1958 insertions, 0 deletions
diff --git a/ds9/library/analysis.tcl b/ds9/library/analysis.tcl new file mode 100644 index 0000000..da1de2e --- /dev/null +++ b/ds9/library/analysis.tcl @@ -0,0 +1,1958 @@ +# Copyright (C) 1999-2016 +# Smithsonian Astrophysical Observatory, Cambridge, MA, USA +# For conditions of distribution and use, see copyright notice in "copyright" + +package provide DS9 1.0 + +proc AnalysisDef {} { + global ianalysis + global panalysis + + global ds9 + + set ianalysis(menu,count) 0 + set ianalysis(menu,hmenu,count) 0 + set ianalysis(menu,hmenu) {} + set ianalysis(bind,count) 0 + set ianalysis(param,count) 0 + set ianalysis(param,seq) 0 + set ianalysis(file) ".$ds9(app).ans" + set ianalysis(alt) ".$ds9(app).analysis" + + # prefs only + set panalysis(log) 0 + set panalysis(autoload) 1 + set panalysis(user) {} + set panalysis(user2) {} + set panalysis(user3) {} + set panalysis(user4) {} +} + +proc OpenAnalysisMenu {} { + set fn [OpenFileDialog analysisfbox] + if {$fn != {}} { + ProcessAnalysisFile $fn + } +} + +proc ClearAnalysisMenu {} { + global pds9 + + if {$pds9(confirm)} { + if {[tk_messageBox -type okcancel -icon question -message [msgcat::mc {Clear External Analysis Commands?}]] != {ok}} { + return + } + } + ClearAnalysis +} + +# Analysis Menu Delete +proc ClearAnalysis {} { + global ds9 + global ianalysis + + # is something loaded? + if {$ianalysis(menu,count) == 0} { + return + } + + # delete cascade menus + for {set ii 0} {$ii<$ianalysis(menu,hmenu,count)} {incr ii} { + destroy [lindex $ianalysis(menu,hmenu) $ii] + } + set ianalysis(menu,hmenu) {} + set ianalysis(menu,hmenu,count) 0 + + # clear menu + $ds9(mb).analysis delete $ds9(menu,size,analysis) end + + for {set ii 0} {$ii<$ianalysis(menu,count)} {incr ii} { + unset ianalysis(menu,$ii,parent) + unset ianalysis(menu,$ii,item) + unset ianalysis(menu,$ii,template) + unset ianalysis(menu,$ii,cmd) + unset ianalysis(menu,$ii,inuse) + unset ianalysis(menu,$ii,var) + } + set ianalysis(menu,count) 0 + + # clear all bindings, first + + foreach ff $ds9(frames) { + for {set ii 0} {$ii<$ianalysis(bind,count)} {incr ii} { + $ds9(canvas) bind $ff "$ianalysis(bind,$ii,item)" {} + } + } + + # clear bindings + + for {set ii 0} {$ii<$ianalysis(bind,count)} {incr ii} { + unset ianalysis(bind,$ii,item) + unset ianalysis(bind,$ii,template) + unset ianalysis(bind,$ii,cmd) + unset ianalysis(bind,$ii,inuse) + } + set ianalysis(bind,count) 0 + + # clear params + + for {set ii 0} {$ii<$ianalysis(param,count)} {incr ii} { + for {set jj 0} {$jj<$ianalysis(param,$ii,count)} {incr jj} { + unset ianalysis(param,$ii,$jj,var) + unset ianalysis(param,$ii,$jj,type) + unset ianalysis(param,$ii,$jj,title) + unset ianalysis(param,$ii,$jj,default) + unset ianalysis(param,$ii,$jj,last) + unset ianalysis(param,$ii,$jj,value) + unset ianalysis(param,$ii,$jj,info) + } + unset ianalysis(param,$ii,count) + unset ianalysis(param,$ii) + } + set ianalysis(param,count) 0 +} + +proc InitAnalysisFile {} { + global ianalysis + global panalysis + global ds9 + + set done {} + + # autoload + if {$panalysis(autoload)} { + foreach dir [list {.} "[GetEnvHome]/bin" {/usr/local/bin} {/opt/local/bin} {/soft/saord/bin}] { + foreach fn [glob -directory $dir -nocomplain "*.ds9"] { + if {[file exists $fn]} { + ProcessAnalysisFile $fn + lappend done $fn + } + } + } + } + + # default name ds9.ans + # backward compatible ds9.analysis + foreach ff {{.} {~}} { + foreach gg {{} {.}} { + foreach ext {{ans} {analysis}} { + set fn "$ff/$gg$ds9(app).$ext" + if {[file exists $fn]} { + if {[lsearch $done $fn] == -1} { + ProcessAnalysisFile $fn + lappend done $fn + } + } + } + } + } + + # user specified + foreach ii {{user} {user2} {user3} {user4}} { + if {[info exists panalysis($ii)]} { + set fn $panalysis($ii) + if {[file exists $fn]} { + if {[lsearch $done $fn] == -1} { + ProcessAnalysisFile $fn + lappend done $fn + } + } + } + } + + UpdateAnalysisMenu +} + +proc ProcessAnalysisFile {fn} { + global env + + # check for simple file + if {[file exists "$fn"] && + [file isfile "$fn"] && + ![file executable "$fn"] && + ![file isdirectory "$fn"]} { + + set ch [open $fn r] + set data [read $ch] + close $ch + + if {![ProcessAnalysis data]} { + Error "[msgcat::mc {Unable to process Analysis file}] $fn" + return + } + + # add directory to path + set env(PATH) "[file dirname $fn]:$env(PATH)" + } else { + Error "[msgcat::mc {Unable to open file}] $fn" + } +} + +proc ProcessAnalysis {varname} { + upvar $varname var + + global ds9 + global ianalysis + + # simple check for ascii data + if {![string is ascii $var]} { + return 0 + } + + set state 1 + set baseparent $ds9(mb).analysis + set currentparent $baseparent + set parentstack $baseparent + + $baseparent add separator + + set lines [split $var \n] + set l [llength $lines] + + for {set ii 0} {$ii<$l} {incr ii} { + set line [string trim [lindex $lines $ii]] + + # eat empty lines and comments for all except help + if {$state != 6} { + # empty line + if {[string length $line] == 0} continue + + # comments + if {[string range $line 0 0] == "\#"} continue + + # strip any end of line comments + set id [string first "\#" $line] + if {$id > 0} { + set line [string range $line 0 [expr $id-1]] + } + } + + switch -- $state { + 1 { + # param + if {[lindex $line 0] == {param}} { + if {[lindex $line 1] != {}} { + set ianalysis(param,$ianalysis(param,count)) \ + [lindex $line 1] + set ianalysis(param,$ianalysis(param,count),count) 0 + set state 5 + } + continue + } + + # help + if {[lindex $line 0] == {help}} { + set id [string first " " $line] + if {$id > 0} { + set item [string range $line [expr $id+1] end] + } else { + set item Help + } + + set i $ianalysis(menu,count) + set ianalysis(menu,$i,parent) $currentparent + set ianalysis(menu,$i,item) $item + set ianalysis(menu,$i,template) {*} + set ianalysis(menu,$i,cmd) {help} + set ianalysis(menu,$i,inuse) 0 + set ianalysis(menu,$i,var) {} + $currentparent add command -label $item \ + -command [list AnalysisTask $i menu] + + set state 6 + continue + } + + # hmenu + if {[lindex $line 0] == {hmenu}} { + set id [string first " " $line] + if {$id > 0} { + set item [string range $line [expr $id+1] end] + } else { + set item Tasks + } + + # make the menu label unique + set nmenu "$currentparent.hmenu$ianalysis(menu,hmenu,count)" + lappend ianalysis(menu,hmenu) $nmenu + incr ianalysis(menu,hmenu,count) + + menu $nmenu + $currentparent add cascade -label "$item" -menu $nmenu + + set currentparent $nmenu + lappend parentstack $currentparent + continue + } + + # end hmenu + if {[lindex $line 0] == {endhmenu} || + [lindex $line 0] == {end}} { + set parentstack [lreplace $parentstack end end] + set currentparent [lindex $parentstack end] + continue + } + + if {[lindex $line 0] == {---}} { + $currentparent add separator + continue + } + + # assume new command + + set item "$line" + set template {} + set type {} + set cmd {} + set state 2 + } + + 2 { + set template "$line" + set state 3 + } + + 3 { + set type "$line" + set state 4 + } + + 4 { + set cmd "$line" + if {$item != {} && $template != {} && + $type != {} && $cmd != {}} { + switch -- [lindex $type 0] { + bind { + set b [lindex $type 1] + if {$b != {}} { + set i $ianalysis(bind,count) + set ianalysis(bind,$i,item) "<$b>" + set ianalysis(bind,$i,template) "$template" + set ianalysis(bind,$i,cmd) "$cmd" + set ianalysis(bind,$i,inuse) 0 + incr ianalysis(bind,count) + } + } + web { + set i $ianalysis(menu,count) + set ianalysis(menu,$i,parent) $currentparent + set ianalysis(menu,$i,item) $item + set ianalysis(menu,$i,template) "$template" + set ianalysis(menu,$i,cmd) {web} + set ianalysis(menu,$i,inuse) 0 + set ianalysis(menu,$i,var) "$cmd" + $currentparent add command -label "$item" \ + -command [list AnalysisTask $i menu] + incr ianalysis(menu,count) + } + menu { + set i $ianalysis(menu,count) + set ianalysis(menu,$i,parent) $currentparent + set ianalysis(menu,$i,item) "$item" + set ianalysis(menu,$i,template) "$template" + set ianalysis(menu,$i,cmd) "$cmd" + set ianalysis(menu,$i,inuse) 0 + set ianalysis(menu,$i,var) {} + $currentparent add check -label "$item" \ + -command [list AnalysisTask $i menu] \ + -variable ianalysis(menu,$i,inuse) \ + -selectcolor green + incr ianalysis(menu,count) + } + default { + # something really wrong here, abort + return 0 + } + } + } + set state 1 + } + + 5 { + # end param + if {[lindex $line 0] == {endparam} || + [lindex $line 0] == {end}} { + incr ianalysis(param,count) + set state 1 + continue + } + + if {[string range $line 0 0] == {@}} { + ParseIRAFParam [string range $line 1 end] + continue + } + + set i $ianalysis(param,count) + set j $ianalysis(param,$i,count) + set ianalysis(param,$i,$j,var) [lindex $line 0] + set ianalysis(param,$i,$j,type) [lindex $line 1] + set ianalysis(param,$i,$j,title) [lindex $line 2] + + # default can contain the full menu 'aaa|bbb|ccc' + set ianalysis(param,$i,$j,default) [lindex $line 3] + # set last to first item + set ianalysis(param,$i,$j,last) \ + [lindex [split [lindex $line 3] |] 0] + # and set value to last + set ianalysis(param,$i,$j,value) \ + $ianalysis(param,$i,$j,last) + + set ianalysis(param,$i,$j,info) [lindex $line 4] + incr ianalysis(param,$i,count) + } + + 6 { + # end help + if {[lindex $line 0] == {endhelp} || + [lindex $line 0] == {end}} { + incr ianalysis(menu,count) + set state 1 + continue + } + + set i $ianalysis(menu,count) + append ianalysis(menu,$i,var) "$line\n" + } + } + } + + # events + UnBindEventsCanvas + BindEventsCanvas + + UpdateAnalysisMenu + + return 1 +} + +proc AnalysisTask {i which {frame {}} {x 0} {y 0} {sync 0}} { + global ianalysis + global current + + if {$frame == {}} { + set frame $current(frame) + } + + switch -- $ianalysis($which,$i,cmd) { + help { + AnalysisText "at${which}${i}" $ianalysis($which,$i,item) \ + $ianalysis($which,$i,var) insert + } + web { + if {$frame != {}} { + AnalysisWebDoit $i $which $frame $x $y $sync + } + } + default { + if {$frame != {}} { + AnalysisTaskDoit $i $which $frame $x $y $sync + } + } + } +} + +proc AnalysisWebDoit {i which frame x y sync} { + global ianalysis + global panalysis + + set cmd "$ianalysis($which,$i,var)" + + # do select macro expansion + + # escaped macros + SetEscapedMacros cmd + + # $xpa_method + ParseXPAMethodMacro cmd + + # $xpa + ParseXPAMacro cmd + + # $vo_method + ParseVOMethodMacro cmd + + # $xdim,$ydim,$bitpix + ParseXYBitpixMacro cmd $frame + + # $filename[$regions] + ParseFilenameRegionMacro cmd $frame + + # $filename + ParseFilenameMacro cmd $frame + + # $filedialog + ParseFileDialogMacro cmd + + # $regions + ParseRegionMacro cmd $frame + + # $env + ParseEnvMacro cmd + + # $pan + ParsePanMacro cmd $frame + + # $value + ParseValueMacro cmd $frame $x $y + + # $x,$y + ParseXYMacro cmd $frame $x $y + + # $z + ParseZMacro cmd $frame + + # escaped macros + UnsetEscapedMacros cmd + + if {$panalysis(log)} { + SimpleTextDialog acmd [msgcat::mc {Analysis Commands}] \ + 80 20 append bottom "$cmd\n" + } + + HVAnalysisCmd "at${which}${i}" "$ianalysis($which,$i,item)" "$cmd" $sync +} + +proc AnalysisTaskDoit {i which frame x y sync} { + global ianalysis + global pds9 + + if {[info exists ianalysis($which,$i,pid)]} { + set ianalysis($which,$i,inuse) 1 + + if {$pds9(confirm)} { + if {[tk_messageBox -type okcancel -icon question -message [msgcat::mc {This analysis task is already running. Do you wish to kill it?}]] != {ok}} { + return + } + } + + if {[info exists ianalysis($which,$i,pid)]} { + if {$ianalysis($which,$i,pid)>0} { + eval "exec kill -9 $ianalysis($which,$i,pid)" + } else { + HVAnalysisCancel $which $i + } + } + + return + } + + # don't turn on til task has started + set ianalysis($which,$i,inuse) 0 + + set ianalysis($which,$i,start) {} + set ianalysis($which,$i,start,fn) {} + set ianalysis($which,$i,start,url) {} + set ianalysis($which,$i,finish) {} + set ianalysis($which,$i,result) {} + set ianalysis($which,$i,plot,title) {} + set ianalysis($which,$i,plot,xaxis) {} + set ianalysis($which,$i,plot,yaxis) {} + set ianalysis($which,$i,plot,dim) 2 + set ianalysis($which,$i,image) {} + + set cmd $ianalysis($which,$i,cmd) + + # escaped macros + SetEscapedMacros cmd + + # $data + ParseDataMacro cmd $which $i + + # $xpa_method + ParseXPAMethodMacro cmd + + # $xpa + ParseXPAMacro cmd + + # $vo_method + ParseVOMethodMacro cmd + + # $xdim,$ydim,$bitpix + ParseXYBitpixMacro cmd $frame + + # $filename[$regions] + ParseFilenameRegionMacro cmd $frame + + # $filename + ParseFilenameMacro cmd $frame + + # $filedialog + ParseFileDialogMacro cmd + + # $regions + ParseRegionMacro cmd $frame + + # $env + ParseEnvMacro cmd + + # $cen + ParsePanMacro cmd $frame + + # $value + ParseValueMacro cmd $frame $x $y + + # $x,$y + ParseXYMacro cmd $frame $x $y + + # $z + ParseZMacro cmd $frame + + # $message + if {![ParseMessageMacro cmd]} { + AnalysisTaskEnd $which $i + return + } + + # $entry + if {![ParseEntryMacro cmd]} { + AnalysisTaskEnd $which $i + return + } + + # $param + if {![ParseParamMacro cmd]} { + AnalysisTaskEnd $which $i + return + } + + # $text + ParseTextMacro cmd $which $i + + # $plot + ParsePlotMacro cmd $which $i + + # $null + ParseNullMacro cmd $which $i + + # $url + ParseURLMacro cmd $which $i + + # $geturl + # do this next to last + ParseGetURLMacro cmd $which $i + + # $image + # do this last + ParseImageMacro cmd $which $i + + # escaped macros + UnsetEscapedMacros cmd + + # ok, we are off and running + set ianalysis($which,$i,inuse) 1 + + switch -- $ianalysis($which,$i,start) { + geturl { + AnalysisGetURL $which $i $sync + } + default { + AnalysisPipe $which $i $cmd $sync + } + } +} + +proc AnalysisPipe {which i cmd sync} { + global ianalysis + global panalysis + global current + + switch -- $ianalysis($which,$i,start) { + data {$current(frame) save fits image file "\{$ianalysis($which,$i,start,fn)\}"} + url {GetFileURL $ianalysis($which,$i,start,url) ianalysis($which,$i,start,fn)} + } + + # last step, change all '][' into ',' so that multiple filters work right + regsub -all {\]\[} $cmd "," cmd + + # log the command, if necessary + if {$panalysis(log)} { + SimpleTextDialog acmd [msgcat::mc {Analysis Commands}] \ + 80 20 append bottom "$cmd\n" + } + + switch -- $ianalysis($which,$i,finish) { + null { + # nothing is returned, so there is aways an error, + # however, the command will be executed. + catch {open "| $cmd"} + global errorInfo + set errorInfo {} + AnalysisTaskEnd $which $i + return + } + default { + if {[catch {set ch [open "| $cmd"]}]} { + Error [msgcat::mc {An error has occurred invoking the Analysis task}] + AnalysisTaskEnd $which $i + return + } + set ianalysis($which,$i,pid) [pid $ch] + + switch -- $ianalysis($which,$i,finish) { + image { + switch -- $ianalysis($which,$i,image) { + new {CreateFrame} + rgb {CreateRGBFrame} + 3d {Create3DFrame} + current {} + } + global loadParam + set loadParam(load,type) channel + set loadParam(load,layer) {} + set loadParam(channel,name) $ch + set loadParam(file,type) fits + set loadParam(file,mode) {} + set loadParam(file,name) \ + "[string tolower [lindex $ianalysis($which,$i,item) 0]].fits" + + StartLoad + ProcessLoad + FinishLoad + + AnalysisTaskEnd $which $i + } + default { + if {$sync} { + AnalysisReaderAppend $ch $which $i + AnalysisReaderFinish $ch $which $i + } else { + fileevent $ch readable \ + [list AnalysisReader $ch $which $i] + fconfigure $ch -blocking 0 -buffering none + } + } + } + } + } +} + +proc AnalysisReader {ch which i} { + global ianalysis + + if {[eof $ch]} { + AnalysisReaderFinish $ch $which $i + return + } + AnalysisReaderAppend $ch $which $i +} + +proc AnalysisReaderAppend {ch which i} { + global ianalysis + + set r [read $ch] + # for real-time update + switch -- $ianalysis($which,$i,finish) { + text { + AnalysisText "at${which}${i}" $ianalysis($which,$i,item) $r append + + global debug + if {$debug(tcl,idletasks)} { + puts stderr "AnalysisReader" + } + update idletasks + } + } + append ianalysis($which,$i,result) $r +} + +proc AnalysisReaderFinish {ch which i} { + global ianalysis + + catch {close $ch} + + switch -- $ianalysis($which,$i,finish) { + null - + image - + text {} + plot { + PlotLine "at${which}${i}" \ + $ianalysis($which,$i,item) \ + $ianalysis($which,$i,plot,title) \ + $ianalysis($which,$i,plot,xaxis) \ + $ianalysis($which,$i,plot,yaxis) \ + $ianalysis($which,$i,plot,dim) \ + $ianalysis($which,$i,result) + } + plotstdin { + AnalysisPlotStdin line "at${which}${i}" $ianalysis($which,$i,item) \ + $ianalysis($which,$i,result) + } + default {puts stdout $ianalysis($which,$i,result)} + } + + AnalysisTaskEnd $which $i +} + +proc AnalysisPlotStdin {type w wtt result} { + # if no result, just return + if {$result == {}} { + return + } + + # check for $ERROR + set id [string first {$ERROR} $result] + if {$id >= 0} { + AnalysisText "${w}e" $wtt \ + [string range $result [expr $id+1] end] append + return + } + + # check for ERROR: + set id [string first {ERROR:} $result] + if {$id >= 0} { + AnalysisText "${w}e" $wtt [string range $result $id end] append + return + } + + # check for $BEGINTEXT/$ENDTEXT + # assume each is followed by a \n, so skip it + if {[string range $result 0 9] == {$BEGINTEXT}} { + set eid [string first {$ENDTEXT} $result] + if {$eid > 0} { + AnalysisText "${w}t" $wtt \ + [string range $result 11 [expr $eid-1]] append + set result [string range $result [expr $eid+9] end] + } else { + # looks like all text + AnalysisText "${w}t" $wtt [string range $result 11 end] append + return + } + } + + # now find the title, x axis label, y axis label, and dimension + set id [string first "\n" $result] + set tt [string range $result 0 $id] + set rr [string range $result [expr $id+1] end] + + set l [llength $tt] + set t [join [lrange $tt 0 [expr $l-4]]] + set x [lindex $tt [expr $l-3]] + set y [lindex $tt [expr $l-2]] + set d [lindex $tt [expr $l-1]] + + if {$d != {} && $rr != {}} { + switch $type { + line {PlotLine $w $wtt $t $x $y $d $rr} + bar {PlotBar $w $wtt $t $x $y $d $rr} + scatter {PlotScatter $w $wtt $t $x $y $d $rr} + } + } else { + Error "[msgcat::mc {Error}] [string range $tt 0 40]" + } +} + +proc AnalysisGetURL {which i sync} { + global ianalysis + global panalysis + + if {![ParseURL $ianalysis($which,$i,start,url) r]} { + Error [msgcat::mc {An error has occurred invoking the Analysis task}] + AnalysisTaskEnd $which $i + return + } + + # format all spaces and brackets + set url {} + regsub -all { } $ianalysis($which,$i,start,url) "%20" url + regsub -all {\[} $url "%5B" url + regsub -all {\]} $url "%5D" url + + if {$panalysis(log)} { + SimpleTextDialog acmd [msgcat::mc {Analysis Commands}] \ + 80 20 append bottom "$url\n" + } + + set ianalysis($which,$i,pid) -1 + HVAnalysisURL $which $i $url $sync +} + +proc AnalysisProcessGetURL {which i result} { + global ianalysis + + set ianalysis($which,$i,result) $result + switch -- $ianalysis($which,$i,finish) { + text {AnalysisText "at${which}${i}" $ianalysis($which,$i,item) \ + $ianalysis($which,$i,result) append} + plot {PlotLine "at${which}${i}" \ + $ianalysis($which,$i,item) \ + $ianalysis($which,$i,plot,title) \ + $ianalysis($which,$i,plot,xaxis) \ + $ianalysis($which,$i,plot,yaxis) \ + $ianalysis($which,$i,plot,dim) \ + $ianalysis($which,$i,result)} + plotstdin {AnalysisPlotStdin line "at${which}${i}" \ + $ianalysis($which,$i,item) \ + $ianalysis($which,$i,result)} + image { + set fn "[string tolower [lindex $ianalysis($which,$i,item) 0]].fits" + LoadVar result $fn {} {} + } + default {Error $ianalysis($which,$i,result)} + } +} + +proc AnalysisTaskEnd {which i} { + global ianalysis + + set ianalysis($which,$i,inuse) 0 + if {$ianalysis($which,$i,start,fn) != {}} { + if {[file exists $ianalysis($which,$i,start,fn)]} { + catch {file delete -force $ianalysis($which,$i,start,fn)} + } + } + + if {[info exists ianalysis($which,$i,pid)]} { + unset ianalysis($which,$i,pid) + } + unset ianalysis($which,$i,start) + unset ianalysis($which,$i,start,fn) + unset ianalysis($which,$i,start,url) + unset ianalysis($which,$i,finish) + unset ianalysis($which,$i,result) + unset ianalysis($which,$i,plot,title) + unset ianalysis($which,$i,plot,xaxis) + unset ianalysis($which,$i,plot,yaxis) + unset ianalysis($which,$i,plot,dim) + unset ianalysis($which,$i,image) +} + +proc SetEscapedMacros {cmdname} { + upvar $cmdname cmd + global xpa + + set seq "WaJaWaJaW" + if {[regexp {\$\$} $cmd]} { + # fill with tempory sequence + regsub -all {\$\$} $cmd $seq cmd + } +} + +proc UnsetEscapedMacros {cmdname} { + upvar $cmdname cmd + global xpa + + set seq "WaJaWaJaW" + if {[regexp $seq $cmd]} { + # reset to $ + regsub -all $seq $cmd {\$} cmd + } +} + +proc ParseDataMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp {\$data.?\|} + if {[regexp $exp $cmd]} { + set ianalysis($which,$i,start) data + set ianalysis($which,$i,start,fn) [tmpnam {.fits}] + + regsub $exp $cmd "cat \{$ianalysis($which,$i,start,fn)\} |" cmd + } +} + +proc ParseVOMethodMacro {cmdname} { + upvar $cmdname cmd + global pvo + + if {[regexp {\$vo_method} $cmd]} { + regsub -all {\$vo_method} $cmd $pvo(method) cmd + } +} + +proc ParseXPAMethodMacro {cmdname} { + upvar $cmdname cmd + global ds9 + + if {[regexp {\$xpa_method} $cmd]} { + regsub -all {\$xpa_method} $cmd [XPAMethod] cmd + } +} + +proc ParseXPAMacro {cmdname} { + upvar $cmdname cmd + global ds9 + + if {[regexp {\$xpa} $cmd]} { + regsub -all {\$xpa} $cmd $ds9(title) cmd + } +} + +proc ParseXYBitpixMacro {cmdname frame} { + upvar $cmdname cmd + + if {$frame != {}} { + if {[regexp {\$width} $cmd]} { + regsub -all {\$width} $cmd [$frame get fits width] cmd + } + + if {[regexp {\$height} $cmd]} { + regsub -all {\$height} $cmd [$frame get fits height] cmd + } + + if {[regexp {\$depth} $cmd]} { + regsub -all {\$depth} $cmd [$frame get fits depth 2] cmd + } + + if {[regexp {\$bitpix} $cmd]} { + regsub -all {\$bitpix} $cmd [$frame get fits bitpix] cmd + } + + if {[regexp {\$xdim} $cmd]} { + regsub -all {\$xdim} $cmd [$frame get fits width] cmd + } + + if {[regexp {\$ydim} $cmd]} { + regsub -all {\$ydim} $cmd [$frame get fits height] cmd + } + } +} + +proc ParseFilenameRegionMacro {cmdname frame} { + upvar $cmdname cmd + + set exp {(\$filename)\[(\$regions\(([^)]*)\))\]} + while {[regexp $exp $cmd foo fn reg pp]} { + set type ds9 + set prop {} + set sys physical + set sky fk5 + set format degrees + + # default for mosaics + if {$frame != {}} { + if {[$frame has fits mosaic]} { + set sys wcs + } + } + + foreach p [split $pp ,] { + switch -- $p { + ds9 - + ciao - + saotng - + saoimage - + pros - + xy {set type $p} + + include {append prop {include = yes }} + exclude {append prop {include = no }} + source {append prop {source = yes }} + background {append prop {source = no }} + + image - + physical - + detector - + amplifier + wcs - + wcsa - + wcsb - + wcsc - + wcsd - + wcse - + wcsf - + wcsg - + wcsh - + wcsi - + wcsj - + wcsk - + wcsl - + wcsm - + wcsn - + wcso - + wcsp - + wcsq - + wcsr - + wcss - + wcst - + wcsu - + wcsv - + wcsw - + wcsx - + wcsy - + wcsz {set sys $p} + + fk4 - + b1950 - + fk5 - + j2000 - + icrs - + galactic - + ecliptic { + if {"$sys"=="physical"} { + set sys wcs + } + set sky $p + } + + hms {set format sexagesimal} + sexagesimal - + degrees {set format $p} + } + } + + SubstFilenameRegion cmd $frame $exp $type $prop $sys $sky $format + } + + set exp {(\$filename)\[(\$regions)\]} + while {[regexp $exp $cmd foo fn reg]} { + set type ds9 + set prop {} + set sys physical + set sky fk5 + set format degrees + + # default for mosaics + if {$frame != {}} { + if {[$frame has fits mosaic]} { + set sys wcs + } + } + + SubstFilenameRegion cmd $frame $exp $type $prop $sys $sky $format + } +} + +proc SubstFilenameRegion {cmdname frame exp type prop sys sky format} { + upvar $cmdname cmd + global ianalysis + + set fn [$frame get fits file name full] + set region [string trimright [$frame marker list $type $sys $sky $format yes $prop] ";"] + + if {$region != {}} { + set sub {} + foreach f $fn { + append sub "$f\[$region\] " + } + } else { + set sub $fn + } + + # substitute + # ok, we need to check the length + if {[string length $region] > 256} { + # since we are writing to a file, + # we don't have to worry about quoting + # special characters + set fn [tmpnam {.reg}] + incr ianalysis(param,seq) + + if {![catch {set ch [open "$fn" w]}]} { + puts $ch "$sub" + close $ch + } + + regsub $exp $cmd "\@$fn" cmd + + } else { + CleanFileName sub + regsub $exp $cmd $sub cmd + } +} + +proc ParseFilenameMacro {cmdname frame} { + upvar $cmdname cmd + + set exp {\$filename\(([^)]*)\)} + if {[regexp $exp $cmd foo pp]} { + switch $pp { + root - + root,base { + set sub [join [$frame get fits file name root base]] + CleanFileName sub + regsub -all $exp $cmd $sub cmd + } + full - + full,base { + set sub [join [$frame get fits file name full base]] + CleanFileName sub + regsub -all $exp $cmd $sub cmd + } + } + } + + set exp {\$filename} + if {[regexp $exp $cmd]} { + set sub [join [$frame get fits file name full]] + CleanFileName sub + regsub -all $exp $cmd $sub cmd + } +} + +proc ParseFileDialogMacro {cmdname} { + upvar $cmdname cmd + + set exp {\$filedialog\(open\)} + if {[regexp $exp $cmd]} { + set sub [OpenFileDialog analysisparamfbox] + regsub -all $exp $cmd $sub cmd + } + + set exp {\$filedialog\(save\)} + if {[regexp $exp $cmd]} { + set sub [SaveFileDialog analysisparamfbox] + regsub -all $exp $cmd $sub cmd + } +} + +proc CleanFileName {varname} { + upvar $varname sub + + # we have to quote {"}, else problems down the road + regsub -all {\"} $sub {\\"} sub + + # we have to quote {&}, else problems down the road + regsub -all {\&} $sub {\\&} sub +} + +proc ParseRegionMacro {cmdname frame} { + upvar $cmdname cmd + + set exp {\$regions\(([^)]*)\)} +while {[regexp $exp $cmd foo pp]} { + + set type ds9 + set prop {} + set sys physical + set sky fk5 + set format degrees + + # default for mosaics + if {$frame != {}} { + if {[$frame has fits mosaic]} { + set sys wcs + } + } + + foreach p [split $pp ,] { + switch -- $p { + ds9 - + ciao - + saotng - + saoimage - + pros - + xy {set type $p} + + include {append prop {include = yes }} + exclude {append prop {include = no }} + source {append prop {source = yes }} + background {append prop {source = no }} + + image - + physical - + detector - + amplifier - + wcs - + wcsa - + wcsb - + wcsc - + wcsd - + wcse - + wcsf - + wcsg - + wcsh - + wcsi - + wcsj - + wcsk - + wcsl - + wcsm - + wcsn - + wcso - + wcsp - + wcsq - + wcsr - + wcss - + wcst - + wcsu - + wcsv - + wcsw - + wcsx - + wcsy - + wcsz {set sys $p} + + fk4 - + b1950 - + fk5 - + j2000 - + icrs - + galactic - + ecliptic { + if {"$sys"=="physical"} { + set sys wcs + } + set sky $p + } + + hms {set format sexagesimal} + sexagesimal - + degrees {set format $p} + } + } + + SubstRegion cmd $frame $exp $type $prop $sys $sky $format +} + +# SAOtng format +set exp {\$((|include|exclude|source|background)_)?regions(_(|degrees|hms|pixels))?} +while {[regexp $exp $cmd foo a prop b sys]} { + + # check valid props + switch -- $prop { + include {set prop {include = yes}} + exclude {set prop {include = no}} + source {set prop {source = yes}} + background {set prop {source = no}} + default {set prop {}} + } + + # check valid coordinate systems + set sky fk5 + switch -- $sys { + degrees {set sys wcs; set format degrees} + hms {set sys wcs; set format sexagesimal} + pixels - + default {set sys physical; set format degrees} + } + + SubstRegion cmd $frame $exp ds9 $prop $sys $sky $format +} +} + +proc SubstRegion {cmdname frame exp type prop sys sky format} { + upvar $cmdname cmd + global ianalysis + + # get any regions + set region [string trimright [$frame marker list $type $sys $sky $format yes $prop] ";"] + + # substitute + # ok, we need to check the length + if {[string length $region] > 8192} { + # since we are writing to a file, we don't have to worry about quoting + # special characters + set fn [tmpnam {.reg}] + incr ianalysis(param,seq) + + if {![catch {set ch [open "$fn" w]}]} { + puts $ch "$region" + close $ch + } + + regsub $exp $cmd "\@$fn" cmd + + } else { + # we have to quote {"}, else problems down the road + regsub -all {\"} $region {\\"} region + + # we have to quote {&}, else problems down the road + regsub -all {\&} $region {\\&} region + + regsub $exp $cmd $region cmd + } +} + +proc ParseEnvMacro {cmdname} { + upvar $cmdname cmd + global env + + set exp {\$env\(([^)]*)\)} +if {[regexp $exp $cmd foo ee]} { + if {[info exists env($ee)]} { + regsub -all $exp $cmd "$env($ee)" cmd + } else { + regsub -all $exp $cmd {} cmd + } +} +} + +proc ParsePanMacro {cmdname frame} { + upvar $cmdname cmd + + set exp {\$pan\(([^)]*)\)} +if {[regexp $exp $cmd foo pp]} { + set sys physical + set sky fk5 + set format degrees + + foreach p [split $pp ,] { + switch -- $p { + image - + physical - + detector - + amplifier - + wcs - + wcsa - + wcsb - + wcsc - + wcsd - + wcse - + wcsf - + wcsg - + wcsh - + wcsi - + wcsj - + wcsk - + wcsl - + wcsm - + wcsn - + wcso - + wcsp - + wcsq - + wcsr - + wcss - + wcst - + wcsu - + wcsv - + wcsw - + wcsx - + wcsy - + wcsz {set sys $p} + + fk4 - + b1950 - + fk5 - + j2000 - + icrs - + galactic - + ecliptic {set sky $p; set sys wcs} + + hms {set format sexagesimal} + sexagesimal - + degrees {set format $p} + } + } + + set coord [$frame get cursor $sys $sky $format] + regsub -all $exp $cmd "[lindex $coord 0],[lindex $coord 1]" cmd + + return +} + +# no args + +set exp {\$pan} +if {[regexp $exp $cmd foo1]} { + set coord [$frame get cursor physical] + regsub -all $exp $cmd "[lindex $coord 0],[lindex $coord 1]" cmd +} +} + +proc ParseValueMacro {cmdname frame x y} { + upvar $cmdname cmd + + # menu items will not have a frame arg + if {$frame == {}} { + return + } + + set exp1 {\$value} + if {[regexp $exp1 $cmd foo]} { + set vv [$frame get value canvas $x $y] + regsub -all $exp1 $cmd "$vv" cmd + } +} + +proc ParseXYMacro {cmdname frame x y} { + upvar $cmdname cmd + + # menu items will not have a frame arg + if {$frame == {}} { + return + } + + set exp1 {\$x\(([^)]*)\)} +set exp2 {\$y\(([^)]*)\)} +if {[regexp $exp1 $cmd foo pp] && [regexp $exp2 $cmd foo2 pp2]} { + set sys physical + set sky fk5 + set format degrees + + foreach p [split $pp ,] { + switch -- $p { + image - + physical - + detector - + amplifier - + wcs - + wcsa - + wcsb - + wcsc - + wcsd - + wcse - + wcsf - + wcsg - + wcsh - + wcsi - + wcsj - + wcsk - + wcsl - + wcsm - + wcsn - + wcso - + wcsp - + wcsq - + wcsr - + wcss - + wcst - + wcsu - + wcsv - + wcsw - + wcsx - + wcsy - + wcsz {set sys $p} + + fk4 - + b1950 - + fk5 - + j2000 - + icrs - + galactic - + ecliptic {set sky $p; set sys wcs} + + hms {set format sexagesimal} + sexagesimal - + degrees {set format $p} + } + } + + switch -- $sys { + image - + physical - + detector - + amplifier {set coord [$frame get coordinates $x $y $sys]} + default {set coord [$frame get coordinates $x $y $sys $sky $format]} + } + + regsub -all $exp1 $cmd [lindex $coord 0] cmd + regsub -all $exp2 $cmd [lindex $coord 1] cmd + + return +} + +# no args + +set exp1 {\$x} +set exp2 {\$y} +if {[regexp $exp1 $cmd foo1] && [regexp $exp2 $cmd foo2]} { + set coord [$frame get coordinates $x $y physical] + + regsub -all $exp1 $cmd [lindex $coord 0] cmd + regsub -all $exp2 $cmd [lindex $coord 1] cmd +} +} + +proc ParseZMacro {cmdname frame} { + upvar $cmdname cmd + + # menu items will not have a frame arg + if {$frame == {}} { + return + } + + set sl [$frame get fits slice] + + # args + set exp1 {\$z\(([^)]*)\)} + if {[regexp $exp1 $cmd foo pp]} { + set sys $pp + set coord [$frame get coordinates $sl image $sys 2] + regsub -all $exp1 $cmd "$coord" cmd + return + } + + # no args + # look for '$z"' + set exp1 {\$z\"} + if {[regexp $exp1 $cmd foo1]} { + regsub -all $exp1 $cmd "$sl\"" cmd + } + # look for "$z " + set exp1 {\$z\s} + if {[regexp $exp1 $cmd foo1]} { + regsub -all $exp1 $cmd "$sl " cmd + } +} + +proc ParseMessageMacro {cmdname} { + upvar $cmdname cmd + + # two args + set exp {\|?.?\$message\((ok|okcancel|yesno),([^)]*)\).?\|?} +while {[regexp $exp $cmd foo type message]} { + regsub $exp $cmd {} cmd + if {![AnalysisMessage $type $message]} { + return 0 + } +} + +# one args +set exp {\|?.?\$message\(([^)]*)\).?\|?} +while {[regexp $exp $cmd foo message]} { + regsub $exp $cmd {} cmd + AnalysisMessage ok $message +} + +return 1 +} + +proc ParseEntryMacro {cmdname} { + upvar $cmdname cmd + + # one args + set exp {\|?.?\$entry\(([^)]*)\).?\|?} +while {[regexp $exp $cmd foo message]} { + set result {} + if {![AnalysisEntry $message result]} { + return 0 + } + regsub $exp $cmd $result cmd +} + +return 1 +} + +proc ParseParamMacro {cmdname} { + upvar $cmdname cmd + global ianalysis + + set exp {\$param\(([^)]*)\).?;?} +while {[regexp $exp $cmd foo param]} { + regsub $exp $cmd {} cmd + if {![AnalysisParam cmd $param]} { + return 0 + } +} +return 1 +} + +proc ParseTextMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp1 {\|.?\$text} + set exp2 {\|\&.?\$text} + if {[regexp $exp1 $cmd]} { + regsub $exp1 $cmd {} cmd + + set ianalysis($which,$i,finish) text + } elseif {[regexp $exp2 $cmd]} { + regsub $exp2 $cmd { 2>@ stdout} cmd + + set ianalysis($which,$i,finish) text + } +} + +proc ParseNullMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp {\|.?\$null} + if {[regexp $exp $cmd]} { + regsub $exp $cmd {} cmd + + set ianalysis($which,$i,finish) null + } +} + +proc ParsePlotMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp {\|.?\$plot\(([^,]+),([^,]+),([^,]+),([^)]+)\)} +if {[regexp $exp $cmd foo \ + ianalysis($which,$i,plot,title) \ + ianalysis($which,$i,plot,xaxis) \ + ianalysis($which,$i,plot,yaxis) \ + ianalysis($which,$i,plot,dim)]} { + regsub $exp $cmd {} cmd + + set ianalysis($which,$i,finish) plot +} + +set exp {\|.?\$plot\(stdin\)} +if {[regexp $exp $cmd]} { + regsub $exp $cmd {} cmd + + set ianalysis($which,$i,finish) plotstdin +} + +set exp {\|.?\$plot} +if {[regexp $exp $cmd]} { + regsub $exp $cmd {} cmd + + set ianalysis($which,$i,finish) plot +} +} + +proc ParseURLMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp {\$url\((.*)\) \|} + if {[regexp $exp $cmd foo ianalysis($which,$i,start,url)]} { + set ianalysis($which,$i,start) url + set ianalysis($which,$i,start,fn) [tmpnam {.fits}] + + regsub $exp $cmd "cat \{$ianalysis($which,$i,start,fn)\} |" cmd + } +} + +proc ParseGetURLMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp {\$geturl\((.*)\)} + if {[regexp $exp $cmd foo ianalysis($which,$i,start,url)]} { + set ianalysis($which,$i,start) geturl + set ianalysis($which,$i,start,fn) [tmpnam {.fits}] + + regsub $exp $cmd {} cmd + } +} + +proc ParseImageMacro {cmdname which i} { + upvar $cmdname cmd + global ianalysis + + set exp {\|.?\$image\(([^)]*)\)} +if {[regexp $exp $cmd foo ianalysis($which,$i,image)]} { + regsub $exp $cmd {} cmd + + set ianalysis($which,$i,finish) image +} + +set exp {\|.?\$image} +if {[regexp $exp $cmd]} { + regsub $exp $cmd {} cmd + + set ianalysis($which,$i,finish) image +} +} + +proc AnalysisText {tt title txt method} { + if {$txt != {} && $txt != "\n"} { + SimpleTextDialog ${tt}txt $title 80 20 $method bottom $txt + } +} + +proc AnalysisMessage {type message} { + if {$type == {}} { + set type ok + } + + switch -- [tk_messageBox -message $message -type $type] { + ok {return 1} + yes {return 1} + cancel {return 0} + default {return 0} + } +} + +proc AnalysisEntry {message resultvar} { + upvar $resultvar result + + return [EntryDialog [msgcat::mc {Entry}] $message 60 result] +} + +proc AnalysisPrefOpen {varname} { + upvar $varname var + + FileLast analysisfbox $var + set var [OpenFileDialog analysisfbox] +} + +# Cmds + +proc ProcessAnalysisCmd {varname iname buf fn} { + upvar $varname var + upvar $iname i + + global ime + global ianalysis + + switch -- [string tolower [lindex $var $i]] { + message { + incr i + switch [string tolower [lindex $var $i]] { + ok - + okcancel - + retrycancel - + yesno - + yesnocancel { + AnalysisMessage [lindex $var $i] [lindex $var [expr $i+1]] + incr i + } + default { + AnalysisMessage ok [lindex $var $i] + } + } + } + text { + if {$buf != {}} { + AnalysisText apXPA Analysis $buf append + } elseif {$fn != {}} { + if {[file exists $fn]} { + set ch [open $fn r] + set txt [read $ch] + close $ch + AnalysisText apXPA Analysis $txt append + } + } else { + incr i + AnalysisText apXPA Analysis [lindex $var $i] append + } + } + plot { + # for backward compatibility + # used by chandra-ed + # use xpa plot instead + + incr i + if {$buf != {}} { + ProcessAnalysisPlotCmd $varname $iname $buf + } elseif {$fn != {}} { + if {[file exists $fn]} { + set ch [open $fn r] + set rr [read $ch] + close $ch + ProcessAnalysisPlotCmd $varname $iname $rr + } + } else { + ProcessAnalysisPlotCmd $varname $iname {} + } + } + load { + if {$buf != {}} { + ProcessAnalysis buf + } elseif {$fn != {}} { + ProcessAnalysisFile $fn + } else { + incr i + ProcessAnalysisFile [lindex $var $i] + } + } + clear { + ClearAnalysis + incr i + switch -- [lindex $var $i] { + load { + if {$buf != {}} { + ProcessAnalysis buf + } elseif {$fn != {}} { + ProcessAnalysisFile $fn + } else { + incr i + ProcessAnalysisFile [lindex $var $i] + } + } + default {incr i -1} + } + } + mode { + incr i + switch -- [lindex $var $i] { + stats - + statistics {set ime(task) stats} + hist - + histogram {set ime(task) hist} + radial - + radialprofile {set ime(task) radial} + 2d - + plot2d {set ime(task) plot2d} + 3d - + plot3d {set ime(task) plot3d} + } + + ProcessRealizeDS9 + IMEChangeTask + } + task { + incr i + if {[string is integer [lindex $var $i]]} { + AnalysisTask [lindex $var $i] menu + } else { + # invoke by name + for {set ii 0} {$ii<$ianalysis(menu,count)} {incr ii} { + if {[string equal -nocase $ianalysis(menu,$ii,item) [lindex $var $i]]} { + AnalysisTask $ii menu + } + } + } + } + default { + if {[string is integer [lindex $var $i]]} { + AnalysisTask [lindex $var $i] menu + } else { + ProcessAnalysisFile [lindex $var $i] + } + } + } +} + +proc ProcessAnalysisPlotCmd {varname iname buf} { + upvar 2 $varname var + upvar 2 $iname i + + global iap + switch -- [string tolower [lindex $var $i]] { + stdin {AnalysisPlotStdin line $iap(tt) {} $buf} + default { + PlotLine $iap(tt) Plot \ + [lindex $var [expr $i+0]] \ + [lindex $var [expr $i+1]] \ + [lindex $var [expr $i+2]] \ + [lindex $var [expr $i+3]] \ + $buf + incr i 3 + } + } +} + +proc ProcessSendAnalysisCmd {proc id param sock fn} { + global ianalysis + global ime + + set result {} + switch -- [string tolower [lindex $param 0]] { + entry { + AnalysisEntry [lrange $param 1 end] result + append result "\n" + $proc $id $result + } + mode {$proc $id "$ime(task)\n"} + task { + # invoke by name + for {set ii 0} {$ii<$ianalysis(menu,count)} {incr ii} { + append result "$ii $ianalysis(menu,$ii,item)\n" + } + $proc $id $result + } + lock {$proc $id "$ime(lock)\n"} + default { + for {set i 0} {$i<$ianalysis(menu,count)} {incr i} { + append result "\#$i menu" + append result "\n$ianalysis(menu,$i,item)" + append result "\n$ianalysis(menu,$i,template)" + if {$ianalysis(menu,$i,cmd) != {web}} { + append result "\nmenu" + append result "\n$ianalysis(menu,$i,cmd)" + } else { + append result "\n$ianalysis(menu,$i,cmd)" + append result "\n$ianalysis(menu,$i,var)" + } + append result "\n\n" + } + for {set i 0} {$i<$ianalysis(bind,count)} {incr i} { + set key [string range $ianalysis(bind,$i,item) 1 1] + append result "\#$i bind" + append result "\nbind key $ianalysis(bind,$i,item)" + append result "\n$ianalysis(bind,$i,template)" + append result "\nbind $key" + append result "\n$ianalysis(bind,$i,cmd)" + append result "\n\n" + } + ProcessSend $proc $id $sock $fn {.ans} $result + } + } +} |