Skip to content

Commit

Permalink
move isolayer logic to separate mixin-like class
Browse files Browse the repository at this point in the history
  • Loading branch information
chrishavlin committed Jul 1, 2024
1 parent 6ec51e7 commit 4967ea8
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 173 deletions.
173 changes: 1 addition & 172 deletions yt_idv/scene_components/base_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ class SceneComponent(traitlets.HasTraits):
priority = traitlets.CInt(0)
visible = traitlets.Bool(True)
use_db = traitlets.Bool(False) # use depth buffer
iso_tol_is_pct = traitlets.Bool(True) # if True, the tolerance is a fraction
iso_log = traitlets.Bool(True) # if True, iso values are base 10 exponents
iso_tolerance = traitlets.List() # the tolerance for finding isocontours
iso_layers = traitlets.List() # the target values for isocontours
iso_layers_alpha = traitlets.List() # the transparency of isocontours
display_bounds = traitlets.Tuple(
traitlets.CFloat(),
traitlets.CFloat(),
Expand Down Expand Up @@ -109,30 +104,9 @@ def render_gui(self, imgui, renderer, scene):
_ = add_popup_help(imgui, "Click to reset the colorbounds of the current view.")
changed = changed or _

if self.render_method == "isocontours":
_ = self._render_isolayer_inputs(imgui)
changed = changed or _

return changed

@traitlets.observe("iso_log")
def _switch_iso_log(self, change):
# if iso_log, then the user is setting 10**x, otherwise they are setting
# x directly. So when toggling this checkbox we convert the existing
# values between the two forms.
if change["old"]:
# if True, we were taking the log, but now are not:
new_tol = [10**iso_tol for iso_tol in self.iso_tolerance]
self.iso_tolerance = new_tol
new_iso_layers = [10**iso_val for iso_val in self.iso_layers]
self.iso_layers = new_iso_layers
else:
# we were not taking the log but now we are, so convert to the exponent
new_tol = [np.log10(iso_tol) for iso_tol in self.iso_tolerance]
self.iso_tolerance = new_tol
new_iso_layers = [np.log10(iso_val) for iso_val in self.iso_layers]
self.iso_layers = new_iso_layers

@traitlets.default("display_name")
def _default_display_name(self):
return self.name
Expand All @@ -151,18 +125,6 @@ def _change_render_method(self, change):
self.colormap_vertex = new_combo["second_vertex"]
self.colormap_fragment = new_combo["second_fragment"]

@traitlets.observe("render_method")
def _add_initial_isolayer(self, change):
# this adds an initial isocontour entry when the render method
# switches to isocontours and if there are no layers yet.
if change["new"] == "isocontours" and len(self.iso_layers) == 0:
val =(self.data.min_val +self.data.max_val)/2.0
if self.iso_log:
val = np.log10(val)
self.iso_layers.append(val)
self.iso_tolerance.append(0.0)
self.iso_layers_alpha.append(1.0)

@traitlets.default("fb")
def _fb_default(self):
return Framebuffer()
Expand Down Expand Up @@ -259,15 +221,7 @@ def program2(self):
self._program2_invalid = False
return self._program2

def _set_iso_uniforms(self, p):
# these could be handled better by watching traits.
p._set_uniform("iso_num_layers", int(len(self.iso_layers)))
isolayervals = self._get_sanitized_iso_layers()
p._set_uniform("iso_layers_min", isolayervals[0])
p._set_uniform("iso_layers_max", isolayervals[1])
avals = np.zeros((32,), dtype="float32")
avals[: len(self.iso_layers)] = np.array(self.iso_layers_alpha)
p._set_uniform("iso_alphas", avals)


def run_program(self, scene):
# Store this info, because we need to render into a framebuffer that is the
Expand All @@ -280,8 +234,6 @@ def run_program(self, scene):
with self.program1.enable() as p:
scene.camera._set_uniforms(scene, p)
self._set_uniforms(scene, p)
if self.render_method == "isocontours":
self._set_iso_uniforms(p)
with self.data.vertex_array.bind(p):
self.draw(scene, p)

Expand Down Expand Up @@ -310,48 +262,6 @@ def run_program(self, scene):
def draw(self, scene, program):
raise NotImplementedError

@property
def _iso_layer_array(self):
iso_vals = np.asarray(self.iso_layers, dtype="float32")
if self.iso_log:
iso_vals = 10 ** iso_vals
return iso_vals
def _get_sanitized_iso_layers(self, normalize=True):
# returns an array of the isocontour layer values, padded with 0s out
# to max number of contours (32).
iso_vals = self._iso_layer_array

tols = self._get_sanitized_iso_tol()
iso_min_max = [iso_vals - tols/2.,
iso_vals + tols/2.]

min_max_outputs = []
for id in range(2):
vals = iso_min_max[id]
if normalize:
vals = self.data._normalize_by_min_max(vals)

full_array = np.zeros(32, dtype="float32")
full_array[: len(self.iso_layers)] = vals.astype("float32")
min_max_outputs.append(full_array)

return min_max_outputs

def _get_sanitized_iso_tol(self):
tol = np.asarray(self.iso_tolerance)
if self.iso_log:
# the tol value is an exponent, convert
tol = 10 ** tol

if self.iso_tol_is_pct:
# tolerance depends on the layer value
tol = np.asarray(tol) * 0.01
iso_vals = self._iso_layer_array
final_tol = iso_vals * tol
else:
final_tol = tol
return final_tol

def _recompile_shader(self) -> bool:
# removes existing shaders, invalidates shader programs
shaders = (
Expand All @@ -368,87 +278,6 @@ def _recompile_shader(self) -> bool:
self._program1_invalid = self._program2_invalid = True
return True

def _render_isolayer_inputs(self, imgui) -> bool:
changed = False
if imgui.tree_node("Isocontours"):
_, self.iso_log = imgui.checkbox("set exponent", self.iso_log)
_ = add_popup_help(
imgui, "If checked, will treat isocontour values as base-10 exponents."
)
changed = changed or _

# imgui.columns(2, "iso_tol_cols", False)

# _, self.iso_tolerance = imgui.input_float(
# "tol",
# self.iso_tolerance,
# flags=imgui.INPUT_TEXT_ENTER_RETURNS_TRUE,
# )
# _ = add_popup_help(imgui, "The tolerance for selecting an isocontour.")
# changed = changed or _

imgui.next_column()
_, self.iso_tol_is_pct = imgui.checkbox("set tolerance in %", self.iso_tol_is_pct)
_ = add_popup_help(imgui, "If checked, the tolerance is a percent.")
changed = changed or _
imgui.columns(1)

if imgui.button("Add Layer"):
if len(self.iso_layers) < 32:
changed = True
self.iso_layers.append(0.0)
self.iso_layers_alpha.append(1.0)
_ = self._construct_isolayer_table(imgui)
changed = changed or _
imgui.tree_pop()
return changed

def _construct_isolayer_table(self, imgui) -> bool:
imgui.columns(4, "iso_layers_cols", False)

i = 0
changed = False
while i < len(self.iso_layers):
_, self.iso_layers[i] = imgui.input_float(
f"Layer {i + 1}",
self.iso_layers[i],
flags=imgui.INPUT_TEXT_ENTER_RETURNS_TRUE,
)
_ = add_popup_help(imgui, "The value of the isocontour layer.")
changed = changed or _

imgui.next_column()
_, self.iso_tolerance[i] = imgui.input_float(
f"tol {i}",
self.iso_tolerance[i],
flags=imgui.INPUT_TEXT_ENTER_RETURNS_TRUE,
)
_ = add_popup_help(imgui, "The tolerance of the isocontour layer.")
changed = changed or _


imgui.next_column()
_, self.iso_layers_alpha[i] = imgui.input_float(
f"alpha {i}",
self.iso_layers_alpha[i],
flags=imgui.INPUT_TEXT_ENTER_RETURNS_TRUE,
)
_ = add_popup_help(imgui, "The opacity of the isocontour layer.")
changed = changed or _

imgui.next_column()
if imgui.button("Remove##rl" + str(i + 1)):
self.iso_layers.pop(i)
self.iso_layers_alpha.pop(i)
i -= 1
_ = True
changed = changed or _
imgui.next_column()
i += 1
imgui.columns(1)

return changed

def _reset_cmap_bounds(self):
data = self.fb.data
if self.use_db:
Expand Down
8 changes: 7 additions & 1 deletion yt_idv/scene_components/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
from yt_idv.gui_support import add_popup_help
from yt_idv.opengl_support import TransferFunctionTexture
from yt_idv.scene_components.base_component import SceneComponent
from yt_idv.scene_components.isolayers import Isolayers
from yt_idv.scene_data.block_collection import BlockCollection
from yt_idv.shader_objects import component_shaders


class BlockRendering(SceneComponent):
class BlockRendering(SceneComponent, Isolayers):
"""
A class that renders block data. It may do this in one of several ways,
including mesh outline. This allows us to render a single collection of
Expand Down Expand Up @@ -120,6 +121,9 @@ def render_gui(self, imgui, renderer, scene):
changed = changed or _
_ = add_popup_help(imgui, "The normal vector of the slicing plane.")
changed = changed or _
elif self.render_method == "isocontours":
_ = self._render_isolayer_inputs(imgui)
changed = changed or _

return changed

Expand Down Expand Up @@ -149,3 +153,5 @@ def _set_uniforms(self, scene, shader_program):
shader_program._set_uniform("tf_log", float(self.tf_log))
shader_program._set_uniform("slice_normal", np.array(self.slice_normal))
shader_program._set_uniform("slice_position", np.array(self.slice_position))
if self.render_method == "isocontours":
self._set_iso_uniforms(shader_program)
Loading

0 comments on commit 4967ea8

Please sign in to comment.