mdkits 0.1a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mdkits might be problematic. Click here for more details.
- mdkits/__init__.py +0 -0
- mdkits/cli/,hb_distribution.py +126 -0
- mdkits/cli/,hb_distribution_down.py +114 -0
- mdkits/cli/adsorbate.py +84 -0
- mdkits/cli/build_bulk.py +55 -0
- mdkits/cli/build_interface.py +86 -0
- mdkits/cli/build_surface.py +134 -0
- mdkits/cli/cmdline.py +41 -0
- mdkits/cli/convert.py +63 -0
- mdkits/cli/cp2k_input.py +479 -0
- mdkits/cli/cube.py +59 -0
- mdkits/cli/cut_surface.py +38 -0
- mdkits/cli/data.py +80 -0
- mdkits/cli/density.py +89 -0
- mdkits/cli/density2.py +91 -0
- mdkits/cli/extract.py +80 -0
- mdkits/cli/hartree_potential.py +59 -0
- mdkits/cli/hartree_potential_ave.py +84 -0
- mdkits/cli/hb.py +101 -0
- mdkits/cli/log.py +64 -0
- mdkits/cli/matplot.py +60 -0
- mdkits/cli/packmol_input.py +76 -0
- mdkits/cli/pdos.py +36 -0
- mdkits/cli/plot.py +289 -0
- mdkits/cli/supercell.py +72 -0
- mdkits/cli/wrap.py +36 -0
- mdkits/config/__init__.py +35 -0
- mdkits/config/settings.yml +4 -0
- mdkits/mdtool.py +28 -0
- mdkits/util/__init__.py +0 -0
- mdkits/util/arg_type.py +41 -0
- mdkits/util/cp2k_input_parsing.py +46 -0
- mdkits/util/encapsulated_ase.py +134 -0
- mdkits/util/encapsulated_mda.py +59 -0
- mdkits/util/fig_operation.py +28 -0
- mdkits/util/numpy_geo.py +118 -0
- mdkits/util/os_operation.py +35 -0
- mdkits/util/structure_parsing.py +147 -0
- mdkits-0.1a1.dist-info/LICENSE +21 -0
- mdkits-0.1a1.dist-info/METADATA +161 -0
- mdkits-0.1a1.dist-info/RECORD +43 -0
- mdkits-0.1a1.dist-info/WHEEL +4 -0
- mdkits-0.1a1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
filename: cp2k_input_parsing.py
|
|
3
|
+
function: prase cp2k file
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_cell(cp2k_input_file):
|
|
11
|
+
"""
|
|
12
|
+
function: parse cell information from cp2k input file
|
|
13
|
+
parameter:
|
|
14
|
+
cp2k_input_file: filename of cp2k input
|
|
15
|
+
return:
|
|
16
|
+
cell: list with 6 number
|
|
17
|
+
"""
|
|
18
|
+
try:
|
|
19
|
+
with open(cp2k_input_file, 'r') as f:
|
|
20
|
+
cell = []
|
|
21
|
+
for line in f:
|
|
22
|
+
if "ABC" in line:
|
|
23
|
+
xyz = line.split()[-3:]
|
|
24
|
+
cell.extend(xyz)
|
|
25
|
+
if "ALPHA_BETA_GAMMA" in line:
|
|
26
|
+
abc = line.split()[-3:]
|
|
27
|
+
cell.extend(abc)
|
|
28
|
+
if len(cell) == 3:
|
|
29
|
+
cell.extend([90.0, 90.0, 90.0])
|
|
30
|
+
|
|
31
|
+
print(f"system cell: x = {cell[0]}, y = {cell[1]}, z = {cell[2]}, a = {cell[3]}\u00B0, b = {cell[4]}\u00B0, c = {cell[5]}\u00B0")
|
|
32
|
+
return cell
|
|
33
|
+
except FileNotFoundError:
|
|
34
|
+
print(f'cp2k input file name "{cp2k_input_file}" is not found, assign a cp2k input file or assign a "cell"')
|
|
35
|
+
sys.exit(1)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#def get_cell(cp2k_input_file, cell=None):
|
|
39
|
+
# if cell is None:
|
|
40
|
+
# cell = parse_cell(cp2k_input_file)
|
|
41
|
+
# else:
|
|
42
|
+
# cell = cell
|
|
43
|
+
# if len(cell) == 3:
|
|
44
|
+
# cell.extend([90.0, 90.0, 90.0])
|
|
45
|
+
#
|
|
46
|
+
# return cell
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""
|
|
2
|
+
filename: encapsulated_ase.py
|
|
3
|
+
function: some encapsulated ase method
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from ase.io import iread, read
|
|
8
|
+
import io
|
|
9
|
+
import numpy as np
|
|
10
|
+
from ase.io.cube import read_cube_data
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def wrap_to_cell(chunk, cell, name, big=False):
|
|
14
|
+
"""
|
|
15
|
+
function: encapsulated ase.Atom.wrap method
|
|
16
|
+
parameter:
|
|
17
|
+
chunk: a list of frame of structure
|
|
18
|
+
cell: a list of cell parameter
|
|
19
|
+
name: path of temp file to write
|
|
20
|
+
big: make 3X3X1 supercell
|
|
21
|
+
return:
|
|
22
|
+
write into a temp file
|
|
23
|
+
"""
|
|
24
|
+
# wrap a chunk of .xyz sturcture in a cell, and write wraped structure to file
|
|
25
|
+
if len(chunk) > 1:
|
|
26
|
+
atoms = iread(io.StringIO('\n'.join(chunk)), format='xyz')
|
|
27
|
+
else:
|
|
28
|
+
atoms = iread(chunk, format='xyz')
|
|
29
|
+
with open(name, 'w') as f:
|
|
30
|
+
f.write('')
|
|
31
|
+
for atom in atoms:
|
|
32
|
+
atom.set_cell(cell)
|
|
33
|
+
atom.set_pbc(True)
|
|
34
|
+
atom.wrap()
|
|
35
|
+
if big:
|
|
36
|
+
from ase.build import make_supercell
|
|
37
|
+
P = [ [3, 0, 0], [0, 3, 0], [0, 0, 1] ]
|
|
38
|
+
atom = make_supercell(atom, P)
|
|
39
|
+
atom.write(f'{name}', append='a', format='xyz')
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def rdf(chunk, cell, bin_size, name, parallel=True):
|
|
43
|
+
"""
|
|
44
|
+
not used
|
|
45
|
+
"""
|
|
46
|
+
from ase.geometry.analysis import Analysis
|
|
47
|
+
from math import ceil
|
|
48
|
+
n = ceil(cell[2] / bin_size)
|
|
49
|
+
if parallel:
|
|
50
|
+
atoms = iread(io.StringIO('\n'.join(chunk)), format='xyz')
|
|
51
|
+
else:
|
|
52
|
+
atoms = iread(chunk, format='xyz')
|
|
53
|
+
atom_list = []
|
|
54
|
+
for atom in atoms:
|
|
55
|
+
atom.set_cell(cell)
|
|
56
|
+
atom.set_pbc(True)
|
|
57
|
+
atom_list.append(atom)
|
|
58
|
+
print(len(atom_list))
|
|
59
|
+
ana = Analysis(atom_list)
|
|
60
|
+
rdf = ana.get_rdf(3.5, n, elements=['O'])
|
|
61
|
+
rdf_array = np.vstack(rdf)
|
|
62
|
+
rdf_array = np.mean(rdf_array, axis=0)
|
|
63
|
+
print(name)
|
|
64
|
+
np.save(name, rdf_array)
|
|
65
|
+
ana.clear_cache()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def ave_potential(filepath):
|
|
69
|
+
"""
|
|
70
|
+
function: average hartree file in z_coordinate
|
|
71
|
+
parameter:
|
|
72
|
+
filepath: hartree cube file path
|
|
73
|
+
return:
|
|
74
|
+
z_potential: a list of potential alone z axes
|
|
75
|
+
z_coordinates: a list of coordinates of z axes
|
|
76
|
+
"""
|
|
77
|
+
# read data from filepath
|
|
78
|
+
data, atoms = read_cube_data(filepath)
|
|
79
|
+
# define need parameter
|
|
80
|
+
npoints = data.shape[2]
|
|
81
|
+
step_size = atoms.cell[2, 2] / ( npoints - 1 )
|
|
82
|
+
# average hartree file, and calculate z_coordinates
|
|
83
|
+
z_coordinates = [i * step_size for i in range(npoints)]
|
|
84
|
+
z_potential = 27.2114 * data[:, :, :].sum(axis=(0, 1)) / ( data.shape[0] * data.shape[1] )
|
|
85
|
+
return z_potential, z_coordinates
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def atoms_read_with_cell(file_name, cell=None, coord_mode=False, default_cell=np.array([0., 0., 0., 90., 90., 90.])):
|
|
89
|
+
"""
|
|
90
|
+
function: read structure file return a Atoms object with cell
|
|
91
|
+
parameter:
|
|
92
|
+
file_name: structure file name
|
|
93
|
+
cell: cell list
|
|
94
|
+
coord_mode: if file name is coord format
|
|
95
|
+
default_cell: default cell of Atoms object
|
|
96
|
+
return:
|
|
97
|
+
atoms: Atoms object with cell
|
|
98
|
+
"""
|
|
99
|
+
import sys, os
|
|
100
|
+
from . import cp2k_input_parsing, structure_parsing
|
|
101
|
+
|
|
102
|
+
if coord_mode:
|
|
103
|
+
xyz = structure_parsing.coord_to_xyz(file_name)
|
|
104
|
+
atoms = read(io.StringIO('\n'.join(xyz)), format='xyz')
|
|
105
|
+
else:
|
|
106
|
+
atoms = jread(file_name)
|
|
107
|
+
|
|
108
|
+
if cell == None:
|
|
109
|
+
cp2k_cell_file_name = ( 'cell.inc', 'setup.inp', 'input.inp' )
|
|
110
|
+
existing_cell_file = [ file for file in cp2k_cell_file_name if os.path.isfile(file) ]
|
|
111
|
+
if existing_cell_file:
|
|
112
|
+
cell = cp2k_input_parsing.parse_cell(existing_cell_file[0])
|
|
113
|
+
|
|
114
|
+
if np.array_equal(atoms.cell.cellpar(), default_cell):
|
|
115
|
+
if cell != None:
|
|
116
|
+
atoms.set_cell(cell)
|
|
117
|
+
print('cell: \n' + ', '.join(map(str, atoms.cell.cellpar())))
|
|
118
|
+
return atoms
|
|
119
|
+
else:
|
|
120
|
+
print("no cell")
|
|
121
|
+
sys.exit(1)
|
|
122
|
+
print('cell: \n' + ', '.join(map(str, atoms.cell.cellpar())))
|
|
123
|
+
return atoms
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def jread(filepath):
|
|
127
|
+
from ase.io import read
|
|
128
|
+
suffix = filepath.split('.')[-1]
|
|
129
|
+
if suffix == 'data':
|
|
130
|
+
atom = read(filepath, format='lammps-data', atom_style='atomic')
|
|
131
|
+
else:
|
|
132
|
+
atom = read(filepath)
|
|
133
|
+
|
|
134
|
+
return atom
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import MDAnalysis
|
|
2
|
+
import numpy as np
|
|
3
|
+
from . import numpy_geo
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def update_water(self, o_group, h_group, distance_judg=1.2, angle_judg:tuple[float, float]=None, return_index=False):
|
|
7
|
+
"""
|
|
8
|
+
input: o and h atom
|
|
9
|
+
output: o and two h in this frame
|
|
10
|
+
"""
|
|
11
|
+
oh_pair = MDAnalysis.lib.distances.capped_distance(o_group.positions, h_group.positions, min_cutoff=0, max_cutoff=distance_judg, box=self.u.dimensions, return_distances=False)
|
|
12
|
+
|
|
13
|
+
oh_o = oh_pair[:, 0]
|
|
14
|
+
unique_oh_o = np.unique(oh_o)
|
|
15
|
+
|
|
16
|
+
group_oh_h = {}
|
|
17
|
+
for oh_o_index in unique_oh_o:
|
|
18
|
+
oh_h_index = oh_pair[oh_o == oh_o_index, 1]
|
|
19
|
+
group_oh_h[oh_o_index] = oh_h_index
|
|
20
|
+
|
|
21
|
+
oh1_list = []
|
|
22
|
+
oh2_list = []
|
|
23
|
+
o_list = []
|
|
24
|
+
for oh_o_index in unique_oh_o:
|
|
25
|
+
oh_h_index = group_oh_h[oh_o_index]
|
|
26
|
+
if angle_judg is not None and len(oh_h_index) >= 2:
|
|
27
|
+
for i in range(len(oh_h_index)):
|
|
28
|
+
for j in range(i + 1, len(oh_h_index)):
|
|
29
|
+
h1_index = oh_h_index[i]
|
|
30
|
+
h2_index = oh_h_index[j]
|
|
31
|
+
|
|
32
|
+
o_pos = o_group[oh_o_index].position
|
|
33
|
+
h1_pos = h_group[h1_index].position
|
|
34
|
+
h2_pos = h_group[h2_index].position
|
|
35
|
+
|
|
36
|
+
oh1_vec = h1_pos - o_pos
|
|
37
|
+
oh2_vec = h2_pos - o_pos
|
|
38
|
+
|
|
39
|
+
angle_deg = numpy_geo.vector_vector_angle(oh1_vec, oh2_vec)
|
|
40
|
+
|
|
41
|
+
if angle_judg[0] <= angle_deg <= angle_judg[1]:
|
|
42
|
+
o_list.append(oh_o_index)
|
|
43
|
+
oh1_list.append(h1_index)
|
|
44
|
+
oh2_list.append(h2_index)
|
|
45
|
+
elif len(oh_h_index) == 2:
|
|
46
|
+
o_list.append(oh_o_index)
|
|
47
|
+
oh1_list.append(oh_h_index[0])
|
|
48
|
+
oh2_list.append(oh_h_index[1])
|
|
49
|
+
oh1_index = np.array(oh1_list)
|
|
50
|
+
oh2_index = np.array(oh2_list)
|
|
51
|
+
o_index = np.array(o_list)
|
|
52
|
+
|
|
53
|
+
if return_index:
|
|
54
|
+
return o_index, oh1_index, oh2_index
|
|
55
|
+
else:
|
|
56
|
+
o = o_group[o_index]
|
|
57
|
+
oh1 = h_group[oh1_index]
|
|
58
|
+
oh2 = h_group[oh2_index]
|
|
59
|
+
return o, oh1, oh2
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def savefig(fig, name, fold=None):
|
|
6
|
+
current_path = os.getcwd()
|
|
7
|
+
if fold:
|
|
8
|
+
if not os.path.exists(fold):
|
|
9
|
+
os.mkdir(fold)
|
|
10
|
+
fig.savefig(f"{current_path}/{fold}/{name}.png", format='png')
|
|
11
|
+
vector_fig_dir = f'pdf'
|
|
12
|
+
if not os.path.exists(vector_fig_dir):
|
|
13
|
+
os.mkdir(vector_fig_dir)
|
|
14
|
+
vector_fig_dir = f'pdf/{fold}'
|
|
15
|
+
if not os.path.exists(vector_fig_dir):
|
|
16
|
+
os.mkdir(vector_fig_dir)
|
|
17
|
+
fig.savefig(f"{current_path}/{vector_fig_dir}/{name}.pdf", format='pdf', transparent=True)
|
|
18
|
+
else:
|
|
19
|
+
fig.savefig(f"{current_path}/{name}.png", format='png')
|
|
20
|
+
vector_fig_dir = f'pdf'
|
|
21
|
+
if not os.path.exists(vector_fig_dir):
|
|
22
|
+
os.mkdir(vector_fig_dir)
|
|
23
|
+
fig.savefig(f"{current_path}/{vector_fig_dir}/{name}.pdf", format='pdf', transparent=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def scaled_figsize(scale_w=1.0, scale_h=1.0):
|
|
27
|
+
default_size = plt.rcParams["figure.figsize"]
|
|
28
|
+
return [default_size[0]*scale_w, default_size[1]*scale_h]
|
mdkits/util/numpy_geo.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
filename: numpy_geo.py
|
|
3
|
+
function: some vector calculation with numpy
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from numpy import array, dot, abs, cross
|
|
8
|
+
from numpy.linalg import norm
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def point_plane_distance(plane):
|
|
14
|
+
# distance of point with a plane(a list with [normal_voctor, a_point_in_plane])
|
|
15
|
+
def point(point):
|
|
16
|
+
return abs(dot(plane[0], point - plane[1])) / norm(plane[0])
|
|
17
|
+
return point
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def point_point_distance(point1, point2):
|
|
21
|
+
# distance of point with a point
|
|
22
|
+
return norm(point1 - point2)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def point(frame):
|
|
26
|
+
# return a point of atom, from .xyz file
|
|
27
|
+
def point_index(index):
|
|
28
|
+
return array(frame[index].split()[1:]).astype(float)
|
|
29
|
+
return point_index
|
|
30
|
+
|
|
31
|
+
def plane(frame, index1, index2, index3):
|
|
32
|
+
# return a normal voctor of a plane with three point(index and group)
|
|
33
|
+
get_point = point(frame)
|
|
34
|
+
base1 = get_point(index1)
|
|
35
|
+
base2 = get_point(index2)
|
|
36
|
+
base3 = get_point(index3)
|
|
37
|
+
return [cross(base2 - base1, base3 - base1), base3]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def vector_between_two_vector(vector1, vector2):
|
|
41
|
+
vector1_unit = vector1 / np.linalg.norm(vector1)
|
|
42
|
+
vector2_unit = vector2 / np.linalg.norm(vector2)
|
|
43
|
+
vector = vector1_unit + vector2_unit
|
|
44
|
+
return vector
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def vector_vector_angle(vector, surface_vector):
|
|
48
|
+
cos = np.dot(vector, surface_vector) / (np.linalg.norm(vector) * np.linalg.norm(surface_vector))
|
|
49
|
+
vector_vector_angle = np.arccos(np.clip(cos, -1.0, 1.0))
|
|
50
|
+
vector_vector_angle = np.degrees(vector_vector_angle)
|
|
51
|
+
return vector_vector_angle
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def cell_to_wrap_coefficients(cell, z=False):
|
|
55
|
+
angle = np.radians(180-cell[-1])
|
|
56
|
+
dangle = [np.cos(angle), np.sin(angle)]
|
|
57
|
+
xyz = cell[0:3]
|
|
58
|
+
if z:
|
|
59
|
+
coefficients = np.array([
|
|
60
|
+
[(kx * xyz[0] + ky * dangle[0] * xyz[1]), (ky * dangle[1] * xyz[1]), kz * xyz[2]]
|
|
61
|
+
for kx in range(-1, 2)
|
|
62
|
+
for ky in range(-1, 2)
|
|
63
|
+
for kz in range(-1, 2)
|
|
64
|
+
])
|
|
65
|
+
else:
|
|
66
|
+
coefficients = np.array([
|
|
67
|
+
[(kx * xyz[0] + ky * dangle[0] * xyz[1]), (ky * dangle[1] * xyz[1]), 0]
|
|
68
|
+
for kx in range(-1, 2)
|
|
69
|
+
for ky in range(-1, 2)
|
|
70
|
+
])
|
|
71
|
+
|
|
72
|
+
return coefficients
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def unwrap(atom1, atom2, coefficients, max=0, total=False):
|
|
76
|
+
init_dist = point_point_distance(atom1, atom2)
|
|
77
|
+
if total:
|
|
78
|
+
atoms = atom2 + coefficients
|
|
79
|
+
distance = np.linalg.norm(atoms-atom1, axis=1)
|
|
80
|
+
|
|
81
|
+
return distance, atoms
|
|
82
|
+
else:
|
|
83
|
+
if init_dist > max:
|
|
84
|
+
min_dist = float('inf')
|
|
85
|
+
closest_point = None
|
|
86
|
+
atoms = atom2 + coefficients
|
|
87
|
+
distance = np.linalg.norm(atoms-atom1, axis=1)
|
|
88
|
+
min_index = np.argmin(distance)
|
|
89
|
+
min_dist = distance[min_index]
|
|
90
|
+
closest_point = atoms[min_index]
|
|
91
|
+
|
|
92
|
+
else:
|
|
93
|
+
closest_point = atom2
|
|
94
|
+
min_dist = init_dist
|
|
95
|
+
|
|
96
|
+
return min_dist, closest_point
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def find_surface(surface_group:np.ndarray, layer_tolerance=1, surface_tolerance=5):
|
|
100
|
+
sort_group = surface_group.sort()
|
|
101
|
+
layer_mean = []
|
|
102
|
+
current_layer = [sort_group[0]]
|
|
103
|
+
for i in range(1, len(sort_group)):
|
|
104
|
+
if abs(sort_group[i] - sort_group[i-1]) < layer_tolerance:
|
|
105
|
+
current_layer.append(sort_group[i])
|
|
106
|
+
else:
|
|
107
|
+
layer_mean.append(np.mean(current_layer))
|
|
108
|
+
current_layer = [sort_group[i]]
|
|
109
|
+
|
|
110
|
+
if len(current_layer) == 1:
|
|
111
|
+
return layer_mean[0]
|
|
112
|
+
|
|
113
|
+
diff = np.diff(layer_mean)
|
|
114
|
+
if np.any(diff > surface_tolerance):
|
|
115
|
+
index = np.argmax(diff > 5)
|
|
116
|
+
return (layer_mean[index], layer_mean[index + 1])
|
|
117
|
+
else:
|
|
118
|
+
return layer_mean[-1]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import os, shutil, atexit
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def make_temp_dir(temp_dir, delete=False):
|
|
5
|
+
if os.path.exists(temp_dir):
|
|
6
|
+
shutil.rmtree(temp_dir)
|
|
7
|
+
os.mkdir(temp_dir)
|
|
8
|
+
if delete:
|
|
9
|
+
atexit.register(remove_temp_dir, temp_dir)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def remove_temp_dir(temp_dir):
|
|
13
|
+
shutil.rmtree(temp_dir)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def default_file_name(match, last=False):
|
|
17
|
+
import glob
|
|
18
|
+
file_list = glob.glob(match)
|
|
19
|
+
if file_list:
|
|
20
|
+
if last:
|
|
21
|
+
default_file_name = sort_word_and_number(file_list)[-1]
|
|
22
|
+
else:
|
|
23
|
+
default_file_name = list(file_list)
|
|
24
|
+
else:
|
|
25
|
+
default_file_name = None
|
|
26
|
+
|
|
27
|
+
return default_file_name
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def sort_word_and_number(unsort_list):
|
|
31
|
+
import re
|
|
32
|
+
fns = lambda s: sum(((s,int(n))for s,n in re.findall('(\D+)(\d+)','a%s0'%s)),())
|
|
33
|
+
sorted_list = sorted(unsort_list, key=fns)
|
|
34
|
+
|
|
35
|
+
return sorted_list
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""
|
|
2
|
+
filename: structure_parsing.py
|
|
3
|
+
function: prase file with .xyz structue
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def xyz_to_chunks(filename, thread):
|
|
11
|
+
"""
|
|
12
|
+
function: split .xyz file to chunks to parallel analysis
|
|
13
|
+
"""
|
|
14
|
+
with open(filename, 'r') as f:
|
|
15
|
+
data = f.read()
|
|
16
|
+
|
|
17
|
+
#with open(filename, 'r') as f:
|
|
18
|
+
# atom_number = int(f.readline().split()[0]) + 2
|
|
19
|
+
|
|
20
|
+
atom_number = int(data[:data.index('\n') + 1]) + 2
|
|
21
|
+
line_data = data.split('\n')
|
|
22
|
+
chunk_size = (len(line_data) / atom_number) // thread
|
|
23
|
+
chunks = [line_data[i:i+int(chunk_size*atom_number)] for i in range(0, len(line_data), int(chunk_size*atom_number))]
|
|
24
|
+
return chunks
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def xyz_to_groups(filename, cut=0):
|
|
28
|
+
"""
|
|
29
|
+
function: split .xyz file to groups, every groups is one single frame
|
|
30
|
+
"""
|
|
31
|
+
with open(filename, 'r') as f:
|
|
32
|
+
data = f.read()
|
|
33
|
+
|
|
34
|
+
# read number of atoms
|
|
35
|
+
end_index = data.index('\n') + 1
|
|
36
|
+
natom = int(data[:end_index]) + 2
|
|
37
|
+
|
|
38
|
+
# seqrate file with natom +2
|
|
39
|
+
lines = data.split('\n')
|
|
40
|
+
groups = [lines[i+cut:i+natom] for i in range(0, len(lines), natom)][:-1]
|
|
41
|
+
return groups
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def xyz_to_specified_list(filename, atom_range, cut=0):
|
|
45
|
+
"""
|
|
46
|
+
function: split .xyz file to specified list, specified atoms position list
|
|
47
|
+
"""
|
|
48
|
+
with open(filename, 'r') as f:
|
|
49
|
+
data = f.read()
|
|
50
|
+
|
|
51
|
+
# read number of atoms
|
|
52
|
+
end_index = data.index('\n') + 1
|
|
53
|
+
natom = int(data[:end_index]) + 2
|
|
54
|
+
|
|
55
|
+
# seqrate file with natom +2
|
|
56
|
+
lines = data.split('\n')
|
|
57
|
+
if len(atom_range) > 1:
|
|
58
|
+
groups = [lines[i+atom_range[0]:i+atom_range[1]] for i in range(0, len(lines), natom)][:-1]
|
|
59
|
+
else:
|
|
60
|
+
groups = [lines[i+atom_range[0]] for i in range(0, len(lines), natom)][:-1]
|
|
61
|
+
return groups
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def xyz_to_specified_array(filename, atom_range, cut=0):
|
|
65
|
+
"""
|
|
66
|
+
function: split .xyz file to specified list, specified atoms position list
|
|
67
|
+
"""
|
|
68
|
+
with open(filename, 'r') as f:
|
|
69
|
+
data = f.read()
|
|
70
|
+
|
|
71
|
+
# read number of atoms
|
|
72
|
+
end_index = data.index('\n') + 1
|
|
73
|
+
natom = int(data[:end_index]) + 2
|
|
74
|
+
|
|
75
|
+
# seqrate file with natom +2
|
|
76
|
+
lines = data.split('\n')
|
|
77
|
+
if len(atom_range) > 1:
|
|
78
|
+
groups = [lines[i+atom_range[0]:i+atom_range[1]] for i in range(0, len(lines), natom)][:-1]
|
|
79
|
+
else:
|
|
80
|
+
groups = [lines[i+atom_range[0]] for i in range(0, len(lines), natom)][:-1]
|
|
81
|
+
groups = [groups[i][j].split()[1:] for i in range(len(groups)) for j in range(len(groups[i]))]
|
|
82
|
+
return np.array(groups, dtype=np.float64)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def xyz_to_npy(filename):
|
|
86
|
+
"""
|
|
87
|
+
function: parse .xyz file to numpy array with float dtype, and cut first column of atom type
|
|
88
|
+
"""
|
|
89
|
+
data = xyz_to_groups(filename, cut=2)
|
|
90
|
+
new_data = [[list(map(float, subsublist.split()[1:])) for subsublist in sublist] for sublist in data]
|
|
91
|
+
return np.array(new_data)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def chunk_to_groups(data):
|
|
95
|
+
"""
|
|
96
|
+
function: split chunk to single frames
|
|
97
|
+
"""
|
|
98
|
+
natom = int(data[0]) + 2
|
|
99
|
+
groups = [data[i:i+natom] for i in range(0, len(data), natom)][:-1]
|
|
100
|
+
return groups
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def groups_to_xyz(filename, groups, cut=None):
|
|
104
|
+
"""
|
|
105
|
+
function: write groups(some of frame) to .xyz file
|
|
106
|
+
"""
|
|
107
|
+
with open(filename, 'w') as f:
|
|
108
|
+
for group in groups:
|
|
109
|
+
for i in group[cut:]:
|
|
110
|
+
f.write(i + '\n')
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def group_to_xyz(filename, group, cut=None):
|
|
114
|
+
"""
|
|
115
|
+
function: write groups(some of frame) to .xyz file
|
|
116
|
+
"""
|
|
117
|
+
with open(filename, 'w') as f:
|
|
118
|
+
for i in group[cut:]:
|
|
119
|
+
f.write(i + '\n')
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def coord_to_xyz(filename):
|
|
123
|
+
with open(filename, 'r') as f:
|
|
124
|
+
data = f.read()
|
|
125
|
+
data = data.split('\n')
|
|
126
|
+
data.insert(0, '')
|
|
127
|
+
data.insert(0, str(len(data)-2))
|
|
128
|
+
return data
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def atom_mass_parse(group):
|
|
132
|
+
import periodictable
|
|
133
|
+
atom_mass_dict = {}
|
|
134
|
+
names = atom_name_parse()
|
|
135
|
+
for name in names:
|
|
136
|
+
if hasattr(periodictable, name):
|
|
137
|
+
atom = getattr(periodictable, name)
|
|
138
|
+
atom_mass_dict[name] = atom.mass
|
|
139
|
+
else:
|
|
140
|
+
print(f'dont have face named {name}, use mass is 0')
|
|
141
|
+
atom_mass_dict[name] = 0
|
|
142
|
+
return atom_mass_dict
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def atom_name_parse(group):
|
|
146
|
+
names = {row.split()[0] for row in group[2:]}
|
|
147
|
+
return names
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 jxxcr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|