def group(self, ifes, inters): """Group chains from the same pdb into structured units. This will place structured chains into their own groups, but allow a non structured chain to be grouped with it if present. Non structured chains that have no interacting partners (singleton unstructured chains) are also present in the output. :ifes: A list of chain objects from nr.chains.Info.load. :interactions: A dictionary of interactions of the form produced by nr.chains.Info.cross_chain_interactions. :returns: A list of ife groups formed from the given ifes and interactions. """ groups = {} for ife in ifes: groups[ife.id] = IfeGroup(ife) same, rest = self.parition_interactions(ifes, inters) # If both groups are structured or not structured and the ifes can be # joined then they should be merged into one group and both ifes should # reflect this. Basically connections between these types of ifes # are transitive. for ife1, ife2 in self.joinable(same, ifes): current = groups[ife1.id] current.merge(groups[ife2.id]) linked = set(groups[ife1.id].chains() + groups[ife2.id].chains()) for ife in linked: groups[ife.id] = current # Here if we are merging an unstructured into a structured we only # should update the structured one, the unstructured chain may be part # of many different structured ifes. Basically connections are not # transitive across types of groups. structured = [ife for ife in ifes if ife.is_structured] unstructured = [ife for ife in ifes if not ife.is_structured] strip = set() for ife1, ife2 in self.joinable(rest, structured, unstructured): groups[ife1.id].merge(groups[ife2.id]) strip.add(groups[ife2.id].id) # There will be duplicated groups so we must get only the unique ones. # We sort to ensure that the ordering is consistent. return sorted(set(g for g in groups.values() if g.id not in strip))
def test_uses_structured_only_in_id(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=5, model=10), IfeChain(pdb='0111', chain='C', internal=0, model=0), IfeChain(pdb='0111', chain='D', internal=6, model=10)) self.assertEquals('0111|10|D+0111|10|A', val.id)
def test_has_an_id(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=5, model=10), IfeChain(pdb='0111', chain='C', internal=0, model=10)) self.assertEquals('0111|10|A', val.id)
def test_knows_how_many_chains_in_it(self): val = IfeGroup(IfeChain(chain='A', internal=4), IfeChain(chain='B', internal=0)) self.assertEquals(2, len(val))
def test_knows_if_structured_if_has_no_structured_chain(self): val = IfeGroup(IfeChain(chain='A', internal=4), IfeChain(chain='B', internal=0)) self.assertFalse(val.is_structured)
def test_uses_name_to_tiebreak_integral_chain(self): val = IfeGroup(IfeChain(pdb='0111', chain='C', length=10, internal=0, model=3), IfeChain(pdb='0111', chain='A', length=10, internal=0, model=3)) self.assertEquals('0111|3|A', val.integral.id)
def test_uses_length_as_tiebreak(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', length=10, internal=50, model=10), IfeChain(pdb='0111', chain='C', length=50, internal=50, model=10)) self.assertEquals('0111|10|C', val.integral.id)
def test_uses_most_bp_chain_as_integral(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=4, model=1), IfeChain(pdb='0111', chain='C', internal=0, model=1)) self.assertEquals('0111|1|A', val.integral.id)
def test_getattr_complains_if_missing_key(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=4, full_length=5)) self.assertRaises(AttributeError, lambda: val.bob)
def test_dispatches_model_to_integral(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=100, full_length=5, model=2), IfeChain(pdb='0111', chain='B', internal=10, full_length=5, model=10)) self.assertEquals(2, val.model)
def test_dispatches_bps_to_integral(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=100, full_length=5, bps=120), IfeChain(pdb='0111', chain='B', internal=10, full_length=5, bps=12)) self.assertEquals(120, val.bps)
def test_dispatches_pdb_to_integral(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=4, full_length=5)) self.assertEquals('0111', val.pdb)
def test_duplicate_additions_do_nothing(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=4, model=4), IfeChain(pdb='0111', chain='C', internal=0, model=4)) val.add(IfeChain(pdb='0111', chain='A', internal=4, model=4)) self.assertEquals('0111|4|A+0111|4|C', val.id)
def test_if_no_structured_in_id_uses_all(self): val = IfeGroup(IfeChain(pdb='0111', chain='A', internal=2, model=1), IfeChain(pdb='0111', chain='C', internal=0, model=2), IfeChain(pdb='0111', chain='D', internal=2, model=3)) self.assertEquals('0111|1|A+0111|3|D+0111|2|C', val.id)