Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compact color table args #1457

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
- [email protected]

### Added
- Added a compressed color table format.
- Added action options relating to logging functionality including `open_log`, `flush_log`, and `close_log` to toggle logging as well as `set_log_threshold` and `set_echo_threshold` to control logging and standard output levels.
- Added a new unified logging infrastructure.
- Added support for unstructured topologies with mixed elements types (for example, hexs and tets).
Expand Down
11 changes: 11 additions & 0 deletions src/docs/sphinx/Actions/Examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,17 @@ Resulting image:

.. image:: examples/milk_chocolate100.png

An example of creating a custom color map using a compressed format.
-------------------------------------------

YAML actions:

.. literalinclude:: examples/milk_chocolate_compressed100.yaml

Resulting image:

.. image:: examples/milk_chocolate100.png

An example if using the composite vector filter to compose three scalar fields into a vector.
-----------------------------------------------------------------------------------------------

Expand Down
23 changes: 23 additions & 0 deletions src/docs/sphinx/Actions/Scenes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,29 @@ but when a color table is specified, then the color table needs to include
alpha values. Otherwise, the volume plot will look exactly the same as a
pseudocolor plot.

There are two formats that can be used to add a custom color table. The first is
a compact color table format:

.. code-block:: c++

conduit::Node control_points;
control_points["r"] = {.23, .48, .99};
control_points["g"] = {0.08, .23, 1.};
control_points["b"] = {0.08, .04, .96};
control_points["a"] = {1., 1., 1.};
control_points["position"] = {0., .5, 1.};

conduit::Node scenes;
scenes["s1/plots/p1/type"] = "volume";
scenes["s1/plots/p1/field"] = "braid";
scenes["s1/plots/p1/color_table/control_points"] = control_points;

conduit::Node actions;
conduit::Node &add_plots = actions.append();
add_plots["action"] = "add_scenes";
add_plots["scenes"] = scenes;

Alternatively, there is a second, expanded color table format that can be used.
Here is an example of adding a custom color table to the volume plot:

.. code-block:: c++
Expand Down
23 changes: 23 additions & 0 deletions src/docs/sphinx/Actions/examples/milk_chocolate_compressed100.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#An example of creating a custom color map.

-
action: "add_scenes"
scenes:
s1:
plots:
p1:
type: "pseudocolor"
field: "braid"
color_table:
control_points:
r: [0.23, 0.48, 0.99]
g: [0.08, 0.23, 1.0]
b: [0.08, 0.04, 0.9]
a: [1.0, 1.0, 1.0]
position: [0.0, 0.5, 1.0]
image_prefix: "/Users/harrison37/Work/alpine/ascent/build-debug/tests/_output/milk_chocolate"
renders:
r1:
image_width: 512
image_height: 512
image_prefix: "/Users/harrison37/Work/alpine/ascent/build-debug/tests/_output/milk_chocolate"
Original file line number Diff line number Diff line change
Expand Up @@ -229,16 +229,30 @@ parse_color_table(const conduit::Node &color_table_node)

if(color_table_node.has_child("control_points"))
{
bool clear = false;
const Node &control_points_node = color_table_node.fetch("control_points");

// check to see if we have rgb points and clear the table
NodeConstIterator itr = color_table_node.fetch("control_points").children();
while(itr.has_next())
bool clear = false;
if (control_points_node.dtype().is_list())
{
const Node &peg = itr.next();
if (peg["type"].as_string() == "rgb")
NodeConstIterator itr = control_points_node.children();
while(itr.has_next())
{
clear = true;
break;
const Node &peg = itr.next();
if (peg["type"].as_string() == "rgb")
{
clear = true;
break;
}
}
}
else if (control_points_node.dtype().is_object())
{
if (control_points_node.has_child("r") &&
control_points_node.has_child("g") &&
control_points_node.has_child("b"))
{
clear = true;
}
}

Expand All @@ -247,51 +261,122 @@ parse_color_table(const conduit::Node &color_table_node)
color_table.ClearColors();
}

itr = color_table_node.fetch("control_points").children();
while(itr.has_next())
if (control_points_node.dtype().is_list())
{
const Node &peg = itr.next();
if(!peg.has_child("position"))
NodeConstIterator itr = control_points_node.children();
while(itr.has_next())
{
// FIXME: This should be an error
ASCENT_WARN("Color map control point must have a position");
const Node &peg = itr.next();
if(!peg.has_child("position"))
{
// FIXME: This should be an error
ASCENT_WARN("Color map control point must have a position");
}

float64 position = peg["position"].to_float64();

if(position > 1.0 || position < 0.0)
{
ASCENT_WARN("Cannot add color map control point position "
<< position
<< ". Must be a normalized scalar.");
}

if (peg["type"].as_string() == "rgb")
{
conduit::Node n;
peg["color"].to_float64_array(n);
const float64 *color = n.as_float64_ptr();

vtkm::Vec<vtkm::Float64,3> ecolor(color[0], color[1], color[2]);

for(int i = 0; i < 3; ++i)
{
ecolor[i] = std::min(1., std::max(ecolor[i], 0.));
}

color_table.AddPoint(position, ecolor);
}
else if (peg["type"].as_string() == "alpha")
{
float64 alpha = peg["alpha"].to_float64();
alpha = std::min(1., std::max(alpha, 0.));
color_table.AddPointAlpha(position, alpha);
}
else
{
ASCENT_WARN("Unknown color table control point type "
<< peg["type"].as_string()<<
"\nValid types are 'alpha' and 'rgb'");
}
}
}
else if (control_points_node.dtype().is_object())
{
if(!control_points_node.has_child("r"))
{
ASCENT_ERROR("Color map control point must provide r values");
}

if(!control_points_node.has_child("g"))
{
ASCENT_ERROR("Color map control point must provide g values");
}

float64 position = peg["position"].to_float64();
if(!control_points_node.has_child("b"))
{
ASCENT_ERROR("Color map control point must provide b values");
}

if(position > 1.0 || position < 0.0)
if(!control_points_node.has_child("position"))
{
ASCENT_WARN("Cannot add color map control point position "
<< position
<< ". Must be a normalized scalar.");
ASCENT_ERROR("Color map control point must have a position");
}

if (peg["type"].as_string() == "rgb")
float64_array r_vals = control_points_node.fetch("r").value();
float64_array g_vals = control_points_node.fetch("g").value();
float64_array b_vals = control_points_node.fetch("b").value();
float64_array pos_vals = control_points_node.fetch("position").value();

if(r_vals.number_of_elements() != g_vals.number_of_elements() ||
g_vals.number_of_elements() != b_vals.number_of_elements() ||
b_vals.number_of_elements() != pos_vals.number_of_elements())
{
conduit::Node n;
peg["color"].to_float64_array(n);
const float64 *color = n.as_float64_ptr();
ASCENT_ERROR("Color map color channels should all be of the same size");
}

vtkm::Vec<vtkm::Float64,3> ecolor(color[0], color[1], color[2]);
for(index_t i=0; i<r_vals.number_of_elements();i++)
{
vtkm::Vec<vtkm::Float64,3> ecolor(r_vals[i], g_vals[i], b_vals[i]);

for(int i = 0; i < 3; ++i)
{
ecolor[i] = std::min(1., std::max(ecolor[i], 0.));
ecolor[i] = std::min(1., std::max(ecolor[i], 0.));
}

color_table.AddPoint(position, ecolor);
}
else if (peg["type"].as_string() == "alpha")
{
float64 alpha = peg["alpha"].to_float64();
alpha = std::min(1., std::max(alpha, 0.));
color_table.AddPointAlpha(position, alpha);
if(pos_vals[i] > 1.0 || pos_vals[i] < 0.0)
{
ASCENT_ERROR("Cannot add color map control point position "
<< pos_vals[i]
<< ". Must be a normalized scalar.");
}

color_table.AddPoint(pos_vals[i], ecolor);
}
else

if(control_points_node.has_child("a"))
{
ASCENT_WARN("Unknown color table control point type "
<< peg["type"].as_string()<<
"\nValid types are 'alpha' and 'rgb'");
float64_array alpha_vals = control_points_node.fetch("a").value();

if(pos_vals.number_of_elements() != alpha_vals.number_of_elements())
{
ASCENT_ERROR("Color map alpha channel should have same size as color channels");
}

for(index_t i=0; i<alpha_vals.number_of_elements();i++)
{
color_table.AddPointAlpha(pos_vals[i], std::min(1., std::max(alpha_vals[i], 0.)));
}
}
}
}
Expand Down
Loading
Loading