Beispiel #1
0
def normalized_formula_parts(assignments, ratios, counts):

    formula = {}
    alloccs = {}
    maxc = 0
    for i in range(len(counts)):
        assignment = assignments[i]
        ratio = ratios[i]
        if not assignment in formula:
            formula[assignment] = FracVector.create(0)
            alloccs[assignment] = FracVector.create(0)
        occ = ratio
        formula[assignment] += occ * counts[i]
        alloccs[assignment] += FracVector.create(counts[i])
        if alloccs[assignment] > maxc:
            maxc = alloccs[assignment]

    alloccs = FracVector.create(alloccs.values())
    alloccs = (alloccs / maxc).simplify()

    for symbol in formula.keys():
        formula[symbol] = (formula[symbol] * alloccs.denom / maxc).simplify()
    #    if abs(value-int(value))<1e-6:
    #        formula[symbol] = int(value)
    #    elif int(100*(value-(int(value)))) > 1:
    #        formula[symbol] = float("%d.%.2e" % (value, 100*(value-(int(value)))))
    #    else:
    #        formula[symbol] = float("%d" % (value,))

    return formula
Beispiel #2
0
def main():
    cell = FracVector.create([[1, 1, 0], [1, 0, 1], [0, 1, 1]])
    coordgroups = FracVector.create([[[2, 3, 5], [3, 5, 4]], [[4, 6, 7]]])
    assignments = [2, 5]

    print(cell, coordgroups)
    cell, coordgroups = coordswap(0, 2, cell, coordgroups)
    print(cell, coordgroups)

    pass
Beispiel #3
0
    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
Beispiel #4
0
    def read_coords_occs(results, match):
        if results['in_input']:
            coordstr = 'sgcoords'
            occstr = 'sgoccupancies'
            seenstr = 'sgseen'
            idxstr = 'sgidx'
        elif results['in_output']:
            coordstr = 'coords'
            occstr = 'occupancies'
            seenstr = 'seen'
            idxstr = 'idx'
        else:
            return

        newcoord = (match.group(2), match.group(3), match.group(4))
        #newcoord = FracVector.create([match.group(2),match.group(3),match.group(4)]).limit_denominator(5000000).simplify()
        species = match.group(1).split("/")
        occups = match.group(6).split("/")

        for j in range(len(species)):        
            occup = {'atom': periodictable.atomic_number(species[j]), 'ratio': FracVector.create(occups[j]), }
    
            if newcoord in results[seenstr]:
                idx = results[seenstr][newcoord]
                #print("OLD",results[occstr],idx)
                results[occstr][idx].append(occup)
            else:
                results[seenstr][newcoord] = results[idxstr]
                results[coordstr].append(newcoord)
                results[occstr].append([occup])
                results[idxstr] += 1
Beispiel #5
0
def normalized_formula_parts(assignments, ratios, counts):

    formula = {}
    alloccs = {}
    maxc = 0
    for i in range(len(counts)):
        assignment = assignments[i]
        ratio = ratios[i]
        if is_sequence(assignment):
            if len(assignment) == 1:
                assignment = assignment[0]
                ratio = ratio[0]
                occ = ratio
            else:
                assignment = tuple([(x, FracVector.use(y))
                                    for x, y in zip(assignment, ratio)])
                occ = 1
        else:
            occ = ratio
        if not assignment in formula:
            formula[assignment] = FracVector.create(0)
            alloccs[assignment] = FracVector.create(0)
        formula[assignment] += FracVector.create(occ * counts[i])
        alloccs[assignment] += FracVector.create(counts[i])
        if alloccs[assignment] > maxc:
            maxc = alloccs[assignment]

    alloccs = FracVector.create(alloccs.values())
    alloccs = (alloccs / maxc).simplify()

    for symbol in formula.keys():
        formula[symbol] = (formula[symbol] * alloccs.denom / maxc).simplify()
    #    if abs(value-int(value))<1e-6:
    #        formula[symbol] = int(value)
    #    elif int(100*(value-(int(value)))) > 1:
    #        formula[symbol] = float("%d.%.2e" % (value, 100*(value-(int(value)))))
    #    else:
    #        formula[symbol] = float("%d" % (value,))

    return formula
Beispiel #6
0
    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)
Beispiel #7
0
def coordswap(fromidx, toidx, cell, coordgroups):
    new_coordgroups = []
    for group in coordgroups:
        coords = MutableFracVector.from_FracVector(group)
        rows = coords[:, toidx]
        coords[:, toidx] = coords[:, fromidx]
        coords[:, fromidx] = rows
        new_coordgroups.append(coords.to_FracVector())
    coordgroups = FracVector.create(new_coordgroups)

    cell = MutableFracVector.from_FracVector(cell)
    row = cell[toidx]
    cell[toidx] = cell[fromidx]
    cell[fromidx] = row
    cell = cell.to_FracVector()

    return (cell, coordgroups)
Beispiel #8
0
def occupations_and_coords_to_assignments_and_coordgroups(
        occupationscoords, occupations):
    if len(occupationscoords) == 0:
        return [], FracVector((), 1)

    occupationscoords = FracVector.use(occupationscoords)

    new_coordgroups = []
    new_assignments = []
    for i in range(len(occupations)):
        for j in range(len(new_assignments)):
            if occupations[i] == new_assignments[j]:
                new_coordgroups[j].append(occupationscoords[i])
                break
        else:
            new_coordgroups.append([occupationscoords[i]])
            new_assignments.append(occupations[i])
    new_coordgroups = FracVector.create(new_coordgroups)
    return new_assignments, new_coordgroups
Beispiel #9
0
def basis_to_niggli(basis):
    basis = FracVector.use(basis)

    A = basis.noms
    det = basis.det()
    if det == 0:
        raise Exception("basis_to_niggli: singular cell matrix.")

    if det > 0:
        orientation = 1
    else:
        orientation = -1

    s11 = A[0][0] * A[0][0] + A[0][1] * A[0][1] + A[0][2] * A[0][2]
    s22 = A[1][0] * A[1][0] + A[1][1] * A[1][1] + A[1][2] * A[1][2]
    s33 = A[2][0] * A[2][0] + A[2][1] * A[2][1] + A[2][2] * A[2][2]

    s23 = A[1][0] * A[2][0] + A[1][1] * A[2][1] + A[1][2] * A[2][2]
    s13 = A[0][0] * A[2][0] + A[0][1] * A[2][1] + A[0][2] * A[2][2]
    s12 = A[0][0] * A[1][0] + A[0][1] * A[1][1] + A[0][2] * A[1][2]

    new = FracVector.create(((s11, s22, s33), (2 * s23, 2 * s13, 2 * s12)),
                            denom=basis.denom**2).simplify()
    return new, orientation
Beispiel #10
0
def get_primitive_basis_transform(hall_symbol):
    """
    Transform to be applied to conventional unit cell to give the primitive unit cell
    """
    half = Fraction(1, 2)
    lattice_symbol = hall_symbol.lstrip("-")[0][0]
    crystal_system = crystal_system_from_hall(hall_symbol)

    lattrans = None
    unit = FracVector.create([[1, 0, 0], [0, 1, 0], [0, 0, 1]])

    if lattice_symbol == 'P':
        lattrans = unit
    elif crystal_system == 'cubic':
        if lattice_symbol == 'F':
            lattrans = FracVector.create([[half, half, 0], [half, 0, half],
                                          [0, half, half]])
        elif lattice_symbol == 'I':
            lattrans = FracVector.create([[half, half, half],
                                          [-half, half, half],
                                          [-half, -half, half]])
    elif crystal_system == 'hexagonal' or crystal_system == 'trigonal':
        if lattice_symbol == 'R':
            lattrans = unit

    elif crystal_system == 'tetragonal':
        if lattice_symbol == 'I':
            lattrans = FracVector.create([[half, -half, half],
                                          [half, half, half],
                                          [-half, -half, half]])

    elif crystal_system == 'orthorhombic':
        if lattice_symbol == 'A':
            lattrans = FracVector.create([[1, 0, 0], [0, half, half],
                                          [0, -half, half]])
        elif lattice_symbol == 'B':
            lattrans = FracVector.create([[half, 0, half], [0, 1, 0],
                                          [-half, 0, half]])
        elif lattice_symbol == 'C':
            lattrans = FracVector.create([[half, half, 0], [-half, half, 0],
                                          [0, 0, 1]])
        elif lattice_symbol == 'F':  # or lattice_symbol == 'A' or lattice_symbol == 'B' or lattice_symbol == 'C':
            lattrans = FracVector.create([[half, 0, half], [half, half, 0],
                                          [0, half, half]])
        elif lattice_symbol == 'I':
            lattrans = FracVector.create([[half, half, half],
                                          [-half, half, half],
                                          [-half, -half, half]])

    elif crystal_system == 'monoclinic':
        if lattice_symbol == 'A':
            lattrans = FracVector.create([[1, 0, 0], [0, half, -half],
                                          [0, half, half]])
        if lattice_symbol == 'B':
            lattrans = FracVector.create([[half, 0, -half], [0, 1, 0],
                                          [half, 0, half]])
        if lattice_symbol == 'C':
            lattrans = FracVector.create([[half, -half, 0], [half, half, 0],
                                          [0, 0, 1]])

    elif crystal_system == 'triclinic':
        lattrans = unit

    else:
        raise Exception(
            "structureutils.get_primitive_basis_transform: unknown crystal system, "
            + str(crystal_system))

    if lattrans is None:
        raise Exception(
            "structureutils.get_primitive_basis_transform: no match for lattice transform."
        )

    return lattrans
Beispiel #11
0
def build_supercell_old(structure, transformation, max_search_cells=1000):
    ### New basis matrix, note: works in units of old_cell.scale to avoid floating point errors
    #print("BUILD SUPERCELL",structure.uc_sites.cell.basis.to_floats(), repetitions)

    transformation = FracVector.use(transformation).simplify()
    if transformation.denom != 1:
        raise Exception(
            "Structure.build_supercell requires integer transformation matrix")

    old_cell = structure.uc_sites.cell.get_normalized_longestvec()
    new_cell = Cell.create(basis=transformation * old_cell.basis)
    #conversion_matrix = (new_cell.inv*old_cell.basis).T().simplify()
    conversion_matrix = (old_cell.basis * new_cell.inv).T().simplify()

    volume_ratio = (new_cell.basis.det() /
                    abs(old_cell.basis.det())).simplify()

    # Generate the reduced (old cell) coordinates of each corner in the new cell
    # This determines how far we must loop the old cell to cover all these corners
    nb = new_cell.basis
    corners = FracVector.create([(0, 0, 0), nb[0], nb[1], nb[2], nb[0] + nb[1],
                                 nb[0] + nb[2], nb[1] + nb[2],
                                 nb[0] + nb[1] + nb[2]])
    reduced_corners = corners * (old_cell.basis.inv().T())

    maxvec = [
        int(reduced_corners[:, 0].max()) + 2,
        int(reduced_corners[:, 1].max()) + 2,
        int(reduced_corners[:, 2].max()) + 2
    ]
    minvec = [
        int(reduced_corners[:, 0].min()) - 2,
        int(reduced_corners[:, 1].min()) - 2,
        int(reduced_corners[:, 2].min()) - 2
    ]

    if max_search_cells is not None and maxvec[0] * maxvec[1] * maxvec[
            2] > max_search_cells:
        raise Exception(
            "Very obtuse angles in cell, to search over all possible lattice vectors will take a very long time. To force, set max_search_cells = None when calling find_prototypeid()"
        )

    ### Collect coordinate list of all sites inside the new cell
    coordgroups = structure.uc_reduced_coordgroups
    extendedcoordgroups = [[] for x in range(len(coordgroups))]
    for idx in range(len(coordgroups)):
        coordgroup = coordgroups[idx]
        for i in range(minvec[0], maxvec[0]):
            for j in range(minvec[1], maxvec[1]):
                for k in range(minvec[2], maxvec[2]):
                    newcoordgroup = coordgroup + FracVector(
                        ((i, j, k), ) * len(coordgroup))
                    new_reduced = newcoordgroup * conversion_matrix
                    new_reduced = [
                        x for x in new_reduced if x[0] >= 0 and x[1] >= 0
                        and x[2] >= 0 and x[0] < 1 and x[1] < 1 and x[2] < 1
                    ]
                    extendedcoordgroups[idx] += new_reduced

    # Safety check for avoiding bugs that change the ratio of atoms
    new_counts = [len(x) for x in extendedcoordgroups]
    for i in range(len(structure.uc_counts)):
        if volume_ratio * structure.uc_counts[i] != new_counts[i]:
            print("Volume ratio:", float(volume_ratio), volume_ratio)
            print("Extended coord groups:",
                  FracVector.create(extendedcoordgroups).to_floats())
            print("Old counts:", structure.uc_counts,
                  structure.assignments.symbols)
            print("New counts:", new_counts, structure.assignments.symbols)
            #raise Exception("Structure.build_supercell safety check failure. Volume changed by factor "+str(float(volume_ratio))+", but atoms in group "+str(i)+" changed by "+str(float(new_counts[i])/float(structure.uc_counts[i])))

    return structure.create(uc_reduced_coordgroups=extendedcoordgroups,
                            basis=new_cell.basis,
                            assignments=structure.assignments,
                            cell=structure.uc_cell)
Beispiel #12
0
def orthogonal_supercell_transformation(structure,
                                        tolerance=None,
                                        ortho=[True, True, True]):
    # TODO: How to solve for exact orthogonal cell?
    if tolerance is None:
        prim_cell = structure.uc_cell.basis
        print("Starting cell:", prim_cell)
        inv = prim_cell.inv().simplify()
        if ortho[0]:
            row0 = (inv[0] / max(inv[0])).simplify()
        else:
            row0 = [1, 0, 0]
        if ortho[1]:
            row1 = (inv[1] / max(inv[1])).simplify()
        else:
            row1 = [0, 1, 0]
        if ortho[2]:
            row2 = (inv[2] / max(inv[2])).simplify()
        else:
            row2 = [0, 0, 1]
        transformation = FracVector.create(
            [row0 * row0.denom, row1 * row1.denom, row2 * row2.denom])
    else:
        maxtol = max(int(FracVector.use(tolerance)), 2)
        bestval = None
        besttrans = None
        for tol in range(1, maxtol):
            prim_cell = structure.uc_cell.basis
            inv = prim_cell.inv().set_denominator(tol).simplify()
            if inv[0] == [0, 0, 0] or inv[1] == [0, 0, 0
                                                 ] or inv[2] == [0, 0, 0]:
                continue
            absinv = abs(inv)
            if ortho[0]:
                row0 = (inv[0] / max(absinv[0])).simplify()
            else:
                row0 = [1, 0, 0]
            if ortho[1]:
                row1 = (inv[1] / max(absinv[1])).simplify()
            else:
                row1 = [0, 1, 0]
            if ortho[2]:
                row2 = (inv[2] / max(absinv[2])).simplify()
            else:
                row2 = [0, 0, 1]
            transformation = FracVector.create(
                [row0 * row0.denom, row1 * row1.denom, row2 * row2.denom])
            try:
                cell = Cell.create(basis=transformation * prim_cell)
            except Exception:
                continue
            maxval = (abs(cell.niggli_matrix[1][0]) +
                      abs(cell.niggli_matrix[1][1]) +
                      abs(cell.niggli_matrix[1][2])).simplify()
            if maxval == 0:
                besttrans = transformation
                break
            if bestval is None or maxval < bestval:
                bestval = maxval
                besttrans = transformation
        transformation = besttrans

    if transformation == None:
        raise Exception(
            "Not possible to find a othogonal supercell with this limitation of number of repeated cell (increase tolerance.)"
        )

    return transformation
Beispiel #13
0
def out_to_struct(ioa):
    """
    Example input::
    
        OUTPUT CELL INFORMATION
        Symmetry information:
        Trigonal crystal system.
        Space group number     : 165
        Hall symbol            : -P 3 2"c
        Hermann-Mauguin symbol : P-3c1
        
        Bravais lattice vectors :
          0.8660254  -0.5000000   0.0000000 
          0.0000000   1.0000000   0.0000000 
          0.0000000   0.0000000   1.0231037 
        All sites, (lattice coordinates):
        Atom           a1          a2          a3 
        La      0.6609000   0.0000000   0.2500000
        La      0.3391000   0.0000000   0.7500000
        ...
        F       0.0000000   0.0000000   0.2500000
        F       0.0000000   0.0000000   0.7500000
        
        Unit cell volume  : 328.6477016 A^3
        Unit cell density :   3.5764559 u/A^3 =   5.9388437 g/cm^3
    """
    results = {}
    results['output_cell'] = []
    results['input_cell'] = []
    results['coords'] = []
    results['sgcoords'] = []
    results['occupancies'] = []
    results['sgoccupancies'] = []
    results['in_output'] = False
    results['in_input'] = False
    results['in_input_coords'] = False
    results['in_coords'] = False
    results['in_cell'] = False
    results['in_input_cell'] = False
    results['in_bib'] = False
    results['bib'] = ""
    results['seen'] = {}
    results['sgseen'] = {}
    results['idx'] = 0
    results['sgidx'] = 0
    
    def read_cell(results, match):
        if results['in_input']:
            results['input_cell'].append([(match.group(1)), (match.group(2)), (match.group(3))])
        elif results['in_output']:
            results['output_cell'].append([(match.group(1)), (match.group(2)), (match.group(3))])

    def read_coords_occs(results, match):
        if results['in_input']:
            coordstr = 'sgcoords'
            occstr = 'sgoccupancies'
            seenstr = 'sgseen'
            idxstr = 'sgidx'
        elif results['in_output']:
            coordstr = 'coords'
            occstr = 'occupancies'
            seenstr = 'seen'
            idxstr = 'idx'
        else:
            return

        newcoord = (match.group(2), match.group(3), match.group(4))
        #newcoord = FracVector.create([match.group(2),match.group(3),match.group(4)]).limit_denominator(5000000).simplify()
        species = match.group(1).split("/")
        occups = match.group(6).split("/")

        for j in range(len(species)):        
            occup = {'atom': periodictable.atomic_number(species[j]), 'ratio': FracVector.create(occups[j]), }
    
            if newcoord in results[seenstr]:
                idx = results[seenstr][newcoord]
                #print("OLD",results[occstr],idx)
                results[occstr][idx].append(occup)
            else:
                results[seenstr][newcoord] = results[idxstr]
                results[coordstr].append(newcoord)
                results[occstr].append([occup])
                results[idxstr] += 1
                #print("NEW",results[occstr],results[idxstr])
                          
    def read_coords(results, match):
        if results['in_input']:
            coordstr = 'sgcoords'
            occstr = 'sgoccupancies'
            seenstr = 'sgseen'
            idxstr = 'sgidx'
        elif results['in_output']:
            coordstr = 'coords'
            occstr = 'occupancies'
            seenstr = 'seen'
            idxstr = 'idx'
        else:
            return

        newcoord = (match.group(2), match.group(3), match.group(4))
        #newcoord = FracVector.create([match.group(2),match.group(3),match.group(4)]).limit_denominator(5000000).simplify()
        species = match.group(1)
        occup = {'atom': periodictable.atomic_number(species)}        

        if newcoord in results[seenstr]:
            idx = results[seenstr][newcoord]
            #print("XOLD",results[occstr],idx)
            results[occstr][idx].append(occup)
        else:
            results[seenstr][newcoord] = results[idxstr]
            results[coordstr].append(newcoord)
            results[occstr].append([occup])
            results[idxstr] += 1
            #print("XNEW",results[occstr],results['idx'])

        #if results['in_input']:
        #    results['sgcoords'].append(newcoord)
        #    results['sgoccupancies'].append(periodictable.atomic_symbol(match.group(1)))
        #elif results['in_output']:
        #    results['coords'].append(newcoord)
        #    results['occupancies'].append(periodictable.atomic_symbol(match.group(1)))
 
    def read_volume(results, match):
        results['volume'] = match.group(1)

    def read_hall(results, match):
        if results['in_input']:
            results['sghall'] = match.group(1)
        elif results['in_output']:
            results['hall'] = match.group(1)

    def read_id(results, match):
        results['id'] = match.group(1)

    def coords_stop(results, match):
        results['in_coords'] = False

    def coords_start(results, match):
        if results['in_input']:
            results['in_input_coords'] = True
        elif results['in_output']:
            results['in_coords'] = True

    def cell_stop(results, match):
        results['in_cell'] = False

    def input_cell_stop(results, match):
        results['in_input_cell'] = False

    def cell_start(results, match):
        results['in_cell'] = True

    def input_cell_start(results, match):
        results['in_input_cell'] = True

    def output_start(results, match):
        results['in_output'] = True        
        results['in_input'] = False

    def read_version(results, match):
        results['version'] = match.group(1)

    def read_name(results, match):
        expr = httk.basic.parse_parexpr(match.group(1))
        # Grab the last, nested, parenthesed expression 
        p = ""
        for x in expr:
            if x[0] == 0:
                p = x[1]
        results['name'] = p

    def read_bib(results, match):
        if match.group(1).strip() != 'Failed to get author information, No journal information':
            results['bib'] += match.group(1).strip()

    def bib_start(results, match):
        results['in_bib'] = True

    def bib_stop_input_start(results, match):
        results['in_bib'] = False
        results['in_input'] = True

    def read_source(results, match):        
        results['source'] = match.group(1).rstrip('.')
                
    out = httk.basic.micro_pyawk(ioa, [
        ['^ *INPUT CELL INFORMATION *$', None, bib_stop_input_start],
        ['^ *CIF2CELL ([0-9.]*)', None, read_version],
        ['^ *Output for (.*\)) *$', None, read_name],
        ['^ *Database reference code: *([0-9]+)', None, read_id],
        ['^ *All sites, (lattice coordinates): *$', lambda results, match: results['in_cell'], cell_stop],
        ['^ *Representative sites *: *$', lambda results, match: results['in_input_cell'], input_cell_stop],
        ['^ *$', lambda results, match: results['in_coords'], coords_stop],
        ['^ *([-0-9.]+) +([-0-9.]+) +([-0-9.]+) *$', lambda results, match: results['in_cell'] or results['in_input_cell'], read_cell],
        ['^ *([a-zA-Z]+) +([-0-9.]+) +([-0-9.]+) +([-0-9.]+) *$', lambda results, match: results['in_coords'] or results['in_input_coords'], read_coords],
        ['^ *([a-zA-Z/]+) +([-0-9.]+) +([-0-9.]+) +([-0-9.]+)( +([-0-9./]+)) *$', lambda results, match: results['in_coords'] or results['in_input_coords'], read_coords_occs],
        #            ['^ *Hermann-Mauguin symbol *: *(.*)$',lambda results,match: results['in_output'],read_spacegroup],
        ['^ *Hall symbol *: *(.*)$', lambda results, match: results['in_output'] or results['in_input'], read_hall],
        ['^ *Unit cell volume *: *([-0-9.]+) +A\^3 *$', lambda results, match: results['in_output'], read_volume],
        ['^ *Bravais lattice vectors : *$', lambda results, match: results['in_output'], cell_start],
        ['^ *Lattice parameters: *$', lambda results, match: results['in_input'], input_cell_start],
        ['^ *Atom +a1 +a2 +a3', lambda results, match: results['in_output'] or results['in_input'], coords_start],
        ['^ *OUTPUT CELL INFORMATION *$', None, output_start],
        ['^([^\n]*)$', lambda results, match: results['in_bib'], read_bib],
        ['^ *BIBLIOGRAPHIC INFORMATION *$', None, bib_start],
        ['CIF file exported from +(.*) *$', None, read_source]
          
    ], debug=False, results=results)

    out['bib'] = out['bib'].strip()

    rc_a, rc_b, rc_c = [float(x) for x in out['input_cell'][0]]
    rc_alpha, rc_beta, rc_gamma = [float(x) for x in out['input_cell'][1]]

    uc_a, uc_b, uc_c = [float(x) for x in out['output_cell'][0]]
    uc_alpha, uc_beta, uc_gamma = [float(x) for x in out['output_cell'][1]]

    rc_cell = FracVector.create(out['input_cell'])
    uc_cell = FracVector.create(out['output_cell'])
    coords = FracVector.create(out['coords']).limit_denominator(5000000).simplify()
    sgcoords = FracVector.create(out['sgcoords']).limit_denominator(5000000).simplify()

    hall_symbol = out['hall']
    sghall_symbol = out['sghall']
    tags = {}
    if 'source' in out:
        tags['source'] = out['source']+":"+out['id']
    if 'bib' in out and out['bib'] != '':
        refs = [out['bib']]
    else:
        refs = None
    if 'name' in out:
        tags['name'] = filter(lambda x: x in string.printable, out['name'])

    # This is to handle a weird corner case, where atoms in a disordered structure
    # are placed on equivalent but different sites in the representative representation; then
    # they will be mapped to the same sites in the filled cell. Our solution in that case is
    # to throw away the rc_cell, since it is incorrect - it has equivalent sites that appear
    # different even though they are the same.
    remaining_filled_sites = list(out['occupancies'])
    for i in range(len(out['sgoccupancies'])):
        if out['sgoccupancies'][i] in remaining_filled_sites:
            remaining_filled_sites = filter(lambda a: a != out['sgoccupancies'][i], remaining_filled_sites)
    if len(remaining_filled_sites) > 0:
        rc_cell_broken = True
    else:
        rc_cell_broken = False

    if not rc_cell_broken:    
        struct = Structure.create(rc_lengths=rc_cell[0],
                                  rc_angles=rc_cell[1], 
                                  rc_reduced_occupationscoords=sgcoords, 
                                  uc_cell=uc_cell,
                                  uc_reduced_occupationscoords=coords, 
                                  uc_volume=out['volume'],
                                  rc_occupancies=out['sgoccupancies'], 
                                  uc_occupancies=out['occupancies'], 
                                  spacegroup=sghall_symbol, 
                                  tags=tags, refs=refs, periodicity=0)
    else:
        struct = Structure.create(uc_cell=uc_cell,
                                  uc_reduced_occupationscoords=coords, 
                                  uc_volume=out['volume'],
                                  uc_occupancies=out['occupancies'], 
                                  spacegroup=sghall_symbol, 
                                  tags=tags, refs=refs, periodicity=0)        

    # A bit of santiy check to trigger on possible bugs from cif2cell
    if len(struct.uc_sites.counts) != len(struct.rc_sites.counts):
        print(struct.uc_sites.counts, struct.rc_sites.counts)
        raise Exception("cif2cell_if.out_to_struct: non-sensible parsing of cif2cell output.")

    #if 'volume' in out:
    #    vol = FracVector.create(out['volume'])
    #else:
    #    volstruct = httk.Structure.create(a=a,b=b,c=c,alpha=alpha,beta=beta,gamma=gamma, occupancies=out['sgoccupancies'], coords=sgcoords, hall_symbol=sghall_symbol, refs=refs)
    #    vol = volstruct.volume

    #struct = httk.Structure.create(cell,occupancies=out['occupancies'],coords=coords,volume=vol,tags=tags,hall_symbol=hall_symbol, refs=refs)
    #struct._sgstructure = httk.SgStructure.create(a=a,b=b,c=c,alpha=alpha,beta=beta,gamma=gamma, occupancies=out['sgoccupancies'], coords=sgcoords, hall_symbol=sghall_symbol)
    #print("HERE WE ARE:",out['sgoccupancies'],sgcoords,sghall_symbol)
    #print("HERE WE ARE:",out['occupancies'],coords)
    #struct = httk.Structure.create(cell, volume=vol, unique_occupations=out['sgoccupancies'], uc_occupations=out['occupancies'], unique_reduced_occupationscoords=sgcoords, uc_reduced_occupationscoords=coords, spacegroup=sghall_symbol, tags=tags, refs=refs, periodicity=0)
    #print("HERE",sgcoords, coords)
    #counts = [len(x) for x in out['occupancies']]
    #p1structure = httk.Structure.create(cell,occupancies=out['occupancies'],coords=coords,volume=vol,tags=tags, refs=refs, periodicity=0)
    #struct.set_p1structure(p1structure)

    return struct
Beispiel #14
0
    def get(self, table, sid, types, name):
        #types=self.types[table]

        if name in types['keydict']:
            t = types['keydict'][name]
        else:
            t = types['derived_keydict'][name]

        origt = t

        # Regular column, no strangeness
        if t in self.basics:
            if t == FracScalar:
                val = self.db.get_val(table, table + "_id", sid, name)
                if val is None:
                    return None
                return FracVector.create(
                    FracScalar(int(val),
                               1000000000).limit_denominator(5000000))
            return self.db.get_val(table, table + "_id", sid, name)

        # List type means we need to establish a second table and store key values
        elif isinstance(t, list):
            if not isinstance(t[0], tuple):
                t = [(name, t[0])]
            subtablename = table + "_" + name
            subtypes = [(table + "_sid", int)]
            columns = []

            must_convert_sids = []
            for i in range(len(t)):
                if issubclass(t[i][1], HttkObject):
                    subtypename = t[i][0] + "_" + t[i][1].types(
                    )['name'] + "_sid"
                    subtypes.append((
                        subtypename + "_sid",
                        int,
                    ))
                    columns.append(subtypename)
                    must_convert_sids.append(i)
                else:
                    subtypename = t[i][0]
                    subtypes.append((
                        subtypename,
                        t[i][1],
                    ))
                    columns.append(subtypename)

            result = self.db.get_row(subtablename, table + "_sid", sid,
                                     columns)

            # If the type points to another Storable obect, we need to turn all the sid:s into real objects.
            newresult = []
            for line in result:
                line = list(line)
                for i in must_convert_sids:
                    line[i] = instantiate_from_store(t[i][1], self, line[i])
                newresult.append(line)
            result = newresult

            #print("TYPE0",types['keydict'][name])
            #print("TYPE",origt[0])
            #print("RESULT",result)
            if not type(origt[0]) in (list, tuple):
                return [x[0] for x in result]
            else:
                return result

        # Tuple means numpy array
        elif isinstance(t, tuple):
            tupletype = t[0]

            # Numpy array with fixed number of entries, just flatten and store as _1, _2, ... columns
            if t[1] >= 1:
                size = t[1] * t[2]

                #                 flat = tuple(flatten(val))
                #                 for i in range(size):
                #                     columname=name+"_"+str(i)
                #                     columns.append(columname)
                #                     if tupletype == FracVector:
                #                         columndata.append((flat[i]*1000000000).to_ints())
                #                     else:
                #                         columndata.append(flat[i])
                #
                #                 # Variable length numpy array, needs subtable
                #                 if t[1] == 0:
                #                     subtablename = table+"_"+name
                #                     subtablecolumnname = name
                #                     subdimension = (tupletype,1,t[2])
                #
                #                     for entry in val:  # loops over rows in 2d array
                #                         #data = {table+"_sid":sid,name:entry}
                #                         #self.insert(subtablename,data)
                #                         data = {name:entry}
                #                         subtypes = [(subtablecolumnname,subdimension),(table+"_sid",int)]
                #                         subinserts.append((subtablename, subtypes, data,))

                columnames = []
                for i in range(size):
                    columnames.append(name + "_" + str(i))
                flat = self.db.get_row(table, table + "_id", sid,
                                       columnames)[0]

                if tupletype == FracVector or tupletype == FracScalar:
                    for x in flat:
                        if x is None:
                            return flat
                    #def flatterer(l):
                    #    if l == None:
                    #        return None
                    #    else:
                    #        return Fraction(int(l),1000000000)
                    #flat=map(flatterer,flat)
                    flat = map(
                        lambda l: FracScalar(int(l), 1000000000).
                        limit_denominator(5000000), flat)
                    reshaped = zip(*[iter(flat)] * t[1])
                    return FracVector.create(reshaped)
                else:
                    map(tupletype, flat)
                    return zip(*[iter(flat)] * t[1])
                # TODO: ADD support for numpy

            # Variable length numpy array, needs subtable
            if t[1] == 0:
                subtablename = table + "_" + name
                columnames = []
                for i in range(t[2]):
                    columnames.append(name + "_" + str(i))
                if tupletype == FracVector or tupletype == FracScalar:
                    vals = self.db.get_row(subtablename, table + "_sid", sid,
                                           columnames)
                    vals = map(
                        lambda l: map(lambda x: FracScalar(int(x), 1000000000),
                                      l), vals)
                    return FracVector.create(vals).limit_denominator(5000000)
                else:
                    return self.db.get_row(subtablename, table + "_sid", sid,
                                           columnames)

#       elif issubclass(t,Storable):
        elif hasattr(t, 'types'):
            columnname = name + "_" + t.types()['name'] + "_sid"
            subsid = self.db.get_val(table, table + "_id", sid, columnname)
            return instantiate_from_store(t, self, subsid)

        else:
            raise Exception(
                "Dictstore.get: unexpected class; can only handle basic types and subclasses of Storable. Offending class:"
                + str(t))