View on GitHub

Chapter 10
Sandbox

10.1 Introduction

As explained in Section 3.5, Components can run in either the Sandbox or in a Domain. The Sandbox is an environment to run Components and Devices without artifacts like a Domain, Device Manager, name service, or event service.

REDHAWK provides two sandboxes, a Python-based one or an IDE-based one. The Python-based Sandbox can run from any Python session on any system with a REDHAWK install. The IDE-based Sandbox can host an instance of a Python-based Sandbox, with both interlinked, allowing artifacts from the Python environment to interact with those on the graphical UI.

10.2 Python Sandbox

The Python-based Sandbox is a Python package that is imported as any other Python package. Included in the Python package are tools that provide a means for passing BulkIO data to and from Components or Devices. Plotting is also supported from the Python package. This section discusses how to instantiate and test a Component using the provided Sandbox tools.

The Sandbox is Python-centric, so its use requires some basic Python knowledge.

10.2.1 Setup

In order to run the Sandbox, REDHAWK must be installed and the OSSIEHOME and SDRROOT environment variables must be set correctly (Appendix D.1.2).

To use the Sandbox none of the following programs need to be running: omniNames, omniEvents, DomainManager, DeviceManager, nodeBooter

The Python-based Sandbox includes basic analytical plotting tools based on the matplotlib Python plotting library. To use these plots, the following Python packages must be installed:

10.2.2 Starting the Sandbox

The Python-based Sandbox, like any other Python module, may be used in another Python program or run directly within the Python interpreter. The following examples assume that the Sandbox is being used within the Python interpreter.

To begin, start a Python interpreter session and import the Sandbox:

As with any other Python module, the built-in functions help() and dir() are useful when searching for available commands.

To exit the Sandbox, press Ctrl+D at the Python prompt. On exit, the Sandbox terminates and cleans up all of the Components and helpers it creates.

10.2.3 Running the Sandbox

Within the Sandbox, Components and helpers are launched in an idle state. In order to begin processing (e.g., serviceFunction() in C++ Components), each object must be started.

After the desired Components and helpers are created, the start() method starts all registered objects:

It is not necessary to stop the Sandbox prior to exiting, as this is handled as part of normal exit cleanup. However, if you wish to stop processing, the stop() method stops all registered objects:

In non-interactive scripts, the Python interpeter exits after the last statement. This may be undesirable, such as in the case where a set of Components should run for an arbitrary amount of time, with their output monitored via plots. The built-in Python method raw_input() can be used to prevent the interpreter from exiting:

When using plots, calling raw_input() instead of time.sleep() allows the UI thread to continue updating.

10.2.4 Working with Components, Devices, and Services

The Sandbox contains the following commands for working with Components, Devices, and Services:

The show() command displays running Components, connections between Components, and the SDRROOT:

The catalog() command displays which Components, Devices, and Services are available in SDRROOT. To determine what types are displayed, use the objType argument (by default objType="components") as shown below:

The api() method displays the Ports and properties for a running Component:

The launch() command launches Components, Devices, and Services. The first argument identifies the object to launch. It may be either a path to an SPD file or, for objects installed to the current SDRROOT, the name of the object as given in the SPD. The path can be absolute or relative and does not need to reside in SDRROOT.

The following example demonstrates how to launch a Device from the current working directory using the path:

The following example demonstrates how to launch a Device named SigGen from the current working directory using the name:

The execparams or property kind properties for a Component may be overridden by command line at launch time by passing a Python dictionary of parameter names and values to the keyword argument execparams:

In the case of Components and Devices, after the process is launched and the Component is initialized, the Component’s configure and property kind Properties are set to their default values as listed in the PRF file. The default values for this initial calls to configure() and initializeProperties() may be overridden by passing a Python dictionary of Property names and values to the keyword argument configure:

By default, the Sandbox selects the first Component implementation whose entry point exists on the file system. A particular implementation may be specified by passing the implementation id to the impl argument:

The Sandbox includes limited support for attaching a debugger to a Component process. The debugger console opens in a new XTerm window to allow continued interaction on the Sandbox console.

To launch a Component and attach gdb to the process, enter the following command:

The Component and gdb are run in separate processes. Exiting gdb closes the window, but the Component continues to function.

10.2.4.1 Properties

In addition to the standard REDHAWK query() and configure() functions, the Sandbox presents a simplified interface to Properties for Components and Devices. Configure Properties can be accessed as attributes on the Component object:

Property names are taken from the Component PRF file, with any characters that are invalid for Python identifiers replaced by an underscore.

The current value of properties with a mode of “readonly” or “readwrite” may be inspected. Properties with a mode of “readwrite” or “writeonly” can be assigned a new value.

To view the configure Properties that are available for a given Component, along with their types and current and default values, use the api() function.

Simple Properties with numeric types can be assigned from any Python numeric type:

The value is range checked and coerced into the desired type before being configured on the Component:

Floating point values are truncated, not rounded, during conversion to integer types:

A simple property with a complex value type can be assigned from a Python complex or two-item sequence. The numeric conversion of the real and imaginary components is identical to that of single numeric values.

Complex Properties support assignment from single numeric values; the imaginary component is assumed to be 0.

Properties that have enumerated values in the Component’s PRF support assignment using the enumerated name as a Python string:

Struct Properties can be set with a Python dictionary:

The dictionary keys are the IDs of the simple Properties that make up the struct. Each value is converted to the appropriate type following the same rules as simple Properties. Any struct members that are not in the dictionary retain their current values.

Individual struct members may be set directly, using the simple property name:

Properties have a mode (i.e.: readwrite, readonly, writeonly), and, for compatibility reasons, is a member of the Python Struct property container and cannot change. If the Struct Property has a member called “mode”, requesting the member “mode” from the Property will return its access mode rather than the content of the Property member. Access the value of any element of a Property with a reserved word as its name as follows,

Setting a struct member as an attribute uses the simple property’s name, while setting the member via a dictionary uses the simple property’s id.

Both simple and struct sequence Properties may be manipulated as lists. Sequence Properties support the common Python list operations, such as slicing and in-place modifiers:

The items of simple sequences follow the same conversion rules as the corresponding simple Property:

Each item in a struct sequence works identically to a single struct Property:

The Sandbox generates a low-level CORBA configure() call each time a Property value is set. However, Sandbox Components also support setting multiple Property values at once using a Python dictionary:

The keys may be either the Property names or IDs. The values are converted in the same manner as setting the individual Property directly.

10.2.5 Devices

Devices in the Sandbox support all of the features of Components, plus additional features specific to Devices. A Sandbox Device instance always supports the base CF::Device allocation and deallocation interfaces. If the Device supports the CF::LoadableDevice, CF::ExecutableDevice or CF::AggregateDevice interfaces, the methods for those interfaces are also available.

10.2.5.1 Capacity Allocation

The Sandbox provides a simplified interface for capacity allocation and deallocation. The allocateCapacity() and deallocateCapacity() methods can take a Python dictionary of allocation Property names and values. The values are automatically converted to the correct data type in the same manner as configure Properties.

The following code demonstrates allocation and deallocation of multiple Properties, including a struct Property:

If an allocation is successful, allocateCapacity() returns True; if the Device does not have sufficient capacity, it returns False.

10.2.5.2 Allocation Properties

The api() method for Devices shows the allocation Properties in addition to the Ports and configure Properties. The names, types and actions of the allocation Properties are given:

Only Properties with an action of “external” may be used for the allocateCapacity() and deallocateCapacity() methods.

10.2.6 Example Sandbox Interaction

The code below provides an example of Component interaction in the Sandbox:

10.2.6.1 Connecting Components

Connecting Components is done by invoking a connect() function on the uses-side (output-side) Component with the provides-side (input-side) Component as the argument of the call.

Note that if the connections are ambiguous (multiple uses Ports or multiple provides Ports have matching types), an error occurs. To resolve the ambiguity, usesPortName and/or providesPortName must be specified as arguments to the function. For example, the following call specifies providesPortName as an argument.

Note that if the connections are ambiguous (more than one Port on either the uses or provides side have matching types), an error occurs. To resolve the ambiguity, usesPortName and/or providesPortName needs to be specified as arguments to the function.

10.2.6.2 Setting Component Log Levels

The log level of the Component may be set using the execparams argument in the Component constructor.

10.2.7 Built-in Sources and Sinks

REDHAWK includes a variety of helpers that allow a developer to inject data into or extract data from Components deployed through the Sandbox. The following section describes each of these helpers and how they are used.

10.2.7.1 Data Sources

The DataSource module provides a mechanism for producing BulkIO data to be sent to a provides (input) Port. Once instantiated, a Python vector of data can be pushed to the DataSource.

An example instantiation and use of the Data Source module can be seen below:

When the DataSource sends data, it attempts to match the data type to the type of the associated provides (input) Port. Alternatively, the data type may be set explicitly in the DataSource constructor. Note that the default type for the DataSource is short, which implies that values over 32768 may induce an exception.

The default setting for number of bytes per pushPacket() is 512000 bytes. Data is broken up into chunks of this size before being sent via the Port’s pushPacket() method. To change this default size, set the bytesPerPush argument in the DataSource constructor.

A specific module is provided for reading data from a file. This module, FileSource, is used and instantiated much like the DataSource module. The most significant difference between the two modules is the presence of a file name in the FileSource constructor.

SRI keywords may be generated and sent with data from the DataSource module.

An example generate/send can be seen below:

The SRIKeyword() constructor takes in the following arguments:

Messages can be sent to Components using the MessageSource module. Messages sent to the sendMessage() method can be one of four types: struct, dictionary, CORBA Any, and data types that can be mapped to a CORBA Any.

The default Message id is sb_struct:

10.2.7.2 Data Sinks

The Sandbox provides a DataSink module, which simply reads data from a uses (output) Port. Below is an example instantiation and use of the DataSink module. In this example, data sent from myComponent’s uses (output) Port is written to the received_data variable.

SRI associated with the packet can be viewed using the sri() method:

To block until a certain amount of data is received, specify the data length as an argument to the getData() method:

The eos() method indicates whether or not an EOS was received:

The eos_block argument may be used to configure the getData() method to block until an EOS is received:

Similar to the DataSource’s FileSource counterpart, the DataSink has an associated FileSink module for writing data to a file:

Messages may be displayed using the MessageSink module. Data sent to a running MessageSink is printed in the Python interpreter.

Below is an example of MessageSink usage:

10.2.7.3 Plotting Data Example

Note that for plotting data, the REDHAWK IDE must be installed and the path to the eclipse directory of the installed IDE must be specified to the Sandbox.

This can be done through the IDELocation() function:

This can also be done by setting the RH_IDE environment variable prior to starting the Python session.

10.2.7.4 Continuous Data Flow Example

10.2.7.5 File Data Plotting Example

10.2.7.6 Passing a Struct to sendMessage Example

10.2.8 Plotting Data

The Sandbox includes tools for plotting BulkIO data from Components and Devices. The built-in matplotlib plots support visualizing BulkIO data in the time and frequency domains, as well as constellations. The plots are fully integrated into the Sandbox, support all numeric BulkIO data types, and may be used as the provides side for Component connections.

The following example plots the data from a Component as a line plot:

Before displaying data, plots must be started either by calling their start() method or by calling sb.start(). If the Sandbox is already started when the plot is created, then the plot’s initial state is started.

10.2.8.1 Frame Size

By default, all the plots display 1024 input samples at a time. To override this default setting, set the frame size by using the frameSize argument:

Larger frame sizes allow the plot to keep up with a higher rate of input data.

10.2.8.2 FFT Size

Plots that display the PSD of input data use a default FFT size of 1024 points. To increase the frequency resolution, set the nfft argument to a larger FFT size:

The frame size defaults to the FFT size, but can be overridden with frameSize. It may be smaller than the FFT size; however, it cannot exceed the FFT size. If the frame size is smaller than the FFT size, the data is zero-padded.

10.2.8.3 Line Plots

Line plots display signal or PSD data as a series of colored line segments, similar to an oscilloscope display. Each input signal is represented by a different line color. A new trace is created for each connect() call, and traces may be added and removed dynamically.

All input signals must have the same sample rate or the sources may get out of sync.

The X range is based on the frame size and input SRI. By default, the Y range is determined automatically per-frame based on the input data. A fixed minimum and maximum may be set independently with the ymin and ymax attributes:

Automatic scaling can be re-enabled by setting ymin or ymax to None.

The LinePlot plot displays one or more input signals. Time and value are displayed on the X and Y axes, respectively.

The LinePSD plot displays the PSD of one or more input signals. The frequency is represented by the X axis, while the magnitude is represented by the Y axis using a logarithmic scale.

10.2.8.4 Raster Plots

Raster plots display signal or PSD data as a two-dimensional image. Each horizontal line represents one frame of data. This plot type is most useful for visualizing an input signal in the frequency domain over time.

All raster plots allow configuration of the image size at creation time. The default image size is 1024x1024; height and width can be overridden with the imageHeight and imageWidth arguments:

The plot X and Y ranges are fixed based on the FFT or frame size (X) and image height (Y). The Z range (magnitude) can be set at creation time or changed dynamically with the zmin and zmax attributes:

The RasterPSD plot displays the PSD of an input signal as a falling raster. Time and frequency are displayed on the Y and X axes, respectively. The magnitude of a given frequency bin is represented by a logarithmic colormap. The default Z (magnitude) range is [1e-18, 1].

The RasterPlot plot displays a falling raster of an input signal. Inter-frame time is displayed on the Y axis, while intra-frame time is displayed on the X axis. The sample value of a given point is represented by a linear colormap. The default Z (magnitude) range is [-1, 1].

10.2.9 X/Y Plot

The XYPlot plot displays a series of complex samples as points on a two-dimensional plane. The real and imaginary components of a given sample are mapped to the point’s X and Y coordinates. This plot type is designed for viewing signal constellations, though it may be useful for other purposes.

By default, the plot is centered at the origin, and both the X and Y ranges are [-1, 1]. The minimum and maximum X and Y values may be set at creation time or changed dynamically with any combination of the xmin, xmax, ymin and ymax attributes:

10.2.10 Miscellaneous

10.2.10.1 Saving and Loading Waveforms

The Components making up a Waveform can be loaded into the workspace by passing the path and name of the Waveform’s SAD XML file to the loadSADFile() method. Note that usesdevice relationships are ignored when loading a SAD file onto the Sandbox.

The instantiated Components and their associated connections can also be saved as a Waveform. To perform this operation, pass the desired Waveform name to the generateSADXML() method.

This method returns an XML string representing the contents of the SAD file; this string may then be written to a file:

10.2.10.2 Debug Statements and Standard Out

Standard out and standard error can be redirected to a file:

Debug statements can be set explicitly.

To set the debug output status, pass True or False to the setDEBUG() method:

To get the current state of the debug output, use the getDEBUG() method:

10.2.10.3 Processing Components from the Command Line

To process individual Components from the command line, use the proc() function. The following command is an example of the proc() function call with sample arguments:

The arguments for the proc() function are described in Table 10.1.




Name

Description



<first argument>

Specifies the name of the Component to run (required).



<second argument>

Specifies the name of the input file (required).



sink

Specifies the name of the output file (optional). If this argument is omitted, exit the proc() function with Ctrl+C.



sourceFmt

Specifies the format for the input file (optional).

- 8/16/32/64 bit resolution

- u/t: unsigned/signed

- c: complex (real if omitted)

- r: big endian (little endian if omitted)



sinkFmt

Specifies the format for the output file (optional).



sampleRate

Specifies the sampling rate for the input file (optional).



execparams

Specifies the dictionary describing properties (of kind execparam or property) to be passed as command-line arguments (optional).



configure

Specifies the dictionary describing properties (of kind configure or property) to be over-ridden (optional).



providesPortName

Specifies the Component input Port name (optional).



usesPortName

Specifies the Component output Port name (optional).



timeout

Specifies how long the proc() function runs before exiting (optional).


Table 10.1: proc() Function Arguments

10.3 IDE Sandbox

The IDE-based Sandbox provides a graphical environment for launching, inspecting, and debugging Components, Devices, Services, and Waveforms. The IDE-based Sandbox can host an instance of a Python-based Sandbox, with both interlinked, allowing artifacts from the Python environment to interact with those on the graphical UI. For more information about the Python Sandbox, refer to Section 10.2.

10.3.1 Launching Components in the IDE Sandbox

The following procedures explain how to launch a Component in the IDE Sandbox.

10.3.1.1 Default Property Values

  1. To launch an implementation of a Component with default property values, from the REDHAWK Explorer View, right-click the Component, select Launch in Sandbox, and select an implementation of the Component to start within the Sandbox’s Chalkboard.

    The Component is launched in the Sandbox. The Component will initially be gray in color until launching is complete. When the Component is finished loading, its background color is blue.

10.3.1.2 Customized Property Values

  1. To launch an implementation of a Component with customized property values, from the REDHAWK Explorer View, right-click the Component, select Launch in Sandbox, and select Advanced.

    If the Component has multiple implementations, the Select Implementation dialog of the Launch wizard is displayed. Select the implementation and click Next.


    PIC
    Figure 10.1: The Select Implementation Dialog


    The Assign Initial Properties dialog of the Launch wizard is displayed.


    PIC
    Figure 10.2: The Assign Initial Properties Dialog


  2. Enter the Properties information and click Next.

    The Launch Configuration Options dialog is displayed.


    PIC
    Figure 10.3: The Launch Configuration Options Dialog


  3. Specify the launch options and click Finish.

    The Component is launched in the IDE Sandbox. The Component will initially be gray in color until launching is complete. When the Component is finished loading, its background color is blue.

10.3.2 Launching Devices in the IDE Sandbox

The following procedures explain how to launch a Device in the IDE Sandbox.

10.3.2.1 Default Property Values

  1. To launch an implementation of a Device with default property values, from the REDHAWK Explorer View, right-click the Device, select Launch in Sandbox, and select an implementation of the Device to start within the Sandbox’s Chalkboard.

    The Device is launched in the Sandbox.

10.3.2.2 Customized Property Values

  1. To launch an implementation of a Device with customized property values, from the REDHAWK Explorer View, right-click the Device, select Launch in Sandbox, and select Advanced.

    If the Device has multiple implementations, the Select Implementation dialog of the Launch wizard is displayed. Select the implementation and click Next.

    The Assign Initial Properties dialog of the Launch wizard is displayed.

  2. Enter the Properties information and click Next.

    The Launch Configuration Options dialog is displayed.

  3. Specify the launch options and click Finish.

    The Device is launched in the IDE Sandbox.

10.3.3 Launching Services in the IDE Sandbox

The following procedures explain how to launch a Service in the IDE Sandbox.

10.3.3.1 Default Property Values

  1. To launch an implementation of a Service with default property values, from the REDHAWK Explorer View, right-click the Service, select Launch in Sandbox, and select an implementation of the Service to start within the Sandbox’s Chalkboard.

    The Service is launched in the Sandbox.

10.3.3.2 Customized Property Values

  1. To launch an implementation of a Service with customized property values, right-click the Service, select Launch in Sandbox, and select Advanced.

    If the Service has multiple implementations, the Select Implementation dialog of the Launch wizard is displayed. Select the implementation and click Next.

    The Assign Initial Properties dialog of the Launch wizard is displayed.

  2. Enter the Properties information and click Next.

    The Launch Configuration Options dialog is displayed.

  3. Specify the launch options and click Finish.

    The Service is launched in the IDE Sandbox.

10.3.4 Launching Waveforms in the IDE Sandbox

The following procedures explain how to launch a Waveform in the IDE Sandbox.

10.3.4.1 Default Property Values

  1. To launch a Waveform with default property values, right-click the Waveform, select Launch in Sandbox, and select Default.

    The Waveform is launched in the Sandbox.

10.3.4.2 Customized Property Values

  1. To launch a Waveform with customized property values, right-click the Waveform, select Launch in Sandbox, and select Advanced.

    The Assign Initial Properties dialog of the Launch Waveform wizard is displayed.


    PIC
    Figure 10.4: The Assign Initial Properties Dialog


  2. Enter the Properties information and click Next.

    The Launch Configuration Options dialog of the Launch Waveform wizard is displayed.


    PIC
    Figure 10.5: The Launch Configuration Options Dialog


  3. Specify the launch options and click Finish.

    The Waveform is launched in the IDE Sandbox.


Creative Commons License
REDHAWK Documentation is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.