Skip to content

Commit

Permalink
Packaging (#12)
Browse files Browse the repository at this point in the history
* Add packaging instructions

* Add ./cargo to gitignore

* Add build instructions

* Separate API

* Add README
  • Loading branch information
t-young31 authored Jun 2, 2022
1 parent 4f1ea0c commit 3aeb2aa
Show file tree
Hide file tree
Showing 23 changed files with 192 additions and 95 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
test:
name: Test
env:
PROJECT_NAME_UNDERSCORE: mors
PROJECT_NAME_UNDERSCORE: optrs
CARGO_INCREMENTAL: 0
RUSTFLAGS: -Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort
RUSTDOCFLAGS: -Cpanic=abort
Expand Down
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/target
**target/
**.DS_Store
**/.idea
**build
/Cargo.lock
**Cargo.lock
.env/
examples/*opt.xyz
.cargo/
api/examples/*opt.xyz
15 changes: 5 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
[package]
name = "mors"
name = "optrs"
version = "0.1.0"
edition = "2021"
authors = ["Tom Young"]


[lib]
name = "mors"
crate-type = ["cdylib"]
[[bin]]
name = "optrs"
path = "src/main.rs"

[dependencies]
clap = { version = "3.1.6", features = ["derive"] }
log = "0.4"
rand = "0.8.5"
pyo3 = { version = "0.16.3", features = ["extension-module"] }


[profile.release]
debug = 1
pyo3 = { version = "0.16.5", features = ["extension-module"] }
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,33 @@
mors
[![Test](https://github.com/t-young31/opt-rs/actions/workflows/test.yml/badge.svg)](https://github.com/t-young31/opt-rs/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/t-young31/mors/branch/main/graph/badge.svg?token=5KTYG2WJ9L)](https://codecov.io/gh/t-young31/mors)

![alt text](src/common/logo.png)

**optrs** is a lightweight molecular mechanics optimisation code written in rust.

***
### Installation
Install the binary with

```bash
pip install optrs
```

or the [Python API](https://github.com/t-young31/opt-rs/tree/main/api).

***
### Usage
Optimise a molecule provided as a [.xyz](https://en.wikipedia.org/wiki/XYZ_file_format) file

```bash
optrs molecule.xyz
```

which will generate _opt.xyz_ in working directory.
[API examples](https://github.com/t-young31/opt-rs/tree/main/api/examples).

***
### Features
- [UFF](https://doi.org/10.1021/ja00051a040) forcefield
- [RB](https://doi.org/10.1002/anie.202011941) forcefield
- 3D structure generation
- Steepest decent optimisation
16 changes: 16 additions & 0 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "optrs"
version = "0.1.0"
edition = "2021"
authors = ["Tom Young"]

[lib]
path = "../src/lib.rs"
name = "optrs"
crate-type = ["cdylib"]

[dependencies]
clap = { version = "3.1.6", features = ["derive"] }
log = "0.4"
rand = "0.8.5"
pyo3 = { version = "0.16.5", features = ["extension-module"] }
8 changes: 8 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### Python API

***
Install with

```bash
pip install optrs-api
```
4 changes: 2 additions & 2 deletions examples/a_optimise.py → api/examples/a_optimise.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Optimise a structure using the default (UFF) forcefield:"""
import mors
import optrs

mol = mors.Molecule.from_xyz_file("metallocage.xyz")
mol = optrs.Molecule.from_xyz_file("metallocage.xyz")
mol.optimise()
mol.write_xyz_file("metallocage_opt.xyz")
4 changes: 2 additions & 2 deletions examples/b_build.py → api/examples/b_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
Molecular structures can be built from only atomic symbols and the bond order
matrix (defined between all pairs of atoms):
"""
import mors
import optrs

mol = mors.Molecule.from_atomic_symbols(["O", "H", "H"])
mol = optrs.Molecule.from_atomic_symbols(["O", "H", "H"])

mol.set_bond_orders([0., 1., 1.,
1., 0., 0.,
Expand Down
4 changes: 2 additions & 2 deletions examples/c_coordinates.py → api/examples/c_coordinates.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Atomic coordinates can be set from the Python API
"""
import mors
import optrs

try:
import autode as ade
Expand All @@ -14,7 +14,7 @@
symbols = ade.Molecule('metallocage.xyz').atomic_symbols
coordinates = ade.Molecule('metallocage.xyz').coordinates.flatten().tolist()

mol = mors.Molecule.from_atomic_symbols(symbols)
mol = optrs.Molecule.from_atomic_symbols(symbols)
mol.set_coordinates(coordinates)

mol.generate_connectivty() # Then build the connectivity (bonds, angles etc.),
Expand Down
File renamed without changes.
5 changes: 4 additions & 1 deletion pyproject.toml → api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ requires = ["maturin>=0.12,<0.13"]
build-backend = "maturin"

[project]
name = "mors"
name = "optrs-api"
requires-python = ">=3.6"
dependencies = [
"optrs",
]
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
Expand Down
20 changes: 20 additions & 0 deletions dev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
### Development documentation

#### Packaging
Linux wheels are built using the maturin manylinux docker container with

```bash
docker run -it --rm -v $(pwd):/io --entrypoint bash ghcr.io/pyo3/maturin:main
maturin build --release --strip --interpreter python3.7 python3.8 python3.9 python3.10
```

while macOS wheels are generated with
```bash
./dev/build_mac_wheels.sh
```

Upload to TestPyPI first with
```bash
python3 -m twine upload --repository testpypi target/wheels/*
```

9 changes: 9 additions & 0 deletions dev/build_mac_wheels.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash -l

for minor_version in {8..10}; do
conda create -n test "python=3.$minor_version" --yes
conda activate test
pip install maturin
maturin build --release --strip --universal2
conda deactivate
done
66 changes: 66 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use clap::Parser;

use crate::molecule::Molecule;
use crate::ff::forcefield::Forcefield;
use crate::ff::rb::core::RB;
use crate::ff::uff::core::UFF;


#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct CommandLineArguments {
#[clap(index = 1)]
xyz_filename: String,

#[clap(short, long, default_value="UFF")]
forcefield: String,
}


pub fn run(args: CommandLineArguments) {

let mut mol = Molecule::from_xyz_file(&args.xyz_filename);

match args.forcefield.as_str() {
"UFF" => mol.optimise(&mut UFF::new(&mol)),
"RB" => mol.optimise(&mut RB::new(&mol)),
_ => panic!("Cannot set a forcefield. Unknown type")
}

mol.write_xyz_file("opt.xyz");
}



/*
/$$ /$$
| $$ | $$
/$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$
|_ $$_/ /$$__ $$ /$$_____/|_ $$_/ /$$_____/
| $$ | $$$$$$$$| $$$$$$ | $$ | $$$$$$
| $$ /$$| $$_____/ \____ $$ | $$ /$$\____ $$
| $$$$/| $$$$$$$ /$$$$$$$/ | $$$$//$$$$$$$/
\___/ \_______/|_______/ \___/ |_______/
*/

#[cfg(test)]
mod tests{

use super::*;
use crate::utils::*;

#[test]
fn test_simple_cli(){

let filename = "h2_tscli.xyz";
print_dihydrogen_xyz_file(filename);

let args = CommandLineArguments{xyz_filename: filename.to_string(),
forcefield: "UFF".to_string()};
run(args);

remove_file_or_panic(filename);
remove_file_or_panic("opt.xyz")
}

}
Binary file added src/common/logo.key
Binary file not shown.
Binary file added src/common/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/ff/rb/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::coordinates::{Point, Vector3D};
use crate::ff::bonds::HarmonicBond;
use crate::ff::forcefield::EnergyFunction;
use crate::ff::nonbonded::RepulsiveInverseDistance;
use crate::Molecule;
use crate::molecule::Molecule;


#[derive(Default)]
Expand Down
2 changes: 1 addition & 1 deletion src/ff/uff/atom_typing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::f64::consts::PI;
use crate::atoms::{Atom, AtomicNumber};
use crate::connectivity::bonds::BondOrder;
use crate::coordinates::angle_value;
use crate::Molecule;
use crate::molecule::Molecule;

/// See Table 1 in J. Am. Chem. Soc. 1992, 114, 25, 10024–10035
/// https://doi.org/10.1021/ja00051a040
Expand Down
2 changes: 1 addition & 1 deletion src/io/xyz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::io::{self, BufRead, Write};
use log::{info, warn};
use crate::atoms::AtomicNumber;
use crate::coordinates::Point;
use crate::Molecule;
use crate::molecule::Molecule;


#[derive(Default)]
Expand Down
10 changes: 9 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ mod opt;
mod utils;
mod pairs;
mod coordinates;
mod cli;


use clap::Parser;
use crate::cli::{run, CommandLineArguments};


fn main() { run(CommandLineArguments::parse()) }


/// A Python module implemented in Rust.
#[pymodule]
fn mors(_py: Python, m: &PyModule) -> PyResult<()> {
fn optrs(_py: Python, m: &PyModule) -> PyResult<()> {

m.add_class::<PyMoleculeWrapper>()?;
Ok(())
Expand Down
69 changes: 3 additions & 66 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,73 +17,10 @@ mod opt;
mod utils;
mod pairs;
mod coordinates;
mod cli;

use clap::Parser;

use crate::molecule::Molecule;
use crate::ff::forcefield::Forcefield;
use crate::ff::rb::core::RB;
use crate::ff::uff::core::UFF;
use crate::cli::{run, CommandLineArguments};


#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct CommandLineArguments {
#[clap(index = 1)]
xyz_filename: String,

#[clap(short, long, default_value="UFF")]
forcefield: String,
}


fn run(args: CommandLineArguments) {

let mut mol = Molecule::from_xyz_file(&args.xyz_filename);

match args.forcefield.as_str() {
"UFF" => mol.optimise(&mut UFF::new(&mol)),
"RB" => mol.optimise(&mut RB::new(&mol)),
_ => panic!("Cannot set a forcefield. Unknown type")
}

mol.write_xyz_file("opt.xyz");
}


fn main(){ run(CommandLineArguments::parse()) }



/*
/$$ /$$
| $$ | $$
/$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$
|_ $$_/ /$$__ $$ /$$_____/|_ $$_/ /$$_____/
| $$ | $$$$$$$$| $$$$$$ | $$ | $$$$$$
| $$ /$$| $$_____/ \____ $$ | $$ /$$\____ $$
| $$$$/| $$$$$$$ /$$$$$$$/ | $$$$//$$$$$$$/
\___/ \_______/|_______/ \___/ |_______/
*/

#[cfg(test)]
mod tests{

use super::*;
use crate::utils::*;

#[test]
fn test_simple_cli(){

let filename = "h2_tscli.xyz";
print_dihydrogen_xyz_file(filename);

let args = CommandLineArguments{xyz_filename: filename.to_string(),
forcefield: "UFF".to_string()};
run(args);

remove_file_or_panic(filename);
remove_file_or_panic("opt.xyz")
}

}
fn main() { run(CommandLineArguments::parse()) }
Loading

0 comments on commit 3aeb2aa

Please sign in to comment.