mdkits 0.1.29__py3-none-any.whl → 0.2.0__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.

@@ -18,6 +18,7 @@ from mdkits.util import arg_type, encapsulated_ase, out_err
18
18
  @click.option('--offset', type=click.Tuple([float, float]), help='adjust site', default=(0, 0), show_default=True)
19
19
  @click.option("--cover", type=int, help='cover the surface with adsorbate randomly')
20
20
  def main(atoms, adsorbate, cell, select, height, rotate, offset, cover):
21
+ """add adsorbate molcule to the surface"""
21
22
  if height is None:
22
23
  raise ValueError("height is required")
23
24
 
@@ -22,10 +22,7 @@ def surface_check(obj, surface_type):
22
22
  @click.option('--orth', is_flag=True, help='if specified and true, forces the creation of a unit cell with orthogonal basis vectors. if the default is such a unit cell, this argument is not supported')
23
23
  @click.option('--vacuum', type=float, help='designate vacuum of surface, default is None', default=0.1, show_default=True)
24
24
  def main(symbol, surface, size, kind, a, c, thickness, orth, vacuum):
25
- #if args.primitive:
26
- # a = args.a * 0.7071 * 2
27
- #else:
28
- # a = args.a
25
+ """build a common surface"""
29
26
 
30
27
  vacuum = vacuum / 2
31
28
  build_surface = surface_check(build, surface)
mdkits/cli/extract.py CHANGED
@@ -9,11 +9,12 @@ import MDAnalysis
9
9
  from MDAnalysis import Universe
10
10
 
11
11
 
12
- def write_to_xyz(u, frames, o, cut=None):
13
- with MDAnalysis.Writer(o, u.atoms.n_atoms, format='XYZ') as w:
12
+ def write_to_xyz(u, frames, o, select, cut=None):
13
+ ag = u.select_atoms(select)
14
+ with MDAnalysis.Writer(o, ag.atoms.n_atoms, format='XYZ') as w:
14
15
  for ts in u.trajectory:
15
16
  if ts.frame in frames:
16
- w.write(u)
17
+ w.write(ag)
17
18
  if cut:
18
19
  with open(o, 'r') as fi, open(o+'t', 'w') as fo:
19
20
  for i, line in enumerate(fi):
@@ -22,13 +23,18 @@ def write_to_xyz(u, frames, o, cut=None):
22
23
  os.replace(o+'t', o)
23
24
 
24
25
 
25
- def write_to_xyz_s(u, frames, cut=None):
26
+ def write_to_xyz_s(u, frames, select, cut=None):
26
27
  index = 0
28
+ ag = u.select_atoms(select)
29
+ if select:
30
+ dir = f'./coord/{"_".join(select.split())}'
31
+ else:
32
+ dir = './coord/all'
27
33
  for ts in u.trajectory:
28
34
  if ts.frame in frames:
29
- o = f'./coord/coord_{index:03d}'
30
- with MDAnalysis.Writer(o, u.atoms.n_atoms, format='XYZ') as w:
31
- w.write(u)
35
+ o = f'{dir}/coord_{index:03d}'
36
+ with MDAnalysis.Writer(o, ag.atoms.n_atoms, format='XYZ') as w:
37
+ w.write(ag)
32
38
  index += 1
33
39
  if cut:
34
40
  with open(o, 'r') as fi, open(o+'t', 'w') as fo:
@@ -39,10 +45,10 @@ def write_to_xyz_s(u, frames, cut=None):
39
45
 
40
46
  @click.command(name='extract')
41
47
  @click.argument('input_file_name', type=click.Path(exists=True), default=os_operation.default_file_name('*-pos-1.xyz', last=True))
42
- @click.option('-o', type=str, help='output file name', default='extracted.xyz', show_default=True)
43
48
  @click.option('-r', type=arg_type.FrameRange, help='frame range to slice', default='-1', show_default=True)
44
49
  @click.option('-c', help='output a coord.xyz', is_flag=True)
45
- def main(input_file_name, o, r, c):
50
+ @click.option("--select", type=str, help="select atoms to extract")
51
+ def main(input_file_name, r, c, select):
46
52
  """
47
53
  extract frames in trajectory file
48
54
  """
@@ -63,16 +69,21 @@ def main(input_file_name, o, r, c):
63
69
  cut = None
64
70
 
65
71
  if len(r) == 3 and r[-1] is not None:
66
- if not os.path.exists('./coord'):
67
- os.makedirs('./coord')
72
+ if select:
73
+ dir = f'./coord/{"_".join(select.split())}'
74
+ else:
75
+ dir = './coord/all'
76
+ if not os.path.exists(dir):
77
+ os.makedirs(dir)
68
78
  else:
69
79
  import shutil
70
- shutil.rmtree('./coord')
71
- os.makedirs('./coord')
72
- write_to_xyz_s(u, frames, cut=cut)
73
- click.echo(os.path.abspath('./coord'))
80
+ shutil.rmtree(dir)
81
+ os.makedirs(dir)
82
+ write_to_xyz_s(u, frames, select, cut=cut)
83
+ click.echo(os.path.abspath(dir))
74
84
  else:
75
- write_to_xyz(u, frames, o, cut=cut)
85
+ o = f"{os.path.basename(u.filename).split('.')[0]}_{'_'.join([str(i) for i in r])}_{'_'.join(select.split()) if select else 'all'}.xyz"
86
+ write_to_xyz(u, frames, o, select, cut=cut)
76
87
  click.echo(os.path.abspath(o))
77
88
 
78
89
 
mdkits/md_cli/angle.py CHANGED
@@ -5,6 +5,7 @@ import MDAnalysis
5
5
  import sys
6
6
  from mdkits.util import numpy_geo, encapsulated_mda, arg_type
7
7
  import numpy as np
8
+ from .setting import common_setting
8
9
 
9
10
 
10
11
  class Angle_distribution(AnalysisBase):
@@ -102,15 +103,9 @@ class Angle_distribution(AnalysisBase):
102
103
  np.savetxt("angle_distribution.dat", conbined_data, header="angle\tw_suf_dist\toh_suf_dist", fmt='%.5f', delimiter='\t')
103
104
 
104
105
 
105
- @click.command(name="angle")
106
- @click.argument("filename", type=click.Path(exists=True))
107
- @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")
106
+ @click.command(name="angle", help="analysis angle between normal vectors and OH vector or bisector")
107
+ @common_setting
108
108
  @click.option("--water_height", type=float, help="water height from surface")
109
- @click.option("--surface", type=str, help="surface group")
110
- @click.option('--update_water', is_flag=True, help='update water with distance or angle judgment')
111
- @click.option('--distance', type=float, help='update water distance judgment', default=1.2, show_default=True)
112
- @click.option('--angle', type=(float, float), help='update water angle judgment')
113
- @click.option('-r', type=arg_type.FrameRange, help='range of frame to analysis')
114
109
  def main(filename, cell, water_height, update_water, distance, angle, surface, r):
115
110
  """analysis angle between normal vectors and OH vector or bisector"""
116
111
  a = Angle_distribution(filename, cell, water_height, update_water, distance_judg=distance, angle_judg=angle, surface=surface)
mdkits/md_cli/density.py CHANGED
@@ -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
 
@@ -79,9 +80,10 @@ class Density_distribution(AnalysisBase):
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
+ if len(surface) > 1:
86
+ self.surface_pos[1] += surface[1]
85
87
 
86
88
  self.frame_count += 1
87
89
 
@@ -98,7 +100,8 @@ class Density_distribution(AnalysisBase):
98
100
 
99
101
  if self.surface:
100
102
  lower_z = self.surface_pos[0] / self.frame_count
101
- upper_z = self.surface_pos[1] / self.frame_count
103
+ if self.surface_pos[1] == 0:
104
+ upper_z = np.inf
102
105
 
103
106
  mask = (bins_z >= lower_z) & (bins_z <= upper_z)
104
107
  filtered_bins_z = bins_z[mask] - lower_z
@@ -110,16 +113,11 @@ class Density_distribution(AnalysisBase):
110
113
 
111
114
  np.savetxt(self.o, conbined_data, header="Z\tdensity", fmt='%.5f', delimiter='\t')
112
115
 
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')
116
+ @click.command(name='density', help="analysis density or concentration of element in a trajectory file")
117
+ @common_setting
118
+ @click.option('--group', type=str, help='group to analysis')
117
119
  @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
120
  @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
121
  def main(filename, cell, o, element, atomic_mass, update_water, distance, angle, surface):
124
122
  """
125
123
  analysis density or concentration of element in a trajectory file
@@ -0,0 +1,120 @@
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
90
+
91
+ if self.surface:
92
+ lower_z, upper_z = self.surface_pos / self.frame_count
93
+
94
+ mask = (bins_z >= lower_z) & (bins_z <= upper_z)
95
+ filtered_bins_z = bins_z[mask] - lower_z
96
+ filtered_dipole_distribution = average_dipole[mask]
97
+
98
+ conbined_data = np.column_stack((filtered_bins_z, filtered_dipole_distribution))
99
+ else:
100
+ conbined_data = np.column_stack((bins_z, average_dipole))
101
+
102
+ np.savetxt("dipole_distribution.dat", conbined_data, header="z\tDipole Z Positions\tWater Density", fmt='%.5f', delimiter='\t')
103
+
104
+
105
+ @click.command(name="dipole")
106
+ @common_setting
107
+ def main(filename, cell, update_water, distance, angle, surface, r):
108
+ """analysis dipole along z-axis"""
109
+ a = Dipole_distribution(filename, cell, update_water, distance_judg=distance, angle_judg=angle, surface=surface)
110
+ if r is not None:
111
+ if len(r) == 2:
112
+ a.run(start=r[0], stop=r[1])
113
+ elif len(r) == 3:
114
+ a.run(start=r[0], stop=r[1], step=r[2])
115
+ else:
116
+ a.run()
117
+
118
+
119
+ if __name__ == "__main__":
120
+ main()
@@ -5,8 +5,9 @@ import click
5
5
  import MDAnalysis
6
6
  from MDAnalysis import Universe
7
7
  from MDAnalysis.analysis.base import AnalysisBase
8
- from mdkits.util import arg_type, os_operation, numpy_geo, encapsulated_mda
8
+ from mdkits.util import numpy_geo, encapsulated_mda
9
9
  import warnings, sys
10
+ from .setting import common_setting
10
11
  warnings.filterwarnings("ignore")
11
12
 
12
13
 
@@ -120,23 +121,27 @@ class Hb_distribution(AnalysisBase):
120
121
  self._append(hb_d, hb_a, o_group.positions[:, 2])
121
122
 
122
123
  if self.surface_group:
123
- lower_z, upper_z = numpy_geo.find_surface(self.surface_group.positions[:, 2])
124
- self.surface_pos[0] += lower_z
125
- self.surface_pos[1] += upper_z
124
+ surface = numpy_geo.find_surface(self.surface_group.positions[:, 2])
125
+ self.surface_pos[0] += surface[0]
126
+ if len(surface) > 1:
127
+ self.surface_pos[1] += surface[1]
126
128
 
127
129
  self.frame_count += 1
128
130
 
129
131
  def _conclude(self):
130
132
  if self.frame_count > 0 and self.index is None:
131
133
  average_od = self.od / self.frame_count
132
- average_donor = (self.donor / self.frame_count) / average_od
133
- average_accepter = (self.accepter / self.frame_count) / average_od
134
+ average_donor = np.nan_to_num((self.donor / self.frame_count) / average_od, nan=0)
135
+ average_accepter = np.nan_to_num((self.accepter / self.frame_count) / average_od, nan=0)
134
136
  average_sum = average_donor + average_accepter
135
137
 
136
138
  bins_z = np.arange(len(self.donor)) * self.bin_size
137
139
 
138
140
  if self.surface:
139
- lower_z, upper_z = self.surface_pos/self.frame_count
141
+ surface = self.surface_pos/self.frame_count
142
+ lower_z = surface[0]
143
+ if surface[1] ==0:
144
+ upper_z = np.inf
140
145
  mask = (bins_z >= lower_z) & (bins_z <= upper_z)
141
146
  filtered_bins_z = bins_z[mask] - lower_z
142
147
  filtered_average_accepter = average_accepter[mask]
@@ -158,15 +163,9 @@ class Hb_distribution(AnalysisBase):
158
163
  print(output)
159
164
 
160
165
 
161
- @click.command(name="hb")
162
- @click.argument('filename', type=click.Path(exists=True), default=os_operation.default_file_name('*-pos-1.xyz', last=True))
166
+ @click.command(name="hb", help="analysis hydrogen bond distribution along z-axis")
167
+ @common_setting
163
168
  @click.option('--hb_param', type=click.Tuple([float, float]), help='parameter for hydrogen bond', default=(3.5, 35), show_default=True)
164
- @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')
165
- @click.option('--surface', type=str, help='surface element')
166
- @click.option('-r', type=arg_type.FrameRange, help='range of frame to analysis')
167
- @click.option('--update_water', is_flag=True, help='update water with distance or angle judgment')
168
- @click.option('--distance', type=float, help='update water distance judgment', default=1.2, show_default=True)
169
- @click.option('--angle', type=(float, float), help='update water angle judgment')
170
169
  @click.option('--index', type=int, help='index of an atom')
171
170
  def main(filename, hb_param, cell, surface, r, update_water, distance, angle, index):
172
171
  """analysis hydrogen bond distribution along z-axis"""
mdkits/md_cli/md_cli.py CHANGED
@@ -1,21 +1,32 @@
1
1
  import click
2
2
  from mdkits.md_cli import (
3
+ wrap,
4
+ dipole,
5
+ angle,
3
6
  density,
4
7
  hb_distribution,
5
- angle,
8
+ vac,
9
+ rdf,
10
+ msd,
11
+ monitor,
6
12
  )
7
13
 
8
14
 
9
15
  @click.group(name='md')
10
16
  @click.pass_context
11
- def main(ctx):
17
+ def cli(ctx):
12
18
  """kits for MD analysis"""
13
- pass
14
19
 
15
- main.add_command(density.main)
16
- main.add_command(hb_distribution.main)
17
- main.add_command(angle.main)
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)
18
29
 
19
30
 
20
31
  if __name__ == '__main__':
21
- 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,30 @@
1
+ import click
2
+ import MDAnalysis as mda
3
+ import MDAnalysis.analysis.msd as msd
4
+ import numpy as np
5
+
6
+
7
+ @click.command(name="msd")
8
+ @click.argument("filename", type=click.Path(exists=True))
9
+ @click.argument('type', type=click.Choice(['xyz', 'xy', 'yz', 'xz', 'x', 'y', 'z']))
10
+ @click.argument("group", type=str)
11
+ def main(filename, type, group):
12
+ """analysis msd along the given axis"""
13
+ u = mda.Universe(filename)
14
+ MSD = msd.EinsteinMSD(u, select=group, msd_type=type, fft=True)
15
+ MSD.run(verbose=True)
16
+
17
+ data = np.arange(1, MSD.n_frames + 1).reshape(-1, 1)
18
+ s = "_"
19
+ name = f"{s.join(group.split(' '))}"
20
+ header = ''
21
+ for i in range(MSD.n_particles):
22
+ data = np.concatenate((data, MSD.results.msds_by_particle[:, i].reshape(-1, 1)), axis=1)
23
+ header += name + f"_{i}\t"
24
+
25
+ np.savetxt(f"msd_{type}.dat", data, fmt="%.5f", delimiter="\t", header=f"frame\t{header}")
26
+
27
+
28
+
29
+ if __name__ == '__main__':
30
+ 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