CTclGrammerApp

Name

CTclGrammerApp -- Base Application class

Synopsis


#include <TclGrammerApp.h>
class CTclGrammerApp
{
  UInt_t getDisplaySize() const;
  UInt_t getParams() const; 
  UInt_t getListSize() const;
  CAnalyzer* getAnalyzer() const;
  CTCLHistogrammer* getHistogrammer() const;
  CTKRunControl* getRunControl() const;
  CXamineEventHandler* getXamineEvents() const;
  CRunControlPackage* getRunControlPackage() const;
  CParameterPackage* getParameterPackage() const;
  CSpectrumPackage* getSpectrumPackage() const;
  CDataSourcePackage* getDataSourcePackage() const;
  CGatePackage* getGatePackage() const;
  CTCLVariable getTclDisplaySize() const;
  CTCLVariable getTclParameterCount() const;
  CTCLVariable getTclEventListSize() const;
  CMultiTestSource* getTestDataSource();
  CDisplayInterface* getDisplayInterface();
  
protected:
  void setDisplaySize (const UInt_t am_nDisplaySize);
  void setParams (const UInt_t am_nParams);
  void setListSize (const UInt_t am_nListSize);
  void setAnalyzer (CAnalyzer* am_pAnalyzer);
  void setHistogrammer (CTCLHistogrammer* am_pHistogrammer);
  void setRunControl (CTKRunControl* am_pRunControl);
  void setXamineEvents (CXamineEventHandler* am_pXamineEvents);
  void setRunControlPackage (CRunControlPackage* am_pRunControlPackage);
  void setParameterPackage (CParameterPackage* am_pParameterPackage);
  void setSpectrumPackage (CSpectrumPackage* am_pSpectrumPackage);
  void setDataSourcePackage (CDataSourcePackage* am_pDataSourcePackage);
  void setGatePackage (CGatePackage* am_pGatePackage);
  void setRCFile (const CTCLVariable am_RCFile);
  void setTclDisplaySize (const CTCLVariable am_TclDisplaySize);
  void setTclParameterCount (const CTCLVariable am_TclParameterCount);
  void setTclEventListSize (const CTCLVariable am_TclEventListSize);
  void setDisplayInterface(CDisplayInterface* pInterface);

public:
  void RegisterEventProcessor(CEventProcessor& rEventProcessor,
                              const char* name = 0); 
  virtual void BindTCLVariables(CTCLInterpreter& rInterp); 
  virtual void SourceLimitScripts(CTCLInterpreter& rInterpreter);
  virtual void SetLimits(); 
  virtual void CreateHistogrammer(); 
  virtual void CreateDisplays(); 
  virtual void SelectDisplayer();
  virtual void SetUpDisplay(); 
  virtual void SetupTestDataSource(); 
  virtual void CreateAnalyzer(CEventSink* pSink);
  virtual void SelectDecoder(CAnalyzer& rAnalyzer); 
  virtual void CreateAnalysisPipeline(CAnalyzer& rAnalyzer) = 0;
  virtual void AddCommands(CTCLInterpreter& rInterp);
  void SetupRunControl();
  virtual void SourceFunctionalScripts(CTCLInterpreter& rInterp);
  virtual int operator()(); 

  virtual void run();
  CTCLInterpreter* getInterpreter();

  static CTclGrammerApp* getInstance();

protected:
  static void UpdateUInt(CTCLVariable& rVar, UInt_t& rValue);
  static void UpdateString(CTCLVariable& rVar, std::string& rString);
  static std::string SourceOptionalFile(CTCLInterpreter& rInterp,
    std::string filename);


 public:
  static CTclGrammerApp* m_pInstance; 
  static int             m_argc;  
  static char**          m_pArgV; 

};

                

DESCRIPTION

This class is the base class of the SpecTcl application class. The standard SpecTcl skeleton provides a derivation (MySpecTclApp) which has stubs for all of the pure virtual methods. Specialized derived classes can do quite a bit more.

In general, to make a complete SpecTcl, you must write a class derived from CTclGrammerApp, instantiate it and assign a pointer to the global variable CTclGrammerApp::m_pInstance.

While normally this sort of thing might be a singleton pattern, our need to derive and use the strategy pattern makes these gymnastics necessary. For more on the singleton pattern see: https://en.wikipedia.org/wiki/Singleton_pattern. For information on the strategy pattern, see: https://en.wikipedia.org/wiki/Strategy_pattern.

METHODS

The methods for this class come in several categories. Since this is an important base class, we'll be documenting methods that include accessors and mutators for member data as well as protected methods that may be of use in special situations.

The first category of methods we'll document are accessors. These are methods that allow read access to member data. They are all public as external objects may want to obtain the values of these variables as well as derived classes:

const UInt_t getDisplaySize();

SpecTcl places bulk spectrum data in a shared memory region using the sbind command. This allows displayers running on the same system as SpecTcl rapid access to these data improving display rendering times.

The size of the shared memory region is determined at startup (just after limit scripts are sourced). This method returns the number of megabytes allocated to this shared memory region.

Note that as for most computer applications Mega means 1024*1024.

const UInt_t getParams() ();

SpecTcl uses a CEvent object to represent unpacked parameters from an event. This object is self-resizing. It looks like an array but if an element is referenced out of range of the allowed indices, it is expanded as needed.

The CEvent object is instantiated by SpecTcl with an initial size. This method returns the initial number of elements in a CEvent. Note that since these objects are recycled from event to event, tuning the initial size has no amortized effect on performance as all of these objects eventually grow to the appropriate size (usually quite quickly).

const UInt_t getListSize();

Determines the number of CEvent objects that are collected for each pass through the histogrammer.

const CAnalyzer* getAnalyzer();

Returns a pointer to the analyzer object. This is deprecated in favor of the GetAnalyzer method in the SpecTcl API class.

const CTCLHistogrammer* getHistogrammer();

Returns a pointer to the histogrammer object. This is the special event sink pipeline element that performs gating and histogramming

Note that this is deprecated in favor of the GetHistogrammer method if the SpecTcl API class.

const CTKRunControl* getRunControl();

CRunControl objects are responsible for starting and stopping playback from data sources as well as providing a callback when data can be read from a source.

The drun control object used by default for CTclGrammerApp objects is a CTKRunControl object that uses file events to know when data are ready from a data source. This method returns a pointer to the run control object currently in use.

const CXamineEventHandler* getXamineEvents();

The Xamine displayer communicates with the its client via Unix IPC objects. Shared memory is used to provide bulk spectrum data and metadata to Xamine. Message based IPS are used to pass events from Xamine to SpecTcl.

An XamineEventHandler object is an object that is used to mediate message traffic from Xamine to SpecTcl. It handles both gate notifictions and notifications of button clicks for user button boxes.

This method returns thye current instance of the CXamienEventHandler. This may not be meaningful if a displayer other than Xamine is used.

const CRunControlPackage* getRunControlPackage();

SpecTcl's commands are grouped into sets of related functionality called command packages. Command package objects, derived from CTCCommandPackage, not only contain a set of commands but also provide services that can be accessed by the commands in the package.

This scheme also servers to insulate SpecTcl's command functionality from the language that invokes it... to some extent.

This method returns a pointer to the run control command package. This package provides services for the run control commands; start and stop.

const CParameterPackage* getParameterPackage();

See getRunControlPackage for background information about command packages. CParameterPackage is a package containing the commands that manipulate SpecTcl parameter definitions. This includes both the parameter and psuedo commands.

This method returns a pointer to the parameter package object.

const CSpectrumPackage* getSpectrumPackage();

The CSpectrumPackage object contains and provides services for commands that affect spectra. These include spectrum, clar, sbind, unbind, channel, swrite and sread. This method returns a pointer to this package object.

const CDataSourcePackage* getDataSourcePackage();

The CDataSourcePackage contains and provides services for commands that provide access to SpecTcl data sources. These include the attach and ringformat classes. Older versions of SpecTcl also provide access to the obsolete tape command.

This method returns a pointer to the data source package object.

const CGatePackage* getGatePackage();

CGatePackage contains and provides services for commands that have to do with gates. These commands include: gate, apply and ungate.

This method returns a pointer to the CGatePackage object used by SpecTcl.

const CTCLVariable getTclDisplaySize();

Returns a CTCLVariable that, in BindTCLVariables is bound to the Tcl variable DisplayMegabytes.

This can be set to be the default number of display shared memory megabytes. This must be done prior to the call to SourceLimitScripts. One way to accomplish this is to override SourceLimitScripts and replace it with something like:


void MySpecTclApp::SourceLimitScripts(CTCLInterpreter& interp)
{
    CTCLVariable displaySize = getTclDisplaySize();
    displaySize.Bind();
    displaySize.Set("16");
    
    TclGrammerApp::SourceLimitScripts(interp);
}
                            

The method above, sets the default value for the display size to 16MB before invoking the base class method to actually source the limit scripts.

const CTCLVariable getTclParameterCount();

Returns an object that represents the Tcl variable that sets the default value for the initial size of new CEvent objects. As discussed previously, there's not much to be gained from altering this default as eventually these objects equilibrate in size to the size needed to hold all of the parameters.

const CTCLVariable getTclEventListSize();

Returns an object that respresents the Tcl variable that holds the default number of events that are processed by the event processing pipeline before passing events to the event sink pipeline. This can be set prior to the base class executing SourceLimitScripts. Note that method may invoke a script that overrides the default and that method will also set that parameter. It is possible that playing with this will have a minor effect on SpecTcl performancde.

CMultiTestSource* getTestDataSource();

Returns the object that provides test data for SpecTcl prior to first being attached to a real data source. It's possible, once you have that object to add or select other than the default test source (fixed length events with gaussian parameters).

One potential use for this would be to hook directly to some event simulator, although much simpler would be to teach SpecTcl to analyze the saved event files from such a simulator.

CDisplayInterface* getDisplayInterface();

Provides a pointer to the current display interface. This object provides methods to manage displayers that can be used by SpecTcl.

The second set of methods we will document are mutators. A mutator is a method that allows you to modify internal attributes of an object. These methods are all intended to be used by derived classes and therefore are all protected.

void setDisplaySize (const UInt_t am_nDisplaySize);

Sets the display memory size in megabytes. This must be called after SourceLimitScripts to override the value in those scripts or prior to set the default value. It should also be called prior to CreateDisplays which actually sets up the display shared memory.

void setParams (const UInt_t am_nParams);

Sets the number of parameters that will be used as the initial size for CEvent vectors. To override the user's settings, this should be called after SourceLimitScripts, otherwise it is used as a default value for that parameter if it is not set in the user's scripts.

As previously discussed, setting this has essentially no impact on SpecTcl's performance due to the autosizing and recycling of parameter vectors.

void setListSize (const UInt_t am_nListSize);

Sets the event list size. This is the number of events that is analyzed by the event processing pipeline before those events are passed to the event sink pipeline for histogramming and other processing.

This set of methods are virtual and therefore can be overridden. These methods are all exposed in the MySpecTclApp class in the SpecTcl Skeleton. In that class, the base class method is invoked. You can add code as needed to meet your needs.

void RegisterEventProcessor( CEventProcessor& rEventProcessor, const char* name = 0);

Not actually a virtual method, this method is used to add an event processor to the end of the event processing pipeline. rEventProcessor, is the processor to add and name, if supplied is a name associated with the event processor. If name is not supplied, one is assigned.

virtual void BindTCLVariables( CTCLInterpreter& rInterp);

This is called to bind SpecTcl's special Tcl variables to this object's CTCLVariable members. Doing this allows those objects to access the underlying Tcl variables. Variables bound and created include:

  • tcl_rcFilename The name of the early Tcl initialization file.

  • DisplayMegabytes Number of megabytes of display shared memory allocated.

  • ParameterCount Number of parameers allocated in the initial create of CEvent objects.

  • EventListSize Number events analyzed by the analysis pipeline before passing them on to the sink pipeline.

  • DisplayType type of displayer used.

virtual void SourceLimitScripts( CTCLInterpreter& rInterpreter);

Sources the limit setting scripts (SpecTclInit.tcl) into rInterpreter. All of the following locations are searched and for the reasons given:

  • The etc subdirectory of the SpecTcl installation is searched to provide system defaults that override the default values compiled in to SpecTcl.

  • The user's home directory is searched to provide account wide settings that may override the system wide settings.

  • The current working directory is searched to provide project specific settings.

virtual void SetLimits();

Updates the SpecTcl Tcl variables from the final tuning values after SourceLimitScripts has been executed.

virtual void CreateHistogrammer();

This method creates the event sink pipeline, assigning a pointer to it to gpEventSinkPipeline. It then immediately creates a CHistogrammer object saving it's pointer in gpEventSink and adding it to the end of the event sink pipeline.

In addition an observer is attached to the spectrum dictionary (part of the histogrammer). This observer, a SpectrumDictionaryFitObserver destroys fits on spectra that are being removed from the spectrum dictionary.

virtual void CreateDisplays();

SpecTcl supports more than one displayer. Currently it supports Xamine, a displayer built directly on Motif and the Xt/X11 toolkit and Spectra, a displayer build on Root. This method sets up a factory of display interfaces. It stocks it with creators for Xamine, Spectra and headless (batch) mode.

virtual void SelectDisplayer();

Selects and starts the displayer whose name is stored in the Tcl variable DisplayType. DisplayType must have been set prior to SourceLimitScripts.

The displayer process is started if appropriate.

virtual void SetUpDisplay();

Sets up communication between SpecTcl and the displayer. Specifically, when gates are created or destroyed, when spectra have gates applied to them or are ungated, the displayer may provide visual cues. This method sets up observers on the SpecTcl side that detect appropriate changes and communicate with the selected displayer so that this information is updated by the displayer..

virtual void SetupTestDataSource();

SpecTcl has a test data source. If analysis is started, prior to attaching to a data source, the test source will supply data. The test data source is, by default, a CMlutiTestSource which is can be a container for several types of data sources.

This method establishes that data source and selects its default data source. The default data source delivers fixed sized events that contain several parameters of gaussian distributed parameters.

The SpecTcl skeleton files can analyze data from the default test source without modification. This is one way to use and become familiar with SpecTcl.

virtual void CreateAnalyzer( CEventSink* pSink);

Creates and attaches the analyzer to the system. The analyzer is the object that controls the flow of data from a data source through the analysis pipeline and to the event sink pipeline.

By default a CTclAnalyzer is instantiated and hooked in to SpecTcl. A pointer to the analyzer object is stored in gpAnalyzer as well as in the attribute m_pAnalyzer. Both should be updated to change the analyzer, if that's desired.

virtual void SelectDecoder( CAnalyzer& rAnalyzer);

Sets the initial buffer decoder. Note that in most cases, SpecTcl's attach command will select a new buffer decoder object to match the -format value, implied by or explicit in the command.

virtual void CreateAnalysisPipeline( CAnalyzer& rAnalyzer = 0);

This is a pure virtual method and therefore must be implemented by any subclass that can be instantiated. The code in this method should create and add elements to the event processing pipeline.

RegisterEventProcessor is provided as a convenience method for adding event processors to the analyzer. Note that event processors are a property of the CTclAnalyzer class and its descendents.

virtual void AddCommands( CTCLInterpreter& rInterp);

Adds SpecTcl specific commands to the Tcl interpreter rInterp. The base class method creates and adds all of the command packages that hold most of SpecTcl's commands.

void SetupRunControl();

Not virtual and therefore cannot be overridden, this method creates a new CTkRunControl object, stores a pointer to it in gpRunControl which establishes it as the run control object that SpecTcl uses. The object's pointer is also stored in the attribute m_pRunControl.

virtual void SourceFunctionalScripts( CTCLInterpreter& rInterp);

Sources functional setup scripts into rInterp. The functional setup scripts are those named SpecTclRC.tcl. SpecTcl will first run any script by this name that exists in the user's home directory. Next it will run any script by that name that exists in the current working directory.

virtual int operator()();

Entry point. This method invokes all of the initialization methods in turn. It should return TCL_OK if successful and TCL_ERROR on any failure.

The remainder of the methods we'll document are utility functions. These are protected and therefore can only be called from methods in this class or a class derived from this class (e.g. MySpecTclApp).

static void UpdateUInt( CTCLVariable& rVar, UInt_t& rValue);

This utility method accepts a Tcl variable object (rVar) which is supposed to hold an unsigned integer and sets rValue to the value of that integer. If the variable does not exist in the Tcl interpreter, no error is thrown and the rValue is un-modified.

static void UpdateString( CTCLVariable& rVar, std::string& rString);

Similiar to UpdateUInt but the Tcl variable is an arbitrary string.

static std::string SourceOptionalFile( CTCLInterpreter& rInterp, std::string filename);

This method attempts to source the file filename into the interpreter rInterp. It is not an error for the file to not exist. That's the meaning of the "optional" part of this method's name.

The return value from this method is an empty string on success (including missing file) and an error message string if an error occured (such as the script failing).