Skip to content

Commit 898417a

Browse files
committed
added pdz11 support
1 parent 9833fca commit 898417a

File tree

7 files changed

+707
-200
lines changed

7 files changed

+707
-200
lines changed

notebooks/30_parsing-bytes.ipynb

+58-77
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@
910910
{
911911
"data": {
912912
"text/plain": [
913-
"'hi-3i9f7hfhfhfhf8hfhi-S-h-Z'"
913+
"'hi-3i9f7hfhfhfhf8hfhi-*Z'"
914914
]
915915
},
916916
"execution_count": null,
@@ -934,6 +934,13 @@
934934
"id": "d38a5b21-8a4f-4191-8f39-9e8ec4312191",
935935
"metadata": {},
936936
"outputs": [
937+
{
938+
"name": "stdout",
939+
"output_type": "stream",
940+
"text": [
941+
"[b'\\x0cRoHS 50 Hi-Z\\x01']\n"
942+
]
943+
},
937944
{
938945
"data": {
939946
"text/html": [
@@ -1157,18 +1164,13 @@
11571164
" </tr>\n",
11581165
" <tr>\n",
11591166
" <th>39</th>\n",
1160-
" <td>RoHS 50 Hi-Z</td>\n",
1161-
" <td>TubeSpec?</td>\n",
1162-
" </tr>\n",
1163-
" <tr>\n",
1164-
" <th>40</th>\n",
1165-
" <td>1</td>\n",
1167+
" <td>[b'\\x0cRoHS 50 Hi-Z\\x01']</td>\n",
11661168
" <td>??</td>\n",
11671169
" </tr>\n",
11681170
" <tr>\n",
1169-
" <th>41</th>\n",
1171+
" <th>40</th>\n",
11701172
" <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ...</td>\n",
1171-
" <td>2048 counts</td>\n",
1173+
" <td>Intensity_2048_channels</td>\n",
11721174
" </tr>\n",
11731175
" </tbody>\n",
11741176
"</table>\n",
@@ -1215,9 +1217,8 @@
12151217
"36 1017.0 \n",
12161218
"37 2048 \n",
12171219
"38 38 \n",
1218-
"39 RoHS 50 Hi-Z \n",
1219-
"40 1 \n",
1220-
"41 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ... \n",
1220+
"39 [b'\\x0cRoHS 50 Hi-Z\\x01'] \n",
1221+
"40 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ... \n",
12211222
"\n",
12221223
" param_keys \n",
12231224
"0 block_type \n",
@@ -1259,9 +1260,8 @@
12591260
"36 NosePressureInMilliBars \n",
12601261
"37 NumberOfChannels \n",
12611262
"38 NoseTemperatureInC \n",
1262-
"39 TubeSpec? \n",
1263-
"40 ?? \n",
1264-
"41 2048 counts "
1263+
"39 ?? \n",
1264+
"40 Intensity_2048_channels "
12651265
]
12661266
},
12671267
"metadata": {},
@@ -1394,6 +1394,8 @@
13941394
"source": [
13951395
"#|export \n",
13961396
"\n",
1397+
"# 'hi-3i9f7hfhfhfhf8hfhi-S-h-Z'\n",
1398+
"\n",
13971399
"PDZ_25_STRUCTURE_DICT = {\n",
13981400
" 25: {'xformat': 'hi-10X-i', \n",
13991401
" 'param_keys': ['pdz_type', 'block_size', 'FileFormatString?', '??']}, \n",
@@ -1404,7 +1406,7 @@
14041406
" 'param_keys': ['block_type', 'block_size', '??', 'RawCounts', 'ValidCounts', '??', '??', \n",
14051407
" '??', 'ActiveTimeInSeconds', 'DeadTimeInSeconds', 'ResetTimeInSeconds', \n",
14061408
" 'LiveTimeInSeconds', 'TotalElapsedTimeInSeconds', '??']}, \n",
1407-
" 3: {'xformat': 'hi-3i9f7hfhfhfhf8hfhi-S-h-Z', \n",
1409+
" 3: {'xformat': 'hi-3i9f7hfhfhfhf8hfhi-*Z', \n",
14081410
" 'param_keys': ['block_type', 'block_size', '??', 'RawCounts', 'ValidCounts', \n",
14091411
" '??', '??', '??', 'ActiveTimeInSeconds', 'DeadTimeInSeconds', \n",
14101412
" 'ResetTimeInSeconds', 'LiveTimeInSeconds', 'XrayVoltageInkV', 'XrayFilamentCurrentInMicroAmps', \n",
@@ -1413,61 +1415,10 @@
14131415
" '??', '??', 'eVPerChannel', '??', 'eVStart', \n",
14141416
" 'Year', 'Month', 'AM/PM code?', 'Day', 'Hour', 'Minutes', 'Seconds', \n",
14151417
" '??', 'NosePressureInMilliBars', 'NumberOfChannels', 'NoseTemperatureInC', \n",
1416-
" 'TubeSpec?', '??', '2048 counts']}}\n",
1418+
" '??', 'Intensity_2048_channels']}}\n",
14171419
"\n",
1420+
"# moved extract_spectra() function to legacy module \n",
14181421
"\n",
1419-
"def extract_spectra(pdz_file, to_csv=True, verbose=True): \n",
1420-
" '''Directly extract spectral data from `pdz_file`. \n",
1421-
" \n",
1422-
" Robust extraction of spectrum counts and energy calibration. Other meta data is ignored. '''\n",
1423-
"\n",
1424-
" pdz_bytes = file_to_bytes(pdz_file)\n",
1425-
" block_list = get_blocks(pdz_bytes, verbose=False) \n",
1426-
" \n",
1427-
" # select type 3 blocks\n",
1428-
" b3_list = [b for b in block_list if b['block_type'] == 3] \n",
1429-
" n_spectra = len(b3_list) \n",
1430-
"\n",
1431-
" # parsing spectrum parameters \n",
1432-
" #from first block to compute channel energies (keV) \n",
1433-
" # (assuming that these are similar for all spectra in the pdz file) \n",
1434-
" \n",
1435-
" arr = b3_list[0]['bytes'] # only using first spectrum! \n",
1436-
" spectrum_params = multiparse('hi-3i9f7hfhfhfhf8hfhi-S-h', arr, verbose=False)[0] \n",
1437-
" tube_keV = spectrum_params[12] # FYI \n",
1438-
" delta_keV = spectrum_params[25] / 1000\n",
1439-
" start_keV = spectrum_params[27] / 1000 \n",
1440-
" n_channels = spectrum_params[37] \n",
1441-
" if n_channels != 2048: \n",
1442-
" print(f'Found unexpected number of channels in pdz metadata: {n_channels}')\n",
1443-
" \n",
1444-
" stop_keV = start_keV + delta_keV * (n_channels -1)\n",
1445-
" x_keV = np.linspace(start_keV, stop_keV, num=n_channels) \n",
1446-
"\n",
1447-
" # initialize array \n",
1448-
" \n",
1449-
" spectra_df = pd.DataFrame(index=x_keV)\n",
1450-
"\n",
1451-
" # TODO: Test if computed channel energies `x_keV` are reasonable, \n",
1452-
" # Parsing of spectrum parameters might fail \n",
1453-
" # if Bruker messes with file format. \n",
1454-
" # otherwise fall back on 0-40 keV range \n",
1455-
"\n",
1456-
" spectrum_list = [] \n",
1457-
"\n",
1458-
" for i, b3 in enumerate(b3_list): \n",
1459-
" arr = b3['bytes'] \n",
1460-
" counts = np.array(parse(f'{n_channels}i', arr[-4*n_channels:], verbose=False)[0]) \n",
1461-
"\n",
1462-
" spectra_df[f'spectrum #{i+1}'] = counts\n",
1463-
"\n",
1464-
" if to_csv == True: \n",
1465-
" csv_file = f'{pdz_file}.csv' \n",
1466-
" print(f'Saving spectral data to: {csv_file}')\n",
1467-
" spectra_df.to_csv(csv_file, float_format='%10.5f')\n",
1468-
"\n",
1469-
" return spectra_df\n",
1470-
" \n",
14711422
"\n",
14721423
"def multiparse(xformat, arr, param_keys=None, verbose=True): \n",
14731424
" '''Parse segments in extendend format string `xformat` e.g. '<i5f-2S-T-3S-S-f' '''\n",
@@ -1483,11 +1434,35 @@
14831434
" result, arr = read_table(p, arr, verbose=False) \n",
14841435
" elif 'X' in p: \n",
14851436
" result, arr = skip_bytes(p, arr, verbose=False) \n",
1486-
" elif 'Z' in p: \n",
1437+
" \n",
1438+
" # four spectral data scenarios here: \n",
1439+
"\n",
1440+
" # (1) 2048 channels at end of array and skip any bytes before\n",
1441+
" elif p == '*Z': \n",
1442+
" # split array \n",
1443+
" n_channels = 2048 \n",
1444+
" arr_0 = arr[:-n_channels*4] # head \n",
1445+
" arr_1 = arr[-n_channels*4:] # tail \n",
1446+
" skipped, _ = skip_bytes('*X', arr_0, verbose=False)\n",
1447+
" counts, arr = read_counts('Z', arr_1 , verbose=False) # arr should now be empty \n",
1448+
" result = [skipped, counts] \n",
1449+
" # (2) 1024 channels at end of array and skip any bytes before\n",
1450+
" elif p == '*z': \n",
1451+
" # split array \n",
1452+
" n_channels = 1024 \n",
1453+
" arr_0 = arr[:-n_channels*4] # head \n",
1454+
" arr_1 = arr[-n_channels*4:] # tail \n",
1455+
" \n",
1456+
" skipped, _ = skip_bytes('*X', arr_0, verbose=False)\n",
1457+
" counts, arr = read_counts('z', arr_1 , verbose=False) # arr should now be empty \n",
1458+
" result = [skipped, counts] \n",
1459+
" # (3) 2048 channels not at end of array \n",
1460+
" elif p == 'Z': \n",
14871461
" result, arr = read_counts(p, arr, verbose=False)\n",
14881462
" result = [result]\n",
1489-
" elif 'z' in p: \n",
1490-
" result, arr = read_counts(p, arr, n_channels=1028, verbose=False)\n",
1463+
" # (4) 1024 channels not at end of array \n",
1464+
" elif p == 'z': \n",
1465+
" result, arr = read_counts(p, arr, verbose=False)\n",
14911466
" result = [result] \n",
14921467
" \n",
14931468
" else: \n",
@@ -1620,14 +1595,20 @@
16201595
" return table, arr\n",
16211596
"\n",
16221597
"\n",
1623-
"def read_counts(xformat, arr, n_channels=2048, verbose=True): \n",
1598+
"def read_counts(xformat, arr, verbose=True): \n",
16241599
" '''Extract counts. '''\n",
16251600
"\n",
1626-
" assert xformat == 'Z' or xformat == 'z', 'Incorrect format string'\n",
1627-
"\n",
1628-
" format = f'<{n_channels}i'\n",
1601+
" assert xformat == 'Z' or xformat == 'z', 'Incorrect spectral data format string. Should be `Z` or `z`' \n",
1602+
" \n",
1603+
" if xformat == 'Z': \n",
1604+
" n_channels = 2048 \n",
1605+
" elif xformat == 'z': \n",
1606+
" n_channels = 1024 \n",
1607+
" \n",
1608+
" # make struct compatible format string \n",
1609+
" _format = f'<{n_channels}i'\n",
16291610
"\n",
1630-
" counts, arr = parse(format, arr, verbose=False) \n",
1611+
" counts, arr = parse(_format, arr, verbose=False) \n",
16311612
" counts = np.array(counts)\n",
16321613
" \n",
16331614
" if verbose: \n",

0 commit comments

Comments
 (0)