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
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
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 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
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
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 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)
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
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
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
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)
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
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
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))