Description#
This module allows to propagate 2D wavefront using either:
near field propagation
far field propagation
continuous propagation using the fractional Fourier Transform approach
Sub-module
pynx.wavefront.fzp
can be used to calculate the coherent illumination from a Fresnel Zone PlateSub-module
pynx.wavefront.fresnel
can be used to simulate
Calculations can be done using a GPU (OpenCL or CUDA), and use an ‘operator’ approach, where operations on agiven wavefront can be simply written by multiplying that wavefront by the corresponding operator or by a seriesof operators.
API Reference#
Note that the Python API uses an ‘operator’ approach, to enable writingcomplex operations in a more mathematical and natural way.
Wavefront#
- exception pynx.wavefront.wavefront.UserWarningWavefrontNearFieldPropagation#
- class pynx.wavefront.wavefront.Wavefront(d=None, z=0, pixel_size=5.5e-05, wavelength=1.5498e-10, copy_d=True)#
A 2D Wavefront object
Create the Wavefront object.
- Parameters:
z – current position of 2D Wavefront along direction propagation, in meters
pixel_size – current pixelsize at z, in meters
d –
the original data array at z - will be converted to complex64 if needed.This can either be :- a 2D array- a 3D array which will be treated as a stack of 2D wavefront for multi-views/modes propagation.- None: will be initialized to a 512x512 data array filled with 1.- a string to use one image from either scipy or scikit-image data. These will be truncated to 512x512.Available string values are ‘ascent’, ‘face’, ‘camera’, ‘hubble’, ‘immunohistochemistry’.In the case of RGB images, all 3 components are loaded.
The data should have its center at (0,0) to avoid requiring fftshifts during propagation.
Any 2D data will be converted to 3D with a shape of (1, ny, nx)
wavelength – X-ray wavelength in meters.
- copy(copy_d=True)#
Creates a copy (without any reference passing) of this object, unless copy_d is False.
- Parameters:
copy_d – if False, the new object will be a shallow copy, with d copied as a reference.
- Returns:
a copy of the object.
- get(shift=False)#
Get the wavefront data array. This will automatically get the latest data, either from GPU or from the hostmemory, depending where the lat changes were made.
- Parameters:
shift – if True, the data array will be fft-shifted so that the center of the data is in the centerof the array, rather than in the corner (the default).
- Returns:
the 2D or 3D (stack of wavefront) numpy data array
- get_x_y()#
Get 1D arrays of x and y coordinates, taking into account the pixel size. The arrays are centeredat (0,0) - i.e. with the origin in the corner for FFT puroposes. x is an horizontal vector and y vertical.
- Returns:
a tuple (x, y) of 2D numpy arrays
- set(d, shift=False)#
Set the wavefront data array.
- Parameters:
d – the data array (complex64 numpy array)
shift – if True, the data array will be fft-shifted so that the center of the stored data isin the corner of the array (0,0). [default: the array is already shifted]
- Returns:
nothing
Wavefront operators#
This section lists the OpenCL operators, but identical operators are available for CUDA. The best set ofoperators (determined by querying available languages and devices) is imported automatically when performingfrom pynx.wavefront import * or from pynx.cdi.wavefront import *
- class pynx.wavefront.cl_operator.BackPropagatePaganin(dz=1, delta=1e-06, beta=1e-09)#
Back-propagation algorithm using the single-projection approach.Ref: Paganin et al., Journal of microscopy 206 (2002), 33–40. (DOI: 10.1046/j.1365-2818.2002.01010.x)
This operator is special since it will use only the intensity of the wavefront. Therefore it will first take thesquare modulus of the wavefront it is applied to, discarding any phase information.The result of the transformation is the calculated wavefront at the sample position, i.e. if T(r) is theestimated thickness of the sample, it is exp(-mu * T - 2*pi/lambda * T)
- Parameters:
dz – distance between sample and detector (meter)
delta – real part of the refraction index, n = 1 - delta + i * beta
beta – imaginary part of the refraction index
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.CircularMask(radius, invert=False)#
Multiplies the wavefront by a binary circular mask with a given radius
- Parameters:
radius – radius of the mask (in meters)
invert – if True, the inside of the circle will be masked rather than the outside
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.FT(processing_unit=None)#
Forward Fourier transform.
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.FreePU(processing_unit=None)#
Operator freeing OpenCL memory. The gpyfft data reference in self.processing_unit is removed,as well as any OpenCL pyopencl.array.Array attribute in the supplied wavefront.
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- timestamp_increment(cdi)#
Increment the timestamp counter corresponding to the processing language used (OpenCL or CUDA)Virtual, must be derived.
- Parameters:
w – the object (e.g. wavefront) the operator will be applied to.
- Returns:
- class pynx.wavefront.cl_operator.IFT(processing_unit=None)#
Inverse Fourier transform
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.PropagateFRT(dz, forward=True)#
- Wavefront propagator using a fractional Fourier transform
References:
Mas, J. Garcia, C. Ferreira, L.M. Bernardo, and F. Marinho, Optics Comm 164, 233 (1999)
García, D. Mas, and R.G. Dorsch, Applied Optics 35, 7013 (1996)
Notes:
the computed phase is only ‘valid’ for dz<N*pixel_size**2/wavelength, i.e near-to-medium field(I am not sure this is strictly true - the phase will vary quickly from pixel to pixel as fora spherical wave propagation but the calculation is still correct)
the amplitude remains correct even in the far field
only forward propagation works correctly (z>0)
- Parameters:
dz – the propagation distance
forward – if True (default), forward propagation. Note that backward propagation is purely experimentaland not fully correct.
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.PropagateFarField(dz, forward=True, no_far_field_quadphase=True)#
Far field propagator
- Parameters:
dz – propagation distance in meters
forward – if True, forward propagation, otherwise backward
no_far_field_quadphase – if True (default), no quadratic phase is applied in the far field
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.PropagateNearField(dz, magnification=None, verbose=False)#
Near field propagator
- Parameters:
dz – propagation distance (in meters)
magnification – if not None, the destination pixel size will will be multiplied by this factor.Note that it creates important restrictions on the validity domain of the calculation,both near and far.
verbose – if True, prints the propagation limit for a valid phase.
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.QuadraticPhase(factor, scale=1)#
Operator applying a quadratic phase factor
Application of a quadratic phase factor, and optionally a scale factor.
The actual factor is: \(scale * e^{i * factor * (ix^2 + iy^2)}\)where ix and iy are the integer indices of the pixels
- Parameters:
factor – the factor for the phase calculation.
scale – the data will be scaled by this factor. Useful to normalize after a Fourier transform,without accessing twice the array data.
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.RectangularMask(width, height, invert=False)#
Multiplies the wavefront by a rectangular mask with a given width and height
- Parameters:
width – width of the mask (in meters)
height – height of the mask (in meters)
invert – if True, the inside of the rectangle will be masked rather than the outside
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.Scale(x)#
Multiply the wavefront by a scalar (real or complex).
- Parameters:
x – the scaling factor
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
- class pynx.wavefront.cl_operator.ThinLens(focal_length)#
Multiplies the wavefront by a quadratic phase factor corresponding to a thin lens with a given focal length.The phase factor is: \(e^{-\frac{i * \pi * (x^2 + y^2)}{\lambda * focal\_length}}\)
Note that a too short focal_length can lead to aliasing, which will occur when the phase variesfrom more than pi from one pixel to the next. A warning will be written if this occurs at half the distancefrom the center (i.e. a quarter of the array size).
- Parameters:
focal_length – focal length (in meters)
- op(w: Wavefront)#
- Parameters:
w – the Wavefront object this operator applies to
- Returns:
the updated Wavefront object
Fresnel propagation#
Warning: this code is old and was mostly written as a proof-of-concept, but is no longer tested/developed.It is recommended to use the Wavefront operators.
- pynx.wavefront.fresnel.Fresnel_thread(v1, vx1, vy1, vx2, vy2, vdz2, wavelength=1e-10, verbose=False, gpu_name='GTX', cl_platform='')#
Compute the Fresnel propagation between an origin and a destination plane, using direct calculation.Uses OpenCL.
NOTE: this code is experimental, mostly used for tests !
- Parameters:
v1 – complex 2D array of the field to propagate, size=nx1*ny1
vx1 – 1D vectors of x and y coordinates of v1 (nx1, ny1)
vy1 – 1D vectors of x and y coordinates of v1 (nx1, ny1)
vx2 – 1D vectors of x and y coordinates of v2 (nx1, ny1)
vy2 – 1D vectors of x and y coordinates of v2 (nx1, ny1)
vdz2 – distance (m) between the origin and destination plane
wavelength – wavelength
verbose – if True, print calculcation messages
gpu_name – name of the GPU to use (string)
cl_platform – OpenCL platform name to use (string)
- Returns:
a complex array of the propagated wavefront with the same shape as vx2, vy2.
Illumination from a Fresnel Zone Place#
Warning: this code is old and was mostly written as a proof-of-concept, but is no longer tested/developed.It is recommended to use the Wavefront operators.
- pynx.wavefront.fzp.FZP_thread(x, y, z, sourcex=0, sourcey=0, sourcez=-50, wavelength=1, focal_length=0.129, rmax=0.0001, r_cs=0, osa_z=0, osa_r=1000000.0, nr=512, ntheta=256, fzp_xmin=None, fzp_xmax=None, fzp_ymin=None, fzp_ymax=None, fzp_nx=None, fzp_ny=None, gpu_name='GTX', cl_platform='', verbose=False)#
Compute illumination from a FZP, itself illuminated from a single monochromatic point source. Uses OpenCL.
The integration is either made on the fill circular shaphe of the FZP, or a rectangular area.
All units are SI.
NOTE: this code is experimental, mostly used for tests !
- Parameters:
x – numpy array of coordinates where the illumination will be calculated
y – numpy array of coordinates where the illumination will be calculated
z – numpy array of coordinates where the illumination will be calculated
sourcex – position of the point source illuminating the FZP (float)
sourcey – position of the point source illuminating the FZP (float)
sourcez – position of the point source illuminating the FZP (float)
wavelength – the wavelength of the incident beam
focal_length – the focal length of the FZP
rmax – max radius of the FZP
r_cs – radius of the central stop
osa_z – z position of the Order Sorting Aperture, relative to the FZP
osa_r – radius of the OSA
nr – number of radial steps for the integration
ntheta – number of angular (polar) steps for the integration
fzp_xmin – x min coordinate for a rectangular illumination
fzp_xmax – x max coordinate for a rectangular illumination
fzp_ymin – y min coordinate for a rectangular illumination
fzp_ymax – y max coordinate for a rectangular illumination
fzp_nx – number of x steps for the integration, for a rectangular illumination
fzp_ny – number of y steps for the integration, for a rectangular illumination
gpu_name – name (sub-string) of the gpu to be used
cl_platform – OpenCL platform to use (optional)
verbose – if true, will report on the progress of threaded calculations.
- Returns:
a complex numpy array of the calculated illumination, with the same shape as x,y,z.
Examples#
Propagation operators#
# -*- coding: utf-8 -*-# PyNX - Python tools for Nano-structures Crystallography# (c) 2016-present : ESRF-European Synchrotron Radiation Facility# authors:# Vincent Favre-Nicolin, favre@esrf.frimport timeitfrom pylab import *# The following import will use CUDA if available, otherwise OpenCLfrom pynx.wavefront import *if True: # Near field propagation of a simple 20x200 microns slit w = Wavefront(d=np.zeros((512, 512), dtype=np.complex64), pixel_size=1e-6, wavelength=1.5e-10) a = 20e-6 / 2 x, y = w.get_x_y() w.set((abs(y) < a) * (abs(x) < 100e-6)) w = PropagateNearField(0.5) * w # w = PropagateFRT(3) * w w = ImshowRGBA(fig_num=1, title="Near field propagation (0.5m) of a 20x200 microns aperture") * wif True: # Near field propagation of a simple 40x200 microns slit, displaying the propagated wavefront by steps # of 0.2 m propagation w = Wavefront(d=np.zeros((512, 512), dtype=np.complex64), pixel_size=1e-6, wavelength=1.5e-10) a = 40e-6 / 2 x, y = w.get_x_y() w.set((abs(y) < a) * (abs(x) < 100e-6)) # Perform 15 near field propagation of 0.2m steps, displaying the complex wavefront each time # the **15 expression allows to repeat the series of operators 15 times. w = (ImshowRGBA(fig_num=2) * PropagateNearField(0.2))**15 * wif True: w = Wavefront(d=np.zeros((1024, 1024), dtype=np.complex64), pixel_size=1.3e-6, wavelength=1.e-10) a = 43e-6 / 2 x, y = w.get_x_y() w.set((abs(y) < a) * (abs(x) < 100e-6)) # w = PropagateNearField(3) * w w = PropagateFRT(3) * w # w = PropagateFarField(20) * w # w = PropagateNearField(-3) * PropagateNearField(3) * w # w = PropagateFRT(3, forward=False) * PropagateFRT(3) * w # w = PropagateFarField(100, forward=False) * PropagateFarField(100) * w w = ImshowRGBA(fig_num=3, title="Fractional Fourier transform propagation (3m) of a 43x200 microns slit") * wif True: # Jacques et al 2012 single slit setup - here with simulated 1 micron pixel # Compare with figure 7 for a=43,88,142,82 microns figure(figsize=(15, 10)) for a in np.array([22, 43, 88, 142, 182]) * 1e-6 / 2: w = Wavefront(d=np.zeros((1024, 1024), dtype=np.complex64), wavelength=1e-10, pixel_size=1.3e-6) x, y = w.get_x_y() w.set(abs(y) < (a) + x * 0) # +x*0 needed to make sure the array is 2D # w = PropagateNearField(3) * w w = PropagateFRT(3) * w # w = PropagateFarField(3) * w icalc = fftshift(abs(w.get())).mean(axis=1) ** 2 x, y = w.get_x_y() plot(fftshift(y) * 1e6, icalc, label=u'a=%5.1f µm' % (a * 2e6)) text(0, icalc[len(icalc) // 2], u'a=%5.1f µm' % (a * 2e6)) print('a=%5.1fum, dark spot at a^2/(2pi*lambda)=%5.2fm, I[0]=%5.2f' % ( 2 * a * 1e6, (2 * a) ** 2 / (2 * pi * w.wavelength), icalc[len(icalc) // 2])) title("Propagation of a slit at 3 meters, wavelength= 0.1nm") legend() xlim(-100, 100) xlabel(u'X (µm)')if True: # propagation of a stack of A x 200 microns apertures, varying A w = Wavefront(d=np.zeros((16, 512, 512), dtype=np.complex64), pixel_size=1e-6, wavelength=1.5e-10) x, y = w.get_x_y() d = w.get() for i in range(16): a = 5e-6 / 2 * (i + 1) d[i] = ((abs(y) < a) * (abs(x) < 100e-6)) w.set(d) w = PropagateFRT(1.2) * w figure(figsize=(15, 10)) x, y = w.get_x_y() x *= 1e6 y *= 1e6 for i in range(16): subplot(4, 4, i + 1) imshow(abs(fftshift(w.get()[i])), extent=(x.min(), x.max(), y.min(), y.max()), origin='lower') title(u"A=%dµm" % (10 * (i + 1))) if i >= 12: xlabel(u'X (µm)') if i % 4 == 0: ylabel(u'Y (µm)') xlim(-150, 150) ylim(-100, 100) suptitle(u"Fractional Fourier propagation (0.5m) of a A x 200 µm aperture")if True: # Using a lens plus near field propagation to focus a 40x80 microns^ wavefront w = Wavefront(d=np.zeros((512, 512), dtype=np.complex64), pixel_size=1e-6, wavelength=1.5e-10) x, y = w.get_x_y() w.set((abs(y) < 20e-6) * (abs(x) < 40e-6)) w = PropagateNearField(1.5) * ThinLens(focal_length=2) * w w = ImshowAbs(fig_num=6, title="1.5m propagation after a f=2m lens") * wif True: # Time propagation of stacks of 1024x1024 wavefronts for nz in [1, 1, 10, 50, 100, 200]: # First size is repeated to avoid counting initializations t0 = timeit.default_timer() d = np.zeros((nz, 512, 512), dtype=np.complex64) w = Wavefront(d=d, pixel_size=1e-6, wavelength=1.5e-10) print("####################### Stack size: %4d x %4d *%4d ################" % w.get().shape) x, y = w.get_x_y() a = 20e-6 / 2 d[:] = (abs(y) < a) * (abs(x) < 100e-6) w.set(d) t1 = timeit.default_timer() print("%30s: dt=%6.2fms" % ("Wavefront creation (CPU)", (t1 - t0) * 1000)) w = PropagateFRT(1.2) * w t2 = timeit.default_timer() print("%30s: dt=%6.2fms" % ("Copy to GPU and propagation", (t2 - t1) * 1000)) w = PropagateFRT(1.2) * w t3 = timeit.default_timer() print("%30s: dt=%6.2fms" % ("Propagation", (t3 - t2) * 1000)) w = FreePU() * w # We use FreePU() to make sure we release GPU memory as fast as possible t4 = timeit.default_timer() print("%30s: dt=%6.2fms" % ("Copy from GPU", (t4 - t3) * 1000))
Paganin operator#
# -*- coding: utf-8 -*-# PyNX - Python tools for Nano-structures Crystallography# (c) 2017-present : ESRF-European Synchrotron Radiation Facility# authors:# Vincent Favre-Nicolin, favre@esrf.frimport numpy as nptry: from scipy.datasets import ascentexcept ImportError: from scipy.misc import ascentfrom pylab import *# The following import will use CUDA if available, otherwise OpenCLfrom pynx.wavefront import *################################################################################################################# Create a wavefront as a simple transmission through a rectangular objectw = Wavefront(d=np.zeros((512, 512), dtype=np.complex64), pixel_size=1e-6, wavelength=1.5e-10)a, b = 100e-6 / 2, 200e-6 / 2x, y = w.get_x_y()d = ((abs(y) < a) * (abs(x) < b))delta = 1e-6beta = 1e-9thickness = 1e-6mu = 4 * np.pi * beta / w.wavelengthk = 2 * np.pi / w.wavelengthprint(" mu * t = %f\nk * delta * t = %f" % (mu * thickness, k * delta * thickness))w.set(exp(1j * k * (-delta + 1j * beta) * thickness * d))# Display the amplitudew = ImshowAbs(fig_num=1) * w# Propagate and display amplitudew = ImshowAbs(fig_num=2) * PropagateNearField(0.5) * w# Reconstruct original wavefield using Paganin's equation (only using propagated intensity, phase is discarded)w = BackPropagatePaganin(dz=0.5) * w# Display reconstructed Amplitude, phasew = ImshowAngle(fig_num=3) * ImshowAbs(fig_num=4) * w# Display the calculated thickness from the reconstructed phasefigure(5)imshow(fftshift(-np.angle(w.get())/(k*delta)), extent=(x.min(), x.max(), y.min(), y.max()), origin='lower')title("Back-propagation using Paganin's approach")xlabel(u'X (µm)')ylabel(u'Y (µm)')c=colorbar()################################################################################################################# Slightly more complicated examplew = Wavefront(d=np.zeros((512, 512), dtype=np.complex64), pixel_size=1e-6, wavelength=1.5e-10)delta = 1e-6beta = 1e-9mu = 4 * np.pi * beta / w.wavelengthk = 2 * np.pi / w.wavelengthprint(" mu * t = %f\nk * delta * t = %f" % (mu * thickness, k * delta * thickness))w.set(exp(1j * k * (-delta + 1j * beta) * fftshift(ascent()) * 1e-7))d1 = w.get(shift=True).copy()# Propagate and reconstructdz = 0.5w = PropagateNearField(dz) * wd2 = w.get(shift=True).copy()w = BackPropagatePaganin(dz=dz) * wd3 = w.get(shift=True).copy()# Displayfigure(6, figsize=(10, 8))subplot(221)imshow(abs(d1))title("Amplitude (z=0)")colorbar()subplot(222)imshow(abs(d2))title("Amplitude (z=%5.2fm)" % dz)colorbar()subplot(223)imshow(abs(d3))title("Reconstructed Amplitude (Paganin)")colorbar()subplot(224)imshow(np.angle(d3))title("Reconstructed Phase (Paganin)")colorbar()
Illumination from a Fresnel Zone Place#
# -*- coding: utf-8 -*-from pynx.wavefront import fzpfrom pynx.utils.plot_utils import complex2rgbalin, colorwheelfrom pylab import *import numpy as npdelta_min = 70e-9wavelength = np.float32(12398.4 / 7000 * 1e-10)rmax = np.float32(150e-6) # radius of FZPfocal_length = 2 * rmax * delta_min / wavelengthprint("FZP: diameter= %6.2fum, focal length=%6.2fcm" % (rmax * 2 * 1e6, focal_length * 100))nr, ntheta = np.int32(1024), np.int32(512) # number of points for integration on FZPr_cs = np.float32(25e-6) # Central stop radiusosa_z, osa_r = np.float32(focal_length - .021), np.float32(30e-6) # OSA position and radiussourcex = np.float32(0e-6) # Source positionsourcey = np.float32(0e-6)sourcez = np.float32(-90)focal_point = 1 / (1 / focal_length - 1 / abs(sourcez))gpu_name = "gpu" # will combine available gpu (experimental - it is safer to put part of the name of the gpu you want)if True: # rectangular illumination ? xmin, xmax, ymin, ymax = 50e-6, 110e-6, -100e-6, 100e-6 fzp_nx, fzp_ny = 512, 512else: xmin, xmax, ymin, ymax = False, False, False, False fzp_nx, fzp_ny = None, Noneif True: x = linspace(-.8e-6, .8e-6, 256) y = linspace(-.8e-6, .8e-6, 256)[:, newaxis] z = focal_pointelse: x = linspace(-.8e-6, .8e-6, 256)[:, newaxis] y = 0 z = focal_point + linspace(-2e-3, 2e-3, 256)x = (x + (y + z) * 0).astype(float32)y = (y + (x + z) * 0).astype(float32)z = (z + (x + y) * 0).astype(float32)nxyz = len(x.flat)a_real = (x * 0).astype(np.float32)a_imag = (x * 0).astype(np.float32)a, dt, flop = fzp.FZP_thread(x, y, z, sourcex=sourcex, sourcey=sourcey, sourcez=sourcez, wavelength=wavelength, focal_length=focal_length, rmax=rmax, r_cs=r_cs, osa_z=osa_z, osa_r=osa_r, nr=nr, ntheta=ntheta, fzp_xmin=xmin, fzp_xmax=xmax, fzp_ymin=ymin, fzp_ymax=ymax, fzp_nx=fzp_nx, fzp_ny=fzp_ny, gpu_name=gpu_name, verbose=True)print("clFZP dt=%9.5fs, %8.2f Gflop/s" % (dt, flop / 1e9 / dt))if xmin is not None and xmax is not None: print("Correct phase for off-axis illumination") a *= exp(2j * pi * x * (xmin + xmax) / 2 / focal_length / wavelength)clf()zz = z - focal_pointif (x.max() - x.min()) <= 1e-8: # pylab.imshow(complex2rgba(a,amin=0.0,dlogs=2),extent=(z.min()*1e6,z.max()*1e6,y.min()*1e9,y.max()*1e9),aspect='equal',origin='lower') imshow(complex2rgbalin(a), extent=(zz.min() * 1e6, zz.max() * 1e6, y.min() * 1e9, y.max() * 1e9), aspect='equal', origin='lower') xlabel(r"$z\ (\mu m)$", fontsize=16) ylabel(r"$y\ (nm)$", fontsize=16)elif (z.max() - z.min()) <= 1e-8: # pylab.imshow(complex2rgba(a,amin=0.0,dlogs=2),extent=(x.min()*1e6,x.max()*1e6,y.min()*1e6,y.max()*1e6),aspect='equal',origin='lower') imshow(complex2rgbalin(a), extent=(x.min() * 1e9, x.max() * 1e9, y.min() * 1e9, y.max() * 1e9), aspect='equal', origin='lower') xlabel(r"$x\ (nm)$", fontsize=16) ylabel(r"$y\ (nm)$", fontsize=16)else: # pylab.imshow(complex2rgba(a,amin=0.0,dlogs=2),extent=(z.min()*1e3,z.max()*1e3,x.min()*1e6,x.max()*1e6),aspect='equal',origin='lower') imshow(complex2rgbalin(a), extent=(zz.min() * 1e6, zz.max() * 1e6, x.min() * 1e9, x.max() * 1e9), aspect='equal', origin='lower') xlabel(r"$z\ (\mu m)$", fontsize=16) ylabel(r"$x\ (nm)$", fontsize=16)ax = axes((0.22, 0.76, 0.12, .12), facecolor='w') # [left, bottom, width, height]colorwheel()