Coverage for /Users/Newville/Codes/xraylarch/larch/io/rixs_esrf_fame.py: 0%
75 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
4"""
5RIXS data reader for beamline BM16 @ ESRF
6=========================================
8.. note: RIXS stands for Resonant Inelastic X-ray Scattering
10.. note: BM16 is FAME-UHD, French CRG beamline
12"""
13import os
14import time
15import numpy as np
16from larch.io.specfile_reader import DataSourceSpecH5, _mot2array
17from silx.io.dictdump import dicttoh5
18from larch.utils.logging import getLogger
20_logger = getLogger("io_rixs_bm16")
23def _parse_header(fname):
24 """Get parsed header for the RIXS_###.log file
25 Return
26 ------
27 header : dict
28 """
29 with open(fname) as f:
30 lines = f.read().splitlines()
31 header_lines = [line[1:] for line in lines if line[0] == "#"]
32 header = {}
33 for line in header_lines:
34 ls = line.split(": ")
35 try:
36 k, v = ls[0], ls[1]
37 except IndexError:
38 pass
39 for s in ("START", "END", "STEP"):
40 if s in k:
41 v = float(v)
42 header[k] = v
43 return header
46def get_rixs_bm16(
47 rixs_logfn,
48 sample_name=None,
49 out_dir=None,
50 counter_signal="absF1",
51 counter_norm=None,
52 interp_ene_in=True,
53 save_rixs=False,
54):
55 """Build RIXS map as X,Y,Z 1D arrays
56 Parameters
57 ----------
58 rixs_logfn : str
59 path to the RIXS_###.log file
60 sample_name : str, optional ['UNKNOWN_SAMPLE']
61 out_dir : str, optional
62 path to save the data [None -> data_dir]
63 counter_signal : str
64 name of the data column to use as signal
65 counter_norm : str
66 name of the data column to use as normaliztion
67 interp_ene_in: bool
68 perform interpolation ene_in to the energy step of ene_out [True]
69 save_rixs : bool
70 if True -> save outdict to disk (in 'out_dir')
71 Returns
72 -------
73 outdict : dict
74 {
75 '_x': array, energy in
76 '_y': array, energy out
77 '_z': array, signal
78 'writer_name': str,
79 'writer_version': str,
80 'writer_timestamp': str,
81 'filename_all' : list,
82 'filename_root': str,
83 'name_sample': str,
84 'name_scan': str,
85 'counter_all': str,
86 'counter_signal': str,
87 'counter_norm': str,
88 'ene_grid': float,
89 'ene_unit': str,
90 }
91 """
92 _writer = "get_rixs_bm16"
93 _writer_version = "1.5.1" #: used for reading back in RixsData.load_from_h5()
94 _writer_timestamp = "{0:04d}-{1:02d}-{2:02d}_{3:02d}{4:02d}".format(
95 *time.localtime()
96 )
97 header = _parse_header(rixs_logfn)
98 if sample_name is None:
99 try:
100 sample_name = header["SAMPLE_NAME"]
101 except Exception:
102 sample_name = "UNKNOWN_SAMPLE"
103 sfn = header["DATAFILE"]
104 scntype = header["RIXS_SCAN_TYPE"]
105 data_dir = os.path.join(os.sep, *sfn.split("/")[1:-1])
106 if out_dir is None:
107 out_dir = data_dir
108 ds = DataSourceSpecH5(sfn)
110 logobj = np.genfromtxt(rixs_logfn, delimiter=",", comments="#")
111 scans = logobj[:, 0] # list of scan numers
112 enes = logobj[:, 1]
114 _counter = 0
115 for scan, estep in zip(scans, enes):
116 scan = int(scan)
117 try:
118 ds.set_scan(scan)
119 escan, sig, lab, attrs = ds.get_curve(counter_signal)
120 except Exception:
121 _logger.error(f"cannot load scan {scan}!")
122 continue
123 if scntype == "rixs_et":
124 x = _mot2array(estep, escan)
125 y = escan
126 else:
127 x = escan
128 y = _mot2array(estep, escan)
129 if _counter == 0:
130 xcol = x
131 ycol = y
132 zcol = sig
133 else:
134 xcol = np.append(xcol, x)
135 ycol = np.append(ycol, y)
136 zcol = np.append(zcol, sig)
137 _counter += 1
138 _logger.info(f"Loaded scan {scan}: {estep} eV")
140 outdict = {
141 "_x": xcol * 1000, #to eV
142 "_y": ycol * 1000, #to eV
143 "_z": zcol,
144 "writer_name": _writer,
145 "writer_version": _writer_version,
146 "writer_timestamp": _writer_timestamp,
147 "counter_signal": counter_signal,
148 "counter_norm": counter_norm,
149 "sample_name": sample_name,
150 "ene_unit": "eV",
151 "rixs_header": header,
152 "data_dir": data_dir,
153 "out_dir": out_dir,
154 }
156 if save_rixs:
157 fnstr = sfn.split("/")[-1].split(".")[0]
158 fnout = "{0}_rixs.h5".format(fnstr)
159 dicttoh5(outdict, os.path.join(out_dir, fnout))
160 _logger.info("RIXS saved to {0}".format(fnout))
162 return outdict
165if __name__ == "__main__":
166 pass