Source code for qtdraw.widget.validator

"""
Validator type.

- type: option.
    - int: (min, max)
    - float: (min, max, digit)
    - list_int: (shape, var)
    - list_float: (shape, var ,digit)
    - math: (shape, var)
    - site: (use var?)
    - bond: (use var?)
    - site_bond: (use var?)
    - vector_site_bond: (use var?)
    - orbital_site_bond: (use var?)
"""

import numpy as np

from qtdraw.util.util import str_to_sympy, to_latex

DISPLAY_DIGIT = 5


# ==================================================
[docs] def check_symbol(expr): """ Check symbol. Args: expr (sympy or ndarray) Returns: - (bool) -- if expr contains symbol, return True otherwise False. """ if isinstance(expr, np.ndarray): return any(check_symbol(e) for e in expr.flat) return bool(expr.free_symbols)
# ==================================================
[docs] def convert_to_bond(bond, use_var=False): """ Convert to bond from str. Args: bond (str): bond. use_var (bool, optional): use [x,y,z] for site/bond ? Returns: - (ndarray) -- bond vector. - (ndarray) -- bond center. Note: - bond string is "[tail];[head]/[vector]@[center]/[start]:[vector]". """ var = ["x", "y", "z"] if use_var else [""] try: if ";" in bond: t, h = bond.split(";") t = str_to_sympy(t, check_var=var, check_shape=(3,)) h = str_to_sympy(h, check_var=var, check_shape=(3,)) v = h - t c = (t + h) / 2 elif "@" in bond: v, c = bond.split("@") v = str_to_sympy(v, check_var=var, check_shape=(3,)) c = str_to_sympy(c, check_var=var, check_shape=(3,)) elif ":" in bond: s, v = bond.split(":") s = str_to_sympy(s, check_var=var, check_shape=(3,)) v = str_to_sympy(v, check_var=var, check_shape=(3,)) c = s + v / 2 else: raise Exception(f"invalid separator in {bond}.") return v, c except Exception: return None, None
# ==================================================
[docs] def validator_int(text, **opt): """ Validator for int. Args: text (str): int string. opt (dict, optional): option, "min/max". (default: "*","*") Returns: - (str) -- formatted string if it is valid, otherwise None. """ try: s = int(text) except ValueError: return None r_min = opt.get("min", "*") r_max = opt.get("max", "*") if (r_min != "*" and s < int(r_min)) or (r_max != "*" and s > int(r_max)): return None return str(s)
# ==================================================
[docs] def validator_float(text, **opt): """ Validator for float. Args: text (str): float string. opt (dict, optional): option, "min/max/digit". (default: "*","*",5) Returns: - (str) -- formatted string if it is valid, otherwise None. """ try: s = float(text) except ValueError: return None r_min = opt.get("min", "*") r_max = opt.get("max", "*") digit = opt.get("digit", DISPLAY_DIGIT) if (r_min != "*" and s < float(r_min)) or (r_max != "*" and s > float(r_max)): return None return f"{np.round(s, digit):.{digit}f}"
# ==================================================
[docs] def validator_list_float(text, **opt): """ Validator for list float. Args: text (str): string with list. opt (dict, optional): option, "digit/shape/var". (default: 5,None,[""]) e.g., 15, (), (n,), (n,m), ..., ["x", "y", ...]. Returns: - (str) -- formatted string if it is valid, otherwise None. """ digit = opt.get("digit", DISPLAY_DIGIT) shape = opt.get("shape", None) var = opt.get("var", [""]) try: s = str_to_sympy(text, check_var=var, check_shape=shape) except Exception: return None if digit is not None and not check_symbol(s): if isinstance(s, np.ndarray): s = np.vectorize(lambda x: f"{float(x):.{digit}f}")(s) return str(s.tolist()).replace("'", "").replace(" ", "") else: return f"{float(s):.{digit}f}" if isinstance(s, np.ndarray): return str(s.tolist()).replace(" ", "") else: return str(s)
# ==================================================
[docs] def validator_list_int(text, **opt): """ Validator for list int. Args: text (str): string with list. opt (dict, optional): option, "shape/var". (default: None,[""]) e.g., (), (n,), (n,m), ..., ["x", "y", ...]. Returns: - (str) -- formatted string if it is valid, otherwise None. """ shape = opt.get("shape", None) var = opt.get("var", [""]) try: s = str_to_sympy(text, check_var=var, check_shape=shape) except Exception: return None if not check_symbol(s): try: if isinstance(s, np.ndarray): s = np.vectorize(lambda x: f"{int(x)}")(s) return str(s.tolist()).replace("'", "").replace(" ", "") else: return f"{int(s)}" except Exception: return None if isinstance(s, np.ndarray): return str(s.tolist()).replace(" ", "") else: return str(s)
# ==================================================
[docs] def validator_math(text, **opt): """ Validator for math to LaTeX. Args: text (str): sympy string. opt (dict, optional): option, "shape/var". (default: None,None) Returns: - (str) -- LaTeX string if it is valid, otherwise None. """ shape = opt.get("shape", None) var = opt.get("var", None) try: s = str_to_sympy(text, check_var=var, check_shape=shape) except Exception: return None if isinstance(s, np.ndarray): s = str(to_latex(s).tolist()).replace("'", "").replace("\\\\", "\\") else: s = to_latex(s) return s
# ==================================================
[docs] def validator_site(s, use_var=False): """ Validator for site. Args: s (str): site string, [x,y,z]. use_var (bool, optional): use [x,y,z] for site ? Returns: - (str) -- input s if it is valid, otherwise None. """ var = ["x", "y", "z"] if use_var else [""] return validator_list_float(s, shape=(3,), var=var)
# ==================================================
[docs] def validator_bond(s, use_var=False): """ Validator for bond. Args: s (str): bond string. use_var (bool, optional): use [x,y,z] for bond ? Returns: - (str) -- input s if it is valid, otherwise None. Note: - bond sytles, start:vector, tail;head, vector@center, are accepted. """ def fmt(a): return str([f"{i:.{DISPLAY_DIGIT}f}" for i in a]).replace("'", "").replace(" ", "") v, c = convert_to_bond(s, use_var) return None if v is None else f"{fmt(v)}@{fmt(c)}"
# ==================================================
[docs] def validator_site_bond(s, use_var=False): """ Validator for site or bond. Args: s (str): site or bond string. use_var (bool, optional): use [x,y,z] for site/bond ? Returns: - (str) -- input s if it is valid, otherwise None. Note: - bond sytles, start:vector, tail;head, vector@center, are accepted. """ if (":" in s) or (";" in s) or ("@" in s): return validator_bond(s, use_var) else: return validator_site(s, use_var)
# ==================================================
[docs] def validator_vector_site_bond(s, use_var=False): """ Validator for vector on site or bond. Args: s (str): vector on site or bond string. use_var (bool, optional): use [x,y,z] for site/bond ? Returns: - (str) -- input s if it is valid, otherwise None. Note: - bond sytles, start:vector, tail;head, vector@center, are accepted. """ if "#" not in s: return None v, sb = s.split("#", 1) v = validator_site(v, use_var) sb = validator_site_bond(sb, use_var) return None if v is None or sb is None else v + "#" + sb
# ==================================================
[docs] def validator_orbital_site_bond(s, use_var=False): """ Validator for orbital on site or bond. Args: s (str): orbital on site or bond string. use_var (bool, optional): use [x,y,z] for site/bond ? Returns: - (str) -- input s if it is valid, otherwise None. Note: - orbital can contain x, y, z, r. - bond sytles, start:vector, tail;head, vector@center, are accepted. """ if "#" not in s: return None v, sb = s.split("#", 1) v = validator_list_float(v, var=["x", "y", "z", "r"], shape=()) sb = validator_site_bond(sb, use_var) return None if v is None or sb is None else v + "#" + sb