From 9eba459a16263da8cbeb5064e2a057c8c0bc855a Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Tue, 30 Jul 2024 11:36:09 +0200 Subject: [PATCH 01/15] start revision 2024.1 --- larch/xrd/struct2xas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index aa11542bd..cdf0c1adc 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -43,7 +43,7 @@ __author__ = ["Beatriz G. Foschiani", "Mauro Rovezzi"] __email__ = ["beatrizgfoschiani@gmail.com", "mauro.rovezzi@esrf.fr"] __credits__ = ["Jade Chongsathapornpong", "Marius Retegan"] -__version__ = "2023.3.0" +__version__ = "2024.1.0" # initialize the logger From 76c5ab5b15836adcf4eb8e7699a089bf68940513 Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Tue, 30 Jul 2024 12:19:34 +0200 Subject: [PATCH 02/15] format --- larch/xrd/struct2xas.py | 1 + 1 file changed, 1 insertion(+) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index cdf0c1adc..2694aa9f1 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -4,6 +4,7 @@ """ Struct2XAS: convert CIFs and XYZs files to FDMNES and FEFF inputs """ + # main imports import os import json From 110ffb809a4369ae36937b6216517f56f35802aa Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Tue, 30 Jul 2024 17:36:51 +0200 Subject: [PATCH 03/15] cleaning coord env infos --- larch/xrd/struct2xas.py | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 2694aa9f1..d50f74fc9 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -369,7 +369,7 @@ def get_abs_sites(self): The lists inside the list contain the following respective information: [ - abs_idx, # index identifier of the absorber site + abs_idx, # index identifier of the absorber site # used by self.set_abs_site(). species_string, # The specie for absorber sites. frac_coords, # Fractional coordinate position @@ -618,6 +618,7 @@ def get_coord_envs(self): """ abs_sites = self.get_abs_sites() idx_abs_site = abs_sites[self.abs_site][-1] + coord_env_list = [] if self.is_cif: from pymatgen.analysis.bond_valence import BVAnalyzer @@ -642,7 +643,6 @@ def get_coord_envs(self): except ValueError: valences = "undefined" - coord_env_list = [] se = lgf.compute_structure_environments( max_cn=6, valences=valences, @@ -659,32 +659,26 @@ def get_coord_envs(self): strategy=strategy, structure_environments=se ) coord_env_ce = lse.coordination_environments[idx_abs_site] - ngbs_sites = lse._all_nbs_sites - coord_env_list.append( - [ - f"Coord. Env. for Site {abs_sites[self.abs_site][0]}", - coord_env_ce, - ngbs_sites, - ] - ) + coord_env = lse._all_nbs_sites if self.is_xyz: from pymatgen.analysis.local_env import CrystalNN obj = CrystalNN() - coord_env_list = [] + coord_env = obj.get_nn_info(self.struct, idx_abs_site) for site in coord_env: site["site"].cart_coords = self.struct[site["site_index"]].coords coord_dict = obj.get_cn_dict(self.struct, idx_abs_site) - coord_env_list.append( - [ - f"Coord. Env. for Site {abs_sites[self.abs_site][0]}", - {"ce_symbol": f"Elements Dict = {coord_dict}"}, - coord_env, - ] - ) + coord_env_ce = {"ce_symbol": f"Elements Dict = {coord_dict}"} + coord_env_list.append( + [ + f"Coord. Env. for Site {abs_sites[self.abs_site][0]}", + coord_env_ce, + coord_env, + ] + ) return coord_env_list def get_coord_envs_info(self): @@ -696,7 +690,11 @@ def get_coord_envs_info(self): abs_site_coord = self.get_abs_sites()[self.abs_site][4] elems_dist = [] - for site in coord_env[2]: + sites = coord_env[2] + if len(sites) == 0: + logger.warning("Empty coordination environment") + return None + for site in sites: if self.is_cif: coord_sym = [ coord_env[1][i]["ce_symbol"] for i in range(len(coord_env[1])) From 4008a6020bfb8501d976c5a00d1767320ff4fff7 Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 09:04:33 +0200 Subject: [PATCH 04/15] add sbatch generator --- larch/xrd/struct2xas.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index d50f74fc9..49ff483bf 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -941,6 +941,28 @@ def make_input_fdmnes( logger.info(f"written FDMNES input -> {fnout}") + def make_sbatch(self, template: str = None, **kwargs): + """Generates a SBATCH file (SLURM workload manager) using a template + + Arguments + --------- + + template: str + path to the SBATCH template file + + **kwargs + keyword arguments to be replaced in the template file + + Returns + ------- + None: writes `job.sbatch` + + """ + assert os.path.isfile(template), "template file not existing" + with open(os.path.join(self.outdir, "job.sbatch"), "w") as fp, open(template) as tp: + fp.write(tp.read().format(**kwargs)) + logger.info(f"written {fp.name}") + def make_input_feff( self, radius=7, From 0d8a94a40f168bca5574f1e7a6333e8f61e24c56 Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 10:27:29 +0200 Subject: [PATCH 05/15] start add typing --- larch/xrd/struct2xas.py | 74 +++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 49ff483bf..7dd160a4a 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -9,7 +9,9 @@ import os import json import time -import tempfile +from typing import Union, List#, Any, Dict + +# import tempfile import numpy as np # pymatgen @@ -20,7 +22,8 @@ import larch.utils.logging as logging from larch.utils import mkdir, unixpath -from larch.utils.strutils import fix_filename, unique_name, strict_ascii + +# from larch.utils.strutils import fix_filename, unique_name, strict_ascii from larch.site_config import user_larchdir from larch.io import read_ascii from larch.math.convolution1D import lin_gamma, conv @@ -767,7 +770,12 @@ def make_cluster(self, radius): return atoms def make_input_fdmnes( - self, radius=7, parent_path=None, template=None, green=True, **kwargs + self, + parent_path: str = None, + template: str = None, + radius: float = 7, + green: str = True, + **kwargs, ): """ Create a fdmnes input from a template. @@ -794,15 +802,6 @@ def make_input_fdmnes( directory structure: {parent_path}/fdmnes/{self.file_name}/{self.abs_atom}/frame{self.frame}/site{self.abs_site}/ """ - replacements = {} - replacements.update(**kwargs) - replacements["version"] = __version__ - - if template is None: - template = os.path.join( - os.path.dirname(os.path.realpath(__file__)), "templates", "fdmnes.tmpl" - ) - if parent_path is None: parent_path = self.folders["fdmnes"] @@ -814,6 +813,16 @@ def make_input_fdmnes( f"site{self.abs_site}", ) + if template is None: + template = os.path.join( + os.path.dirname(os.path.realpath(__file__)), "templates", "fdmnes.tmpl" + ) + assert os.path.isfile(template), "wrong template path" + + replacements = {} + replacements.update(**kwargs) + replacements["version"] = __version__ + method = "green" if green else "" absorber = "" crystal = "" @@ -941,9 +950,9 @@ def make_input_fdmnes( logger.info(f"written FDMNES input -> {fnout}") - def make_sbatch(self, template: str = None, **kwargs): + def make_sbatch(self, template: str, **kwargs): """Generates a SBATCH file (SLURM workload manager) using a template - + Arguments --------- @@ -956,22 +965,24 @@ def make_sbatch(self, template: str = None, **kwargs): Returns ------- None: writes `job.sbatch` - + """ - assert os.path.isfile(template), "template file not existing" - with open(os.path.join(self.outdir, "job.sbatch"), "w") as fp, open(template) as tp: + assert os.path.isfile(template), "wrong template path" + with open(os.path.join(self.outdir, "job.sbatch"), "w") as fp, open( + template + ) as tp: fp.write(tp.read().format(**kwargs)) logger.info(f"written {fp.name}") def make_input_feff( self, - radius=7, - parent_path=None, - template=None, - feff_comment="*", - edge="K", - sig2=None, - debye=None, + parent_path: str = None, + template: str = None, + radius: float = 7, + feff_comment: str = "*", + edge: str = "K", + sig2: Union[float, None] = None, + debye: Union[List[float, float], None] = None, **kwargs, ): """ @@ -1005,12 +1016,10 @@ def make_input_feff( None -> writes FEFF input to disk directory structure: {parent_path}/feff/{self.file_name}/{self.abs_atom}/frame{self.frame}/site{self.abs_site}/ """ - replacements = {} - replacements.update(**kwargs) - replacements["version"] = __version__ if parent_path is None: parent_path = self.folders["feff"] + self.outdir = os.path.join( parent_path, self.file_name, @@ -1025,6 +1034,11 @@ def make_input_feff( "templates", "feff_exafs.tmpl", ) + assert os.path.isfile(template), "wrong template path" + + replacements = {} + replacements.update(**kwargs) + replacements["version"] = __version__ if sig2 is None: use_sig2 = "*" @@ -1364,7 +1378,9 @@ def convolve_data( return group -def save_cif_from_mp(api_key, material_id, parent_path=None): +def save_cif_from_mp( + api_key: str, material_id: str, parent_path: str = None +) -> list[str, str]: """Collect a CIF file from the Materials Project Database, given the material id Parameters @@ -1398,7 +1414,7 @@ def save_cif_from_mp(api_key, material_id, parent_path=None): return [parent_path, outfn] -def save_mp_structure(api_key, material_id, parent_path=None): +def save_mp_structure(api_key: str, material_id: str, parent_path: str = None) -> str: """Save structure from Materials Project Database as json, given the material id Parameters From 069019fd13b7626bcc34622554713a1d4e4b90ee Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 11:07:50 +0200 Subject: [PATCH 06/15] add newjob --- larch/xrd/struct2xas.py | 52 +++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 7dd160a4a..275eca60d 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -9,7 +9,8 @@ import os import json import time -from typing import Union, List#, Any, Dict +from dataclasses import dataclass +from typing import Union, List # , Any, Dict # import tempfile import numpy as np @@ -113,6 +114,14 @@ def structure_folders(): return folders +@dataclass +class Job: + num: int #: index of the job + description: str #: description + type: Union[str, None] #: 'fdmnes', 'feff' + timestamp: str #: creation timestamp + + class Struct2XAS: """Class to convert data from CIF and XYZ files to FDMNES and FEFF inputs""" @@ -149,7 +158,6 @@ def __init__(self, file, abs_atom) -> None: For creating the object from cif file, a pymatgen structure is generated with symmetry information from cif file. """ - self.file = file self.abs_atom = abs_atom self.frame = 0 @@ -162,6 +170,8 @@ def __init__(self, file, abs_atom) -> None: self.species = self._get_species() self.parent_path = user_larchdir self.folders = structure_folders() + self.njob = 0 + self.jobs = [] logger.info( f"Frames: {self.nframes}, Absorbing sites: {self.nabs_sites}. (Indexes for frames and abs_sites start at 0)" ) @@ -772,6 +782,7 @@ def make_cluster(self, radius): def make_input_fdmnes( self, parent_path: str = None, + newjob: Union[str, None] = False, template: str = None, radius: float = 7, green: str = True, @@ -782,13 +793,15 @@ def make_input_fdmnes( Arguments --------- - radius : float, [7] - radius for fdmnes calculation in Angstrom parent_path : str, [None] path to the parent directory where the input files are stored if None it will create a temporary directory + newjob : str or None [None] + if a string, a new job is created with the given description template : str, [None] full path to the template file + radius : float, [7] + radius for fdmnes calculation in Angstrom green : boolean [True] True: use `Green` (muffin-tin potentials, faster) False: use finite-difference method (slower) @@ -805,12 +818,23 @@ def make_input_fdmnes( if parent_path is None: parent_path = self.folders["fdmnes"] + if newjob is not None: + self.njob += 1 + job = Job( + num=self.njob, + description=newjob, + type="fdmnes", + timestamp=_get_timestamp(), + ) + self.jobs.append(job) + self.outdir = os.path.join( parent_path, self.file_name, self.abs_atom, f"frame{self.frame}", f"site{self.abs_site}", + f"job{self.njob}", ) if template is None: @@ -977,12 +1001,13 @@ def make_sbatch(self, template: str, **kwargs): def make_input_feff( self, parent_path: str = None, + newjob: Union[str, None] = False, template: str = None, radius: float = 7, feff_comment: str = "*", edge: str = "K", sig2: Union[float, None] = None, - debye: Union[List[float, float], None] = None, + debye: Union[List[float], None] = None, **kwargs, ): """ @@ -990,13 +1015,15 @@ def make_input_feff( Arguments --------- - radius : float, [7] - radius for feff calculation [Angstrom]. parent_path : str, [None] path to the parent directory where the input files are stored if None it will create a temporary directory + newjob : str or None [None] + if a string, a new job is created with the given description template : str, [None] full path to the template file + radius : float, [7] + radius for feff calculation [Angstrom]. feff_coment : str, ["*"] comment character used in the input file sig2 : float or None, [None] @@ -1020,12 +1047,23 @@ def make_input_feff( if parent_path is None: parent_path = self.folders["feff"] + if newjob is not None: + self.njob += 1 + job = Job( + num=self.njob, + description=newjob, + type="feff", + timestamp=_get_timestamp(), + ) + self.jobs.append(job) + self.outdir = os.path.join( parent_path, self.file_name, self.abs_atom, f"frame{self.frame}", f"site{self.abs_site}", + f"job{self.njob}", ) if template is None: From 49f815cccc3b06128fb9bcf1df78c01d19608953 Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 12:39:02 +0200 Subject: [PATCH 07/15] clarifying parent_path directory structure --- larch/xrd/struct2xas.py | 48 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 275eca60d..b2bb39344 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -125,7 +125,7 @@ class Job: class Struct2XAS: """Class to convert data from CIF and XYZ files to FDMNES and FEFF inputs""" - def __init__(self, file, abs_atom) -> None: + def __init__(self, file: str, abs_atom: str, parent_path: Union[str, None]) -> None: """ Arguments @@ -147,7 +147,7 @@ def __init__(self, file, abs_atom) -> None: Structures from xyz files are always considered non-symmetric for the lack of lattice information. For creating the object from an XYZ file, a non-symmetric `structure` object from pymatgen is - generated (spacegroup: P1) from a `molecule` one via + generated (spacegroup: P1) from a `molecule` via :func:`xyz2struct`. The lattice parameters chosen for this structure are arbitrary and are based on the size of the molecule, as are the fractional coordinates. Therefore, the analysis of this @@ -168,10 +168,16 @@ def __init__(self, file, abs_atom) -> None: self.nabs_sites = len(self.get_abs_sites()) self.elems = self._get_elems() self.species = self._get_species() - self.parent_path = user_larchdir + if parent_path is None: + self.parent_path = user_larchdir + else: + self.parent_path = parent_path self.folders = structure_folders() self.njob = 0 self.jobs = [] + self.tmpl_fdmnes = None + self.tmpl_feff = None + self.tmpl_sbatch = None logger.info( f"Frames: {self.nframes}, Absorbing sites: {self.nabs_sites}. (Indexes for frames and abs_sites start at 0)" ) @@ -795,7 +801,7 @@ def make_input_fdmnes( --------- parent_path : str, [None] path to the parent directory where the input files are stored - if None it will create a temporary directory + (under `fdmnes` directory) newjob : str or None [None] if a string, a new job is created with the given description template : str, [None] @@ -812,11 +818,18 @@ def make_input_fdmnes( Returns ------- None -> writes FDMNES input to disk - directory structure: {parent_path}/fdmnes/{self.file_name}/{self.abs_atom}/frame{self.frame}/site{self.abs_site}/ + directory structure: + + {parent_path} + |+ fdmnes + ||+ {file_name} + |||+ {abs_atom} + ||||+ frame{nframe} + |||||+ site{abs_site} + ||||||+ job{njob} """ if parent_path is None: - parent_path = self.folders["fdmnes"] + parent_path = self.parent_path if newjob is not None: self.njob += 1 @@ -827,9 +840,10 @@ def make_input_fdmnes( timestamp=_get_timestamp(), ) self.jobs.append(job) - + self.outdir = os.path.join( parent_path, + "fdmnes", self.file_name, self.abs_atom, f"frame{self.frame}", @@ -1017,7 +1031,7 @@ def make_input_feff( --------- parent_path : str, [None] path to the parent directory where the input files are stored - if None it will create a temporary directory + (under "feff" directory) newjob : str or None [None] if a string, a new job is created with the given description template : str, [None] @@ -1041,11 +1055,18 @@ def make_input_feff( Returns ------- None -> writes FEFF input to disk - directory structure: {parent_path}/feff/{self.file_name}/{self.abs_atom}/frame{self.frame}/site{self.abs_site}/ + directory structure: + + {parent_path} + |+ feff + ||+ {file_name} + |||+ {abs_atom} + ||||+ frame{nframe} + |||||+ site{abs_site} + ||||||+ job{njob} """ if parent_path is None: - parent_path = self.folders["feff"] + parent_path = self.parent_path if newjob is not None: self.njob += 1 @@ -1059,6 +1080,7 @@ def make_input_feff( self.outdir = os.path.join( parent_path, + "feff", self.file_name, self.abs_atom, f"frame{self.frame}", @@ -1428,8 +1450,8 @@ def save_cif_from_mp( material id : str material id (format mp-xxxx) from Materials Project parent_path : str - path where to store the CIF files - if None, a temporary one is created + output where to store the CIF files + if None, user_larchdir + 'mp_structs' is used Returns ------- @@ -1462,7 +1484,7 @@ def save_mp_structure(api_key: str, material_id: str, parent_path: str = None) - material id : str material id (format mp-xxxx) from Materials Project parent_path : str - path where to store the Structure files + output path where to store the Structure files if None, user_larchdir + 'mp_structs' is used Returns From ba49716fb6e8463110a8536cc16fcbad9c234e89 Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 16:48:06 +0200 Subject: [PATCH 08/15] fix newjob --- larch/xrd/struct2xas.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index b2bb39344..107c6ba30 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -120,12 +120,15 @@ class Job: description: str #: description type: Union[str, None] #: 'fdmnes', 'feff' timestamp: str #: creation timestamp + path: Union[str, None] #: path for the calculation class Struct2XAS: """Class to convert data from CIF and XYZ files to FDMNES and FEFF inputs""" - def __init__(self, file: str, abs_atom: str, parent_path: Union[str, None]) -> None: + def __init__( + self, file: str, abs_atom: str, parent_path: Union[str, None] = None + ) -> None: """ Arguments @@ -788,7 +791,7 @@ def make_cluster(self, radius): def make_input_fdmnes( self, parent_path: str = None, - newjob: Union[str, None] = False, + newjob: Union[str, None] = None, template: str = None, radius: float = 7, green: str = True, @@ -831,18 +834,19 @@ def make_input_fdmnes( if parent_path is None: parent_path = self.parent_path - if newjob is not None: + if (newjob is not None) or (self.njob == 0): self.njob += 1 job = Job( num=self.njob, description=newjob, type="fdmnes", timestamp=_get_timestamp(), + path=None, ) self.jobs.append(job) - - self.outdir = os.path.join( - parent_path, + else: + job = self.jobs[self.njob - 1] + calc_path = os.path.join( "fdmnes", self.file_name, self.abs_atom, @@ -850,6 +854,8 @@ def make_input_fdmnes( f"site{self.abs_site}", f"job{self.njob}", ) + job.path = calc_path + self.outdir = os.path.join(parent_path, calc_path) if template is None: template = os.path.join( @@ -986,7 +992,7 @@ def make_input_fdmnes( with open(os.path.join(self.outdir, "fdmfile.txt"), "w") as fp: fp.write("1\njob_inp.txt") - logger.info(f"written FDMNES input -> {fnout}") + logger.info(f"written input for `/{job.path}`") def make_sbatch(self, template: str, **kwargs): """Generates a SBATCH file (SLURM workload manager) using a template @@ -1015,7 +1021,7 @@ def make_sbatch(self, template: str, **kwargs): def make_input_feff( self, parent_path: str = None, - newjob: Union[str, None] = False, + newjob: Union[str, None] = None, template: str = None, radius: float = 7, feff_comment: str = "*", @@ -1068,18 +1074,19 @@ def make_input_feff( if parent_path is None: parent_path = self.parent_path - if newjob is not None: + if (newjob is not None) or (self.njob == 0): self.njob += 1 job = Job( num=self.njob, description=newjob, - type="feff", + type="fdmnes", timestamp=_get_timestamp(), + path=None, ) self.jobs.append(job) - - self.outdir = os.path.join( - parent_path, + else: + job = self.jobs[self.njob - 1] + calc_path = os.path.join( "feff", self.file_name, self.abs_atom, @@ -1087,6 +1094,8 @@ def make_input_feff( f"site{self.abs_site}", f"job{self.njob}", ) + job.path = calc_path + self.outdir = os.path.join(parent_path, calc_path) if template is None: template = os.path.join( From a1f79346ab42501e565e4a680c179b07c955ae97 Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 16:48:13 +0200 Subject: [PATCH 09/15] store calc_path --- larch/xrd/struct2xas.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 107c6ba30..112c0d08b 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -176,12 +176,13 @@ def __init__( else: self.parent_path = parent_path self.folders = structure_folders() + self.calc_path = None self.njob = 0 self.jobs = [] self.tmpl_fdmnes = None self.tmpl_feff = None self.tmpl_sbatch = None - logger.info( + logger.debug( f"Frames: {self.nframes}, Absorbing sites: {self.nabs_sites}. (Indexes for frames and abs_sites start at 0)" ) @@ -856,6 +857,7 @@ def make_input_fdmnes( ) job.path = calc_path self.outdir = os.path.join(parent_path, calc_path) + self.calc_path = calc_path if template is None: template = os.path.join( @@ -1096,6 +1098,7 @@ def make_input_feff( ) job.path = calc_path self.outdir = os.path.join(parent_path, calc_path) + self.calc_path = calc_path if template is None: template = os.path.join( From 91497a48489c4ea972a063c5f6134f6ef34217ea Mon Sep 17 00:00:00 2001 From: opd16 on bm16ctrl Date: Wed, 31 Jul 2024 18:02:25 +0200 Subject: [PATCH 10/15] make batch script executable --- larch/xrd/struct2xas.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 112c0d08b..3fe399986 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -7,6 +7,7 @@ # main imports import os +import stat import json import time from dataclasses import dataclass @@ -1014,12 +1015,18 @@ def make_sbatch(self, template: str, **kwargs): """ assert os.path.isfile(template), "wrong template path" - with open(os.path.join(self.outdir, "job.sbatch"), "w") as fp, open( - template - ) as tp: + batch_script = os.path.join(self.outdir, "job.sbatch") + with open(batch_script, "w") as fp, open(template) as tp: fp.write(tp.read().format(**kwargs)) logger.info(f"written {fp.name}") + # Make the SLURM batch script executable. + current_permissions = os.stat(batch_script) + os.chmod( + batch_script, + current_permissions.st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH, + ) + def make_input_feff( self, parent_path: str = None, From 7b49de7f92ca65ba6a2fdd82a4533446cb35e424 Mon Sep 17 00:00:00 2001 From: Mauro Rovezzi Date: Thu, 1 Aug 2024 11:53:36 +0200 Subject: [PATCH 11/15] simple make batch script executable --- larch/xrd/struct2xas.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 3fe399986..61fc684d4 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -7,7 +7,6 @@ # main imports import os -import stat import json import time from dataclasses import dataclass @@ -1019,13 +1018,7 @@ def make_sbatch(self, template: str, **kwargs): with open(batch_script, "w") as fp, open(template) as tp: fp.write(tp.read().format(**kwargs)) logger.info(f"written {fp.name}") - - # Make the SLURM batch script executable. - current_permissions = os.stat(batch_script) - os.chmod( - batch_script, - current_permissions.st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH, - ) + os.chmod(batch_script, 0o755) def make_input_feff( self, From 5d449e891a3df13cbf1655398366efec3f6cf33e Mon Sep 17 00:00:00 2001 From: Mauro Rovezzi Date: Thu, 1 Aug 2024 17:03:38 +0200 Subject: [PATCH 12/15] avoid overwriting existing job --- larch/xrd/struct2xas.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 61fc684d4..67e79b62b 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -982,7 +982,9 @@ def make_input_fdmnes( try: os.makedirs(self.outdir, mode=0o755) except FileExistsError: - pass + errmsg = f"`job{job.num}` already exists -> use `newjob` or remove it" + logger.error(errmsg) + raise FileExistsError(errmsg) # Write the input file. fnout = os.path.join(self.outdir, "job_inp.txt") @@ -1001,10 +1003,8 @@ def make_sbatch(self, template: str, **kwargs): Arguments --------- - template: str path to the SBATCH template file - **kwargs keyword arguments to be replaced in the template file From 24b244b259a71ab53d197b56235bf722f3c3f2b7 Mon Sep 17 00:00:00 2001 From: Mauro Rovezzi Date: Tue, 20 Aug 2024 09:30:54 +0200 Subject: [PATCH 13/15] add control energy shift to edge --- larch/io/columnfile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/larch/io/columnfile.py b/larch/io/columnfile.py index 95877c6f0..dbc648ab4 100644 --- a/larch/io/columnfile.py +++ b/larch/io/columnfile.py @@ -613,6 +613,7 @@ def write_group(filename, group, scalars=None, arrays=None, def read_fdmnes(filename, **kwargs): """read [FDMNES](http://fdmnes.neel.cnrs.fr/) ascii files""" + shift_energy = kwargs.pop("shift_energy", True) group = read_ascii(filename, **kwargs) group.header_dict = dict(filetype='FDMNES', energy_units='eV') for headline in group.header: @@ -623,7 +624,8 @@ def read_fdmnes(filename, **kwargs): vals_names = headline.split(" = ")[1].split(", ") group.header_dict.update(dict(zip(vals_names, vals))) group.name = f'FDMNES file {filename}' - group.energy += group.header_dict["E_edge"] + if shift_energy: + group.energy += group.header_dict["E_edge"] #fix _arrlabel -> arrlabel for ilab, lab in enumerate(group.array_labels): if lab.startswith("_"): From 0b655d2e82ebd8269fae1fa01e420577558b720e Mon Sep 17 00:00:00 2001 From: Mauro Rovezzi Date: Tue, 20 Aug 2024 11:26:49 +0200 Subject: [PATCH 14/15] WIP: update cif parsing --- larch/xrd/struct2xas.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index 67e79b62b..b54d36dc7 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -267,9 +267,10 @@ def read_structure(self, file): self.molecules = None self.mol = None self.nframes = 1 - self.cif = CifParser(self.file) + self.cif = CifParser(self.file, occupancy_tolerance=10, site_tolerance=5e-3) self.struct = Structure.from_file(self.file) - # self.struct = self.cif.get_structures()[0] #: NOT WORKING! + # self.struct = self.cif.parse_structures()[0] #: TODO + # self.struct = self.cif.get_structures()[0] #: DEPRECATED / NOT WORKING! logger.debug("structure created from a CIF file") elif self.file_ext == ".xyz": self.is_xyz = True From 152e288ad617b759fa69a9d86be2d5b8a9a50691 Mon Sep 17 00:00:00 2001 From: Mauro Rovezzi Date: Tue, 20 Aug 2024 15:29:56 +0200 Subject: [PATCH 15/15] remove logger error message --- larch/xrd/struct2xas.py | 1 - 1 file changed, 1 deletion(-) diff --git a/larch/xrd/struct2xas.py b/larch/xrd/struct2xas.py index b54d36dc7..0c7c31b8d 100644 --- a/larch/xrd/struct2xas.py +++ b/larch/xrd/struct2xas.py @@ -984,7 +984,6 @@ def make_input_fdmnes( os.makedirs(self.outdir, mode=0o755) except FileExistsError: errmsg = f"`job{job.num}` already exists -> use `newjob` or remove it" - logger.error(errmsg) raise FileExistsError(errmsg) # Write the input file.