Skip to content
This repository was archived by the owner on Jun 14, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Made `cas` field of `Identifier` optional. [#56](https://github.com/feos-org/feos-core/pull/56)
- Added type parameter to `FromSegments` and made its `from_segments` function fallible for more control over model limitations. [#56](https://github.com/feos-org/feos-core/pull/56)
- Reverted `ChemicalRecord` back to a struct that only contains the structural information (and not segment and bond counts). [#56](https://github.com/feos-org/feos-core/pull/56)
- Made `IdentifierOption` directly usable in Python using `PyO3`'s new `#[pyclass]` for fieldless enums feature. [#58](https://github.com/feos-org/feos-core/pull/58)

## [0.2.0] - 2022-04-12
### Added
Expand Down
2 changes: 2 additions & 0 deletions build_wheel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use feos_core::python::joback::PyJobackRecord;
use feos_core::python::parameter::*;
use feos_core::{Contributions, Verbosity};
use feos_core::parameter::IdentifierOption;
use pyo3::prelude::*;
use pyo3::wrap_pymodule;
use quantity::python::__PYO3_PYMODULE_DEF_QUANTITY;
Expand All @@ -17,6 +18,7 @@ pub fn feos_core(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<Contributions>()?;
m.add_class::<PyChemicalRecord>()?;
m.add_class::<PyJobackRecord>()?;
m.add_class::<IdentifierOption>()?;

m.add_wrapped(wrap_pymodule!(user_defined))?;
m.add_wrapped(wrap_pymodule!(cubic))?;
Expand Down
21 changes: 1 addition & 20 deletions src/parameter/identifier.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use super::ParameterError;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::hash::{Hash, Hasher};

/// Possible variants to identify a substance.
#[repr(C)]
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[cfg_attr(feature = "python", pyo3::pyclass)]
pub enum IdentifierOption {
Cas,
Name,
Expand All @@ -15,23 +13,6 @@ pub enum IdentifierOption {
Formula,
}

impl TryFrom<&str> for IdentifierOption {
type Error = ParameterError;

fn try_from(s: &str) -> Result<Self, Self::Error> {
let lower = s.to_lowercase();
match lower.as_str() {
"cas" => Ok(Self::Cas),
"name" => Ok(Self::Name),
"iupacname" => Ok(Self::IupacName),
"smiles" => Ok(Self::Smiles),
"inchi" => Ok(Self::Inchi),
"formula" => Ok(Self::Formula),
_ => Err(ParameterError::IdentifierNotFound(s.to_owned())),
}
}
}

/// A collection of identifiers for a chemical structure or substance.
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct Identifier {
Expand Down
59 changes: 20 additions & 39 deletions src/python/parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,27 +545,25 @@ macro_rules! impl_parameter {
/// binary_records : numpy.ndarray[float] or List[BinaryRecord]
/// A matrix of binary interaction parameters or a list
/// containing records for binary interactions.
/// search_option : str, optional, defaults to "Name"
/// Identifier that is used to search substance if binary_records is
/// passed as a list.
/// One of 'Name', 'Cas', 'Inchi', 'IupacName', 'Formula', 'Smiles'
/// search_option : IdentifierOption, optional, defaults to IdentifierOption.Name
/// Identifier that is used to search binary records.
#[staticmethod]
#[pyo3(text_signature = "(pure_records, binary_records, search_option='Name')")]
#[pyo3(text_signature = "(pure_records, binary_records, search_option)")]
fn from_records(
pure_records: Vec<PyPureRecord>,
binary_records: &PyAny,
search_option: Option<&str>,
search_option: Option<IdentifierOption>,
) -> PyResult<Self> {
let prs = pure_records.into_iter().map(|pr| pr.0).collect();
let brs = if let Ok(br) = binary_records.extract::<PyReadonlyArray2<f64>>() {
Ok(br.to_owned_array().mapv(|r| r.try_into().unwrap()))
} else if let Ok(br) = binary_records.extract::<Vec<PyBinaryRecord>>() {
let brs: Vec<_> = br.into_iter().map(|br| br.0).collect();
let io = match search_option {
Some(o) => IdentifierOption::try_from(o)?,
None => IdentifierOption::Name,
};
Ok(<$parameter>::binary_matrix_from_records(&prs, &brs, io))
Ok(<$parameter>::binary_matrix_from_records(
&prs,
&brs,
search_option.unwrap_or(IdentifierOption::Name),
))
} else {
Err(PyErr::new::<PyTypeError, _>(format!(
"Could not parse binary input!"
Expand Down Expand Up @@ -628,28 +626,21 @@ macro_rules! impl_parameter {
/// Path to file containing pure substance parameters.
/// binary_path : str, optional
/// Path to file containing binary substance parameters.
/// search_option : str, optional, defaults to "Name"
/// search_option : IdentifierOption, optional, defaults to IdentifierOption.Name
/// Identifier that is used to search substance.
/// One of 'Name', 'Cas', 'Inchi', 'IupacName', 'Formula', 'Smiles'
#[staticmethod]
#[pyo3(
text_signature = "(substances, pure_path, binary_path=None, search_option='Name')"
)]
#[pyo3(text_signature = "(substances, pure_path, binary_path, search_option)")]
fn from_json(
substances: Vec<&str>,
pure_path: String,
binary_path: Option<String>,
search_option: Option<&str>,
search_option: Option<IdentifierOption>,
) -> Result<Self, ParameterError> {
let io = match search_option {
Some(o) => IdentifierOption::try_from(o)?,
None => IdentifierOption::Name,
};
Ok(Self(Rc::new(<$parameter>::from_json(
substances,
pure_path,
binary_path,
io,
search_option.unwrap_or(IdentifierOption::Name),
)?)))
}

Expand All @@ -662,24 +653,19 @@ macro_rules! impl_parameter {
/// E.g. [(["methane", "propane"], "parameters/alkanes.json"), (["methanol"], "parameters/alcohols.json")]
/// binary_path : str, optional
/// Path to file containing binary substance parameters.
/// search_option : str, optional, defaults to "Name"
/// search_option : IdentifierOption, optional, defaults to IdentifierOption.Name
/// Identifier that is used to search substance.
/// One of 'Name', 'Cas', 'Inchi', 'IupacName', 'Formula', 'Smiles'
#[staticmethod]
#[pyo3(text_signature = "(input, binary_path=None, search_option='Name')")]
fn from_multiple_json(
input: Vec<(Vec<&str>, &str)>,
binary_path: Option<&str>,
search_option: Option<&str>,
search_option: Option<IdentifierOption>,
) -> Result<Self, ParameterError> {
let io = match search_option {
Some(o) => IdentifierOption::try_from(o)?,
None => IdentifierOption::Name,
};
Ok(Self(Rc::new(<$parameter>::from_multiple_json(
&input,
binary_path,
io,
search_option.unwrap_or(IdentifierOption::Name),
)?)))
}

Expand Down Expand Up @@ -738,30 +724,25 @@ macro_rules! impl_parameter_from_segments {
/// Path to file containing segment parameters.
/// binary_path : str, optional
/// Path to file containing binary segment-segment parameters.
/// search_option : str, optional, defaults to "Name"
/// search_option : IdentifierOption, optional, defaults to IdentifierOption.Name
/// Identifier that is used to search substance.
/// One of 'Name', 'Cas', 'Inchi', 'IupacName', 'Formula', 'Smiles'
#[staticmethod]
#[pyo3(
text_signature = "(substances, pure_path, segments_path, binary_path=None, search_option='Name')"
text_signature = "(substances, pure_path, segments_path, binary_path, search_option)"
)]
fn from_json_segments(
substances: Vec<&str>,
pure_path: String,
segments_path: String,
binary_path: Option<String>,
search_option: Option<&str>,
search_option: Option<IdentifierOption>,
) -> Result<Self, ParameterError> {
let io = match search_option {
Some(o) => IdentifierOption::try_from(o)?,
None => IdentifierOption::Name,
};
Ok(Self(Rc::new(<$parameter>::from_json_segments(
&substances,
pure_path,
segments_path,
binary_path,
io,
search_option.unwrap_or(IdentifierOption::Name),
)?)))
}
}
Expand Down