"""Wrapper for structure data loading."""frompathlibimportPathfromase.atomsimportAtomsfromase.ioimportread,writefromloguruimportloggerfromddpc.io.readimportdspaw_asasrdafromddpc.io.readimportrescu_xyzasrrxfromddpc.io.writeimportdspaw_asaswdafromddpc.io.writeimportrescu_xyzaswrx
[docs]@logger.catchdefread_structure(p:str|Path):"""Read crystal structure from various file formats. This function provides a unified interface for reading crystal structures from different file formats. It automatically detects the format based on file extension and uses the appropriate reader. Parameters ---------- p : str or pathlib.Path Path to the structure file. Supported formats include: - .as : DS-PAW atomic structure format - .xyz : RESCU XYZ format - Other formats supported by ASE (POSCAR, CIF, etc.) Returns ------- ase.atoms.Atoms or list of ase.atoms.Atoms Crystal structure(s) as ASE Atoms object(s). Some formats may return multiple structures (e.g., trajectory files). Notes ----- The function uses format-specific readers for: - DS-PAW .as files: Custom reader supporting lattice/atom constraints and magnetism - RESCU .xyz files: Custom reader supporting magnetic moments and constraints - Other formats: ASE's built-in readers """fn=str(p)iffn.endswith(".as"):returnrda.read(fn)iffn.endswith(".xyz"):returnrrx.read(fn)returnread(fn)
[docs]@logger.catchdefread_single_structure(p:str|Path):"""Read the first structure from a file containing one or more structures. This function reads crystal structures from various file formats and ensures that only a single Atoms object is returned. If the file contains multiple structures (e.g., trajectory files), only the first one is returned. Parameters ---------- p : str or pathlib.Path Path to the structure file. Supported formats include: - .as : DS-PAW atomic structure format - .xyz : RESCU XYZ format - Other formats supported by ASE (POSCAR, CIF, etc.) Returns ------- ase.atoms.Atoms Single crystal structure as an ASE Atoms object. If the input file contains multiple structures, only the first one is returned. Notes ----- This function is particularly useful when working with trajectory files or formats that can contain multiple structures, but you only need the first structure for analysis. """fn=str(p)iffn.endswith(".as"):returnrda.read(fn)iffn.endswith(".xyz"):returnrrx.read(fn)res=read(fn)ifisinstance(res,Atoms):returnreslogger.warning("got multiple Atoms, will use the 1st one.")returnres[0]
[docs]@logger.catchdefwrite_structure(p:str|Path,atoms:Atoms|list[Atoms],file_format:str|None=None,**kwargs)->str:"""Write crystal structure(s) to file in various formats. This function provides a unified interface for writing crystal structures to different file formats. It automatically detects the format based on file extension or uses the explicitly specified format. Parameters ---------- p : str or pathlib.Path Path to the output file. The file extension determines the format if file_format is not specified. atoms : ase.atoms.Atoms or list of ase.atoms.Atoms Crystal structure(s) to write. Some formats support multiple structures. file_format : str, optional Explicit file format specification. If None, format is determined from file extension. Supported formats include: - 'as' : DS-PAW atomic structure format - 'xyz' : RESCU XYZ format - Other formats supported by ASE ('vasp', 'cif', etc.) **kwargs Additional keyword arguments passed to the format-specific writer. Returns ------- str String representation of the written structure file content. Raises ------ ValueError If trying to write multiple structures to a format that only supports single structures (.as or .xyz formats). Notes ----- Format-specific behaviors: - DS-PAW .as format: Only supports single Atoms objects, preserves constraints - RESCU .xyz format: Only supports single Atoms objects, preserves magnetism - Other formats: Use ASE's built-in writers with full feature support Examples -------- >>> content = write_structure("output.vasp", atoms, file_format="vasp") >>> content = write_structure("structure.as", atoms) >>> content = write_structure("trajectory.xyz", atoms_list) """fn=str(p)iffile_format=="as"orfn.endswith(".as"):ifisinstance(atoms,Atoms):returnwda.write(fn,atoms)raiseValueError("as format only support single Atoms object")iffile_format=="xyz"orfn.endswith(".xyz"):ifisinstance(atoms,Atoms):returnwrx.write(fn,atoms)raiseValueError("xyz format only support single Atoms object")write(fn,atoms,format=file_format,**kwargs)# type: ignorewithopen(fn,"r",encoding="utf-8")asf:returnf.read()