Sending tool attributes to simulations

VisIt provides interactive tools that can be used to set operator attributes interactively. VisIt's CLI provides a callback function mechanism that lets you install custom Python callback functions on changes to state or execution of specific viewer RPC's. This example shows how to install a callback function for the Box operator since its attributes can be set by the Box tool. The callback function will then get the Box operator settings and send them to a simulation which can then use the Box tool settings to steer its execution.

Python Callback

The Python callback uses the RegisterCallback function to install a callback function that will be called whenever the BoxAttributes state object changes. The BoxAttributes state object is the state object for the Box operator. The BoxAttributes will be updated whenever the Box tool is used to interactively set the Box operator attributes.

import string

# Set the Box operator attributes to include the whole extents.
def InitializeBox():
    w = GetWindowInformation()
    b = BoxAttributes()
    b.minx = w.extents[0]
    b.maxx = w.extents[1]
    b.miny = w.extents[2]
    b.maxy = w.extents[3]
    b.minz = w.extents[4]
    b.maxz = w.extents[5]
    SetOperatorOptions(b)

# Use a class since it can contain state.
class onBoxAttributes(object):
    def __init__(self):
        self.s = ""
        self.win = GetGlobalAttributes().activeWindow

    def change(self, atts):
        # Make sure that we only send the command for when the box operator
        # attributes "really" change.
        if self.win == GetGlobalAttributes().activeWindow:
            s2 = str(atts)
            if self.s != s2:
                self.s = s2
                print "new box attributes: ", atts

                # Send a "box" command to the simulation with the extents of the
                # box as command arguments. For this to work, the simulation will
                # need to have a "box" command registered via the simulation metadata
                # and it will need to handle the box command in its command callback
                # function.
                host,sim = string.split(GetWindowInformation().activeSource, ":")
                args = "%lg %lg %lg %lg %lg %lg" % (atts.minx, atts.maxx, atts.miny, atts.maxy, atts.minz, atts.maxz)
                SendSimulationCommand(host, sim, "box", args)

def main():
    # Replace these with a sim2 file.
    db = "~/Development/data/noise.silo"
    var="hardyglobal"

    r = GetRenderingAttributes()
    r.notifyForEachRender = 1
    SetRenderingAttributes(r)

    OpenDatabase(db)
    AddPlot("Pseudocolor", var)
    AddOperator("Box")
    DrawPlots()
    InitializeBox()

    # Enable the box tool, "wiggle it"
    EnableTool(3,1)
    EnableTool(3,0)
    EnableTool(3,1)

    # Install a callback function on SetOperatorOptions
    b = onBoxAttributes()
    RegisterCallback("BoxAttributes", b.change)


main()

Libsim Control Callback

This is how you advertise commands to VisIt via the simulation metadata. This code gets inserted into your GetMetaData callback function.

visit_handle cmd = VISIT_INVALID_HANDLE;
if(VisIt_CommandMetaData_alloc(&cmd) == VISIT_OKAY)
{
    VisIt_CommandMetaData_setName(cmd, "box");
    VisIt_SimulationMetaData_addGenericCommand(md, cmd);
}

This is how you register the control command with libsim. The "sim" pointer in this example points to a struct containing the simulation's state.

    VisItSetCommandCallback(ControlCommandCallback, (void*)sim);

The actual handler looks something like this:

/* Callback function for control commands. */
void ControlCommandCallback(const char *cmd, const char *args, void *cbdata)
{
    simulation_data *sim = (simulation_data *)cbdata;

    if(strcmp(cmd, "halt") == 0)
        sim->runMode = SIM_STOPPED;
    else if(strcmp(cmd, "step") == 0)
        simulate_one_timestep(sim);
    else if(strcmp(cmd, "run") == 0)
        sim->runMode = SIM_RUNNING;
    /*
     * Handle the "box" command here
     */
    else if(strcmp(cmd, "box") == 0)
    {
        double extents[6];
        sscanf(args, "%lg %lg %lg %lg %lg %lg", &extents[0], &extents[1], &extents[2], &extents[3], &extents[4], &extents[5]);
        /* Do something with the new extents. */
        simulation_data_set_box(sim, extents);
    }
}