Adding a new Query

Queries in VisIt provide a mechanism for you to return information from a plot or its original database.

Making your query

You will need to decide on a name for your query and create avtNAMEQuery.{C,h} files in the src/avt/Queries/Queries directory. Be sure to use something appropriately descriptive for NAME.

You can start with a skeleton like this for your header file. We'll cover the different methods. Methods:

#ifndef AVT_<NAME>_QUERY_H
#define AVT_<NAME>_QUERY_H
#include <query_exports.h>
#include <avtDatasetQuery.h>

class vtkDataArray;
class vtkDataSet;

// ****************************************************************************
//  Class: avt<NAME>Query
//
//  Purpose:
//    A query that <FILL THIS IN>.
//
//  Programmer: <FILL THIS IN>
//  Creation:   <FILL THIS IN>
//
//  Modifications:
//
// ****************************************************************************

class QUERY_API avt<NAME>Query : virtual public avtDatasetQuery
{
public:
                            avt<NAME>Query();
    virtual                ~avt<NAME>Query();

    virtual const char     *GetType(void)   
                                { return "avt<NAME>Query"; };
    virtual const char     *GetDescription(void)
                                { return "Calculating <NAME>."; };

    virtual void            SetInputParams(const MapNode &);
    static  void            GetDefaultInputParams(MapNode &);

protected:
    virtual void            PreExecute(void);
    virtual void            Execute(vtkDataSet *, const int);
    virtual void            PostExecute(void);
    virtual void            VerifyInput(void);   

private:
    // Add private data members
};

#endif

PreExecute

This method is optional and lets you perform any one-time setup prior to the Execute method. This method is called once.

Execute

This method is optional but highly recommended as it provides VTK-level access to the datasets that you will examine to determine your query's output. Since VTK datasets stream through this method, the method will be called once for each VTK dataset. If you run in parallel, some portion of the VTK datasets that correspond to domains will be assigned to each processor. Any query that depends on the values of all domains will need to capture some data about the domains that it has during Execute() and then assemble the full picture during PostExecute().

PostExecute

This method is optional but highly recommended since it lets you set the query's output text and XML output. This method is called once after the Execute method has been called on various VTK datasets. This method is often used to perform collective communication to aggregate query results to the rank 0 processor.

VerifyInput

SetInputParams

This is an optional method that you can implement for your query if you want to be able to accept named arguments from the CLI. If you implement this, it also makes it easy to call your query from C++.

void 
avtGridInformationQuery::SetInputParams(const MapNode &params)
{
    // Check to see if the parameters contain "get_extents".
    if (params.HasEntry("get_extents"))
    {
        // Set an internal bool that influences the query's behavior using the the
        // "get_extents" value from the MapNode. MapNodes provide the ability to
        // pass various types of data to the query easily.

        getExtents = params.GetEntry("get_extents")->ToBool();
    }
}

When your query implements SetInputParams, you can pass named arguments to it from the CLI:

Query("Grid Information", get_extents = True)

You can also call the query easily from a C++ client or embedded viewer:

MapNode queryParams;
queryParams["query_name"] = std::string("Grid Information");
queryParams["get_extents"] = true;
viewer->Methods()->Query(queryParams);

GetDefaultInputParams

This is an optional static method that you can include in your query if you want it to accept default arguments from the GUI or CLI that can help influence the query's behavior. This method gets called directly from the avtQueryFactory to help set up the default arguments for your new query. Fill in any values in the MapNode that you want your query to use when it gets initialized.

void
avtGridInformationQuery::GetDefaultInputParams(MapNode &params)
{
    params["get_extents"] = false;
}

Adding to the factory

The avtQueryFactory class is a factory class that instantiates the various query classes based on the query's name. The class exists in src/avt/Queries/Misc. You'll need to make some changes to the class in order to install your new query.

First, Instantiate your new query in avtQueryFactory::CreateQuery

    // Add a block like this to the if-else statement.
    else if (CaseInsenstiveEqual(qname,"Grid Information"))
    {
        query = new avtGridInformationQuery();
    }

Queries can provide default arguments via a MapNode object that can help VisIt fill in the GUI and inform the default arguments for your query in the CLI. You can think of these default arguments as helping to establish any user-settable arguments that will help your query change its behavior or outputs. In order to provide default arguments, your query must implement a static function that provides the arguments. You must then call that function from avtQueryFactory::GetDefaultInputParams. Be sure to use the same query name as before.

    else if (CaseInsenstiveEqual(qname,"Grid Information"))
    {
        avtGridInformationNode::GetDefaultInputParams(params);
        retval = params.ToXML();
    }

Adding to the viewer

Before your query can be used, it must also be added to the query list in the ViewerQueryManager in the viewer.

Add a line like the following to the ViewerQueryManager::InitializeQueryList() method. This bit of code registers the name of the query with the viewer so the query will be made available in the GUI and CLI.

// See the sources for more about these arguments:
//
// dq == Data Query
// mr = Mesh related
// basic = no extra query UI will be presented in the GUI
// 1 = number of vars
// 0 = ?
// qo = query only

queryTypes->AddQuery("Grid Information", dq, mr, basic, 1, 0, qo);