Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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.")
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
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
Exemple #10
0
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
Exemple #11
0
# 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']
Exemple #12
0
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
Exemple #13
0
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)
Exemple #14
0
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
Exemple #15
0
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
Exemple #16
0
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