.. note::
    :class: sphx-glr-download-link-note

    Click :ref:`here <sphx_glr_download_auto_examples_viz_emwave_animation.py>` to download the full example code
.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_examples_viz_emwave_animation.py:


===============================================
Electromagnetic Wave Propagation Animation
===============================================

A linearly polarized sinusoidal electromagnetic wave, propagating in the
direction +x through a homogeneous, isotropic, dissipationless medium,
such as vacuum. The electric field (blue arrows) oscillates in the
±z-direction, and the orthogonal magnetic field (red arrows) oscillates in
phase with the electric field, but in the ±y-direction.

Function of the sinusoid used in the animation = sin(k*x - w*t + d)
Where, k:wavenumber, x:abscissa, w:angular frequency, t:time, d:phase angle

Importing necessary modules


.. code-block:: default


    from fury import window, actor, utils, ui
    import numpy as np
    import itertools







function that updates and returns the coordinates of the waves which are
changing with time


.. code-block:: default



    def update_coordinates(wavenumber, ang_frq, time, phase_angle):
        x = np.linspace(-3, 3, npoints)
        y = np.sin(wavenumber*x - ang_frq*time + phase_angle)
        z = np.array([0 for i in range(npoints)])
        return x, y, z







Variable(s) and their description-
npoints: For high quality rendering, keep the number of npoints high
         but kindly note that higher values for npoints will slow down the
         rendering process (default = 800)
wavelength : wavelength of the wave (default = 2)
wavenumber : 2*pi/wavelength
time: time (default time i.e. time at beginning of the animation = 0)
incre_time: value by which time is incremented for each call of
            timer_callback (default = 0.1)
angular_frq: angular frequency (default = 0.1)
phase_angle: phase angle (default = 0.002)


.. code-block:: default



    npoints = 800
    wavelength = 2
    wavenumber = 2*np.pi/wavelength
    time = 0
    incre_time = 0.1
    angular_frq = 0.1
    phase_angle = 0.002







Creating a scene object and configuring the camera's position


.. code-block:: default


    scene = window.Scene()
    scene.set_camera(position=(-6, 5, -10), focal_point=(0.0, 0.0, 0.0),
                     view_up=(0.0, 0.0, 0.0))
    showm = window.ShowManager(scene,
                               size=(800, 600), reset_camera=True,
                               order_transparent=True)
    showm.initialize()







Creating a yellow colored arrow to show the direction of propagation of
electromagnetic wave


.. code-block:: default


    centers = np.array([[3, 0, 0]])
    directions = np.array([[-1, 0, 0]])
    heights = np.array([6.4])
    arrow_actor = actor.arrow(centers, directions, window.colors.yellow, heights,
                              resolution=20, tip_length=0.06, tip_radius=0.012,
                              shaft_radius=0.005)
    scene.add(arrow_actor)








Creating point actor that renders the magnetic field


.. code-block:: default


    x = np.linspace(-3, 3, npoints)
    y = np.sin(wavenumber*x - angular_frq*time + phase_angle)
    z = np.array([0 for i in range(npoints)])

    pts = np.array([(a, b, c) for (a, b, c) in zip(x, y, z)])
    pts = [pts]
    colors = window.colors.red
    wave_actor1 = actor.line(pts, colors, linewidth=3)
    scene.add(wave_actor1)

    vertices = utils.vertices_from_actor(wave_actor1)
    vcolors = utils.colors_from_actor(wave_actor1, 'colors')
    no_vertices_per_point = len(vertices)/npoints
    initial_vertices = vertices.copy() - \
        np.repeat(pts, no_vertices_per_point, axis=0)








Creating point actor that renders the electric field


.. code-block:: default


    xx = np.linspace(-3, 3, npoints)
    yy = np.array([0 for i in range(npoints)])
    zz = np.sin(wavenumber*xx - angular_frq*time + phase_angle)

    pts2 = np.array([(a, b, c) for (a, b, c) in zip(xx, yy, zz)])
    pts2 = [pts2]
    colors2 = window.colors.blue
    wave_actor2 = actor.line(pts2, colors2, linewidth=3)
    scene.add(wave_actor2)

    vertices2 = utils.vertices_from_actor(wave_actor2)
    vcolors2 = utils.colors_from_actor(wave_actor2, 'colors')
    no_vertices_per_point2 = len(vertices2)/npoints
    initial_vertices2 = vertices2.copy() - \
        np.repeat(pts2, no_vertices_per_point2, axis=0)








Initializing text box to display the title of the animation


.. code-block:: default


    tb = ui.TextBlock2D(bold=True, position=(160, 90))
    tb.message = "Electromagnetic Wave"
    scene.add(tb)







end is used to decide when to end the animation


.. code-block:: default


    end = 300







Initializing counter


.. code-block:: default


    counter = itertools.count()








Coordinates to be plotted are changed everytime timer_callback is called by
using the update_coordinates function. The wave is rendered here.


.. code-block:: default



    def timer_callback(_obj, _event):
        global pts, pts2, time, time_incre, angular_frq, phase_angle, wavenumber
        time += incre_time
        cnt = next(counter)

        x, y, z = update_coordinates(wavenumber, angular_frq, phase_angle, time)
        pts = np.array([(a, b, c) for (a, b, c) in zip(x, y, z)])
        vertices[:] = initial_vertices + \
            np.repeat(pts, no_vertices_per_point, axis=0)
        utils.update_actor(wave_actor1)

        xx, zz, yy = update_coordinates(wavenumber, angular_frq, phase_angle, time)
        pts2 = np.array([(a, b, c) for (a, b, c) in zip(xx, yy, zz)])
        vertices2[:] = initial_vertices2 + \
            np.repeat(pts2, no_vertices_per_point2, axis=0)
        utils.update_actor(wave_actor2)

        showm.render()

        # to end the animation
        if cnt == end:
            showm.exit()








Run every 25 milliseconds


.. code-block:: default


    showm.add_timer_callback(True, 25, timer_callback)

    interactive = False
    if interactive:
        showm.start()
    window.record(showm.scene, size=(800, 600), out_path="viz_emwave.png")



.. image:: /auto_examples/images/sphx_glr_viz_emwave_animation_001.png
    :class: sphx-glr-single-img





.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  0.138 seconds)


.. _sphx_glr_download_auto_examples_viz_emwave_animation.py:


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download

     :download:`Download Python source code: viz_emwave_animation.py <viz_emwave_animation.py>`



  .. container:: sphx-glr-download

     :download:`Download Jupyter notebook: viz_emwave_animation.ipynb <viz_emwave_animation.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_