6.4.1. Characteristics

Scalar_XYZ is a set of two modules for:

  • Generation of 3D masks and diffractive optical elements.

  • Propagation of light, determination of parameters, and other functions.

  • Drawing sources, masks and fields

For light generation, scalar_sources_XY.py is used.

Warning: This module is not very mature yet.

These modules are named: scalar_fields_XYZ.py,and scalar_masks_XYZ.py.

Each module present a main class:

  • Scalar_field_XYZ

  • Scalar_masks_XYZ

The main attributes for these classes are the following:

  • self.x (numpy.array): linear array with equidistant positions. The number of data is preferibly \(2^n\) .

  • self.y (numpy.array): linear array with equidistant positions. The number of data is preferibly \(2^n\) .

  • self.z (numpy.array): linear array with equidistant positions. The number of data is preferibly \(2^n\) .

  • self.wavelength (float): wavelength of the incident field.

  • self.u (numpy.array): equal size than x * y * z. complex field.

We can also find these atributes:

  • self.X (numpy.array): linear 2D array with size x * y * z storing X position.

  • self.Y (numpy.array): linear 2D array with size x * y * z storing Y position.

  • self.Z (numpy.array): linear 2D array with size x * y * z storing Z position.

  • self.quality (float): quality of RS algorithm. Valid for values > 1.

  • self.info (str): description of data.

  • self.fast (bool): If True, Rayleigh-Sommerfeld computations are performed using Fresnel approximation.

  • self.type (str): Class of the field.

  • self.date (str): date when performed.

[1]:
from diffractio import degrees, eps, mm, no_date, np, plt, um
from diffractio.scalar_fields_XYZ import Scalar_field_XYZ
from diffractio.scalar_masks_XY import Scalar_mask_XY
from diffractio.scalar_masks_XYZ import Scalar_mask_XYZ
from diffractio.scalar_sources_XY import Scalar_source_XY
[30]:
import pyvista as pv

pv.set_jupyter_backend("static")
# normally it is better to use 'trame' backend. In this case a png figure is generated.

6.4.1.1. save_load

[31]:
length = 100 * um
numdata = 16  # 256
x0 = np.linspace(-length / 2, length / 2, numdata)
y0 = np.linspace(-length / 2, length / 2, numdata)
z0 = np.linspace(-length / 2, length / 2, numdata)
wavelength = 0.5 * um
filename = "save_load_xyz.npz"

t1 = Scalar_field_XYZ(x=x0, y=y0, z=z0, wavelength=wavelength)

t1.u = np.ones_like(t1.u)
t1.save_data(filename=filename, add_name="")
[32]:
t2 = Scalar_field_XYZ(x=None, y=None, z=None, wavelength=None)
t2.load_data(filename=filename, verbose=False)

6.4.1.2. clear_field

[33]:
length = 100 * um
numdata = 32  # 256
x0 = np.linspace(-length / 2, length / 2, numdata)
y0 = np.linspace(-length / 2, length / 2, numdata)
z0 = np.linspace(-length / 2, length / 2, numdata)
wavelength = 0.5 * um

u0 = Scalar_field_XYZ(x=x0, y=y0, z=z0, wavelength=wavelength)
u0.u = np.ones_like(u0.u)
print(u0.u.max())

u0.clear_field()
print(u0.u.max())
(1+0j)
0j

6.4.1.3. show_index_refraccion

[34]:
length = 150 * um

x0 = np.linspace(-length / 2, length / 2, 128)
y0 = np.linspace(-length / 2, length / 2, 128)
z0 = np.linspace(-length / 2, length / 2, 128)
wavelength = 0.55 * um

t1 = Scalar_mask_XY(x=x0, y=y0, wavelength=wavelength)
t1.circle(r0=(0 * um, 0 * um), radius=(20 * um, 20 * um), angle=0 * degrees)

uxyz = Scalar_mask_XYZ(
    x=x0, y=y0, z=z0, wavelength=wavelength, n_background=1.0, info=""
)

rotation = dict(kind='point', point=np.array((0,0,0)), angle=np.array((45*degrees, 0,0)) )

uxyz.incident_field(t1)
uxyz.cylinder(
    r0=(0 * um, 0 * um, 0),
    radius=(20 * um, 20 * um),
    length=75 * um,
    refractive_index=1.5,
    rotation=rotation,
)
[35]:
uxyz.draw_XYZ(kind="refractive_index", drawing="projections")
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_11_0.png

6.4.1.4. RS propagation of a circular aperture

[36]:
length = 100 * um
numdata = 128
x0 = np.linspace(-length / 2, length / 2, numdata)
y0 = np.linspace(-length / 2, length / 2, numdata)
z0 = np.linspace(200 * um, 2 * mm, 128)
wavelength = 0.5 * um

u1 = Scalar_source_XY(x=x0, y=y0, wavelength=wavelength)
u1.gauss_beam(A=1, r0=(0 * um, 0 * um), z0=0, w0=(150 * um, 150 * um))

t1 = Scalar_mask_XY(x=x0, y=y0, wavelength=wavelength)
t1.circle(r0=(0 * um, 0 * um), radius=(25 * um, 25 * um))
t3 = u1 * t1
[37]:
uxyz = Scalar_field_XYZ(x=x0, y=y0, z=z0, wavelength=wavelength)
uxyz.incident_field(t3)
uxyz.RS(num_processors=1)
time in RS= 0.3981056213378906. num proc= 1
[38]:
uxyz.draw_XYZ(kind="intensity", drawing="projections")
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_15_0.png

6.4.1.5. Rayleigh-Sommerfeld propagation of a gauss beam passing through a Grating

[39]:
length = 500 * um
x0 = np.linspace(-length / 2, length / 2, 128)
y0 = np.linspace(-length / 2, length / 2, 128)
z0 = np.linspace(2 * mm, 7 * mm, 128)
wavelength = 0.6328 * um

u1 = Scalar_source_XY(x=x0, y=y0, wavelength=wavelength)
u1.gauss_beam(A=1, r0=(0 * um, 0 * um), z0=0, w0=(150 * um, 150 * um))

t1 = Scalar_mask_XY(x=x0, y=y0, wavelength=wavelength)
t1.ronchi_grating(x0=0 * um, period=20 * um, angle=0 * degrees)
t2 = Scalar_mask_XY(x=x0, y=y0, wavelength=wavelength)
t2.lens(
    r0=(0 * um, 0 * um),
    radius=(200 * um, 200 * um),
    focal=(5 * mm, 5 * mm),
    angle=0 * degrees,
)

t3 = u1 * t1 * t2
[40]:
uxyz = Scalar_field_XYZ(x=x0, y=y0, z=z0, wavelength=wavelength)
uxyz.incident_field(t3)
uxyz.RS()
uxyz.normalize()
time in RS= 0.40485596656799316. num proc= 1
[41]:
uxyz.draw_XY(z0=4.5 * mm)
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_19_0.png

A particular plane, can be passed to scalar_field_XY, and then, it can be drawn.

[42]:
u_xy = uxyz.to_Scalar_field_XY(z0=4.75 * mm, is_class=True, matrix=False)
u_xy.draw(kind="intensity")
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_21_0.png

Also, the intensity at the XZ plane can be obtained.

[43]:
uxyz.draw_XZ(y0=0 * mm, logarithm=1e1, draw_borders=True )
plt.ylim(-100, 100)
<Figure size 480x360 with 0 Axes>
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_23_1.png
[44]:
uxyz.draw_XYZ(logarithm=1e1)
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_24_0.png

6.4.1.6. Video from a XYZ distribution

[ ]:
length = 50 * um
numdata = 128  # 256
x0 = np.linspace(-length / 2, length / 2, numdata)
y0 = np.linspace(-length / 2, length / 2, numdata)
z0 = np.linspace(50 * um, 2 * mm, 250)  # 128
wavelength = 0.5 * um

u1 = Scalar_source_XY(x=x0, y=y0, wavelength=wavelength)
u1.gauss_beam(A=1, r0=(0 * um, 0 * um), z0=0, w0=(150 * um, 150 * um))

t1 = Scalar_mask_XY(x=x0, y=y0, wavelength=wavelength)
t1.circle(r0=(0 * um, 0 * um), radius=25*um)
t3 = u1 * t1
[13]:
uxyz = Scalar_field_XYZ(x=x0, y=y0, z=z0, wavelength=wavelength)
uxyz.incident_field(t3)
uxyz.RS()
uxyz.normalize()
time in RS= 0.7574293613433838. num proc= 1
[15]:
uxyz.video(filename="video_RS_int.avi", fps=10, axis='scaled', kind="intensity", frame=False)

alt text

[11]:
%%HTML
<div align="middle">
 <video width="50%" controls>
  <source src="video_RS_int.avi" type="video/avi">
 </video>
</div>

6.4.1.7. benchmark_RS_multiprocessing

[ ]:
x0 = np.linspace(-10 * um, 10 * um, 200)
y0 = np.linspace(-10 * um, 10 * um, 200)
z0 = np.linspace(0 * um, 20 * um, 200)
wavelength = 2 * um

u0 = Scalar_source_XY(x=x0, y=y0, wavelength=wavelength)
u0.plane_wave(A=1, theta=0 * degrees, phi=0 * degrees)

uxyz = Scalar_mask_XYZ(
    x=x0, y=y0, z=z0, wavelength=wavelength, n_background=1.0, info=""
)

rotation = dict(kind='point', point=np.array((0,0,0)), angle=np.array((45*degrees, 0,45*degrees)) )

uxyz.incident_field(u0)
uxyz.sphere( r0=(0 * um, 0 * um, 7 * um), radius=(10 * um, 10* um, 6 * um), refractive_index=3., rotation=None)
[99]:
uxyz.draw_XYZ(kind="refractive_index", drawing="projections")
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_33_0.png
[100]:
uxyz.WPM(has_edges=False, verbose=True)

Time = 0.84 s, time/loop = 4.189 ms
[101]:
uxyz.draw_XYZ(kind="intensity", drawing="projections", logarithm=1e3)
../../../_images/source_tutorial_scalar_scalar_XYZ_tutorial_xyz_35_0.png