Source code for sas.sascalc.calculator.instrument

"""
This module is a small tool to allow user to
control instrumental parameters
"""
import numpy as np

# defaults in cgs unit
_SAMPLE_A_SIZE = [1.27]
_SOURCE_A_SIZE = [3.81]
_SAMPLE_DISTANCE = [1627, 0]
_SAMPLE_OFFSET = [0, 0]
_SAMPLE_SIZE = [2.54]
_SAMPLE_THICKNESS = 0.2
_D_DISTANCE = [1000, 0]
_D_SIZE = [128, 128]
_D_PIX_SIZE = [0.5, 0.5]

_MIN = 0.0
_MAX = 50.0
_INTENSITY = 368428
_WAVE_LENGTH = 6.0
_WAVE_SPREAD = 0.125
_MASS = 1.67492729E-24  # [gr]
_LAMBDA_ARRAY = [[0, 1e+16], [_INTENSITY, _INTENSITY]]


[docs]class Aperture(object): """ An object class that defines the aperture variables """
[docs] def __init__(self): # assumes that all aligned at the centers # aperture_size [diameter] for pinhole, [dx, dy] for rectangular self.sample_size = _SAMPLE_A_SIZE self.source_size = _SOURCE_A_SIZE self.sample_distance = _SAMPLE_DISTANCE
[docs] def set_source_size(self, size=[]): """ Set the source aperture size """ if len(size) == 0: self.source_size = 0.0 else: self.source_size = size validate(size[0])
[docs] def set_sample_size(self, size=[]): """ Set the sample aperture size """ if len(size) == 0: self.sample_size = 0.0 else: self.sample_size = size validate(size[0])
[docs] def set_sample_distance(self, distance=[]): """ Set the sample aperture distance """ if len(distance) == 0: self.sample_distance = 0.0 else: self.sample_distance = distance validate(distance[0])
[docs]class Sample(object): """ An object class that defines the sample variables """
[docs] def __init__(self): # assumes that all aligned at the centers # source2sample or sample2detector distance self.distance = _SAMPLE_OFFSET self.size = _SAMPLE_SIZE self.thickness = _SAMPLE_THICKNESS
[docs] def set_size(self, size=[]): """ Set the sample size """ if len(size) == 0: self.size = 0.0 else: self.size = size validate(size[0])
[docs] def set_thickness(self, thickness=0.0): """ Set the sample thickness """ self.thickness = thickness validate(thickness)
[docs] def set_distance(self, distance=[]): """ Set the sample distance """ if len(distance) == 0: self.distance = 0.0 else: self.distance = distance if distance[0] != 0.0: validate(distance[0])
[docs]class Detector(object): """ An object class that defines the detector variables """
[docs] def __init__(self): # assumes that all aligned at the centers # source2sample or sample2detector distance self.distance = _D_DISTANCE self.size = _D_SIZE self.pix_size = _D_PIX_SIZE
[docs] def set_size(self, size=[]): """ Set the detector size """ if len(size) == 0: self.size = 0 else: # TODO: Make sure detector size is number of pixels # Could be detector dimensions in e.g., mm, but # the resolution calculator assumes it is pixels. # Being pixels, it has to be integers rather than float self.size = [int(s) for s in size] validate(size[0])
[docs] def set_pix_size(self, size=[]): """ Set the detector pix_size """ if len(size) == 0: self.pix_size = 0 else: self.pix_size = size validate(size[0])
[docs] def set_distance(self, distance=[]): """ Set the detector distance """ if len(distance) == 0: self.distance = 0 else: self.distance = distance validate(distance[0])
[docs]class Neutron(object): """ An object that defines the wavelength variables """
[docs] def __init__(self): # neutron mass in cgs unit self.mass = _MASS # wavelength self.wavelength = _WAVE_LENGTH # wavelength spread (FWHM) self.wavelength_spread = _WAVE_SPREAD # wavelength spectrum self.spectrum = self.get_default_spectrum() # intensity in counts/sec self.intensity = np.interp(self.wavelength, self.spectrum[0], self.spectrum[1], 0.0, 0.0) # min max range of the spectrum self.min = min(self.spectrum[0]) self.max = max(self.spectrum[0]) # wavelength band self.band = [self.min, self.max] # default unit of the thickness self.wavelength_unit = 'A'
[docs] def set_full_band(self): """ set band to default value """ self.band = self.spectrum
[docs] def set_spectrum(self, spectrum): """ Set spectrum :param spectrum: numpy array """ self.spectrum = spectrum self.setup_spectrum()
[docs] def setup_spectrum(self): """ To set the wavelength spectrum, and intensity, assumes wavelength is already within the spectrum """ spectrum = self.spectrum intensity = np.interp(self.wavelength, spectrum[0], spectrum[1], 0.0, 0.0) self.set_intensity(intensity) # min max range of the spectrum self.min = min(self.spectrum[0]) self.max = max(self.spectrum[0]) # set default band self.set_band([self.min, self.max])
[docs] def set_band(self, band=[]): """ To set the wavelength band :param band: array of [min, max] """ # check if the wavelength is in range if min(band) < self.min or max(band) > self.max: raise ValueError("band out of range") self.band = band
[docs] def set_intensity(self, intensity=368428): """ Sets the intensity in counts/sec """ self.intensity = intensity validate(intensity)
[docs] def set_wavelength(self, wavelength=_WAVE_LENGTH): """ Sets the wavelength """ # check if the wavelength is in range if wavelength < min(self.band) or wavelength > max(self.band): raise ValueError("wavelength out of range") self.wavelength = wavelength validate(wavelength) self.intensity = np.interp(self.wavelength, self.spectrum[0], self.spectrum[1], 0.0, 0.0)
[docs] def set_mass(self, mass=_MASS): """ Sets the wavelength """ self.mass = mass validate(mass)
[docs] def set_wavelength_spread(self, spread=_WAVE_SPREAD): """ Sets the wavelength spread """ self.wavelength_spread = spread if spread != 0.0: validate(spread)
[docs] def get_intensity(self): """ To get the value of intensity """ return self.intensity
[docs] def get_wavelength(self): """ To get the value of wavelength """ return self.wavelength
[docs] def get_mass(self): """ To get the neutron mass """ return self.mass
[docs] def get_wavelength_spread(self): """ To get the value of wavelength spread """ return self.wavelength_spread
[docs] def get_ramdom_value(self): """ To get the value of wave length """ return self.wavelength
[docs] def get_spectrum(self): """ To get the wavelength spectrum """ return self.spectrum
[docs] def get_default_spectrum(self): """ get default spectrum """ return np.array(_LAMBDA_ARRAY)
[docs] def get_band(self): """ To get the wavelength band """ return self.band
[docs] def plot_spectrum(self): """ To plot the wavelength spactrum : requirement: matplotlib.pyplot """ try: import matplotlib.pyplot as plt plt.plot(self.spectrum[0], self.spectrum[1], linewidth=2, color='r') plt.legend(['Spectrum'], loc='best') plt.show() except: raise RuntimeError("Can't import matplotlib required to plot...")
[docs]class TOF(Neutron): """ TOF: make list of wavelength and wave length spreads """
[docs] def __init__(self): """ Init """ Neutron.__init__(self) #self.switch = switch self.wavelength_list = [self.wavelength] self.wavelength_spread_list = [self.wavelength_spread] self.intensity_list = self.get_intensity_list()
[docs] def get_intensity_list(self): """ get list of the intensity wrt wavelength_list """ out = np.interp(self.wavelength_list, self.spectrum[0], self.spectrum[1], 0.0, 0.0) return out
[docs] def get_wave_list(self): """ Get wavelength and wavelength_spread list """ return self.wavelength_list, self.wavelength_spread_list
[docs] def set_wave_list(self, wavelength=[]): """ Set wavelength list :param wavelength: list of wavelengths """ self.wavelength_list = wavelength
[docs] def set_wave_spread_list(self, wavelength_spread=[]): """ Set wavelength_spread list :param wavelength_spread: list of wavelength spreads """ self.wavelength_spread_list = wavelength_spread
[docs]def validate(value=None): """ Check if the value is folat > 0.0 :return value: True / False """ try: val = float(value) if val >= 0: val = True else: val = False except: val = False