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
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
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
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
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
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