123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #!/usr/bin/env python
- # -*- coding: UTF-8 -*-
- #
- # Copyright (C) 2009-2015 Ovidio Peña Rodríguez <ovidio@bytesfall.com>
- # Copyright (C) 2013-2015 Konstantin Ladutenko <kostyfisik@gmail.com>
- #
- # This file is part of python-scattnlay
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # The only additional remark is that we expect that all publications
- # describing work using this software, or all commercial products
- # using it, cite the following reference:
- # [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by
- # a multilayered sphere," Computer Physics Communications,
- # vol. 180, Nov. 2009, pp. 2348-2354.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- # Several functions to plot field and streamlines (power flow lines).
- from scattnlay import fieldnlay, scattnlay
- import numpy as np
- ###############################################################################
- def GetCoords(crossplane, npts, factor, x):
- """
- crossplane: XZ, YZ, XY, or XYZ (half is XZ, half is YZ)
- npts: number of point in each direction
- factor: ratio of plotting size to outer size of the particle
- x: size parameters for particle layers
- """
- scan = np.linspace(-factor*x[-1], factor*x[-1], npts)
- zero = np.zeros(npts*npts, dtype = np.float64)
- if crossplane=='XZ':
- coordX, coordZ = np.meshgrid(scan, scan)
- coordX.resize(npts*npts)
- coordZ.resize(npts*npts)
- coordY = zero
- elif crossplane == 'YZ':
- coordY, coordZ = np.meshgrid(scan, scan)
- coordY.resize(npts*npts)
- coordZ.resize(npts*npts)
- coordX = zero
- elif crossplane == 'XY':
- coordX, coordY = np.meshgrid(scan, scan)
- coordX.resize(npts*npts)
- coordY.resize(npts*npts)
- coordZ = zero
- elif crossplane=='XYZ': # Upper half: XZ; Lower half: YZ
- coordX, coordZ = np.meshgrid(scan, scan)
- coordY, coordZ = np.meshgrid(scan, scan)
- coordX[:, scan<0] = 0
- coordY[:, scan>=0] = 0
- coordX.resize(npts*npts)
- coordY.resize(npts*npts)
- coordZ.resize(npts*npts)
- else:
- print("Unknown crossplane")
- import sys
- sys.exit()
- return coordX, coordY, coordZ, scan
- ###############################################################################
- def GetField(crossplane, npts, factor, x, m, pl):
- """
- crossplane: XZ, YZ, XY, or XYZ (half is XZ, half is YZ)
- npts: number of point in each direction
- factor: ratio of plotting size to outer size of the particle
- x: size parameters for particle layers
- m: relative index values for particle layers
- """
- coordX, coordY, coordZ, scan = GetCoords(crossplane, npts, factor, x)
- terms, E, H = fieldnlay(x, m, coordX, coordY, coordZ, pl=pl)
- if len(E.shape) > 2:
- E = E[0, :, :]
- H = H[0, :, :]
- S = np.cross(E, np.conjugate(H)).real
- print(S)
- if crossplane=='XZ':
- Sx = np.resize(S[:, 2], (npts, npts)).T
- Sy = np.resize(S[:, 0], (npts, npts)).T
- elif crossplane == 'YZ':
- Sx = np.resize(S[:, 2], (npts, npts)).T
- Sy = np.resize(S[:, 1], (npts, npts)).T
- elif crossplane == 'XY':
- Sx = np.resize(S[:, 1], (npts, npts)).T
- Sy = np.resize(S[:, 0], (npts, npts)).T
- elif crossplane=='XYZ': # Upper half: XZ; Lower half: YZ
- Sx = np.resize(S[:, 2], (npts, npts)).T
- Sy = np.resize(S[:, 0], (npts, npts)).T
- Sy[scan<0] = np.resize(S[:, 1], (npts, npts)).T[scan<0]
- else:
- print("Unknown crossplane")
- import sys
- sys.exit()
- return E, H, S, scan, Sx, Sy
- ###############################################################################
- def fieldplot(fig, ax, x, m, WL, comment='', WL_units=' ', crossplane='XZ',
- field_to_plot='Pabs', npts=101, factor=2.1,
- flow_total=11, density=20, minlength=0.1, maxlength=4.0,
- arrowstyle='-|>', arrowsize=1.0,
- pl=-1, draw_shell=False, outline_width=1, subplot_label=' '):
- E, H, S, scan, Sx, Sy = GetField(crossplane, npts, factor, x, m, pl)
- Er = np.absolute(E)
- Hr = np.absolute(H)
- try:
- from matplotlib import cm
- from matplotlib.colors import LogNorm
- if field_to_plot == 'Pabs':
- label = r'$\operatorname{Re}(E \times H^*)$'
- data = np.resize(np.linalg.norm(np.cross(E, np.conjugate(H)), axis=1).real, (npts, npts)).T
- elif field_to_plot == 'Eabs':
- label = r'$|E|$'
- Eabs = np.sqrt(Er[:, 0]**2 + Er[:, 1]**2 + Er[:, 2]**2)
- data = np.resize(Eabs, (npts, npts)).T
- elif field_to_plot == 'Habs':
- label = r'$|H|$'
- Habs = np.sqrt(Hr[:, 0]**2 + Hr[:, 1]**2 + Hr[:, 2]**2)
- Habs = 376.730313667*Habs # scale to free space impedance
- data = np.resize(Habs, (npts, npts)).T
- elif field_to_plot == 'angleEx':
- label = r'$arg(E_x)$'
- Eangle = np.angle(E[:, 0])/np.pi*180
- data = np.resize(Eangle, (npts, npts)).T
- elif field_to_plot == 'angleHy':
- label = r'$arg(H_y)$'
- Hangle = np.angle(H[:, 1])/np.pi*180
- data = np.resize(Hangle, (npts, npts)).T
- # Rescale to better show the axes
- scale = scan*WL/2.0/np.pi
- # Define scale ticks
- min_tick = np.amin(data[~np.isnan(data)])
- max_tick = np.amax(data[~np.isnan(data)])
- scale_ticks = np.linspace(min_tick, max_tick, 5)
- ax.set_title(label)
- # build a rectangle in axes coords
- ax.annotate(subplot_label, xy=(0.0, 1.1), xycoords='axes fraction', # fontsize=10,
- horizontalalignment='left', verticalalignment='top')
- # Interpolation can be 'nearest', 'bilinear' or 'bicubic'
- cax = ax.imshow(data, interpolation='nearest', cmap=cm.jet,
- origin='lower', vmin=min_tick, vmax=max_tick,
- extent=(min(scale), max(scale), min(scale), max(scale))
- # ,norm = LogNorm()
- )
- ax.axis("image")
- # Add colorbar
- cbar = fig.colorbar(cax, ticks=[a for a in scale_ticks], ax=ax)
- # vertically oriented colorbar
- if 'angle' in field_to_plot:
- cbar.ax.set_yticklabels(['%3.0f' % (a) for a in scale_ticks])
- else:
- cbar.ax.set_yticklabels(['%g' % (a) for a in scale_ticks])
- if crossplane == 'XZ':
- ax.set_xlabel('Z (%s)' % (WL_units))
- ax.set_ylabel('X (%s)' % (WL_units))
- elif crossplane == 'YZ':
- ax.set_xlabel('Z (%s)' % (WL_units))
- ax.set_ylabel('Y (%s)' % (WL_units))
- elif crossplane=='XYZ':
- ax.set_xlabel('Z (%s)' % (WL_units))
- ax.set_ylabel('Y(<0):X(>0) (%s)' % (WL_units))
- # draw a line to separate both planes
- ax.axhline(linewidth=outline_width, color='black')
- elif crossplane == 'XY':
- ax.set_xlabel('X (%s)' % (WL_units))
- ax.set_ylabel('Y (%s)' % (WL_units))
- if draw_shell:
- # Draw the nanoshell
- from matplotlib import patches
- from matplotlib.path import Path
- for xx in x:
- r = xx*WL/2.0/np.pi
- s1 = patches.Arc((0, 0), 2.0*r, 2.0*r, angle=0.0, zorder=1.8,
- theta1=0.0, theta2=360.0, linewidth=outline_width, color='black')
- ax.add_patch(s1)
- # Draw flow lines
- if (not crossplane == 'XY') and flow_total > 0:
- margin = 0.98
- points = np.vstack((margin*scale.min()*np.ones(flow_total),
- np.linspace(margin*scale.min(),
- margin*scale.max(), flow_total))).transpose()
- # Plot the streamlines with an appropriate colormap and arrow style
- ax.streamplot(scale, scale, Sx, Sy,
- start_points=points, integration_direction='both',
- density=density, minlength=minlength, maxlength=maxlength,
- linewidth=outline_width, color='white',
- arrowstyle=arrowstyle, arrowsize=arrowsize)
- finally:
- terms, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2 = scattnlay(x, m)
- print("Qsca = " + str(Qsca))
- #
|