def read_ase(aseobject, check_triclinic=False, box_vectors=False): """ Function to read from a ASE atoms objects Parameters ---------- aseobject : ASE Atoms object name of the ASE atoms object triclinic : bool, optional True if the configuration is triclinic box_vectors : bool, optional If true, return the full box vectors along with `boxdims` which gives upper and lower bounds. default False. """ #We have to process atoms and atomic objects from ase #Known issues lammps -dump modified format #first get box a = np.array(aseobject.cell[0]) b = np.array(aseobject.cell[1]) c = np.array(aseobject.cell[2]) box = np.array([a, b, c]) boxdims = np.array([[0, np.sqrt(np.sum(a**2))], [0, np.sqrt(np.sum(b**2))], [0, np.sqrt(np.sum(c**2))]]) #box and box dims are set. Now handle atoms chems = np.array(aseobject.get_chemical_symbols()) atomsymbols = np.unique(aseobject.get_chemical_symbols()) atomtypes = np.array(range(1, len(atomsymbols) + 1)) typedict = dict(zip(atomsymbols, atomtypes)) #now start parsing atoms atoms = [] positions = aseobject.positions for count, position in enumerate(positions): atom = pca.Atom() atom.pos = list(position) atom.id = (count + 1) atom.type = typedict[chems[count]] atom.loc = count customdict = {'species': chems[count]} atom.custom = customdict atoms.append(atom) if box_vectors: return atoms, boxdims, box else: return atoms, box
def read_snap(aseobject, check_triclinic=False): """ Function to read from a ASE atoms objects Parameters ---------- aseobject : ASE Atoms object name of the ASE atoms object triclinic : bool, optional True if the configuration is triclinic """ #We have to process atoms and atomic objects from ase #Known issues lammps -dump modified format #first get box a = np.array(aseobject.cell[0]) b = np.array(aseobject.cell[1]) c = np.array(aseobject.cell[2]) box = np.array([a, b, c]) #box and box dims are set. Now handle atoms chems = np.array(aseobject.get_chemical_symbols()) atomsymbols = np.unique(aseobject.get_chemical_symbols()) atomtypes = np.array(range(1, len(atomsymbols) + 1)) typedict = dict(zip(atomsymbols, atomtypes)) #now start parsing atoms atoms = [] positions = aseobject.positions for count, position in enumerate(positions): atom = pca.Atom() atom.pos = list(position) atom.id = (count + 1) atom.type = typedict[chems[count]] atom.loc = count customdict = {'species': chems[count]} atom.custom = customdict atoms.append(atom) return atoms, box
def read_snap(mdobject, check_triclinic=False): """ Function to read from an MDTraj atoms objects Parameters ---------- mdobject : MDTraj Atoms object name of the MDTraj atoms object triclinic : bool, optional True if the configuration is triclinic """ #We have to process atoms and atomic objects from ase #Known issues lammps -dump modified format #first get box a = np.array(mdobject.unitcell_vectors[0][0]) b = np.array(mdobject.unitcell_vectors[0][1]) c = np.array(mdobject.unitcell_vectors[0][2]) box = np.array([a, b, c]) #box and box dims are set. Now handle atoms chems = np.array([atom.name for atom in mdobject.topology.atoms]) atomsymbols = np.unique(chems) atomtypes = np.array(range(1, len(atomsymbols) + 1)) typedict = dict(zip(atomsymbols, atomtypes)) #now start parsing atoms atoms = [] positions = mdobject.xyz[0] for count, position in enumerate(positions): atom = pca.Atom() atom.pos = list(position) atom.id = count + 1 atom.type = typedict[chems[count]] atom.loc = count customdict = {'species': chems[count]} atom.custom = customdict atoms.append(atom) return atoms, box
def unpickle_atom(atom): """ Get a picklable atom and convert it to a catom Parameters ---------- patom : picklable Atom Returns ------- catom : A c++ Atom object """ patom = pc.Atom() patom.pos = atom.pos patom.cluster = atom.cluster patom.neighbors = atom.neighbors patom.coordination = atom.coordination patom.neighbor_weights = atom.neighbor_weights patom.bonds = atom.bonds patom.id = atom.id patom.condition = atom.condition patom.solid = atom.solid patom.surface = atom.surface patom.largest_cluster = atom.largest_cluster patom.structure = atom.structure patom.loc = atom.loc patom.allq = atom.allq patom.allaq = atom.allaq patom.type = atom.type patom.custom = atom.custom patom.volume = atom.volume patom.avg_volume = atom.avg_volume patom.face_vertices = atom.face_vertices patom.face_perimeters = atom.face_perimeters patom.vertex_numbers = atom.vertex_numbers patom.vertex_vectors = atom.vertex_vectors patom.edge_lengths = atom.edge_lengths patom.vorovector = atom.vorovector patom.avg_connection = atom.avg_connection return patom
def make_crystal(structure, lattice_constant=1.00, repetitions=None, ca_ratio=1.633): """ Create a basic crystal structure and return it as a list of `Atom` objects and box dimensions. Parameters ---------- structure : {'bcc', 'fcc', 'hcp', 'diamond'} type of the crystal structure lattice_constant : float, optional lattice constant of the crystal structure, default 1 repetitions : list of ints of len 3, optional of type `[nx, ny, nz]`, repetions of the unit cell in x, y and z directions. default `[1, 1, 1]`. ca_ratio : float, optional ratio of c/a for hcp structures, default 1.633 Returns ------- atoms : list of `Atom` objects list of all atoms as created by user input box : list of list of floats list of the type `[[xlow, xhigh], [ylow, yhigh], [zlow, zhigh]]` where each of them are the lower and upper limits of the simulation box in x, y and z directions respectively. Examples -------- >>> atoms, box = make_crystal('bcc', lattice_constant=3.48, repetitions=[2,2,2]) >>> sys = System() >>> sys.assign_atoms(atoms, box) """ if repetitions == None: nx = 1 ny = 1 nz = 1 else: nx = repetitions[0] ny = repetitions[1] nz = repetitions[2] if structure == 'bcc': coord_no = 2 natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcelly[1] = 0.5 * lattice_constant unitcellz[1] = 0.5 * lattice_constant elif structure == 'fcc': coord_no = 4 natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcellz[1] = 0.5 * lattice_constant unitcelly[2] = 0.5 * lattice_constant unitcellz[2] = 0.5 * lattice_constant unitcellx[3] = 0.5 * lattice_constant unitcelly[3] = 0.5 * lattice_constant elif structure == 'hcp': coord_no = 4 natoms = coord_no * nx * ny * nz xfact = 1. yfact = np.sqrt(3) zfact = ca_ratio unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcelly[1] = 0.5 * lattice_constant * yfact unitcellx[2] = 0.5 * lattice_constant unitcelly[2] = lattice_constant * (1.0 / 6.0) * yfact unitcellz[2] = 0.5 * lattice_constant * zfact unitcelly[3] = 2.0 * lattice_constant * (1.0 / yfact) unitcellz[3] = 0.5 * lattice_constant * zfact elif structure == 'diamond': coord_no = 8 natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.25 * lattice_constant unitcelly[1] = 0.25 * lattice_constant unitcellz[1] = 0.25 * lattice_constant unitcellx[2] = 0.50 * lattice_constant unitcelly[2] = 0.50 * lattice_constant unitcellz[2] = 0.00 * lattice_constant unitcellx[3] = 0.75 * lattice_constant unitcelly[3] = 0.75 * lattice_constant unitcellz[3] = 0.25 * lattice_constant unitcellx[4] = 0.50 * lattice_constant unitcelly[4] = 0.00 * lattice_constant unitcellz[4] = 0.50 * lattice_constant unitcellx[5] = 0.00 * lattice_constant unitcelly[5] = 0.50 * lattice_constant unitcellz[5] = 0.50 * lattice_constant unitcellx[6] = 0.75 * lattice_constant unitcelly[6] = 0.25 * lattice_constant unitcellz[6] = 0.75 * lattice_constant unitcellx[7] = 0.25 * lattice_constant unitcelly[7] = 0.75 * lattice_constant unitcellz[7] = 0.75 * lattice_constant m = 0 co = 1 atoms = [] xh = nx * lattice_constant * xfact yh = ny * lattice_constant * yfact zh = nz * lattice_constant * zfact boxdims = [[0, xh], [0, yh], [0, zh]] #create structure for i in range(1, nx + 1): for j in range(1, ny + 1): for k in range(1, nz + 1): for l in range(1, coord_no + 1): m += 1 posx = (unitcellx[l - 1] + (lattice_constant * xfact * (float(i) - 1))) posy = (unitcelly[l - 1] + (lattice_constant * yfact * (float(j) - 1))) posz = (unitcellz[l - 1] + (lattice_constant * zfact * (float(k) - 1))) atom = pc.Atom() atom.pos = [posx, posy, posz] atom.id = co atom.type = 1 atom.loc = co - 1 atoms.append(atom) co += 1 return atoms, boxdims
def make_crystal(structure, lattice_constant=1.00, repetitions=None, ca_ratio=1.633, noise=0): """ Create a basic crystal structure and return it as a list of `Atom` objects and box dimensions. Parameters ---------- structure : {'sc', 'bcc', 'fcc', 'hcp', 'diamond', 'a15' or 'l12'} type of the crystal structure lattice_constant : float, optional lattice constant of the crystal structure, default 1 repetitions : list of ints of len 3, optional of type `[nx, ny, nz]`, repetions of the unit cell in x, y and z directions. default `[1, 1, 1]`. ca_ratio : float, optional ratio of c/a for hcp structures, default 1.633 noise : float, optional If provided add normally distributed noise with standard deviation `noise` to the atomic positions. Returns ------- atoms : list of `Atom` objects list of all atoms as created by user input box : list of list of floats list of the type `[[xlow, xhigh], [ylow, yhigh], [zlow, zhigh]]` where each of them are the lower and upper limits of the simulation box in x, y and z directions respectively. Examples -------- >>> atoms, box = make_crystal('bcc', lattice_constant=3.48, repetitions=[2,2,2]) >>> sys = System() >>> sys.assign_atoms(atoms, box) """ if repetitions == None: nx = 1 ny = 1 nz = 1 else: nx = repetitions[0] ny = repetitions[1] nz = repetitions[2] #if noise > 0.1: # warnings.warn("Value of noise is rather high. Atom positions might overlap") if structure == 'sc': coord_no = 1 atomtype = [ 1, ] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) elif structure == 'bcc': coord_no = 2 atomtype = [1, 1] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcelly[1] = 0.5 * lattice_constant unitcellz[1] = 0.5 * lattice_constant elif structure == 'fcc': coord_no = 4 atomtype = [1, 1, 1, 1] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcellz[1] = 0.5 * lattice_constant unitcelly[2] = 0.5 * lattice_constant unitcellz[2] = 0.5 * lattice_constant unitcellx[3] = 0.5 * lattice_constant unitcelly[3] = 0.5 * lattice_constant elif structure == 'hcp': coord_no = 4 atomtype = [1, 1, 1, 1] natoms = coord_no * nx * ny * nz xfact = 1. yfact = np.sqrt(3) zfact = ca_ratio unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcelly[1] = 0.5 * lattice_constant * yfact unitcellx[2] = 0.5 * lattice_constant unitcelly[2] = lattice_constant * (1.0 / 6.0) * yfact unitcellz[2] = 0.5 * lattice_constant * zfact unitcelly[3] = 2.0 * lattice_constant * (1.0 / yfact) unitcellz[3] = 0.5 * lattice_constant * zfact elif structure == 'diamond': coord_no = 8 atomtype = [1, 1, 1, 1, 1, 1, 1, 1] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.25 * lattice_constant unitcelly[1] = 0.25 * lattice_constant unitcellz[1] = 0.25 * lattice_constant unitcellx[2] = 0.50 * lattice_constant unitcelly[2] = 0.50 * lattice_constant unitcellz[2] = 0.00 * lattice_constant unitcellx[3] = 0.75 * lattice_constant unitcelly[3] = 0.75 * lattice_constant unitcellz[3] = 0.25 * lattice_constant unitcellx[4] = 0.50 * lattice_constant unitcelly[4] = 0.00 * lattice_constant unitcellz[4] = 0.50 * lattice_constant unitcellx[5] = 0.00 * lattice_constant unitcelly[5] = 0.50 * lattice_constant unitcellz[5] = 0.50 * lattice_constant unitcellx[6] = 0.75 * lattice_constant unitcelly[6] = 0.25 * lattice_constant unitcellz[6] = 0.75 * lattice_constant unitcellx[7] = 0.25 * lattice_constant unitcelly[7] = 0.75 * lattice_constant unitcellz[7] = 0.75 * lattice_constant elif structure == 'a15': coord_no = 8 atomtype = [1, 1, 1, 1, 1, 1, 1, 1] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.50 * lattice_constant unitcelly[1] = 0.50 * lattice_constant unitcellz[1] = 0.50 * lattice_constant unitcellx[2] = 0.25 * lattice_constant unitcelly[2] = 0.50 * lattice_constant unitcellz[2] = 0.00 * lattice_constant unitcellx[3] = 0.75 * lattice_constant unitcelly[3] = 0.50 * lattice_constant unitcellz[3] = 0.00 * lattice_constant unitcellx[4] = 0.00 * lattice_constant unitcelly[4] = 0.25 * lattice_constant unitcellz[4] = 0.50 * lattice_constant unitcellx[5] = 0.00 * lattice_constant unitcelly[5] = 0.75 * lattice_constant unitcellz[5] = 0.50 * lattice_constant unitcellx[6] = 0.50 * lattice_constant unitcelly[6] = 0.00 * lattice_constant unitcellz[6] = 0.25 * lattice_constant unitcellx[7] = 0.50 * lattice_constant unitcelly[7] = 0.00 * lattice_constant unitcellz[7] = 0.75 * lattice_constant elif structure == 'l12': coord_no = 4 atomtype = [1, 2, 2, 2] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcellz[1] = 0.5 * lattice_constant unitcelly[2] = 0.5 * lattice_constant unitcellz[2] = 0.5 * lattice_constant unitcellx[3] = 0.5 * lattice_constant unitcelly[3] = 0.5 * lattice_constant elif structure == 'b2': coord_no = 2 atomtype = [1, 2] natoms = coord_no * nx * ny * nz xfact = 1. yfact = 1. zfact = 1. unitcellx = np.zeros(coord_no) unitcelly = np.zeros(coord_no) unitcellz = np.zeros(coord_no) unitcellx[1] = 0.5 * lattice_constant unitcelly[1] = 0.5 * lattice_constant unitcellz[1] = 0.5 * lattice_constant else: raise ValueError("Unknown crystal structure") m = 0 co = 1 atoms = [] xh = nx * lattice_constant * xfact yh = ny * lattice_constant * yfact zh = nz * lattice_constant * zfact box = [[xh, 0, 0], [0, yh, 0], [0, 0, zh]] #create structure for i in range(1, nx + 1): for j in range(1, ny + 1): for k in range(1, nz + 1): for l in range(1, coord_no + 1): m += 1 posx = (unitcellx[l - 1] + (lattice_constant * xfact * (float(i) - 1))) posy = (unitcelly[l - 1] + (lattice_constant * yfact * (float(j) - 1))) posz = (unitcellz[l - 1] + (lattice_constant * zfact * (float(k) - 1))) if noise > 0: posx = np.random.normal(loc=posx, scale=noise) posy = np.random.normal(loc=posy, scale=noise) posz = np.random.normal(loc=posz, scale=noise) atom = pc.Atom() atom.pos = [posx, posy, posz] atom.id = co atom.type = atomtype[l - 1] atom.loc = co - 1 atoms.append(atom) co += 1 return atoms, box
def read_poscar(infile, compressed=False, box_vectors=False): """ Function to read a POSCAR format. Parameters ---------- infile : string name of the input file compressed : bool, optional force to read a `gz` zipped file. If the filename ends with `.gz`, use of this keyword is not necessary, Default False Returns ------- atoms : list of `Atom` objects list of all atoms as created by user input box : list of list of floats list of the type `[[xlow, xhigh], [ylow, yhigh], [zlow, zhigh]]` where each of them are the lower and upper limits of the simulation box in x, y and z directions respectively. Examples -------- >>> atoms, box = read_poscar('POSCAR') >>> atoms, box = read_poscar('POSCAR.gz') >>> atoms, box = read_poscar('POSCAR.dat', compressed=True) """ raw = infile.split('.') if raw[-1] == 'gz' or compressed: f = gzip.open(infile, 'rt') else: f = open(infile, 'r') data = [] for line in f: data.append(line) no_atoms = data[5].split() nlev = 5 try: no_atoms = np.array(no_atoms) no_atoms = no_atoms.astype(int) except ValueError: no_atoms = data[6].split() nlev = 6 no_atoms = np.array(no_atoms) no_atoms = no_atoms.astype(int) except: raise ValueError("Unknown no of atoms") natoms = np.sum(no_atoms) atom_list = no_atoms scaling_factor = np.array(data[1].strip()).astype(float) xvector = np.array(data[2].strip().split()).astype(float) yvector = np.array(data[3].strip().split()).astype(float) zvector = np.array(data[4].strip().split()).astype(float) boxvecs = [xvector, yvector, zvector] xlow = 0 xhigh = scaling_factor * xvector[0] ylow = 0 yhigh = scaling_factor * yvector[1] zlow = 0 zhigh = scaling_factor * zvector[2] boxdims = [[xlow, xhigh], [ylow, yhigh], [zlow, zhigh]] if (data[nlev + 1].strip().split()[0] == 's' or data[nlev + 1].strip().split()[0] == 'S'): selective_dynamics = True cord_system = data[nlev + 2].strip() atom_start = nlev + 3 else: cord_system = data[nlev + 1].strip() atom_start = nlev + 2 if cord_system in ['Cartesian', 'cartesian']: xhigh = 1 yhigh = 1 zhigh = 1 species = 1 count = 0 cum_list = np.cumsum(atom_list) i = atom_start atoms = [] while i in range(atom_start, atom_start + natoms): if (count < cum_list[species - 1]): raw = np.array(data[i].strip().split()[:3]).astype(float) typ = species x = float(raw[0]) * xhigh y = float(raw[1]) * yhigh z = float(raw[2]) * zhigh #if x,y,z are out of the box, they need to be put in if (x < xlow): x = x + (xhigh - xlow) elif (x > xhigh): x = x - (xhigh - xlow) if (y < ylow): y = y + (yhigh - ylow) elif (y > yhigh): y = y - (yhigh - ylow) if (z < zlow): z = z + (zhigh - zlow) elif (z > zhigh): z = z - (zhigh - zlow) count += 1 idd = count atom = pca.Atom() atom.pos = [x, y, z] atom.id = idd atom.type = typ atom.loc = i - atom_start #atom = pc.Atom(pos=, id=idd, type=typ) atoms.append(atom) i += 1 else: species += 1 if box_vectors: return atoms, boxdims, boxvecs else: return atoms, boxdims
def read_lammps_dump(infile, compressed=False, check_triclinic=False, box_vectors=False, customkeys=None): """ Function to read a lammps dump file format - single time slice. Parameters ---------- infile : string name of the input file compressed : bool, optional force to read a `gz` zipped file. If the filename ends with `.gz`, use of this keyword is not necessary. Default True. check_triclinic : bool, optional If true check if the sim box is triclinic. Default False. box_vectors : bool, optional If true, return the full box vectors along with `boxdims` which gives upper and lower bounds. default False. customkeys : list of strings, optional A list of extra keywords to read from trajectory file. Returns ------- atoms : list of `Atom` objects list of all atoms as created by user input boxdims : list of list of floats The dimensions of the box. This is of the form `[[xlo, xhi],[ylo, yhi],[zlo, zhi]]` where `lo` and `hi` are the upper and lower bounds of the simulation box along each axes. For triclinic boxes, this is scaled to `[0, scalar length of the vector]`. box : list of list of floats list of the type `[[x1, x2, x3], [y1, y2, y3], [zz1, z2, z3]]` which are the box vectors. Only returned if `box_vectors` is set to True. triclinic : bool True if the box is triclinic. Only returned if `check_triclinic` is set to True .. note:: Values are always returned in the order `atoms, boxdims, box, triclinic` if all return keywords are selected. For example, ff `check_triclinic` is not selected, the return values would still preserve the order and fall back to `atoms, boxdims, box`. Notes ----- Read a lammps-dump style snapshot that can have variable headers, reads in type and so on. Zipped files which end with a `.gz` can also be read automatically. However, if the file does not end with a `.gz` extension, keyword `compressed = True` can also be used. Examples -------- >>> atoms, box = read_lammps_dump('conf.dump') >>> atoms, box = read_lammps_dump('conf.dump.gz') >>> atoms, box = read_lammps_dump('conf.d', compressed=True) """ if customkeys == None: customkeys = [] #first depending on if the extension is .gz - use zipped read raw = infile.split('.') if raw[-1] == 'gz' or compressed: f = gzip.open(infile, 'rt') else: f = open(infile, 'r') #now go through the file line by line paramsread = False atoms = [] triclinic = False volume_fraction = 1.00 #now if custokeys are provided - read those in too customread = False customlength = len(customkeys) if customlength > 0: customread = True nblock = 0 for count, line in enumerate(f): #print(count, line) if not paramsread: #atom numer is at line 3 if count == 3: natoms = int(line.strip()) nblock = natoms + 9 #box dims in lines 5,6,7 elif count == 5: raw = line.strip().split() boxx = [float(raw[0]), float(raw[1])] if len(raw) == 3: xy = float(raw[2]) elif count == 6: raw = line.strip().split() boxy = [float(raw[0]), float(raw[1])] if len(raw) == 3: xz = float(raw[2]) elif count == 7: raw = line.strip().split() boxz = [float(raw[0]), float(raw[1])] if len(raw) == 3: yz = float(raw[2]) triclinic = True tilts = [xy, xz, yz] #boxdims = [boxx, boxy, boxz] #header is here elif count == 8: raw = line.strip().split() headerdict = {raw[x]: x - 2 for x in range(0, len(raw))} paramsread = True if customread: if not np.prod([(x in headerdict) for x in customkeys]): raise KeyError( "some values in custokeys was not found in the file" ) #add a new keyword for scaled coordinates if "x" in headerdict.keys(): scaled = False elif "xs" in headerdict.keys(): scaled = True headerdict["x"] = headerdict.pop("xs") headerdict["y"] = headerdict.pop("ys") headerdict["z"] = headerdict.pop("zs") else: raise ValueError( "only x/xs, y/ys andz/zs keys are allowed for traj file" ) else: if count == nblock: break raw = line.strip().split() idd = int(raw[headerdict["id"]]) typ = int(raw[headerdict["type"]]) x = float(raw[headerdict["x"]]) y = float(raw[headerdict["y"]]) z = float(raw[headerdict["z"]]) atom = pca.Atom() atom.pos = [x, y, z] atom.id = idd atom.type = typ atom.loc = count - 8 customdict = {} #if customkeys need to be read, do it if customread: for cc, kk in enumerate(customkeys): customdict[kk] = raw[headerdict[kk]] atom.custom = customdict atoms.append(atom) #close files f.close() if triclinic: #process triclinic box amin = min([0.0, tilts[0], tilts[1], tilts[0] + tilts[1]]) amax = max([0.0, tilts[0], tilts[1], tilts[0] + tilts[1]]) bmin = min([0.0, tilts[2]]) bmax = max([0.0, tilts[2]]) xlo = boxx[0] - amin xhi = boxx[1] - amax ylo = boxy[0] - bmin yhi = boxy[1] - bmax zlo = boxz[0] zhi = boxz[1] #triclinic cell a = np.array([xhi - xlo, 0, 0]) b = np.array([tilts[0], yhi - ylo, 0]) c = np.array([tilts[1], tilts[2], zhi - zlo]) rot = np.array([a, b, c]).T rotinv = np.linalg.inv(rot) ortho_origin = np.array([boxx[0], boxy[0], boxz[0]]) for atom in atoms: #correct zero of the atomic positions (shift box to origin) dist = np.array(atom.pos) - ortho_origin atom.pos = dist #finally change boxdims - to triclinic box size box = np.array([a, b, c]) boxdims = np.array([[0, np.sqrt(np.sum(a**2))], [0, np.sqrt(np.sum(b**2))], [0, np.sqrt(np.sum(c**2))]]) else: box = np.array([[boxx[1] - boxx[0], 0, 0], [0, boxy[1] - boxy[0], 0], [0, 0, boxz[1] - boxz[0]]]) boxdims = np.array([[boxx[0], boxx[1]], [boxy[0], boxy[1]], [boxz[0], boxz[1]]]) #adjust for scled coordinates if scaled: for atom in atoms: dist = atom.pos ndist = dist[0] * box[0] + dist[1] * box[1] + dist[2] * box[2] atom.pos = ndist if box_vectors and check_triclinic: return atoms, boxdims, box, triclinic elif box_vectors: return atoms, boxdims, box elif check_triclinic: return atoms, boxdims, triclinic else: return atoms, boxdims