source: sasview/src/sas/sascalc/file_converter/bsl_loader.py @ 4139147

Last change on this file since 4139147 was f00691d4, checked in by lewis, 8 years ago

Correctly set BSL Q-axis units

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[18e7309]1from sas.sascalc.file_converter.core.bsl_loader import CLoader
[fe498b83]2from sas.sascalc.dataloader.data_info import Data2D
[6eaf89ea]3from copy import deepcopy
4import os
[2760662]5import numpy as np
[18e7309]6
[9c500ab]7class BSLParsingError(Exception):
8    pass
9
[18e7309]10class BSLLoader(CLoader):
[9c500ab]11    """
12    Loads 2D SAS data from a BSL file.
13    CLoader is a C extension (found in c_ext/bsl_loader.c)
14
15    See http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html
16    for more info on the BSL file format.
17    """
[18e7309]18
[535e181]19    def __init__(self, filename):
[9c500ab]20        """
21        Parses the BSL header file and sets instance variables apropriately
22
23        :param filename: Path to the BSL header file
24        """
[6eaf89ea]25        header_file = open(filename, 'r')
26        data_info = {}
27        is_valid = True
28        err_msg = ""
[18e7309]29
[6eaf89ea]30        [folder, filename] = os.path.split(filename)
[9c500ab]31        # SAS data will be in file Xnn001.mdd
32        sasdata_filename = filename.replace('000.', '001.')
33        if sasdata_filename == filename:
[dc8a553]34            err_msg = ("Invalid header filename {}.\nShould be of the format "
[9c500ab]35                "Xnn000.XXX where X is any alphanumeric character and n is any"
36                " digit.").format(filename)
37            raise BSLParsingError(err_msg)
[6eaf89ea]38
39        # First 2 lines are headers
40        header_file.readline()
41        header_file.readline()
42
43        while True:
44            metadata = header_file.readline().strip()
45            metadata = metadata.split()
46            data_filename = header_file.readline().strip()
47
48            if len(metadata) != 10:
49                is_valid = False
50                err_msg = "Invalid header file: {}".format(filename)
51                break
[9c500ab]52
53            if data_filename != sasdata_filename:
54                last_file = (metadata[9] == '0')
55                if last_file: # Reached last file we have metadata for
56                    is_valid = False
57                    err_msg = "No metadata for {} found in header file: {}"
58                    err_msg = err_msg.format(sasdata_filename, filename)
59                    break
[6eaf89ea]60                continue
61            try:
62                data_info = {
63                    'filename': os.path.join(folder, data_filename),
64                    'pixels': int(metadata[0]),
65                    'rasters': int(metadata[1]),
66                    'frames': int(metadata[2]),
67                    'swap_bytes': int(metadata[3])
68                }
69            except:
70                is_valid = False
[c3f0114]71                err_msg = "Invalid metadata in header file for {}"
[9c500ab]72                err_msg = err_msg.format(sasdata_filename)
[6eaf89ea]73            break
74
[d889d80]75        header_file.close()
[6eaf89ea]76        if not is_valid:
[9c500ab]77            raise BSLParsingError(err_msg)
[6eaf89ea]78
[535e181]79        CLoader.__init__(self, data_info['filename'], data_info['frames'],
[6eaf89ea]80            data_info['pixels'], data_info['rasters'], data_info['swap_bytes'])
[18e7309]81
[fe498b83]82    def load_frames(self, frames):
83        frame_data = []
84        # Prepare axis values (arbitrary scale)
85        x = self.n_rasters * range(1, self.n_pixels+1)
86        y = [self.n_pixels * [i] for i in range(1, self.n_rasters+1)]
87        y = np.reshape(y, (1, self.n_pixels*self.n_rasters))[0]
88        x_bins = x[:self.n_pixels]
89        y_bins = y[0::self.n_pixels]
90
91        for frame in frames:
92            self.frame = frame
93            raw_frame_data = self.load_data()
94            data2d = Data2D(data=raw_frame_data, qx_data=x, qy_data=y)
95            data2d.x_bins = x_bins
96            data2d.y_bins = y_bins
[f00691d4]97            data2d.Q_unit = '' # Using arbitrary units
[fe498b83]98            frame_data.append(data2d)
99
100        return frame_data
101
102
[cc03f59]103    def __setattr__(self, name, value):
104        if name == 'filename':
105            return self.set_filename(value)
[535e181]106        elif name == 'n_frames':
107            return self.set_n_frames(value)
[cc03f59]108        elif name == 'frame':
109            return self.set_frame(value)
110        elif name == 'n_pixels':
111            return self.set_n_pixels(value)
112        elif name == 'n_rasters':
113            return self.set_n_rasters(value)
[6eaf89ea]114        elif name == 'swap_bytes':
115            return self.set_swap_bytes(value)
116        return CLoader.__setattr__(self, name, value)
[2760662]117
118    def __getattr__(self, name):
119        if name == 'filename':
120            return self.get_filename()
[535e181]121        elif name == 'n_frames':
122            return self.get_n_frames()
[2760662]123        elif name == 'frame':
124            return self.get_frame()
125        elif name == 'n_pixels':
126            return self.get_n_pixels()
127        elif name == 'n_rasters':
128            return self.get_n_rasters()
[6eaf89ea]129        elif name == 'swap_bytes':
130            return self.get_swap_bytes()
131        return CLoader.__getattr__(self, name)
Note: See TracBrowser for help on using the repository browser.