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

Add conversion for VisIt color table to Ascent actions color table #1446

Merged
merged 7 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
- Added `near_plane` and `far_plane` to the camera details provided in Ascent::info()
- Added `add_mpi_ranks` and `add_domain_ids` filters for adding rank and domain fields to a mesh
- Added `transform` filter, which allows you to rotate, scale, translate, mesh coordinates
- Added python script in src/utilities/visit_session_converters to convert VisIt color table to Ascent actions color table

### Changed
- Changed the replay utility's binary names such that `replay_ser` is now `ascent_replay` and `raplay_mpi` is now `ascent_replay_mpi`. This will help prevent potential name collisions with other tools that also have replay utilities.
Expand Down
49 changes: 49 additions & 0 deletions src/tests/utilities/batlow-visit-ct.ct
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0"?>
<Object name="ColorTable">
<Field name="Version" type="string">3.4.1</Field>
<Object name="ColorControlPointList">
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">1 25 89 255 </Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">16 63 96 255 </Field>
<Field name="position" type="float">0.1111111</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">28 90 98 255 </Field>
<Field name="position" type="float">0.2222222</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">60 109 86 255 </Field>
<Field name="position" type="float">0.3333333</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">104 123 62 255 </Field>
<Field name="position" type="float">0.4444444</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">157 137 43 255 </Field>
<Field name="position" type="float">0.5555555</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">210 147 67 255 </Field>
<Field name="position" type="float">0.6666666</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">248 161 123 255 </Field>
<Field name="position" type="float">0.7777777</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">253 183 188 255 </Field>
<Field name="position" type="float">0.8888888</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">250 204 250 255 </Field>
<Field name="position" type="float">0.9999999</Field>
</Object>
<Field name="smoothing" type="string">None</Field>
<Field name="discrete" type="bool">true</Field>
<Field name="tags" type="stringVector">"Color Blind Safe" "Crameri" "Sequential" "Discrete" "User Defined" </Field>
<Field name="builtin" type="bool">false</Field>
</Object>
</Object>
49 changes: 49 additions & 0 deletions src/tests/utilities/batlow.ct
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0"?>
<Object name="ColorTable">
<Field name="Version" type="string">3.4.1</Field>
<Object name="ColorControlPointList">
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">1 25 89 255 </Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">16 63 96 255 </Field>
<Field name="position" type="float">0.1111111</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">28 90 98 255 </Field>
<Field name="position" type="float">0.2222222</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">60 109 86 255 </Field>
<Field name="position" type="float">0.3333333</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">104 123 62 255 </Field>
<Field name="position" type="float">0.4444444</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">157 137 43 255 </Field>
<Field name="position" type="float">0.5555555</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">210 147 67 255 </Field>
<Field name="position" type="float">0.6666666</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">248 161 123 255 </Field>
<Field name="position" type="float">0.7777777</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">253 183 188 255 </Field>
<Field name="position" type="float">0.8888888</Field>
</Object>
<Object name="ColorControlPoint">
<Field name="colors" type="unsignedCharArray" length="4">250 204 250 255 </Field>
<Field name="position" type="float">0.9999999</Field>
</Object>
<Field name="smoothing" type="string">None</Field>
<Field name="discrete" type="bool">true</Field>
<Field name="tags" type="stringVector">"Color Blind Safe" "Crameri" "Sequential" "Discrete" "User Defined" </Field>
<Field name="builtin" type="bool">false</Field>
</Object>
</Object>
8 changes: 8 additions & 0 deletions src/tests/utilities/t_python_visit_session_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ def test_extract_opac(self):
print(cmd)
subprocess.check_call(cmd,shell=True)

def test_extract_ct(self):
test_script = pjoin(utils_src_dir(),"visit_session_converters","visit_color_table_to_ascent_color_table.py")
test_sess = pjoin(test_src_dir(),"batlow-visit-ct.ct")
print(test_script)
print(test_sess)
cmd = " ".join([sys.executable,test_script,test_sess])
print(cmd)
subprocess.check_call(cmd,shell=True)

if __name__ == '__main__':
unittest.main()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#
# session_to_opac.py
#

import xml.etree.ElementTree as ET
import sys


def print_tree(node,indent=0):
"""Recursively prints the tree."""
print (' '*indent + '%s: %s' % (node.tag.title(), node.attrib.get('name', node.text)))
name = str(node.attrib.get('name', node.text))
print (' '*indent + '%s' % name)
indent += 4
for elem in node:
print_tree(elem,indent)
indent -= 4

def find_color_control_point_list(node):
"""Finds the ColorControlPointList entry in the xml tree."""
name = str(node.attrib.get('name', node.text))
if name == "ColorControlPointList":
# found it!
print("found it")

print_tree(node)
return node
for elem in node:
res = find_color_control_point_list(elem)
if res is not None:
return res

def parse_color_control_points(color_control_point_list_node):
"""Parses the color control points from the xml node and formats them for ascent actions."""
ascent_color_table = {
"name": "custom",
"control_points": []
}

for control_point in color_control_point_list_node.iter('Object'):
if control_point.attrib.get('name') == 'ColorControlPoint':
color_field = control_point.find("Field[@name='colors']")
position_field = control_point.find("Field[@name='position']")

if color_field is not None:
values = list(map(int, color_field.text.split()))
if len(values) == 4: # Ensure the color has RGBA values
r, g, b, a = values
position = float(position_field.text) if position_field is not None else len(ascent_color_table["control_points"]) / 10.0
ascent_color_table["control_points"].append({
"type": "rgb",
"position": position,
"color": [r / 255.0, g / 255.0, b / 255.0]
})

return ascent_color_table


def print_ascent_color_table_yaml(color_table):
"""Prints the Ascent color table in yaml format."""
print("color_table:")
print(" control_points:")
for point in color_table["control_points"]:
print(" -")
print(" type: \"%s\"" % point['type'])
print(" position: %s" % point['position'])
if point['type'] == 'rgb':
print(" color: %s" % point['color'])

def write_ascent_color_table_yaml(color_table, output_file):
"""Writes the Ascent color table to a yaml file."""
with open(output_file, 'w') as yaml_file:
yaml_file.write("color_table:\n")
yaml_file.write(" control_points:\n")
for cp in color_table["control_points"]:
yaml_file.write(" -\n")
yaml_file.write(" type: \"%s\"\n" % cp["type"])
yaml_file.write(" position: %.6f\n" % cp["position"])
yaml_file.write(" color: %s\n" % cp["color"])

def main():
if len(sys.argv) != 2:
print("usage: python3 session_to_color_table {visit_color_table.ct}")
exit(1)

session_file = str(sys.argv[1])

tree = ET.parse(session_file)
root = tree.getroot()

color_control_point_list_node = find_color_control_point_list(root)
if color_control_point_list_node is None:
print('Warning: failed to find ColorControlPointList entry in %s' % session_file)
else:
ascent_color_table = parse_color_control_points(color_control_point_list_node)
print_ascent_color_table_yaml(ascent_color_table)
# Write to a YAML file
output_file = session_file.rsplit('.', 1)[0] + '.yaml'
write_ascent_color_table_yaml(ascent_color_table, output_file)
main()