55import numpy as np
66
77from diffpy .utils .tools import get_package_info
8+ from diffpy .utils .transforms import q_to_tth , tth_to_q
89
910QQUANTITIES = ["q" ]
1011ANGLEQUANTITIES = ["angle" , "tth" , "twotheta" , "2theta" ]
1718 "and specifying how to handle the mismatch."
1819)
1920
20- wavelength_warning_emsg = (
21- "INFO: no wavelength has been specified. You can continue "
22- "to use the DiffractionObject but some of its powerful features "
23- "will not be available. To specify a wavelength, set "
24- "diffraction_object.wavelength = [number], "
25- "where diffraction_object is the variable name of you Diffraction Object, "
26- "and number is the wavelength in angstroms."
27- )
28-
29- length_mismatch_emsg = "Please ensure {array_name} array and intensity array are of the same length."
30- non_numeric_value_emsg = "Invalid value found in {array_name} array. Please ensure all values are numeric."
31- invalid_tth_emsg = "Two theta exceeds 180 degrees. Please check the input values for errors."
32- invalid_q_or_wavelength_emsg = (
33- "The supplied q-array and wavelength will result in an impossible two-theta. "
34- "Please check these values and re-instantiate the DiffractionObject with correct values."
35- )
36-
3721
3822class Diffraction_object :
3923 """A class to represent and manipulate data associated with diffraction experiments.
@@ -54,9 +38,9 @@ def __init__(self, name="", wavelength=None):
5438 self .name = name
5539 self .wavelength = wavelength
5640 self .scat_quantity = ""
57- self .on_q = [np .empty (0 ), np .empty (0 )]
58- self .on_tth = [np .empty (0 ), np .empty (0 )]
59- self .on_d = [np .empty (0 ), np .empty (0 )]
41+ self .on_q = np . array ( [np .empty (0 ), np .empty (0 )])
42+ self .on_tth = np . array ( [np .empty (0 ), np .empty (0 )])
43+ self .on_d = np . array ( [np .empty (0 ), np .empty (0 )])
6044 self ._all_arrays = [self .on_q , self .on_tth ]
6145 self .metadata = {}
6246
@@ -311,97 +295,19 @@ def insert_scattering_quantity(
311295 if wavelength is not None :
312296 self .wavelength = wavelength
313297 if xtype .lower () in QQUANTITIES :
314- self .on_q = [ np .array (xarray ), np . array ( yarray )]
298+ self .on_q = np .array ([ xarray , yarray ])
315299 elif xtype .lower () in ANGLEQUANTITIES :
316- self .on_tth = [ np .array (xarray ), np . array ( yarray )]
300+ self .on_tth = np .array ([ xarray , yarray ])
317301 elif xtype .lower () in DQUANTITIES :
318- self .on_tth = [ np .array (xarray ), np . array ( yarray )]
302+ self .on_tth = np .array ([ xarray , yarray ])
319303 self .set_all_arrays ()
320304
321- def q_to_tth (self ):
322- r"""
323- Helper function to convert q to two-theta.
324-
325- By definition the relationship is:
326-
327- .. math::
328-
329- \sin\left(\frac{2\theta}{2}\right) = \frac{\lambda q}{4 \pi}
330-
331- thus
332-
333- .. math::
334-
335- 2\theta_n = 2 \arcsin\left(\frac{\lambda q}{4 \pi}\right)
336-
337- Parameters
338- ----------
339- q : array
340- An array of :math:`q` values
341-
342- wavelength : float
343- Wavelength of the incoming x-rays
344-
345- Function adapted from scikit-beam. Thanks to those developers
346-
347- Returns
348- -------
349- two_theta : array
350- An array of :math:`2\theta` values in radians
351- """
352- q = self .on_q [0 ]
353- q = np .asarray (q )
354- wavelength = float (self .wavelength )
355- pre_factor = wavelength / (4 * np .pi )
356- return np .rad2deg (2.0 * np .arcsin (q * pre_factor ))
357-
358- def tth_to_q (self ):
359- r"""
360- Helper function to convert two-theta to q
361-
362- By definition the relationship is
363-
364- .. math::
365-
366- \sin\left(\frac{2\theta}{2}\right) = \frac{\lambda q}{4 \pi}
367-
368- thus
369-
370- .. math::
371-
372- q = \frac{4 \pi \sin\left(\frac{2\theta}{2}\right)}{\lambda}
373-
374-
375-
376- Parameters
377- ----------
378- two_theta : array
379- An array of :math:`2\theta` values in units of degrees
380-
381- wavelength : float
382- Wavelength of the incoming x-rays
383-
384- Function adapted from scikit-beam. Thanks to those developers.
385-
386- Returns
387- -------
388- q : array
389- An array of :math:`q` values in the inverse of the units
390- of ``wavelength``
391- """
392- two_theta = np .asarray (np .deg2rad (self .on_tth [0 ]))
393- wavelength = float (self .wavelength )
394- pre_factor = (4 * np .pi ) / wavelength
395- return pre_factor * np .sin (two_theta / 2 )
396-
397305 def set_all_arrays (self ):
398306 master_array , xtype = self ._get_original_array ()
399307 if xtype == "q" :
400- self .on_tth [0 ] = self .q_to_tth ()
401- self .on_tth [1 ] = master_array [1 ]
402- if xtype == "tth" :
403- self .on_q [0 ] = self .tth_to_q ()
404- self .on_q [1 ] = master_array [1 ]
308+ self .on_tth = q_to_tth (self .on_q , self .wavelength )
309+ elif xtype == "tth" :
310+ self .on_q = tth_to_q (self .on_tth , self .wavelength )
405311 self .tthmin = self .on_tth [0 ][0 ]
406312 self .tthmax = self .on_tth [0 ][- 1 ]
407313 self .qmin = self .on_q [0 ][0 ]
@@ -500,9 +406,9 @@ def __init__(self, name="", wavelength=None):
500406 self .name = name
501407 self .wavelength = wavelength
502408 self .scat_quantity = ""
503- self .on_q = [ np .empty (0 ), np .empty ( 0 )]
504- self .on_tth = [ np .empty (0 ), np .empty ( 0 )]
505- self .on_d = [ np .empty (0 ), np .empty ( 0 )]
409+ self .on_q = np .empty (( 2 , 0 ), dtype = np .float64 )
410+ self .on_tth = np .empty (( 2 , 0 ), dtype = np .float64 )
411+ self .on_d = np .empty (( 2 , 0 ), dtype = np .float64 )
506412 self ._all_arrays = [self .on_q , self .on_tth ]
507413 self .metadata = {}
508414
@@ -757,115 +663,19 @@ def insert_scattering_quantity(
757663 if wavelength is not None :
758664 self .wavelength = wavelength
759665 if xtype .lower () in QQUANTITIES :
760- self .on_q = [ np .array (xarray ), np . array ( yarray )]
666+ self .on_q = np .array ([ xarray , yarray ])
761667 elif xtype .lower () in ANGLEQUANTITIES :
762- self .on_tth = [ np .array (xarray ), np . array ( yarray )]
763- elif xtype .lower () in DQUANTITIES :
764- self .on_tth = [ np .array (xarray ), np . array ( yarray )]
668+ self .on_tth = np .array ([ xarray , yarray ])
669+ elif xtype .lower () in DQUANTITIES : # Fixme when d is implemented. This here as a placeholder
670+ self .on_tth = np .array ([ xarray , yarray ])
765671 self .set_all_arrays ()
766672
767- def q_to_tth (self ):
768- r"""
769- Helper function to convert q to two-theta.
770-
771- By definition the relationship is:
772-
773- .. math::
774-
775- \sin\left(\frac{2\theta}{2}\right) = \frac{\lambda q}{4 \pi}
776-
777- thus
778-
779- .. math::
780-
781- 2\theta_n = 2 \arcsin\left(\frac{\lambda q}{4 \pi}\right)
782-
783- Function adapted from scikit-beam. Thanks to those developers
784-
785- Parameters
786- ----------
787- q : array
788- The array of :math:`q` values
789-
790- wavelength : float
791- Wavelength of the incoming x-rays
792-
793- Returns
794- -------
795- two_theta : array
796- The array of :math:`2\theta` values in radians
797- """
798- for i , value in enumerate (self .on_q [0 ]):
799- if not isinstance (value , (int , float )):
800- raise TypeError (non_numeric_value_emsg .format (array_name = "q" ))
801- if len (self .on_q [0 ]) != len (self .on_q [1 ]):
802- raise RuntimeError (length_mismatch_emsg .format (array_name = "q" ))
803- if self .wavelength is None :
804- warnings .warn (wavelength_warning_emsg , UserWarning )
805- return np .empty (0 )
806- q = self .on_q [0 ]
807- q = np .asarray (q )
808- wavelength = float (self .wavelength )
809- pre_factor = wavelength / (4 * np .pi )
810- if np .any (np .abs (q * pre_factor ) > 1 ):
811- raise ValueError (invalid_q_or_wavelength_emsg )
812- return np .rad2deg (2.0 * np .arcsin (q * pre_factor ))
813-
814- def tth_to_q (self ):
815- r"""
816- Helper function to convert two-theta to q
817-
818- By definition the relationship is
819-
820- .. math::
821-
822- \sin\left(\frac{2\theta}{2}\right) = \frac{\lambda q}{4 \pi}
823-
824- thus
825-
826- .. math::
827-
828- q = \frac{4 \pi \sin\left(\frac{2\theta}{2}\right)}{\lambda}
829-
830- Function adapted from scikit-beam. Thanks to those developers.
831-
832- Parameters
833- ----------
834- two_theta : array
835- The array of :math:`2\theta` values in units of degrees
836-
837- wavelength : float
838- Wavelength of the incoming x-rays
839-
840- Returns
841- -------
842- q : array
843- The array of :math:`q` values in the inverse of the units
844- of ``wavelength``
845- """
846- for i , value in enumerate (self .on_tth [0 ]):
847- if not isinstance (value , (int , float )):
848- raise TypeError (non_numeric_value_emsg .format (array_name = "two theta" ))
849- if len (self .on_tth [0 ]) != len (self .on_tth [1 ]):
850- raise RuntimeError (length_mismatch_emsg .format (array_name = "two theta" ))
851- two_theta = np .asarray (np .deg2rad (self .on_tth [0 ]))
852- if np .any (two_theta > np .pi ):
853- raise ValueError (invalid_tth_emsg )
854- if self .wavelength is None :
855- warnings .warn (wavelength_warning_emsg , UserWarning )
856- return np .empty (0 )
857- wavelength = float (self .wavelength )
858- pre_factor = (4 * np .pi ) / wavelength
859- return pre_factor * np .sin (two_theta / 2 )
860-
861673 def set_all_arrays (self ):
862674 master_array , xtype = self ._get_original_array ()
863675 if xtype == "q" :
864- self .on_tth [0 ] = self .q_to_tth ()
865- self .on_tth [1 ] = master_array [1 ]
866- if xtype == "tth" :
867- self .on_q [0 ] = self .tth_to_q ()
868- self .on_q [1 ] = master_array [1 ]
676+ self .on_tth = q_to_tth (self .on_q , self .wavelength )
677+ elif xtype == "tth" :
678+ self .on_q = tth_to_q (self .on_tth , self .wavelength )
869679 self .tthmin = self .on_tth [0 ][0 ]
870680 self .tthmax = self .on_tth [0 ][- 1 ]
871681 self .qmin = self .on_q [0 ][0 ]
0 commit comments