# Presentation: 367559

## Tcl/Tk and the OAG Tcl/Tk Environment

*Robert Soliday*
*Assistant Scientist / AOD*
*September 21**st**, 2004*

**Notes:**
Mark Twain said success comes from a mixture of ignorance and confidence. I home to my fellow colleges would say I have more of the later. I have been working with the OAG group for over five years as a computer programmer working with the operators and scientists to create and improve software they need to do their job. Today I hope to give you a better understanding of what the OAG group does. I will try to focus on the software that I personally have worked on and leave the rest for the others to talk about.

## Outline

**Introduction to the Tcl/Tk environment**
**Misconceptions about Tcl/Tk**
**Explanation of OAG Tcl/Tk**
**Channel Access extension**
- Loading the package
- Explanation of commands
**SDDS extension**
- Loading the package
- Explanation of commands
**Documentation on the web**
**How to obtain OAG Tcl/Tk for your system**

**Notes:**
I’ll be hitting a lot of topics today and try and explain the underlying problems and the solutions that we came up with. *Starting with the software related to operations which would include the procedure execution manager, otherwise known as the PEM, which is used by the operators daily. This was the topic of my paper at the Linac 2000 Conference. *Next storage ring simulator which was the topic of one of my PAC 2003 papers. *I’ll try to show a demo of the PEM using the SR simulator. *Next is the controllaw software running in the EPICS IOC which was needed for the integration of orbit control with real-time feedback in the SR. This was in an oral presentation by Frank Lenkszus at PAC 2003. *I’ll touch on our data logging software the the different types of data archiving programs that we use. *And the related web based data review is a new convenient way of accessing the data logs from a web browser which may be more convenient for the CAT users. *Next is an explanation of the software reliability controls which include our version control tools. *Then we’ve got the Linux computer clusters that we are now using to run CPU intensive accelerator related software. *One of the newer projects is the Tcl/Tk SDDS plotter based off the sddsplot program. *Next is the MATLAB/SDDS interface that was created to allow MATLAB users direct access to SDDS data. *And finally a quick list of some of the places where OAG software is used outside the APS.

## Introduction to the Tcl/Tk Environment

**Why would I want to use Tcl/Tk? What is in it for me?**
- With Tcl (Tool Command Language) you can creating useful programs in minutes.
- Freely available for X Windows, Windows, and Macintosh.
- Tcl has simple constructs and looks somewhat like C.
*This means that it is easy read and understand the source code. This is useful when editing other people’s programs.*
**Three benefits to a script-based Tk approach to user interface programming.**
- No compilations means fast development.
- GUIs require just a handful of commands to define them because the Tk library provides a higher level interface than most standard C library toolkits.
- The GUI is clearly factored out from the rest of the application.

**Notes:**
The motivation for creating the PEM was the observation that many accelerator operations take the form of written or memorized procedures. While this may work, it is a long way from automated. *Automation helps with the occasional need to switch quickly between two different operational states such as switching from RFGun1 to RFGun2. *Many times there are independent steps that can be performed at the same time but with an operator the physical limitation of one mouse, one screen, makes this almost impossible. The ability to automate procedures in parallel is one of the best way to speed up the procedures. *The beam quality and characteristics are hard to reproduce with the complicated accelerator systems when the operators do it by hand because each operator may have a preferred order and or manor in the steps needed. 

## Misconceptions about Tcl/Tk

**Perl is faster than Tcl?**
- This was true many years ago, but Tcl caught up with the 8.0 release in 1997. This version introduced the bytecode interpreter.
**Perl has better regular expressions?**
- Again, this was true in the past, but the current Tcl’s regular expression package has all of the advanced features Perl has.
**Tcl doesn’t support namespaces or object-oriented programming?**
- Namespaces were added in 1997 and object-oriented programming is available in the [incr Tcl] extension.
**Tcl can’t handle binary data?**
- Tcl has supported binary data since the 8.0 release.

**Notes:**
*With the use of the PEM we have a scripting environment for the coding of accelerator operation procedures and a top level manager application for running and monitoring these procedures. *The PEM allows for expandability by adding new procedures in sequence or in parallel. Smaller PEM procedures can be linked together and run by a parent PEM procedure, and so on. *Usually PEM procedures have an initial dialog where the user can select or exclude certain options. For child PEM procedures these selections are set by the parent PEM and the dialog is not displayed. *The use of PEMs has become routine in the APS control room. The similar look and feel between PEM procedures has been helpful with getting operators orientated with new PEM procedures.

## Explanation of OAG Tcl/Tk

**OAG Tcl/Tk Interpreter**
- Extensive collection of general purpose graphical and non-graphical Tcl/Tk procedures.
- Main windows
- Basic widgets
- Complex widgets
- Utility procedures
- Our version of Tcl/Tk includes four C extensions.
- CA (Channel Access based originally on et_wish)
- SDDS (Self Describing Data Sets)
- RPN (Reverse Polish Notation)
- OS (Miscellaneous commands)

## Explanation of OAG Tcl/Tk

**10 years of development has resulted in a wide range of applications and general purpose functions.**
**Having a GUI with a simple and powerful scripting language along with CA and SDDS extensions that works on most operating systems means we can spend less time worrying about the tools and more time working about the project.**

## OAG Tcl/Tk Applications

**OAGapps**
- Contains a large collection of OAG Tcl/Tk applications.
- Available off the Workspace Menu under Accelerator Data.

## OAG Tcl/Tk Widgets and Procedures

**OAG Tcl/Tk Help**
- Used as a quick reference to display the syntax of OAG Tcl/Tk widgets and procedures.

## OAG Tcl/Tk Main Window

**Creating the main window in an OAG application.**
**#!/bin/sh**
**# \**
**exec oagwish “$0” “$@”**
**set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]**
**set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]**
**APSApplication . –name “Demo Script”**

## OAG Tcl/Tk Basic Widgets

## OAG Tcl/Tk Basic Widgets

## OAG Tcl/Tk Basic Widgets

## OAG Tcl/Tk Complex Widgets

## OAG Tcl/Tk Complex Widgets

## OAG Tcl/Tk Complex Widgets

**APSPlotCanvas .plot \****    -parent .userFrame \****    -sddsplotOptions “-column=Time,(iocs11fb:load,iocs13fb:load,iocs15fb:load) ****        srIOC-2003-310-1106.gz -graph=symbol,vary=subtype -ticks=xtime -legend"**

## OAG Tcl/Tk Utility Procedures

**APSStandardSetup**
- Initializes a number of global variables and Tcl/Tk options. Usually used in place of APSApplication for non-GUI applications.
**APSStrictParseArguments**
- Translates sequences like “-keyword value” into “set keyword value”; that is, the keyword names are variable names in the calling procedure.
**APSWaitWithUpdate**
- Pauses the execution but keeps the GUI responsive. Also allows for an abort variable whose change will result in the execution to continue immediately.
**APSEnableDisableWidget**
- Enables or disables the named widget and all of its children.

## OAG Tcl/Tk Utility Procedures

**APSPrintText**
- Options include the variable containing the text and the print command itself.
**APSSendEMail**
- Used to send email or page. Includes the option to not page at inconsiderate hours.
**APScavget, APScavput**
- Copies the functionality and command line options of cavget and cavput while using the Tcl CA Extension. The benefit being that only one CA connection is made per PV no matter how many times it is called.

## Channel Access with OAG Tcl/Tk

**PV values are linked to Tcl/Tk variables**
- Values can be changed locally and set to an IOC, or
- PV values in an IOC can change and be monitored by OAG Tcl/Tk
**No external programs are required**
- Increased speed because of the time it takes to launch an external program

## OAG Tcl/Tk Demo using CA Extension

## Channel Access Extension

**Loading the CA extension into oagwish (basic method)**
**> oagwish**
**% package require ca**
**1.0**
**Loading the CA extension into oagwish (standard method)**
**#!/bin/sh**
**# \**
**exec oagwish “$0” “$@”**
**set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]**
**set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]**
**APSApplication . –name “Demo Script”**

## Overview of CA Extension Commands

**link, linkw, unlink**
- Link and unlink to process variables.
**get, getw**
- Set related Tcl variable to the value of the PV.
**put, putw, putq**
- Set PV to the value of the related Tcl variable.
**mon, umon, cmon**
- Establish a monitor between the Tcl variable and the value of the PV.
**info**
- Obtain information about PVs.
**stat**
- Obtain state, status, severity and time information about a PV.
**toggleErrorMode**
- Toggle between standard error handling and backward compatibility with previous versions of the CA extension.

## CA Link Commands

**When should you use link instead of linkw?**
- When you want to keep the GUI responsive.
*If the user is allowed to type the PV name there is a chance of a typo which would lead to long timeout periods where the GUI would appear to lockup if using linkw.*
- When you want to find the name of a PV that is not connecting.
*With linkw it is not possible to isolate an invalid PV name.*
**When should you use linkw instead of link?**
- When you are reasonably sure the PVs will link without problems.
*Normally PVs will connect in under a second and GUI responsiveness does not come into play.*
- When ease of use is desirable.
*It blocks execution until all the PVs have connected.*

## CA Link Commands in Demo

**“****pv link” is used for all connections because it needs to know the name of the PV that is not connecting in order to white out the corresponding widget.**

## CA Link Commands

**Syntax**
**	****pv link tclVars iocVars [<timeout>]**
**Example**
- 	**pv link current S35DCCT:currentCC 10**
**	****set endtime [expr [clock seconds] + 10]**
**	****set connected 0**
**	****while {[clock seconds] <= $endtime} {**
**	****	****update**
**	****	****pv stat current currentStat**
**	****	****if {$currentStat(state) == “OK”} {**
**	****	****    ****set connected 1 ; break**
**	****	****}**
**	****}**
**	****if {$connected} {**
**	****	****puts $current**
**	****}**

**Notes:**
What is one of the main problems with the SR studies time?...Could it be there is just not enough of it. *SR studies time is scarce during a run, and with the TopUp mode in the SR injector studies time has been increasingly scarce as well. This has led to the need to test software outside the main control room. *To do this we needed to be able to simulate various PVs so that the software would not know the difference. *Another requirement is that the simulated PVs must be easy to add and some of their real properties must also be simulated. 

## CA Link Commands

**Syntax**
**	****pv linkw tclVars iocVars [<timeout>] [-blunderAhead]**
**Example #1**
- 	**pv linkw current S35DCCT:currentCC**
**	****puts $current**
**Example #2**
- 	**set iocVars “Mt:S:NumBucketsFilledAI NoOfShuttersOpenA”**
**	****pv linkw “nbuckets nshutters” $iocVars**
**	****puts “nbuckets=$nbuckets nshutters=$nshutters”**

## CA Link Commands

**Syntax**
**	****pv unlink tclVars**
**Example**
- 	**pv linkw current S35DCCT:currentCC**
**	****puts $current**
**	****pv unlink current**

## CA Get Commands

**When should you use get instead of getw?**
- When you what to keep the GUI responsive and are willing to use the stat command to detect when the response has been received.
**When should you use getw instead of get?**
- When ease of use is desirable.
*It blocks execution until all the PVs have responded.*

## CA Get Commands

**Syntax**
**	****pv get tclVars [<timeout>]**
**Example**
**	****pv linkw current S35DCCT:currentCC**
**	****...**
**	****pv get current**
**	****pv stat current currentStat**
**	****while {$currentStat(state) != “OK”} {**
**	****	****update**
**	****	****pv stat current currentStat**
**	****}**
**	****puts $current**

## CA Get Commands

**Syntax**
**	****pv getw tclVars [<timeout>]**
**Example**
**	****pv linkw current S35DCCT:currentCC**
**	****...**
**	****pv getw current**
**	****puts $current**

## CA Put Commands

**When should you use put?**
- Require notification from the IOC that record processing has completed. However it will not block execution.
**When should you use putw?**
- Require notification from the IOC that record processing has completed. It will block execution until record processing has completed.
**When should you use putq?**
- When there is no need to wait for notification from the IOC that record processing has completed.

## CA Put Commands in Demo

**“****pv putq” is used with entry boxes, scales, buttons and radio buttons**

## CA Put Commands 

**Syntax**
**	****pv put tclVars [<timeout>]**
**Example**
**	****pv linkw current win32:cathodeCurrentC**
**	****set current 12.0**
**	****pv put current**

## CA Put Commands

**Syntax**
**	****pv putw tclVars [<timeout>]**
**Example**
**	****pv linkw current win32:cathodeCurrentC**
**	****set current 12.0**
**	****pv putw current**

## CA Put Commands

**Syntax**
**	****pv putq tclVars [<timeout>]**
**Example**
**	****pv linkw current win32:cathodeCurrentC**
**	****set current 12.0**
**	****pv putq current**

## CA Monitor Commands

**When should you use mon instead of umon?**
- When the Tcl variable is not linked to a Tk widget.
*The value of the variable is only updated when it is read.*
**When should you use umon instead of mon?**
- When a Tk widget is used to display the value of the variable.
*The widget will update at the same time as the variable.*
**When should you use cmon?**
- Used to stop monitoring a PV.

## CA Monitor Commands in Demo

**“****pv mon” is used indirectly with labels, bars, plots, text boxes**
- Every second a procedure is run to update the widgets
- This method reduces excess screen updates for readback PVs
**“****pv umon” is used with entry boxes, scales, radio buttons**
- Widgets are updated instantly because the can be changed by the user.

## CA Monitor Commands

**Syntax**
**	****pv mon tclVars [script]**
**Example**
**	****pv linkw voltage L1:RG2:KIK:PFNVoltageAI**
**	****pv mon voltage {puts “voltage=$voltage”}**

## CA Monitor Commands

**Syntax**
**	****pv umon tclVars [script]**
**Example**
**	****pv linkw voltage L1:RG2:KIK:PFNVoltageAI**
**	****label .voltage –textvariable voltage**
**	****pack .voltage**
**	****pv umon voltage {puts “voltage=$voltage”}**

## CA Monitor Commands

**Syntax**
**	****pv cmon tclVars**
**Example**
**	****pv linkw voltage L1:RG2:KIK:PFNVoltageAI**
**	****pv umon voltage {puts “voltage=$voltage”}**
**	****...**
**	****pv cmon voltage**

## CA Info Command

**When would you use the info command?**
- To obtain information in the form of lists of lists about linked Tcl channel access connections.
- That information could include
*State of communication link*
*Severity as defined by EPICS*
*Status as defined by EPICS*
*Units as defined by EPICS*
*Choices for enumerated PVs*
*IOC name*
*Upper and lower limits*
*Read and write access privileges*

## CA Info Command

**Syntax**
**pv info tclVars <requestedInfo>**
**	****<requestedInfo> - state, severity, status, time, units, name, choices, hopr, lopr, drvh, drvl, hihi, hi, lolo, lo, precision, ioc, access, size**
**Example**
**pv linkw voltage L1:RG2:KIK:PFNVoltageAI**
**pv info voltage “lolo hihi”**

## CA Stat Command

**When would you use the stat command?**
- To obtain state, status, severity and time information about a PV as elements of a Tcl array.
- Some may find the stat command to be more convenient than the info command

## CA Stat Command

**Syntax**
**	****pv stat tclVar <associative_array_name>**
**Example**
**	****pv linkw voltage L1:RG2:KIK:PFNVoltageAI**
**	****pv stat voltage v**
**	****puts “$v(status) $v(state) $v(severity)”**

## CA toggleErrorMode command

**To keep backward compatibility with previous versions of the CA extension the link, get, put, mon and stat commands by default return 0 on successful completion and 1 when an error occurs. The error message is then stored in a global variable called “errorCode.” **
**The toggleErrorMode command toggles between standard Tcl error handling and backward compatibility mode.**
**By using standard Tcl error handling it is possible to use the Tcl “catch” command to trap errors.**

## SDDS (Self Describing Data Sets)

**SDDS is the file format that we use to store and process data logs of process variables and various other types of data.**
**Stable, general purpose file protocol**
**Generic tools that operate on SDDS files**
**EPICS tools that are configured by SDDS files**
**Libraries for working with such files**
**Multi-platform and open-source**
- Solaris, Linux, Windows, OS X, VxWorks
**Supported languages**
- C/C++, Tcl/Tk, Python, Java, IDL, MATLAB, FORTRAN

## Why Use Self Describing Data?

**Programs that use it are much more robust and flexible**
- Check existence, data-type, units of data instead of crashing or doing something inappropriate
- Respond appropriately to the data that is provided
*Exit and warn user*
*Use defaults for missing data*
- Data does not become obsolete when the program is upgraded
**Data sets can evolve without breaking applications**
**Multiple uses for one data set are possible**
- Helps maintain consistent configuration of multiple applications

## SDDS File Protocol

**Consists of**
- A header describing what the file contains.
- One or more pages containing
*Parameter values*
*Column values*
*Array values*
**The header defines the name, type, and units for the parameters, columns and arrays. Where the type can be a string, character, double, float, long or short.**
**Includes support for binary, ASCII and compressed storage modes.**

## SDDS Toolkits

**Without the Toolkits, SDDS would just be another boring file format**
**Toolkit is inspired by UNIX**

## SDDS and Tcl/Tk

**SDDS and Tcl/Tk complement each other**
**Tcl/Tk is a good language for GUIs, but**
- Lacks data management capabilities
- Not great for computation
**SDDS offers data management, analysis, and computation, but**
- Is not a programming language
- Has commandline user interface

## SDDS Extension

**Loading the SDDS extension into oagwish (basic method)**
**> oagwish**
**% package require sdds**
**1.0**
**Loading the SDDS extension into oagwish (standard method)**
**#!/bin/sh**
**# \**
**exec oagwish “$0” “$@”**
**set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)**
**set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)**
**APSApplication . –name “Demo Script”**

## Overview of SDDS Extension Commands

**load**
- Used to load SDDS files into a Tcl array
**save**
- For saving SDDS files from a Tcl array
**Older and superseded commands**
- open, close
- getParameter, getColumn, getArray
- getParameterInformation, getColumnInformation, getArrayInformation
- getNames
- sddsDefineParameter, sddsDefineColumn, sddsDefineArray
- writeLayout, startPage, writePage
- setParameter, setColumn, setRowValues, setArray

## SDDS Load and Save Commands

**Syntax**
**	****sdds load <fileName> <tclArrayName>**
**	****sdds save <fileName> <tclArrayName>**
**Contents of Tcl array**
- (Layout.DataMode.Mode) – “ascii” or “binary”
- (Layout.LinesPerRow) – integer
- (Description.Contents) – string
- (Description.Text) – string
- (ParameterNames) – list of parameter names
- (ArrayNames) – list of array names
- (ColumnNames) – list of column names

## SDDS Load and Save Commands

**Contents of Tcl array (continued)**
- (ParameterInfo.{name}) – list similar to:“name Time symbol {} units {} description {} format_string {} type SDDS_LONG fixed_value {}”
- (Parameter.{name}) – list where each element represents the parameter value for a different page
- (ArrayInfo.{name}) – list similar to:“name Direction symbol {} units {} description {} format_string {} type SDDS_DOUBLE dimensions 2”
- (Array.{name}) - List where each element represents the array data for a different page. The data for each page is a list that alternates between an index and the corresponding array value.

## SDDS Load and Save Commands

**Contents of Tcl array (continued)**
- (ColumnInfo.{name}) – list similar to“name Days symbol {} units {} description {} format_string {} type SDDS_STRING”
- (Column.{name}) - List where each element represents the column data for a different page. The data for each page is separated into different elements for each row.

## SDDS Load Command

**Example**
**	****sdds load foo.sdds bar****foreach name $bar(ParameterNames) {****    set page 1****    foreach data $bar(Parameter.$name) {****        puts “page $page, $name = $data”****        incr page****    }****}****foreach name $bar(ColumnNames) {****    set page 1****    foreach data $bar(Column.$name) {****        set row 1****        foreach item $data {****            puts “page $page, row $row, $name = $item”****            incr row****        }****        incr page****    }****}**

## SDDS Save Command

**Example**
**	****set now [clock seconds]****set tomorrow [expr $now + 86400]****set bar(Description.Text) “Example file”****set bar(Description.Contents) “Random data”****set bar(ParameterNames) “Time Date”****set bar(ParameterInfo.Time) “type SDDS_LONG”****set bar(Parameter.Time) [list $now $tomorrow]****set bar(Parameter.Date) [list [clock format $now] [clock format $tomorrow]]****set bar(ColumnNames) “Days Colors”****set bar(Column.Days) [list “Sun Mon Tue” “Wed Thur Fri Sat”]****set bar(Column.Colors) [list “Red Pink Blue” “Brown Black Green White”]****if {[catch {sdds save foo.sdds bar} result]} {****    puts stderr “unable to save foo.sdds: $result”****    exit****}**

## OAG Tcl/Tk Documentation on the Web

_**[www.aps.anl.gov/asd/oag/documentation.shtml](http://www.aps.anl.gov/asd/oag/documentation.shtml)**_
- HTML, postscript and PDF
- APS Tcl/Tk Library and Interpreter Extensions
- APS CA Tcl/Tk Extension
- APS SDDS Tcl/Tk Extension

## Obtaining and Installing OAG Tcl/Tk

_**[www.aps.anl.gov/asd/oag/oagPackages.shtml](http://www.aps.anl.gov/asd/oag/oagPackages.shtml)**_
- Prebuilt installation packages for Windows and Linux
- Source code available
*Requires EPICS and SDDS packages to be built first.*

## Conclusions

**With 10 years of development and a dedicated OAG staff, OAG Tcl/Tk has become a strong general purpose tool that others can use to avoid excessive development time worrying about the underlying structure.**
**With the CA and SDDS extensions it is possible to create complex applications well suited for the APS environment.**