Skip to content

Commit

Permalink
improve logic to collect passive and handle missing resnumbers
Browse files Browse the repository at this point in the history
  • Loading branch information
rvhonorato committed Aug 13, 2024
1 parent 24238f0 commit 4bab4b9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/air.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl Air {
// tbl.push_str(&header);

// TODO: Refactor this logic to also collect wildcards
let target_res = interactor::collect_resnums(partners);
let target_res = interactor::collect_residues(partners);
let block = interactor.create_block(target_res);
tbl.push_str(&block);
}
Expand Down
90 changes: 61 additions & 29 deletions src/interactor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ impl Interactor {
&self.passive
}

pub fn wildcard(&self) -> &str {
match &self.wildcard {
Some(wildcard) => wildcard,
None => "",
}
}

pub fn target(&self) -> &HashSet<u16> {
&self.target
}
Expand Down Expand Up @@ -211,32 +218,27 @@ impl Interactor {
self.passive_atoms = Some(atoms);
}

pub fn create_block(&self, target_res: Vec<(&str, &i16)>) -> String {
pub fn create_block(&self, passive_res: Vec<PassiveResidues>) -> String {
let mut block = String::new();
let mut _active: Vec<i16> = self.active().iter().cloned().collect();
_active.sort();

// Sort the target residues by residue number
let mut target_res: Vec<(&str, &i16)> = target_res.clone();
target_res.sort_by(|a, b| a.1.cmp(b.1));
let mut passive_res: Vec<PassiveResidues> = passive_res.clone();
passive_res.sort_by(|a, b| a.res_number.cmp(&b.res_number).reverse());

// Check if need to use multiline separation
let multiline = target_res.len() > 1;
let multiline = passive_res.len() > 1;

for resnum in _active {
let atom_str = format_atom_string(&self.active_atoms);
let binding = "".to_string();
let wildcard_str = match &self.wildcard {
Some(wildcard) => wildcard,
None => &binding,
};

let mut assign_str = format!(
"assign ( resid {} and segid {}{} {} )",
resnum,
self.chain(),
atom_str,
wildcard_str
&self.wildcard()
);

if multiline {
Expand All @@ -245,40 +247,42 @@ impl Interactor {

block.push_str(assign_str.as_str());

let res_lines: Vec<String> = target_res
// panic!("Target res: {:?}", target_res);

let res_lines: Vec<String> = passive_res
.iter()
.enumerate()
.map(|(index, res)| {
let passive_atom_str = format_atom_string(&self.passive_atoms);

let binding = "".to_string();
let wildcard_str = match &self.wildcard {
Some(wildcard) => wildcard,
None => &binding,
};
println!("Wildcard: {}", wildcard_str);
println!("res_lines: {:?}", &self);

let mut res_line = String::new();
if multiline {
res_line.push_str(
format!(
" ( resid {} and segid {}{} {} )\n",
res.1, res.0, passive_atom_str, wildcard_str
" ( {} segid {}{} {} )\n",
res.res_number
.map_or(String::new(), |num| format!("resid {} and ", num)),
res.chain_id,
passive_atom_str,
res.wildcard
)
.as_str(),
);
} else {
res_line.push_str(
format!(
" ( resid {} and segid {}{} {} )",
res.1, res.0, passive_atom_str, wildcard_str
" ( {} segid {}{} {} )",
res.res_number
.map_or(String::new(), |num| format!("resid {} and ", num)),
res.chain_id,
passive_atom_str,
res.wildcard
)
.as_str(),
);
}

if index != target_res.len() - 1 {
if index != passive_res.len() - 1 {
res_line.push_str(" or\n");
}
res_line
Expand All @@ -302,11 +306,39 @@ impl Interactor {
}
}

pub fn collect_resnums(interactors: Vec<&Interactor>) -> Vec<(&str, &i16)> {
let mut resnums = Vec::<(&str, &i16)>::new();
#[derive(Debug, Clone)]
pub struct PassiveResidues<'a> {
chain_id: &'a str,
res_number: Option<i16>,
wildcard: &'a str,
}

pub fn collect_residues(interactors: Vec<&Interactor>) -> Vec<PassiveResidues> {
let mut resnums = Vec::new();
for interactor in interactors {
resnums.extend(interactor.active().iter().map(|x| (interactor.chain(), x)));
resnums.extend(interactor.passive().iter().map(|x| (interactor.chain(), x)));
let active = interactor.active().iter().map(|&x| PassiveResidues {
chain_id: interactor.chain(),
res_number: Some(x),
wildcard: interactor.wildcard(),
});

let passive = interactor.passive().iter().map(|&x| PassiveResidues {
chain_id: interactor.chain(),
res_number: Some(x),
wildcard: interactor.wildcard(),
});

resnums.extend(active);
resnums.extend(passive);

// If both active and passive are empty, add a single ResidueIdentifier with None as res_number
if interactor.active().is_empty() && interactor.passive().is_empty() {
resnums.push(PassiveResidues {
chain_id: interactor.chain(),
res_number: None,
wildcard: interactor.wildcard(),
});
}
}
resnums
}
Expand Down Expand Up @@ -357,7 +389,7 @@ mod tests {
interactor.set_active(vec![1]);
interactor.set_chain("A");

let observed = interactor.create_block(vec![("B", &2), ("B", &3)]);
let observed = interactor.create_block(vec![("B", &2, Some("")), ("B", &3, Some(""))]);

let block = "assign ( resid 1 and segid A )\n (\n ( resid 2 and segid B )\n or\n ( resid 3 and segid B )\n ) 2.0 2.0 0.0\n\n";

Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,13 @@ fn generate_z_restraints(
interactor_i.set_chain("A");
interactor_i.set_active(vec![*resnum as i16]);
interactor_i.set_active_atoms(vec!["CA".to_string()]);
interactor_i.set_passive_atoms(vec!["SHA".to_string()]);
interactor_i.set_lower_margin(0.0);
interactor_i.set_upper_margin(0.0);
interactor_i.set_target_distance(2.0);

interactor_j.set_chain("S");
interactor_j.set_active_atoms(vec!["SHA".to_string()]);
interactor_j.set_wildcard(format!("attr z gt {:?}", z).as_str());
interactor_j.set_wildcard(format!("attr z gt {:.2}", z).as_str());

interactors.push(interactor_i);
interactors.push(interactor_j);
Expand Down

0 comments on commit 4bab4b9

Please sign in to comment.