source: sasview/src/sas/sascalc/dataloader/readers/abs_reader.py @ 0e0c645

ticket-1243
Last change on this file since 0e0c645 was d96744de, checked in by Jeff Krzywon <jkrzywon@…>, 6 years ago

Fix for loading USANS data in ABS reader including fixes to unit tests.

  • Property mode set to 100644
File size: 9.2 KB
RevLine 
[959eb01]1"""
[ad92c5a]2    IGOR 1D data reader
[959eb01]3"""
4#####################################################################
[ad92c5a]5# This software was developed by the University of Tennessee as part of the
6# Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
7# project funded by the US National Science Foundation.
8# See the license text in license.txt
9# copyright 2008, University of Tennessee
[959eb01]10######################################################################
11
[ad92c5a]12import logging
[46cf4c9]13
[959eb01]14import numpy as np
[46cf4c9]15
16from sas.sascalc.data_util.nxsunit import Converter
17from ..file_reader_base_class import FileReader
18from ..data_info import DataInfo, plottable_1D, Data1D, Detector
19from ..loader_exceptions import FileContentsException, DefaultReaderException
[ad92c5a]20
21logger = logging.getLogger(__name__)
22
23
24class Reader(FileReader):
[959eb01]25    """
26    Class to load IGOR reduced .ABS files
27    """
[ad92c5a]28    # File type
[959eb01]29    type_name = "IGOR 1D"
[ad92c5a]30    # Wildcards
[a32c19c]31    type = ["IGOR 1D files (*.abs)|*.abs", "IGOR 1D USANS files (*.cor)|*.cor"]
[ad92c5a]32    # List of allowed extensions
[a32c19c]33    ext = ['.abs', '.cor']
[574adc7]34
[ad92c5a]35    def get_file_contents(self):
[574adc7]36        """
[ad92c5a]37        Get the contents of the file
[574adc7]38
[959eb01]39        :raise RuntimeError: when the file can't be opened
40        :raise ValueError: when the length of the data vectors are inconsistent
41        """
[46cf4c9]42        buff = self.readall()
[ad92c5a]43        filepath = self.f_open.name
44        lines = buff.splitlines()
45        self.output = []
46        self.current_datainfo = DataInfo()
47        self.current_datainfo.filename = filepath
48        detector = Detector()
49        data_line = 0
[d96744de]50        x_index = 4
[ad92c5a]51        self.reset_data_list(len(lines))
52        self.current_datainfo.detector.append(detector)
53        self.current_datainfo.filename = filepath
54
55        is_info = False
56        is_center = False
57        is_data_started = False
58
59        base_q_unit = '1/A'
60        base_i_unit = '1/cm'
61        data_conv_q = Converter(base_q_unit)
62        data_conv_i = Converter(base_i_unit)
63
64        for line in lines:
65            # Information line 1
[d96744de]66            if line.find(".bt5") > 0:
67                x_index = 0
[ad92c5a]68            if is_info:
69                is_info = False
70                line_toks = line.split()
71
72                # Wavelength in Angstrom
[959eb01]73                try:
[ad92c5a]74                    value = float(line_toks[1])
[46cf4c9]75                    if self.current_datainfo.source.wavelength_unit != 'A':
[ad92c5a]76                        conv = Converter('A')
77                        self.current_datainfo.source.wavelength = conv(value,
78                            units=self.current_datainfo.source.wavelength_unit)
79                    else:
80                        self.current_datainfo.source.wavelength = value
81                except KeyError:
82                    msg = "ABSReader cannot read wavelength from %s" % filepath
83                    self.current_datainfo.errors.append(msg)
84
85                # Detector distance in meters
86                try:
87                    value = float(line_toks[3])
[46cf4c9]88                    if detector.distance_unit != 'm':
[ad92c5a]89                        conv = Converter('m')
90                        detector.distance = conv(value,
91                                        units=detector.distance_unit)
92                    else:
93                        detector.distance = value
[46cf4c9]94                except Exception:
[ad92c5a]95                    msg = "ABSReader cannot read SDD from %s" % filepath
96                    self.current_datainfo.errors.append(msg)
97
98                # Transmission
99                try:
100                    self.current_datainfo.sample.transmission = \
101                        float(line_toks[4])
102                except ValueError:
103                    # Transmission isn't always in the header
104                    pass
105
106                # Sample thickness in mm
107                try:
[9e6aeaf]108                    # ABS writer adds 'C' with no space to the end of the
109                    # thickness column.  Remove it if it is there before
110                    # converting the thickness.
[1efbc190]111                    if line_toks[5][-1] not in '012345679.':
[9e6aeaf]112                        value = float(line_toks[5][:-1])
113                    else:
114                        value = float(line_toks[5])
[46cf4c9]115                    if self.current_datainfo.sample.thickness_unit != 'cm':
[ad92c5a]116                        conv = Converter('cm')
117                        self.current_datainfo.sample.thickness = conv(value,
118                            units=self.current_datainfo.sample.thickness_unit)
119                    else:
120                        self.current_datainfo.sample.thickness = value
121                except ValueError:
122                    # Thickness is not a mandatory entry
123                    pass
124
125            # MON CNT  LAMBDA  DET ANG  DET DIST  TRANS  THICK  AVE   STEP
126            if line.count("LAMBDA") > 0:
127                is_info = True
128
129            # Find center info line
130            if is_center:
[959eb01]131                is_center = False
[ad92c5a]132                line_toks = line.split()
133                # Center in bin number
134                center_x = float(line_toks[0])
135                center_y = float(line_toks[1])
136
137                # Bin size
[46cf4c9]138                if detector.pixel_size_unit != 'mm':
[ad92c5a]139                    conv = Converter('mm')
140                    detector.pixel_size.x = conv(5.08,
141                                        units=detector.pixel_size_unit)
142                    detector.pixel_size.y = conv(5.08,
143                                        units=detector.pixel_size_unit)
[959eb01]144                else:
[ad92c5a]145                    detector.pixel_size.x = 5.08
146                    detector.pixel_size.y = 5.08
147
148                # Store beam center in distance units
149                # Det 640 x 640 mm
[46cf4c9]150                if detector.beam_center_unit != 'mm':
[ad92c5a]151                    conv = Converter('mm')
152                    detector.beam_center.x = conv(center_x * 5.08,
153                                     units=detector.beam_center_unit)
154                    detector.beam_center.y = conv(center_y * 5.08,
[46cf4c9]155                                     units=detector.beam_center_unit)
[959eb01]156                else:
[ad92c5a]157                    detector.beam_center.x = center_x * 5.08
158                    detector.beam_center.y = center_y * 5.08
159
160                # Detector type
161                try:
162                    detector.name = line_toks[7]
163                except:
164                    # Detector name is not a mandatory entry
165                    pass
166
167            # BCENT(X,Y)  A1(mm)  A2(mm)  A1A2DIST(m)  DL/L  BSTOP(mm)  DET_TYP
168            if line.count("BCENT") > 0:
169                is_center = True
170
171            # Parse the data
172            if is_data_started:
173                toks = line.split()
174
175                try:
[d96744de]176                    _x = float(toks[x_index])
[ad92c5a]177                    _y = float(toks[1])
178                    _dy = float(toks[2])
179                    _dx = float(toks[3])
180
181                    if data_conv_q is not None:
182                        _x = data_conv_q(_x, units=base_q_unit)
183                        _dx = data_conv_q(_dx, units=base_q_unit)
184
185                    if data_conv_i is not None:
186                        _y = data_conv_i(_y, units=base_i_unit)
187                        _dy = data_conv_i(_dy, units=base_i_unit)
188
189                    self.current_dataset.x[data_line] = _x
190                    self.current_dataset.y[data_line] = _y
191                    self.current_dataset.dy[data_line] = _dy
[11112b2]192                    if _dx > 0:
193                        self.current_dataset.dx[data_line] = _dx
194                    else:
195                        if data_line == 0:
196                            self.current_dataset.dx = None
197                            self.current_dataset.dxl = np.zeros(len(lines))
198                            self.current_dataset.dxw = np.zeros(len(lines))
199                        self.current_dataset.dxl[data_line] = abs(_dx)
200                        self.current_dataset.dxw[data_line] = 0
[ad92c5a]201                    data_line += 1
202
203                except ValueError:
204                    # Could not read this data line. If we are here
205                    # it is because we are in the data section. Just
206                    # skip it.
207                    pass
208
[11112b2]209            # SANS Data:
[ad92c5a]210            # The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev.
211            # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor|
[11112b2]212            # USANS Data:
213            # EMP LEVEL: <value> ; BKG LEVEL: <value>
[e3775c6]214            if line.startswith("The 6 columns") or line.startswith("EMP LEVEL"):
[ad92c5a]215                is_data_started = True
216
[7b07fbe]217        self.remove_empty_q_values()
[ad92c5a]218
219        # Sanity check
220        if not len(self.current_dataset.y) == len(self.current_dataset.dy):
221            self.set_all_to_none()
222            msg = "abs_reader: y and dy have different length"
223            raise ValueError(msg)
224        # If the data length is zero, consider this as
225        # though we were not able to read the file.
226        if len(self.current_dataset.x) == 0:
227            self.set_all_to_none()
228            raise ValueError("ascii_reader: could not load file")
229
[3bab401]230        self.current_dataset = self.set_default_1d_units(self.current_dataset)
[ad92c5a]231        if data_conv_q is not None:
232            self.current_dataset.xaxis("\\rm{Q}", base_q_unit)
233        if data_conv_i is not None:
234            self.current_dataset.yaxis("\\rm{Intensity}", base_i_unit)
235
236        # Store loading process information
237        self.current_datainfo.meta_data['loader'] = self.type_name
238        self.send_to_output()
Note: See TracBrowser for help on using the repository browser.