source: sasview/src/sas/sascalc/calculator/instrument.py @ 44a698c

ESS_GUI_sync_sascalc
Last change on this file since 44a698c was 44a698c, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 5 years ago

Cherry-picked changes from py37-sascalc branch.

  • Property mode set to 100644
File size: 10.0 KB
Line 
1"""
2This module is a small tool to allow user to
3control instrumental parameters
4"""
5import numpy as np
6
7# defaults in cgs unit
8_SAMPLE_A_SIZE = [1.27]
9_SOURCE_A_SIZE = [3.81]
10_SAMPLE_DISTANCE = [1627, 0]
11_SAMPLE_OFFSET = [0, 0]
12_SAMPLE_SIZE = [2.54]
13_SAMPLE_THICKNESS = 0.2
14_D_DISTANCE = [1000, 0]
15_D_SIZE = [128, 128]
16_D_PIX_SIZE = [0.5, 0.5]
17
18_MIN = 0.0
19_MAX = 50.0
20_INTENSITY = 368428
21_WAVE_LENGTH = 6.0
22_WAVE_SPREAD = 0.125
23_MASS = 1.67492729E-24  # [gr]
24_LAMBDA_ARRAY = [[0, 1e+16], [_INTENSITY, _INTENSITY]]
25
26
27class Aperture(object):
28    """
29    An object class that defines the aperture variables
30    """
31    def __init__(self):
32
33        # assumes that all aligned at the centers
34        # aperture_size [diameter] for pinhole, [dx, dy] for rectangular
35        self.sample_size = _SAMPLE_A_SIZE
36        self.source_size = _SOURCE_A_SIZE
37        self.sample_distance = _SAMPLE_DISTANCE
38
39    def set_source_size(self, size=[]):
40        """
41        Set the source aperture size
42        """
43        if len(size) == 0:
44            self.source_size = 0.0
45        else:
46            self.source_size = size
47            validate(size[0])
48
49    def set_sample_size(self, size=[]):
50        """
51        Set the sample aperture size
52        """
53        if len(size) == 0:
54            self.sample_size = 0.0
55        else:
56            self.sample_size = size
57            validate(size[0])
58
59    def set_sample_distance(self, distance=[]):
60        """
61        Set the sample aperture distance
62        """
63        if len(distance) == 0:
64            self.sample_distance = 0.0
65        else:
66            self.sample_distance = distance
67            validate(distance[0])
68
69
70class Sample(object):
71    """
72    An object class that defines the sample variables
73    """
74    def __init__(self):
75
76        # assumes that all aligned at the centers
77        # source2sample or sample2detector distance
78        self.distance = _SAMPLE_OFFSET
79        self.size = _SAMPLE_SIZE
80        self.thickness = _SAMPLE_THICKNESS
81
82    def set_size(self, size=[]):
83        """
84        Set the sample size
85        """
86        if len(size) == 0:
87            self.size = 0.0
88        else:
89            self.size = size
90            validate(size[0])
91
92    def set_thickness(self, thickness=0.0):
93        """
94        Set the sample thickness
95        """
96        self.thickness = thickness
97        validate(thickness)
98
99    def set_distance(self, distance=[]):
100        """
101        Set the sample distance
102        """
103        if len(distance) == 0:
104            self.distance = 0.0
105        else:
106            self.distance = distance
107            if distance[0] != 0.0:
108                validate(distance[0])
109
110
111class Detector(object):
112    """
113    An object class that defines the detector variables
114    """
115    def __init__(self):
116
117        # assumes that all aligned at the centers
118        # source2sample or sample2detector distance
119        self.distance = _D_DISTANCE
120        self.size = _D_SIZE
121        self.pix_size = _D_PIX_SIZE
122
123    def set_size(self, size=[]):
124        """
125        Set the detector  size
126        """
127        if len(size) == 0:
128            self.size = 0
129        else:
130            # TODO: Make sure detector size is number of pixels
131            # Could be detector dimensions in e.g., mm, but
132            # the resolution calculator assumes it is pixels.
133            # Being pixels, it has to be integers rather than float
134            self.size = [int(s) for s in size]
135            validate(size[0])
136
137    def set_pix_size(self, size=[]):
138        """
139        Set the detector pix_size
140        """
141        if len(size) == 0:
142            self.pix_size = 0
143        else:
144            self.pix_size = size
145            validate(size[0])
146
147    def set_distance(self, distance=[]):
148        """
149        Set the detector distance
150        """
151        if len(distance) == 0:
152            self.distance = 0
153        else:
154            self.distance = distance
155            validate(distance[0])
156
157
158class Neutron(object):
159    """
160    An object that defines the wavelength variables
161    """
162    def __init__(self):
163
164        # neutron mass in cgs unit
165        self.mass = _MASS
166
167        # wavelength
168        self.wavelength = _WAVE_LENGTH
169        # wavelength spread (FWHM)
170        self.wavelength_spread = _WAVE_SPREAD
171        # wavelength spectrum
172        self.spectrum = self.get_default_spectrum()
173        # intensity in counts/sec
174        self.intensity = np.interp(self.wavelength,
175                                      self.spectrum[0],
176                                      self.spectrum[1],
177                                      0.0,
178                                      0.0)
179        # min max range of the spectrum
180        self.min = min(self.spectrum[0])
181        self.max = max(self.spectrum[0])
182        # wavelength band
183        self.band = [self.min, self.max]
184
185        # default unit of the thickness
186        self.wavelength_unit = 'A'
187
188    def set_full_band(self):
189        """
190        set band to default value
191        """
192        self.band = self.spectrum
193
194    def set_spectrum(self, spectrum):
195        """
196        Set spectrum
197
198        :param spectrum: numpy array
199        """
200        self.spectrum = spectrum
201        self.setup_spectrum()
202
203    def setup_spectrum(self):
204        """
205        To set the wavelength spectrum, and intensity, assumes
206        wavelength is already within the spectrum
207        """
208        spectrum = self.spectrum
209        intensity = np.interp(self.wavelength,
210                                 spectrum[0],
211                                 spectrum[1],
212                                 0.0,
213                                 0.0)
214        self.set_intensity(intensity)
215        # min max range of the spectrum
216        self.min = min(self.spectrum[0])
217        self.max = max(self.spectrum[0])
218        # set default band
219        self.set_band([self.min, self.max])
220
221    def set_band(self, band=[]):
222        """
223        To set the wavelength band
224
225        :param band: array of [min, max]
226        """
227        # check if the wavelength is in range
228        if min(band) < self.min or max(band) > self.max:
229            raise ValueError("band out of range")
230        self.band = band
231
232    def set_intensity(self, intensity=368428):
233        """
234        Sets the intensity in counts/sec
235        """
236        self.intensity = intensity
237        validate(intensity)
238
239    def set_wavelength(self, wavelength=_WAVE_LENGTH):
240        """
241        Sets the wavelength
242        """
243        # check if the wavelength is in range
244        if wavelength < min(self.band) or wavelength > max(self.band):
245            raise ValueError("wavelength out of range")
246        self.wavelength = wavelength
247        validate(wavelength)
248        self.intensity = np.interp(self.wavelength,
249                                      self.spectrum[0],
250                                      self.spectrum[1],
251                                      0.0,
252                                      0.0)
253
254    def set_mass(self, mass=_MASS):
255        """
256        Sets the wavelength
257        """
258        self.mass = mass
259        validate(mass)
260
261    def set_wavelength_spread(self, spread=_WAVE_SPREAD):
262        """
263        Sets the wavelength spread
264        """
265        self.wavelength_spread = spread
266        if spread != 0.0:
267            validate(spread)
268
269    def get_intensity(self):
270        """
271        To get the value of intensity
272        """
273        return self.intensity
274
275    def get_wavelength(self):
276        """
277        To get the value of wavelength
278        """
279        return self.wavelength
280
281    def get_mass(self):
282        """
283        To get the neutron mass
284        """
285        return self.mass
286
287    def get_wavelength_spread(self):
288        """
289        To get the value of wavelength spread
290        """
291        return self.wavelength_spread
292
293    def get_ramdom_value(self):
294        """
295        To get the value of wave length
296        """
297        return self.wavelength
298
299    def get_spectrum(self):
300        """
301        To get the wavelength spectrum
302        """
303        return self.spectrum
304
305    def get_default_spectrum(self):
306        """
307        get default spectrum
308        """
309        return np.array(_LAMBDA_ARRAY)
310
311    def get_band(self):
312        """
313        To get the wavelength band
314        """
315        return self.band
316
317    def plot_spectrum(self):
318        """
319        To plot the wavelength spactrum
320        : requirement: matplotlib.pyplot
321        """
322        try:
323            import matplotlib.pyplot as plt
324            plt.plot(self.spectrum[0], self.spectrum[1], linewidth=2, color='r')
325            plt.legend(['Spectrum'], loc='best')
326            plt.show()
327        except:
328            raise RuntimeError("Can't import matplotlib required to plot...")
329
330
331class TOF(Neutron):
332    """
333    TOF: make list of wavelength and wave length spreads
334    """
335    def __init__(self):
336        """
337        Init
338        """
339        Neutron.__init__(self)
340        #self.switch = switch
341        self.wavelength_list = [self.wavelength]
342        self.wavelength_spread_list = [self.wavelength_spread]
343        self.intensity_list = self.get_intensity_list()
344
345    def get_intensity_list(self):
346        """
347        get list of the intensity wrt wavelength_list
348        """
349        out = np.interp(self.wavelength_list,
350                           self.spectrum[0],
351                           self.spectrum[1],
352                           0.0,
353                           0.0)
354        return out
355
356    def get_wave_list(self):
357        """
358        Get wavelength and wavelength_spread list
359        """
360        return self.wavelength_list, self.wavelength_spread_list
361
362    def set_wave_list(self, wavelength=[]):
363        """
364        Set wavelength list
365
366        :param wavelength: list of wavelengths
367        """
368        self.wavelength_list = wavelength
369
370    def set_wave_spread_list(self, wavelength_spread=[]):
371        """
372        Set wavelength_spread list
373
374        :param wavelength_spread: list of wavelength spreads
375        """
376        self.wavelength_spread_list = wavelength_spread
377
378
379def validate(value=None):
380    """
381    Check if the value is folat > 0.0
382
383    :return value: True / False
384    """
385    try:
386        val = float(value)
387        if val >= 0:
388            val = True
389        else:
390            val = False
391    except:
392        val = False
Note: See TracBrowser for help on using the repository browser.