Source code for nanotools.io.xyz

# -*- coding: utf-8 -*-
"""
Created on 2020-08-27

@author: Vincent Michaud-Rioux
"""

import numpy as np


[docs] def readxyz_spin(filename): """Reads an xyz file and returns the spin. The first two lines are the number of atoms and a comment. To parse spin, the function assumes the comment has four tags (usually species, x, y, z) and then sx, sy, sz at some point. The position of sx, sy, sz or sr, st, sp indicates which column has which spin. Args: filename (str): Path of the xyz file. Returns: spins (array): 2D array of the spins in Cartesian format. If no spin is found, then None is returned. If only sz is found then a 1D array of spin-z is returned. If any of sx, sy, sz are found then a 2D array of spins is returned. If any of sr, st, sp are found then a 2D array of spins is returned. """ f = open(filename, "r") lines = f.readlines() natoms = int(lines[0]) comment = lines[1].strip().split() if not any([s in comment for s in ["sx", "sy", "sz", "sr", "st", "sp"]]): return None, None if any([s in comment for s in ["sx", "sy", "sz"]]) and any( [s in comment for s in ["sr", "st", "sp"]] ): raise Exception( "Cannot specify spin in both Cartesian and spherical coordinates." ) if "sx" in comment: isx = comment.index("sx") else: isx = None if "sy" in comment: isy = comment.index("sy") else: isy = None if "sz" in comment: isz = comment.index("sz") else: isz = None if "sr" in comment: isr = comment.index("sr") else: isr = None if "st" in comment: ist = comment.index("st") else: ist = None if "sp" in comment: isp = comment.index("sp") else: isp = None if any([s in comment for s in ["sx", "sy", "sz"]]): iscart = True coordinates = "Cartesian" else: iscart = False coordinates = "spherical" if isx is None and isy is None and ist is None and isp is None: iscollinear = True spins = np.zeros((natoms, 1)) else: iscollinear = False spins = np.zeros((natoms, 3)) for l in range(2, 2 + natoms): line = lines[l].split() if iscollinear: if iscart: spins[l - 2, 0] = float(line[isz]) else: spins[l - 2, 0] = float(line[isr]) continue if iscart: if isx is not None: spins[l - 2, 0] = float(line[isx]) if isy is not None: spins[l - 2, 1] = float(line[isy]) if isz is not None: spins[l - 2, 2] = float(line[isz]) else: if isr is not None: spins[l - 2, 0] = float(line[isr]) if ist is not None: spins[l - 2, 1] = float(line[ist]) if isp is not None: spins[l - 2, 2] = float(line[isp]) f.close() return spins, coordinates
[docs] def readxyz_doping(filename): """Reads an xyz file and returns the doping ratios.""" f = open(filename, "r") lines = f.readlines() natoms = int(lines[0]) comment = lines[1].strip().split() if "doping_ratio" not in comment: return None ind = comment.index("doping_ratio") rates = np.zeros(natoms) for l in range(2, 2 + natoms): line = lines[l].split() rates[l - 2] = float(line[ind]) f.close() return rates
[docs] def readxyz_pos(filename): """ Reads an xyz file. The first two lines are the number of atoms and a comment. Then each lines has 4 columns: species, x, y, z. Args: filename (str): Path of the xyz file. Returns: formula (str): xyz (array): 2D array of the coordinates. """ f = open(filename, "r") lines = f.readlines() natoms = int(lines[0]) formula = "" xyz = np.zeros((natoms, 3)) for l in range(2, 2 + natoms): symbol, x, y, z = lines[l].split()[:4] formula += symbol xyz[l - 2, :] = [float(x), float(y), float(z)] f.close() return formula, xyz