def shifted_sites_after_prismatic_disto(struct, metal_index, angle): mini = MinimumDistanceNN(tol=0.3) print("rotating around index : ", metal_index) neighbor_O = mini.get_nn_info(struct, metal_index) [X, Y, Z] = struct[metal_index].coords print("metal coords : ", [X, Y, Z]) trueSites = [] # list of dict with index and shifted coordinates O_above = [O['site_index'] for O in neighbor_O if O['site'].z - Z > 0] O_below = [O['site_index'] for O in neighbor_O if O['site'].z - Z < 0] symOperation = find_symmop(struct, angle, translation=(0, 0, 0), center=[X, Y, Z]) trueSites += find_translated_sites(struct, O_above, symOperation) symOperation = find_symmop(struct, -angle, translation=(0, 0, 0), center=[X, Y, Z]) trueSites += find_translated_sites(struct, O_below, symOperation) return (trueSites)
def get_MO_pairs(struct, metal_str="Mn"): print("getting {} - O pairs".format(metal_str)) atom_pair_list = [] mini = MinimumDistanceNN(tol=0.3) for center_index in struct.indices_from_symbol(metal_str): neighbor_O = mini.get_nn_info(struct, center_index) atom_pair_list += [[center_index, O['site_index']] for O in neighbor_O if O['site'].species_string in ["O", "S"]] return (atom_pair_list)
def get_metal_next_neighbor(struct, center_index): next_metal_neighbors = [] # gather the indices of all metal next neighbors # metals around neighbor of neighbor Os mini = MinimumDistanceNN(tol=0.3) neighbor_O = mini.get_nn_info(struct, center_index) for O_index in [O['site_index'] for O in neighbor_O]: next_metal_neighbors += [ M['site_index'] for M in mini.get_nn_info(struct, O_index) if (M['site'].specie.symbol not in ["Na", "Li", "O"]) ] # remove the doubles and the metal center next_metal_neighbors = set(next_metal_neighbors) next_metal_neighbors.discard(center_index) return (next_metal_neighbors)
def metal_envt(struc): # Counts the Me environment in a structure # argument : pymatgen.core.structure # return : 2elt list of (7 element list) : the i th element is the # propotion of A with i A neighbors A = "Mg" B = "Mn" C = "Na" # neighborA = [0 for i in range(0, 7, 1)] # neighborB = [0 for i in range(0, 7, 1)] # A_indices = struc.indices_from_symbol(A) nbC = len(struc.indices_from_symbol(C)) neighborC = np.zeros(6) #print("{0} {1}".format(nbC,C)) sCopy = RemoveSpeciesTransformation(["O"]).apply_transformation(struc) # print(sCopy) mini = MinimumDistanceNN(tol=0.3) for i, site in enumerate(sCopy): # print(str(i)) # print(site) siteName = site.species_string if siteName == C: neigList = mini.get_nn_info(sCopy, i) #print("{0} closest neighboors \n".format(len(neigList))) coordA = 0 coordB = 0 for neighbor in neigList: # index = neighbor['site_index'] neighborName = neighbor['site'].species_string #print(" ( {0} at {1} ) ".format(neighborName,index)) if neighborName == A: coordA += 1 if neighborName == B: coordB += 1 neighborC[coordA] += 1 #print("neighborC list :" , neighborC) if nbC == 0: normalizedNeighborC = [0 for i in neighborC] else: normalizedNeighborC = [i / nbC for i in neighborC] print("coordination {0} : {1} \nnormalized by {2} : {3} \n".format( C, neighborC, nbC, normalizedNeighborC)) return normalizedNeighborC
def get_layer_indices(struct, separator_specie, refIndex=-1): # fonction to gather the indexes of all the atoms in layers separated by Na atoms # input : the layered structure, the index of one non-Na reference atom # returns : an ordered list of indexes of all the atoms in the layer of # the reference atom A = "Mn" B = "Mg" C = "O" # if no reference is given, takes the first atom of A as a reference if refIndex == -1: layerIndices = [struct.indices_from_symbol(C)[0]] else: layerIndices = [refIndex] mini = MinimumDistanceNN(tol=0.5) # algorithm : 2 buffer list (prev and new atomList) and a definitive list # adds all neighbor of the old buffer atoms to a new buffer list # if they are non-Na and non-already counted in the definitive List # Stops when the new buffer is empty (all non-Na atoms next to the layer # have been counted) prevAtomList = layerIndices finish = False while not finish: newAtomList = [] for prevAtomIndex in prevAtomList: neigList = mini.get_nn_info(struct, prevAtomIndex) for neighbor in neigList: index = neighbor['site_index'] name = neighbor['site'].species_string # print(name) if not (name in separator_specie + [struct[prevAtomIndex].species_string]) and not ( index in layerIndices): layerIndices.append(index) if len(newAtomList) > 0: previousAtomList = newAtomList layerIndices = layerIndices + newAtomList else: finish = True layerIndices.sort() return layerIndices
def metalBondCount(struc): # Counts the metal metal bounds in a structure # argument pymatgen.core.structure # return [ normalizedBonds, normalizedAA, normalizedBB] # normalizedBond = 3 elt list =[ nb AA bonds, nb BB bonds, nb AB bonds ] / nb of metal # normalizedAA = 7 element list : the ith elt is the number of A with i A-neighbor # (ie if there are 1/4 of the Mg surrounded by 3 Mg, normalizedAA[3] = 0.25) # normalizedBB = idem for B # Logically, if nbA = nbB, normalizedAA = normalizedBB A = "Mg" B = "Mn" countAA = 0 countAB = 0 countBB = 0 neighborAA = [0 for i in range(7)] neighborBB = [0 for i in range(7)] A_indices = struc.indices_from_symbol(A) B_indices = struc.indices_from_symbol(B) nbA = len(A_indices) nbB = len(B_indices) nbTot = nbA + nbB print("{0} {1}, {2} {3} : {4}".format(nbA, A, nbB, B, nbTot)) sCopy = RemoveSpeciesTransformation(["Na", "O"]).apply_transformation(struc) # struc.remove_species('O') mini = MinimumDistanceNN(tol=0.3) for i, site in enumerate(sCopy): # print(str(i)) neigList = mini.get_nn_info(sCopy, i) #print("{0} closest neighboors \n".format(len(neigList))) coord = 0 for neighbor in neigList: index = neighbor['site_index'] name = neighbor['site'].species_string # print(" ( {0} at {1} ) ".format(name,index)) if site.species_string == A: if name == A: countAA += 1 coord += 1 if name == B: countAB += 1 if site.species_string == B: if name == A: countAB += 1 if name == B: countBB += 1 coord += 1 if site.species_string == A: neighborAA[coord] += 1 elif site.species_string == B: neighborBB[coord] += 1 bonds = [countAA // 2, countBB // 2, countAB // 2] normalizedBonds = [i / nbTot for i in bonds] print("[{3}{3}, {4}{4}, {3}{4}] = {0} normalized by {1} : {2} \n".format( bonds, nbTot, normalizedBonds, A, B)) if nbA > 0: normalizedAA = [i / nbA for i in neighborAA] print( "[Nombre de {0} avec [1-6] {0} autour] = {1} normalized by {2} : {3} \n" .format(A, neighborAA, nbA, normalizedAA)) else: normalizedAA = neighborAA if nbB > 0: normalizedBB = [i / nbB for i in neighborBB] print( "[Nombre de {0} avec [1-6] {0} autour] = {1} normalized by {2} : {3} \n" .format(B, neighborBB, nbB, normalizedBB)) else: normalizedBB = neighborBB return [normalizedBonds, normalizedAA, normalizedBB]
def get_MMOO_quadruplets(struct): AB_list = get_Mn_Mn_pairs(struct) print("nb of pairs to test : {}".format(len(AB_list))) quadruplets = [] for A, B in AB_list: mini = MinimumDistanceNN(tol=0.35) O_A_indices = [O['site_index'] for O in mini.get_nn_info(struct, A)] O_pair = [ O['site_index'] for O in mini.get_nn_info(struct, B) if O["site_index"] in O_A_indices ] # O_pair = O_A_indices & O_B_indices nb_O = len(O_pair) if nb_O == 2: quadruplets.append({"metal_pair": [A, B], "oxygen_pair": O_pair}) elif nb_O > 2: O_pair_dict = [ O for O in mini.get_nn_info(struct, B) if O['site_index'] in O_pair ] print("common O between atoms {} are not a pair : {}".format( [A, B], O_pair)) for O in O_pair_dict: dA, imgA = O["site"].distance_and_image(struct[B], jimage=None) dB, imgB = O["site"].distance_and_image(struct[A], jimage=None) # print(imgA,imgB) O["hash"] = hash((tuple(imgA), tuple(imgB))) #print("O site : {}, dist : {}".format(O["site_index"],dA+dB)) O_pair = [ O["site_index"] for O in sorted(O_pair, key=itemgetter('hash')) ] print("sorted O list : {}".format( [dictA["site_index"] for dictA in O_pair])) while len(O_pair) > 0: O1 = O_pair.pop() O2 = O_pair.pop() quadruplets.append({ "metal_pair": [A, B], "oxygen_pair": [O1, O2] }) else: print("Not enough O in the pair !!") print("Valid MMOO quadruplets : {}".format(len(quadruplets))) return (quadruplets)
def get_OO_pairs(struct): AB_list = get_Mn_Mn_pairs(struct) print("nb of pairs to test : {}".format(len(AB_list))) O_found = set() OO_pairs = set() for A, B in AB_list: #print("A : {} , B : {}".format(A,B)) # getting the common O in the neighboorhods of the two metals mini = MinimumDistanceNN(tol=0.35) O_A_indices = set( [O['site_index'] for O in mini.get_nn_info(struct, A)]) #print("found O around A : {}".format( O_A_indices) ) O_B_indices = set( [O['site_index'] for O in mini.get_nn_info(struct, B)]) #print("found O around B : {}".format( O_B_indices) ) O_pair = O_A_indices & O_B_indices #print("found O around A still untreated : {}".format(O_A_indices) ) nb_O = len(O_pair) if nb_O > 2: O_pair -= O_found O_pair_dict = [ O for O in mini.get_nn_info(struct, B) if O['site_index'] in O_pair ] # print("found O pair : {}".format([ (dictA["image"],dictA["site_index"]) for dictA in O_pair])) # O_pair = [ O for O in O_pair if O["site_index"] not in O_found] print("common O between atoms {} are not a pair : {}".format( [A, B], O_pair)) #print("B site {} and image : {} ".format(struct[B],np.array(site_B["image"]) ) ) for O in O_pair_dict: #jimg = np.array([site_B["image"][i] for i in [0,1] ]+[0] ) dA, imgA = O["site"].distance_and_image(struct[B], jimage=None) dB, imgB = O["site"].distance_and_image(struct[A], jimage=None) # print(imgA,imgB) O["hash"] = hash((tuple(imgA), tuple(imgB))) #print("O site : {}, dist : {}".format(O["site_index"],dA+dB)) O_pair = [ O["site_index"] for O in sorted(O_pair, key=itemgetter('hash')) ] print("sorted O list : {}".format( [dictA["site_index"] for dictA in O_pair])) elif nb_O < 2: print("Not enough O in the pair !!") continue while len(O_pair) > 0: O1 = O_pair.pop() O2 = O_pair.pop() O_found.add(O1) O_found.add(O2) OO_pairs.add((O1, O2)) print("Valid OO pairs : {}".format(len(OO_pairs))) return (list(OO_pairs))