-
Notifications
You must be signed in to change notification settings - Fork 23
Add animation tutorials to the main tutorials branch #1915
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
Merged
luisaFelixSalles
merged 18 commits into
doc/new-tutorials-section
from
tutorials/animate/first-animation-tutorials
Dec 3, 2024
Merged
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
719573b
add animate_data.rst tutorial
luisaFelixSalles 6bb092a
completes the animate_data.rst tutorial
luisaFelixSalles 1ad47fe
Apply suggestions from code review
luisaFelixSalles 198141d
codes for just one case and erase badges
luisaFelixSalles 5bf154a
change tutorial name
luisaFelixSalles 343a578
last updates
luisaFelixSalles 57ff22b
Update animate_time.rst
PProfizi 1733ba6
Fixing moving camera
PProfizi f6a5c53
Merge branch 'doc/new-tutorials-section' into tutorials/animate/first…
PProfizi 04d1f21
Apply suggestions from code review
PProfizi e0a45af
Update doc/source/user_guide/tutorials/animate/animate_time.rst
PProfizi 7779304
Merge branch 'doc/new-tutorials-section' into tutorials/animate/first…
PProfizi cdfb01b
Apply suggestions from code review
PProfizi 899d8e2
Apply suggestions from code review
PProfizi cd719b5
Apply suggestions from code review
PProfizi 18fa9dc
Update doc/source/user_guide/tutorials/animate/animate_time.rst
luisaFelixSalles d99c2ed
updates
luisaFelixSalles 6061aba
Merge branch 'doc/new-tutorials-section' into tutorials/animate/first…
luisaFelixSalles File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
363 changes: 363 additions & 0 deletions
363
doc/source/user_guide/tutorials/animate/animate_time.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,363 @@ | ||
| .. _ref_tutorials_animate_time: | ||
|
|
||
| ====================== | ||
| Animate data over time | ||
| ====================== | ||
|
|
||
| .. |Examples| replace:: :mod:`ansys.dpf.core.examples` | ||
| .. |Animator| replace:: :class:`Animator<ansys.dpf.core.animator.Animator>` | ||
| .. |Field| replace:: :class:`Field<ansys.dpf.core.field.Field>` | ||
| .. |FieldsContainer| replace:: :class:`FieldsContainer<ansys.dpf.core.fields_container.FieldsContainer>` | ||
| .. |MeshedRegion| replace:: :class:`MeshedRegion <ansys.dpf.core.meshed_region.MeshedRegion>` | ||
| .. |TimeFreqSupport| replace:: :class:`TimeFreqSupport <ansys.dpf.core.time_freq_support.TimeFreqSupport>` | ||
| .. |animate| replace:: :func:`FieldsContainer.animate() <ansys.dpf.core.fields_container.FieldsContainer.animate>` | ||
| .. |Result| replace:: :class:`Result <ansys.dpf.core.results.Result>` | ||
| .. |Operator| replace:: :class:`Operator<ansys.dpf.core.dpf_operator.Operator>` | ||
| .. |Workflow| replace:: :class:`Workflow<ansys.dpf.core.workflow.Workflow>` | ||
| .. |Elemental| replace:: :class:`elemental<ansys.dpf.core.common.locations>` | ||
| .. |ElementalNodal| replace:: :class:`elemental_nodal<ansys.dpf.core.common.locations>` | ||
| .. |Nodal| replace:: :class:`nodal<ansys.dpf.core.common.locations>` | ||
| .. |Faces| replace:: :class:`faces<ansys.dpf.core.common.locations>` | ||
| .. |Overall| replace:: :class:`overall<ansys.dpf.core.common.locations>` | ||
| .. |open_movie| replace:: :class:`pyvista.Plotter.open_movie` | ||
|
|
||
| This tutorial demonstrates how to create 3D animations of data in time. | ||
|
|
||
| :jupyter-download-script:`Download tutorial as Python script<animate_time>` | ||
|
|
||
| :jupyter-download-notebook:`Download tutorial as notebook<animate_time>` | ||
luisaFelixSalles marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| To animate data across time, you must store the data in a |FieldsContainer| with a ``time`` label. | ||
|
|
||
|
|
||
| Get the result files | ||
| -------------------- | ||
|
|
||
| First, import a results file. For this tutorial, you can use the one available in the |Examples| module. | ||
| For more information about how to import your own result file in DPF, see | ||
| the :ref:`ref_tutorials_import_data` tutorial section. | ||
|
|
||
| .. jupyter-execute:: | ||
|
|
||
| # Import the ``ansys.dpf.core`` module | ||
| from ansys.dpf import core as dpf | ||
| # Import the examples module | ||
| from ansys.dpf.core import examples | ||
| # Import the operators module | ||
| from ansys.dpf.core import operators as ops | ||
|
|
||
| # Define the result file path | ||
| result_file_path = examples.find_msup_transient() | ||
| # Create the model | ||
| model = dpf.Model(data_sources=result_file_path) | ||
|
|
||
| Define a time scoping | ||
| --------------------- | ||
|
|
||
| To animate across time, you must define the time steps you are interested in. | ||
| This tutorial retrieves all the time steps available in |TimeFreqSupport|, but you can also filter them. | ||
| For more information on how to define a scoping, see the ``Narrow down data`` tutorial in the | ||
| :ref:`ref_tutorials_import_data` tutorials section. | ||
|
|
||
| .. jupyter-execute:: | ||
|
|
||
| # Get a scoping of all time steps available | ||
| time_steps = model.metadata.time_freq_support.time_frequencies | ||
|
|
||
| Extract the results | ||
| ------------------- | ||
|
|
||
| Extract the results to animate. In this tutorial, you extract the displacement and stress results. | ||
|
|
||
| .. note:: | ||
|
|
||
| Only the |Elemental|, |Nodal|, or |Faces| locations are supported for animations. | ||
| |Overall| and |ElementalNodal| locations are not currently supported. | ||
|
|
||
|
|
||
| .. jupyter-execute:: | ||
|
|
||
| # Get the displacement fields (already on nodes) at all time steps | ||
| disp_fc = model.results.displacement(time_scoping=time_steps).eval() | ||
| print(disp_fc) | ||
|
|
||
| .. jupyter-execute:: | ||
|
|
||
| # Get the stress fields on nodes at all time steps | ||
| # Request the stress on |Nodal| location as the default |ElementalNodal| location is not supported. | ||
| stress_fc = model.results.stress.on_location(location=dpf.locations.nodal).on_time_scoping(time_scoping=time_steps).eval() | ||
| print(stress_fc) | ||
|
|
||
| Animate the results | ||
| ------------------- | ||
|
|
||
| Animate the results with the |animate| method. | ||
| You can animate them on a deformed mesh (animate the color map and the mesh) | ||
| or on a static mesh (animate the color map only). | ||
|
|
||
| The default behavior of the |animate| method is to: | ||
|
|
||
| - Display the norm of the data components; | ||
| - Display data at the top layer for shells; | ||
| - Display the deformed mesh when animating displacements; | ||
| - Display the static mesh for other types of results; | ||
| - Use a constant and uniform scale factor of 1.0 when deforming the mesh. | ||
|
|
||
| You can animate any result on a deformed geometry by providing displacement results in the `deform_by` parameter. | ||
|
|
||
| The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a |FieldsContainer| | ||
| of same length as the one being animated), or a |FieldsContainer| (also of same length as the one being animated). | ||
|
|
||
| .. note:: | ||
|
|
||
| The behavior of the |animate| method is defined by a |Workflow| it creates and feeds to an |Animator|. | ||
| This |Workflow| loops over a |Field| of frame indices and for each frame generates a field of norm contours | ||
| to render, as well as a displacement field to deform the mesh if `deform_by` is provided. | ||
| For more information on plots on deformed meshes see: :ref:`ref_plotting_data_on_deformed_mesh`. | ||
|
|
||
|
|
||
| Animate the displacement results | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| Use |animate| with the displacement results. | ||
|
|
||
| .. tab-set:: | ||
|
|
||
| .. tab-item:: Deformed mesh | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Animate the displacement results in a deformed geometry | ||
| disp_fc.animate() | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_1.gif") | ||
|
|
||
| .. image:: animate_disp_1.gif | ||
| :scale: 50 % | ||
| :align: center | ||
|
|
||
| .. tab-item:: Static mesh | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Animate the displacement results on a static mesh using ``deform_by=False`` | ||
| disp_fc.animate(deform_by=False) | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_2.gif", | ||
| deform_by=False) | ||
|
|
||
| .. image:: animate_disp_2.gif | ||
| :scale: 50 % | ||
| :align: center | ||
|
|
||
| Animate the stress | ||
| ^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| Use |animate| with the stress results. | ||
|
|
||
| .. tab-set:: | ||
|
|
||
| .. tab-item:: Deformed mesh | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Animate the stress results on a deformed mesh | ||
| # Use the ``deform_by`` argument and give the displacement results. | ||
| stress_fc.animate(deform_by=disp_fc) | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| stress_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_1.gif", | ||
| deform_by=disp_fc) | ||
|
|
||
| .. image:: animate_stress_1.gif | ||
| :scale: 50 % | ||
| :align: center | ||
|
|
||
| .. tab-item:: Static mesh | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Animate the stress results in a static geometry | ||
| stress_fc.animate() | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| stress_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_2.gif") | ||
|
|
||
| .. image:: animate_stress_2.gif | ||
| :scale: 50 % | ||
| :align: center | ||
|
|
||
| Change the scale factor | ||
| ----------------------- | ||
|
|
||
| You can change the scale factor using: | ||
|
|
||
| - A single number for a uniform constant scaling; | ||
| - A list of numbers for a varying scaling (same length as the number of frames). | ||
|
|
||
PProfizi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Uniform constant scaling | ||
| ^^^^^^^^^^^^^^^^ | ||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Define a uniform scale factor | ||
| uniform_scale_factor=10. | ||
| # Animate the displacements | ||
| disp_fc.animate(scale_factor=uniform_scale_factor) | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_3.gif", | ||
| scale_factor=uniform_scale_factor, text="Uniform scale factor") | ||
|
|
||
| .. image:: animate_disp_3.gif | ||
| :scale: 45 % | ||
| :align: center | ||
|
|
||
| Varying scaling | ||
| ^^^^^^^^^^ | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Define a varying scale factor | ||
| varying_scale_factor = [i for i in range(len(disp_fc))] | ||
| # Animate the displacements | ||
| disp_fc.animate(scale_factor=varying_scale_factor) | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_4.gif", | ||
| scale_factor=varying_scale_factor, text="Varying scale factor") | ||
|
|
||
| .. image:: animate_disp_4.gif | ||
| :scale: 45 % | ||
| :align: center | ||
|
|
||
| Save the animation | ||
| ------------------ | ||
|
|
||
| You can save the animation using the ``save_as`` argument with a target file path with the desired format as the extension key. | ||
| Accepted extensions are: | ||
| - ``.gif``; | ||
| - ``.avi``; | ||
| - ``.mp4`` | ||
|
|
||
| For more information see |open_movie|. | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Animate the stress results and save it | ||
| stress_fc.animate(deform_by=disp_fc, save_as="animate_stress.gif") | ||
|
|
||
|
|
||
| Control the camera | ||
| ------------------ | ||
|
|
||
| Control the camera with the ``cpos`` argument. | ||
|
|
||
| A camera position is a combination of: | ||
| - A position; | ||
| - A focal point (the target); | ||
| - A upwards vector. | ||
|
|
||
| It results in a list of format: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| camera_position= [[pos_x, pos_y, pos_z], # position | ||
| [fp_x, fp_y, fp_z], # focal point | ||
| [up_x, up_y, up_z]] # upwards vector | ||
|
|
||
| The |animate| method accepts a single camera position or a list of camera positions for each frame. | ||
|
|
||
| .. note:: | ||
| A tip for defining a camera position is to do a first interactive plot of the data | ||
| with argument ``return_cpos=True``, position the camera as desired in the view, and retrieve | ||
| the output of the plotting command. | ||
|
|
||
| Fixed camera | ||
| ^^^^^^^^^^^^ | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| # Define the camera position | ||
| cam_pos = [[0., 2.0, 0.6], [0.05, 0.005, 0.5], [0.0, 0.0, 1.0]] | ||
| # Animate the stress with a custom fixed camera position | ||
| stress_fc.animate(cpos=cam_pos) | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| stress_fc.animate(save_as="source/user_guide/tutorials/animate/animate_disp_5.gif", | ||
| cpos=cpos, | ||
| off_screen=True) | ||
|
|
||
| .. image:: animate_disp_5.gif | ||
| :scale: 50 % | ||
| :align: center | ||
|
|
||
| Moving camera | ||
| ^^^^^^^^^^^^^ | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-output: | ||
|
|
||
| import copy | ||
| # Define the list of camera positions | ||
| cpos_list = [cam_pos] | ||
| # Incrementally increase the x coordinate of the camera by 0.1 for each frame | ||
| for i in range(1, len(disp_fc)): | ||
| new_pos = copy.deepcopy(cpos_list[i-1]) | ||
| new_pos[0][0] += 0.1 | ||
| cpos_list.append(new_pos) | ||
|
|
||
| # Animate the stress with a moving camera | ||
| stress_fc.animate(cpos=cpos_list) | ||
|
|
||
| .. jupyter-execute:: | ||
| :hide-code: | ||
| :hide-output: | ||
|
|
||
| stress_fc.animate(save_as="source/user_guide/tutorials/animate/animate_disp_6.gif", | ||
| cpos=cpos_list, | ||
| off_screen=True) | ||
|
|
||
| .. image:: animate_disp_6.gif | ||
| :scale: 50 % | ||
| :align: center | ||
|
|
||
| Additional options | ||
| ------------------ | ||
|
|
||
| You can use additional PyVista arguments of |open_movie|), such as: | ||
|
|
||
| - Show or hide the coordinate system axis with ``show_axes=True`` or ``show_axes=False``; | ||
| - Render off-screen for batch animation creation with ``off_screen=True``; | ||
| - Change the frame-rate with ``framerate``; | ||
| - Change the image quality with ``quality``. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.