source: sasview/src/sas/sascalc/dataloader/readers/danse_reader.py @ 5a405bd

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalcmagnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 5a405bd was a78a02f, checked in by krzywon, 7 years ago

Make suggested changes for unit test fixes.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1"""
2    DANSE/SANS file reader
3"""
4############################################################################
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#If you use DANSE applications to do scientific research that leads to
9#publication, we ask that you acknowledge the use of the software with the
10#following sentence:
11#This work benefited from DANSE software developed under NSF award DMR-0520547.
12#copyright 2008, University of Tennessee
13#############################################################################
14import math
15import os
16import numpy as np
17import logging
18from sas.sascalc.dataloader.data_info import plottable_2D, DataInfo, Detector
19from sas.sascalc.dataloader.manipulations import reader2D_converter
20from sas.sascalc.dataloader.file_reader_base_class import FileReader
21from sas.sascalc.dataloader.loader_exceptions import FileContentsException, DataReaderException
22
23logger = logging.getLogger(__name__)
24
25# Look for unit converter
26has_converter = True
27try:
28    from sas.sascalc.data_util.nxsunit import Converter
29except:
30    has_converter = False
31
32
33class Reader(FileReader):
34    """
35    Example data manipulation
36    """
37    ## File type
38    type_name = "DANSE"
39    ## Wildcards
40    type = ["DANSE files (*.sans)|*.sans"]
41    ## Extension
42    ext  = ['.sans', '.SANS']
43
44    def get_file_contents(self):
45        self.current_datainfo = DataInfo()
46        self.current_dataset = plottable_2D()
47        self.output = []
48
49        loaded_correctly = True
50        error_message = ""
51
52        # defaults
53        # wavelength in Angstrom
54        wavelength = 10.0
55        # Distance in meter
56        distance   = 11.0
57        # Pixel number of center in x
58        center_x   = 65
59        # Pixel number of center in y
60        center_y   = 65
61        # Pixel size [mm]
62        pixel      = 5.0
63        # Size in x, in pixels
64        size_x     = 128
65        # Size in y, in pixels
66        size_y     = 128
67        # Format version
68        fversion   = 1.0
69
70        self.current_datainfo.filename = os.path.basename(self.f_open.name)
71        detector = Detector()
72        self.current_datainfo.detector.append(detector)
73
74        self.current_dataset.data = np.zeros([size_x, size_y])
75        self.current_dataset.err_data = np.zeros([size_x, size_y])
76
77        read_on = True
78        data_start_line = 1
79        while read_on:
80            line = self.f_open.readline()
81            data_start_line += 1
82            if line.find("DATA:") >= 0:
83                read_on = False
84                break
85            toks = line.split(':')
86            try:
87                if toks[0] == "FORMATVERSION":
88                    fversion = float(toks[1])
89                elif toks[0] == "WAVELENGTH":
90                    wavelength = float(toks[1])
91                elif toks[0] == "DISTANCE":
92                    distance = float(toks[1])
93                elif toks[0] == "CENTER_X":
94                    center_x = float(toks[1])
95                elif toks[0] == "CENTER_Y":
96                    center_y = float(toks[1])
97                elif toks[0] == "PIXELSIZE":
98                    pixel = float(toks[1])
99                elif toks[0] == "SIZE_X":
100                    size_x = int(toks[1])
101                elif toks[0] == "SIZE_Y":
102                    size_y = int(toks[1])
103            except ValueError as e:
104                error_message += "Unable to parse {}. Default value used.\n".format(toks[0])
105                loaded_correctly = False
106
107        # Read the data
108        data = []
109        error = []
110        if not fversion >= 1.0:
111            msg = "danse_reader can't read this file {}".format(self.f_open.name)
112            raise FileContentsException(msg)
113
114        for line_num, data_str in enumerate(self.f_open.readlines()):
115            toks = data_str.split()
116            try:
117                val = float(toks[0])
118                err = float(toks[1])
119                data.append(val)
120                error.append(err)
121            except ValueError as exc:
122                msg = "Unable to parse line {}: {}".format(line_num + data_start_line, data_str.strip())
123                raise FileContentsException(msg)
124
125        num_pts = size_x * size_y
126        if len(data) < num_pts:
127            msg = "Not enough data points provided. Expected {} but got {}".format(
128                size_x * size_y, len(data))
129            raise FileContentsException(msg)
130        elif len(data) > num_pts:
131            error_message += ("Too many data points provided. Expected {0} but"
132                " got {1}. Only the first {0} will be used.\n").format(num_pts, len(data))
133            loaded_correctly = False
134            data = data[:num_pts]
135            error = error[:num_pts]
136
137        # Qx and Qy vectors
138        theta = pixel / distance / 100.0
139        i_x = np.arange(size_x)
140        theta = (i_x - center_x + 1) * pixel / distance / 100.0
141        x_vals = 4.0 * np.pi / wavelength * np.sin(theta / 2.0)
142        xmin = x_vals.min()
143        xmax = x_vals.max()
144
145        i_y = np.arange(size_y)
146        theta = (i_y - center_y + 1) * pixel / distance / 100.0
147        y_vals = 4.0 * np.pi / wavelength * np.sin(theta / 2.0)
148        ymin = y_vals.min()
149        ymax = y_vals.max()
150
151        self.current_dataset.data = np.array(data, dtype=np.float64).reshape((size_y, size_x))
152        if fversion > 1.0:
153            self.current_dataset.err_data = np.array(error, dtype=np.float64).reshape((size_y, size_x))
154
155        # Store all data
156        # Store wavelength
157        if has_converter == True and self.current_datainfo.source.wavelength_unit != 'A':
158            conv = Converter('A')
159            wavelength = conv(wavelength,
160                              units=self.current_datainfo.source.wavelength_unit)
161        self.current_datainfo.source.wavelength = wavelength
162
163        # Store distance
164        if has_converter == True and detector.distance_unit != 'm':
165            conv = Converter('m')
166            distance = conv(distance, units=detector.distance_unit)
167        detector.distance = distance
168
169        # Store pixel size
170        if has_converter == True and detector.pixel_size_unit != 'mm':
171            conv = Converter('mm')
172            pixel = conv(pixel, units=detector.pixel_size_unit)
173        detector.pixel_size.x = pixel
174        detector.pixel_size.y = pixel
175
176        # Store beam center in distance units
177        detector.beam_center.x = center_x * pixel
178        detector.beam_center.y = center_y * pixel
179
180
181        self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}')
182        self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}')
183        self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}")
184
185        self.current_dataset.x_bins = x_vals
186        self.current_dataset.y_bins = y_vals
187
188        # Reshape data
189        x_vals = np.tile(x_vals, (size_y, 1)).flatten()
190        y_vals = np.tile(y_vals, (size_x, 1)).T.flatten()
191        if (np.all(self.current_dataset.err_data == None)
192                or np.any(self.current_dataset.err_data <= 0)):
193            new_err_data = np.sqrt(np.abs(self.current_dataset.data))
194        else:
195            new_err_data = self.current_dataset.err_data.flatten()
196
197        self.current_dataset.err_data = new_err_data
198        self.current_dataset.qx_data = x_vals
199        self.current_dataset.qy_data = y_vals
200        self.current_dataset.q_data = np.sqrt(x_vals**2 + y_vals**2)
201        self.current_dataset.mask = np.ones(len(x_vals), dtype=bool)
202
203        # Store loading process information
204        self.current_datainfo.meta_data['loader'] = self.type_name
205
206        self.send_to_output()
207
208        if not loaded_correctly:
209            raise DataReaderException(error_message)
Note: See TracBrowser for help on using the repository browser.