MIDAS
Loading...
Searching...
No Matches
stripchart.tcl
Go to the documentation of this file.
1#!/bin/sh
2#-*-tcl-*-
3# the next line restarts using wish \
4exec /bin/nice bltwish "$0" -- ${1+"$@"}
5
6#=========================================================================
7# Gertjan Hofman, U. of Colorado, Boulder, March-00.
8#
9# tcl program to replace the gstripchart thingy that comes with
10# gnome
11#
12#
13# requires: tcl + tk + BLT = bltwish
14#
15# v 1.0 Mar - 00 for PAA/Triumf/Midas
16#
17# There are a few tricky things going on here.
18# Since passing TCL lists to the graph seems to have a memory leak,
19# I use BLT vectors, which are hot linked to the graph elements.
20# Since I dont know a priori how many vectors to create, I the name
21# of the item that I am plotting as the vector name, preceded by
22# V_x_ or V_y_.
23# To access an individual data point, which I need for the scrolling
24# now have to do a double de-refencing. Say we create a vector
25# vector create my_vect(10)
26# then I can access the vector using puts $my_vect(3)
27# but if I have
28# set name my_vect
29# vector create $x
30# Now I need to translate x--> my_vect --> its value.
31# you can do this in two ways:
32# puts [set [set x](0)] or puts [ set ${x}(0)] or even
33# puts [set $x\‍(0)]. In the first case, the inner 'set' returns
34# my_vect. This is then appended to (0) and the second set returns
35# the result. In the last case, the \ 'escapes' or seperates the (0)
36# as not being part of the name. etc etc. Think about it.
37#
38# v. 1.0 -added help menu, added smarter scaling of of the expanded
39# graphs.
40# v 1.1 -added mouse select of graph items
41# v. 2.0 -added support for mhist (odb history)
42# v. 2.1 -added postscript support + zooming of single graph windows
43# v 3.0 -added scroll bars for variable selections
44# -corrected dd.mm.yy to yy.mm.dd for Stefan.
45# things to do:
46# - improve help/info menu's
47# - trap errors !
48# - check compatibility with gchart, esp. reading of fields
49# - what about simple arithmetic ? (a la gchart).
50# - think of some cool back grounds (chaos.../midas etc)
51#
52# 12.10.2000
53# updates:
54# 1. Search for most recent mhist executable and use that
55# 2. Change history file menu's slightly
56# 3. option -mhist is no longer necessary - default
57
58# 17.10.2000
59# fixed bug in online mode - string comparison was wrong
60# re-ordered some code (no functional change)
61#
62# $Id:$
63#
64#
65# 29.11.01
66# Updates - discovered minor bugs in decoding time format for the year 2001
67# - minor bug in exec statements (was appending new items instead
68# of overwritting)
69# -* found BLT problesm - things that worked before dont with
70# RH72 distr - nameles vector x(++end) $data kind of statements
71# Had to use vector append instead.
72# This is version 2.0
73# 07.12.01
74# Added file path input box.
75# Added busy signal - changing colour of the screen
76
77# Added cross hairs
78# Added buttons to scan through the expanded/single graphs
79# Allow resizing of expanded/single graphs
80
81# May-2002. Cosmetic changes.
82# Allow Manual entry of y-scale settings
83
84#========================================================================
85
86
87namespace import blt::* ;# get BLT commands imported
88
89#============================================================
90# SHOW MESSAGE - pop up message window and display error
91#============================================================
92
93proc show_message {message} {
94 global message_done ;# indicate whether message has been read
95 toplevel .messages ; # create a new window
96 wm title .messages "stripchart warning"
97 label .messages.1 -text "$message"
98 pack .messages.1 -side top
99 button .messages.ok -text "OK" -command {
100 destroy .messages
101 set message_done 1
102 return}
103 pack .messages.ok -side bottom
104 update
105}
106
107
108#=============================================================
109# Convert clock seconds to HH:MM:SS format
110#=============================================================
111# this function converts a 'x' axis value to a time format according to
112# a format statement passed to it.
113proc my_clock_format {format graph ltime} {
114 return "[clock format [expr round( ($ltime/60.)*60)] -format $format]"
115}
116
117
118#=============================================================
119# EXIT procedure
120#=============================================================
121proc nice_exit {} {
122 exit
123return
124}
125#=============================================================
126# FIND LATEST MHIST VERSION -by checking modificationd dates
127#=============================================================
128proc find_newest_mhist {} {
129
130 global mhist_path
131
132 # search for the latest copy of mhist and store that path
133 set mhistlist "/usr/local/bin /usr/bin . /midas/linux/bin/"
134 set minmod 0
135 foreach file $mhistlist {
136 # get the modification time
137 if [file exist $file/mhist] {
138 if {[file mtime $file/mhist] > $minmod } {
139 set minmod [file mtime $file/mhist]
140 set mhist_path $file
141 }
142 }
143 }
144
145 if {$mhist_path==""} {
146 tk_messageBox -message "Error: Can not find ANY mhist in \n
147 $mhist_list \n"
148 return 0
149 } else {
150 wm title . "using mhist from path: $mhist_path/mhist"
151 return 1
152 }
153
154
155}
156#==============================================================
157# READ THE MCHART CONFIGURATION FILE
158#==============================================================
159proc read_conf_file {conf_fname} {
160
161 global item_fname item_fields item_pattern item_equation
162 global item_color item_max item_min item_list
163 global equip_name
164
165 # open the file, get ptr.
166 set file_hndl [open $conf_fname r]
167
168 while {! [eof $file_hndl]} {
169
170 gets $file_hndl string
171
172 # skip over comments ...except catch Pierre's equipment name.
173 if {[string first "#Equipment:" $string] != -1 } {
174 set equip_name [lindex $string 1]
175 }
176
177 if {[string index $string 0]=="#" || [llength $string]==0} {
178 continue
179 }
180 set string [string tolower $string] ;# convert to lower case
181
182 #disect string to obtain info. Look for begin line.
183 # note: string first return location of first occurance -1 if not found
184 if { [string first "begin:" $string] != -1} {
185
186 # now fetch the second item - the value name
187
188 set item [lindex $string 1] ;# assume its the second item
189
190 set item [filter_bad_chars $item]
191
192 lappend item_list $item ;# create a list of items for looping
193
194 set item_color($item) [get_new_color]
195 # "color:" { set item_color($item) [lindex $string 1] }
196 # ok we got a begin. Check for the usefil items
197 while { [string first "end:" $string] == -1 } {
198 gets $file_hndl string
199 switch -glob -- [lindex $string 0] {
200 "filename:" { set item_fname($item) [lindex $string 1] }
201 "fields:" { set item_fields($item) [lindex $string 1] }
202 "pattern:" { set item_pattern($item) [lindex $string 1] }
203 "equation:" { set item_equation($item) [lindex $string 1] }
204 "maximum:" { set item_max($item) [lindex $string 1] }
205 "minimum:" { set item_min($item) [lindex $string 1] }
206 "begin:" {
207 show_message "Error in .conf file - begin but no previous end "
208 after 5000
209 exit
210 }
211 }
212 }
213 }
214 }
215
216 close $file_hndl
217
218
219# do some checks on the max/min values, in case Pierre screwed them up
220 foreach item $item_list {
221 if { $item_max($item)==0 && $item_min($item)==0} {
222 puts "found zero max/min values for $item. Correcting"
223 set item_max($item) 1
224 }
225 }
226
227
228 return
229}
230
231
232#======================================================================
233# GRAPH INDIVIDUAL ITEM ON FULL SCALE
234#======================================================================
235
236proc select_graph {item} {
237# here we show the REAL data, unscaled, on a seperate graph
238# note: we want to be able to crack open multiple graphs
239# so the names of the widget need to be a variable.
240# can't remember how to make static variables, so make it
241# global
242
243# global V_x_$item ;# vectors associated with the plotte item
244# global V_y_$item
245 global item_color ;# colour associated with item
246 global scale_ymin scale_ymax ;# present best y-scale
247 global winsize_x winsize_y ;# size of toplevel and graph windows
248 global doing_mhist
249
250# check if window exist already - dont replot the same item twice
251 if [winfo exists .fullscale$item ] {
252 wm deiconify .fullscale$item ;# de-iconize it it
253 raise .fullscale$item ;# raise to foreground
254 return
255 }
256
257 toplevel .fullscale$item ;# create new window with unique name
258 wm title .fullscale$item "$item"
259
260# split screen in two parts -
261 frame .fullscale$item.col1 ;# create to columes - rhs for graph
262 frame .fullscale$item.col2 ;# left hand side for buttons.
263 pack .fullscale$item.col1 -side left
264 pack .fullscale$item.col2 -side right -fill both -expand 1
265
266 set fgraph .fullscale$item.col2.graph
267
268 graph $fgraph -title "" -relief ridge -bd 3 -background "#c8f8ce" ;# make a new graph
269 #cross hairs - why doesnt $fgraph crosshair on work ?
270 Blt_Crosshairs $fgraph
271 $fgraph configure -width 5.0i -height 2.0i ;# configure it a little
272 $fgraph legend configure -position @80,8 -anchor nw -relief raised
273
274 pack $fgraph -side right -fill both -expand 1
275
276 # now, autoscaling may not be the best. Lets try use the standard
277 # deviation for the data points that we have stored right now.
278 calc_best_scale $item ;# returns calc values, or "" if not enough data
279
280 $fgraph yaxis configure -max $scale_ymax -min $scale_ymin
281
282 # add day of the week if using the history command
283 if {$doing_mhist} {
284 $fgraph xaxis configure -loose 1 -title "" -command {my_clock_format "%d/%m %H:%M"}
285 } else {
286 $fgraph xaxis configure -loose 1 -title "" -command {my_clock_format %H:%M}
287 }
288
289 $fgraph element create line
290 $fgraph element configure line \
291 -label $item -color $item_color($item) -symbol "" \
292 -xdata V_x_$item -ydata V_y_$item
293
294 # puts "data are now [set V_y_[set item](:)]"
295 # create exit button
296 button .fullscale$item.col1.ok -text "close" -relief flat -underline 0 -bd 0 \
297 -width 6 -command "destroy .fullscale$item ; return"
298 pack .fullscale$item.col1.ok -side bottom
299
300 # create re-scaling button
301
302# button .fullscale$item.col1.scale1 -text "AutoScale" -relief flat -underline 0 -bd 0 \
303# -width 6 -font 6x12 -command "scale_single_window Auto $item"
304# pack .fullscale$item.col1.scale1 -side top
305# button .fullscale$item.col1.scale2 -text "ReScale" -relief flat -underline 0 -bd 0 \
306# -font 6x12 -width 6 -command "scale_single_window Rescale $item"
307# pack .fullscale$item.col1.scale2 -side top
308
309
310 # trial code - scale menu:
311 menubutton .fullscale$item.col1.scale_gen -text "Scaling" -menu .fullscale$item.col1.scale_gen.mnu \
312 -width 6
313 menu .fullscale$item.col1.scale_gen.mnu
314 .fullscale$item.col1.scale_gen.mnu add command -command "scale_single_window Manual $item 1" \
315 -label "Manual Scale"
316 .fullscale$item.col1.scale_gen.mnu add command -command "scale_single_window Rescale $item 1" \
317 -label "AutoScale 1"
318 .fullscale$item.col1.scale_gen.mnu add command -command "scale_single_window Auto $item 1" \
319 -label "AutoScale 2"
320 pack .fullscale$item.col1.scale_gen -side top
321 # end of trial code
322
323 # create information button
324 button .fullscale$item.col1.info -text "Info/Help" -relief flat -underline 0 -bd 0 \
325 -width 6 -command "show_item_info $item"
326 pack .fullscale$item.col1.info -side top
327
328 # create hard copy pull down menu:
329 menubutton .fullscale$item.col1.hard -text "HardCopy" -relief flat -underline 0 -bd 0 \
330 -menu .fullscale$item.col1.hard.mnu -relief raised
331
332 set hardcopy_menu [ menu .fullscale$item.col1.hard.mnu]
333
334 $hardcopy_menu add command -command "hardcopy ps $fgraph" -label "ps file"
335 $hardcopy_menu add command -command "hardcopy jpg $fgraph" -label "jpg file"
336 $hardcopy_menu add command -command "hardcopy gif $fgraph" -label "gif file"
337 $hardcopy_menu add command -command "hardcopy png $fgraph" -label "png file"
338
339 pack .fullscale$item.col1.hard
340 # bindings for the zooming function.
341 bind $fgraph <ButtonPress-1> "zoom_select %W %x %y start"
342 bind $fgraph <ButtonRelease-1> "zoom_select %W %x %y stop"
343
344
345 return
346}
347
348
349
350
351#======================================================================
352# GRAPH ALL ON FULL SCALE (AS ABOVE), BUT PACKED TOGETHER
353#======================================================================
354
355proc show_all_full_scale { } {
356
357 global item_list ;# list of all items to plot
358 global item_color ;# colour associated with item
359 global scale_ymin scale_ymax ;# present best y-scale
360 global winsize_x winsize_y ;# size of toplevel and graph windows
361 global doing_mhist
362
363 global display_item_cnt ;# pointer to start of 5 items to display
364 global debug_code
365 global item_counter_text ;# copy of display_item but for label
366 global fix_y_scale ;# whether or not mouse zoom changes y-scale
367
368
369 # check if window exist already - if so, destroy the graphs on it.
370 if { [winfo exists .fullscale_main ] } {
371 foreach item $item_list {
372 set full_name .fullscale_main.fullscale$item
373 if {[winfo exists $full_name]} { destroy $full_name}
374 }
375 } else {
376 toplevel .fullscale_main
377 wm title .fullscale_main "zoom using left-mouse-drag"
378 wm geometry .fullscale_main +[winfo rootx .]+[winfo rooty .]
379 }
380
381 #if we have more than 4 items provide skip buttons
382 if { [llength $item_list] > 4} {
383 if {![winfo exist .fullscale_main.row1]} {
384 if {$debug_code} { puts "Creating top row << >> "}
385 frame .fullscale_main.row1 -relief ridge -bd 3 -height 0.3i
386
387 button .fullscale_main.row1.prev1 -text "< " -command {
388 incr display_item_cnt -4
389 show_all_full_scale
390 }
391 button .fullscale_main.row1.next1 -text "> " -command {
392 incr display_item_cnt 4
393 show_all_full_scale
394 }
395 button .fullscale_main.row1.prev2 -text "<<" -command {
396 incr display_item_cnt -8
397 show_all_full_scale
398 }
399 button .fullscale_main.row1.next2 -text ">>" -command {
400 incr display_item_cnt 8
401 show_all_full_scale
402 }
403 button .fullscale_main.row1.quit -text "exit" -command {destroy .fullscale_main}
404 label .fullscale_main.row1.number -textvariable item_counter_text
405
406 button .fullscale_main.row1.fixy -text "Freeze Y scale" \
407 -command {
408 set fix_y_scale [expr !$fix_y_scale] ; # invert toggle
409 if {$fix_y_scale} {
410 .fullscale_main.row1.fixy configure -bg red -activebackground red2
411 } else {
412 .fullscale_main.row1.fixy configure -bg grey -activebackground "#d6d8d6"
413 }
414 }
415
416 pack .fullscale_main.row1.fixy -side right
417
418
419
420 pack .fullscale_main.row1.prev2 -side left
421 pack .fullscale_main.row1.prev1 -side left
422 pack .fullscale_main.row1.quit -side left
423 pack .fullscale_main.row1.number -side right -fill x -padx 20
424 pack .fullscale_main.row1.next2 -side right
425 pack .fullscale_main.row1.next1 -side right
426
427 pack .fullscale_main.row1 -side top -expand 1
428
429 }
430 }
431
432 # make sure we dont over run the list
433 if { $display_item_cnt < 0 } { set display_item_cnt 0}
434 if { $display_item_cnt > [expr [llength $item_list]-4] } {
435 set display_item_cnt [expr [llength $item_list] -4 ]
436 }
437
438
439
440 if { $debug_code } {
441 puts "Debug: item to display list counter is $display_item_cnt"
442 puts "Debug: item list length is [llength $item_list] "
443 }
444
445 set last_item [expr $display_item_cnt + 3]
446 set n_items 0
447
448 # for display only:
449 set item_counter_text "[expr $display_item_cnt+1] to [expr $last_item+1] out of [llength $item_list]"
450
451 foreach item [lrange $item_list $display_item_cnt $last_item] {
452
453 # only plot first 4.
454 incr n_items
455 if {$n_items>4} { break }
456
457 set full_name .fullscale_main.fullscale$item
458
459 frame $full_name
460
461 # split screen in two parts -
462 frame $full_name.col1 ;# create two columes - rhs for graph
463 frame $full_name.col2 ;# left hand side for buttons.
464 pack $full_name.col1 -side left
465 pack $full_name.col2 -side right -fill both -expand 1
466
467 set fgraph $full_name.col2.graph
468
469 graph $fgraph -title "" -relief ridge -bd 3 -background "#c8f8ce"
470 #-plotbackground black
471 # switch cross hairs on. For some reason $fgraph crosshairs on doesnt work?
472
473 Blt_Crosshairs $fgraph
474
475
476 $fgraph configure -width 5.0i -height 2.0i ;# configure it a little
477 $fgraph legend configure -position @80,8 -anchor nw -relief raised
478
479 pack $fgraph -side right -fill both -expand 1
480
481 # now, autoscaling may not be the best. Lets try use the standard
482 # deviation for the data points that we have stored right now.
483
484 calc_best_scale $item ;# returns calc values, or "" if not enough data
485
486 $fgraph yaxis configure -max $scale_ymax -min $scale_ymin
487
488 # add day of the week if using the history command
489 if {$doing_mhist} {
490 $fgraph xaxis configure -loose 1 -title "" -command {my_clock_format "%d/%m %H:%M"}
491 } else {
492 $fgraph xaxis configure -loose 1 -title "" -command {my_clock_format %H:%M}
493 }
494
495 $fgraph element create line
496 $fgraph element configure line \
497 -label $item -color $item_color($item) -symbol "" \
498 -xdata V_x_$item -ydata V_y_$item
499
500
501 # create exit button
502 button $full_name.col1.ok -text "close" -width 6 -relief flat -underline 0 -bd 0 \
503 -command "destroy $full_name ; return"
504 pack $full_name.col1.ok -side bottom
505
506 # create re-scaling button
507# button $full_name.col1.scale1 -text "AutoScale" -width 6 -font 6x12 \
508# -command "scale_single_window2 Auto $item"
509# pack $full_name.col1.scale1 -side top
510# button $full_name.col1.scale2 -text "ReScale" -font 6x12 -width 6 \
511# -command "scale_single_window2 Rescale $item"
512# pack $full_name.col1.scale2 -side top
513# pack $full_name.col1.scale2 -side top
514
515
516 # trial code - scale menu:
517 menubutton $full_name.col1.scale_gen -text "Scaling" -menu $full_name.col1.scale_gen.mnu \
518 -width 6
519 menu $full_name.col1.scale_gen.mnu
520 $full_name.col1.scale_gen.mnu add command -command "scale_single_window Manual $item 2" \
521 -label "Manual Scale"
522 $full_name.col1.scale_gen.mnu add command -command "scale_single_window Rescale $item 2" \
523 -label "AutoScale 1"
524 $full_name.col1.scale_gen.mnu add command -command "scale_single_window Auto $item 2" \
525 -label "AutoScale 2"
526 pack $full_name.col1.scale_gen -side top
527 # end of trial code
528
529
530
531 # create information button
532 button $full_name.col1.info -text "Info/Help" -width 6 -relief flat -underline 0 -bd 0 \
533 -command "show_item_info $item"
534 pack $full_name.col1.info -side top
535
536 # create hard copy pull down menu:
537 menubutton $full_name.col1.hard -text "HardCopy" -relief flat -underline 0 -bd 0 \
538 -menu $full_name.col1.hard.mnu
539
540 set hardcopy_menu [ menu $full_name.col1.hard.mnu]
541
542 $hardcopy_menu add command -command "hardcopy ps $fgraph" -label "ps file"
543 $hardcopy_menu add command -command "hardcopy jpg $fgraph" -label "jpg file"
544 $hardcopy_menu add command -command "hardcopy gif $fgraph" -label "gif file"
545 $hardcopy_menu add command -command "hardcopy png $fgraph" -label "png file"
546
547 pack $full_name.col1.hard
548
549 # bindings for the zooming function.
550 bind $fgraph <ButtonPress-1> "zoom_select %W %x %y start"
551 bind $fgraph <ButtonRelease-1> "zoom_select %W %x %y stop"
552 pack $full_name -side top -expand 1 -fill both
553
554 }
555
556
557 return
558}
559
560
561#proc popup_next_prev_window { } {
562#
563# global display_item_cnt
564#
565# toplevel .disp_next -background green
566#
567# wm geometry .disp_next \
568# +[winfo rootx .fullscale_main]+[winfo rooty .fullscale_main]
569# label .disp_next.title -text "Prev 5 or Next 5 " -background green
570# button .disp_next.prev -text "<<" -command {
571# incr display_item_cnt -5
572# show_all_full_scale
573# }
574# button .disp_next.next -text ">>" -command {
575# incr display_item_cnt 5
576# show_all_full_scale
577# }
578# button .disp_next.quit -text "exit" -command {destroy .disp_next}
579# pack .disp_next.title -side top
580# pack .disp_next.prev -side left
581# pack .disp_next.quit -side left
582# pack .disp_next.next -side right
583# update
584
585#return
586#}
587
588
589
590
591#======================================================================
592# ZOOM ON SELECTED GRAPHS USING MOUSE
593#======================================================================
594proc zoom_select {window x y point} {
595 global zoom_coor
596 global fix_y_scale
597
598
599 if {$point=="start"} {
600 set zoom_coor(corner1) [$window invtransform $x $y]
601 return
602 } elseif {$point=="stop"} {
603 set zoom_coor(corner2) [$window invtransform $x $y]
604 } else {
605 tk_messageBox -message "Error: wrong parameter to zoom routine"
606 return
607 }
608
609 # ok have corner 1 and 2
610 # reset graph axis:
611 # robustness check:
612 if { [lindex $zoom_coor(corner1) 0] < [lindex $zoom_coor(corner2) 0] } {
613 $window xaxis configure -min [lindex $zoom_coor(corner1) 0] -max [lindex $zoom_coor(corner2) 0]
614 }
615
616 if {!$fix_y_scale} {
617 if { [lindex $zoom_coor(corner1) 1] < [lindex $zoom_coor(corner2) 1] } {
618 $window yaxis configure -min [lindex $zoom_coor(corner1) 1] -max [lindex $zoom_coor(corner2) 1]
619 } else {
620 $window yaxis configure -max [lindex $zoom_coor(corner1) 1] -min [lindex $zoom_coor(corner2) 1]
621 }
622 }
623
624 return
625}
626
627#================================================================
628# HARDCOPY TO POSTSCRIPT/JPG/PNG/GIF FILE
629#================================================================
630
631proc hardcopy {type window} {
632 $window postscript configure -paperwidth 6.5i -paperheight 8i \
633 -landscape false
634 $window postscript output stripchart.ps
635
636 if {$type =="ps"} {
637 tk_messageBox -message "Postscript output to file stripchart.ps"
638 return
639 }
640
641 if {$type=="jpg"} {
642 catch "exec convert stripchart.ps stripchart.jpg" err
643 if {$err==""} {
644 tk_messageBox -message "JPEG output to file stripchart.jpg"
645 return
646 } else {
647 tk_messageBox -message "Error: $err.\n Output defaults to ps file stripchart.ps"
648 return
649 }
650 }
651 if {$type=="png"} {
652 catch "exec convert stripchart.ps stripchart.png" err
653 if {$err==""} {
654 tk_messageBox -message "PNG output to file stripchart.png"
655 return
656 } else {
657 tk_messageBox -message "Error: $err.\n Output defaults to ps file stripchart.ps"
658 return
659 }
660 }
661
662 if {$type=="gif"} {
663 catch "exec convert stripchart.ps stripchart.gif" err
664 if {$err==""} {
665 tk_messageBox -message "GIF output to file stripchart.gif"
666 return
667 } else {
668 tk_messageBox -message "Error: $err.\n Output defaults to ps file stripchart.ps"
669 return
670 }
671 }
672
673 return
674}
675
676
677#================================================================
678# RESET SCALE ON EXANDED WINDOW
679#================================================================
680
681proc scale_single_window {scale_mode item window} {
682
683 global scale_ymax scale_ymin ;# returned and calculated values
684
685# window =1 for the individual guys =2 for the stacked guys
686
687 if {$window==1} { set fgraph .fullscale$item.col2.graph }
688 if {$window==2} { set fgraph .fullscale_main.fullscale$item.col2.graph }
689
690 switch -glob -- $scale_mode {
691 "Auto" { set scale_ymax "" ; set scale_ymin "" }
692 "Rescale" { calc_best_scale $item} ;# this returns new best values
693 "Manual" {
694 toplevel .inputbox ;# make a seperate window for this
695 # put new window at (x,y) of root window:
696 wm geometry .inputbox +[winfo rootx .]+[winfo rooty .]
697
698 frame .inputbox.row1
699 frame .inputbox.row2
700 frame .inputbox.row3
701
702 grid .inputbox.row1 -row 1
703 grid .inputbox.row2 -row 2
704 grid .inputbox.row3 -row 3
705
706 label .inputbox.row1.startlab -text "Ymin = " -height 2
707 entry .inputbox.row1.start -textvariable scale_ymin -width 40
708 pack .inputbox.row1.start -side right
709 pack .inputbox.row1.startlab -side left
710
711 label .inputbox.row2.startlab -text "Ymax = " -height 2
712 entry .inputbox.row2.start -textvariable scale_ymax -width 40
713 pack .inputbox.row2.start -side right
714 pack .inputbox.row2.startlab -side left
715
716
717 # create a button which, when clicked, will read the box, then destroy the box
718 button .inputbox.row3.ok -text "ok" -command {
719 .inputbox.row1.start get ;# gets read into var.
720 destroy .inputbox
721 }
722 button .inputbox.row3.cancel -text "cancel" -command {
723 destroy .inputbox
724 }
725
726 pack .inputbox.row3.ok -side left
727 pack .inputbox.row3.cancel -side left
728 tkwait window .inputbox ;# wait until its been destroyed
729 update
730 }
731
732
733 }
734
735 $fgraph yaxis configure -min $scale_ymin -max $scale_ymax
736 $fgraph xaxis configure -min "" -max ""
737 update
738 return
739}
740
741# copy of the routine, but called by the stacked detail graphs
742#proc scale_single_window2 {scale_mode item} {
743# global scale_ymax scale_ymin ;# returned and calculated values
744# set fgraph .fullscale_main.fullscale$item.col2.graph
745# switch -glob -- $scale_mode {
746# "Auto" { set scale_ymax "" ; set scale_ymin "" }
747# "Rescale" { calc_best_scale $item} ;# this returns new best values
748# }
749#
750# $fgraph yaxis configure -min $scale_ymin -max $scale_ymax
751# $fgraph xaxis configure -min "" -max ""
752# update
753# return
754#}
755
756
757#==================================================================
758# CALCULATE Y-SCALE USING DATA VALUE STANDARD DEVIATIONS
759#==================================================================
760
761proc calc_best_scale { item } {
762# now, autoscaling may not be the best. Lets try use the standard
763# deviation for the data points that we have stored right now.
764# global V_x_$item
765# global V_y_$item
766 global scale_ymin scale_ymax
767
768 if { [vector expr length(V_y_$item)] > 10 } {
769 set stand_dev [ vector expr sdev(V_y_$item) ] ;# get standard deviation
770 set mean [ vector expr mean(V_y_$item) ] ;# get the mean
771
772 set scale_ymin [expr $mean - 8.* $stand_dev]
773 set scale_ymax [expr $mean + 8.* $stand_dev]
774
775 if { [expr abs($scale_ymin- $scale_ymax) ] < 10.E-10 } {
776 set scale_ymin [expr $mean - 1.]
777 set scale_ymax [expr $mean + 1.]
778 }
779
780
781 if { [expr abs($scale_ymin)] <10.E-20} {
782 set scale_ymin [expr $mean - 1.]
783 }
784 if { [expr abs($scale_ymax)] <10.E-20} {
785 set scale_ymax [expr $mean + 1.]
786 }
787
788
789
790
791 #robustness check:
792 if { $scale_ymin >= $scale_ymax } {
793# tk_messageBox -message "warning: data is constant - no y-scaling \
794# possible for $item. \n\n ymax/min = $scale_ymin $scale_ymax \n\
795# Standard deviation = $stand_dev"
796# puts "data are now [set V_y_[set item](:)]"
797 set scale_ymin ""
798 set scale_ymax ""
799 }
800
801 } else {
802 set scale_ymin ""
803 set scale_ymax ""
804 }
805
806 return
807}
808
809#====================================================================
810# SLEEP ROUTINE (ms)
811#====================================================================
812
813proc wait_ms {mill_sec} {
814 set mill_sec [expr $mill_sec/100.0]
815 for {set count 0 } { $count < $mill_sec} { incr count} {
816 after 100
817 update
818 }
819 return
820}
821
822#======================================================================
823# SET THE SCROLL TIME INTERVAL USING RADIO BUTTONS
824#======================================================================
825
826proc new_scroll_time { } {
827 global time_limit
828
829# did the button already get pressed ?
830 if [winfo exists .main.radio ] {
831 wm deiconify .
832 raise .
833 return
834 }
835
836 frame .main.radio
837 raise .
838 update
839 set radio .main.radio
840
841 radiobutton $radio.radio1 -text "100 sec " -relief flat \
842 -variable time_limit -value 100.
843 radiobutton $radio.radio2 -text "5 min " -relief flat \
844 -variable time_limit -value [expr 5*60.]
845 radiobutton $radio.radio3 -text "1 hrs " -relief flat \
846 -variable time_limit -value [expr 60*60.]
847 radiobutton $radio.radio4 -text "5 hrs " -relief flat \
848 -variable time_limit -value [expr 5*60*60.]
849 radiobutton $radio.radio5 -text "12 hrs " -relief flat \
850 -variable time_limit -value [expr 12*60*60.]
851 button $radio.ok -text "ok" -command "destroy $radio"
852
853 pack $radio
854 for {set i 1} {$i<6} {incr i} {
855 pack $radio.radio$i
856 }
857
858 pack $radio.ok
859
860 update
861 return
862}
863
864#=====================================================================
865# SHOW INFO ON INDIVUDUAL ITEM
866#=====================================================================
867
868proc show_item_info {item} {
869 global equip_name
870
871 toplevel .item_info
872 # put a an <ok> button on it:
873 button .item_info.ok -text "OK" -command {destroy .item_info ; return}
874 pack .item_info.ok -side bottom
875
876 # put the text in the window:
877 message .item_info.mess -width 6i -text \
878 "note: <spaces> are substituted by _ as are \\+- and % signs \n\n \
879 item name : $equip_name/ $item \n\n \
880 Available functions: \n\n \
881 Click-and-drag Left button to zoom time axis.\
882 Click Rescale to return to normal mode\n \
883 Autoscale = optimun scale for graph size \n \
884 ReScale = scale calculate using data standard deviation\n \
885 HardCopy = output to JPEG/PS/PNG etc\n \
886 Close = close this window\n"
887
888
889
890 pack .item_info.mess
891
892 return
893}
894
895
896#=======================================================================
897# LOCATE GRAPH ITEM POINTED TO BY MOUSE
898#=======================================================================
899
900proc mouse_find_item {window x y } {
901 global item_list
902
903 # transform X-win coordinates to graph coordinates.
904 set graph_coor [$window invtransform $x $y]
905 set x_coor [lindex $graph_coor 0]
906 set y_coor [lindex $graph_coor 1]
907
908 # loop over entire list of data find the closest point and display
909 # the item belonging to that point.
910
911 set closest [expr 10000000000000000.0]
912
913 foreach item $item_list {
914 global V_x_$item
915 global V_y_plot_$item
916
917 vector create dist ;# dummy vector
918 dist expr "(V_x_$item- $x_coor)^2 + (V_y_plot_$item - $y_coor)^2 "
919
920 # rember smallest element
921 if { [vector expr min(dist)] < $closest} {
922 set closest [vector expr min(dist)]
923 set closest_item $item
924 }
925 }
926 # clean up
927 vector destroy dist
928
929 # call the graph spawn routine.
930 select_graph $closest_item
931 return
932}
933
934
935#========================================================================
936# READ THE OUTPUT OF MHIST, ALLOW SELECTION OF DATA AND GRAPH ** MHIST **
937#========================================================================
938proc read_mhist_file {open_file } {
939 global event_choice
940 global pick_event_var
941 global event_var
942 global history_time history_interval history_unit history_amount
943
944
945 global item_fname item_fields item_pattern item_equation
946 global item_color item_max item_min item_list
947 global equip_name
948
949 global strip_chart
950
951 global exit_now
952 global select_men
953 global event_ids_info ; #mhist event ID and name
954 global event_var ; #varialbe name
955
956 global debug
957 global debug_code ; #general code debugging
958 global button_toggle ; #use to toggle lots of variables on/off simul.
959
960 global mhist_path ; # place to find mhist
961 global selected_items ; # list of history items from listbox selection
962
963 global hist_file ; # name of history file to open
964 global file_pref ; # /tmp file prefix
965
966 global file_path ; # path to the actual history files
967
968
969 set error_var ""
970 set exit_now 0
971
972
973
974
975 if {![find_newest_mhist]} return ; # locate mhist executable
976
977
978 if {$debug_code} {puts "Debug: in routine read mhist file"}
979
980# this is the FILE read version -
981#i.e. implicitly gets user to select a file.
982# Then select the EVENT ID
983# Then select items to be displayed
984 if { [llength $item_list] >0} {
985 clean_list_and_vectors_and_widgets ;# remove all things associate
986 ;# with previous data
987 }
988
989
990 # get a new file or use the old ?
991 if {$open_file} {
992 if {$debug_code} {puts "Debug: file path is $file_path"}
993 # here we go..a *new* widget
994 set types {{"History files .hst" {.hst}}}
995 set hist_file [tk_getOpenFile -filetypes $types -initialdir $file_path]
996 # but have to remember the path for the next call:
997 if {$hist_file !=""} { set file_path [file dirname $hist_file] }
998
999 } else {
1000 if {$hist_file==""} {
1001 tk_messageBox -message "You need to open a file first \n"
1002 return
1003 }
1004 }
1005
1006 if {$debug_code} {puts "Debug: file path is now $file_path"}
1007 if ![string compare $hist_file ""] return
1008 # ok, so we have the file name. Now repeat the previous excercicse
1009 # of getting the event ID.
1010 catch "exec rm -f /tmp/${file_pref}mhist" error_var
1011 set exec_string "$mhist_path/mhist -f $hist_file -l"
1012
1013 if {$debug_code} {puts "debug1: exec string is $exec_string"}
1014
1015 catch "exec $exec_string > /tmp/${file_pref}mhist" error_var
1016 if {$error_var !="" } {
1017 tk_messageBox -message "Could not start mhist (*path problem ?) \n \
1018 $error_var \n. Command line was \n $exec_string"
1019 return
1020 }
1021
1022 # assume the mhist out put is there and get event selection
1023
1024 if {$debug_code} {puts "debug: calling get_mhist_list"}
1025 if {![get_mhist_list]} return
1026
1027 if {$debug_code} {puts "debug: calling select_event_id"}
1028 if {[select_event_id]=="do_exit"} return
1029
1030
1031 # if an element is actually it self an array, expand that element to show
1032 # all array elements as seperate event variables
1033 if {[deal_with_array_vars]=="do_exit"} return
1034
1035
1036 # now do all the item selection stuff.
1037 if {$debug_code} {puts "debug: calling select_event_items"}
1038 if {[select_event_items old_file]=="do_exit"} return
1039
1040 # now set the pick_event_var variables, just like before but using the results
1041 # from the list box retrieved from routine select_event_items
1042 # selected_items is only the index to the stuff that was picked from the scroll
1043 # list.
1044 foreach i $selected_items {
1045 set var [ lindex $event_var($event_choice) $i]
1046 set pick_event_var($var) 1
1047 if {$debug_code} {puts "Have picked index $i and name is $var"}
1048 }
1049
1050 # now calculate history time (needed only for plotting here
1051 switch -glob -- $history_unit {
1052 "days" {set history_time [expr $history_amount *1 ] }
1053 "weeks" {set history_time [expr $history_amount *7 ] }
1054 "months" {set history_time [expr $history_amount *30 ] }
1055 }
1056
1057 # when opening old file, assume start date (-s) = name of file
1058 # end date (-p) = calculated from user input above
1059
1060
1061 # calc start date from file name: (hist_file)
1062 # unfortunately, Stephan uses yymmdd.hst. Oh well.
1063 # split list at the '.'
1064 # ah, but stephan has fixed the file names now
1065 # Here analyze the file name to get starting date.
1066 # remove unix path:
1067 set hist_file [lindex [split $hist_file /] end]
1068 set date_part [lindex [split $hist_file .] 0]
1069
1070
1071 if { [string range $date_part 0 1]=="97" || [string range $date_part 0 1]=="98" } {
1072 set start_time $date_part
1073 } else {
1074 set day_part [string range $date_part 4 5]
1075 set mon_part [string range $date_part 2 3]
1076 set yre_part [string range $date_part 0 1]
1077 # set start_time $day_part$mon_part$yre_part
1078 set start_time $yre_part$mon_part$day_part
1079 }
1080
1081 # ok, do the end part.
1082 if {$history_unit =="until_now"} {
1083 set stop_time [clock format [clock seconds] -format "%d%m%y"]
1084 } else {
1085 # gets tough. Must calculate a new day from old date and interval
1086 if {$debug_code} {puts "debug: calling calc_history_stop_time $day_part"}
1087 set stop_time [calc_history_stop_time $day_part $mon_part $yre_part]
1088 }
1089
1090
1091 # now, now filter out which events we dont want and repeatedly call mhist
1092 # to get what we want.
1093 # -b = time in seconds.
1094
1095
1096
1097 foreach var $event_var($event_choice) {
1098
1099
1100 wm title . "Loading data......... $var"
1101 .main.middle.strip_chart configure -background red
1102 update
1103
1104 set ignore_item 0
1105
1106 # was this guy enabled ?
1107 if { !$pick_event_var($var)} { continue }
1108
1109
1110 # check if it was an array - if so, add -i option and remove brackets
1111 if {[string match {*\[*\]} $var]} {
1112 if {$debug_code} {puts "Debug: back in read mhist - array var case"}
1113 # extract index number:
1114 set num_elem [string range $var [string last "\[" $var] [string last "\]" $var]]
1115 set num_elem [string range $num_elem 1 [expr [string length $num_elem] -2]]
1116 # remove bracket:
1117 set new_var [string range $var 0 [expr [string last "\[" $var] -1]]
1118 # add -i to exec_string
1119 if {$debug_code} {puts "Debug: array index is $num_elem and new name $new_var"}
1120 set exec_string \
1121 "$mhist_path/mhist -b -s $start_time \
1122 -p $stop_time -t $history_interval -e $event_choice -v \"$new_var\" -i $num_elem"
1123 } else {
1124
1125 set exec_string \
1126 "$mhist_path/mhist -b -s $start_time \
1127 -p $stop_time -t $history_interval -e $event_choice -v \"$var\" "
1128 }
1129
1130
1131 # note the surround by quotes
1132 # now add the path name to the files, in case we are not in the PWD.
1133 if {$file_path !=""} {
1134 set exec_string "$exec_string -z $file_path"
1135 }
1136
1137 # if we are not debugging....go for it.
1138 if { [string compare $debug "mhist"] } {
1139 if {$debug_code} {puts "debug2: Exec string is: $exec_string"}
1140 catch {exec rm -f /tmp/${file_pref}mhist_data} error_var
1141 catch "exec $exec_string > /tmp/${file_pref}mhist_data" error_var
1142 }
1143
1144 if {$error_var !=""} {
1145 tk_messageBox -message "problem: error from mhist \n $exec_string \n $error_var\n"
1146 return
1147 }
1148
1149
1150 # check if MHIST was busy recovering the index files. This should only happen
1151 # once. Mhist does then give the data, but it's easier to run it again I think
1152 set file_hndl [open "/tmp/${file_pref}mhist_data" r ]
1153 if {![eof $file_hndl]} {
1154 gets $file_hndl string
1155 if {[string first "Recovering" $string]!=-1} {
1156 if {$debug_code} {puts "Ooops - mhist recovered index files ! -repeat extraction:"}
1157 if {$debug_code} {puts "Exec string is $exec_string"}
1158 catch {exec rm -f /tmp/${file_pref}mhist_data} error_var
1159 catch "exec $exec_string > /tmp/${file_pref}mhist_data" error_var
1160 }
1161 } else {
1162 tk_messageBox -message "problem: mhist output /tmp/${file_pref}mhist_data emptry \n \
1163 $exec_string \n $error_var"
1164 return
1165 }
1166 close $file_hndl
1167 # end of index generation checking
1168
1169
1170
1171 # get ready to create the vector names
1172 set item $var
1173 set item [filter_bad_chars $item] ;# remove spaces, slashes, etc etc
1174
1175 # create the new vectors
1176
1177 vector create V_x_$item
1178 vector create V_y_$item
1179 vector create V_y_plot_$item
1180
1181 # get the data and read into BLT vectors as usual.
1182 set file_hndl [open "/tmp/${file_pref}mhist_data" r ]
1183
1184 while {![eof $file_hndl]} {
1185 gets $file_hndl string
1186
1187# if { $debug_code } { puts "From file got string $string " }
1188 if { [llength $string] == 2} {
1189 set x_val [string toupper [lindex $string 0]]
1190 set y_val [string toupper [lindex $string 1]]
1191 if { [string first "NAN" $x_val]==-1 && [string first "NAN" $y_val]==-1} {
1192# if {$debug_code} {puts "Adding to item $item value (x,y) $x_val $y_val " }
1193 V_x_${item} append $x_val
1194 V_y_${item} append $y_val
1195 } else {
1196 puts "Stripchart: - Found NAN number in MHIST data for $item -set to 0 "
1197 V_x_${item} append 0
1198 V_y_${item} append 0
1199 }
1200# set V_x_${item}(++end) [lindex $string 0]
1201# set V_y_${item}(++end) [lindex $string 1]
1202
1203 # check for error from mhist:
1204 } elseif {[llength $string] >=2 } {
1205 if {[tk_messageBox -type abortretryignore \
1206 -message "problem: looking for data.\n $exec_string\
1207 but got from mhist:\n $string\n\
1208 Ignore to skip this item \n\
1209 Abort to cancel all items \n"]=="ignore"} {
1210 set ignore_item 1
1211 break
1212 } else {
1213 return
1214 }
1215
1216 }
1217 }
1218
1219
1220 close $file_hndl
1221
1222
1223 if {!$ignore_item} {
1224 # fill in the same info we might have gotten from a .conf file:
1225 # add to the list of items plotted
1226 lappend item_list $item
1227 # set the color
1228 set item_color($item) [get_new_color]
1229
1230 # now for these data calculate appropiate max/min values, as we were
1231 # given them from the .conf file:
1232 if { [vector expr length(V_y_$item)] <= 1} {
1233 tk_messageBox -default ok -message "Not enough data read for plotting" -type ok
1234 return
1235 }
1236
1237 if { [vector expr length(V_y_$item)] > 10 } {
1238 set stand_dev [ vector expr sdev(V_y_$item) ] ;# get standard deviation
1239 set mean [ vector expr mean(V_y_$item) ] ;# get the mean
1240
1241 set item_min($item) [expr $mean - 8.* $stand_dev]
1242 set item_max($item) [expr $mean + 8.* $stand_dev]
1243# puts "before checl: min and max are $item_max($item) $item_min($item) $mean"
1244 #robustness check:
1245 if { [expr abs($item_min($item)-$item_max($item))] < 10.E-10 } {
1246 set item_min($item) [expr $mean - 1.]
1247 set item_max($item) [expr $mean + 1.]
1248 }
1249 if { [expr abs($item_min($item))] <10.E-20} {
1250 set item_min($item) [expr $mean - 1.]
1251 }
1252 if { [expr abs($item_max($item))] <10.E-20} {
1253 set item_max($item) [expr $mean + 1.]
1254 }
1255# puts "min and max are $item_max($item) $item_min($item)"
1256 } else {
1257 set mean [ vector expr mean(V_y_$item) ]
1258 set item_min($item) [expr $mean - 100.]
1259 set item_max($item) [expr $mean + 100.]
1260# puts "min and max are $item_max($item) $item_min($item) --------"
1261 }
1262
1263
1264 # from this max/min value, calculate the plotted normalized histo values:
1265 # do a vector calculation on this new guy.
1266
1267 V_y_plot_$item \
1268 expr "(V_y_$item - $item_min($item)) / ($item_max($item)-$item_min($item))"
1269
1270 # finally associate/create a graph item for this guy
1271 if {! [$strip_chart element exists line_$item]} {
1272 $strip_chart element create line_$item
1273 }
1274 $strip_chart element configure line_$item -label "" -color $item_color($item) -symbol ""
1275 # now hot-link it to the new graph line
1276 $strip_chart element configure line_$item -xdata V_x_$item -ydata V_y_plot_$item
1277 # change the labelling format on the x-axis if plotting more then one day
1278 if {$history_time >= 1} {
1279 $strip_chart xaxis configure -command {my_clock_format "%d/%m %H:%M"}
1280 } else {
1281 $strip_chart xaxis configure -command {my_clock_format "%H:%M"}
1282 }
1283
1284 # create the pull down item menu. Also align the text string
1285 set blank_string " "
1286 set item_length [string length $item]
1287 if {$item_length > 13} {set item_length 13}
1288 set menu_string "$item [string range $blank_string 1 [expr 13 - $item_length] ]"
1289 append menu_string $item_color($item)
1290 $select_men add command -command "select_graph $item" -label $menu_string
1291
1292
1293 # next item:
1294 update
1295 }
1296 }
1297
1298 return
1299}
1300
1301#=========================================================================
1302# READ PRESENT MHIST DATA - this routine is very simular to the above
1303# but subtle difference with respect to picking the start/stop time
1304#=========================================================================
1305proc read_present_mhist { } {
1306 global event_choice
1307 global pick_event_var
1308 global event_var
1309 global history_time history_interval history_unit history_amount
1310
1311
1312 global item_fname item_fields item_pattern item_equation
1313 global item_color item_max item_min item_list
1314 global equip_name
1315
1316 global strip_chart
1317
1318 global exit_now
1319 global select_men
1320
1321 global event_ids_info ;#mhist event ID and name
1322 global event_var ;#varialbe name
1323
1324 global debug_code ; #general code debugging
1325 global debug
1326 global button_toggle ; #use to toggle lots of variables on/off simul.
1327
1328 global mhist_path ; # place to find mhist
1329 global selected_items ; # list of history items from listbox selection
1330
1331 global file_pref ; #/tmp tmp file prefix
1332 global file_path ; # path to history files.
1333
1334 if {![find_newest_mhist]} return ; # locate mhist executable
1335
1336 if {$debug_code} {puts "Debug: in routine read present_mhist file"}
1337
1338
1339 set error_var ""
1340 set exit_now 0
1341
1342
1343 if { [llength $item_list] >0} {
1344 if {$debug_code} {puts "Debug: calling clean_list_and_vectors"}
1345 clean_list_and_vectors_and_widgets ;# remove all things associate
1346 ;# with previous data
1347 }
1348
1349
1350# note: string compare is like 'c' - 0 == string match !!!
1351# so if NOT debugging, execute mhist:
1352
1353 if {$file_path !=""} {
1354 set exec_string "$mhist_path/mhist -l -z $file_path > /tmp/${file_pref}mhist"
1355 } else {
1356 set exec_string "$mhist_path/mhist -l > /tmp/${file_pref}mhist"
1357 }
1358
1359 if { [string compare $debug "mhist"] } {
1360 if {$debug_code} {
1361 puts "Executing mhist command: $exec_string"
1362 }
1363 catch "exec rm -f /tmp/${file_pref}mhist" error_var
1364 catch "exec $exec_string" error_var
1365 }
1366
1367 if {$error_var !="" } {
1368 tk_messageBox -message "Could not start mhist (path problem ?) \n $error_var"
1369 return
1370 }
1371
1372 # assume the mhist out put is there. Retrieve the ID list
1373 if {![get_mhist_list] } return
1374
1375 # do selection of the event_id:
1376 if {$debug_code} {puts "Calling select_event_id"}
1377 if {[select_event_id] =="do_exit"} return
1378
1379 # if an element is actually it self an array, expand that element to show
1380 # all array elements as seperate event variables i.e. DATA[5] become 5 seperate items in the list.
1381 # see the -i option in mhist
1382 if {$debug_code} {puts "Calling deal with arrays"}
1383 if {[deal_with_array_vars]=="do_exit"} return
1384
1385 if {$debug_code} {puts "Calling select_event_items"}
1386 if {[select_event_items today]=="do_exit"} return
1387
1388 # now set the pick_event_var variables, just like before but using the results
1389 # from the list box.
1390
1391
1392 foreach i $selected_items {
1393 set var [ lindex $event_var($event_choice) $i]
1394 set pick_event_var($var) 1
1395 }
1396
1397
1398 # now calculate history time (assume todays history
1399 switch -glob -- $history_unit {
1400 "days" {set history_time [expr $history_amount *1 ] }
1401 "weeks" {set history_time [expr $history_amount *7 ] }
1402 "months" {set history_time [expr $history_amount *30 ] }
1403 }
1404
1405 # deal with the open file possibility
1406 # when opening old file, assume start date (-s) = name of file
1407 # end date (-p) = calculated from user input above
1408
1409 # now, now filter out which events we dont want and repeatedly call mhist
1410 # to get what we want.
1411 # -b = time in seconds.
1412
1413
1414 foreach var $event_var($event_choice) {
1415
1416 wm title . "Loading data......... $var"
1417 .main.middle.strip_chart configure -background red
1418 update
1419
1420 # was this guy enabled ?
1421 if { !$pick_event_var($var)} { continue }
1422
1423 # was it an array data word (must use -i to get the actual value)
1424 if {[string match {*\[*\]} $var]} {
1425 if {$debug_code} {puts "Debug: back in read mhist - array var case"}
1426 # extract index number:
1427 set num_elem [string range $var [string last "\[" $var] [string last "\]" $var]]
1428 set num_elem [string range $num_elem 1 [expr [string length $num_elem] -2]]
1429 # remove bracket:
1430 set new_var [string range $var 0 [expr [string last "\[" $var] -1]]
1431 # add -i to exec_string
1432 if {$debug_code} {puts "Debug: array index is $num_elem and new name $new_var"}
1433
1434 set exec_string \
1435 "$mhist_path/mhist -b -d $history_time -t $history_interval -e $event_choice -v \"$new_var\" -i $num_elem"
1436 } else {
1437
1438 set exec_string \
1439 "$mhist_path/mhist -b -d $history_time -t $history_interval -e $event_choice -v \"$var\" "
1440 }
1441
1442
1443
1444 if {$file_path !=""} {
1445 set exec_string "$exec_string -z $file_path"
1446 }
1447
1448
1449 # if we are not debugging....go for it.
1450 if { [string compare $debug "mhist"] } {
1451 if {$debug_code} {puts "Debug5: exec string is: $exec_string > /tmp/${file_pref}mhist_data"}
1452 catch {exec rm -f /tmp/${file_pref}mhist_data} error_var
1453 catch "exec $exec_string > /tmp/${file_pref}mhist_data" error_var
1454 }
1455
1456 if {$error_var !=""} {
1457 tk_messageBox -message "problem: error from mhist \n $exec_string \n $error_var"
1458 return
1459 }
1460
1461
1462 # get ready to create the vector names
1463 set item $var
1464 set item [filter_bad_chars $item] ;# remove spaces, slashes, etc etc
1465
1466
1467 # create the new vectors
1468
1469 vector create V_x_$item
1470 vector create V_y_$item
1471 vector create V_y_plot_$item
1472
1473
1474
1475 # get the data and read into BLT vectors as usual.
1476 set file_hndl [open "/tmp/${file_pref}mhist_data" r ]
1477
1478 while {![eof $file_hndl]} {
1479 gets $file_hndl string
1480 if { [llength $string] == 2} {
1481 set x_val [string toupper [lindex $string 0]]
1482 set y_val [string toupper [lindex $string 1]]
1483 if { [string first "NAN" $x_val]==-1 && [string first "NAN" $y_val]==-1} {
1484 V_x_${item} append $x_val
1485 V_y_${item} append $y_val
1486 } else {
1487 puts "Stripchart: - Found NAN number in MHIST data for $item"
1488 V_x_${item} append 0
1489 V_y_${item} append 0
1490 }
1491 # Original code has: - which should work, but broke under RH7.2 distr
1492 #set V_x_${item}(++end) [lindex $string 0]
1493 #set V_y_${item}(++end) [lindex $string 1]
1494
1495 } elseif {[llength $string] >=2 } {
1496 tk_messageBox -message "problem: looking for data.\n Send $exec_string \n \
1497 , but found \n $string \n\
1498 Probably means, there really is no file for today's date."
1499 return
1500 }
1501 }
1502
1503 close $file_hndl
1504
1505 # fill in the same info we might have gotten from a .conf file:
1506 # add to the list of items plotted
1507 lappend item_list $item
1508 # set the color
1509 set item_color($item) [get_new_color]
1510
1511 if {$debug_code} {
1512 puts "Debug:"
1513 puts "Item name $item"
1514 puts "Vector length y [vector expr length(V_y_$item)]"
1515 puts "Vector length x [vector expr length(V_x_$item)]"
1516 }
1517
1518# now for these data calculate appropiate max/min values, as we were
1519# given them from the .conf file:
1520 if { [vector expr length(V_y_$item)] <= 1} {
1521 tk_messageBox -default ok -message "Not enough data read for plotting" -type ok
1522 return
1523 }
1524
1525 if { [vector expr length(V_y_$item)] > 10 } {
1526 set stand_dev [ vector expr sdev(V_y_$item) ] ;# get standard deviation
1527 set mean [ vector expr mean(V_y_$item) ] ;# get the mean
1528
1529 set item_min($item) [expr $mean - 8.* $stand_dev]
1530 set item_max($item) [expr $mean + 8.* $stand_dev]
1531
1532 #robustness check:
1533 if { [expr abs($item_min($item)-$item_max($item))] < 10.E-10 } {
1534 set item_min($item) [expr $mean - 1.]
1535 set item_max($item) [expr $mean + 1.]
1536 }
1537 if { [expr abs($item_min($item))] <10.E-20} {
1538 set item_min($item) [expr $mean - 1.]
1539 }
1540 if { [expr abs($item_max($item))] <10.E-20} {
1541 set item_max($item) [expr $mean + 1.]
1542 }
1543
1544
1545 } else {
1546 set mean [ vector expr mean(V_y_$item) ]
1547 set item_min($item) [expr $mean - 100.]
1548 set item_max($item) [expr $mean + 100.]
1549 }
1550
1551 # from this max/min value, calculate the plotted normalized histo values:
1552 # do a vector calculation on this new guy.
1553
1554 V_y_plot_$item \
1555 expr "(V_y_$item - $item_min($item)) / ($item_max($item)-$item_min($item))"
1556
1557 # finally associate/create a graph item for this guy
1558 if {! [$strip_chart element exists line_$item]} {
1559 $strip_chart element create line_$item
1560 }
1561 $strip_chart element configure line_$item -label "" -color $item_color($item) -symbol ""
1562 # now hot-link it to the new graph line
1563 $strip_chart element configure line_$item -xdata V_x_$item -ydata V_y_plot_$item
1564 # change the labelling format on the x-axis if plotting more then one day
1565 if {$history_time >= 1} {
1566 $strip_chart xaxis configure -command {my_clock_format "%d/%m %H:%M"}
1567 } else {
1568 $strip_chart xaxis configure -command {my_clock_format "%H:%M"}
1569 }
1570
1571 # create the pull down item menu. Also align the text string
1572 set blank_string " "
1573 set item_length [string length $item]
1574 if {$item_length > 13} {set item_length 13}
1575 set menu_string "$item [string range $blank_string 1 [expr 13 - $item_length] ]"
1576 append menu_string $item_color($item)
1577 $select_men add command -command "select_graph $item" -label $menu_string
1578
1579
1580 # next item:
1581 update
1582
1583 }
1584
1585
1586 return
1587}
1588
1589
1590#===================================================================
1591# DEAL WITH VARIABLES THAT ARE ACTUALLY ARRAYS
1592# expand the actual variable list to include all elements as
1593# seperate variables i.e. MY_AR[4] adds 4 new elements
1594#===================================================================
1595proc deal_with_array_vars { } {
1596
1597 global event_choice # number of the chosen event
1598 global event_var # this is the list of list of variables
1599 global debug_code
1600
1601 if {$debug_code} {puts "Debug: In deal with array vars "}
1602
1603# set i 0
1604# puts "new list "
1605# foreach var $event_var($event_choice) {
1606# puts "$i $var"
1607# }
1608
1609
1610
1611 set i 0
1612 foreach var $event_var($event_choice) {
1613 # look for [] in variable name
1614 if {[string match {*\[*\]} $var]} {
1615
1616 # extract the number of elements for this variable:
1617 set num_elem [string range $var [string last "\[" $var] [string last "\]" $var]]
1618 set num_elem [string range $num_elem 1 [expr [string length $num_elem] -2]]
1619 if {$debug_code} {puts "Debug: Found an array variable $var with $num_elem elements"}
1620 # expand the array and add each as a new element
1621 for {set k 0} { $k < $num_elem} {incr k} {
1622 set new_var_name [string range $var 0 [expr [string last "\[" $var] -1]]
1623 set new_var_name ${new_var_name}\[$k\]
1624 if {$k==0} {
1625 # replace the first -
1626 set event_var($event_choice) [lreplace $event_var($event_choice) $i $i $new_var_name]
1627 } else {
1628 set event_var($event_choice) [linsert $event_var($event_choice) $i $new_var_name]
1629 }
1630 incr i
1631 }
1632 incr i -1
1633 }
1634 incr i
1635 }
1636
1637# puts "new list "
1638# foreach var $event_var($event_choice) {
1639# puts $var
1640# }
1641
1642 return ""
1643}
1644
1645
1646
1647#===================================================================
1648# PICK THE ITEMS TO BE PLOTTED
1649#===================================================================
1650proc select_event_items { today_or_file} {
1651
1652 global event_choice
1653 global pick_event_var
1654 global event_var
1655 global history_time history_interval history_unit history_amount
1656
1657 global exit_now
1658 global debug_code
1659 # ok, now display and pick list of events_names. Use checkbutton
1660 toplevel .select_vars
1661 wm title .select_vars "mhist variable select"
1662 # glue it to the existing window:
1663# wm geometry .select_vars +[winfo rootx .]+[winfo rooty .]
1664
1665 frame .select_vars.col1row1 -relief ridge -bd 3
1666 frame .select_vars.col2row1 -relief ridge -bd 3
1667 frame .select_vars.col1row2 -relief ridge -bd 3
1668 frame .select_vars.col2row2 -relief ridge -bd 3
1669 frame .select_vars.col1row3 -relief ridge -bd 3
1670 frame .select_vars.col2row3 -relief ridge -bd 3
1671 frame .select_vars.col1row4 -relief ridge -bd 3
1672 frame .select_vars.col2row4 -relief ridge -bd 3
1673 frame .select_vars.col1row5 -relief ridge -bd 3
1674 grid .select_vars.col1row1 -row 1 -column 1
1675 grid .select_vars.col2row1 -row 1 -column 2
1676 grid .select_vars.col1row2 -row 2 -column 1
1677 grid .select_vars.col2row2 -row 2 -column 2
1678 grid .select_vars.col1row3 -row 3 -column 1 -columnspan 2
1679 grid .select_vars.col2row3 -row 3 -column 2
1680 grid .select_vars.col1row4 -row 4 -column 1
1681 grid .select_vars.col2row4 -row 4 -column 2
1682 grid .select_vars.col1row5 -row 5 -column 1 -columnspan 2
1683
1684 # trial code for the list box with scroll bar, to replaces the radiobuttons:
1685 # create scroll bar:
1686 scrollbar .select_vars.col1row3.scroll -command ".select_vars.col1row3.listb yview"
1687 # create the list box:
1688 listbox .select_vars.col1row3.listb \
1689 -yscrollcommand ".select_vars.col1row3.scroll set" \
1690 -selectmode extended -height 15
1691 pack .select_vars.col1row3.listb -side left
1692 pack .select_vars.col1row3.scroll -fill y -side right
1693
1694 # fill the list box
1695 set i 0
1696 foreach var $event_var($event_choice) {
1697 if {$debug_code} {puts "List contains $var"}
1698 set pick_event_var($var) 0
1699 .select_vars.col1row3.listb insert end $var
1700 .select_vars.col1row3.listb selection set $i
1701 incr i
1702 }
1703
1704 label .select_vars.col1row5.lab -text "Use <ctrl/shift> for multiple select"
1705 pack .select_vars.col1row5.lab -side bottom -fill x
1706
1707
1708 set button_toggle 1
1709 checkbutton .select_vars.col1row4.all -text "select all/none" -relief ridge \
1710 -variable button_toggle -command {
1711
1712 for {set i 0} {$i< [llength $event_var($event_choice) ]} {incr i} {
1713 if {$button_toggle} {
1714 .select_vars.col1row3.listb selection set $i
1715 } else {
1716 .select_vars.col1row3.listb selection clear $i
1717 }
1718 }
1719 }
1720
1721 pack .select_vars.col1row4.all -fill x -expand 1
1722
1723 button .select_vars.col2row4.ok -text "ok" -command {
1724 # for the list box (no more radiobuttons), get the chosen events
1725 set selected_items [.select_vars.col1row3.listb curselection]
1726 destroy .select_vars
1727 }
1728
1729 button .select_vars.col2row4.cancel \
1730 -text "cancel" -command "set exit_now 1; destroy .select_vars"
1731
1732 pack .select_vars.col2row4.ok -side left
1733 pack .select_vars.col2row4.cancel -side right
1734
1735
1736 # add radio buttons for the time duration and interval
1737
1738 # if using old file, add some text and an 'until now' choice
1739 if {$today_or_file=="old_file"} {
1740 frame .select_vars.col1row0
1741 grid .select_vars.col1row0 -row 0 -column 1 -columnspan 2
1742 label .select_vars.col1row0.text -text "Old history file selected. Displayed \
1743 period is \n\ calculated starting from date of the history file " \
1744 -relief ridge -bd 3
1745 pack .select_vars.col1row0.text
1746 }
1747
1748 frame .select_vars.col1row1.left ;# subdivide even further: day/weeks etc
1749 frame .select_vars.col1row1.right ;# multiplier
1750 grid .select_vars.col1row1.right -column 2 -row 1
1751 grid .select_vars.col1row1.left -column 1 -row 1
1752
1753 set radio .select_vars.col1row1.left
1754 set history_time 1
1755
1756 label .select_vars.col1row1.lab1 -text "History Time:" -anchor center -justify center
1757 grid .select_vars.col1row1.lab1 -row 0 -columnspan 2
1758
1759 label .select_vars.col1row1.left.lab -text "Units"
1760 pack .select_vars.col1row1.left.lab
1761
1762 set radio .select_vars.col1row1.left
1763
1764 # set defualt variable values
1765 set history_time 1
1766 set history_unit days
1767
1768
1769 radiobutton $radio.day -text "days" -relief flat -anchor w \
1770 -variable history_unit -value days
1771 pack $radio.day -fill x -expand 1
1772 radiobutton $radio.week -text "weeks" -relief flat -anchor w \
1773 -variable history_unit -value weeks
1774 pack $radio.week -fill x -expand 1
1775 radiobutton $radio.month -text "months" -relief flat -anchor w \
1776 -variable history_unit -value months
1777 pack $radio.month -fill x -expand 1
1778
1779 if {$today_or_file=="old_file"} {
1780 radiobutton $radio.until_now -text "until now" -relief flat -anchor w \
1781 -variable history_unit -value until_now
1782 pack $radio.until_now -fill x -expand 1
1783 }
1784
1785 # now the day/week/month multiplier
1786 set history_amount 1
1787 label .select_vars.col1row1.right.lab -text "Multiplier"
1788 pack .select_vars.col1row1.right.lab
1789
1790 set radio .select_vars.col1row1.right
1791
1792
1793 radiobutton $radio.1 -text "1" -relief flat -anchor w \
1794 -variable history_amount -value 1
1795 pack $radio.1 -fill x -expand 1
1796 radiobutton $radio.2 -text "2" -relief flat -anchor w \
1797 -variable history_amount -value 2
1798 pack $radio.2 -fill x -expand 1
1799 radiobutton $radio.3 -text "3" -relief flat -anchor w \
1800 -variable history_amount -value 3
1801 pack $radio.3 -fill x -expand 1
1802 radiobutton $radio.4 -text "4" -relief flat -anchor w \
1803 -variable history_amount -value 4
1804 pack $radio.4 -fill x -expand 1
1805 radiobutton $radio.5 -text "5" -relief flat -anchor w \
1806 -variable history_amount -value 5
1807 pack $radio.5 -fill x -expand 1
1808
1809
1810 # for the interval:
1811 set history_interval 300 ;# default values
1812
1813 label .select_vars.col2row1.lab -text "History Interval"
1814 pack .select_vars.col2row1.lab
1815
1816 set radio .select_vars.col2row1
1817
1818 radiobutton $radio.1day -text "100 s" -relief flat -anchor w \
1819 -variable history_interval -value 100
1820 pack $radio.1day -fill x -expand 1
1821 radiobutton $radio.2day -text "5 mins" -relief flat -anchor w \
1822 -variable history_interval -value 300
1823 pack $radio.2day -fill x -expand 1
1824 radiobutton $radio.3day -text "30 mins" -relief flat -anchor w \
1825 -variable history_interval -value [expr 30*60]
1826 pack $radio.3day -fill x -expand 1
1827 radiobutton $radio.4day -text "1 hours" -relief flat -anchor w \
1828 -variable history_interval -value [expr 60*60]
1829 pack $radio.4day -fill x -expand 1
1830 radiobutton $radio.5day -text "5 hours" -relief flat -anchor w \
1831 -variable history_interval -value [expr 5*60*60]
1832 pack $radio.5day -fill x -expand 1
1833
1834 update
1835
1836 # now wait until the window with the variables/times is gone before going on:
1837
1838 tkwait window .select_vars
1839
1840 if {$exit_now} {return "do_exit"}
1841
1842
1843}
1844
1845
1846
1847#===================================================================
1848# CALCULATE HISTORTY STOP TIME FROM START DATE AND INTERVAL
1849#===================================================================
1850
1851proc calc_history_stop_time {day_part mon_part yre_part} {
1852 global history_unit history_amount
1853
1854# problem - if the amount starts with 0, like 08 say, tcl
1855# thinks its octal !
1856# So check whether its two digits:if so trim of leading zero.
1857
1858 if {[string length $day_part] == 2} {
1859 set day_part [string trimleft $day_part 0]
1860 }
1861 if {[string length $mon_part] == 2} {
1862 set mon_part [string trimleft $mon_part 0]
1863 }
1864
1865 switch -glob -- $history_unit {
1866 "days" {
1867 set lday_part [expr $day_part + $history_amount ]
1868 set lmon_part $mon_part
1869 set lyre_part $yre_part
1870 if {$lday_part > 28} {
1871 set lmon_part [incr lmon_part]
1872 set lday_part [expr $lday_part - 28]
1873 }
1874
1875 }
1876 "weeks" {
1877 set lday_part [expr $day_part + $history_amount*7 ]
1878 set lmon_part $mon_part
1879 set lyre_part $yre_part
1880 if {$lday_part > 28} {
1881 set lmon_part [incr lmon_part]
1882 set lday_part [expr $lday_part - 28]
1883 }
1884 }
1885 "months" {
1886 set lday_part $day_part
1887 set lmon_part [expr $mon_part + $history_amount ]
1888 set lyre_part $yre_part
1889 if {$lmon_part > 12} {
1890 set lyre_part [incr lyre_part]
1891 set lmon_part [expr $lmon_part - 12]
1892 }
1893 }
1894 }
1895
1896 # make sure they are all 2 digits
1897 if {[string length $lday_part] == 1} {
1898 set lday_part "0$lday_part"
1899 }
1900 if {[string length $lmon_part] == 1} {
1901 set lmon_part "0$lmon_part"
1902 }
1903 if {[string length $lyre_part] == 1} {
1904 set lyre_part "0$lyre_part"
1905 }
1906
1907 # ok now put the string back together
1908 #return $lday_part$lmon_part$lyre_part
1909 return $lyre_part$lmon_part$lday_part
1910
1911}
1912
1913#=========================================================================
1914# SELECT THE EVENT ID TO DISPLAY IN MHIST
1915#=========================================================================
1916
1917
1918proc select_event_id { } {
1919 global event_choice
1920 global pick_event_var
1921
1922 global event_var ;#variable name
1923 global history_time history_interval history_unit history_amount
1924
1925
1926 global item_fname item_fields item_pattern item_equation
1927 global item_color item_max item_min item_list
1928 global equip_name
1929
1930 global strip_chart
1931
1932 global exit_now
1933 global select_men
1934
1935 global event_ids_info ; #mhist event ID and name
1936
1937
1938 global debug
1939 global button_toggle ; #use to toggle lots of variables on/off simul.
1940
1941 set exit_now 0
1942
1943
1944 # ok, first throw up a selection window for the event id. I guess
1945 # this should be a radio button ?
1946
1947 if [winfo exists .select_event ] {
1948 wm deiconify .select_event
1949 raise .select_event
1950 } else {
1951 toplevel .select_event
1952 wm title .select_event "mhist event select"
1953 # the next puts the new window at the same position as the root window
1954 wm geometry .select_event +[winfo rootx .]+[winfo rooty .]
1955 frame .select_event.radio
1956 frame .select_event.row2
1957 }
1958
1959 set radio .select_event.radio
1960 # set default choice
1961 set event_choice [lindex [lindex $event_ids_info 0] 0]
1962
1963 # note: the variables in a -variable statement MUST be global
1964 foreach event_id $event_ids_info {
1965 set win_name [filter_bad_chars [lindex $event_id 0]]
1966 radiobutton $radio.radio$win_name -text $event_id -relief flat -anchor w \
1967 -variable event_choice -value [lindex $event_id 0]
1968 pack $radio.radio$win_name -fill x -expand 1
1969 }
1970
1971 button .select_event.row2.ok -text "ok" -command "destroy .select_event "
1972 button .select_event.row2.cancel -text "cancel" -command "set exit_now 1 ; destroy .select_event"
1973# if {$which_time=="first_time"} {
1974# button .select_event.row2.openfile \
1975# -text "open file" -command "set open_file 1;destroy .select_event"
1976# pack .select_event.row2.openfile -side right
1977# }
1978
1979 pack $radio
1980 pack .select_event.row2 -side bottom
1981 pack .select_event.row2.ok -side left
1982 pack .select_event.row2.cancel -side right
1983 update
1984
1985 # !! The next command forces the script to halt until the .select_event
1986 # dialog box has been destroyed. This is the only way to get a 'top down'
1987 # order of events.
1988
1989 tkwait window .select_event
1990
1991
1992 if {$exit_now} {
1993 return "do_exit"
1994 }
1995
1996 return "continue"
1997
1998}
1999
2000
2001
2002
2003
2004#===================================================================
2005# EMPTY THE ITEM LIST DESTROY EXISTING VECTORS
2006#===================================================================
2007
2008proc clean_list_and_vectors_and_widgets { } {
2009 global item_fname item_fields item_pattern item_equation
2010 global item_color item_max item_min item_list
2011 global select_men
2012
2013 $select_men delete 1 [llength $item_list] ;# remove pull down menu's
2014
2015# GJH Nov-01. This doesnt seem to work. I dont get the scope of vectors
2016 foreach item $item_list {
2017 global V_x_$item
2018 global V_y_$item
2019 global V_y_plot_$item
2020 if {[array exist V_x_$item]} {vector destroy V_x_$item}
2021 if {[array exist V_y_$item]} {vector destroy V_y_$item}
2022 if {[array exist V_y_plot_$item]} {vector destroy V_y_plot_$item}
2023 }
2024
2025 set item_list ""
2026
2027 if {[array exist item_fname]} {unset item_fname}
2028 if {[array exist item_fields]} {unset item_fields}
2029 if {[array exist item_pattern]} {unset item_pattern}
2030 if {[array exist item_equation]} {unset item_equation}
2031 if {[array exist item_color]} {unset item_color}
2032 if {[array exist item_max]} {unset item_max}
2033 if {[array exist item_min]} {unset item_min}
2034
2035
2036
2037 return
2038
2039}
2040
2041
2042#===================================================================
2043# READ THE MHIST -l OUTPUT TO FIND EVID's, VARIABLE NAMES
2044#===================================================================
2045
2046proc get_mhist_list { } {
2047 global event_ids_info ;#mhist event ID and name
2048 global event_var ;#varialbe name
2049 global debug_code ;#general code debug
2050 global file_pref ; #/tmp tmp file prefix
2051 global file_path ;# path to dir containing history files.
2052
2053# erase the previous list
2054
2055 set event_ids_info ""
2056 if {[array exist event_var]} {unset event_var}
2057
2058 set file_hndl [open "/tmp/${file_pref}mhist" r]
2059
2060 while {! [eof $file_hndl]} {
2061 gets $file_hndl string
2062
2063# check for a couple of commom errors:
2064 if {[string first "cannot find recent history file" $string ] !=-1} {
2065 tk_messageBox -message "mhist output: \n $string \n\n\
2066 Possible cause: you are not in the current working directory.\n\
2067 Set directory using Mhist-->Set History Path"
2068 return 0;
2069 }
2070
2071# look for a couple of things: ID: give event iD number
2072# x: gives some of the possible variables.
2073 if {[string first "Event ID" $string ] !=-1 } {
2074 # ok, found an event ID: read the id, name
2075 # look for ID and the ':'
2076 set pos1 [string first "ID" $string]
2077 set pos2 [string first ":" $string]
2078 set evid [string range $string [expr $pos1 +2 ] [expr $pos2 -1] ]
2079 set evid [string trim $evid]
2080 set evnam [string range $string [expr $pos2 +1] [string length $string]]
2081 set evnam [string trim $evnam]
2082 lappend event_ids_info "$evid $evnam"
2083
2084 # skip next spaces:
2085 set string ""
2086 while {![eof $file_hndl] && [llength $string ] == 0 } {
2087 gets $file_hndl string
2088 }
2089 # read the variables
2090 while {![eof $file_hndl] && [llength $string] != 0 } {
2091 # skip midas error messages:
2092 while {[string first "midas.c" $string ] !=-1 } {
2093 gets $file_hndl string
2094 }
2095 # take everything beyond the first :
2096 set pos [string first ":" $string]
2097 set nam [string range $string [expr $pos +1 ] end ]
2098 set nam [string trim $nam]
2099 if {[string length $nam] !=0} {
2100 lappend event_var($evid) $nam
2101 }
2102 gets $file_hndl string
2103 }
2104 }
2105 }
2106
2107 close $file_hndl
2108
2109 return 1
2110}
2111
2112#=========================================================================
2113# REMOVE SPACES, UNDERSCORES, OTHER NON ALPHANUMERIC CHARACTERS
2114#=========================================================================
2115
2116proc filter_bad_chars {word} {
2117 set word [string tolower $word]
2118 regsub -all "\\." $word "_" word ;# eliminate '.' characters
2119 regsub -all "\\+" $word "p" word ;# eliminate '+' characters
2120 regsub -all "\\-" $word "_" word ;# eliminate '-' characters
2121 regsub -all {\[} $word "_" word ;# eliminate '[' characters
2122 regsub -all {\]} $word "_" word ;# eliminate ']' characters
2123 regsub -all " " $word "_" word ;# eliminate ' ' characters
2124 regsub -all "#" $word "_nr_" word ;# eliminate '#' characters
2125 regsub -all "%" $word "_" word ;# eliminate '%' characters
2126 return $word
2127}
2128
2129
2130#==========================================================================
2131# GENERATE NEW COLORS FOR GRAPHS
2132#==========================================================================
2133proc get_new_color { } {
2134
2135 global color_pointer
2136 global max_color_number
2137
2138 set color {SpringGreen1 navy purple orange red cyan DarkGreen blue3 brown green goldenrod \
2139 orange maroon DarkSlateGrey purple blue4 LimeGreen sienna}
2140
2141 set max_color_number 17
2142
2143 incr color_pointer
2144
2145 if {$color_pointer > $max_color_number} {set color_pointer 0}
2146
2147 return [lindex $color $color_pointer]
2148
2149}
2150
2151proc set_main_y_scale {new_ratio} {
2152 # this routine changes the effective y-scale from a the
2153 # standard value of 0-1 to a bigger range using the
2154 # value extracted rom the RHS slider
2155 global slider_scale
2156 global strip_chart
2157
2158 if { $new_ratio<= 2 } {
2159 set mmax 1
2160 set mmin 0
2161 } else {
2162 set mmax $new_ratio
2163 set mmin [expr -1.* $new_ratio]
2164 }
2165
2166 $strip_chart yaxis configure -min $mmin -max $mmax
2167 update
2168 return
2169}
2170
2171
2172#===========================================================================
2173#
2174#===========================================================================
2175proc set_file_path { } {
2176
2177 global file_path ;# path to actual history files
2178 global debug_code
2179 global tit_font
2180
2181 # get current working dir as first guess
2182 if {$file_path==""} {catch "exec pwd" file_path}
2183
2184
2185 toplevel .inputbox ;# make a seperate window for this
2186# put new window at (x,y) of root window:
2187 wm geometry .inputbox +[winfo rootx .]+[winfo rooty .]
2188
2189 frame .inputbox.row1
2190 frame .inputbox.row3
2191
2192 grid .inputbox.row1 -row 1
2193 grid .inputbox.row3 -row 3
2194
2195 label .inputbox.row1.startlab -text "Path to history files: " -height 2
2196 entry .inputbox.row1.start -textvariable file_path -width 40 -font $tit_font
2197 pack .inputbox.row1.start -side right
2198 pack .inputbox.row1.startlab -side left
2199
2200 # create a button which, when clicked, will read the box, then destroy the box
2201 button .inputbox.row3.ok -text "ok" -command {
2202 .inputbox.row1.start get ;# gets read into var.
2203 destroy .inputbox
2204 }
2205 button .inputbox.row3.cancel -text "cancel" -command {
2206 destroy .inputbox
2207 }
2208
2209 pack .inputbox.row3.ok -side left
2210 pack .inputbox.row3.cancel -side left
2211 tkwait window .inputbox ;# wait until its been destroyed
2212
2213 update
2214 if {$debug_code} { puts "Setting file path to $file_path"}
2215 return
2216
2217
2218}
2219
2220
2221#===========================================================================
2222# DISPLAY HELP TEXT
2223#===========================================================================
2224proc help_menu { } {
2225
2226 toplevel .info ; # create a new window
2227 # put a an <ok> button on it:
2228 button .info.ok -text "OK" -command {destroy .info ; return}
2229 pack .info.ok -side bottom
2230
2231 # now create the text widget
2232 # text .info.text -height 25 -width 65
2233 # pack .info.text -side top
2234
2235 # put the text in the window:
2236 # .info.text insert end " \
2237
2238 # use a message window instead of a text window - simpler
2239 message .info.mess -width 6.5i -text \
2240 "Introduction: Stripchart can:\n\n\
2241 1. plot any data in the\
2242 midas database. It uses mchart, (a midas utility) to actually\
2243 extract the data from odb\n\n\
2244 2. view the data stored by mhist, the MIDAS history program.\n\n\n \
2245 This program should live in the ~/bin directory. To start it \
2246 type\n stripchart <name_of_conf_file> or just\n stripchart \n to look\
2247 at data in the history files\n\n \
2248 The configuration files \
2249 are generated by mchart (eg. target.conf, chvi.conf) and \
2250 are in the same format as that understood by gnome \
2251 gstripchart. \n\n \
2252 Example: to see the CHAOS target info type: \n \
2253 mchart -q /equipment/target/variables -f target.conf\n\
2254 and then start\n stripchart target.conf\n or just type \n \
2255 mchart -q /equipment/target/variables -g -f target.conf \n \
2256 \n and stripchart is invoked automatically \n\n\n\
2257 Note that all overlayed graphs are scaled using the max/min values \
2258 defined in the .conf file to fit between 0 and 1. Hence the \
2259 unlabelled y-scale on the main window.\n\
2260 To see a particular data set in its normal, unscaled \
2261 units, use 'view full graph' and select the line or just click \
2262 with the mouse on a point close to the line of interest. \n\n \
2263 Note that the single graphs can be zoomed by dragging the mouse, \
2264 auto-scaled, or 'best' scaled. Hardcopy is available in ps, jpg, gif \
2265 or png format and goes to a file.\n\n\
2266 To use the history function, click on the mhist button. You must be \
2267 in the directory containing the .hst files. You will\
2268 then be asked to select the event number and data words, as well as the\
2269 history duration and interval\
2270 \n\n \
2271 The tcl interpreter bltwish must be in your system.\n
2272 G.J. Hofman gertjan@triumf.ca \n \
2273 Nov-01 \n \
2274 TRIUMF"
2275
2276 pack .info.mess -side bottom
2277
2278 update
2279 return
2280}
2281
2282
2283
2284
2285#======================================================================================
2286# MAIN PROGRAM
2287#======================================================================================
2288
2289# set a few parameters
2290
2291set color_pointer 0
2292
2293set tit_font "-*-helvetica-bold-r-normal-*-13-180-*-*-*-*-*-*"
2294
2295# define the default scrolling time period
2296set time_limit [expr 60*60] ;# in seconds 5 min default.
2297
2298# default y-scaling values for the pop-up windows
2299set scale_ymin ""
2300set scale_ymax ""
2301
2302set last_rescale_time [clock seconds] ;# last time we checked the scaling
2303 # of the pop up windows
2304set conf_fname ""
2305set equip_name ""
2306set item_list ""
2307
2308set doing_mhist 0 ;# data from mhist OR mchart conf file
2309set debug ""
2310set debug_code 0
2311
2312set hist_file ""
2313
2314#new:search for latest mhist
2315set mhist_path ""
2316set file_path ""
2317
2318# get the file name of the .conf files. Command line parsing
2319set arguse 0 ;# no arguments used up by options
2320
2321set display_item_cnt 0 ;# when showing 5 detailed at same time, the pointer.
2322
2323set fix_y_scale 0 ;# whether or not mouse zoom changes y-scale
2324
2325# no option = doing mhistory
2326# last option parameter = .conf file name
2327# assume doing mhist
2328set doing_mhist 1
2329
2330if {$argc!=0} {
2331 for {set i 0} {$i < $argc } {incr i} {
2332 switch -glob -- [lindex $argv $i] {
2333 "-h" {puts "Usage: stripchart <-options> <config-file>\n\
2334 -mhist (look at history file -default)\n\
2335 -dmhist debug mhist \n\
2336 -debug debug stripchart\n\
2337 config_file: see mchart"
2338 exit}
2339 "-mhist" { set doing_mhist 1 ; incr arguse}
2340 "-dmhist" { set debug mhist ; incr arguse}
2341 "-debug" { set debug_code 1 ; incr arguse}
2342 }
2343 }
2344 if {$arguse < $argc} {
2345 set conf_fname [lindex $argv [expr $argc -1] ]
2346 set doing_mhist 0
2347 }
2348}
2349
2350if {$debug_code} {
2351 puts "Debugging on"
2352 if {$doing_mhist} {
2353 puts "Debug: doing mhist "
2354 } else {
2355 puts "Debug: doing mchart "
2356 }
2357}
2358
2359
2360if {!$doing_mhist} {
2361 if {![file exists $conf_fname]} {
2362 tk_messageBox -message "Error: conf file $conf_fname not found_!" -type ok
2363 exit
2364 } else {
2365 # read in the .conf file and parse:
2366 read_conf_file $conf_fname
2367 }
2368}
2369
2370
2371frame .main -background beige ;# define name of main window.
2372frame .main.toprow -relief ridge -bd 3 ;# for the buttons
2373frame .main.middle -relief ridge -bd 3 ;# for the graph
2374frame .main.botrow ;# unused for now
2375
2376wm title . "midas stripchart: $equip_name (GJH v.2.2)" ;# configure the FVWM window
2377wm iconname . "StripC"
2378
2379set strip_chart .main.middle.strip_chart
2380
2381#graph $strip_chart -background goldenrod -title "" ;# no title on the graph.
2382graph $strip_chart -background "#02a2fe" -title "" ;# no title on the graph.
2383
2384# standard size is 5.5ix 2.0i
2385$strip_chart configure -width 6.5i -height 2.5i -font $tit_font
2386
2387#$strip_chart marker create bitmap -under yes -coords { .2 .7} -bitmap @midas.xbm
2388
2389
2390# configure the x-axis to plot Clock time instead of plain numbers
2391$strip_chart xaxis configure -loose 0 -title "" \
2392 -command "my_clock_format %H:%M" -tickfont $tit_font -titlefont $tit_font
2393
2394# fix the yaxis scale
2395$strip_chart yaxis configure -min 0 -max 1 \
2396 -tickfont $tit_font -titlefont $tit_font -showticks 0
2397
2398# switch on cross hairs
2399#Blt_Crosshairs $strip_chart ;# what is this comand ???
2400# bind the mouse click to the item search routine and pass
2401# window name, x and y coordinate
2402bind $strip_chart <B1-ButtonRelease> "mouse_find_item %W %x %y"
2403
2404# create an exit button. The -bd 0 mean a tight fit of text - no border
2405button .main.toprow.exit -text "exit" -command {nice_exit} -relief flat -underline 0
2406pack .main.toprow.exit -side left
2407
2408
2409# create an exit button
2410button .main.toprow.help -text "help" -command {help_menu} -relief flat -underline 0 -bd 0
2411pack .main.toprow.help -side left
2412
2413
2414# menu for selecting of individual items = make a 'menubutton'
2415set select_but [menubutton .main.toprow.select -text "detail-single" \
2416 -menu .main.toprow.select.mnu -relief flat -underline 0 -bd 0 ]
2417set select_men [menu $select_but.mnu]
2418
2419pack $select_but -side left -fill x
2420
2421
2422# Nov 201- new way of showing detail graphs:
2423button .main.toprow.show_all -text "detail-all" -command {show_all_full_scale} \
2424 -relief flat -underline 0 -bd 0
2425pack .main.toprow.show_all -side left
2426
2427
2428
2429# create an *new* scroll time selection.
2430
2431menubutton .main.toprow.scrollt -text "scroll time" -menu .main.toprow.scrollt.mnu \
2432 -relief flat -underline 0 -bd 0
2433menu .main.toprow.scrollt.mnu
2434.main.toprow.scrollt.mnu add radiobutton -label "100 s" -variable time_limit \
2435 -value 100
2436.main.toprow.scrollt.mnu add radiobutton -label "5 mins" -variable time_limit \
2437 -value 300
2438.main.toprow.scrollt.mnu add radiobutton -label "30 mins" -variable time_limit \
2439 -value [expr 30*60]
2440.main.toprow.scrollt.mnu add radiobutton -label "1 hour" -variable time_limit \
2441 -value [expr 60*60]
2442.main.toprow.scrollt.mnu add radiobutton -label "5 hour" -variable time_limit \
2443 -value [expr 5*60*60]
2444.main.toprow.scrollt.mnu add radiobutton -label "10 hours" -variable time_limit \
2445 -value [expr 10*60*60]
2446.main.toprow.scrollt.mnu add radiobutton -label "24 hours" -variable time_limit \
2447 -value [expr 24*60*60]
2448pack .main.toprow.scrollt -side left -fill x
2449
2450
2451# old mhist button, now replaced by a pull down meni
2452#button .main.toprow.hist -text "mhist" -command {read_mhist} \
2453# -relief flat -underline 0 -bd 0
2454#pack .main.toprow.hist -side left
2455
2456set mhist_but [menubutton .main.toprow.mhist -text "mhist" \
2457 -menu .main.toprow.mhist.mnu -relief flat -underline 0 -bd 0]
2458set mhist_men [menu $mhist_but.mnu]
2459pack $mhist_but -side left -fill x
2460$mhist_men add command -command "read_present_mhist" -label "Today's MHIST"
2461$mhist_men add command -command "read_mhist_file 1" -label "Open old history file"
2462$mhist_men add command -command "read_mhist_file 0" -label "Same file, New event"
2463$mhist_men add command -command "set_file_path" -label "Set history-file path"
2464
2465
2466# create a warning label to show whether we have new data coming in
2467label .main.toprow.update -relief sunken \
2468 -textvariable prev_update_time_formatted -bd 0
2469pack .main.toprow.update -side right
2470label .main.toprow.warning -relief flat -pady 4 \
2471 -text "Update: " -background green -bd 0
2472pack .main.toprow.warning -side right -fill x
2473
2474# pack all the remaining windows: - first pack graph in middle row:
2475# note: its the 'fill both' and 'expand 1' that does the resizing
2476# of the graph when the window size changes.
2477
2478pack $strip_chart -side left -fill both -expand 1 ;# put it in its parent.
2479
2480# then pack middlerow in the .main:
2481pack .main.middle -side top -fill both -expand 1
2482pack .main.toprow -side top -fill x -expand 1
2483
2484#pack .main.botrow -side top -fill both -expand 1 ; # bot row unused
2485
2486pack .main -fill both -expand 1 ;# put it all on the screen
2487update
2488
2489# try the slider to change the scale of the main graph
2490# note: the -command automatically appends the value of the slide
2491#set scale_slider 1
2492#scale .main.middle.slide -orient vertical -label "" -variable scale_slider \
2493# -borderwidth 0 -showvalue 0 -width 10 -from 10 -to .1 \
2494# -command "set_main_y_scale"
2495#pack .main.middle.slide -side right -fill y -expand 1
2496
2497
2498
2499# check if we can write to /tmp/ - get a file namw prefix.
2500# catch returns zero if it's ok.
2501
2502set file_pref "0"
2503set fcnt 0
2504# look until we have no error from deletion:
2505while { [catch "exec rm -f /tmp/${file_pref}mhist" error_var] || \
2506 [catch "exec rm -f /tmp/${file_pref}mhist_data" error_var] } {
2507 incr file_pref
2508}
2509
2510
2511
2512#============================================================================
2513# CODE HERE IS INFINITE LOOP FOR MHIST USAGE
2514#============================================================================
2515
2516# ok, done all the things we can do for both mhist AND normal stripcharting
2517# if we didn't open a .conf file, just sit here and wait:
2518if {$doing_mhist} {
2519 .main.toprow.warning configure -text "mhist " -background cyan
2520
2521 while {1} {
2522 $strip_chart configure -background "#02a2fe"
2523 wm title . "midas stripchart: $equip_name (GJH v.2.0)"
2524 wait_ms 200
2525 }
2526}
2527
2528
2529
2530# ===============================================================================
2531# CODE BELOW FOR ONLINE STRIPCHARTING ONLY
2532# ===============================================================================
2533
2534# remove the mist button - dont need it for mchar applications
2535destroy $mhist_but
2536
2537
2538# create the pull down item menu. Also align the text string
2539set blank_string " "
2540foreach item $item_list {
2541 set item_length [string length $item]
2542 if {$item_length > 13} {set item_length 13}
2543 set menu_string "$item [string range $blank_string 1 [expr 13 - $item_length
2544 ] ]"
2545 append menu_string $item_color($item)
2546 $select_men add command -command "select_graph $item" -label $menu_string
2547}
2548
2549
2550# ok, finally, create vectors associated with the data.
2551# create also the graph elements:
2552
2553foreach item $item_list {
2554 if {! [$strip_chart element exists line_$item]} {
2555 $strip_chart element create line_$item
2556 } else {
2557 tk_messageBox -message "Error(online): line $item already exist - skipped "
2558 continue
2559 }
2560 $strip_chart element configure line_$item -label "" -color $item_color($item) -symbol ""
2561 vector create V_y_$item ;# for storing raw data
2562 vector create V_y_plot_$item ;# 'scaled' vector for plotting
2563 vector create V_x_$item ;# time vector.
2564 # now hot-link it to the new graph line
2565 $strip_chart element configure line_$item -xdata V_x_$item -ydata V_y_plot_$item
2566}
2567
2568
2569
2570# for now I am assuming all data values are read from the SAME file.
2571
2572set data_fname $item_fname([lindex $item_list 0]) ;# just grab the first filename
2573
2574
2575# main plotting loop:
2576
2577set prev_update_time 0 ;# last time the data file was written
2578
2579set time_limit 600
2580
2581while {1} {
2582
2583# check if the file exist and when it was last written
2584
2585 if {![file exists $data_fname]} {
2586 show_message "Error: data file $data_fname not found !"
2587 .main.toprow.warning configure -text "No Data File" -background red
2588 vwait message_done ;# wait until message ok button was hit.
2589 # go into loop, waiting for file:
2590 while {![file exists $data_fname]} {
2591 wait_ms 1000
2592 }
2593 } else {
2594
2595 # check the last modification time of the file:
2596 while { [file mtime $data_fname]== $prev_update_time} {
2597 after 50
2598 update
2599 set time_passed [expr ( [clock seconds] - [file mtime $data_fname])]
2600 if { $time_passed > 200 } {
2601 .main.toprow.warning configure -text "No Data" -background red
2602 }
2603 }
2604 wait_ms 1000
2605 }
2606
2607# ok, we have a new file:
2608 .main.toprow.warning configure -text "Update: " -background green
2609
2610 set prev_update_time [file mtime $data_fname]
2611# for output to screen, format the time for humans:
2612 set prev_update_time_formatted [clock format $prev_update_time -format "%H:%M:%S"]
2613
2614 set file_hndl [open $data_fname r]
2615
2616 set cnter 0
2617 # loop over all lines in the file
2618 while {! [eof $file_hndl]} {
2619
2620 gets $file_hndl string
2621
2622 # for some reason, the last line is an empty string. Not sure why
2623 # skip empty strings
2624 if {[string length $string]==0} {
2625 break
2626 }
2627
2628 set item_string [lindex $string 0]
2629
2630 set item_string [string tolower $item_string]
2631 # remove underscores etc.
2632 set item_string [filter_bad_chars $item_string]
2633
2634 # loop over all known keyword and compare to file.
2635
2636
2637 foreach item $item_list {
2638 if { $item==$item_string} {
2639 incr cnter
2640 set new_data [expr 1.0 *[lindex $string 1]]
2641 set vec_name V_x_$item
2642 set ${vec_name}(++end) $prev_update_time
2643 set vec_name V_y_$item
2644 set ${vec_name}(++end) $new_data
2645
2646 # now scale the vector to fit on the graph.
2647 set plot_vec_name V_y_plot_$item
2648 set norm_data \
2649 [expr " ($new_data - $item_min($item)) / ($item_max($item)-$item_min($item)) " \
2650 + $cnter/100.]
2651 # note I add a small offset... just so that lines dont overlap each other
2652 set ${plot_vec_name}(++end) $norm_data
2653 }
2654 }
2655 update
2656 }
2657
2658 close $file_hndl
2659
2660
2661 # take care of the scrolling:
2662 # I do some tricky double de-referencing here. I need to access the
2663 # vector but I only have the name of the vector. So the inner 'set'
2664 # returns the name of the vector. I then concatenate (0) and
2665 # finally get the actual value stored in the vector
2666
2667
2668 foreach item $item_list {
2669 set oldest_time [ set V_x_[set item](0)]
2670 set newest_time [ set V_x_[set item](end)]
2671
2672# puts "data are now [set V_y_[set item](:)]"
2673
2674 if { [expr ( $newest_time - $oldest_time)] > $time_limit } {
2675 V_x_$item delete 0
2676 V_y_$item delete 0
2677 V_y_plot_$item delete 0
2678 }
2679 }
2680
2681
2682 # also check if we you re-evaluate the scaling on the individual plots
2683 # say at every 300 s.
2684 set time_now [clock seconds]
2685 if { [expr $time_now - $last_rescale_time ] > 200} {
2686 foreach item $item_list {
2687 if [winfo exists .fullscale$item ] {
2688 scale_single_window Rescale $item 1
2689 }
2690 if [winfo exist .fullscale_main.fullscale$item] {
2691 scale_single_window Rescale $item 2
2692 }
2693 }
2694 set last_rescale_time $time_now
2695 }
2696
2697 update
2698
2699 wait_ms 10000
2700
2701
2702}
2703
2704
2705
2706#=======================================================================================
2707#====================== END OF CODE ====================================================
2708#=======================================================================================