spc_spectra.subfile

Classes for reading subfile data segments

  1"""
  2Classes for reading subfile data segments
  3"""
  4
  5# --- Imports
  6
  7# Standard library
  8from __future__ import division, absolute_import, unicode_literals, print_function
  9import struct
 10
 11# External packages
 12import numpy as np
 13
 14
 15# --- Utility functions
 16
 17
 18def read_subheader(subheader):
 19    """
 20    Return the subheader as a list
 21
 22    Parameters
 23    ----------
 24    subheader (string):
 25        32 character string in the subheader format
 26
 27    Returns
 28    -------
 29    list:
 30        10 item list with the following data members:
 31        [0] subflgs
 32        [1] subexp
 33        [2] subindx
 34        [3] subtime
 35        [4] subnext
 36        [5] subnois
 37        [6] subnpts
 38        [7] subscan
 39        [8] subwlevel
 40        [9] subresv
 41    """
 42
 43    subhead_str = "<cchfffiif4s"
 44    items = struct.unpack(subhead_str.encode("utf8"), subheader)
 45
 46    item_cpy = [ord(i) for i in items[:2]]
 47    item_cpy += items[2:]
 48
 49    return item_cpy
 50
 51
 52# --- subFile class
 53
 54
 55class subFile:
 56    """
 57    Processes each subfile passed to it, extracts header information and data
 58    information and places them in data members
 59
 60    Data
 61    ----
 62    x: x-data (optional)
 63    y: y-data
 64    y_int: integer y-data if y-data is not floating
 65    """
 66
 67    def __init__(self, data, fnpts, fexp, txyxy, tsprec, tmulti):
 68
 69        # extract subheader info
 70        (
 71            self.subflgs,
 72            self.subexp,
 73            self.subindx,
 74            self.subtime,
 75            self.subnext,
 76            self.subnois,
 77            self.subnpts,
 78            self.subscan,
 79            self.subwlevel,
 80            self.subresv,
 81        ) = read_subheader(data[:32])
 82
 83        # header is 32 bytes
 84        y_dat_pos = 32
 85
 86        if txyxy:
 87            # only reason to use subnpts if x data is here
 88            pts = self.subnpts
 89        else:
 90            pts = fnpts
 91
 92        # Choosing exponent
 93        # -----------------
 94        # choose local vs global exponent depending on tmulti
 95        if not tmulti:
 96            exp = fexp
 97        else:
 98            exp = self.subexp
 99
100        # Make sure it is reasonable, if it out of range zero it
101        if not (-128 < exp <= 128):
102            exp = 0
103
104        # --------------------------
105        # if x_data present
106        # --------------------------
107        if txyxy:
108            x_str = "<" + "i" * pts
109            x_dat_pos = y_dat_pos
110            x_dat_end = x_dat_pos + (4 * pts)
111
112            x_raw = np.array(
113                struct.unpack(x_str.encode("utf8"), data[x_dat_pos:x_dat_end])
114            )
115            self.x = (2 ** (exp - 32)) * x_raw
116
117            y_dat_pos = x_dat_end
118
119        # --------------------------
120        # extract y_data
121        # --------------------------
122        y_dat_str = "<"
123        if exp == 128:
124            # Floating y-values
125            y_dat_str += "f" * pts
126            y_dat_end = y_dat_pos + (4 * pts)
127            y_raw = np.array(
128                struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
129            )
130            self.y = y_raw
131        else:
132            # integer format
133            # lydata = len(data) - y_dat_pos
134            if tsprec:
135                # 16 bit
136                y_dat_str += "h" * pts  # short
137                y_dat_end = y_dat_pos + (2 * pts)
138                y_raw = np.array(
139                    struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
140                )
141                self.y = (2 ** (exp - 16)) * y_raw
142            else:
143                # 32 bit, using size of subheader to figure out data type
144                # actually there is flag for this, use it instead
145                # self.tsprec
146                y_dat_str += "i" * pts
147                y_dat_end = y_dat_pos + (4 * pts)
148                y_raw = np.array(
149                    struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
150                )
151                self.y = (2 ** (exp - 32)) * y_raw
152
153
154class subFileOld:
155    """
156    Processes each subfile passed to it, extracts header information and data
157    information and places them in data members.
158
159    Used for the old format where the y-values are stored in an odd way
160
161    Data
162    ----
163    x: x-data (optional)
164    y: y-data
165    """
166
167    def __init__(self, data, pts, fexp, txyxy):
168        # fixed header size
169        y_dat_pos = 32
170
171        # extract subheader info
172        (
173            self.subflgs,
174            self.subexp,
175            self.subindx,
176            self.subtime,
177            self.subnext,
178            self.subnois,
179            self.subnpts,
180            self.subscan,
181            self.subwlevel,
182            self.subresv,
183        ) = read_subheader(data[:y_dat_pos])
184
185        # assume it is an integer unless told otherwise
186        yfloat = False
187        if self.subexp == 128:
188            yfloat = True
189
190        # if the sub exp is reasonable, use it
191        if self.subexp > 0 and self.subexp < 128:
192            exp = self.subexp
193        else:
194            # or use the global one
195            exp = fexp
196
197        # --------------------------
198        # if x_data present
199        # --------------------------
200
201        if txyxy:
202            x_str = "i" * pts
203            x_dat_pos = y_dat_pos
204            x_dat_end = x_dat_pos + (4 * pts)
205
206            x_raw = np.array(
207                struct.unpack(x_str.encode("utf8"), data[x_dat_pos:x_dat_end])
208            )
209            self.x = (2 ** (exp - 32)) * x_raw
210
211            y_dat_pos = x_dat_end
212
213        # --------------------------
214        # extract y_data
215        # --------------------------
216
217        # assuming can't have 2 byte y-values, !! fix maybe
218        y_dat_end = y_dat_pos + (4 * pts)
219        if yfloat:
220            # floats are pretty straigtfoward
221            y_dat_str = "<" + "f" * pts
222            y_raw = struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
223            self.y = y_raw
224        else:
225            # for old format, extract the entire array out as 1 bit unsigned
226            # integers, swap 1st and 2nd byte, as well as 3rd and 4th byte to get
227            # the final integer then scale by the exponent
228            y_dat_str = ">" + "B" * 4 * pts
229            y_raw = struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
230
231            y_int = []
232            for i in range(0, len(y_raw), 4):
233                y_int.append(
234                    y_raw[i + 1] * (256**3)
235                    + y_raw[i] * (256**2)
236                    + y_raw[i + 3] * (256)
237                    + y_raw[i + 2]
238                )
239
240            # convert y-data to signed ints
241            y_int = np.array(y_int).astype("int32", copy=False)
242
243            # convert y-data to floats
244            self.y = y_int / (2 ** (32 - exp))
245
246        # do stuff if subflgs
247        # if 1 subfile changed
248        # if 8 if peak table should not be used
249        # if 128 if subfile modified by arithmetic
def read_subheader(subheader):
19def read_subheader(subheader):
20    """
21    Return the subheader as a list
22
23    Parameters
24    ----------
25    subheader (string):
26        32 character string in the subheader format
27
28    Returns
29    -------
30    list:
31        10 item list with the following data members:
32        [0] subflgs
33        [1] subexp
34        [2] subindx
35        [3] subtime
36        [4] subnext
37        [5] subnois
38        [6] subnpts
39        [7] subscan
40        [8] subwlevel
41        [9] subresv
42    """
43
44    subhead_str = "<cchfffiif4s"
45    items = struct.unpack(subhead_str.encode("utf8"), subheader)
46
47    item_cpy = [ord(i) for i in items[:2]]
48    item_cpy += items[2:]
49
50    return item_cpy

Return the subheader as a list

Parameters

subheader (string): 32 character string in the subheader format

Returns

list: 10 item list with the following data members: [0] subflgs [1] subexp [2] subindx [3] subtime [4] subnext [5] subnois [6] subnpts [7] subscan [8] subwlevel [9] subresv

class subFile:
 56class subFile:
 57    """
 58    Processes each subfile passed to it, extracts header information and data
 59    information and places them in data members
 60
 61    Data
 62    ----
 63    x: x-data (optional)
 64    y: y-data
 65    y_int: integer y-data if y-data is not floating
 66    """
 67
 68    def __init__(self, data, fnpts, fexp, txyxy, tsprec, tmulti):
 69
 70        # extract subheader info
 71        (
 72            self.subflgs,
 73            self.subexp,
 74            self.subindx,
 75            self.subtime,
 76            self.subnext,
 77            self.subnois,
 78            self.subnpts,
 79            self.subscan,
 80            self.subwlevel,
 81            self.subresv,
 82        ) = read_subheader(data[:32])
 83
 84        # header is 32 bytes
 85        y_dat_pos = 32
 86
 87        if txyxy:
 88            # only reason to use subnpts if x data is here
 89            pts = self.subnpts
 90        else:
 91            pts = fnpts
 92
 93        # Choosing exponent
 94        # -----------------
 95        # choose local vs global exponent depending on tmulti
 96        if not tmulti:
 97            exp = fexp
 98        else:
 99            exp = self.subexp
100
101        # Make sure it is reasonable, if it out of range zero it
102        if not (-128 < exp <= 128):
103            exp = 0
104
105        # --------------------------
106        # if x_data present
107        # --------------------------
108        if txyxy:
109            x_str = "<" + "i" * pts
110            x_dat_pos = y_dat_pos
111            x_dat_end = x_dat_pos + (4 * pts)
112
113            x_raw = np.array(
114                struct.unpack(x_str.encode("utf8"), data[x_dat_pos:x_dat_end])
115            )
116            self.x = (2 ** (exp - 32)) * x_raw
117
118            y_dat_pos = x_dat_end
119
120        # --------------------------
121        # extract y_data
122        # --------------------------
123        y_dat_str = "<"
124        if exp == 128:
125            # Floating y-values
126            y_dat_str += "f" * pts
127            y_dat_end = y_dat_pos + (4 * pts)
128            y_raw = np.array(
129                struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
130            )
131            self.y = y_raw
132        else:
133            # integer format
134            # lydata = len(data) - y_dat_pos
135            if tsprec:
136                # 16 bit
137                y_dat_str += "h" * pts  # short
138                y_dat_end = y_dat_pos + (2 * pts)
139                y_raw = np.array(
140                    struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
141                )
142                self.y = (2 ** (exp - 16)) * y_raw
143            else:
144                # 32 bit, using size of subheader to figure out data type
145                # actually there is flag for this, use it instead
146                # self.tsprec
147                y_dat_str += "i" * pts
148                y_dat_end = y_dat_pos + (4 * pts)
149                y_raw = np.array(
150                    struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
151                )
152                self.y = (2 ** (exp - 32)) * y_raw

Processes each subfile passed to it, extracts header information and data information and places them in data members

Data

x: x-data (optional) y: y-data y_int: integer y-data if y-data is not floating

subFile(data, fnpts, fexp, txyxy, tsprec, tmulti)
 68    def __init__(self, data, fnpts, fexp, txyxy, tsprec, tmulti):
 69
 70        # extract subheader info
 71        (
 72            self.subflgs,
 73            self.subexp,
 74            self.subindx,
 75            self.subtime,
 76            self.subnext,
 77            self.subnois,
 78            self.subnpts,
 79            self.subscan,
 80            self.subwlevel,
 81            self.subresv,
 82        ) = read_subheader(data[:32])
 83
 84        # header is 32 bytes
 85        y_dat_pos = 32
 86
 87        if txyxy:
 88            # only reason to use subnpts if x data is here
 89            pts = self.subnpts
 90        else:
 91            pts = fnpts
 92
 93        # Choosing exponent
 94        # -----------------
 95        # choose local vs global exponent depending on tmulti
 96        if not tmulti:
 97            exp = fexp
 98        else:
 99            exp = self.subexp
100
101        # Make sure it is reasonable, if it out of range zero it
102        if not (-128 < exp <= 128):
103            exp = 0
104
105        # --------------------------
106        # if x_data present
107        # --------------------------
108        if txyxy:
109            x_str = "<" + "i" * pts
110            x_dat_pos = y_dat_pos
111            x_dat_end = x_dat_pos + (4 * pts)
112
113            x_raw = np.array(
114                struct.unpack(x_str.encode("utf8"), data[x_dat_pos:x_dat_end])
115            )
116            self.x = (2 ** (exp - 32)) * x_raw
117
118            y_dat_pos = x_dat_end
119
120        # --------------------------
121        # extract y_data
122        # --------------------------
123        y_dat_str = "<"
124        if exp == 128:
125            # Floating y-values
126            y_dat_str += "f" * pts
127            y_dat_end = y_dat_pos + (4 * pts)
128            y_raw = np.array(
129                struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
130            )
131            self.y = y_raw
132        else:
133            # integer format
134            # lydata = len(data) - y_dat_pos
135            if tsprec:
136                # 16 bit
137                y_dat_str += "h" * pts  # short
138                y_dat_end = y_dat_pos + (2 * pts)
139                y_raw = np.array(
140                    struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
141                )
142                self.y = (2 ** (exp - 16)) * y_raw
143            else:
144                # 32 bit, using size of subheader to figure out data type
145                # actually there is flag for this, use it instead
146                # self.tsprec
147                y_dat_str += "i" * pts
148                y_dat_end = y_dat_pos + (4 * pts)
149                y_raw = np.array(
150                    struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
151                )
152                self.y = (2 ** (exp - 32)) * y_raw
class subFileOld:
155class subFileOld:
156    """
157    Processes each subfile passed to it, extracts header information and data
158    information and places them in data members.
159
160    Used for the old format where the y-values are stored in an odd way
161
162    Data
163    ----
164    x: x-data (optional)
165    y: y-data
166    """
167
168    def __init__(self, data, pts, fexp, txyxy):
169        # fixed header size
170        y_dat_pos = 32
171
172        # extract subheader info
173        (
174            self.subflgs,
175            self.subexp,
176            self.subindx,
177            self.subtime,
178            self.subnext,
179            self.subnois,
180            self.subnpts,
181            self.subscan,
182            self.subwlevel,
183            self.subresv,
184        ) = read_subheader(data[:y_dat_pos])
185
186        # assume it is an integer unless told otherwise
187        yfloat = False
188        if self.subexp == 128:
189            yfloat = True
190
191        # if the sub exp is reasonable, use it
192        if self.subexp > 0 and self.subexp < 128:
193            exp = self.subexp
194        else:
195            # or use the global one
196            exp = fexp
197
198        # --------------------------
199        # if x_data present
200        # --------------------------
201
202        if txyxy:
203            x_str = "i" * pts
204            x_dat_pos = y_dat_pos
205            x_dat_end = x_dat_pos + (4 * pts)
206
207            x_raw = np.array(
208                struct.unpack(x_str.encode("utf8"), data[x_dat_pos:x_dat_end])
209            )
210            self.x = (2 ** (exp - 32)) * x_raw
211
212            y_dat_pos = x_dat_end
213
214        # --------------------------
215        # extract y_data
216        # --------------------------
217
218        # assuming can't have 2 byte y-values, !! fix maybe
219        y_dat_end = y_dat_pos + (4 * pts)
220        if yfloat:
221            # floats are pretty straigtfoward
222            y_dat_str = "<" + "f" * pts
223            y_raw = struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
224            self.y = y_raw
225        else:
226            # for old format, extract the entire array out as 1 bit unsigned
227            # integers, swap 1st and 2nd byte, as well as 3rd and 4th byte to get
228            # the final integer then scale by the exponent
229            y_dat_str = ">" + "B" * 4 * pts
230            y_raw = struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
231
232            y_int = []
233            for i in range(0, len(y_raw), 4):
234                y_int.append(
235                    y_raw[i + 1] * (256**3)
236                    + y_raw[i] * (256**2)
237                    + y_raw[i + 3] * (256)
238                    + y_raw[i + 2]
239                )
240
241            # convert y-data to signed ints
242            y_int = np.array(y_int).astype("int32", copy=False)
243
244            # convert y-data to floats
245            self.y = y_int / (2 ** (32 - exp))
246
247        # do stuff if subflgs
248        # if 1 subfile changed
249        # if 8 if peak table should not be used
250        # if 128 if subfile modified by arithmetic

Processes each subfile passed to it, extracts header information and data information and places them in data members.

Used for the old format where the y-values are stored in an odd way

Data

x: x-data (optional) y: y-data

subFileOld(data, pts, fexp, txyxy)
168    def __init__(self, data, pts, fexp, txyxy):
169        # fixed header size
170        y_dat_pos = 32
171
172        # extract subheader info
173        (
174            self.subflgs,
175            self.subexp,
176            self.subindx,
177            self.subtime,
178            self.subnext,
179            self.subnois,
180            self.subnpts,
181            self.subscan,
182            self.subwlevel,
183            self.subresv,
184        ) = read_subheader(data[:y_dat_pos])
185
186        # assume it is an integer unless told otherwise
187        yfloat = False
188        if self.subexp == 128:
189            yfloat = True
190
191        # if the sub exp is reasonable, use it
192        if self.subexp > 0 and self.subexp < 128:
193            exp = self.subexp
194        else:
195            # or use the global one
196            exp = fexp
197
198        # --------------------------
199        # if x_data present
200        # --------------------------
201
202        if txyxy:
203            x_str = "i" * pts
204            x_dat_pos = y_dat_pos
205            x_dat_end = x_dat_pos + (4 * pts)
206
207            x_raw = np.array(
208                struct.unpack(x_str.encode("utf8"), data[x_dat_pos:x_dat_end])
209            )
210            self.x = (2 ** (exp - 32)) * x_raw
211
212            y_dat_pos = x_dat_end
213
214        # --------------------------
215        # extract y_data
216        # --------------------------
217
218        # assuming can't have 2 byte y-values, !! fix maybe
219        y_dat_end = y_dat_pos + (4 * pts)
220        if yfloat:
221            # floats are pretty straigtfoward
222            y_dat_str = "<" + "f" * pts
223            y_raw = struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
224            self.y = y_raw
225        else:
226            # for old format, extract the entire array out as 1 bit unsigned
227            # integers, swap 1st and 2nd byte, as well as 3rd and 4th byte to get
228            # the final integer then scale by the exponent
229            y_dat_str = ">" + "B" * 4 * pts
230            y_raw = struct.unpack(y_dat_str.encode("utf8"), data[y_dat_pos:y_dat_end])
231
232            y_int = []
233            for i in range(0, len(y_raw), 4):
234                y_int.append(
235                    y_raw[i + 1] * (256**3)
236                    + y_raw[i] * (256**2)
237                    + y_raw[i + 3] * (256)
238                    + y_raw[i + 2]
239                )
240
241            # convert y-data to signed ints
242            y_int = np.array(y_int).astype("int32", copy=False)
243
244            # convert y-data to floats
245            self.y = y_int / (2 ** (32 - exp))
246
247        # do stuff if subflgs
248        # if 1 subfile changed
249        # if 8 if peak table should not be used
250        # if 128 if subfile modified by arithmetic