source: sasview/src/sas/sascalc/file_converter/ascii2d_loader.py @ eee94bf

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since eee94bf was dcb91cf, checked in by lewis, 7 years ago

Make suggested changes

  • Property mode set to 100644
File size: 5.8 KB
Line 
1"""
2ASCII 2D Loader
3"""
4from sas.sascalc.dataloader.data_info import Data2D
5from sas.sascalc.file_converter.nxcansas_writer import NXcanSASWriter
6import numpy as np
7
8# ISIS 2D ASCII File Format
9# http://www.isis.stfc.ac.uk/instruments/loq/software/colette-ascii-file-format-descriptions9808.pdf
10# line: property
11# 0: File header
12# 1: q_x axis label and units
13# 2: q_y axis label and units
14# 3: Intensity axis label and units
15# 4: n_use_rec - number of lines of user content following this line
16# 5 to (5+n_use_rec): user content
17# Number of qx points
18# List of qx points
19# Number of qy points
20# List of qy points
21# numqx numqy scale
22
23class ASCII2DLoader(object):
24
25    def __init__(self, data_path):
26        """
27        :param data_path: The path to the file to load
28        """
29        self.data_path = data_path
30
31    def load(self):
32        """
33        Load the data from the file into a Data2D object
34
35        :return: A Data2D instance containing data from the file
36        :raises ValueError: Raises a ValueError if the file is incorrectly
37            formatted
38        """
39        with open(self.data_path, 'r') as file_handle:
40            file_buffer = file_handle.read()
41            all_lines = file_buffer.splitlines()
42
43            # Load num_points line-by-line from lines into a numpy array,
44            # starting on line number start_line
45            def _load_points(lines, start_line, num_points):
46                qs = np.zeros(num_points)
47                n = start_line
48                filled = 0
49                while filled < num_points:
50                    row = np.fromstring(lines[n], dtype=np.float32, sep=' ')
51                    qs[filled:filled+len(row)] = row
52                    filled += len(row)
53                    n += 1
54                return n, qs
55
56            current_line = 4
57            try:
58                # Skip n_use_rec lines
59                n_use_rec = int(all_lines[current_line].strip()[0])
60                current_line += n_use_rec + 1
61                # Read qx data
62                num_qs = int(all_lines[current_line].strip())
63                current_line += 1
64                current_line, qx = _load_points(all_lines, current_line, num_qs)
65
66                # Read qy data
67                num_qs = int(all_lines[current_line].strip())
68                current_line += 1
69                current_line, qy = _load_points(all_lines, current_line, num_qs)
70            except ValueError as e:
71                err_msg = "File incorrectly formatted.\n"
72                if str(e).find('broadcast') != -1:
73                    err_msg += "Incorrect number of q data points provided. "
74                    err_msg += "Expected {}.".format(num_qs)
75                elif str(e).find('invalid literal') != -1:
76                    err_msg += ("Expected integer on line {}. "
77                        "Instead got '{}'").format(current_line + 1,
78                            all_lines[current_line])
79                else:
80                    err_msg += str(e)
81                raise ValueError(err_msg)
82
83            # dimensions: [width, height, scale]
84            try:
85                dimensions = np.fromstring(all_lines[current_line],
86                    dtype=np.float32, sep=' ')
87                if len(dimensions) != 3: raise ValueError()
88                width = int(dimensions[0])
89                height = int(dimensions[1])
90            except ValueError as e:
91                err_msg = "File incorrectly formatted.\n"
92                err_msg += ("Expected line {} to be of the form: <num_qx> "
93                    "<num_qy> <scale>.").format(current_line + 1)
94                err_msg += " Instead got '{}'.".format(all_lines[current_line])
95                raise ValueError(err_msg)
96
97            if width > len(qx) or height > len(qy):
98                err_msg = "File incorrectly formatted.\n"
99                err_msg += ("Line {} says to use {}x{} points. "
100                    "Only {}x{} provided.").format(current_line + 1, width,
101                    height, len(qx), len(qy))
102                raise ValueError(err_msg)
103
104            # More qx and/or qy points can be provided than are actually used
105            qx = qx[:width]
106            qy = qy[:height]
107
108            current_line += 1
109            # iflag = 1 => Only intensity data (not dealt with here)
110            # iflag = 2 => q axis and intensity data
111            # iflag = 3 => q axis, intensity and error data
112            try:
113                iflag = int(all_lines[current_line].strip()[0])
114                if iflag <= 0 or iflag > 3: raise ValueError()
115            except:
116                err_msg = "File incorrectly formatted.\n"
117                iflag = all_lines[current_line].strip()[0]
118                err_msg += ("Expected iflag on line {} to be 1, 2 or 3. "
119                    "Instead got '{}'.").format(current_line+1, iflag)
120                raise ValueError(err_msg)
121
122            current_line += 1
123
124            try:
125                current_line, I = _load_points(all_lines, current_line,
126                    width * height)
127                dI = np.zeros(width*height)
128
129                # Load error data if it's provided
130                if iflag == 3:
131                    _, dI = _load_points(all_lines, current_line, width*height)
132            except Exception as e:
133                err_msg = "File incorrectly formatted.\n"
134                if str(e).find("list index") != -1:
135                    err_msg += ("Incorrect number of data points. Expected {}"
136                        " intensity").format(width * height)
137                    if iflag == 3:
138                        err_msg += " and error"
139                    err_msg += " points."
140                else:
141                    err_msg += str(e)
142                raise ValueError(err_msg)
143
144            # Format data for use with Data2D
145            qx = list(qx) * height
146            qy = np.array([[y] * width for y in qy]).flatten()
147
148            data = Data2D(qx_data=qx, qy_data=qy, data=I, err_data=dI)
149
150        return data
Note: See TracBrowser for help on using the repository browser.