.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/renderblender/ex2_2_stereodeformed.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_renderblender_ex2_2_stereodeformed.py: Blender example: Deforming a sample with stereo DIC =================================================== This example takes you through creating stereo DIC scene, applying deformation to the sample, and rendering images at each deformation timestep. Test case: mechanical analysis of a plate with a hole loaded in tension. .. GENERATED FROM PYTHON SOURCE LINES 16-23 .. code-block:: Python import numpy as np from scipy.spatial.transform import Rotation from pathlib import Path import pyvale import mooseherder as mh .. GENERATED FROM PYTHON SOURCE LINES 24-27 The simulation results are loaded in here in the same way as the previous example. As mentioned this `data_path` can be replaced with your own MOOSE simulation output in exodus format (*.e). .. GENERATED FROM PYTHON SOURCE LINES 27-31 .. code-block:: Python data_path = pyvale.DataSet.render_mechanical_3d_path() sim_data = mh.ExodusReader(data_path).read_all_sim_data() .. GENERATED FROM PYTHON SOURCE LINES 32-37 This is then scaled to mm, as all lengths in Blender are to be set in mm. The `SimData` object is then converted into a `RenderMeshData` object, as this skins the mesh ready to be imported into Blender. The `disp_comps` are the expected direction of displacement. Since this is a 3D deformation test case, displacement is expected in the x, y and z directions. .. GENERATED FROM PYTHON SOURCE LINES 37-48 .. code-block:: Python disp_comps = ("disp_x","disp_y", "disp_z") sim_data = pyvale.scale_length_units(scale=1000.0, sim_data=sim_data, disp_comps=disp_comps) render_mesh = pyvale.create_render_mesh(sim_data, ("disp_y","disp_x"), sim_spat_dim=3, field_disp_keys=disp_comps) .. GENERATED FROM PYTHON SOURCE LINES 49-54 Firstly, a save path must be set. In order to do this a base path must be set. Then all the generated files will be saved to a subfolder within this specified base directory (e.g. blenderimages). If no base directory is specified, it will be set as your home directory. .. GENERATED FROM PYTHON SOURCE LINES 54-57 .. code-block:: Python base_dir = Path.cwd() .. GENERATED FROM PYTHON SOURCE LINES 58-63 Creating the scene ^^^^^^^^^^^^^^^^^^ In order to create a DIC setup in Blender, first a scene must be created. A scene is initialised using the `BlenderScene` class. All the subsequent objects and actions necessary are then methods of this class. .. GENERATED FROM PYTHON SOURCE LINES 63-65 .. code-block:: Python scene = pyvale.BlenderScene() .. GENERATED FROM PYTHON SOURCE LINES 66-71 The next thing that can be added to the scene is a sample. This is done by passing in the `RenderMeshData` object. It should be noted that the mesh will be centred on the origin to allow for the cameras to be centred on the mesh. Once the part is added to the Blender scene, it can be both moved and rotated. .. GENERATED FROM PYTHON SOURCE LINES 71-80 .. code-block:: Python part = scene.add_part(render_mesh, sim_spat_dim=3) # Set the part location part_location = np.array([0, 0, 0]) pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location) # Set part rotation part_rotation = Rotation.from_euler("xyz", [0, 0, 0], degrees=True) pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation) .. GENERATED FROM PYTHON SOURCE LINES 81-96 The cameras can then be initialised. A stereo camera system is defined by a `CameraStereo` object, which contains the intrinsic parameters of both cameras as well as the extrinsic parameters between them. There are two ways to initialise a `CameraStereo` object. One way is to specify the camera parameters separately for each camera, create a `CameraStereo` object, and then add the stereo system using the `add_stereo_system` method. The other method is to use a convenience function, as shown below. This requires you to first initialise one camera. Then you can choose between either a face-on or symmetric stereo system. Then, either of the `symmetric_stereo_cameras` or `faceon_stereo_cameras` functions can be used to initialise a `CameraStereo` object. The only input required to these functions are the camera parameters for the first camera, and the desired stereo angle between the two. The cameras can then be added to the Blender scene using the `add_stereo_system` method. .. GENERATED FROM PYTHON SOURCE LINES 96-116 .. code-block:: Python cam_data_0 = pyvale.CameraData(pixels_num=np.array([1540, 1040]), pixels_size=np.array([0.00345, 0.00345]), pos_world=np.array([0, 0, 400]), rot_world=Rotation.from_euler("xyz", [0, 0, 0]), roi_cent_world=(0, 0, 0), focal_length=15.0) # Set this to "symmetric" to get a symmetric stereo system or set this to # "faceon" to get a face-on stereo system stereo_setup = "faceon" if stereo_setup == "symmetric": stereo_system = pyvale.CameraTools.symmetric_stereo_cameras( cam_data_0=cam_data_0, stereo_angle=15.0) if stereo_setup == "faceon": stereo_system = pyvale.CameraTools.faceon_stereo_cameras( cam_data_0=cam_data_0, stereo_angle=15.0) cam0, cam1 = scene.add_stereo_system(stereo_system) .. GENERATED FROM PYTHON SOURCE LINES 117-125 Since this scene contains a stereo DIC system, a calibration file will be required to run the images through a DIC engine. A calibration file can be generated directly from the `CameraStereo` object. The calibration file will be saved in `YAML` format. However, if you wish to use MatchID to process the images, `save_calibration_mid` can be used instead to save the calibration in a format readable by MatchID. The calibration file will be saved to a sub-directory of the base directory called "calibration". .. GENERATED FROM PYTHON SOURCE LINES 125-127 .. code-block:: Python stereo_system.save_calibration(base_dir) .. GENERATED FROM PYTHON SOURCE LINES 128-131 A light can the be added to the scene. Blender offers different light types: Point, Sun, Spot and Area. The light can also be moved and rotated like the camera. .. GENERATED FROM PYTHON SOURCE LINES 131-146 .. code-block:: Python light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT, pos_world=(0, 0, 400), rot_world=Rotation.from_euler("xyz", [0, 0, 0]), energy=1) light = scene.add_light(light_data) light.location = (0, 0, 410) light.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle # Apply the speckle pattern material_data = pyvale.BlenderMaterialData() speckle_path = pyvale.DataSet.dic_pattern_5mpx_path() # NOTE: If you wish to use a bigger camera, you will need to generate a # bigger speckle pattern generator .. GENERATED FROM PYTHON SOURCE LINES 147-156 A speckle pattern can then be applied to the sample. Firstly, the material properties of the sample must be specified, but these will all be defaulted if no inputs are provided. The speckle pattern can then be specified by providing a path to an image file with the pattern. The mm/px resolution of the camera must also be specified in order to correctly scale the speckle pattern. It should be noted that for a bigger camera or sample you may need to generate a larger speckle pattern. .. GENERATED FROM PYTHON SOURCE LINES 156-163 .. code-block:: Python mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data_0) scene.add_speckle(part=part, speckle_path=speckle_path, mat_data=material_data, mm_px_resolution=mm_px_resolution) .. GENERATED FROM PYTHON SOURCE LINES 164-172 Deforming the sample and rendering images ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Once all the objects have been added to the scene, the sample can be deformed, and images can be rendered. Firstly, all the rendering parameters must be set, including parameters such as the number of threads to use. Differently to a 2D DIC system, both cameras' parameters must be specified in the `RenderData` object. .. GENERATED FROM PYTHON SOURCE LINES 172-177 .. code-block:: Python render_data = pyvale.RenderData(cam_data=(stereo_system.cam_data_0, stereo_system.cam_data_1), base_dir=base_dir, threads=8) .. GENERATED FROM PYTHON SOURCE LINES 178-187 A series of deformed images can then be rendered. This is done by passing in rendering parameters, as well as the `RenderMeshData` object, the part(sample) and the spatial dimension of the simulation. This will automatically deform the sample, and render images from each camera at each deformation timestep. If `stage_image` is set to True, the image will be saved to disk, converted to an array, deleted and the image array will be returned. This is due to the fact that an image cannot be saved directly as an array through Blender. .. GENERATED FROM PYTHON SOURCE LINES 187-194 .. code-block:: Python scene.render_deformed_images(render_mesh=render_mesh, sim_spat_dim=3, render_data=render_data, part=part, stage_image=False) .. GENERATED FROM PYTHON SOURCE LINES 195-196 The rendered image will be saved to this filepath: .. GENERATED FROM PYTHON SOURCE LINES 196-199 .. code-block:: Python print("Save directory of the image:", (render_data.base_dir / "blenderimages")) .. GENERATED FROM PYTHON SOURCE LINES 200-202 There is also the option to save the scene as a Blender project file. This file can be opened with the Blender GUI to view the scene. .. GENERATED FROM PYTHON SOURCE LINES 202-205 .. code-block:: Python pyvale.BlenderTools.save_blender_file(base_dir) .. _sphx_glr_download_examples_renderblender_ex2_2_stereodeformed.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: ex2_2_stereodeformed.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: ex2_2_stereodeformed.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: ex2_2_stereodeformed.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_