mdkits 0.1.13__py3-none-any.whl → 1.2.3__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.
Files changed (48) hide show
  1. mdkits/build_cli/adsorbate.py +2 -1
  2. mdkits/build_cli/build_bulk.py +2 -1
  3. mdkits/build_cli/build_interface.py +5 -0
  4. mdkits/build_cli/build_solution.py +48 -4
  5. mdkits/build_cli/build_surface.py +2 -5
  6. mdkits/build_cli/cut_surface.py +1 -1
  7. mdkits/build_cli/supercell.py +1 -1
  8. mdkits/cli/convert.py +1 -1
  9. mdkits/cli/extract.py +29 -18
  10. mdkits/{cli → dft_cli/.back}/pdos.py +1 -0
  11. mdkits/dft_cli/check_neb.py +0 -0
  12. mdkits/{cli → dft_cli}/cube.py +3 -2
  13. mdkits/dft_cli/dft_cli.py +23 -0
  14. mdkits/dft_cli/fix.py +54 -0
  15. mdkits/dft_cli/pdos.py +119 -0
  16. mdkits/md_cli/angle.py +122 -0
  17. mdkits/{cli → md_cli}/density.py +24 -19
  18. mdkits/md_cli/dipole.py +124 -0
  19. mdkits/md_cli/hb_distribution.py +185 -0
  20. mdkits/md_cli/md_cli.py +32 -0
  21. mdkits/md_cli/monitor.py +104 -0
  22. mdkits/md_cli/msd.py +44 -0
  23. mdkits/md_cli/rdf.py +53 -0
  24. mdkits/md_cli/setting.py +14 -0
  25. mdkits/md_cli/vac.py +65 -0
  26. mdkits/{cli → md_cli}/wrap.py +4 -3
  27. mdkits/mdkits.py +5 -9
  28. mdkits/util/.fig_operation.py.swp +0 -0
  29. mdkits/util/arg_type.py +18 -8
  30. mdkits/util/cp2k_input_parsing.py +5 -1
  31. mdkits/util/encapsulated_ase.py +28 -7
  32. mdkits/util/encapsulated_mda.py +4 -1
  33. mdkits/util/numpy_geo.py +10 -5
  34. mdkits/util/os_operation.py +3 -1
  35. mdkits/util/out_err.py +18 -6
  36. mdkits-1.2.3.dist-info/METADATA +370 -0
  37. mdkits-1.2.3.dist-info/RECORD +51 -0
  38. mdkits/cli/,hb_distribution_down.py +0 -114
  39. mdkits/cli/hartree_potential.py +0 -59
  40. mdkits/cli/hartree_potential_ave.py +0 -84
  41. mdkits/cli/hb.py +0 -101
  42. mdkits/cli/hb_distribution.py +0 -126
  43. mdkits/cli/packmol_input.py +0 -76
  44. mdkits-0.1.13.dist-info/METADATA +0 -226
  45. mdkits-0.1.13.dist-info/RECORD +0 -43
  46. {mdkits-0.1.13.dist-info → mdkits-1.2.3.dist-info}/LICENSE +0 -0
  47. {mdkits-0.1.13.dist-info → mdkits-1.2.3.dist-info}/WHEEL +0 -0
  48. {mdkits-0.1.13.dist-info → mdkits-1.2.3.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
3
  import numpy as np
4
- import click
4
+ import click, math
5
5
  from MDAnalysis import Universe
6
6
  from MDAnalysis.analysis.base import AnalysisBase
7
7
  from mdkits.util import (
@@ -10,6 +10,7 @@ from mdkits.util import (
10
10
  encapsulated_mda,
11
11
  os_operation,
12
12
  )
13
+ from .setting import common_setting
13
14
  import warnings, sys
14
15
  warnings.filterwarnings("ignore")
15
16
 
@@ -75,30 +76,33 @@ class Density_distribution(AnalysisBase):
75
76
  self._append(o.positions[:, 2])
76
77
 
77
78
  else:
78
- group = self.atomgroup.select_atoms(f"{self.element}")
79
+ group = self.atomgroup.select_atoms(f"{self.element}", updating=True)
79
80
  self._append(group.positions[:, 2])
80
81
 
81
82
  if self.surface_group:
82
- lower_z, upper_z = numpy_geo.find_surface(self.surface_group.positions[:, 2], layer_tolerance=1, surface_tolerance=5)
83
- self.surface_pos[0] += lower_z
84
- self.surface_pos[1] += upper_z
83
+ surface = numpy_geo.find_surface(self.surface_group.positions[:, 2])
84
+ self.surface_pos[0] += surface[0]
85
+ self.surface_pos[1] += surface[1]
85
86
 
86
87
  self.frame_count += 1
87
88
 
88
89
  def _conclude(self):
89
90
  if self.frame_count > 0:
90
- V = self.u.dimensions[0] * self.u.dimensions[1] * self.bin_size
91
+ V = self.u.dimensions[0] * self.u.dimensions[1] * math.sin(math.radians(180 - self.u.dimensions[-1])) * self.bin_size
91
92
 
92
93
  if self.atomic_mass:
93
94
  density_distribution = (self.density_distribution * self.atomic_mass * 1.660539 / V) / self.frame_count
94
95
  else:
95
96
  density_distribution = (self.density_distribution * (10000/6.02) / V) / self.frame_count
96
97
 
97
- bins_z = np.arange(len(self.density_distribution)) * self.bin_size
98
+ bins_z = np.arange(len(self.density_distribution)) * self.bin_size + self.bin_size / 2
98
99
 
99
100
  if self.surface:
100
101
  lower_z = self.surface_pos[0] / self.frame_count
101
- upper_z = self.surface_pos[1] / self.frame_count
102
+ if self.surface_pos[1] == 0:
103
+ upper_z = np.inf
104
+ else:
105
+ upper_z = self.surface_pos[1] / self.frame_count
102
106
 
103
107
  mask = (bins_z >= lower_z) & (bins_z <= upper_z)
104
108
  filtered_bins_z = bins_z[mask] - lower_z
@@ -110,24 +114,25 @@ class Density_distribution(AnalysisBase):
110
114
 
111
115
  np.savetxt(self.o, conbined_data, header="Z\tdensity", fmt='%.5f', delimiter='\t')
112
116
 
113
- @click.command(name='density')
114
- @click.argument('filename', type=click.Path(exists=True), default=os_operation.default_file_name('*-pos-1.xyz', last=True))
115
- @click.option('--cell', type=arg_type.Cell, help='set cell from cp2k input file or a list of lattice: --cell x,y,z or x,y,z,a,b,c', default='input.inp', show_default=True)
116
- @click.option('--element', type=str, help='element to analysis')
117
+ @click.command(name='density', help="analysis density or concentration of element in a trajectory file")
118
+ @common_setting
119
+ @click.option('--group', type=str, help='group to analysis')
117
120
  @click.option('--atomic_mass', type=float, help='output density unit (g/cm3), should give atomic mass of element, else is concentration unit (mol/L)')
118
121
  @click.option('-o', type=str, help='output file name', default='density_{element}.dat', show_default=True)
119
- @click.option('--update_water', is_flag=True, help='update water with distance or angle judgment')
120
- @click.option('--distance', type=float, help='update water distance judgment', default=1.2, show_default=True)
121
- @click.option('--angle', type=(float, float), help='update water angle judgment')
122
- @click.option('--surface', type=str, help='surface element')
123
- def main(filename, cell, o, element, atomic_mass, update_water, distance, angle, surface):
122
+ def main(filename, cell, o, group, atomic_mass, update_water, distance, angle, surface, r):
124
123
  """
125
124
  analysis density or concentration of element in a trajectory file
126
125
  """
127
126
 
128
- density_dist = Density_distribution(filename, cell, o=o, distance_judg=distance, angle_judg=angle, element=element, atomic_mass=atomic_mass, update_water=update_water, surface=surface)
127
+ density_dist = Density_distribution(filename, cell, o=o, distance_judg=distance, angle_judg=angle, element=group, atomic_mass=atomic_mass, update_water=update_water, surface=surface)
129
128
 
130
- density_dist.run()
129
+ if r is not None:
130
+ if len(r) == 2:
131
+ density_dist.run(start=r[0], stop=r[1])
132
+ elif len(r) == 3:
133
+ density_dist.run(start=r[0], stop=r[1], step=r[2])
134
+ else:
135
+ density_dist.run()
131
136
 
132
137
 
133
138
  if __name__ == '__main__':
@@ -0,0 +1,124 @@
1
+ import numpy as np
2
+ import click
3
+ import MDAnalysis
4
+ from MDAnalysis import Universe
5
+ from MDAnalysis.analysis.base import AnalysisBase
6
+ from mdkits.util import (
7
+ arg_type,
8
+ numpy_geo,
9
+ encapsulated_mda,
10
+ os_operation
11
+ )
12
+ from .setting import common_setting
13
+ import sys
14
+
15
+
16
+ class Dipole_distribution(AnalysisBase):
17
+ def __init__(self, filename, cell, update_water, distance_judg, angle_judg, surface, dt=0.001, bin_size=0.2):
18
+ u = Universe(filename)
19
+ u.trajectory.ts.dt = dt
20
+ u.dimensions = cell
21
+
22
+ self.u = u
23
+ self.atomgroup = u.select_atoms("all")
24
+ self.bin_size = bin_size
25
+ self.frame_count = 0
26
+ self.surface = surface
27
+ self.update_water = update_water
28
+ self.mid_z = u.dimensions[2] / 2
29
+
30
+ if self.update_water:
31
+ self.distance_judg = distance_judg
32
+ self.angle_judg = angle_judg
33
+
34
+ if surface is not None:
35
+ self.surface_group = self.atomgroup.select_atoms(f"{surface}")
36
+ if self.surface_group.n_atoms == 0:
37
+ sys.exit("Please specify the correct surface group")
38
+ else:
39
+ self.surface_group = False
40
+
41
+ super(Dipole_distribution, self).__init__(self.atomgroup.universe.trajectory, verbose=True)
42
+
43
+ def _prepare(self):
44
+ self.bin_num = int(self.u.dimensions[2] / self.bin_size) + 2
45
+ self.dipole_distribution = np.zeros(self.bin_num, dtype=np.float64)
46
+ self.o_count = np.zeros(self.bin_num, dtype=np.float64)
47
+
48
+ if self.surface_group:
49
+ self.surface_pos = np.zeros(2)
50
+
51
+ def _append(self, angle, z):
52
+ bins = np.floor(z / self.bin_size).astype(int) + 1
53
+ np.add.at(self.dipole_distribution, bins, angle)
54
+ np.add.at(self.o_count, bins , 1)
55
+
56
+ def _single_frame(self):
57
+ o_group = self.atomgroup.select_atoms("name O")
58
+
59
+ if self.update_water:
60
+ h_group = self.atomgroup.select_atoms("name H")
61
+ o, oh1, oh2 = encapsulated_mda.update_water(self, o_group, h_group, distance_judg=self.distance_judg, angle_judg=self.angle_judg, return_index=False)
62
+ else:
63
+ o = o_group
64
+ oh1 = self.atomgroup[o.indices + 1]
65
+ oh2 = self.atomgroup[o.indices + 2]
66
+
67
+ if self.surface_group:
68
+ lower_z, upper_z = numpy_geo.find_surface(self.surface_group.positions[:, 2])
69
+ self.surface_pos[0] += lower_z
70
+ self.surface_pos[1] += upper_z
71
+
72
+ vec1 = MDAnalysis.lib.distances.minimize_vectors(oh1.positions - o.positions, self.u.dimensions)
73
+ vec2 = MDAnalysis.lib.distances.minimize_vectors(oh2.positions - o.positions, self.u.dimensions)
74
+
75
+ bisector = numpy_geo.vector_between_two_vector(vec1, vec2)
76
+
77
+
78
+ angle_bisector = np.hstack((bisector[o.positions[:, 2] < self.mid_z][:, 2] / np.linalg.norm(bisector[o.positions[:, 2] < self.mid_z], axis=1), -bisector[o.positions[:, 2] > self.mid_z][:, 2] / np.linalg.norm(bisector[o.positions[:, 2] > self.mid_z], axis=1)))
79
+
80
+ self._append(angle_bisector, np.hstack((o.positions[:, 2][o.positions[:, 2] < self.mid_z], o.positions[:, 2][o.positions[:, 2] > self.mid_z])))
81
+
82
+ self.frame_count += 1
83
+
84
+ def _conclude(self):
85
+ if self.frame_count > 0:
86
+ average_dipole = self.dipole_distribution / self.o_count
87
+ water_density = (self.o_count * (15.999+1.0008*2) * 1.660539 / (self.u.dimensions[0] * self.u.dimensions[1] * self.bin_size)) / self.frame_count
88
+ average_dipole = average_dipole * water_density
89
+ bins_z = np.arange(len(average_dipole)) * self.bin_size + self.bin_size / 2
90
+
91
+ if self.surface:
92
+ lower_z = self.surface_pos[0] / self.frame_count
93
+ if self.surface_pos[1] == 0:
94
+ upper_z = np.inf
95
+ else:
96
+ upper_z = self.surface_pos[1] / self.frame_count
97
+
98
+ mask = (bins_z >= lower_z) & (bins_z <= upper_z)
99
+ filtered_bins_z = bins_z[mask] - lower_z
100
+ filtered_dipole_distribution = average_dipole[mask]
101
+
102
+ conbined_data = np.column_stack((filtered_bins_z, filtered_dipole_distribution))
103
+ else:
104
+ conbined_data = np.column_stack((bins_z, average_dipole))
105
+
106
+ np.savetxt("dipole_distribution.dat", conbined_data, header="z\tDipole Z Positions\tWater Density", fmt='%.5f', delimiter='\t')
107
+
108
+
109
+ @click.command(name="dipole")
110
+ @common_setting
111
+ def main(filename, cell, update_water, distance, angle, surface, r):
112
+ """analysis dipole along z-axis"""
113
+ a = Dipole_distribution(filename, cell, update_water, distance_judg=distance, angle_judg=angle, surface=surface)
114
+ if r is not None:
115
+ if len(r) == 2:
116
+ a.run(start=r[0], stop=r[1])
117
+ elif len(r) == 3:
118
+ a.run(start=r[0], stop=r[1], step=r[2])
119
+ else:
120
+ a.run()
121
+
122
+
123
+ if __name__ == "__main__":
124
+ main()
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import numpy as np
4
+ import click
5
+ import MDAnalysis
6
+ from MDAnalysis import Universe
7
+ from MDAnalysis.analysis.base import AnalysisBase
8
+ from mdkits.util import numpy_geo, encapsulated_mda
9
+ import warnings, sys
10
+ from .setting import common_setting
11
+ warnings.filterwarnings("ignore")
12
+
13
+
14
+ class Hb_distribution(AnalysisBase):
15
+ def __init__(self, filename, cell, surface, update_water, distance_judg, angle_judg, hb_distance, hb_angle, bin_size=0.2, dt=0.001, index=None):
16
+ u = Universe(filename)
17
+ u.trajectory.ts.dt = dt
18
+ u.dimensions = cell
19
+ self.u = u
20
+ self.atomgroup = u.select_atoms("all")
21
+ self.hb_distance = hb_distance
22
+ self.hb_angle = hb_angle
23
+ self.bin_size = bin_size
24
+ self.surface = surface
25
+ self.update_water = update_water
26
+ self.frame_count = 0
27
+ np.set_printoptions(threshold=np.inf)
28
+
29
+ if surface is not None:
30
+ self.surface_group = self.atomgroup.select_atoms(f"{surface}")
31
+ if self.surface_group.n_atoms == 0:
32
+ sys.exit("Please specify the correct surface group")
33
+ else:
34
+ self.surface_group = False
35
+
36
+ if self.update_water:
37
+ self.distance_judg = distance_judg
38
+ self.angle_judg = angle_judg
39
+
40
+ if index is not None:
41
+ self.index = index
42
+ self.hb_d_index = 0
43
+ self.hb_a_index = 0
44
+ else:
45
+ self.index = None
46
+
47
+ super(Hb_distribution, self).__init__(self.atomgroup.universe.trajectory, verbose=True)
48
+
49
+ def _prepare(self):
50
+ bin_num = int(self.u.dimensions[2] / self.bin_size) + 2
51
+ self.accepter = np.zeros(bin_num, dtype=np.float64)
52
+ self.donor = np.zeros(bin_num, dtype=np.float64)
53
+ self.od = np.zeros(bin_num, dtype=np.float64)
54
+ if self.surface_group:
55
+ self.surface_pos = np.zeros(2)
56
+
57
+ def _append(self, hb_d, hb_a, o):
58
+ bins_d = np.floor(hb_d / self.bin_size).astype(int) + 1
59
+ bins_a = np.floor(hb_a / self.bin_size).astype(int) + 1
60
+ bins_o = np.floor(o / self.bin_size).astype(int) + 1
61
+
62
+ bins_d = bins_d[bins_d < len(self.donor)]
63
+ bins_a = bins_a[bins_a < len(self.accepter)]
64
+ bins_o = bins_o[bins_o < len(self.od)]
65
+
66
+ np.add.at(self.donor, bins_d, 1)
67
+ np.add.at(self.accepter, bins_a, 1)
68
+ np.add.at(self.od, bins_o, 1)
69
+
70
+ def _single_frame(self):
71
+ if self.update_water:
72
+ o = self.atomgroup.select_atoms("name O")
73
+ h = self.atomgroup.select_atoms("name H")
74
+
75
+ o_group, oh1, oh2 = encapsulated_mda.update_water(self, o, h, distance_judg=self.distance_judg, angle_judg=self.angle_judg, return_index=False)
76
+
77
+ o_pair = MDAnalysis.lib.distances.capped_distance(o_group.positions, o_group.positions, min_cutoff=0, max_cutoff=self.hb_distance, box=self.u.dimensions, return_distances=False)
78
+
79
+ o0 = o_group[o_pair[:, 0]]
80
+ o1 = o_group[o_pair[:, 1]]
81
+
82
+ o0h1 = oh1[o_pair[:, 0]]
83
+ o0h2 = oh2[o_pair[:, 0]]
84
+ o1h1 = oh1[o_pair[:, 1]]
85
+ o1h2 = oh2[o_pair[:, 1]]
86
+ else:
87
+ o_group = self.atomgroup.select_atoms("name O")
88
+ o_pair = MDAnalysis.lib.distances.capped_distance(o_group.positions, o_group.positions, min_cutoff=0, max_cutoff=self.hb_distance, box=self.u.dimensions, return_distances=False)
89
+
90
+ o0 = o_group[o_pair[:, 0]]
91
+ o1 = o_group[o_pair[:, 1]]
92
+
93
+ o0h1 = self.atomgroup[o0.indices + 1]
94
+ o0h2 = self.atomgroup[o0.indices + 2]
95
+ o1h1 = self.atomgroup[o1.indices + 1]
96
+ o1h2 = self.atomgroup[o1.indices + 2]
97
+
98
+ angle_o0h1_o0_o1 = np.degrees(
99
+ MDAnalysis.lib.distances.calc_angles(o0h1.positions, o0.positions, o1.positions, box=self.u.dimensions)
100
+ )
101
+ angle_o0h2_o0_o1 = np.degrees(
102
+ MDAnalysis.lib.distances.calc_angles(o0h2.positions, o0.positions, o1.positions, box=self.u.dimensions)
103
+ )
104
+ angle_o1h1_o1_o0 = np.degrees(
105
+ MDAnalysis.lib.distances.calc_angles(o1h1.positions, o1.positions, o0.positions, box=self.u.dimensions)
106
+ )
107
+ angle_o1h2_o1_o0 = np.degrees(
108
+ MDAnalysis.lib.distances.calc_angles(o1h2.positions, o1.positions, o0.positions, box=self.u.dimensions)
109
+ )
110
+
111
+ condition_d = (angle_o0h1_o0_o1 < self.hb_angle) | (angle_o0h2_o0_o1 < self.hb_angle)
112
+ condition_a = (angle_o1h1_o1_o0 < self.hb_angle) | (angle_o1h2_o1_o0 < self.hb_angle)
113
+
114
+ if self.index is not None:
115
+ self.hb_d_index += o0.positions[:, 2][condition_d & (o0.indices == self.index)].shape[0]
116
+ self.hb_a_index += o0.positions[:, 2][condition_a & (o0.indices == self.index)].shape[0]
117
+ else:
118
+ hb_d = o0.positions[:, 2][condition_d]
119
+ hb_a = o0.positions[:, 2][condition_a]
120
+
121
+ self._append(hb_d, hb_a, o_group.positions[:, 2])
122
+
123
+ if self.surface_group:
124
+ surface = numpy_geo.find_surface(self.surface_group.positions[:, 2])
125
+ self.surface_pos[0] += surface[0]
126
+ self.surface_pos[1] += surface[1]
127
+
128
+ self.frame_count += 1
129
+
130
+ def _conclude(self):
131
+ if self.frame_count > 0 and self.index is None:
132
+ average_od = self.od / self.frame_count
133
+ average_donor = np.nan_to_num((self.donor / self.frame_count) / average_od, nan=0)
134
+ average_accepter = np.nan_to_num((self.accepter / self.frame_count) / average_od, nan=0)
135
+ average_sum = average_donor + average_accepter
136
+
137
+ bins_z = np.arange(len(self.donor)) * self.bin_size + self.bin_size / 2
138
+
139
+ if self.surface:
140
+ lower_z = self.surface_pos[0] / self.frame_count
141
+ if self.surface_pos[1] == 0:
142
+ upper_z = np.inf
143
+ else:
144
+ upper_z = self.surface_pos[1] / self.frame_count
145
+
146
+ mask = (bins_z >= lower_z) & (bins_z <= upper_z)
147
+ filtered_bins_z = bins_z[mask] - lower_z
148
+ filtered_average_accepter = average_accepter[mask]
149
+ filtered_average_donor = average_donor[mask]
150
+ filtered_average_sum = average_sum[mask]
151
+
152
+ combined_data = np.column_stack((filtered_bins_z, filtered_average_accepter, filtered_average_donor, filtered_average_sum))
153
+ else:
154
+ combined_data = np.column_stack((bins_z, average_accepter, average_donor, average_sum))
155
+
156
+ np.savetxt("hb_distribution.dat", combined_data, header="Z\tAccepter\tDonor\tAccepter+Donor", fmt='%.5f', delimiter='\t')
157
+
158
+ if self.index is not None and self.frame_count > 0:
159
+ self.hb_d_index /= self.frame_count
160
+ self.hb_a_index /= self.frame_count
161
+ output = f"# {self.index}\naccepter : {self.hb_a_index}\ndonor : {self.hb_d_index}\ntotal : {self.hb_a_index + self.hb_d_index}"
162
+ with open(f"hb_{self.index}.dat", "a") as f:
163
+ f.write(output)
164
+ print(output)
165
+
166
+
167
+ @click.command(name="hb", help="analysis hydrogen bond distribution along z-axis")
168
+ @common_setting
169
+ @click.option('--hb_param', type=click.Tuple([float, float]), help='parameter for hydrogen bond', default=(3.5, 35), show_default=True)
170
+ @click.option('--index', type=int, help='index of an atom')
171
+ def main(filename, hb_param, cell, surface, r, update_water, distance, angle, index):
172
+ """analysis hydrogen bond distribution along z-axis"""
173
+ hb_dist = Hb_distribution(filename, cell, surface, update_water=update_water, distance_judg=distance, angle_judg=angle, hb_distance=hb_param[0], hb_angle=hb_param[1], index=index)
174
+
175
+ if r is not None:
176
+ if len(r) == 2:
177
+ hb_dist.run(start=r[0], stop=r[1])
178
+ elif len(r) == 3:
179
+ hb_dist.run(start=r[0], stop=r[1], step=r[2])
180
+ else:
181
+ hb_dist.run()
182
+
183
+
184
+ if __name__ == '__main__':
185
+ main()
@@ -0,0 +1,32 @@
1
+ import click
2
+ from mdkits.md_cli import (
3
+ wrap,
4
+ dipole,
5
+ angle,
6
+ density,
7
+ hb_distribution,
8
+ vac,
9
+ rdf,
10
+ msd,
11
+ monitor,
12
+ )
13
+
14
+
15
+ @click.group(name='md')
16
+ @click.pass_context
17
+ def cli(ctx):
18
+ """kits for MD analysis"""
19
+
20
+ cli.add_command(wrap.main)
21
+ cli.add_command(density.main)
22
+ cli.add_command(dipole.main)
23
+ cli.add_command(angle.main)
24
+ cli.add_command(hb_distribution.main)
25
+ cli.add_command(vac.main)
26
+ cli.add_command(rdf.main)
27
+ cli.add_command(msd.main)
28
+ cli.add_command(monitor.main)
29
+
30
+
31
+ if __name__ == '__main__':
32
+ cli()
@@ -0,0 +1,104 @@
1
+ import click
2
+ from .setting import common_setting
3
+ import MDAnalysis
4
+ from MDAnalysis import Universe
5
+ from MDAnalysis.analysis.base import AnalysisBase
6
+ from mdkits.util import arg_type, numpy_geo
7
+ import numpy as np
8
+ import sys
9
+
10
+
11
+ class Monitor(AnalysisBase):
12
+ def __init__(self, filename, cell, index, surface, dt=0.001):
13
+ u = Universe(filename)
14
+ u.trajectory.ts.dt = dt
15
+ u.dimensions = cell
16
+
17
+ self.u = u
18
+ self.atomgroup = self.u.select_atoms("all")
19
+ self.surface = surface
20
+
21
+ if index is None:
22
+ sys.exit("Please specify at least one atom to monitor")
23
+ else:
24
+ self.index = index
25
+ self.group = " or ".join([ f"index {i}" for i in self.index ])
26
+
27
+ if surface is not None:
28
+ self.surface_group = self.atomgroup.select_atoms(f"{surface}")
29
+ if self.surface_group.n_atoms == 0:
30
+ sys.exit("Please specify the correct surface group")
31
+ else:
32
+ self.surface_group = False
33
+
34
+ super(Monitor, self).__init__(self.atomgroup.universe.trajectory, verbose=True)
35
+
36
+ def _prepare(self):
37
+ self.height = []
38
+ if len(self.index) == 2:
39
+ self.distance = []
40
+ elif len(self.index) == 3:
41
+ self.distance = []
42
+ self.angle = []
43
+
44
+ def _single_frame(self):
45
+ if self.surface_group:
46
+ surface = numpy_geo.find_surface(self.surface_group.positions[:, 2])
47
+ else:
48
+ surface = [0]
49
+
50
+ self.height.append(self.atomgroup.select_atoms(self.group).positions[:, 2] - surface[0])
51
+
52
+ if len(self.index) == 2:
53
+ vec = MDAnalysis.lib.distances.minimize_vectors(self.atomgroup[self.index[0]].position - self.atomgroup[self.index[1]].position, self.u.dimensions)
54
+
55
+ self.distance.append(np.linalg.norm(vec))
56
+
57
+ if len(self.index) == 3:
58
+ vec1 = MDAnalysis.lib.distances.minimize_vectors(self.atomgroup[self.index[0]].position - self.atomgroup[self.index[1]].position, self.u.dimensions)
59
+ vec2 = MDAnalysis.lib.distances.minimize_vectors(self.atomgroup[self.index[2]].position - self.atomgroup[self.index[1]].position, self.u.dimensions)
60
+
61
+ self.distance.append(np.array([np.linalg.norm(vec1), np.linalg.norm(vec2)]))
62
+ self.angle.append(numpy_geo.vector_vector_angle(vec1, vec2))
63
+
64
+ def _conclude(self):
65
+ frame_count = np.arange(self.u.trajectory.n_frames).reshape(-1, 1)
66
+
67
+ self.height = np.vstack(self.height)
68
+
69
+ np.savetxt("monitor.dat", np.hstack((frame_count, self.height)), fmt="%.5f", header=f"frame\t{' '.join(self.atomgroup.select_atoms(self.group).names)}")
70
+
71
+ if len(self.index) == 2:
72
+ self.distance = np.vstack(self.distance)
73
+
74
+ np.savetxt("monitor.dat", np.hstack((frame_count, self.height, self.distance)), fmt="%.5f", header=f"frame\t\t{' '.join(self.atomgroup.select_atoms(self.group).names)}\t{self.atomgroup.names[self.index[0]]}-{self.atomgroup.names[self.index[1]]}")
75
+ elif len(self.index) == 3:
76
+ self.distance = np.vstack(self.distance)
77
+ self.angle = np.vstack(self.angle)
78
+
79
+ np.savetxt("monitor.dat", np.hstack((frame_count, self.height, self.distance, self.angle)), fmt="%.5f", header=f"frame\t\t{' '.join(self.atomgroup.select_atoms(self.group).names)}\t{self.atomgroup.names[self.index[0]]}-{self.atomgroup.names[self.index[1]]}\t{self.atomgroup.names[self.index[2]]}-{self.atomgroup.names[self.index[1]]}\t{self.atomgroup.names[self.index[0]]}-{self.atomgroup.names[self.index[1]]}-{self.atomgroup.names[self.index[2]]}")
80
+
81
+
82
+ @click.command(name="monitor")
83
+ @click.argument("filename", type=click.Path(exists=True))
84
+ @click.option("--index", "-i", type=int, help="index of atom to monitor", multiple=True)
85
+ @click.option('--cell', type=arg_type.Cell, help="set cell, a list of lattice, --cell x,y,z or x,y,z,a,b,c")
86
+ @click.option("--surface", type=str, help="surface group")
87
+ @click.option('-r', type=arg_type.FrameRange, help='range of frame to analysis')
88
+ def main(filename, cell, index, surface, r):
89
+ """
90
+ monitor the property of between atoms
91
+ """
92
+ a = Monitor(filename, cell, index, surface)
93
+ if r is not None:
94
+ if len(r) == 2:
95
+ a.run(start=r[0], stop=r[1])
96
+ elif len(r) == 3:
97
+ a.run(start=r[0], stop=r[1], step=r[2])
98
+ else:
99
+ a.run()
100
+
101
+
102
+
103
+ if __name__ == "__main__":
104
+ main()
mdkits/md_cli/msd.py ADDED
@@ -0,0 +1,44 @@
1
+ import click
2
+ import MDAnalysis as mda
3
+ import MDAnalysis.analysis.msd as msd
4
+ import numpy as np
5
+ from mdkits.util import arg_type
6
+
7
+
8
+ @click.command(name="msd")
9
+ @click.argument("filename", type=click.Path(exists=True))
10
+ @click.argument('type', type=click.Choice(['xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z']))
11
+ @click.argument("group", type=str)
12
+ @click.option('-r', type=arg_type.FrameRange, help='range of frame to analysis')
13
+ def main(filename, type, group, r):
14
+ """analysis msd along the given axis"""
15
+ u = mda.Universe(filename)
16
+ MSD = msd.EinsteinMSD(u, select=group, msd_type=type, fft=True)
17
+ if r is not None:
18
+ if len(r) == 2:
19
+ MSD.run(start=r[0], stop=r[1], verbose=True)
20
+ elif len(r) == 3:
21
+ MSD.run(start=r[0], stop=r[1], step=r[2], verbose=True)
22
+ else:
23
+ MSD.run(verbose=True)
24
+
25
+ data = np.arange(1, MSD.n_frames + 1).reshape(-1, 1)
26
+ s = "_"
27
+ name = f"{s.join(group.split(' '))}"
28
+ o = f"msd_{type}_{name}.dat"
29
+ header = ''
30
+ msd_cols = []
31
+ for i in range(MSD.n_particles):
32
+ msd_cols.append(MSD.results.msds_by_particle[:, i].reshape(-1, 1))
33
+ header += name + f"_{i}\t"
34
+ msd_array = np.concatenate(msd_cols, axis=1)
35
+ mean_col = np.mean(msd_array, axis=1, keepdims=True)
36
+ data = np.concatenate((data, mean_col, msd_array), axis=1)
37
+ header = "frame\tmean\t" + header
38
+
39
+ np.savetxt(o, data, fmt="%.5f", delimiter="\t", header=header)
40
+
41
+
42
+
43
+ if __name__ == '__main__':
44
+ main()
mdkits/md_cli/rdf.py ADDED
@@ -0,0 +1,53 @@
1
+ import MDAnalysis as mda
2
+ from MDAnalysis.analysis import rdf
3
+ import numpy as np
4
+ import click
5
+ from scipy import integrate
6
+ from mdkits.util import arg_type
7
+
8
+
9
+ def calculate_Gab(r_values, gab_values):
10
+ dr = r_values[1] - r_values[0]
11
+
12
+ integrand = 4 * np.pi * r_values**2 * gab_values
13
+
14
+ G_ab = np.cumsum(integrand) * dr
15
+
16
+ return G_ab
17
+
18
+
19
+ @click.command(name="rdf")
20
+ @click.argument("filename", type=click.Path(exists=True))
21
+ @click.option('--cell', type=arg_type.Cell, help='set cell, a list of lattice, --cell x,y,z or x,y,z,a,b,c')
22
+ @click.option("--group", type=click.Tuple([str, str]), help="two group to analysis")
23
+ @click.option('--range', type=click.Tuple([float, float]), help="the range of rdf")
24
+ @click.option('-r', type=arg_type.FrameRange, help='range of frame to analysis')
25
+ def main(filename, cell, group, range, r):
26
+ """analysis the radial distribution function"""
27
+ u = mda.Universe(filename)
28
+ u.trajectory.ts.dt = 0.0001
29
+ u.dimensions = cell
30
+ o = f"rdf_{'_'.join(group).replace(' ', '_')}.dat"
31
+
32
+ rho = 32/(9.86**3)
33
+
34
+ group1 = u.select_atoms(group[0])
35
+ group2 = u.select_atoms(group[1])
36
+
37
+ crdf = rdf.InterRDF(group1, group2, verbose=True, range=(range[0], range[1]), norm='rdf')
38
+
39
+
40
+ if r is not None:
41
+ if len(r) == 2:
42
+ crdf.run(start=r[0], stop=r[1])
43
+ elif len(r) == 3:
44
+ crdf.run(start=r[0], stop=r[1], step=r[2])
45
+ else:
46
+ crdf.run()
47
+
48
+ combin = np.column_stack((crdf.results.bins, crdf.results.rdf, calculate_Gab(crdf.results.bins, crdf.results.rdf)*rho))
49
+ np.savetxt(o, combin, header="A\tgr\tNr", fmt="%.5f", delimiter='\t')
50
+
51
+
52
+ if __name__ == "__main__":
53
+ main()
@@ -0,0 +1,14 @@
1
+ import click
2
+ from mdkits.util import arg_type, os_operation
3
+
4
+
5
+ def common_setting(f):
6
+ f = click.argument('filename', type=click.Path(exists=True), default=os_operation.default_file_name('*-pos-1.xyz', last=True))(f)
7
+ f = click.option('-r', type=arg_type.FrameRange, help='range of frame to analysis')(f)
8
+ f = click.option('--angle', type=(float, float), help='update water angle judgment')(f)
9
+ f = click.option('--distance', type=float, help='update water distance judgment', default=1.2, show_default=True)(f)
10
+ f = click.option('--update_water', is_flag=True, help='update water with distance or angle judgment')(f)
11
+ f = click.option("--surface", type=str, help="surface group")(f)
12
+ f = click.option('--cell', type=arg_type.Cell, help="set cell, a list of lattice, --cell x,y,z or x,y,z,a,b,c")(f)
13
+
14
+ return f