mdkits 0.1a1__tar.gz
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-0.1a1/LICENSE +21 -0
- mdkits-0.1a1/PKG-INFO +161 -0
- mdkits-0.1a1/README.md +136 -0
- mdkits-0.1a1/pyproject.toml +46 -0
- mdkits-0.1a1/src/mdkits/__init__.py +0 -0
- mdkits-0.1a1/src/mdkits/cli/,hb_distribution.py +126 -0
- mdkits-0.1a1/src/mdkits/cli/,hb_distribution_down.py +114 -0
- mdkits-0.1a1/src/mdkits/cli/adsorbate.py +84 -0
- mdkits-0.1a1/src/mdkits/cli/build_bulk.py +55 -0
- mdkits-0.1a1/src/mdkits/cli/build_interface.py +86 -0
- mdkits-0.1a1/src/mdkits/cli/build_surface.py +134 -0
- mdkits-0.1a1/src/mdkits/cli/cmdline.py +41 -0
- mdkits-0.1a1/src/mdkits/cli/convert.py +63 -0
- mdkits-0.1a1/src/mdkits/cli/cp2k_input.py +479 -0
- mdkits-0.1a1/src/mdkits/cli/cube.py +59 -0
- mdkits-0.1a1/src/mdkits/cli/cut_surface.py +38 -0
- mdkits-0.1a1/src/mdkits/cli/data.py +80 -0
- mdkits-0.1a1/src/mdkits/cli/density.py +89 -0
- mdkits-0.1a1/src/mdkits/cli/density2.py +91 -0
- mdkits-0.1a1/src/mdkits/cli/extract.py +80 -0
- mdkits-0.1a1/src/mdkits/cli/hartree_potential.py +59 -0
- mdkits-0.1a1/src/mdkits/cli/hartree_potential_ave.py +84 -0
- mdkits-0.1a1/src/mdkits/cli/hb.py +101 -0
- mdkits-0.1a1/src/mdkits/cli/log.py +64 -0
- mdkits-0.1a1/src/mdkits/cli/matplot.py +60 -0
- mdkits-0.1a1/src/mdkits/cli/packmol_input.py +76 -0
- mdkits-0.1a1/src/mdkits/cli/pdos.py +36 -0
- mdkits-0.1a1/src/mdkits/cli/plot.py +289 -0
- mdkits-0.1a1/src/mdkits/cli/supercell.py +72 -0
- mdkits-0.1a1/src/mdkits/cli/wrap.py +36 -0
- mdkits-0.1a1/src/mdkits/config/__init__.py +35 -0
- mdkits-0.1a1/src/mdkits/config/settings.yml +4 -0
- mdkits-0.1a1/src/mdkits/mdtool.py +28 -0
- mdkits-0.1a1/src/mdkits/util/__init__.py +0 -0
- mdkits-0.1a1/src/mdkits/util/arg_type.py +41 -0
- mdkits-0.1a1/src/mdkits/util/cp2k_input_parsing.py +46 -0
- mdkits-0.1a1/src/mdkits/util/encapsulated_ase.py +134 -0
- mdkits-0.1a1/src/mdkits/util/encapsulated_mda.py +59 -0
- mdkits-0.1a1/src/mdkits/util/fig_operation.py +28 -0
- mdkits-0.1a1/src/mdkits/util/numpy_geo.py +118 -0
- mdkits-0.1a1/src/mdkits/util/os_operation.py +35 -0
- mdkits-0.1a1/src/mdkits/util/structure_parsing.py +147 -0
mdkits-0.1a1/LICENSE
ADDED
|
@@ -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.
|
mdkits-0.1a1/PKG-INFO
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: mdkits
|
|
3
|
+
Version: 0.1a1
|
|
4
|
+
Summary: tools for md or dft
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: molecular dynamics,density functional theory
|
|
7
|
+
Author: jxxcr
|
|
8
|
+
Author-email: jixxcr@qq.com
|
|
9
|
+
Requires-Python: >=3.11,<4.0
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Requires-Dist: MDAnalysis (>=2.8.0,<3.0.0)
|
|
17
|
+
Requires-Dist: ase (>=3.22.1,<4.0.0)
|
|
18
|
+
Requires-Dist: click (>=8.1.3,<9.0.0)
|
|
19
|
+
Requires-Dist: dynaconf (>=3.1.12,<4.0.0)
|
|
20
|
+
Requires-Dist: matplotlib (>=3.9.0,<4.0.0)
|
|
21
|
+
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
|
22
|
+
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
23
|
+
Project-URL: Repository, https://github.com/jxxcr/mdkits
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# MD 轨迹分析脚本
|
|
27
|
+
`mdtool` 提供了多种工具, 安装脚本:
|
|
28
|
+
```bash
|
|
29
|
+
pip install mdtool --upgrade
|
|
30
|
+
```
|
|
31
|
+
### 密度分布
|
|
32
|
+
|
|
33
|
+
### 氢键
|
|
34
|
+
|
|
35
|
+
#### 单个水分子
|
|
36
|
+
|
|
37
|
+
#### 氢键分布
|
|
38
|
+
|
|
39
|
+
### 角度
|
|
40
|
+
|
|
41
|
+
#### 与表面法向量夹角分布
|
|
42
|
+
|
|
43
|
+
#### ion - O - ion 夹角分布
|
|
44
|
+
|
|
45
|
+
#### $\cos \phi \rho_{H_2 O}$ 分布
|
|
46
|
+
|
|
47
|
+
### RDF
|
|
48
|
+
|
|
49
|
+
### 位置归一化
|
|
50
|
+
`wrap`用于将轨迹文件中的原子位置进行归一化处理, 如将`[FILENAME]`中的原子位置归一化到晶胞中, 并输出为`wrapped.xyz`, 默认从`cp2k`的输出文件`input_inp`中读取`ABC`和`ALPHA_BETA_GAMMA`信息作为晶胞参数:
|
|
51
|
+
```bash
|
|
52
|
+
mdtool wrap [FILENAME]
|
|
53
|
+
```
|
|
54
|
+
或指定`cp2k`的输入文件:
|
|
55
|
+
```bash
|
|
56
|
+
mdtool wrap [FILENAME] --cp2k_input_file setting.inp
|
|
57
|
+
```
|
|
58
|
+
或指定晶胞参数:
|
|
59
|
+
```bash
|
|
60
|
+
mdtool wrap [FILENAME] --cell 10,10,10
|
|
61
|
+
```
|
|
62
|
+
默认的`[FILENAME]`为`*-pos-1.xyz`
|
|
63
|
+
|
|
64
|
+
## DFT 性质分析脚本
|
|
65
|
+
### PDOS
|
|
66
|
+
|
|
67
|
+
### 静电势
|
|
68
|
+
|
|
69
|
+
### 电荷差分
|
|
70
|
+
|
|
71
|
+
## 其他
|
|
72
|
+
### 轨迹提取
|
|
73
|
+
`extract`用于提取轨迹文件中的特定的帧, 如从`frames.xyz`中提取第 1000 帧到第 2000 帧的轨迹文件, 并输出为`1000-2000.xyz`, `-r`选项的参数与`Python`的切片语法一致:
|
|
74
|
+
```bash
|
|
75
|
+
mdtool extract frames.xyz -r 1000:2000 -o 1000-2000.xyz
|
|
76
|
+
```
|
|
77
|
+
或从`cp2k`的默认输出的轨迹文件`*-pos-1.xyz`文件中提取最后一帧输出为`extracted.xyz`(`extract`的默认行为):
|
|
78
|
+
```bash
|
|
79
|
+
mdtool extract
|
|
80
|
+
```
|
|
81
|
+
或每50帧输出一个结构到`./coord`目录中, 同时调整输出格式为`cp2k`的`@INCLUDE coord.xyz`的形式:
|
|
82
|
+
```bash
|
|
83
|
+
mdtool extract -cr ::50
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 结构文件转换
|
|
87
|
+
`convert`用于将结构文件从一种格式转换为另一种格式, 如将`structure.xyz`转换为`out.cif`(默认文件名为`out`), 对于不储存周期性边界条件的文件, 可以使用`--cell`选项指定`PBC`:
|
|
88
|
+
```bash
|
|
89
|
+
mdtool convert -c structure.xyz --cell 10,10,10
|
|
90
|
+
```
|
|
91
|
+
将`structure.cif`转换为`POSCAR`:
|
|
92
|
+
```bash
|
|
93
|
+
mdtool convert -v structure.cif
|
|
94
|
+
```
|
|
95
|
+
将`structure.cif`转换为`structure_xyz.xyz`:
|
|
96
|
+
```bash
|
|
97
|
+
mdtool convert -c structure.cif -o structure_xyz
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 数据处理
|
|
101
|
+
`data`用于对数据进行处理如:
|
|
102
|
+
1. `--nor`: 对数据进行归一化处理
|
|
103
|
+
2. `--gaus`: 对数据进行高斯过滤
|
|
104
|
+
3. `--fold`: 堆数据进行折叠平均
|
|
105
|
+
4. `--err`: 计算数据的误差棒
|
|
106
|
+
等
|
|
107
|
+
|
|
108
|
+
### 绘图工具
|
|
109
|
+
`plot`用于绘制数据图, `plot`需要读取`yaml`格式的配置文件进行绘图, `yaml`文件的形式如下:
|
|
110
|
+
```yaml
|
|
111
|
+
# plot mode 1
|
|
112
|
+
figure1:
|
|
113
|
+
data:
|
|
114
|
+
legend1: ./data1.dat
|
|
115
|
+
legend2: ./data2.dat
|
|
116
|
+
x:
|
|
117
|
+
0: x-axis
|
|
118
|
+
y:
|
|
119
|
+
1: y-axis
|
|
120
|
+
x_range:
|
|
121
|
+
- 5
|
|
122
|
+
- 15
|
|
123
|
+
|
|
124
|
+
# plot mode 2
|
|
125
|
+
figure2:
|
|
126
|
+
data:
|
|
127
|
+
y-xais: ./data.dat
|
|
128
|
+
x:
|
|
129
|
+
0: x-axis
|
|
130
|
+
y:
|
|
131
|
+
1: legend1
|
|
132
|
+
2: legend2
|
|
133
|
+
3: legend3
|
|
134
|
+
4: legend4
|
|
135
|
+
5: legend5
|
|
136
|
+
y_range:
|
|
137
|
+
- 0.5
|
|
138
|
+
- 6
|
|
139
|
+
legend_fontsize: 12
|
|
140
|
+
|
|
141
|
+
# plot mode error
|
|
142
|
+
12_dp_e_error:
|
|
143
|
+
data:
|
|
144
|
+
legend: ./error.dat
|
|
145
|
+
x:
|
|
146
|
+
0: x-axis
|
|
147
|
+
y:
|
|
148
|
+
1: y-axis
|
|
149
|
+
fold: dp
|
|
150
|
+
legend_fontsize: 12
|
|
151
|
+
```
|
|
152
|
+
如上`plot`支持三种绘图模式, `mode 1`, `mode 2`和`mode error`. `mode 1`用于绘制多组数据文件的同一列数据对比, `mode 2`用于绘制同一数据文件的不同列数据对比, `mode error`用于绘制均方根误差图.
|
|
153
|
+
|
|
154
|
+
`plot`可以同时处理多个`yaml`文件, 每个`yaml`文件可以包含多个绘图配置, `mode 1`和`mode 2`的绘图配置可以自动识别, 但是`error`模式需要而外指定, 如:
|
|
155
|
+
```bash
|
|
156
|
+
mdtool plot *.yaml
|
|
157
|
+
```
|
|
158
|
+
和:
|
|
159
|
+
```bash
|
|
160
|
+
mdtool plot *.yaml --error
|
|
161
|
+
```
|
mdkits-0.1a1/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# MD 轨迹分析脚本
|
|
2
|
+
`mdtool` 提供了多种工具, 安装脚本:
|
|
3
|
+
```bash
|
|
4
|
+
pip install mdtool --upgrade
|
|
5
|
+
```
|
|
6
|
+
### 密度分布
|
|
7
|
+
|
|
8
|
+
### 氢键
|
|
9
|
+
|
|
10
|
+
#### 单个水分子
|
|
11
|
+
|
|
12
|
+
#### 氢键分布
|
|
13
|
+
|
|
14
|
+
### 角度
|
|
15
|
+
|
|
16
|
+
#### 与表面法向量夹角分布
|
|
17
|
+
|
|
18
|
+
#### ion - O - ion 夹角分布
|
|
19
|
+
|
|
20
|
+
#### $\cos \phi \rho_{H_2 O}$ 分布
|
|
21
|
+
|
|
22
|
+
### RDF
|
|
23
|
+
|
|
24
|
+
### 位置归一化
|
|
25
|
+
`wrap`用于将轨迹文件中的原子位置进行归一化处理, 如将`[FILENAME]`中的原子位置归一化到晶胞中, 并输出为`wrapped.xyz`, 默认从`cp2k`的输出文件`input_inp`中读取`ABC`和`ALPHA_BETA_GAMMA`信息作为晶胞参数:
|
|
26
|
+
```bash
|
|
27
|
+
mdtool wrap [FILENAME]
|
|
28
|
+
```
|
|
29
|
+
或指定`cp2k`的输入文件:
|
|
30
|
+
```bash
|
|
31
|
+
mdtool wrap [FILENAME] --cp2k_input_file setting.inp
|
|
32
|
+
```
|
|
33
|
+
或指定晶胞参数:
|
|
34
|
+
```bash
|
|
35
|
+
mdtool wrap [FILENAME] --cell 10,10,10
|
|
36
|
+
```
|
|
37
|
+
默认的`[FILENAME]`为`*-pos-1.xyz`
|
|
38
|
+
|
|
39
|
+
## DFT 性质分析脚本
|
|
40
|
+
### PDOS
|
|
41
|
+
|
|
42
|
+
### 静电势
|
|
43
|
+
|
|
44
|
+
### 电荷差分
|
|
45
|
+
|
|
46
|
+
## 其他
|
|
47
|
+
### 轨迹提取
|
|
48
|
+
`extract`用于提取轨迹文件中的特定的帧, 如从`frames.xyz`中提取第 1000 帧到第 2000 帧的轨迹文件, 并输出为`1000-2000.xyz`, `-r`选项的参数与`Python`的切片语法一致:
|
|
49
|
+
```bash
|
|
50
|
+
mdtool extract frames.xyz -r 1000:2000 -o 1000-2000.xyz
|
|
51
|
+
```
|
|
52
|
+
或从`cp2k`的默认输出的轨迹文件`*-pos-1.xyz`文件中提取最后一帧输出为`extracted.xyz`(`extract`的默认行为):
|
|
53
|
+
```bash
|
|
54
|
+
mdtool extract
|
|
55
|
+
```
|
|
56
|
+
或每50帧输出一个结构到`./coord`目录中, 同时调整输出格式为`cp2k`的`@INCLUDE coord.xyz`的形式:
|
|
57
|
+
```bash
|
|
58
|
+
mdtool extract -cr ::50
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 结构文件转换
|
|
62
|
+
`convert`用于将结构文件从一种格式转换为另一种格式, 如将`structure.xyz`转换为`out.cif`(默认文件名为`out`), 对于不储存周期性边界条件的文件, 可以使用`--cell`选项指定`PBC`:
|
|
63
|
+
```bash
|
|
64
|
+
mdtool convert -c structure.xyz --cell 10,10,10
|
|
65
|
+
```
|
|
66
|
+
将`structure.cif`转换为`POSCAR`:
|
|
67
|
+
```bash
|
|
68
|
+
mdtool convert -v structure.cif
|
|
69
|
+
```
|
|
70
|
+
将`structure.cif`转换为`structure_xyz.xyz`:
|
|
71
|
+
```bash
|
|
72
|
+
mdtool convert -c structure.cif -o structure_xyz
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 数据处理
|
|
76
|
+
`data`用于对数据进行处理如:
|
|
77
|
+
1. `--nor`: 对数据进行归一化处理
|
|
78
|
+
2. `--gaus`: 对数据进行高斯过滤
|
|
79
|
+
3. `--fold`: 堆数据进行折叠平均
|
|
80
|
+
4. `--err`: 计算数据的误差棒
|
|
81
|
+
等
|
|
82
|
+
|
|
83
|
+
### 绘图工具
|
|
84
|
+
`plot`用于绘制数据图, `plot`需要读取`yaml`格式的配置文件进行绘图, `yaml`文件的形式如下:
|
|
85
|
+
```yaml
|
|
86
|
+
# plot mode 1
|
|
87
|
+
figure1:
|
|
88
|
+
data:
|
|
89
|
+
legend1: ./data1.dat
|
|
90
|
+
legend2: ./data2.dat
|
|
91
|
+
x:
|
|
92
|
+
0: x-axis
|
|
93
|
+
y:
|
|
94
|
+
1: y-axis
|
|
95
|
+
x_range:
|
|
96
|
+
- 5
|
|
97
|
+
- 15
|
|
98
|
+
|
|
99
|
+
# plot mode 2
|
|
100
|
+
figure2:
|
|
101
|
+
data:
|
|
102
|
+
y-xais: ./data.dat
|
|
103
|
+
x:
|
|
104
|
+
0: x-axis
|
|
105
|
+
y:
|
|
106
|
+
1: legend1
|
|
107
|
+
2: legend2
|
|
108
|
+
3: legend3
|
|
109
|
+
4: legend4
|
|
110
|
+
5: legend5
|
|
111
|
+
y_range:
|
|
112
|
+
- 0.5
|
|
113
|
+
- 6
|
|
114
|
+
legend_fontsize: 12
|
|
115
|
+
|
|
116
|
+
# plot mode error
|
|
117
|
+
12_dp_e_error:
|
|
118
|
+
data:
|
|
119
|
+
legend: ./error.dat
|
|
120
|
+
x:
|
|
121
|
+
0: x-axis
|
|
122
|
+
y:
|
|
123
|
+
1: y-axis
|
|
124
|
+
fold: dp
|
|
125
|
+
legend_fontsize: 12
|
|
126
|
+
```
|
|
127
|
+
如上`plot`支持三种绘图模式, `mode 1`, `mode 2`和`mode error`. `mode 1`用于绘制多组数据文件的同一列数据对比, `mode 2`用于绘制同一数据文件的不同列数据对比, `mode error`用于绘制均方根误差图.
|
|
128
|
+
|
|
129
|
+
`plot`可以同时处理多个`yaml`文件, 每个`yaml`文件可以包含多个绘图配置, `mode 1`和`mode 2`的绘图配置可以自动识别, 但是`error`模式需要而外指定, 如:
|
|
130
|
+
```bash
|
|
131
|
+
mdtool plot *.yaml
|
|
132
|
+
```
|
|
133
|
+
和:
|
|
134
|
+
```bash
|
|
135
|
+
mdtool plot *.yaml --error
|
|
136
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "mdkits"
|
|
3
|
+
version = "0.1.a1"
|
|
4
|
+
description = "tools for md or dft"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = ["jxxcr <jixxcr@qq.com>"]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
keywords = ["molecular dynamics", "density functional theory"]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Operating System :: OS Independent",
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
]
|
|
13
|
+
repository = "https://github.com/jxxcr/mdkits"
|
|
14
|
+
|
|
15
|
+
[tool.poetry.dependencies]
|
|
16
|
+
python = "^3.11"
|
|
17
|
+
dynaconf = "^3.1.12"
|
|
18
|
+
click = "^8.1.3"
|
|
19
|
+
MDAnalysis = "^2.8.0"
|
|
20
|
+
ase = "^3.22.1"
|
|
21
|
+
matplotlib = "^3.9.0"
|
|
22
|
+
pyyaml = "^6.0.1"
|
|
23
|
+
numpy = "^1.26.4"
|
|
24
|
+
|
|
25
|
+
[tool.poetry.group.dev.dependencies]
|
|
26
|
+
pylint = "^2.17.4"
|
|
27
|
+
isort = "^5.12.0"
|
|
28
|
+
pytest = "^7.3.1"
|
|
29
|
+
tox = "^4.5.2"
|
|
30
|
+
mkdocs = "^1.4.3"
|
|
31
|
+
mkdocs-material = "^8.5.11"
|
|
32
|
+
pytest-pylint = "^0.19.0"
|
|
33
|
+
pre-commit = "^3.3.2"
|
|
34
|
+
|
|
35
|
+
[tool.poetry.scripts]
|
|
36
|
+
mdkits = "mdkits.mdkits:cli"
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["poetry-core"]
|
|
40
|
+
build-backend = "poetry.core.masonry.api"
|
|
41
|
+
[tool.pytest.ini_options]
|
|
42
|
+
testpaths = "tests"
|
|
43
|
+
python_files = "tests.py test_*.py *_tests.py"
|
|
44
|
+
|
|
45
|
+
[tool.pylint.design]
|
|
46
|
+
max-line-length = 120
|
|
File without changes
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import argparse
|
|
5
|
+
import MDAnalysis
|
|
6
|
+
from MDAnalysis import Universe
|
|
7
|
+
from MDAnalysis.analysis.base import AnalysisBase
|
|
8
|
+
from util import cp2k_input_parsing
|
|
9
|
+
import warnings
|
|
10
|
+
warnings.filterwarnings("ignore")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Hb_distribution(AnalysisBase):
|
|
14
|
+
def __init__(self, filename, cell, surface, dt=0.001, hb_distance=3.5, hb_angle=35, bin_size=0.2):
|
|
15
|
+
u = Universe(filename)
|
|
16
|
+
u.trajectory.ts.dt = dt
|
|
17
|
+
u.dimensions = cell
|
|
18
|
+
self.u = u
|
|
19
|
+
self.atomgroup = u.select_atoms("all")
|
|
20
|
+
self.hb_distance = hb_distance
|
|
21
|
+
self.hb_angle = hb_angle
|
|
22
|
+
self.bin_size = bin_size
|
|
23
|
+
self.surface = surface
|
|
24
|
+
self.frame_count = 0
|
|
25
|
+
super(Hb_distribution, self).__init__(self.atomgroup.universe.trajectory, verbose=True)
|
|
26
|
+
|
|
27
|
+
def _prepare(self):
|
|
28
|
+
bin_num = int(self.u.dimensions[2] / self.bin_size) + 2
|
|
29
|
+
self.accepter = np.zeros(bin_num, dtype=np.float64)
|
|
30
|
+
self.donor = np.zeros(bin_num, dtype=np.float64)
|
|
31
|
+
|
|
32
|
+
def _append(self, hb_d, hb_a):
|
|
33
|
+
bins_d = np.floor(hb_d / self.bin_size).astype(int) + 1
|
|
34
|
+
bins_a = np.floor(hb_a / self.bin_size).astype(int) + 1
|
|
35
|
+
|
|
36
|
+
bins_d = bins_d[bins_d < len(self.donor)]
|
|
37
|
+
bins_a = bins_a[bins_a < len(self.accepter)]
|
|
38
|
+
|
|
39
|
+
np.add.at(self.donor, bins_d, 1)
|
|
40
|
+
np.add.at(self.accepter, bins_a, 1)
|
|
41
|
+
|
|
42
|
+
self.frame_count += 1
|
|
43
|
+
|
|
44
|
+
def _single_frame(self):
|
|
45
|
+
o_group = self.atomgroup.select_atoms("name O")
|
|
46
|
+
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)
|
|
47
|
+
|
|
48
|
+
o0 = o_group[o_pair[:, 0]]
|
|
49
|
+
o1 = o_group[o_pair[:, 1]]
|
|
50
|
+
|
|
51
|
+
o0h1 = self.atomgroup[o0.indices + 1]
|
|
52
|
+
o0h2 = self.atomgroup[o0.indices + 2]
|
|
53
|
+
o1h1 = self.atomgroup[o1.indices + 1]
|
|
54
|
+
o1h2 = self.atomgroup[o1.indices + 2]
|
|
55
|
+
|
|
56
|
+
angle_o0h1_o0_o1 = np.degrees(
|
|
57
|
+
MDAnalysis.lib.distances.calc_angles(o0h1.positions, o0.positions, o1.positions, box=self.u.dimensions)
|
|
58
|
+
)
|
|
59
|
+
angle_o0h2_o0_o1 = np.degrees(
|
|
60
|
+
MDAnalysis.lib.distances.calc_angles(o0h2.positions, o0.positions, o1.positions, box=self.u.dimensions)
|
|
61
|
+
)
|
|
62
|
+
angle_o1h1_o1_o0 = np.degrees(
|
|
63
|
+
MDAnalysis.lib.distances.calc_angles(o1h1.positions, o1.positions, o0.positions, box=self.u.dimensions)
|
|
64
|
+
)
|
|
65
|
+
angle_o1h2_o1_o0 = np.degrees(
|
|
66
|
+
MDAnalysis.lib.distances.calc_angles(o1h2.positions, o1.positions, o0.positions, box=self.u.dimensions)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
condition_d = (angle_o0h1_o0_o1 < self.hb_angle) | (angle_o0h2_o0_o1 < self.hb_angle)
|
|
70
|
+
condition_a = (angle_o1h1_o1_o0 < self.hb_angle) | (angle_o1h2_o1_o0 < self.hb_angle)
|
|
71
|
+
|
|
72
|
+
hb_d = (o0.positions[:, 2][condition_d] + o1.positions[:, 2][condition_d]) / 2
|
|
73
|
+
hb_a = (o0.positions[:, 2][condition_a] + o1.positions[:, 2][condition_a]) / 2
|
|
74
|
+
|
|
75
|
+
self._append(hb_d, hb_a)
|
|
76
|
+
|
|
77
|
+
def _conclude(self):
|
|
78
|
+
if self.frame_count > 0:
|
|
79
|
+
average_donor = self.donor / self.frame_count
|
|
80
|
+
average_accepter = self.accepter / self.frame_count
|
|
81
|
+
average_sum = average_donor + average_accepter
|
|
82
|
+
|
|
83
|
+
bins_z = np.arange(len(self.donor)) * self.bin_size
|
|
84
|
+
|
|
85
|
+
lower_z, upper_z = self.surface
|
|
86
|
+
mask = (bins_z >= lower_z) & (bins_z <= upper_z)
|
|
87
|
+
filtered_bins_z = bins_z[mask] - lower_z
|
|
88
|
+
filtered_average_accepter = average_accepter[mask]
|
|
89
|
+
filtered_average_donor = average_donor[mask]
|
|
90
|
+
filtered_average_sum = average_sum[mask]
|
|
91
|
+
|
|
92
|
+
combined_data = np.column_stack((filtered_bins_z, filtered_average_accepter, filtered_average_donor, filtered_average_sum))
|
|
93
|
+
|
|
94
|
+
np.savetxt("hb_distribution.dat", combined_data, header="Z\tAccepter\tDonor\tAccepter+Donor", fmt='%.5f', delimiter='\t')
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def parse_data(s):
|
|
98
|
+
return [float(x) for x in s.replace(',', ' ').split()]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def parse_r(s):
|
|
102
|
+
return [int(x) for x in s.replace(':', ' ').split()]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def parse_argument():
|
|
106
|
+
parser = argparse.ArgumentParser(description="analysis hb distribution")
|
|
107
|
+
parser.add_argument('filename', type=str, help='filename to analysis')
|
|
108
|
+
parser.add_argument('--cp2k_input_file', type=str, help='input file name of cp2k, default is "input.inp"', default='input.inp')
|
|
109
|
+
parser.add_argument('-r', type=parse_r, help='range of analysis', default=[0, -1, 1])
|
|
110
|
+
parser.add_argument('--cell', type=parse_data, help='set cell, a list of lattice, --cell x,y,z or x,y,z,a,b,c')
|
|
111
|
+
parser.add_argument('--surface', type=parse_data, help='[down_surface_z, up_surface_z]')
|
|
112
|
+
parser.add_argument('--hb_param', type=parse_data, help='[hb_distance, hb_angle], default is [3.5, 35]', default=[3.5, 35])
|
|
113
|
+
|
|
114
|
+
return parser.parse_args()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def main():
|
|
118
|
+
args = parse_argument()
|
|
119
|
+
cell = cp2k_input_parsing.get_cell(args.cp2k_input_file, args.cell)
|
|
120
|
+
|
|
121
|
+
hb_dist = Hb_distribution(args.filename, cell, args.surface, hb_distance=args.hb_param[0], hb_angle=args.hb_param[1])
|
|
122
|
+
hb_dist.run(start=args.r[0], stop=args.r[1], step=args.r[2])
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == '__main__':
|
|
126
|
+
main()
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import argparse
|
|
5
|
+
import MDAnalysis
|
|
6
|
+
from MDAnalysis import Universe
|
|
7
|
+
from MDAnalysis.analysis.base import AnalysisBase
|
|
8
|
+
from util import cp2k_input_parsing
|
|
9
|
+
import warnings
|
|
10
|
+
warnings.filterwarnings("ignore")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Hb_distribution(AnalysisBase):
|
|
14
|
+
def __init__(self, filename, cell, surface, dt=0.001, hb_distance=3.5, hb_angle=35, bin_size=0.2):
|
|
15
|
+
u = Universe(filename)
|
|
16
|
+
u.trajectory.ts.dt = dt
|
|
17
|
+
u.dimensions = cell
|
|
18
|
+
self.u = u
|
|
19
|
+
self.atomgroup = u.select_atoms("all")
|
|
20
|
+
self.hb_distance = hb_distance
|
|
21
|
+
self.hb_angle = hb_angle
|
|
22
|
+
self.bin_size = bin_size
|
|
23
|
+
self.surface = surface
|
|
24
|
+
self.frame_count = 0
|
|
25
|
+
super(Hb_distribution, self).__init__(self.atomgroup.universe.trajectory, verbose=True)
|
|
26
|
+
|
|
27
|
+
def _prepare(self):
|
|
28
|
+
bin_num = int(self.u.dimensions[2] / self.bin_size) + 2
|
|
29
|
+
self.donor = np.zeros(bin_num, dtype=np.float64)
|
|
30
|
+
|
|
31
|
+
def _append(self, hb_d):
|
|
32
|
+
bins_d = np.floor(hb_d / self.bin_size).astype(int) + 1
|
|
33
|
+
|
|
34
|
+
bins_d = bins_d[bins_d < len(self.donor)]
|
|
35
|
+
|
|
36
|
+
np.add.at(self.donor, bins_d, 1)
|
|
37
|
+
|
|
38
|
+
self.frame_count += 1
|
|
39
|
+
|
|
40
|
+
def _single_frame(self):
|
|
41
|
+
o_group = self.atomgroup.select_atoms("name O")
|
|
42
|
+
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)
|
|
43
|
+
|
|
44
|
+
o0 = o_group[o_pair[:, 0]]
|
|
45
|
+
o1 = o_group[o_pair[:, 1]]
|
|
46
|
+
|
|
47
|
+
o0h1 = self.atomgroup[o0.indices + 1]
|
|
48
|
+
o0h2 = self.atomgroup[o0.indices + 2]
|
|
49
|
+
|
|
50
|
+
angle_o0h1_o0_o1 = np.degrees(
|
|
51
|
+
MDAnalysis.lib.distances.calc_angles(o0h1.positions, o0.positions, o1.positions, box=self.u.dimensions)
|
|
52
|
+
)
|
|
53
|
+
angle_o0h2_o0_o1 = np.degrees(
|
|
54
|
+
MDAnalysis.lib.distances.calc_angles(o0h2.positions, o0.positions, o1.positions, box=self.u.dimensions)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
mid_z = (self.surface[0] + self.surface[1]) / 2
|
|
58
|
+
|
|
59
|
+
condition_d = ((angle_o0h1_o0_o1 < self.hb_angle) | (angle_o0h2_o0_o1 < self.hb_angle)) & (o0.positions[:, 2] - o1.positions[:, 2] > 0)
|
|
60
|
+
#condition_d = ((angle_o0h1_o0_o1 < self.hb_angle) | (angle_o0h2_o0_o1 < self.hb_angle)) & (((o0.positions[:, 2] < mid_z) & (o0.positions[:, 2] - o1.positions[:, 2] > 0)) | ((o0.positions[:, 2] > mid_z) & (o0.positions[:, 2] - o1.positions[:, 2] < 0)))
|
|
61
|
+
#condition_a = ((angle_o1h1_o1_o0 < self.hb_angle) | (angle_o1h2_o1_o0 < self.hb_angle)) & (((o1.positions[:, 2] < mid_z) & (o1.positions[:, 2] - o0.positions[:, 2] > 1.5)) | ((o1.positions[:, 2] > mid_z) & (o1.positions[:, 2] - o0.positions[:, 2] < -1.5)))
|
|
62
|
+
|
|
63
|
+
hb_d = (o0.positions[:, 2][condition_d] + o1.positions[:, 2][condition_d]) / 2
|
|
64
|
+
#hb_a = (o0.positions[:, 2][condition_a] + o1.positions[:, 2][condition_a]) / 2
|
|
65
|
+
|
|
66
|
+
self._append(hb_d)
|
|
67
|
+
|
|
68
|
+
def _conclude(self):
|
|
69
|
+
if self.frame_count > 0:
|
|
70
|
+
average_donor = self.donor / self.frame_count
|
|
71
|
+
|
|
72
|
+
bins_z = np.arange(len(self.donor)) * self.bin_size
|
|
73
|
+
|
|
74
|
+
lower_z, upper_z = self.surface
|
|
75
|
+
mask = (bins_z >= lower_z) & (bins_z <= upper_z)
|
|
76
|
+
filtered_bins_z = bins_z[mask] - lower_z
|
|
77
|
+
filtered_average_donor = average_donor[mask]
|
|
78
|
+
|
|
79
|
+
combined_data = np.column_stack((filtered_bins_z, filtered_average_donor))
|
|
80
|
+
|
|
81
|
+
filename = 'hb_distribution_down.dat'
|
|
82
|
+
np.savetxt(filename, combined_data, header="Z\tDonor", fmt='%.5f', delimiter='\t')
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def parse_data(s):
|
|
86
|
+
return [float(x) for x in s.replace(',', ' ').split()]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def parse_r(s):
|
|
90
|
+
return [int(x) for x in s.replace(':', ' ').split()]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def parse_argument():
|
|
94
|
+
parser = argparse.ArgumentParser(description="analysis hb distribution")
|
|
95
|
+
parser.add_argument('filename', type=str, help='filename to analysis')
|
|
96
|
+
parser.add_argument('--cp2k_input_file', type=str, help='input file name of cp2k, default is "input.inp"', default='input.inp')
|
|
97
|
+
parser.add_argument('-r', type=parse_r, help='range of analysis', default=[0, -1, 1])
|
|
98
|
+
parser.add_argument('--cell', type=parse_data, help='set cell, a list of lattice, --cell x,y,z or x,y,z,a,b,c')
|
|
99
|
+
parser.add_argument('--surface', type=parse_data, help='[down_surface_z, up_surface_z]')
|
|
100
|
+
parser.add_argument('--hb_param', type=parse_data, help='[hb_distance, hb_angle], default is [3.5, 35]', default=[3.5, 35])
|
|
101
|
+
|
|
102
|
+
return parser.parse_args()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def main():
|
|
106
|
+
args = parse_argument()
|
|
107
|
+
cell = cp2k_input_parsing.get_cell(args.cp2k_input_file, args.cell)
|
|
108
|
+
|
|
109
|
+
hb_dist = Hb_distribution(args.filename, cell, args.surface, hb_distance=args.hb_param[0], hb_angle=args.hb_param[1])
|
|
110
|
+
hb_dist.run(start=args.r[0], stop=args.r[1], step=args.r[2])
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == '__main__':
|
|
114
|
+
main()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
from ase import io, build
|
|
4
|
+
from ase.collections import g2
|
|
5
|
+
import argparse, os
|
|
6
|
+
import numpy as np
|
|
7
|
+
from util import encapsulated_ase
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_size(s):
|
|
11
|
+
if s == None:
|
|
12
|
+
return None
|
|
13
|
+
return [float(x) for x in s.replace(',', ' ').split()]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def parse_index(s):
|
|
17
|
+
return [int(x)-1 for x in s.replace(',', ' ').split()]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def parse_argument():
|
|
21
|
+
parser = argparse.ArgumentParser(description='add some adsorbate')
|
|
22
|
+
parser.add_argument('filename', type=str, help='init structure filename')
|
|
23
|
+
parser.add_argument('-m', type=str, help='atom or molecule to add')
|
|
24
|
+
parser.add_argument('--index', type=parse_index, help='index(list) of atom to add atom(top site)')
|
|
25
|
+
parser.add_argument('--offset', type=parse_size, help='adjust site, default is 0,0', default='0,0')
|
|
26
|
+
parser.add_argument('--height', type=float, help='designate vacuum of surface, default is None', default=0.0)
|
|
27
|
+
parser.add_argument('-x', type=float, help='rotate axis and angle')
|
|
28
|
+
parser.add_argument('-y', type=float, help='rotate axis and angle')
|
|
29
|
+
parser.add_argument('-z', type=float, help='rotate axis and angle')
|
|
30
|
+
parser.add_argument('-o', type=str, help='specify the output file name without suffix, default is "adsorbated.cif"', default='adsorbated.cif')
|
|
31
|
+
parser.add_argument('--coord', help='coord format', action='store_true')
|
|
32
|
+
parser.add_argument('--cell', type=parse_size, help='set xyz file cell, --cell x,y,z,a,b,c')
|
|
33
|
+
parser.add_argument('--cp2k', help='output cp2k format', action='store_true')
|
|
34
|
+
|
|
35
|
+
return parser.parse_args()
|
|
36
|
+
|
|
37
|
+
def main():
|
|
38
|
+
args = parse_argument()
|
|
39
|
+
atoms = encapsulated_ase.atoms_read_with_cell(args.filename, cell=args.cell, coord_mode=args.coord)
|
|
40
|
+
|
|
41
|
+
if len(args.offset) < 2:
|
|
42
|
+
args.offset.append(0)
|
|
43
|
+
offset = np.array(args.offset)
|
|
44
|
+
|
|
45
|
+
position_list = []
|
|
46
|
+
for atom in atoms:
|
|
47
|
+
if atom.index in args.index:
|
|
48
|
+
position_list.append(np.copy(atom.position[0:2])+offset)
|
|
49
|
+
|
|
50
|
+
if args.m in g2.names:
|
|
51
|
+
molecule = build.molecule(args.m)
|
|
52
|
+
if args.x:
|
|
53
|
+
molecule.rotate(args.x, 'x')
|
|
54
|
+
if args.y:
|
|
55
|
+
molecule.rotate(args.y, 'y')
|
|
56
|
+
if args.z:
|
|
57
|
+
molecule.rotate(args.z, 'z')
|
|
58
|
+
for position in position_list:
|
|
59
|
+
build.add_adsorbate(atoms, molecule, args.height, position=position)
|
|
60
|
+
else:
|
|
61
|
+
for position in position_list:
|
|
62
|
+
build.add_adsorbate(atoms, args.m, args.height, position=position)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if args.cp2k:
|
|
66
|
+
args.o = 'coord.xyz'
|
|
67
|
+
atoms.write(args.o, format='xyz')
|
|
68
|
+
with open(args.o, 'r') as f:
|
|
69
|
+
lines = f.readlines()
|
|
70
|
+
with open(args.o, 'w') as f:
|
|
71
|
+
f.writelines(lines[2:])
|
|
72
|
+
with open('cell.inc', 'w') as f:
|
|
73
|
+
cell = atoms.get_cell().cellpar()
|
|
74
|
+
f.write('ABC [angstrom] ' + str(cell[0]) + ' ' + str(cell[1]) + ' ' + str(cell[2]) + ' ' + '\n')
|
|
75
|
+
f.write('ALPHA_BETA_GAMMA ' + str(cell[3]) + ' ' + str(cell[4]) + ' ' + str(cell[5]) + '\n')
|
|
76
|
+
else:
|
|
77
|
+
atoms.write(args.o, format='cif')
|
|
78
|
+
|
|
79
|
+
print(os.path.abspath(args.o))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == '__main__':
|
|
83
|
+
main()
|
|
84
|
+
|