Skip to content
Merged
61 changes: 37 additions & 24 deletions ansys/dpf/core/animator.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ def animate_workflow(self, loop_over, workflow, output_name, input_name="loop_ov
if cpos:
if isinstance(cpos[0][0], float):
cpos = [cpos]*len(indices)
str_template = "t={0:{2}} {1}"

def render_field(frame):
def render_frame(frame):
self._plotter.clear()
# print(f"render frame {frame} for input {indices[frame]}")
workflow.connect(input_name, [frame])
Expand All @@ -80,39 +81,51 @@ def render_field(frame):
**kwargs)
kwargs_in = _sort_supported_kwargs(
bound_method=self._plotter.add_text, **freq_kwargs)
str_template = "t={0:{2}} {1}"
self._plotter.add_text(str_template.format(loop_over.data[frame], unit, freq_fmt),
**kwargs_in)
if cpos:
self._plotter.camera_position = cpos[frame]

try:
# Write initial frame
render_field(0)
# If not off_screen, enable the user to choose the camera position
if not kwargs.pop("off_screen", None):
print('Orient the view, then press "q" to close the window '
'and produce an animation')
# Show is necessary even when off_screen to initiate the renderer
result = self.show_figure(auto_close=False, **kwargs)
if save_as:
try:
self._plotter.write_frame()
except AttributeError as e: # pragma: no cover
if "To retrieve an image after the render window has been closed" in e.args[0]:
print("Animation canceled.")
return result
# For each additional frame requested
if len(indices) > 1:
for frame in range(1, len(indices)):
def animation():
if save_as:
try:
render_field(frame)
self._plotter.write_frame()
except AttributeError as e: # pragma: no cover
if "'NoneType' object has no attribute 'interactor'" in e.args[0]:
if "To retrieve an image after the render window has been closed" \
in e.args[0]:
print("Animation canceled.")
print(e)
return result
if save_as:
self._plotter.write_frame()
# For each additional frame requested
if len(indices) > 1:
for frame in range(1, len(indices)):
try:
render_frame(frame)
except AttributeError as e: # pragma: no cover
if "'NoneType' object has no attribute 'interactor'" in e.args[0]:
print("Animation canceled.")
return result
if save_as:
self._plotter.write_frame()

# Write initial frame
render_frame(0)
# If not off_screen, enable the user to choose the camera position
off_screen = kwargs.pop("off_screen", None)
if off_screen is None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PProfizi that means that we set off_screen by defualt. Is that what we want ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anslpa I do not see how this sets off_screen=True by default. This takes the value in kwargs, if not present then it is set to None, and if None then we do a last check of the pv.OFF_SCREEN variable which might have been set globally to True, for example when running tests or examples in our pipelines.
I tested it and to me it is False by default.

import pyvista as pv
off_screen = pv.OFF_SCREEN

if not off_screen:
self._plotter.add_key_event("a", animation)
print('Orient the view, then press "a" to produce an animation')
else:
animation()
# Show is necessary even when off_screen to initiate the renderer
result = self._plotter.show(interactive=True)
# result = self.show_figure(auto_close=False, **kwargs)
# result = self._plotter.show()
except Exception as e: # pragma: no cover
print(e)
raise
Expand Down
14 changes: 12 additions & 2 deletions ansys/dpf/core/fields_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,16 @@ def animate(self, save_as=None, deform_by=None, scale_factor=1.0, **kwargs):
wf.set_input_name("loop_over", forward_index.inputs.any)
# Define the field extraction using the fields_container and indices
extract_field_op = dpf.core.operators.utility.extract_field(self)
to_render = extract_field_op.outputs.field
n_components = self[0].component_count
if n_components > 1:
norm_op = dpf.core.operators.math.norm(extract_field_op.outputs.field)
to_render = norm_op.outputs.field

loop_over = self.get_time_scoping()
frequencies = self.time_freq_support.time_frequencies
if frequencies is None:
raise ValueError("The fields_container has no time_frequencies.")

loop_over = self.get_time_scoping()
frequencies = self.time_freq_support.time_frequencies
Expand All @@ -535,7 +545,7 @@ def animate(self, save_as=None, deform_by=None, scale_factor=1.0, **kwargs):
if deform_by is None or isinstance(deform_by, bool):
# By default, set deform_by as self if nodal 3D vector field
if self[0].location == dpf.core.common.locations.nodal and \
self[0].component_count == 3:
n_components == 3:
deform_by = self
else:
deform = False
Expand Down Expand Up @@ -567,7 +577,7 @@ def animate(self, save_as=None, deform_by=None, scale_factor=1.0, **kwargs):
wf.set_output_name("deform_by", divide_op.outputs.field)
else:
scale_factor = None
wf.set_output_name("to_render", extract_field_op.outputs.field)
wf.set_output_name("to_render", to_render)
wf.progress_bar = False

loop_over_field = dpf.core.fields_factory.field_from_array(
Expand Down