Asking and answering questions with Queries

Queries are a way to ask summarization questions about meshes. Queries results can be used with Triggers to adapt analysis and visualization actions. This section shows how to execute queries with Ascent and access query results. See Queries docs for deeper details on Queries.

Extracting mesh cycle and entropy of a time varying mesh

C++

#include <iostream>
#include <sstream>

#include "ascent.hpp"
#include "conduit_blueprint.hpp"

#include "ascent_tutorial_cpp_utils.hpp"

using namespace ascent;
using namespace conduit;

int main(int argc, char **argv)
{
    // Use Ascent to extract mesh cycle and entropy of a time varying mesh
    Ascent a;

    // open ascent
    a.open();

    // setup actions
    Node actions;
    Node &add_act = actions.append();
    add_act["action"] = "add_queries";

    // declare a queries to ask some questions
    Node &queries = add_act["queries"] ;

    // add a simple query expression (q1)
    queries["q1/params/expression"] = "cycle()";;
    queries["q1/params/name"] = "cycle";

    // add a more complex query expression (q2)
    queries["q2/params/expression"] = "entropy(histogram(field('gyre'), num_bins=128))";
    queries["q2/params/name"] = "entropy_of_gyre";

    // declare a scene to render the dataset
    Node &add_scenes = actions.append();
    add_scenes["action"] = "add_scenes";
    Node &scenes = add_scenes["scenes"];
    scenes["s1/plots/p1/type"] = "pseudocolor";
    scenes["s1/plots/p1/field"] = "gyre";
    // Set the output file name (ascent will add ".png")
    scenes["s1/image_name"] = "out_gyre";

    // print our full actions tree
    std::cout << actions.to_yaml() << std::endl;

    // gyre time varying params
    int nsteps = 10;
    float time_value = 0.0;
    float delta_time = 0.5;

    Node mesh;
    Node info;

    for( int step =0; step < nsteps; step++)
    {
        // call helper that generates a gyre time varying example mesh.
        // gyre ref :https://shaddenlab.berkeley.edu/uploads/LCS-tutorial/examples.html
        tutorial_gyre_example(time_value, mesh);

        // update the example cycle
        int cycle = 100 + step * 100;
        mesh["state/cycle"] = cycle;
        std::cout << "time: " << time_value << " cycle: " << cycle << std::endl;

        // publish mesh to ascent
        a.publish(mesh);

        // update image name
        std::ostringstream oss;
        oss << "out_gyre_" << std::setfill('0') << std::setw(4) << step;
        scenes["s1/image_name"] = oss.str();

        // execute the actions
        a.execute(actions);

        // retrieve the info node that contains the query results
        Node ts_info;
        a.info(ts_info);

        // add to our running info
        info["expressions"].update(ts_info["expressions"]);

        // update time
        time_value = time_value + delta_time;
    }

    // close ascent
    a.close();

    // view the results of the cycle query
    std::cout << info["expressions/cycle"].to_yaml() << std::endl;
    // Note that query results can be indexed by cycle

    // view the results of the cycle query
    std::cout << info["expressions/entropy_of_gyre"].to_yaml() << std::endl;

    // create an array with the entropy values from all 
    // cycles
    Node entropy;
    entropy.set(DataType::float64(nsteps));
    float64 *entropy_vals_ptr = entropy.value();

    // get the node that has the time history
    Node &gyre = info["expressions/entropy_of_gyre"];

    // reformat conduit data into  summary array
    for(int i=i; i < gyre.number_of_children(); i++ )
    {
        entropy_vals_ptr[i] = gyre[i]["value"].to_float64();
    }

    std::cout << "Entropy Result" << std::endl;
    std::cout << entropy.to_yaml() << std::endl;
}

Python


import conduit
import conduit.blueprint
import ascent
import numpy as np

from ascent_tutorial_py_utils import tutorial_gyre_example

# Use Ascent to extract mesh cycle and entropy of a time varying mesh
a = ascent.Ascent()
a.open()

# setup actions
actions = conduit.Node()
add_act = actions.append()
add_act["action"] = "add_queries"

# declare a queries to ask some questions
queries = add_act["queries"] 

# add a simple query expression (q1)
queries["q1/params/expression"] = "cycle()"
queries["q1/params/name"] = "cycle"

# add a more complex query expression (q2)
queries["q2/params/expression"] = "entropy(histogram(field('gyre'), num_bins=128))"
queries["q2/params/name"] = "entropy_of_gyre"

# declare a scene to render the dataset
add_scenes = actions.append()
add_scenes["action"] = "add_scenes"
scenes = add_scenes["scenes"] 
scenes["s1/plots/p1/type"] = "pseudocolor"
scenes["s1/plots/p1/field"] = "gyre"
# Set the output file name (ascent will add ".png")
scenes["s1/image_name"] = "out_gyre"

# view our full actions tree
print(actions.to_yaml())

# gyre time varying params
nsteps = 10
time = 0.0
delta_time = 0.5

info = conduit.Node()
for step in range(nsteps):
    # call helper that generates a gyre time varying example mesh.
    # gyre ref :https://shaddenlab.berkeley.edu/uploads/LCS-tutorial/examples.html
    mesh = tutorial_gyre_example(time)
    
    # update the example cycle
    cycle = 100 + step * 100
    mesh["state/cycle"] = cycle
    print("time: {} cycle: {}".format(time,cycle))
    
    # publish mesh to ascent
    a.publish(mesh)
    
    # update image name
    scenes["s1/image_name"] = "out_gyre_%04d" % step;
    
    # execute the actions
    a.execute(actions)

    # retrieve the info node that contains the query results
    ts_info = conduit.Node()
    a.info(ts_info)

    # add to our running info
    info["expressions"].update(ts_info["expressions"])

    # update time
    time = time + delta_time

# close ascent
a.close()

# view the results of the cycle query
print(info["expressions/cycle"].to_yaml())
# Note that query results can be indexed by cycle

# view the results of the cycle query
print(info["expressions/entropy_of_gyre"].to_yaml())

# create an array with the entropy values from all 
# cycles
entropy = np.zeros(nsteps)
# get the node that has the time history
gyre = info["expressions/entropy_of_gyre"]

# transfer conduit data to our summary numpy array
for i in range(gyre.number_of_children()):
    entropy[i] = gyre[i]["value"]

print("Entropy Result")
print(entropy)

Output


- 
  action: "add_queries"
  queries: 
    q1: 
      params: 
        expression: "cycle()"
        name: "cycle"
    q2: 
      params: 
        expression: "entropy(histogram(field('gyre'), num_bins=128))"
        name: "entropy_of_gyre"
- 
  action: "add_scenes"
  scenes: 
    s1: 
      plots: 
        p1: 
          type: "pseudocolor"
          field: "gyre"
      image_name: "out_gyre"

time: 0.0 cycle: 100
time: 0.5 cycle: 200
time: 1.0 cycle: 300
time: 1.5 cycle: 400
time: 2.0 cycle: 500
time: 2.5 cycle: 600
time: 3.0 cycle: 700
time: 3.5 cycle: 800
time: 4.0 cycle: 900
time: 4.5 cycle: 1000

100: 
  type: "int"
  value: 100
200: 
  type: "int"
  value: 200
300: 
  type: "int"
  value: 300
400: 
  type: "int"
  value: 400
500: 
  type: "int"
  value: 500
600: 
  type: "int"
  value: 600
700: 
  type: "int"
  value: 700
800: 
  type: "int"
  value: 800
900: 
  type: "int"
  value: 900
1000: 
  type: "int"
  value: 1000


100: 
  value: 3.81580590726479
  type: "double"
200: 
  value: 4.43027379899862
  type: "double"
300: 
  value: 4.42357515605932
  type: "double"
400: 
  value: 4.4133821818731
  type: "double"
500: 
  value: 4.40290017527564
  type: "double"
600: 
  value: 4.3643209637501
  type: "double"
700: 
  value: 4.40290017527564
  type: "double"
800: 
  value: 4.4133821818731
  type: "double"
900: 
  value: 4.42357515605932
  type: "double"
1000: 
  value: 4.43027379899862
  type: "double"

Entropy Result
[3.81580591 4.4302738  4.42357516 4.41338218 4.40290018 4.36432096
 4.40290018 4.41338218 4.42357516 4.4302738 ]