Skip to content

Commit 33a0471

Browse files
committed
diff_... and integrate..._complex_medium() now take 1D thetas and phis
1 parent 5a418f1 commit 33a0471

File tree

3 files changed

+44
-37
lines changed

3 files changed

+44
-37
lines changed

pymie/mie.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,20 +1148,18 @@ def diff_scat_intensity_complex_medium(m, x, thetas, kd, phis=None,
11481148
x : complex, array-like
11491149
size parameter, x = ka = 2*pi*n_med/lambda * a (sphere radius a)
11501150
thetas : array-like
1151-
scattering angles. Should be 2D, as output from np.meshgrid, if
1152-
cartesian=True
1151+
Scattering angles. Must be in radians.
11531152
kd : float
11541153
k * distance, where k = 2*np.pi*n_matrix/wavelen, and distance is the
11551154
distance away from the center of the particle. The standard far-field
11561155
solutions are obtained when distance >> radius in a non-absorbing
11571156
medium.
11581157
phis : None or ndarray
1159-
azimuthal angles for which to calculate the diff scat intensity. In the
1158+
Azimuthal angles for which to calculate the diff scat intensity. In the
11601159
'scattering plane' coordinate system, the scattering matrix does not
11611160
depend on phi, so phi should be set to None. In the 'cartesian'
11621161
coordinate system, the scattering matrix does depend on phi, so an
1163-
array of values should be provided. For 'cartesian' both thetas and
1164-
phis should be 2D, as output from np.meshgrid.
1162+
array of values should be provided.
11651163
cartesian : boolean (default False)
11661164
If False (default), scattering calculations will be carried out in the
11671165
'scattering plane' coordinate system, defined by basis vectors parallel
@@ -1233,9 +1231,10 @@ def diff_scat_intensity_complex_medium(m, x, thetas, kd, phis=None,
12331231
# ensure that broadcasting will work correctly by adding an axis
12341232
# corresponding to theta
12351233
kd = np.atleast_1d(kd)[..., np.newaxis]
1236-
if cartesian:
1234+
if phis is not None:
12371235
# add another axis to correspond to phi
12381236
kd = kd[..., np.newaxis]
1237+
thetas, phis = np.meshgrid(thetas, phis, indexing="ij")
12391238

12401239
if near_field:
12411240
if not cartesian:
@@ -1362,7 +1361,7 @@ def integrate_intensity_complex_medium(dscat, thetas, kd,
13621361
"depend on azimuthal angle, so specified values "
13631362
"will be ignored")
13641363

1365-
# strip units from integrand
1364+
# include Jacobian
13661365
integrand_par = dsigma_1 * np.abs(np.sin(thetas))
13671366
integrand_perp = dsigma_2 * np.abs(np.sin(thetas))
13681367

pymie/tests/test_mie.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -730,9 +730,7 @@ def test_diff_scat_intensity_complex_medium_cartesian():
730730
n_particle = 1.59 + 1e-4 * 1.0j
731731
thetas = np.linspace(np.pi/2, np.pi, 4)
732732
phis = np.linspace(0, 2*np.pi, 3)
733-
thetas_2d, phis_2d = np.meshgrid(thetas, phis) # be careful with meshgrid shape.
734-
# for integration, theta dimension must always come first,
735-
# which is not how it is done here
733+
thetas_2d, _ = np.meshgrid(thetas, phis, indexing="ij")
736734

737735
# parameters for calculating scattering
738736
m = index_ratio(n_particle, n_matrix)
@@ -748,8 +746,8 @@ def test_diff_scat_intensity_complex_medium_cartesian():
748746
# calculate differential scattered intensity in xy basis
749747
# if incident vector is unpolarized (1,1), then the resulting differential
750748
# scattered intensity should be the same as I_par, I_perp
751-
I_xy = mie.diff_scat_intensity_complex_medium(m, x, thetas_2d, kd,
752-
cartesian=True, phis = phis_2d,
749+
I_xy = mie.diff_scat_intensity_complex_medium(m, x, thetas, kd,
750+
cartesian=True, phis = phis,
753751
near_field=False, incident_vector = (1, 1))
754752

755753
# calculate magnitudes
@@ -771,8 +769,7 @@ def test_integrate_intensity_complex_medium_cartesian():
771769
n_particle = 1.59 + 1e-4 * 1.0j
772770
thetas = np.linspace(0, np.pi, 500)
773771
phis = np.linspace(0, 2*np.pi, 550)
774-
phis_2d, thetas_2d = np.meshgrid(phis, thetas) # remember, meshgrid shape is (len(thetas), len(phis))
775-
# and theta dimension MUST come first in these calculations
772+
776773
# parameters for calculating scattering
777774
m = index_ratio(n_particle, n_matrix)
778775
x = size_parameter(wavelen, n_matrix, radius)
@@ -781,7 +778,7 @@ def test_integrate_intensity_complex_medium_cartesian():
781778
kd = (k*distance).to("").magnitude
782779

783780
# calculate the differential scattered intensities
784-
I_xy = mie.calc_ang_scat(m, x, thetas_2d, kd=kd, phis=phis_2d)
781+
I_xy = mie.calc_ang_scat(m, x, thetas, kd=kd, phis=phis)
785782
I_parperp = mie.calc_ang_scat(m, x, thetas, kd=kd)
786783

787784
# integrate the differential scattered intensities
@@ -814,7 +811,6 @@ def test_value_errors():
814811
n_particle = 1.59 + 1e-4 * 1.0j
815812
thetas = np.linspace(np.pi/2, np.pi, 4)
816813
phis = np.linspace(0, 2*np.pi, 3)
817-
thetas_2d, phis_2d = np.meshgrid(thetas, phis)
818814

819815
# parameters for calculating scattering
820816
m = index_ratio(n_particle, n_matrix)
@@ -825,13 +821,13 @@ def test_value_errors():
825821

826822
with pytest.raises(ValueError):
827823
# try to calculate near field in cartesian
828-
_ = mie.diff_scat_intensity_complex_medium(m, x, thetas_2d, kd,
824+
_ = mie.diff_scat_intensity_complex_medium(m, x, thetas, kd,
829825
cartesian=True,
830-
phis=phis_2d,
826+
phis=phis,
831827
near_field=True)
832828
# calculate the differential scattered intensities
833-
I_xy = mie.diff_scat_intensity_complex_medium(m, x, thetas_2d, kd,
834-
cartesian=True, phis=phis_2d,
829+
I_xy = mie.diff_scat_intensity_complex_medium(m, x, thetas, kd,
830+
cartesian=True, phis=phis,
835831
near_field=False)
836832

837833
_ = mie.diff_scat_intensity_complex_medium(m, x, thetas, kd,
@@ -842,7 +838,7 @@ def test_value_errors():
842838
_ = mie.integrate_intensity_complex_medium(I_xy, thetas, kd,
843839
cartesian=True)[0]
844840
with pytest.raises(ValueError):
845-
_ = mie.vector_scattering_amplitude(m, x, thetas_2d,
841+
_ = mie.vector_scattering_amplitude(m, x, thetas,
846842
cartesian=True)
847843

848844
def test_dwell_time_and_energy():

pymie/tests/test_mie_vectorized.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -599,20 +599,30 @@ def test_vectorized_angular_functions(self, num_wavelen,
599599
mx(num_wavelen=num_wavelen, num_layer=num_layer, **self.mxargs,
600600
return_all=True)
601601

602+
num_phi = 13
603+
604+
# while diff_scat_intensity_complex_medium() and
605+
# integrate_intensity_complex_medium() take 1D arrays of phis and
606+
# thetas, vector_scattering_amplitude() and
607+
# amplitude_scattering_matrix() do not. So we have to set up
608+
# meshgrid arrays and non-meshgrid and send them to the appropriate
609+
# functions
610+
thetas = self.thetas
602611
if not cartesian:
603612
phis = None
604-
thetas = self.thetas
613+
phis_2d = None
614+
thetas_2d = thetas
605615
else:
606-
phis = np.linspace(0, 2*np.pi, self.num_theta)
607-
thetas, phis = np.meshgrid(self.thetas, phis)
616+
phis = np.linspace(0, 2*np.pi, num_phi)
617+
thetas_2d, phis_2d = np.meshgrid(self.thetas, phis, indexing="ij")
608618

609-
vsa = mie.vector_scattering_amplitude(m, x, thetas,
619+
vsa = mie.vector_scattering_amplitude(m, x, thetas_2d,
610620
cartesian=cartesian,
611-
phis = phis)
621+
phis = phis_2d)
612622

613-
mat = mie.amplitude_scattering_matrix(m, x, thetas,
623+
mat = mie.amplitude_scattering_matrix(m, x, thetas_2d,
614624
cartesian=cartesian,
615-
phis = phis)
625+
phis = phis_2d)
616626

617627
# choose distance reasonably close to the particle for differential
618628
# scattering calculations
@@ -632,14 +642,14 @@ def test_vectorized_angular_functions(self, num_wavelen,
632642

633643
# check that shapes of all the computed quantities are correct
634644
for element in vsa + mat:
635-
assert element.shape == (num_wavelen, ) + thetas.shape
636-
assert i12.shape == (2, num_wavelen) + thetas.shape
645+
assert element.shape == (num_wavelen, ) + thetas_2d.shape
646+
assert i12.shape == (2, num_wavelen) + thetas_2d.shape
637647

638648
# check that vectorized calculations match looped calculations over
639649
# scalars
640-
amp0 = np.zeros((num_wavelen, ) + thetas.shape, dtype=complex)
650+
amp0 = np.zeros((num_wavelen, ) + thetas_2d.shape, dtype=complex)
641651
amp1 = np.zeros_like(amp0)
642-
S1 = np.zeros((num_wavelen, ) + thetas.shape, dtype=complex)
652+
S1 = np.zeros((num_wavelen, ) + thetas_2d.shape, dtype=complex)
643653
S2 = np.zeros_like(S1)
644654
S3 = np.zeros_like(S1)
645655
S4 = np.zeros_like(S1)
@@ -649,21 +659,23 @@ def test_vectorized_angular_functions(self, num_wavelen,
649659
sigma = np.zeros(num_wavelen)
650660
sigma_1 = np.zeros_like(sigma)
651661
sigma_2 = np.zeros_like(sigma)
652-
dsigma_1 = np.zeros((num_wavelen, ) + thetas.shape)
662+
dsigma_1 = np.zeros((num_wavelen, ) + thetas_2d.shape)
653663
dsigma_2 = np.zeros_like(dsigma_1)
654664

655665
m = np.atleast_1d(m)
656666
x = np.atleast_1d(x)
657667
kd = np.atleast_1d(kd)
658668
for i in range(num_wavelen):
659669
# m[[i]] preserves 2D array
660-
mat_loop = mie.amplitude_scattering_matrix(m[[i]], x[[i]], thetas,
670+
mat_loop = mie.amplitude_scattering_matrix(m[[i]], x[[i]],
671+
thetas_2d,
661672
cartesian=cartesian,
662-
phis = phis)
673+
phis = phis_2d)
663674

664-
vsa_loop = mie.vector_scattering_amplitude(m[[i]], x[[i]], thetas,
675+
vsa_loop = mie.vector_scattering_amplitude(m[[i]], x[[i]],
676+
thetas_2d,
665677
cartesian=cartesian,
666-
phis = phis)
678+
phis = phis_2d)
667679
i_loop = mie.diff_scat_intensity_complex_medium(m[[i]], x[[i]],
668680
thetas,
669681
kd[i],

0 commit comments

Comments
 (0)