Skip to content

Commit 9107c60

Browse files
author
Bing Li
committed
completed nxdict class
1 parent 542bcd5 commit 9107c60

7 files changed

+93
-43
lines changed

src/tavi/data/nxdict.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,11 @@ def spice_scan_to_nxdict(
270270
name=NXdataset(ds=metadata.get("samplename"), type="NX_CHAR", EX_required="true"),
271271
type=NXdataset(ds=metadata.get("sampletype"), type="NX_CHAR", EX_required="true"),
272272
unit_cell=NXdataset(ds=metadata.get("latticeconstants"), type="NX_FLOAT", EX_required="true"),
273-
qh=NXdataset(ds=spicelogs.get("h"), type="NX_FLOAT", EX_required="true"),
274-
qk=NXdataset(ds=spicelogs.get("k"), type="NX_FLOAT", EX_required="true"),
275-
ql=NXdataset(ds=spicelogs.get("l"), type="NX_FLOAT", EX_required="true"),
273+
qh=NXdataset(ds=spicelogs.get("h"), type="NX_FLOAT", EX_required="true", units="r.l.u."),
274+
qk=NXdataset(ds=spicelogs.get("k"), type="NX_FLOAT", EX_required="true", units="r.l.u."),
275+
ql=NXdataset(ds=spicelogs.get("l"), type="NX_FLOAT", EX_required="true", units="r.l.u."),
276276
en=NXdataset(ds=spicelogs.get("e"), type="NX_FLOAT", EX_required="true", units="meV"),
277-
q=NXdataset(ds=spicelogs.get("q"), type="NX_FLOAT"),
277+
q=NXdataset(ds=spicelogs.get("q"), type="NX_FLOAT", units="Angstrom^-1"),
278278
sense=NXdataset(ds=metadata["sense"][1], type="NX_CHAR"),
279279
NX_class="NXsample",
280280
EX_required="true",
@@ -379,15 +379,16 @@ def spice_data_to_nxdict(
379379

380380
nexus_dict = {}
381381
for path_to_scan_file in scan_list:
382-
pass
382+
*_, file_name = path_to_scan_file.split("/")
383+
*_, scan_dat = file_name.split("_")
384+
scan_num, _ = scan_dat.split(".")
383385

384-
scan_name, scan_dict = spice_scan_to_nxdict(
386+
nxentry = spice_scan_to_nxdict(
385387
path_to_scan_file,
386388
path_to_instrument_json,
387389
path_to_sample_json,
388390
)
389-
390-
nexus_dict.update({scan_name: scan_dict})
391-
nexus_dict[scan_name]["attrs"].update({"dataset_name": dataset_name})
391+
nxentry["attrs"].update({"dataset_name": dataset_name})
392+
nexus_dict.update({scan_num: nxentry})
392393

393394
return nexus_dict

src/tavi/data/nxentry.py

+22-11
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,28 @@ def _getitem_recursively(obj: dict, key: str, ATTRS: bool):
4444
value = None
4545
if key.split("/")[0] in obj:
4646
for key_item in key.split("/"):
47-
obj = obj[key_item]
48-
if ATTRS:
47+
# you could be looking in the wrong folder
48+
# e.g. looking for detector/data in data/detector
49+
# return None when this happens
50+
try:
51+
obj = obj[key_item]
52+
except KeyError:
53+
return None
54+
if ATTRS: # get attributes
4955
try:
5056
value = obj["attrs"]
5157
except KeyError:
5258
print(f"Attribute of {key} does not exist.")
53-
else:
59+
else: # get dataset
5460
try:
5561
value = obj["dataset"]
5662
except KeyError:
5763
print(f"Dataset of {key} does not exist.")
5864

5965
for k, v in obj.items():
60-
if value is not None:
66+
if value is not None: # value found
6167
break
62-
if k == "attrs" or k == "dataset":
68+
if k == "attrs" or k == "dataset": # gone too far
6369
continue
6470

6571
if isinstance(v, dict):
@@ -107,10 +113,11 @@ def format_dataset(value):
107113
if "dataset" in value.keys():
108114
dv = format_dataset(value)
109115
if key in nexus_entry: # dataset exists
110-
ds = nexus_entry[key]
111-
ds[...] = dv
112-
else: # create dataset
113-
ds = nexus_entry.create_dataset(name=key, data=dv, maxshape=None)
116+
del nexus_entry[key]
117+
# ds = nexus_entry[key]
118+
# ds[...] = dv
119+
# else: # create dataset
120+
ds = nexus_entry.create_dataset(name=key, data=dv, maxshape=None)
114121
NexusEntry._write_recursively(value, ds)
115122
else:
116123
grp = nexus_entry.require_group(key + "/")
@@ -137,7 +144,10 @@ def _read_recursively(nexus_entry, items=None):
137144
except TypeError: # arrays instead
138145
value = value[...]
139146

140-
items.update({key: {"attrs": attr_dict, "dataset": value}})
147+
if not attr_dict: # empty attributes
148+
items.update({key: {"dataset": value}})
149+
else:
150+
items.update({key: {"attrs": attr_dict, "dataset": value}})
141151

142152
return items
143153

@@ -152,7 +162,7 @@ def _dict_to_nexus_entry(nexus_dict):
152162
nexus_entries.update({scan_num: NexusEntry(content_list)})
153163
return nexus_entries
154164

155-
# TODO read in instrument and sample configuratio json files
165+
# TODO read in instrument and sample configuration json files
156166
@classmethod
157167
def from_spice(
158168
cls,
@@ -211,6 +221,7 @@ def to_nexus(self, path_to_nexus: str, name="scan") -> None:
211221
def_x = nexus_file["scan0034"]["data"].attrs["axes"]
212222
path_y = _find_val_path(def_y, nexus_file)
213223
path_x = _find_val_path(def_x, nexus_file)
224+
214225
if path_y is not None:
215226
def_y = "data/" + def_y
216227
if isinstance(scan_grp.get(def_y), h5py.Dataset):

src/tavi/data/spice_reader.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ def read_spice_datafile(file_name: str):
6262

6363

6464
def read_spice_ubconf(ub_file_name: str):
65-
"""Reads ub info from UBConf"""
65+
"""Reads ub info from UBConf
66+
Args:
67+
ub_file_name (str): a string containing the filename
68+
69+
Returns:
70+
"""
6671
ubconf = {}
6772
with open(ub_file_name, encoding="utf-8") as f:
6873
all_content = f.readlines()
@@ -143,7 +148,8 @@ def _create_spicelogs(path_to_scan_file: str) -> dict:
143148
if len(spice_data_shape) == 1: # 1 row ony
144149
if spice_data_shape[0] != 0:
145150
for idx, col_header in enumerate(col_names):
146-
dataset_dict.update({col_header: data[idx]})
151+
# convert to ndarray if one point only
152+
dataset_dict.update({col_header: np.array([data[idx]])})
147153
else: # ignore if empty
148154
pass
149155
elif len(spice_data_shape) == 2: # nomarl data with mutiple rows

test_data/scan_to_nexus_test.h5

53 KB
Binary file not shown.
61.3 KB
Binary file not shown.

test_data/tavi_test_exp424.h5

0 Bytes
Binary file not shown.

tests/test_nxentry.py

+53-21
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,27 @@ def test_get_dataset(nexus_entries):
1010
scan0034 = nexus_entries["scan0034"]
1111
assert scan0034.get("definition") == "NXtas"
1212
assert scan0034.get("title") == "scan_title_34"
13-
assert np.allclose(scan0034.get("a2"), np.array([242.0, 242.1, 242.2]))
13+
assert np.allclose(
14+
scan0034.get("a2"),
15+
np.array([242.0, 242.1, 242.2]),
16+
)
1417
assert scan0034.get("data", ATTRS=True) == {
1518
"EX_required": "true",
1619
"NX_class": "NXdata",
17-
"axes": "en",
20+
"axes": "a1",
1821
"signal": "detector",
1922
}
2023
assert scan0034.get("a3") is None
2124
assert scan0034.get("detector") is None
22-
assert scan0034.get("detector/data", ATTRS=True) == {"EX_required": "true", "type": "NX_INT", "units": "counts"}
23-
assert np.allclose(scan0034.get("instrument/analyser/a2"), np.array([242.0, 242.1, 242.2]))
25+
assert scan0034.get("detector/data", ATTRS=True) == {
26+
"EX_required": "true",
27+
"type": "NX_INT",
28+
"units": "counts",
29+
}
30+
assert np.allclose(
31+
scan0034.get("instrument/analyser/a2"),
32+
np.array([242.0, 242.1, 242.2]),
33+
)
2434

2535
scan0035 = nexus_entries["scan0035"]
2636
assert scan0035.get("title") == "scan_title_35"
@@ -36,24 +46,37 @@ def test_to_nexus(nexus_entries):
3646
assert nexus_file["scan0034"].attrs["NX_class"] == "NXentry"
3747

3848

39-
def test_from_nexus():
49+
def test_from_nexus(nexus_entries):
4050
path_to_nexus_entry = "./test_data/scan_to_nexus_test.h5"
41-
nexus_entries = NexusEntry.from_nexus(path_to_nexus_entry)
42-
scan0034 = nexus_entries["scan0034"]
43-
assert scan0034.get("definition") == "NXtas"
51+
entries = NexusEntry.from_nexus(path_to_nexus_entry)
52+
53+
scan0034 = entries["scan0034"]
54+
assert scan0034["definition"] == nexus_entries["scan0034"]["definition"]
55+
assert np.allclose(
56+
scan0034["instrument"]["analyser"]["a2"]["dataset"],
57+
nexus_entries["scan0034"]["instrument"]["analyser"]["a2"]["dataset"],
58+
)
4459
assert np.allclose(scan0034.get("a2"), np.array([242.0, 242.1, 242.2]))
4560
assert scan0034.get("data", ATTRS=True) == {
4661
"EX_required": "true",
4762
"NX_class": "NXdata",
48-
"axes": "en",
63+
"axes": "a1",
4964
"signal": "detector",
5065
}
5166
assert scan0034.get("a3") is None
52-
assert scan0034.get("detector") is None
53-
assert scan0034.get("detector/data", ATTRS=True) == {"EX_required": "true", "type": "NX_INT", "units": "counts"}
54-
assert np.allclose(scan0034.get("instrument/analyser/a2"), np.array([242.0, 242.1, 242.2]))
67+
assert np.allclose(scan0034.get("detector"), np.array([1, 2, 3]))
68+
assert scan0034.get("detector/data", ATTRS=True) == {
69+
"EX_required": "true",
70+
"type": "NX_INT",
71+
"units": "counts",
72+
"target": "/scan0034/instrument/detector/data",
73+
}
74+
assert np.allclose(
75+
scan0034.get("instrument/analyser/a2"),
76+
np.array([242.0, 242.1, 242.2]),
77+
)
5578

56-
scan0035 = nexus_entries["scan0035"]
79+
scan0035 = entries["scan0035"]
5780
assert scan0035.get("title") == "scan_title_35"
5881

5982

@@ -73,19 +96,27 @@ def test_from_nexus_IPTS32124_CG4C_exp0424():
7396
assert np.allclose(scan0034.get("s1")[0:3], [36.14, 36.5025, 36.855])
7497

7598

76-
def test_from_spice_IPTS32124_CG4C_exp0424():
99+
def test_from_spice_IPTS32124_CG4C_exp0424_single_scan():
77100
path_to_spice_entry = "./test_data/exp424"
78-
nexus_entries = NexusEntry.from_spice(path_to_spice_entry, 34)
101+
scan0034 = NexusEntry.from_spice(path_to_spice_entry, 34)["scan0034"]
79102

80-
path_to_nexus_entry = "./test_data/spice_to_nexus_test_scan34.h5"
81-
for scan_num, nexus_entry in nexus_entries.items():
82-
nexus_entry.to_nexus(path_to_nexus_entry, scan_num)
103+
assert scan0034.get("definition") == "NXtas"
104+
assert scan0034.get("end_time") == "2024-07-03T02:41:28"
105+
assert np.allclose(scan0034.get("s1")[0:3], np.array([36.14, 36.5025, 36.855]))
83106

84-
scan0034 = NexusEntry.from_nexus(path_to_nexus_entry, 34)["scan0034"]
85107

108+
def test_from_spice_IPTS32124_CG4C_exp0424_all_scan():
109+
path_to_spice_entry = "./test_data/exp424"
110+
scans = NexusEntry.from_spice(path_to_spice_entry)
111+
112+
scan0034 = scans["scan0034"]
86113
assert scan0034.get("definition") == "NXtas"
87114
assert scan0034.get("end_time") == "2024-07-03T02:41:28"
88-
# assert np.allclose(scan0034.get("s1")[0:3], np.array([36.14, 36.5025, 36.855]))
115+
assert np.allclose(scan0034.get("s1")[0:3], np.array([36.14, 36.5025, 36.855]))
116+
117+
# scan 41 contains only one data point
118+
scan0041 = scans["scan0041"]
119+
assert scan0041.get("Pt.") == 3
89120

90121

91122
def test_get_from_daslogs():
@@ -132,6 +163,7 @@ def nexus_entries():
132163
"attrs": {"EX_required": "true", "NX_class": "NXdetector"},
133164
"data": {
134165
"attrs": {"EX_required": "true", "type": "NX_INT", "units": "counts"},
166+
"dataset": np.array([1, 2, 3]),
135167
},
136168
}
137169

@@ -169,7 +201,7 @@ def nexus_entries():
169201
"attrs": {
170202
"EX_required": "true",
171203
"NX_class": "NXdata",
172-
"axes": "en",
204+
"axes": "a1",
173205
"signal": "detector",
174206
}
175207
},

0 commit comments

Comments
 (0)