CyFES 3.5
Cython Based Fast FES Calculation Toolkit.
License: MIT

# CyFES：GPU加速高性能数据透视工具

<img alt="Hex.pm" src="https://img.shields.io/badge/License-MIT-blue">
<img alt="Hex.pm" src="https://img.shields.io/badge/Language-Python-orange">
<img alt="Hex.pm" src="https://img.shields.io/badge/Language-Cython-orange">
<img alt="Hex.pm" src="https://img.shields.io/badge/Language-CUDA_C++-orange">
<img alt="Hex.pm" src="https://img.shields.io/badge/Device-GPU-green">

![](./docs/fes01.png)

## 介绍
这是一个使用Cython+CUDA+Python编写的高性能FES计算软件，可以用于加速数据透视的计算：

$$
E(x)=-kT\log\left(\frac{\sum_{j=1}^Ne^{\frac{V_j}{kT}}e^{-\frac{(x-n_j)^2}{2\sigma^2}}}{N\Pi_i\sqrt{2\pi}\sigma_i}\right)
$$

## 安装
### pip安装
本项目可以直接使用pip进行安装：
```bash
$ python3 -m pip install cyfes --user --upgrade -i https://pypi.org/simple
```

### 源码安装
首先将本仓库clone到本地：
```bash
$ git clone https://gitee.com/dechin/cy-fes.git && cd cy-fes/
```
然后直接运行`setup.py`进行安装：
```bash
$ python3 -m pip install .
```

### 安装测试
在本仓库的test路径下存放了一个测试用例，用于测试cyfes是否安装成功。用户可以直接简单的运行：
```bash
$ python3 tests/test_path_fes.py 
[0.00902854 0.         0.09338432 0.02065182]
[0.03961432 0.         0.01514649 0.02259541]
[0.00129778 0.         0.02988457 0.0869869 ]
[0.01712827 0.01378975 0.         0.02229569]
[0.0114323  0.03356422 0.         0.0328276 ]
```
若输出为多个数组，则表示安装成功。也可以使用单元测试运行，但是这需要在本地先安装`pytest`：
```bash
$ python3 -m pip install pytest
```
然后直接在仓库的根目录下运行：
```bash
$ py.test
============================ test session starts =============================
platform linux -- Python 3.7.5, pytest-7.4.4, pluggy-1.2.0
rootdir: /home/cy-fes
collected 5 items                                                            

tests/test_path_fes.py .....                                           [100%]

============================= 5 passed in 14.23s =============================
```
没有报错，则表示安装成功。

## 使用方法
在安装成功后，可以直接在Python脚本中调用：
```python
import numpy as np
from cyfes import PathFES
np.random.seed(0)

def test_path_fes():
    atoms = 4
    cvs = 10000
    crd = np.random.random((atoms, 3))
    cv = np.random.random((cvs, 3))
    bw = np.random.random(3)
    bias = np.random.random(cvs)-1

    fes = np.asarray(PathFES(crd, cv, bw, bias))
    print (fes)

if __name__ == '__main__':
    test_path_fes()
```

还可以使用命令行模式：
```bash
$ python3 -m cyfes --help
usage: __main__.py [-h] [-i I] [-ic IC] [-ib IB] [-s S] [-e E] [-g G] [-o O]
                   [-no_bias NO_BIAS] [-f32 F32] [-sigma SIGMA]
                   [-device DEVICE]

optional arguments:
  -h, --help        show this help message and exit
  -i I              Set the input record file path.
  -ic IC            Set the cv index of input record file. Default: 0,1,2
  -ib IB            Set the bias index of input record file. Default: 3
  -s S              CV length. Default: None
  -e E              Edge length. Default: 1.0
  -g G              Grid numbers. Default: 10,10,10
  -o O              Set the output FES file path.
  -no_bias NO_BIAS  Do not use the bias from input file. Default: false
  -f32 F32          Use float32. Default: false
  -sigma SIGMA      Sigma value when calculating FES. Default: 0.3
  -device DEVICE    Set the device ids separated with commas. Default: 0
```
假如我们有一个三维的CV，那么最简单的运行方式为：
```bash
$ python3 -m cyfes -i /home/Data/xyz_bias.txt -o ./work_dir/z.cub
```
那么最后产生的文件内容为：
```bash
$ head -n 10 work_dir/z.cub
Generated by CyFES
Total	1000	grids
1	21.6622	19.8498	42.3652
10	6.40465	0	0
10	0	7.02147	0
10	0	0	6.33118
1	1.000000	53.6854	54.9571	74.0211
450	450	450	450	450	450	
450	450	450	450	450	450	
450	450	70.0855	70.848	450	450	
```
该cube格式的文件可以在支持的软件（如VMD）中进行可视化操作。

## 已知问题
1. 使用numpy==1.22.2的版本中会出现`ImportError: numpy.core.multiarray failed to import`问题。解决方案：升级numpy版本：`python3 -m pip install numpy --upgrade`。
2. 执行`python3 -m cyfes --help`报错`ModuleNotFoundError: No module named 'cyfes.wrapper'`，这是因为执行命令的目录下存在名为`cyfes`的文件夹，需要切换执行命令的位置。
3. 使用cyfes出现`Segmentation fault`段错误问题，是因为找不到编译好的动态链接库文件，大概率是系统环境下权限不足，没有site路径的权限，可以使用如下脚本进行检查：
```python
# check_dynamics.py
import os
import site
from pathlib import Path

site_path = Path(site.getsitepackages()[0])
site_file_path = site_path.parent.parent.parent / 'cyfes' / 'libcufes.so'
site_dynamics_path = str(site_file_path)

user_site_path = Path(site.USER_SITE)
user_file_path = user_site_path.parent.parent.parent / 'cyfes' / 'libcufes.so'
user_dynamics_path = str(user_file_path)

if not os.path.exists(site_dynamics_path) and not os.path.exists(user_dynamics_path):
    print ('Check dynamics complete, no libcufes.so file founded!')
else:
    print ('Installation of CyFES success!')
```
使用python3运行该脚本，即可判断动态链接库是否被正确安装。