From 8c8975339bca38312691f26225bb0de2b4ecb5e8 Mon Sep 17 00:00:00 2001 From: ahxbcn Date: Wed, 4 Mar 2026 19:04:48 +0800 Subject: [PATCH] feature: get kpath from structure file --- src/abacusagent/modules/symmetry.py | 20 +++++- src/abacusagent/modules/util/symmetry.py | 84 +++--------------------- 2 files changed, 28 insertions(+), 76 deletions(-) diff --git a/src/abacusagent/modules/symmetry.py b/src/abacusagent/modules/symmetry.py index 08a8862..f0c001c 100644 --- a/src/abacusagent/modules/symmetry.py +++ b/src/abacusagent/modules/symmetry.py @@ -1,8 +1,26 @@ from pathlib import Path -from typing import Dict, Any +from typing import Dict, Any, Literal from abacusagent.init_mcp import mcp +@mcp.tool() +def get_high_symm_points_from_stru(stru_file: Path, + stru_type: Literal['cif', 'poscar', 'abacus/stru'] = 'cif' +) -> Dict[str, Any]: + """ + Get high symmetry points and kpath from structure file. + Args: + stru_file (Path): Absolute path to the structure file. + stru_type (Literal): Type of the structure file, can be 'cif', 'poscar', or 'abacus/stru'. + Returns: + A Dictionary with keys: + - high_symm_points: A list of dictionary, where the key is the label of the point, and the value is the fractional coordinates of the point. + - kpath: A list of tuples, where each tuple is a pair of labels of the two points in the kpath. + """ + from abacusagent.modules.util.symmetry import get_high_symm_points_from_stru as _get_high_symm_points_from_stru + + return _get_high_symm_points_from_stru(stru_file, stru_type) + @mcp.tool() def get_high_symm_points_from_abacus_inputs_dir(abacusjob_dir: Path) -> Dict[str, Any]: """ diff --git a/src/abacusagent/modules/util/symmetry.py b/src/abacusagent/modules/util/symmetry.py index 9e48a97..e16530c 100644 --- a/src/abacusagent/modules/util/symmetry.py +++ b/src/abacusagent/modules/util/symmetry.py @@ -2,94 +2,28 @@ from pathlib import Path from typing import Literal, Dict, Any -from abacustest.lib_prepare.abacus import AbacusStru, ReadInput +from abacustest import AbacusSTRU, ReadInput def get_high_symm_points_from_stru(stru_file: Path, stru_type: Literal['cif', 'poscar', 'abacus/stru'] = 'cif' -) -> Any: +) -> Dict[str, Any]: """ Get high symmetry points and kpath from structure file. Args: stru_file (Path): Absolute path to the structure file. stru_type (Literal): Type of the structure file, can be 'cif', 'poscar', or 'abacus/stru'. Returns: - A tuple containing high symmetry points and kpath. + A Dictionary with keys: + - high_symm_points: A list of dictionary, where the key is the label of the point, and the value is the fractional coordinates of the point. + - kpath: A list of tuples, where each tuple is a pair of labels of the two points in the kpath. """ - import seekpath - from ase.io import read - - if stru_type in ['cif', 'poscar']: - stru = read(stru_file) - cell = stru.get_cell() - coord = stru.get_positions() - labels = stru.get_chemical_symbols() - label = [] - for i in labels: - if i not in label: - label.append(i) - number = [label.index(i) for i in labels] - stru_final = (cell, coord, number) - elif stru_type == 'abacus/stru': - stru = AbacusStru.ReadStru(stru_file) - cell = stru.get_cell(bohr=True) - coord = stru.get_coord(bohr=True) - labels = stru.get_label() - number = stru.get_label() - label = [] - for i in labels: - if i not in label: - label.append(i) - number = [label.index(i) for i in labels] - stru_final = (cell,coord,number) + if stru_type in ['cif', 'poscar', 'abacus/stru']: + stru = AbacusSTRU.read(stru_file, stru_type) else: raise ValueError("stru_type should be 'cif', 'poscar', or 'abacus/stru'") - sym_prec = 1e-5 - while sym_prec <= 1e-2: - try: - kpath = seekpath.get_path_orig_cell(stru_final, - with_time_reversal=True, - recipe='hpkot', - threshold=1e-5, - symprec=sym_prec, - angle_tolerance=-1.0) - break - except: - print("WARNING: get_path failed, increase symprec to %e" % (sym_prec*10)) - sym_prec *= 10 - - if sym_prec > 1e-2: - print(f"Symmetry precision {sym_prec} is too large") - - concatenated_kpath, path = [], None - for path_idx, path_line in enumerate(kpath['path']): - path_line_start, path_line_end = path_line[0], path_line[1] - if path is None: - path = [path_line_start, path_line_end] - else: - if path_idx == len(kpath['path']) - 1: - if path is None: - path.append(path_line_start) - path.append(path_line_end) - concatenated_kpath.append(path) - path = None - elif path_idx < len(kpath['path']) - 1: - if path is None: - path.append(path_line_start) - path.append(path_line_end) - next_line_start = kpath['path'][path_idx+1][0] - if path_line_end != next_line_start: - concatenated_kpath.append(path) - path = None - else: - if path is None: - path = [path_line_start, path_line_end] - else: - path.append(path_line_end) - concatenated_kpath.append(path) - - kpath['path'] = concatenated_kpath - return kpath + high_symm_points, kpath = stru.get_kline() + return {"high_symm_points": high_symm_points, "kpath": kpath} def get_high_symm_points_from_abacus_inputs_dir(abacus_inputs_dir: Path) -> Dict[str, Any]: """