def coordgroups_reduced_rc_to_unitcellsites(coordgroups, basis, hall_symbol, reduce=False): # Just fake representative assignments for the coordgroups assignments = range(1, len(coordgroups) + 1) struct = Structure.create(rc_cell=basis, assignments=assignments, rc_reduced_coordgroups=coordgroups, hall_symbol=hall_symbol) rescale = 1 atoms = structure_to_ase_atoms(struct) if reduce: beforevol = FracScalar.create(atoms.get_volume()) spacegroup, setting = httk.atomistic.data.spacegroups.spacegroup_get_number_and_setting( hall_symbol) atoms = primitive_from_conventional_cell(atoms, spacegroup, setting) aftervol = FracScalar.create(atoms.get_volume()) rescale = (rescale * aftervol / beforevol).simplify() atomic_symbols = atoms.get_chemical_symbols() coords = atoms.get_scaled_positions() cell = atoms.get_cell() sites = UnitcellSites.create(cell=cell, occupancies=atomic_symbols, reduced_coords=coords, periodicity=atoms.pbc) cell = Cell(basis=cell) return sites, cell
def poscar_to_structure(f, included_decimals=''): cell, scale, volume, coords, coords_reduced, counts, occupations, comment = poscar_to_strs( f, included_decimals) frac_cell = FracVector.create(cell, simplify=True) counts = [int(x) for x in counts] if coords_reduced: frac_coords = cartesian_to_reduced(cell, coords) else: frac_coords = FracVector.create(coords, simplify=True) if volume is not None: volume = FracScalar.create(volume) if scale is not None: scale = FracScalar.create(scale) newoccupations = [] for occupation in occupations: newoccupations.append(periodictable.atomic_number(occupation)) struct = Structure.create(uc_basis=frac_cell, uc_volume=volume, uc_scale=scale, uc_reduced_coords=frac_coords, uc_counts=counts, assignments=newoccupations, tags={'comment': comment}, periodicity=0) return struct
def ase_atoms_to_structure(atoms, hall_symbol): #occupancies = [periodictable.atomic_number(x) for x in atoms.get_chemical_symbols()] atomic_symbols = atoms.get_chemical_symbols() #counts = [1]*len(assignments) coords = atoms.get_scaled_positions() cell = atoms.get_cell() if hall_symbol is None: struct = Structure.create(uc_basis=cell, uc_occupancies=atomic_symbols, uc_reduced_occupationscoords=coords, periodicity=atoms.pbc) else: struct = Structure.create(rc_basis=cell, rc_occupancies=atomic_symbols, rc_reduced_occupationscoords=coords, periodicity=atoms.pbc, hall_symbol=hall_symbol) return struct
def coordgroups_reduced_rc_to_unitcellsites(coordgroups, basis, hall_symbol): # Just fake representative assignments for the coordgroups assignments = range(1, len(coordgroups) + 1) struct = Structure.create(rc_cell=basis, assignments=assignments, rc_reduced_coordgroups=coordgroups, hall_symbol=hall_symbol) ioa = IoAdapterString() struct_to_cif(struct, ioa) struct = cif_to_structure_reduce(ioa) return struct.uc_sites, struct.uc_cell
def structure_reduced_uc_to_representative(struct, backends=['isotropy', 'fake']): for backend in backends: if backend == 'isotropy': try: from httk.external import isotropy_ext sys.stderr.write( "Warning: need to run symmetry finder. This may take a while.\n" ) struct = isotropy_ext.struct_process_with_isotropy(struct) return struct except ImportError: pass if backend == 'fake': try: from httk.atomistic import Structure sys.stderr.write( "Warning: using 'fake' symmetry finder that never finds any symmetry.\n" ) newstruct = Structure.create( assignments=struct.assignments, rc_cell=struct.uc_cell, rc_reduced_coords=struct.uc_reduced_coords, rc_counts=struct.uc_counts, uc_cell=struct.uc_cell, uc_reduced_coords=struct.uc_reduced_coords, uc_counts=struct.uc_counts, spacegroup='P 1', tags=struct.get_tags(), refs=struct.get_refs(), periodicity=struct.uc_sites.pbc) return newstruct except ImportError: raise pass raise Exception( "structure_to_sgstructure: None of the available backends available.")
def platon_styout_to_structure(ioa, based_on_struct=None): """ Example input:: Results for id=[0] dblock_code=[44325-I New: F-43m ===================================================== Pearson code : cF 8 Sb 4.0 Al 4.0 Cell parameters : 7.7782 7.7782 7.7782 90.000 90.000 90.000 Space group symbol : F -4 3 m Number in IT : 216 Setting x,y,z Origin ( 0.0000 0.0000 0.0000) Gamma = 0.4330 Al1 4(c) 1/4 1/4 1/4 Al 1 Sb1 4(a) 0 0 0 Sb 1 Wyckoff sequence : c a Volume of Unit Cell : 470.5842 OTHER Standardization with Similar Gamma : Setting -x,-y,-z Origin ( 0.7500 0.7500 0.7500) Gamma = 0.4330 Sb1 4(c) 1/4 1/4 1/4 Sb 1 Al1 4(a) 0 0 0 Al 1 Wyckoff sequence : c a Volume of Unit Cell : 470.5842 """ results = {} results['cell'] = {} results['spacegroup'] = {} results['setting'] = [] results['in_setting'] = False def cell_params(results, match): results['cell']['rc_a'] = float(match.group(1)) results['cell']['rc_b'] = float(match.group(2)) results['cell']['rc_c'] = float(match.group(3)) results['cell']['rc_alpha'] = float(match.group(4)) results['cell']['rc_beta'] = float(match.group(5)) results['cell']['rc_gamma'] = float(match.group(6)) def spacegroup(results, match): results['spacegroup']['symbol'] = match.group(1).strip() results['spacegroup']['number'] = match.group(2).strip() #def setting_start(results,match): # results['setting'].append({'coords':[],'occupancies':[],'wycoff':[]}) # results['in_setting'] = True def setting_stop(results, match): results['in_setting'] = False def read_coords(results, match): if not results['in_setting']: results['setting'].append({'coords': [], 'occupancies': [], 'wyckoff': [], 'multiplicities': []}) results['in_setting'] = True newcoord = FracVector.create([match.group(4), match.group(5), match.group(6)]).limit_denominator(5000000).simplify() #print("CHECK1",[match.group(4),match.group(5),match.group(6)]) #print("CHECK2:",newcoord) results['setting'][-1]['coords'].append([match.group(4), match.group(5), match.group(6)]) if based_on_struct is None: results['setting'][-1]['occupancies'].append(match.group(1)) else: abstract_symbol = match.group(1).strip() index = httk.basic.anonymous_symbol_to_int(abstract_symbol) results['setting'][-1]['occupancies'].append(based_on_struct.assignments[index]) wyckoff_string = match.group(3) wyckoff_symbol = wyckoff_string[wyckoff_string.index("(") + 1:wyckoff_string.rindex(")")] multiplicity = int(wyckoff_string[:wyckoff_string.index("(")]) results['setting'][-1]['wyckoff'].append(wyckoff_symbol) results['setting'][-1]['multiplicities'].append(multiplicity) results['in_setting'] = True #def debug(results,match): # print("DEBUG",match) out = httk.basic.micro_pyawk(ioa, [ #['^Wyckoff',None,setting_stop], ['^ *$', None, setting_stop], ['^Cell parameters : +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([0-9.-]+)', None, cell_params], ['^Space group symbol : +(.+) +Number in IT : +([0-9]+)', None, spacegroup], ['^ +([a-zA-Z]+)([0-9]*)#* +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+)', None, read_coords], #['^Setting',None,setting_start], ], results=results, debug=False) #print("HX",out['setting'][0]['wyckoff']) if based_on_struct is None: structdata = dict(out['cell'].items() + [('rc_reduced_occupationscoords', out['setting'][0]['coords']), ('rc_occupancies', out['setting'][0]['occupancies']), ('spacegroup', out['spacegroup']['symbol']), ('wyckoff_symbols', out['setting'][0]['wyckoff']) ]) sgstruct = Structure.create(**structdata) else: # Handle both normal structures and scaleless structures sg = Spacegroup.create(hm_symbol=out['spacegroup']['symbol'], spacegroupnumber=out['spacegroup']['number']) try: rc_cell = based_on_struct.rc_cell structdata = dict(out['cell'].items() + [('rc_reduced_occupationscoords', out['setting'][0]['coords']), ('rc_occupancies', out['setting'][0]['occupancies']), ('spacegroup', sg), ('rc_cell', rc_cell), ('wyckoff_symbols', out['setting'][0]['wyckoff']), ('multiplicities', out['setting'][0]['multiplicities']) ] ) sgstruct = based_on_struct.create(**structdata) sgstruct.add_tags(based_on_struct.get_tags()) sgstruct.add_refs(based_on_struct.get_refs()) except AttributeError: structdata = dict(out['cell'].items() + [('rc_reduced_occupationscoords', out['setting'][0]['coords']), ('rc_occupancies', out['setting'][0]['occupancies']), ('spacegroup', sg), ('wyckoff_symbols', out['setting'][0]['wyckoff']), ('multiplicities', out['setting'][0]['multiplicities']) ] ) sgstruct = based_on_struct.create(**structdata) sgstruct.add_tags(based_on_struct.get_tags()) sgstruct.add_refs(based_on_struct.get_refs()) sgstruct.add_rc_cells(based_on_struct.get_rc_cells()) return sgstruct
def platon_styout_to_sgstruct(ioa): """ Example input:: Results for id=[0] dblock_code=[44325-I New: F-43m ===================================================== Pearson code : cF 8 Sb 4.0 Al 4.0 Cell parameters : 7.7782 7.7782 7.7782 90.000 90.000 90.000 Space group symbol : F -4 3 m Number in IT : 216 Setting x,y,z Origin ( 0.0000 0.0000 0.0000) Gamma = 0.4330 Al1 4(c) 1/4 1/4 1/4 Al 1 Sb1 4(a) 0 0 0 Sb 1 Wyckoff sequence : c a Volume of Unit Cell : 470.5842 OTHER Standardization with Similar Gamma : Setting -x,-y,-z Origin ( 0.7500 0.7500 0.7500) Gamma = 0.4330 Sb1 4(c) 1/4 1/4 1/4 Sb 1 Al1 4(a) 0 0 0 Al 1 Wyckoff sequence : c a Volume of Unit Cell : 470.5842 """ results = {} results['cell'] = {} results['spacegroup'] = {} results['setting'] = [] results['in_setting'] = False def cell_params(results, match): results['cell']['a'] = float(match.group(1)) results['cell']['b'] = float(match.group(2)) results['cell']['c'] = float(match.group(3)) results['cell']['alpha'] = float(match.group(4)) results['cell']['beta'] = float(match.group(5)) results['cell']['gamma'] = float(match.group(6)) def spacegroup(results, match): results['spacegroup']['symbol'] = match.group(1) results['spacegroup']['number'] = int(match.group(2)) #def setting_start(results,match): # results['setting'].append({'coords':[],'occupancies':[],'wycoff':[]}) # results['in_setting'] = True def setting_stop(results, match): results['in_setting'] = False def read_coords(results, match): if not results['in_setting']: results['setting'].append({'coords': [], 'occupancies': [], 'wycoff': []}) results['in_setting'] = True results['setting'][-1]['coords'].append([match.group(4), match.group(5), match.group(6)]) results['setting'][-1]['occupancies'].append(match.group(1)) results['setting'][-1]['wycoff'].append([match.group(3)]) results['in_setting'] = True #def debug(results,match): # print("DEBUG",match) out = httk.basic.micro_pyawk(ioa, [ #['^Wyckoff',None,setting_stop], ['^ *$', None, setting_stop], ['^Cell parameters : +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([0-9.-]+)', None, cell_params], ['^Space group symbol : +(.+) +Number in IT : +([0-9]+)', None, spacegroup], ['^ +([a-zA-Z]+)([0-9]*)#* +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+)', None, read_coords], #['^Setting',None,setting_start], ], results=results, debug=False) structdata = dict(out['cell'].items() + [('coords', out['setting'][0]['coords']), ('occupancies', out['setting'][0]['occupancies']), ('spacegroup', out['spacegroup']['symbol']) ]) sgstruct = Structure.create(**structdata) return sgstruct
def platon_lis_to_struct_broken(ioa): """ Example input format:: ============ ====================================================== Crystal Data ================================================================ ============ Input Cell (Lattice Type: P) - Temp = 0K Reduced Cell (Acta Cryst.(1976),A32,297-298) --------------------------------------------------------------------------------- ------------------------------------------------ a = 3.47100 Angstrom alpha = 90 Degree a = 3.471 alpha = 90.00 V = 79.6 b = 3.47100 beta = 90 b = 3.471 beta = 90.00 c = 6.60300 gamma = 90 c = 6.603 gamma = 90.00 ... ------------------------------------------------------------------------------------------------------------------------------------ Flags Label Fractional Coordinates (x,y,z) Orthogonal Coordinates (XO,YO,ZO) Site SSN*SSOF = S.O.F Move Type ------------------------------------------------------------------------------------------------------------------------------------ - Ag(1) 1/4 1/4 0.61200 0.8677 0.8677 4.0410 4mm 8 1/8 1 - Met - Zr(2) 1/4 1/4 0.13700 0.8677 0.8677 0.9046 4mm 8 1/8 1 - Met - Ag(1)a -1/4 -1/4 -0.61200 -0.8677 -0.8677 -4.0410 4mm 8 1/8 1 5.455 Met - Zr(2)a -1/4 -1/4 -0.13700 -0.8677 -0.8677 -0.9046 4mm 8 1/8 1 5.455 Met - Ag(1)b -1/4 -1/4 0.38800 -0.8678 -0.8678 2.5620 4mm 8 1/8 1 5.456 Met - Zr(2)b -1/4 -1/4 0.86300 -0.8678 -0.8678 5.6984 4mm 8 1/8 1 5.456 Met - Ag(1)c -1/4 3/4 -0.61200 -0.8677 2.6033 -4.0410 4mm 8 1/8 1 5.465 Met - Zr(2)c -1/4 3/4 -0.13700 -0.8678 2.6033 -0.9046 4mm 8 1/8 1 5.465 Met - Ag(1)d -1/4 3/4 0.38800 -0.8678 2.6033 2.5620 4mm 8 1/8 1 5.466 Met - Zr(2)d -1/4 3/4 0.86300 -0.8678 2.6032 5.6984 4mm 8 1/8 1 5.466 Met - Ag(1)e 3/4 -1/4 -0.61200 2.6033 -0.8677 -4.0410 4mm 8 1/8 1 5.555 Met - Zr(2)e 3/4 -1/4 -0.13700 2.6033 -0.8677 -0.9046 4mm 8 1/8 1 5.555 Met - Ag(1)f 3/4 -1/4 0.38800 2.6033 -0.8678 2.5620 4mm 8 1/8 1 5.556 Met - Zr(2)f 3/4 -1/4 0.86300 2.6032 -0.8678 5.6984 4mm 8 1/8 1 5.556 Met - Ag(1)g 3/4 3/4 -0.61200 2.6033 2.6033 -4.0410 4mm 8 1/8 1 5.565 Met - Zr(2)g 3/4 3/4 -0.13700 2.6033 2.6033 -0.9046 4mm 8 1/8 1 5.565 Met - Ag(1)h 3/4 3/4 0.38800 2.6033 2.6033 2.5620 4mm 8 1/8 1 5.566 Met - Zr(2)h 3/4 3/4 0.86300 2.6032 2.6032 5.6984 4mm 8 1/8 1 5.566 Met ==================================================================================================================================== """ ioa = httk.IoAdapterFileReader(ioa) seen_coords = set() def read_spacegroup(results, match): results['spacegroup'] = match.group(1).strip() def read_a_alpha(results, match): results['a'] = float(match.group(1).replace('(', '').replace(')', '')) results['alpha'] = float(match.group(3).replace('(', '').replace(')', '')) def read_b_beta(results, match): results['b'] = float(match.group(1).replace('(', '').replace(')', '')) results['beta'] = float(match.group(3).replace('(', '').replace(')', '')) def read_c_gamma(results, match): results['c'] = float(match.group(1).replace('(', '').replace(')', '')) results['gamma'] = float(match.group(3).replace('(', '').replace(')', '')) def read_coords(results, match): sys.stdout.write("\n>>|") #for i in range(1,14): # sys.stdout.write(match.group(i)+"|") species = periodictable.atomic_number(match.group(1)) ratio = FracVector.create(re.sub(r'\([^)]*\)', '', match.group(11))) a1 = re.sub(r'\([^)]*\)', '', match.group(2)) b1 = re.sub(r'\([^)]*\)', '', match.group(3)) c1 = re.sub(r'\([^)]*\)', '', match.group(4)) a = match.group(2).replace('(', '').replace(')', '') b = match.group(3).replace('(', '').replace(')', '') c = match.group(4).replace('(', '').replace(')', '') coord = FracVector.create([a1, b1, c1]).normalize() sys.stdout.write(str(species)+" "+str(coord.to_floats())) limcoord = FracVector.create([a1, b1, c1]).normalize() coordtuple = ((species, ratio.to_tuple()), limcoord.to_tuple()) if coordtuple in seen_coords: return results['occupancies'].append((species, float(ratio))) results['coords'].append(coord) seen_coords.add(coordtuple) def in_table(results, match): results['in_table'] = True def end_table(results, match): results['in_table'] = False def section(results, match): results['section'] = match.group(1) results = {} results['spacegroup'] = None results['section'] = None results['in_table'] = None results['occupancies'] = [] results['coords'] = [] out = httk.basic.micro_pyawk(ioa, [ ['^ *Space Group +(([^ ]+ )+) +', lambda results, match: results['section'] == 'Space Group Symmetry' and results['spacegroup'] is None, read_spacegroup], ['^ *a = +([0-9.()-]+) +(Angstrom)? +alpha = +([0-9.()-]+)', lambda results, match: results['section'] == 'Crystal Data', read_a_alpha], ['^ *b = +([0-9.()-]+) +(Angstrom)? +beta = +([0-9.()-]+)', lambda results, match: results['section'] == 'Crystal Data', read_b_beta], ['^ *c = +([0-9.()-]+) +(Angstrom)? +gamma = +([0-9.()-]+)', lambda results, match: results['section'] == 'Crystal Data', read_c_gamma], ['^ Asymmetric Residue Unit \(= ARU\) Code List *$', lambda results, match: results['in_table'], end_table], #['^ *=+ *$',lambda results,match: results['in_table']==True,end_table], ['^[^ ]* +[^A-Z]*([a-zA-Z]+)[^ ]* +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([^ ]*) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([^ \n]+) *$', lambda results, match: results['in_table'], read_coords], ['^ *Flags Label +Fractional Coordinates \(x,y,z\) +Orthogonal Coordinates \(XO,YO,ZO\) +', lambda results, match: results['in_table'] is None and results['section'] == 'Space Group Symmetry', in_table], ['^ *=+ ([A-Za-z ]+) =+ *$', None, section], ], results=results, debug=False) # If we only have =1 occupancy everywhere, drop the occupancy ratio simple_occs = [] for occupancy in out['occupancies']: if occupancy[1] > (1-1e-6): occupancies = out['occupancies'] break simple_occs.append(occupancy[0]) else: occupancies = simple_occs #print("OUT",out['occupancies']) #exit(0) struct = Structure.create(a=out['a'], b=out['b'], c=out['c'], alpha=out['alpha'], beta=out['beta'], gamma=out['gamma'], occupancies=occupancies, coords=out['coords'], tags={'platon_sg': out['spacegroup']}).round() return struct
def platon_styin_to_sgstruct(ioa): """ Example input: F -4 3 M id=[0] dblock_code=[44325-ICSD] formula= 5.5000 5.5000 5.5000 90.0000 90.0000 90.0000 N Sb1 0.25000 0.25000 0.25000 Al1 0.00000 0.00000 0.00000 END END """ ioa = httk.IoAdapterFileReader(ioa) # print(ioa.file.read()) # exit() # # fi = iter(ioa) # # spg_comment = next(fi).strip() # spgsymbol = spg_comment[:15] # comment = spg_comment[16:] # a,b,c,alpha,beta,gamma = [float(x) for x in next(fi).strip().split()] # # coords = [] # occupancies = [] # for line in fi: # strcoord = line.strip().split() # if strcoord[0] == 'END': # break # coord = map(lambda x: float(x.strip()),strcoord[1:4]) # coords.append(coord) # occupation = strcoord[0] # occupation = re.sub('[0-9]*#*$', '', occupation) # occupancies.append(occupation) def read_spacegroup(results, match): results['spacegroup'] = match.group(0).strip() def read_cell(results, match): results['a'] = float(match.group(1)) results['b'] = float(match.group(2)) results['c'] = float(match.group(3)) results['alpha'] = float(match.group(4)) results['beta'] = float(match.group(5)) results['gamma'] = float(match.group(6)) results['has_cell'] = True def read_coords(results, match): results['occupancies'].append(periodictable.atomic_number(match.group(1))) results['coords'].append([float(match.group(2)), float(match.group(3)), float(match.group(4))]) def read_end(results, match): results['end'] = True results = {} results['spacegroup'] = None results['has_cell'] = False results['occupancies'] = [] results['coords'] = [] results['end'] = False out = httk.basic.micro_pyawk(ioa, [ ['^ *([a-zA-Z]+)[^ ]* +([0-9.-]+) +([0-9.-]+) +([0-9.-]+) *$', lambda results, match: results['has_cell'] and not results['end'], read_coords], ['^ *([0-9.-]+) +([0-9.-]+) +([0-9.-]+) +([0-9.-]+) +([0-9.-]+) +([0-9.-]+) *$', lambda results, match: results['spacegroup'] is not None and not results['end'], read_cell], ['^ *([^ ]+ )+ ', lambda results, match: results['spacegroup'] is None and not results['end'], read_spacegroup], ['^ *[Ee][Nn][Dd] *$', lambda results, match: results['has_cell'] and not results['end'], read_end], ], results=results, debug=False) #spacegroup = "".join(out['spacegroup'].split()) #spacegroup = spacegroup[0]+(spacegroup[1:].lower()) #print("GOT SPACEGROUP",spacegroup) spacegroup = out['spacegroup'] sgstruct = Structure.create(a=out['a'], b=out['b'], c=out['c'], alpha=out['alpha'], beta=out['beta'], gamma=out['gamma'], occupancies=out['occupancies'], coords=out['coords'], spacegroup=spacegroup, tags={'platon_sg': spacegroup}).round() return sgstruct
def platon_lis_to_struct_broken2(ioa): """ Example input:: ============ ====================================================== Crystal Data ================================================================ ============ Input Cell (Lattice Type: P) - Temp = 0K Reduced Cell (Acta Cryst.(1976),A32,297-298) --------------------------------------------------------------------------------- ------------------------------------------------ a = 3.47100 Angstrom alpha = 90 Degree a = 3.471 alpha = 90.00 V = 79.6 b = 3.47100 beta = 90 b = 3.471 beta = 90.00 c = 6.60300 gamma = 90 c = 6.603 gamma = 90.00 ... ==================================================================================================================================== 10.0 Angstrom Coordination Sphere Around Atom I = Ag(1) [ARU = 1555.01] 1/4 1/4 0.61200 0.8677 0.8677 4.0410 ------------------------------------------------------------------------------------------------------------------------------------ Nr d(I,J) To Atom J Symm_Oper. on Atom J ARU(J) Type Phi Mu X Y Z XO YO ZO ------------------------------------------------------------------------------------------------------------------------------------ 1 2.9615 -- Zr(4) [ = ] Intra-135.00 34.03 -1/4 -1/4 0.86300 -0.8678 -0.8678 5.6984 2 2.9615 -- Zr(4)n [1+x,1+y,z = 1665.01] Intra 45.00 34.03 3/4 3/4 0.86300 2.6032 2.6032 5.6984 3 2.9615 -- Zr(4)j [x,1+y,z = 1565.01] Intra 135.00 34.03 -1/4 3/4 0.86300 -0.8678 2.6032 5.6984 4 2.9615 -- Zr(4)l [1+x,y,z = 1655.01] Intra -45.00 34.03 3/4 -1/4 0.86300 2.6032 -0.8678 5.6984 5 3.1364 -- Zr(3) [ = ] Intra 0.00 -90.00 1/4 1/4 0.13700 0.8677 0.8677 0.9046 """ ioa = httk.IoAdapterFileReader(ioa) seen_coords = set() def read_spacegroup(results, match): results['spacegroup'] = match.group(1).strip() def read_a_alpha(results, match): results['a'] = float(match.group(1).replace('(', '').replace(')', '')) results['alpha'] = float(match.group(3).replace('(', '').replace(')', '')) def read_b_beta(results, match): results['b'] = float(match.group(1).replace('(', '').replace(')', '')) results['beta'] = float(match.group(3).replace('(', '').replace(')', '')) def read_c_gamma(results, match): results['c'] = float(match.group(1).replace('(', '').replace(')', '')) results['gamma'] = float(match.group(3).replace('(', '').replace(')', '')) def read_coords(results, match): sys.stdout.write("\n>>|") #for i in range(1,14): # sys.stdout.write(match.group(i)+"|") species = periodictable.atomic_number(match.group(1)) ratio = FracVector.create(re.sub(r'\([^)]*\)', '', match.group(11))) a1 = re.sub(r'\([^)]*\)', '', match.group(2)) b1 = re.sub(r'\([^)]*\)', '', match.group(3)) c1 = re.sub(r'\([^)]*\)', '', match.group(4)) a = match.group(2).replace('(', '').replace(')', '') b = match.group(3).replace('(', '').replace(')', '') c = match.group(4).replace('(', '').replace(')', '') coord = FracVector.create([a1, b1, c1]).normalize() sys.stdout.write(str(species)+" "+str(coord.to_floats())) limcoord = FracVector.create([a1, b1, c1]).normalize() coordtuple = ((species, ratio.to_tuple()), limcoord.to_tuple()) if coordtuple in seen_coords: return results['occupancies'].append((species, float(ratio))) results['coords'].append(coord) seen_coords.add(coordtuple) def in_table(results, match): results['in_table'] = True def end_table(results, match): results['in_table'] = False def section(results, match): results['section'] = match.group(1) results = {} results['spacegroup'] = None results['section'] = None results['in_table'] = None results['occupancies'] = [] results['coords'] = [] out = httk.basic.micro_pyawk(ioa, [ ['^ *Space Group +(([^ ]+ )+) +', lambda results, match: results['section'] == 'Space Group Symmetry' and results['spacegroup'] is None, read_spacegroup], ['^ *a = +([0-9.()-]+) +(Angstrom)? +alpha = +([0-9.()-]+)', lambda results, match: results['section'] == 'Crystal Data', read_a_alpha], ['^ *b = +([0-9.()-]+) +(Angstrom)? +beta = +([0-9.()-]+)', lambda results, match: results['section'] == 'Crystal Data', read_b_beta], ['^ *c = +([0-9.()-]+) +(Angstrom)? +gamma = +([0-9.()-]+)', lambda results, match: results['section'] == 'Crystal Data', read_c_gamma], ['^ Asymmetric Residue Unit \(= ARU\) Code List *$', lambda results, match: results['in_table'], end_table], #['^ *=+ *$',lambda results,match: results['in_table']==True,end_table], ['^[^ ]* +[^ ]* +[^ ]* +[^A-Z]*([a-zA-Z]+)[^ ]* +.* +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) +([/0-9.()-]+) *$', lambda results, match: results['in_table'], read_coords], ['^ *Angstrom Coordination Sphere Around Atom +', lambda results, match: results['in_table'] is None and results['section'] == 'Space Group Symmetry', in_table], ['^ *=+ ([A-Za-z ]+) =+ *$', None, section], ], results=results, debug=False) # If we only have =1 occupancy everywhere, drop the occupancy ratio simple_occs = [] for occupancy in out['occupancies']: if occupancy[1] > (1-1e-6): occupancies = out['occupancies'] break simple_occs.append(occupancy[0]) else: occupancies = simple_occs #print("OUT",out['occupancies']) #exit(0) struct = Structure.create(a=out['a'], b=out['b'], c=out['c'], alpha=out['alpha'], beta=out['beta'], gamma=out['gamma'], occupancies=occupancies, coords=out['coords'], tags={'platon_sg': out['spacegroup']}).round() return struct
# This is an example program using the High-Throughput toolkit (httk) # This program saves a structure object import httk from httk.core import * from httk.atomistic import Structure basis = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] coordgroups = [[[0.5, 0.5, 0.5]], [[0.0, 0.0, 0.0]], [[0.5, 0.0, 0.0], [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]]] assignments = ['Pb', 'Ti', 'O'] struct = Structure.create(uc_basis=basis, uc_reduced_coordgroups=coordgroups, assignments=assignments, uc_volume=62.79) # One alternative struct.io.save("PbTiO3.vasp") print("PbTiO3.vasp saved (POSCAR format)") # Another alternative httk.save(struct, "PbTiO3_alt.vasp") print("PbTiO3_alt.vasp saved (POSCAR format)") basis = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] coordgroups = [[[0.5, 0.5, 0.5]], [[0.0, 0.0, 0.0]], [[0.5, 0.0, 0.0]]] assignments = ['Pb', 'Ti', 'O']
def structure_to_ase_atoms(struct): ensure_ase_is_imported() struct = Structure.use(struct) if struct.has_uc_repr: symbollist, scaled_positions = httk.iface.ase_if.uc_structure_to_symbols_and_scaled_positions( struct) scaled_positions = scaled_positions.to_floats() cell = struct.uc_basis.to_floats() symbols = [] for s in symbollist: if is_sequence(s): if len(s) == 1: symbols += [s[0]] else: symbols += [str(s)] else: symbols += [s] atoms = Atoms(symbols=symbols, cell=cell, scaled_positions=scaled_positions, pbc=True) elif struct.has_rc_repr: symbollist, scaled_positions = httk.iface.ase_if.rc_structure_to_symbols_and_scaled_positions( struct) symbols = [] for s in symbollist: if is_sequence(s): if len(s) == 1: symbols += [s[0]] else: symbols += [str(s)] else: symbols += [s] hall = struct.rc_sites.hall_symbol symops = get_symops_strs(hall) rot, trans = ase.spacegroup.spacegroup.parse_sitesym(symops) spgnbr, setting = spacegroup_get_number_and_setting(hall) spg = ase.spacegroup.spacegroup.spacegroup_from_data( no=spgnbr, symbol=hall, centrosymmetric=None, scaled_primitive_cell=None, reciprocal_cell=None, subtrans=None, sitesym=None, rotations=rot, translations=trans, datafile=None) atoms = crystal(symbols, scaled_positions, spg, cellpar=[ float(struct.rc_a), float(struct.rc_b), float(struct.rc_c), float(struct.rc_alpha), float(struct.rc_beta), float(struct.rc_gamma) ]) else: raise Exception( "ase_glue.structure_to_ase_atoms: structure has neither primcell, nor representative, representation." ) return atoms
def spglib_out_to_struct(out): cell = FracVector.from_floats(out[0].tolist()) coords = FracVector.from_floats(out[1].tolist()) occupations = out[2] print("OCCUPATIONS:", occupations) return Structure.create(cell=cell, coords=coords, occupations=occupations)
def readstruct(ioa, struct, importers=None): fileadapter = ioadapters.IoAdapterFileReader(ioa) if fileadapter.ext == 'structure': struct.parse(fileadapter) if importers is None: try_importers = ['ase', 'openbabel'] else: try_importers = importers for importer in try_importers: if importer == 'ase': try: import ase.io atoms = ase.io.read(fileadapter.filename_open_workaround()) species = atoms.get_atomic_numbers() coords = atoms.get_positions() basis = atoms.get_cell() return Structure(basis=basis, coords=coords, species=species) except Exception as e: if importers is not None: reraise_from( Exception, "Error while trying ase importer: " + str(info[1]), e) elif importer == 'openbabel': try: import openbabel file = fileadapter.file filename = fileadapter.filename # Use babel to read data from file obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats( obConversion.FormatFromExt(fileadapter.filename), obConversion.FindFormat("pdb")) obmol = openbabel.OBMol() obConversion.ReadString(obmol, file.read()) unitcell = openbabel.toUnitCell( obmol.GetData(openbabel.UnitCell)) unitcell.FillUnitCell(obmol) basisvecs = unitcell.GetCellVectors() basis = array([[ basisvecs[0].GetX(), basisvecs[0].GetY(), basisvecs[0].GetZ() ], [ basisvecs[1].GetX(), basisvecs[1].GetY(), basisvecs[1].GetZ() ], [ basisvecs[2].GetX(), basisvecs[2].GetY(), basisvecs[2].GetZ() ]]) coords = [] species = [] for obatom in openbabel.OBMolAtomIter(obmol): cart = openbabel.vector3(obatom.GetX(), obatom.GetY(), obatom.GetZ()) coords.append([cart.GetX(), cart.GetY(), cart.GetZ()]) species.append(obatom.GetAtomicNum()) return Structure(basis=basis, coords=coords, species=species) except: if importers is not None: info = sys.exc_info() reraise_from( Exception, "Error while trying openbabel importer: " + str(info[1]), info) raise Exception("Could not figure out a way to read structure") return None
def cifdata_to_struct(cifdata, debug=False): if len(cifdata) > 1: raise Exception("httk.atomistic.atomisticio.structure_cif_io: cifdata to struct with more than one image in cifdata.") element = cifdata[0][1] if debug: import pprint pp = pprint.PrettyPrinter() debugout = dict(element) if 'symmetry_equiv_pos_as_xyz' in debugout: del debugout['symmetry_equiv_pos_as_xyz'] if 'space_group_symop_operation_xyz' in debugout: del debugout['space_group_symop_operation_xyz'] if 'space_group_symop_id' in debugout: del debugout['space_group_symop_id'] pp.pprint(debugout) rc_lengths = FracVector.create([element['cell_length_a'], element['cell_length_b'], element['cell_length_c']]) rc_cosangles = FracVector.create_cos([element['cell_angle_alpha'], element['cell_angle_beta'], element['cell_angle_gamma']],degrees=True) hall_symbol = None hm_symbol = None spacegroupnumber = None setting = None symops = None if 'symmetry_space_group_name_hall' in element: hall_symbol = element['symmetry_space_group_name_hall'] if 'space_group_symop_operation_xyz' in element: symops = element['space_group_symop_operation_xyz'] elif 'symmetry_equiv_pos_as_xyz' in element: symops = element['symmetry_equiv_pos_as_xyz'] if 'symmetry_space_group_name_h-m' in element: hm_symbol = element['symmetry_space_group_name_h-m'] if 'symmetry_Int_Tables_number' in element: spacegroupnumber = int(element['symmetry_Int_Tables_number']) # cif verb symmetry_cell_setting really is not defined as it would seems logical. Due to ensuing confusion, we better simply ignore it #if 'symmetry_cell_setting' in element: # setting = element['symmetry_cell_setting'] if hall_symbol is None and symops is None and hm_symbol is None and spacegroupnumber is None: raise Exception("No symmetry information given in cif file, impossible to interpret coordinate data!") spacegroup = Spacegroup.create(hall_symbol=hall_symbol, hm_symbol=hm_symbol, spacegroupnumber=spacegroupnumber, setting=setting, symops=symops) rc_occupancies = [] rc_reduced_occupationscoords = [] wyckoff_symbols = None multiplicities = None if 'atom_site_wyckoff_symbol' in element: wyckoff_symbols = element['atom_site_wyckoff_symbol'] elif 'atom_site_wyckoff_label' in element: wyckoff_symbols = element['atom_site_wyckoff_label'] if 'atom_site_symmetry_multiplicity' in element: multiplicities = [int(x) for x in element['atom_site_symmetry_multiplicity']] for atom in range(len(element['atom_site_label'])): if 'atom_site_occupancy' in element: ratio = element['atom_site_occupancy'][atom] else: ratio = 1 symbol = str(re.match('[A-Z][a-z]?',element['atom_site_label'][atom]).group(0)) occup = {'atom': periodictable.atomic_number(symbol), 'ratio': FracVector.create(ratio), } coord = [element['atom_site_fract_x'][atom], element['atom_site_fract_y'][atom], element['atom_site_fract_z'][atom]] rc_occupancies += [occup] rc_reduced_occupationscoords += [coord] #print("X",rc_lengths,rc_angles,rc_reduced_occupationscoords,rc_occupancies,spacegroup,setting,wyckoff_symbols,multiplicities) tags = {} if 'chemical_name_common' in element: if is_sequence(element['chemical_name_common']): tags['name'] = element['chemical_name_common'][0] tags['names'] = ",".join(element['chemical_name_common']) else: tags['name'] = element['chemical_name_common'] elif 'chemical_name_systematic' in element: if is_sequence(element['chemical_name_systematic']): tags['name'] = element['chemical_name_systematic'][0] tags['names'] = ",".join(element['chemical_name_systematic']) else: tags['name'] = element['chemical_name_systematic'] authorlist = None if 'publ_author_name' in element: authorlist = [] authors = element['publ_author_name'] if not basic.is_sequence(authors): authors = [authors] for author in authors: authorparts = author.partition(",") lastname = authorparts[0].strip() givennames = authorparts[2].strip() authorlist += [Author.create(lastname, givennames)] # I didn't find this in the spec, on the other hand, the publ_ space is "not specified", so, this seems # as a logical extension of the author list in case of a cif file that has been published in a book. # I see no harm in including it, at least. editorlist = None if 'publ_editor_name' in element: editorlist = [] editors = element['publ_editor_name'] if not basic.is_sequence(editors): editors = [editors] for editor in editors: editorparts = editor.partition(",") lastname = editorparts[0].strip() givennames = editorparts[2].strip() editorlist += [Author.create(lastname, givennames)] refs = None if 'journal_name_full' in element or 'journal_name_abbrev' in element: journal = None journal_page_first = None journal_page_last = None journal_volume = None journal_title = None journal_book_title = None journal_year = None journal_issue = None journal_publisher = None journal_publisher_city = None if 'journal_name_abbrev' in element: journal = element['journal_name_abbrev'] if 'journal_name_full' in element: journal = element['journal_name_full'] if 'journal_page_first' in element: journal_page_first = element['journal_page_first'] if 'journal_page_last' in element: journal_page_last = element['journal_page_last'] if 'journal_volume' in element: journal_volume = element['journal_volume'] if 'journal_issue' in element: journal_issue = element['journal_issue'] if 'journal_title' in element: journal_title = element['journal_title'] if 'journal_book_title' in element: journal_book_title = element['journal_book_title'] if 'journal_year' in element: journal_year = element['journal_year'] if 'journal_publisher' in element: journal_publisher = element['journal_publisher'] if 'journal_publisher_city' in element: journal_publisher_city = element['journal_publisher_city'] if 'journal_book_publisher' in element: journal_publisher = element['journal_book_publisher'] if 'journal_book_publisher_city' in element: journal_publisher_city = element['journal_book_publisher_city'] refs = [Reference.create(authors=authorlist, editors=editorlist, journal=journal, journal_issue=journal_issue, journal_volume=journal_volume, page_first=journal_page_first, page_last=journal_page_last, title=journal_title, year=journal_year, book_publisher=journal_publisher, book_publisher_city=journal_publisher_city, book_title=journal_book_title)] # This is based on some assumptions... IF a journal_* type tree exists, then we assume this is a 'published' cif, and # in that case the only reference we want to keep is the one to the published work. Citations in the citation_* tree is going to be # all the citations from that paper, which we do not want, *unless* they mark citation_coordinate_linkage. However, # if no journal_* tree exists, then this is a 'generic' structure cif, where the citations should point to all publications of # this structure; and we don't want to assume 'citation_coordinate_linkage' add_all_citations = False if refs is None or len(refs) == 0: add_all_citations = True if 'citation_journal_full' in element or 'citation_journal_abbrev' in element or 'citation_book_title' in element: if refs is None: refs = [] if 'citation_journal_full' in element: N = len(element['citation_journal_full']) elif 'citation_journal_abbrev' in element: N = len(element['citation_journal_abbrev']) elif 'citation_book_title' in element: N = len(element['citation_book_title']) for i in range(N): if not add_all_citations and ('citation_coordinate_linkage' not in element or (element['citation_coordinate_linkage'][i].lower() != 'yes' and element['citation_coordinate_linkage'][i].lower() != 'y')): continue journal = None journal_page_first = None journal_page_last = None journal_volume = None journal_title = None journal_book_title = None journal_issue = None journal_publisher = None journal_publisher_city = None if 'citation_journal_full' in element: journal = element['citation_journal_full'][i] if 'citation_journal_abbrev' in element: journal = element['citation_journal_abbrev'][i] if 'citation_page_first' in element: journal_page_first = element['citation_page_first'][i] if 'citation_page_last' in element: journal_page_last = element['citation_page_last'][i] if 'citation_journal_volume' in element: journal_volume = element['citation_journal_volume'][i] if 'citation_journal_issue' in element: journal_issue = element['citation_journal_issue'][i] if 'citation_title' in element: journal_title = element['citation_title'][i] if 'citation_book_title' in element: journal_book_title = element['citation_book_title'][i] if 'journal_year' in element: journal_year = element['journal_year'][i] if 'citation_book_publisher' in element: journal_publisher = element['citation_book_publisher'][i] if 'citation_book_publisher_city' in element: journal_publisher_city = element['citation_book_publisher_city'][i] refs += [Reference.create(authors=authorlist, editors=editorlist, journal=journal, journal_issue=journal_issue, journal_volume=journal_volume, page_first=journal_page_first, page_last=journal_page_last, title=journal_title, year=journal_year, book_publisher=journal_publisher, book_publisher_city=journal_publisher_city, book_title=journal_book_title)] struct = Structure.create(rc_lengths=rc_lengths, rc_cosangles=rc_cosangles, rc_reduced_occupationscoords=rc_reduced_occupationscoords, rc_occupancies=rc_occupancies, spacegroup=spacegroup, setting=setting, periodicity=0, wyckoff_symbols=wyckoff_symbols, multiplicities=multiplicities, tags=tags, refs=refs) return struct
def cif_reader_that_can_only_read_isotropy_cif(ioa): def cell_length(results, match): results['length_'+match.group(1)] = FracVector.create(match.group(2)) def cell_angle(results, match): results['angle_'+match.group(1)] = FracVector.create(match.group(2)) def print_hm_and_hall(results): grpnbr = results['grpnbr'] setting = results['setting'] hmsymb = results['hmfull'] hallsymb = spacegroups.spacegroup_get_hall(str(grpnbr)+":"+setting) results['hall_symbol'] = hallsymb def hm_symbol_origin(results, match): results['out'] = True results['hmfull'] = match.group(1) results['hm'] = match.group(2) if match.group(3) == 'hexagonal axes': results['setting'] = '1' else: results['setting'] = str(match.group(3)) if 'hm' in results and 'grpnbr' in results: print_hm_and_hall(results) def hm_symbol_no_origin(results, match): results['out'] = True results['hmfull'] = match.group(1) results['hm'] = match.group(1) results['setting'] = "1" if 'hm' in results and 'grpnbr' in results: print_hm_and_hall(results) def groupnbr(results, match): results['grpnbr'] = match.group(1) if 'hm' in results and 'grpnbr' in results: print_hm_and_hall(results) def coords(results, match): newcoord = httk.FracVector.create([match.group(5), match.group(6), match.group(7)]) occup = {'atom': periodictable.atomic_number(match.group(2)), 'ratio': FracVector.create(match.group(8)), } if match.group(4) == 'alpha': wyckoff = '&' else: wyckoff = match.group(4) multiplicities = int(match.group(3)) if newcoord in results['seen_coords']: idx = results['seen_coords'][newcoord] results['occups'][idx].append(occup) else: results['seen_coords'][newcoord] = results['idx'] results['coords'].append(newcoord) results['occups'].append([occup]) results['wyckoff'].append(wyckoff) results['multiplicities'].append(multiplicities) results['idx'] += 1 results = {'idx': 0, 'occups': [], 'wyckoff': [], 'multiplicities': [], 'coords': [], 'seen_coords': {}} httk.basic.micro_pyawk(ioa, [ ['^_cell_length_([^ ]*) (.*) *$', None, cell_length], ['^_cell_angle_([^ ]*) (.*) *$', None, cell_angle], ['^_symmetry_Int_Tables_number +(.*)$', None, groupnbr], ['^_symmetry_space_group_name_H-M +"(([^()]+) \(origin choice ([0-9]+)\))" *$', None, hm_symbol_origin], ['^_symmetry_space_group_name_H-M +"(([^()]+) \((hexagonal axes)\))" *$', None, hm_symbol_origin], ['^_symmetry_space_group_name_H-M +"([^()]+)" *$', None, hm_symbol_no_origin], ['^ *([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([0-9.-]+) +([0-9.-]+) +([0-9.-]+) +([0-9.-]+) *$', None, coords], ], debug=False, results=results) struct = Structure.create(rc_a=results['length_a'], rc_b=results['length_b'], rc_c=results['length_c'], rc_alpha=results['angle_alpha'], rc_beta=results['angle_beta'], rc_gamma=results['angle_gamma'], rc_reduced_occupationscoords=results['coords'], rc_occupancies=results['occups'], spacegroup=results['hall_symbol'], wyckoff_symbols=results['wyckoff'], multiplicities=results['multiplicities']) return struct