Add ability to load cif data

This commit is contained in:
usov_i 2022-04-12 12:05:42 +02:00
parent 4131eb31e7
commit 94df4869d4
2 changed files with 77 additions and 6 deletions

View File

@ -23,6 +23,8 @@ import pyzebra
def create(): def create():
cif_data = None
anglim_div = Div(text="Angular min/max limits:") anglim_div = Div(text="Angular min/max limits:")
sttgamma_ti = TextInput(title="stt/gamma", width=100) sttgamma_ti = TextInput(title="stt/gamma", width=100)
omega_ti = TextInput(title="omega", width=100) omega_ti = TextInput(title="omega", width=100)
@ -40,11 +42,17 @@ def create():
phi_ti.value = " ".join(ang_lims["phi"][:2]) phi_ti.value = " ".join(ang_lims["phi"][:2])
def _update_params(params): def _update_params(params):
if "WAVE" in params:
wavelen_input.value = float(params["WAVE"]) wavelen_input.value = float(params["WAVE"])
if "SPGR" in params:
cryst_space_group.value = params["SPGR"] cryst_space_group.value = params["SPGR"]
if "CELL" in params:
cryst_cell.value = params["CELL"] cryst_cell.value = params["CELL"]
if "UBMAT" in params:
ub_matrix.value = " ".join(params["UBMAT"]) ub_matrix.value = " ".join(params["UBMAT"])
if "HLIM" in params:
ranges_hkl.value = params["HLIM"] ranges_hkl.value = params["HLIM"]
if "SRANG" in params:
ranges_expression.value = params["SRANG"] ranges_expression.value = params["SRANG"]
def open_geom_callback(_attr, _old, new): def open_geom_callback(_attr, _old, new):
@ -63,8 +71,15 @@ def create():
open_cfl = FileInput(accept=".cfl", width=200) open_cfl = FileInput(accept=".cfl", width=200)
open_cfl.on_change("value", open_cfl_callback) open_cfl.on_change("value", open_cfl_callback)
def open_cif_callback(_attr, _old, new):
nonlocal cif_data
with io.StringIO(base64.b64decode(new).decode()) as fileobj:
cif_data = pyzebra.read_cif_file(fileobj)
_update_params(cif_data)
open_cif_div = Div(text="or open CIF:") open_cif_div = Div(text="or open CIF:")
open_cif = FileInput(accept=".cif", width=200) open_cif = FileInput(accept=".cif", width=200)
open_cif.on_change("value", open_cif_callback)
wavelen_input = NumericInput(title="\u200B", width=70, mode="float") wavelen_input = NumericInput(title="\u200B", width=70, mode="float")

View File

@ -180,3 +180,59 @@ def read_cfl_file(fileobj):
params[param] = val params[param] = val
return params return params
def read_cif_file(fileobj):
params = {"SPGR": None, "CELL": None, "ATOM": []}
cell_params = {
"_cell_length_a": None,
"_cell_length_b": None,
"_cell_length_c": None,
"_cell_angle_alpha": None,
"_cell_angle_beta": None,
"_cell_angle_gamma": None,
}
cell_param_names = tuple(cell_params)
atom_param_pos = {
"_atom_site_label": 0,
"_atom_site_type_symbol": None,
"_atom_site_fract_x": None,
"_atom_site_fract_y": None,
"_atom_site_fract_z": None,
"_atom_site_U_iso_or_equiv": None,
"_atom_site_occupancy": None,
}
atom_param_names = tuple(atom_param_pos)
for line in fileobj:
line = line.strip()
if line.startswith("_space_group_name_H-M_alt"):
_, val = line.split(maxsplit=1)
params["SPGR"] = val.strip("'")
elif line.startswith(cell_param_names):
param, val = line.split(maxsplit=1)
cell_params[param] = val
elif line.startswith("_atom_site_label"): # assume this is the start of atom data
for ind, line in enumerate(fileobj, start=1):
line = line.strip()
# read fields
if line.startswith("_atom_site"):
if line.startswith(atom_param_names):
atom_param_pos[line] = ind
continue
# read data till an empty line
if not line:
break
vals = line.split()
params["ATOM"].append(" ".join([vals[ind] for ind in atom_param_pos.values()]))
if None not in cell_params.values():
params["CELL"] = " ".join(cell_params.values())
return params