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

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

Catch error when incorrect number of intensity/error points in file

  • Property mode set to 100644
File size: 5.3 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: nUseRec - number of lines of user content following this line
16# 5 - 5+nUseRec: 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 formatted
37        """
38        file_handle = open(self.data_path, 'r')
39        file_buffer = file_handle.read()
40        all_lines = file_buffer.splitlines()
41
42        # Load num_points line-by-line from lines into a numpy array, starting
43        # on line number start_line
44        def _load_points(lines, start_line, num_points):
45            qs = np.zeros(num_points)
46            n = start_line
47            filled = 0
48            while filled < num_points:
49                row = np.fromstring(lines[n], dtype=np.float32, sep=' ')
50                qs[filled:filled+len(row)] = row
51                filled += len(row)
52                n += 1
53            return n, qs
54
55        current_line = 4
56        try:
57            # Skip nUseRec lines
58            nUseRec = int(all_lines[current_line].strip()[0])
59            current_line += nUseRec + 1
60            # Read qx data
61            num_qs = int(all_lines[current_line].strip())
62            current_line += 1
63            current_line, qx = _load_points(all_lines, current_line, num_qs)
64
65            # Read qy data
66            num_qs = int(all_lines[current_line].strip())
67            current_line += 1
68            current_line, qy = _load_points(all_lines, current_line, num_qs)
69        except ValueError as e:
70            err_msg = "File incorrectly formatted.\n"
71            if str(e).find('broadcast') != -1:
72                err_msg += "Incorrect number of q data points provided. "
73                err_msg += "Expected {}.".format(num_qs)
74            elif str(e).find('invalid literal') != -1:
75                err_msg += "Expected integer on line {}. Instead got '{}'".format(current_line + 1,
76                    all_lines[current_line])
77            else:
78                err_msg += str(e)
79            raise ValueError(err_msg)
80
81        # dimensions: [width, height, scale]
82        try:
83            dimensions = np.fromstring(all_lines[current_line], dtype=np.float32, sep=' ')
84            if len(dimensions) != 3: raise ValueError()
85            width = int(dimensions[0])
86            height = int(dimensions[1])
87        except ValueError as e:
88            err_msg = "File incorrectly formatted.\n"
89            err_msg += "Expected line {} to be of the form: <num_qx> <num_qy> <scale>.".format(current_line + 1)
90            err_msg += " Instead got '{}'.".format(all_lines[current_line])
91            raise ValueError(err_msg)
92
93        if width > len(qx) or height > len(qy):
94            err_msg = "File incorrectly formatted.\n"
95            err_msg += ("Line {} says to use {}x{} points. "
96                "Only {}x{} provided.").format(current_line + 1, width, height,
97                len(qx), len(qy))
98            raise ValueError(err_msg)
99
100        # More qx and/or qy points can be provided than are actually used
101        qx = qx[:width]
102        qy = qy[:height]
103
104        current_line += 1
105        # iflag = 1 => Only intensity data (not dealt with here)
106        # iflag = 2 => q axis and intensity data
107        # iflag = 3 => q axis, intensity and error data
108        try:
109            iflag = int(all_lines[current_line].strip()[0])
110            if iflag <= 0 or iflag > 3: raise ValueError()
111        except:
112            err_msg = "File incorrectly formatted.\n"
113            iflag = all_lines[current_line].strip()[0]
114            err_msg += "Expected iflag on line {} to be 1, 2 or 3. Instead got '{}'.".format(current_line+1, iflag)
115            raise ValueError(err_msg)
116
117        current_line += 1
118
119        try:
120            current_line, I = _load_points(all_lines, current_line, width*height)
121            dI = np.zeros(width*height)
122
123            # Load error data if it's provided
124            if iflag == 3:
125                _, dI = _load_points(all_lines, current_line, width*height)
126        except Exception as e:
127            err_msg = "File incorrectly formatted.\n"
128            if str(e).find("list index") != -1:
129                err_msg += ("Incorrect number of data points. Expected {} intensity").format(width*height)
130                if iflag == 3:
131                    err_msg += " and error"
132                err_msg += " points."
133            else:
134                err_msg += str(e)
135            raise ValueError(err_msg)
136
137        # Format data for use with Data2D
138        qx = list(qx) * height
139        qy = np.array([[y] * width for y in qy]).flatten()
140
141        data = Data2D(qx_data=qx, qy_data=qy, data=I, err_data=dI)
142
143        return data
Note: See TracBrowser for help on using the repository browser.