diff --git a/pyzebra/app/panel_ccl_prepare.py b/pyzebra/app/panel_ccl_prepare.py index 0f9c7bb..c3b88c6 100644 --- a/pyzebra/app/panel_ccl_prepare.py +++ b/pyzebra/app/panel_ccl_prepare.py @@ -23,6 +23,8 @@ import pyzebra def create(): + cif_data = None + anglim_div = Div(text="Angular min/max limits:") sttgamma_ti = TextInput(title="stt/gamma", width=100) omega_ti = TextInput(title="omega", width=100) @@ -40,12 +42,18 @@ def create(): phi_ti.value = " ".join(ang_lims["phi"][:2]) def _update_params(params): - wavelen_input.value = float(params["WAVE"]) - cryst_space_group.value = params["SPGR"] - cryst_cell.value = params["CELL"] - ub_matrix.value = " ".join(params["UBMAT"]) - ranges_hkl.value = params["HLIM"] - ranges_expression.value = params["SRANG"] + if "WAVE" in params: + wavelen_input.value = float(params["WAVE"]) + if "SPGR" in params: + cryst_space_group.value = params["SPGR"] + if "CELL" in params: + cryst_cell.value = params["CELL"] + if "UBMAT" in params: + ub_matrix.value = " ".join(params["UBMAT"]) + if "HLIM" in params: + ranges_hkl.value = params["HLIM"] + if "SRANG" in params: + ranges_expression.value = params["SRANG"] def open_geom_callback(_attr, _old, new): with io.StringIO(base64.b64decode(new).decode()) as fileobj: @@ -63,8 +71,15 @@ def create(): open_cfl = FileInput(accept=".cfl", width=200) 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 = FileInput(accept=".cif", width=200) + open_cif.on_change("value", open_cif_callback) wavelen_input = NumericInput(title="\u200B", width=70, mode="float") diff --git a/pyzebra/sxtal_refgen.py b/pyzebra/sxtal_refgen.py index 2de5660..c806a0d 100644 --- a/pyzebra/sxtal_refgen.py +++ b/pyzebra/sxtal_refgen.py @@ -180,3 +180,59 @@ def read_cfl_file(fileobj): params[param] = val 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