The Tcl bindings to the C++ API closely mimic the C++ API. Tcl is a command based language. The C++ API is object oriented. The standard way to do object oriented programming or present object oriented APIs is through command ensembles.
A Tcl command ensemble is a command with subcommands. You can think of a command as a class or an object and the subcommand as methods (class or object level). You can imagine a Tcl command that represents a class. It might have construction subcommand that would dynamically generate a new command ensemble that represents an object. This is the approach taken by the Tcl bindings.
The Tcl bindingsx are in a package called SpecTclDB which is stored in the SpecTcl Tcl package library. There are two ways to bring that library directory tree into the Tcl package search path:
Via an environment variable. For example, suppose the environment variable SPECTCLHOME is defined and is the top level directory in which the version of SpecTcl you are using is stored. TCLLIBPATH=$SPECTCLHOME/TclLibs tclsh will run a Tcl shell that includes the SpecTcl Tcl library tree in the search path.
Extension of the the Tcl auto_path
variable. Suppose, as before SPECTCLHOME is defined
to be the top level installation directory of your SpecTcl
version, the following script fragment will bring the
SpecTcl Tcl packages into your search path.
The global env
array contains
the values of environment variables indexed by variable
name. The file join command joins file
system path elments and lappend
appends items to a list, in this case the
auto_path
search list.
Our examples will use the second form. They will mirror closely the examples in the C++ API section. The examples are deployed in the share/dbexamples directory.
Example 5-1. Creating an empty database in Tcl (makedb.tcl)
#!/bin/sh# -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs]
package require SpecTclDB
if {[llength $argv] != 1} {
puts stderr "Usage: makedb.tcl database-file" exit -1 } DBTcl create [lindex $argv 0]
![]()
argv
list contains
the command parameters that follow the command.
Note that the command itself is not included.
The next example shows how to make a save set in an existing database file. We'll learn how to form a connection to a database and what that means. We'll then use that connection to create a new saveset.
Example 5-2. Creating savesets in a database (makesaveset.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: makesaveset.tcl database-file" exit -1 } set status [catch {set db [DBTcl connect [lindex $argv 0]]
set saveset [$db createSaveset "a saveset"]
$saveset destroy
$db destroy } msg] if {$status} { puts "Error: $msg"
exit -1 }
status
variable.
The optional second argument to catch is the name of a variable. If the command is successful, this will hold the result of the script. If not, it will hold the error message associated with the failure.
db
variable are analogous to
object methods.
This command ensemble is referred to as a data base instance command.
saveset
varible is called a saveset instance command.
Example 5-3. Listing savesets in a database (lssaveset.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: makesaveset.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] puts "Savesets in [lindex $argv 0]" foreach name [$db listSavesets] {puts $name } $db destroy } msg] if {$status} { puts "Error: $msg" }
Example 5-4. Defining parameters (pardef.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: pardef.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] set saveset [$db getSaveset "a saveset"]$saveset createParameter p1 100
$saveset createParameter p2 101 -10.0 10.0 100 "cm" puts "Parameters defined:" foreach param [$saveset listParameters] {
puts [dict get $param name] } $saveset destroy
$db destroy } msg] if {$status} { puts stderr "error: $msg" }
This example program creates two parameters named p1 and p2. Parameter p2 has full metadata. After creating the parameters the names of all parameters in the saveset are listed to stdout.
The command ensemble that
getSaveset produces, is called a
save set instance command and
is captured in the saveset
variable.
CEvent
)
object at which the parameter should be stored and retrieved.
Tree parameters have additional metadata.
The first command creates a raw parameter named p1. The second command creates a tree parametr with metadata. The metadata provides hints to both the user and SpecTcl GUI scripts about how to define axes of spectra that depend on this parameter. In this case a range of [-10.0..10.0) with 100 bins is recommended. In addition, the units of measure of the parameter are documented as centimeters (cm).
Contains an integer that is the primary key of the spectrum in the spectrum definition table. This is useful in programs that may do ad-hoc queries of the database for advanced applications.
Text string that is the name of the parameter.
THe number of the parameter. This differs from the id key. It's a value that the program supplies, rather than a value assigned by the database engine.
This key is only present for tree parameters. It's the recommended low limit of spectrum axes defined on this parameter.
This key is only present for tree parameters. It is the recommended high limit for axes defined on this parameter.
This key is only present for tree parameters. It is the recommended number of bins on axes defined on this parameter.
This key is only present for tree parameters. It is the units of measure defined for the parameter. Note that an empty string is perectly allowed an usually means the parameter is unit-less (e.g. raw ADC values).
Example 5-5. Defining Spectra (specdef.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: specdef.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] set saveset [$db getSaveset "a saveset"] $saveset createSpectrum s1 1 p1 [list [list 0 1023 1024]]$saveset createSpectrum s2 2 \
[list p1 p2] [list [list 0 1023 1024] [list -10.0 10.0 100]] puts "Spectra in saveset:" foreac spectrum [$saveset listSpectra] {
puts [dict get $spectrum name] } } msg] $saveset destroy $db destroy if {$status} { puts stderr "error: $msg" }
This example creates a 1d and a 2d spectrum named s1 and s2 respectively.
In the sample command, the spectrum name is s1. The spectrum type code, 1 means that the spectrum is a 1-d spectrum. p1 is a single element Tcl list that says the spectrum increments the p1 value for each event in which it is defined. Note that had the spectrum type been s (summary spectrum), or g1 (gamma 1-d) this parameter list would, in general contain additional parameter names. After the parameter is a list of axis definitions. Each axis definition, in turn is a three element list containing the axis low limit, high limit and number of bins in that order. Thus p1 will have an axis that runs from 0 to 1023 and has 1024 channels.
By default, SpecTcl spectra contain longword (32 bit) channel values. The createSpectrum subcommand also uses this as the default channel datatype. You can explicitly provide a data type as an additional command parameter. This additional parameter can have one of the following values:
Channels will be 8 bit values.
Channels will be 16 bit values.
Channels will be 32 bit values
The primary key of the spectrum in the top level spectrum definition table. This is really not useful to Tcl scripts that only use the API. It can be useful to scripts that also do ad-hoc queries of the database (e.g. via the sqlite3 package).
Name of the spectrum.
The spectrum type code.
The list of parameters the spectrum depends on.
List of axis definitions for each of the free defined axes of the spectrum. Note that each axis definition is a three element list containing in order, the axis low limit, high limit and number of bins.
The data type code as described above.
As with the C++ API, there are a family of subcommands that create gates of different types. The sample script below creates several types of gates.
Example 5-6. Defining gates (gatedef.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: gatedef.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] set saveset [$db getSaveset "a saveset"] $saveset create1dGate slice s p1 100 200$saveset create2dGate contour c [list p1 p2] \
[list {100 10} {200 100} {200 200} {100 200} ] $saveset createCompoundGate and * [list slice contour]
$saveset createMaskGate mask em p1 0x55555555
puts "Gates in saveset:" foreach gate [$saveset listGates] {
puts [dict get $gate name] } $saveset destroy $db destroy } msg] if {$status} { puts stderr "error: $msg" }
Note that the gate limits for this and all gates with limits are in raw parameter coordinates. There is often a temptation to believe that since gates are clicked on on spectra they are accepted in spectrum coordinates. This is not the case.
In this example a new gate and is created that is an and gate (type *) that depends on the gates slice and contour. This gate will only be true of both gates are true in an event.
Here's list of the gates an when they are present.
Gives the gate classification. All gates will be one of point, compound, or mask gates. In the keys below, after the key term parenthesized text will describe which keys are present in which clasifications. Note that (all) as in above means that all classification types have this key.
The primary key in the top level table used to define gates. This is normally not useful to programs that use only this Tcl API. It can be useful if a script also uses e.g. sqlite3 to perform arbitrary queries of the database.
The name of the gate.
The gate type code string.
The parameters that are checked by the gate. Note that mask gates only have one parameter.
The names of the gates this gate depends on
A list of two element sub lists. Each element is a point in the gate. For 1d gates, the Y coordinate is meaningless and there will only be two points. For 2-d gates, the X and Y coordinate are both meaningful and there can be be an arbitrary number of points.
The bitmask for a mask gate.
Example 5-7. Applying gates to spectra (applydef.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: applydef.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] set saveset [$db getSaveset "a saveset"] $saveset applyGate slice s2foreach app [$saveset listApplications] {
set gate [dict get $app gate] set spec [dict get $app spectrum] puts "$gate is applied to $spec" } $saveset destroy $db destroy } msg] if {$status} { puts stderr "error: $msg" }
Gates are objects that are totally passive unless applied to a spectrum. When applied to a spectrum, a gate conditionalizes the normal incrementation of that spectrum. If a gate is applied to a spectrum, the spectrum will only be incremented if the gate is true.
Contains the primary key of the application in the gate applications table. This is only useful for ad-hoc queries of the database performed by by e.g. the sqlite3 package.
The name of the gate
The spectrum to which that gate is being applied in this entry.
Example 5-8. Saving and recovering tree variables (vardef.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: vardef.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] set saveset [$db getSaveset "a saveset"] $saveset createVariable slope 1.23 KeV/lsb$saveset createVariable offset 10 KeV $saveset createVariable gainmatch 1.23
puts "Tree variables: " foreach var [$saveset listVariables] {
set name [dict get $var name] set val [dict get $var value] set units [dict get $var units] puts "$name : $val$units" } $saveset destroy $db destroy } msg] if {$status} { puts stderr "error: $msg" }
This and the next line of code create a pair of variables that might be used to do an energy calibration of a parameter. The units of measure clearly show what the units of the calibrated parameter will be; KeV.
Primary key of the variable in the tree variable table. This is useless for Tcl scripts that only use the published API. It can be useful if a script does ad-hoc database queries (e.g. using the sqlite3 package).
Name of the treevariable.
Value of the tree variable (double).
Units of measure text string. If no units were supplied, this will be an empty string.
Example 5-9. Storing spectrum contents (specstore.tcl)
#!/bin/sh # -*- tcl -*- # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} lappend auto_path [file join $::env(SPECTCLHOME) TclLibs] package require SpecTclDB if {[llength $argv] != 1} { puts stderr "Usage: specstore.tcl database-file" exit -1 } set status [catch { set db [DBTcl connect [lindex $argv 0]] set saveset [$db getSaveset "a saveset"] $saveset storeChannels s1 \[list {100 123} {101 2000} {102 400} {103 60}] set channels [$saveset getChannels s1]
puts "Channels in s1: " foreach chan $channels { set x [lindex $chan 0] set v [lindex $chan 2]
puts "Channel $x: $v" } $saveset destroy $db destroy } msg] if {$status} { puts stderr "error: $msg" }
The Tcl interface supports some queries of the event data stored in a save set but does not support storing events or scaler readouts. See the reference section for more information about this.