Skip to content

Commit a2deaa1

Browse files
raise valueerror for tth>180, arcsin value > 1
1 parent 638b216 commit a2deaa1

File tree

2 files changed

+54
-11
lines changed

2 files changed

+54
-11
lines changed

src/diffpy/utils/scattering_objects/diffraction_objects.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,11 @@ def q_to_tth(self):
323323
q = np.asarray(q)
324324
wavelength = float(self.wavelength)
325325
pre_factor = wavelength / (4 * np.pi)
326-
# limit q * pre_factor to 1 to avoid invalid input to arcsin
327-
arcsin_value = np.where(q * pre_factor <= 1, q * pre_factor, 1)
328-
return np.rad2deg(2.0 * np.arcsin(arcsin_value))
326+
if np.any(np.abs(q * pre_factor) > 1):
327+
raise ValueError(
328+
"Invalid input for arcsin: some values exceed the range [-1, 1]. " "Check wavelength or q values."
329+
)
330+
return np.rad2deg(2.0 * np.arcsin(q * pre_factor))
329331

330332
def tth_to_q(self):
331333
r"""
@@ -362,6 +364,8 @@ def tth_to_q(self):
362364
of ``wavelength``
363365
"""
364366
two_theta = np.asarray(np.deg2rad(self.on_tth[0]))
367+
if np.any(two_theta > np.pi):
368+
raise ValueError("Two theta exceeds 180 degrees.")
365369
wavelength = float(self.wavelength)
366370
pre_factor = (4 * np.pi) / wavelength
367371
return pre_factor * np.sin(two_theta / 2)
@@ -425,6 +429,8 @@ def tth_to_d(self):
425429
of ``wavelength``
426430
"""
427431
two_theta = np.asarray(np.deg2rad(self.on_tth[0]))
432+
if np.any(two_theta > np.pi):
433+
raise ValueError("Two theta exceeds 180 degrees.")
428434
wavelength = float(self.wavelength)
429435
sin_two_theta = np.sin(two_theta / 2)
430436
d = np.where(sin_two_theta != 0, wavelength / (2 * sin_two_theta), np.inf)
@@ -452,7 +458,11 @@ def d_to_tth(self):
452458
"""
453459
d = np.asarray(self.on_d[0])
454460
wavelength = float(self.wavelength)
455-
pre_factor = np.where(d != 0, wavelength / (2 * d), 1)
461+
pre_factor = wavelength / (2 * d)
462+
if np.any(np.abs(pre_factor) > 1):
463+
raise ValueError(
464+
"Invalid input for arcsin: some values exceed the range [-1, 1]. " "Check wavelength or d values."
465+
)
456466
return np.rad2deg(2.0 * np.arcsin(pre_factor))[::-1]
457467

458468
def set_all_arrays(self):

tests/test_diffraction_objects.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,25 +232,40 @@ def test_diffraction_objects_equality(inputs1, inputs2, expected):
232232

233233

234234
def test_q_to_tth():
235+
# valid q values including edge cases when q=0 or 1, expected tth values are 2 * arcsin(q)
235236
actual = Diffraction_object(wavelength=4 * np.pi)
236-
setattr(actual, "on_q", [[0, 0.2, 0.4, 0.6, 0.8, 1, 40, 60], [1, 2, 3, 4, 5, 6, 7, 8]])
237+
setattr(actual, "on_q", [[0, 0.2, 0.4, 0.6, 0.8, 1], [1, 2, 3, 4, 5, 6]])
237238
actual_tth = actual.q_to_tth()
238-
# expected tth values are 2 * arcsin(q)
239-
# when q gets large, we set tth = 180
240-
# we allow q to exceed QMAX for user inputs
241-
expected_tth = [0, 23.07392, 47.15636, 73.73980, 106.26020, 180, 180, 180]
239+
expected_tth = [0, 23.07392, 47.15636, 73.73980, 106.26020, 180]
242240
assert np.allclose(actual_tth, expected_tth)
243241

244242

243+
def test_q_to_tth_bad():
244+
# invalid q values when arcsin value is not in the range of [-1, 1]
245+
actual = Diffraction_object(wavelength=4 * np.pi)
246+
setattr(actual, "on_q", [[0.6, 0.8, 1, 1.2], [1, 2, 3, 4]])
247+
with pytest.raises(ValueError):
248+
actual.q_to_tth()
249+
250+
245251
def test_tth_to_q():
252+
# valid tth values including edge cases when tth=0 or 180 degree,
253+
# expected q vales are sin15, sin30, sin45, sin60, sin90
246254
actual = Diffraction_object(wavelength=4 * np.pi)
247255
setattr(actual, "on_tth", [[0, 30, 60, 90, 120, 180], [1, 2, 3, 4, 5, 6]])
248256
actual_q = actual.tth_to_q()
249-
# expected q vales are sin15, sin30, sin45, sin60, sin90
250257
expected_q = [0, 0.258819, 0.5, 0.707107, 0.866025, 1]
251258
assert np.allclose(actual_q, expected_q)
252259

253260

261+
def test_tth_to_q_bad():
262+
# invalid tth values > 180 degree
263+
actual = Diffraction_object(wavelength=4 * np.pi)
264+
setattr(actual, "on_tth", [[0, 30, 60, 90, 120, 181], [1, 2, 3, 4, 5, 6]])
265+
with pytest.raises(ValueError):
266+
actual.tth_to_q()
267+
268+
254269
def test_q_to_d():
255270
actual = Diffraction_object()
256271
setattr(actual, "on_q", [[0, np.pi, 2 * np.pi, 3 * np.pi, 4 * np.pi, 5 * np.pi], [1, 2, 3, 4, 5, 6]])
@@ -270,14 +285,23 @@ def test_d_to_q():
270285

271286

272287
def test_tth_to_d():
288+
# valid tth values including edge cases when tth=0 or 180 degree,
289+
# expected d values are DMAX=100, 1/sin15, 1/sin30, 1/sin45, 1/sin60, 1/sin90, in reverse order
273290
actual = Diffraction_object(wavelength=2)
274291
setattr(actual, "on_tth", [[0, 30, 60, 90, 120, 180], [1, 2, 3, 4, 5, 6]])
275292
actual_d = actual.tth_to_d()
276-
# expected d values are DMAX=100, 1/sin15, 1/sin30, 1/sin45, 1/sin60, 1/sin90, in reverse order
277293
expected_d = [1, 1.1547, 1.41421, 2, 3.8637, 100]
278294
assert np.allclose(actual_d, expected_d)
279295

280296

297+
def test_tth_to_d_bad():
298+
# invalid tth values > 180 degree
299+
actual = Diffraction_object(wavelength=2)
300+
setattr(actual, "on_tth", [[0, 30, 60, 90, 120, 181], [1, 2, 3, 4, 5, 6]])
301+
with pytest.raises(ValueError):
302+
actual.tth_to_d()
303+
304+
281305
def test_d_to_tth():
282306
actual = Diffraction_object(wavelength=2)
283307
setattr(actual, "on_d", [[0, 2, 4, 6, 8, 100, 200], [1, 2, 3, 4, 5, 6, 7]])
@@ -289,6 +313,15 @@ def test_d_to_tth():
289313
assert np.allclose(actual_tth, expected_tth)
290314

291315

316+
def test_d_to_tth_bad():
317+
# invalid d values when arcsin value is not in the range of [-1, 1]
318+
actual = Diffraction_object(wavelength=2)
319+
setattr(actual, "on_d", [[0, 10, 20, 30], [1, 2, 3, 4]])
320+
with pytest.raises(ValueError):
321+
actual.d_to_tth()
322+
323+
324+
# Inputs cover a good valid range and provide the same expected values, ensuring conversion precision.
292325
params_array = [
293326
(["tth", "on_tth", [30, 60, 90, 120, 150], [1, 2, 3, 4, 5]]),
294327
(["q", "on_q", [1.626208, 3.141593, 4.442883, 5.441398, 6.069091], [1, 2, 3, 4, 5]]),

0 commit comments

Comments
 (0)