Commit 1c36fb34 authored by NOEL Philippe's avatar NOEL Philippe

add tests and doc for selection atoms

parent e1f92a6c
...@@ -229,6 +229,25 @@ impl<'a> Protein { ...@@ -229,6 +229,25 @@ impl<'a> Protein {
/// Select atom from a pattern and return a new protein structure /// Select atom from a pattern and return a new protein structure
/// ///
/// The pattern could use keywords "Chain", "Resid" or "Backbone" (keyword are not case sensitive)
///
/// ## "Chain"
/// The Chain keyword is used to select chain. It must be follow by one or two chain names separate by the "to" keyword.
/// The chain name is case sensitive.
/// examples:
/// "Chain A" will select only the Chain A.
/// "Chain A to D" will select chains A, B, C and D.
///
/// ## "Resid"
/// The Resid keyword is used to select residues. It must be follow by one or two chain names separate by the "to" keyword.
/// In case where the protein has multiple chains, the Resid will return residue(s) for all chains.
/// examples:
/// "Resid 1" will select only the residue 1 of each chain
/// "Resid 12 to 50" will select residues 12, 13, .., 50 for all chains
///
/// ## "Backbone"
/// The Backbone keyword is used to select atoms in the backbone for each residues. It don't take parameters.
///
/// TODO: The methode is idiot and need to be improve. /// TODO: The methode is idiot and need to be improve.
/// ex: don't parse the chain if it's not selected /// ex: don't parse the chain if it's not selected
/// ///
...@@ -247,7 +266,7 @@ impl<'a> Protein { ...@@ -247,7 +266,7 @@ impl<'a> Protein {
let c_res = residue.res_num; let c_res = residue.res_num;
for atom in &residue.lst_atom { for atom in &residue.lst_atom {
if selection_atom::atom_match(&select, c_chain, c_res) { if selection_atom::atom_match(&select, c_chain, c_res) {
n_prot.update_protein(c_chain, residue.name.clone(), c_res, atom.name.clone(), atom.number, atom.coord) n_prot.update_protein(c_chain, residue.name.clone(), c_res, atom.name.clone(), atom.number, atom.coord);
} }
} }
} }
......
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Select { pub enum Select {
Chainid(char, char), Chain(char, char),
Resid(usize, usize), Resid(usize, usize),
Backbone, Backbone,
} }
...@@ -11,6 +11,8 @@ pub enum Select { ...@@ -11,6 +11,8 @@ pub enum Select {
/// ///
/// ///
fn parse_options_int(opt: &[&str]) -> Option<[usize; 2]> { fn parse_options_int(opt: &[&str]) -> Option<[usize; 2]> {
// if the len is 1 mean that the request is like "Resid 1".
// return Some(1, 1)
if opt.len() == 1 { if opt.len() == 1 {
match opt[0].parse() { match opt[0].parse() {
Ok(v) => return Some([v, v]), Ok(v) => return Some([v, v]),
...@@ -36,6 +38,8 @@ fn parse_options_int(opt: &[&str]) -> Option<[usize; 2]> { ...@@ -36,6 +38,8 @@ fn parse_options_int(opt: &[&str]) -> Option<[usize; 2]> {
/// TODO: Remove this one because it's a doublon of parse_option_int /// TODO: Remove this one because it's a doublon of parse_option_int
/// ///
fn parse_options_char(opt: &[&str]) -> Option<[char; 2]> { fn parse_options_char(opt: &[&str]) -> Option<[char; 2]> {
// if the len is 1 mean that the request is like "Chain A".
// return Some(1, 1)
if opt.len() == 1 { if opt.len() == 1 {
match opt[0].parse() { match opt[0].parse() {
Ok(v) => return Some([v, v]), Ok(v) => return Some([v, v]),
...@@ -75,7 +79,7 @@ pub fn parse_select(select: &str) -> Option<Select> { ...@@ -75,7 +79,7 @@ pub fn parse_select(select: &str) -> Option<Select> {
} }
"chain" => { "chain" => {
match parse_options_char(&sel[1..]) { match parse_options_char(&sel[1..]) {
Some(x) => return Some(Select::Chainid(x[0], x[1])), Some(x) => return Some(Select::Chain(x[0], x[1])),
None => return None, None => return None,
} }
} }
...@@ -89,7 +93,7 @@ pub fn parse_select(select: &str) -> Option<Select> { ...@@ -89,7 +93,7 @@ pub fn parse_select(select: &str) -> Option<Select> {
pub fn atom_match(sel: &Select, chain: char, res_id: u64) -> bool { pub fn atom_match(sel: &Select, chain: char, res_id: u64) -> bool {
match sel { match sel {
Select::Chainid(x, y) => { Select::Chain(x, y) => {
if chain >= *x && chain <= *y { if chain >= *x && chain <= *y {
return true return true
} else { } else {
...@@ -110,12 +114,29 @@ pub fn atom_match(sel: &Select, chain: char, res_id: u64) -> bool { ...@@ -110,12 +114,29 @@ pub fn atom_match(sel: &Select, chain: char, res_id: u64) -> bool {
} }
#[test] #[test]
fn test_fn(){ fn test_parse_select() {
assert_eq!(None, parse_select("")); assert_eq!(None, parse_select(""));
assert_eq!(Some(Select::Resid(5, 96)), parse_select("resid 5 to 96")); assert_eq!(Some(Select::Resid(5, 96)), parse_select("resid 5 to 96"));
assert_eq!(None, parse_select("resid 5 t 96")); assert_eq!(None, parse_select("resid 5 t 96"));
assert_eq!(Some(Select::Backbone), parse_select("BaCkbone")); assert_eq!(Some(Select::Backbone), parse_select("BaCkbone"));
assert_eq!(Some(Select::Chainid('B', 'B')), parse_select("chain B")); assert_eq!(Some(Select::Chain('B', 'B')), parse_select("chain B"));
assert_eq!(Some(Select::Chainid('B', 'C')), parse_select("chain B to C")); assert_eq!(Some(Select::Chain('B', 'C')), parse_select("chain B to C"));
assert_eq!(None, parse_select("resid 3 to TO")); assert_eq!(None, parse_select("resid 3 to TO"));
}
#[test]
fn test_atom_search_Chain() {
assert!(atom_match(&Select::Chain('B', 'C'), 'C', 15));
assert!(!atom_match(&Select::Chain('A', 'B'), 'C', 15));
assert!(atom_match(&Select::Chain('1', '4'), '2', 15));
//assert!(atom_match(&Select::Chain('A', '9'), '2', 15));
assert!(atom_match(&Select::Chain('A', 'a'), 'Z', 15));
assert!(!atom_match(&Select::Chain('A', 'a'), 'd', 15));
}
#[test]
fn test_atom_search_resid() {
assert!(atom_match(&Select::Resid(1, 105), 'A', 15));
assert!(!atom_match(&Select::Resid(1, 105), 'A', 0));
assert!(atom_match(&Select::Resid(1, 105), 'A', 105));
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment