msspec_python3/msspec/es/es_mod/es_tools.py

279 lines
10 KiB
Python
Raw Normal View History

2019-11-14 15:16:51 +01:00
# coding: utf-8
from ase import Atoms
from ase.visualize import view
import numpy as np
import math
# List of tools :
"""
=================Vector tools==================
vector_def(A,B) : returns simply the vector translating A to B
vector_norm(V) : return euclidian norm of a vector
vector_trslt(P,V) : return image of translation of P from vector V
throw_away (P,O,d) : returns P' so as O,P and P' are aligned, and OP'=d. So it translate P from O with distance d to direction OP
angle_vector(u,v) : returns the value of the convex angle defined by vectors u and v, in radians.
ColinearTest(u,v) : returns 1 if u and v colinear, and 0 if not.
===========Distance and Proximity tools========
distance(a,b) : calculate distance between 2 points
search_nearest(point,set,d) : search the point in set wich is the nearest from point. We must know that the min distance is d
point_set_proximity(point, set) : returns the min distance between the point and the set of points
set_set_proximity(S1,S2) : returns minimal distance between each points of each sets.
longest_dist(set) : returns the longest distance between the points in the set
shortest_dist(set) : returns the shortest distance between the points in the set
dist_point_plan(Pt,Plan) : From Pt=[x,y,z] and Plan=[a,b,c,d], return distance beetween Pt and Plan
===============Construction tools===============
Isobarycenter(set) : Calculate isobarycenter of a set of points. Returns his coordinates
Invert_Coord(set,O,r) : Apply circular inversion to every point in the set, excepted for origin, remaining origin.
Midpoint(P1,P2) : Computes the middle point of P1 and P2
rot3D(P,A,u) : Returns P' image of P by rotation from angle A around unity vector u
===================Data tools===================
commonlist(L1,L2) : Returns a list of elements common to L1 and L2, ie output is L1 intercection with L2
cleanlist(list) : Returns a list without repeated elements (each element in cleaned list appears only once)
"""
# ========================Vector Tools=============================
def vector_def(A, B):
# returns simply the vector translating A to B
l = len(A)
if l != len(B):
print("Major Error : The 2 given points aren't same dimensioned :\nA = {}\nB={}".format(A, B))
V = []
for i in range(0, l):
V.append(B[i] - A[i])
return V
# ==========================================
def vector_norm(V):
# return euclidian norm of a vector
l = (len(V))
Origin = np.ndarray.tolist(np.zeros(l))
return distance(V, Origin)
# ==========================================
def vector_trslt(P, V):
x, y, z = P
a, b, c = V
return [x + a, y + b, z + c]
# ==========================================
def throw_away(P, O, d):
# returns P' so as O,P and P' are aligned, and OP'=d. So it translate P from O with distance d to direction OP
OP = tool.vector_def(O, P)
OP = np.ndarray.tolist(np.multiply(OP, 1. / tool.vector_norm(OP)))
output = np.ndarray.tolist(np.multiply(OP, d))
return output
# ==========================================
def angle_vector(u, v):
# returns the value in radian of the convex angle defined by vectors u and v.
U = vector_norm(u)
V = vector_norm(v)
UV = np.dot(u, v)
# print("U : {}\nV : {}\n u.v : {}".format(U,U,UV,))
if UV == 0:
# print("u.v = 0, on a donc un angle de {}, soit {}°".format(math.pi/2,math.pi/2*180/math.pi))
return math.pi / 2
else:
# print("L'angle est donc donc arccos({}) = {} = {}°".format(UV / (U * V),np.arccos(UV/(U*V)),np.arccos(UV/(U*V))*180/math.pi))
return np.arccos(UV / (U * V))
# ==========================================
def ColinearTest(u, v):
# Tests if u and v colinear
L = len(u)
k = 999999999999 # initial value, to be sure first ktest will become k
if L != len(v):
print(
"Error : u and v ant same dimension : \nu={}\nv={}\nSo we return u and v not aligned... but verify consequences".format(
u, v))
else:
for i in range(0, L):
if u[i] == 0 or v[i] == 0:
if u[i] != 0 or v[i] != 0:
return 1
else:
ktest = u[i] / v[i]
if k == 999999999999:
k = ktest
elif np.abs(k - ktest) < 0.0000001: # We accept almost colinearité at 1/10^6
return 1
return 0
# ==========================================
# ==========================================
# ==========================================
# ==============Distance and Proximity Tools=======================
def distance(a, b):
# Calculate distance between 2 points
d = 0.0
dim = len(a)
for i in range(0, dim):
d += (b[i] - a[i]) ** 2
d = np.sqrt(d)
return d
# ==========================================
def search_nearest(point, set, d):
# search the point in set wich is the nearest from point. We must know that the min distance is d
for p in set:
if distance(point, p) == d:
return p
# ==========================================
# ==========================================
def point_set_proximity(point, set):
# returns the min distance between the point and the set of points
d = distance(point, set[0])
for p in set[1:]:
d = min(d, distance(point, p))
return d
# ==========================================
def set_set_proximity(S1, S2):
# returns minimal distance between each points of each sets.
d = point_set_proximity(S1[0], S2)
for s in S1[1:]:
d = min(d, point_set_proximity(s, S2))
return d
# ==========================================
def longest_dist(set):
# returns the longest distance between the points in the set
L = len(set)
if L < 2:
print("Major ERROR : the set has become a 1-UPLET")
quit()
else:
d = distance(set[L - 2], set[L - 1]) # The last ones
for i in range(0, L - 2):
for j in range(i + 1, L - 2):
d = max(d, distance(set[i], set[j]))
return d
# ==========================================
def shortest_dist(set):
# returns the shortest distance between the points in the set
L = len(set)
if L < 2:
print("Major ERROR : the set has become a 1-UPLET")
quit()
else:
d = distance(set[L - 2], set[L - 1]) # The last ones
for i in range(0, L - 2):
for j in range(i + 1, L - 2):
d = min(d, distance(set[i], set[j]))
return d
# ==========================================
def dist_point_plan(Pt, Plan):
# From Pt=[x,y,z] and Plan=[a,b,c,d] corresponding to plan's equation ax + by + cz + d = 0, give the distance beetween Pt and the Plan
x, y, z = Pt
a, b, c, d = Plan
dist = np.abs(a * x + b * y + c * z + d) / np.sqrt(a ** 2 + b ** 2 + c ** 2)
return dist
# ======================Construction tools=========================
def Isobarycenter(set):
# Calculate isobarycenter of a set of points. Returns his coordinates
x = y = z = 0.0
l = len(set)
for point in set:
x += point[0] / l
y += point[1] / l
z += point[2] / l
# print("New Centroid of cluter:",[x,y,z])
return [x, y, z]
# ==========================================
def Invert_Coord(set, O, r):
# Apply circular inversion to every point in the set, excepted for origin, remaining origin.
output = []
for point in set:
if point == O:
output.append(point)
else:
D = distance(O, point)
OP = vector_def(O, point)
OP = np.multiply(OP, 1. / D) # set OP to unity vector
add = np.ndarray.tolist(np.array(O) + np.multiply(OP, r ** 2 / D))
output.append(add)
return output
# ==========================================
def Midpoint(P1, P2):
# From points coordinates P1 and P2 : construct the middle point of [P1,P2]
output = np.ndarray.tolist(np.multiply((np.array(P1) + np.array(P2)), 0.5))
return output
# ==========================================
def rot3D(P, A, u):
# Verify first if u is unity vector :
if vector_norm(u) != 1:
u = np.ndarray.tolist(np.multiply(u, 1. / vector_norm(u)))
# From P in R3, A in R and u in R3, returns the image from P's rotation around u from angle A
x, y, z = P
ux, uy, uz = u
c = np.cos(A)
s = np.sin(A)
# We compute directly the result : see the 3D rotation matrix
X = x * (ux ** 2 * (1 - c) + c) + y * (ux * uy * (1 - c) - uz * s) + z * (ux * uz * (1 - c) + uy * s)
Y = x * (ux * uy * (1 - c) + uz * s) + y * (uy ** 2 * (1 - c) + c) + z * (uy * uz * (1 - c) - ux * s)
Z = x * (ux * uz * (1 - c) - uy * s) + y * (uy * uz * (1 - c) + ux * s) + z * (uz ** 2 * (1 - c) + c)
return [X, Y, Z]
# =========================Data Tools==============================
def commonlist(L1, L2):
# Returns a list of elements common to L1 and L2, ie output is L1 intercection with L2
output = []
for i in L1:
if i in L2:
output.append(i)
return output
# ==========================================
def cleanlist(list):
# Returns a list without repeated elements (each element in cleaned list appears only once)
ls = len(list)
Index = range(ls)
Output = []
for iS in range(ls):
if iS in Index:
for iOS in range(iS + 1, ls):
S = list[iS]
OS = list[iOS]
if S == OS:
Index.remove(iOS) # S and OS are same coord or almost : we remove the last : OS
# else : iS correspond to coord needed to be deleted, so we don't add it
for I in Index:
Output.append(list[I])
return Output
# ==========================================