Skip to content

Commit

Permalink
Merge branch 'feature/provenance' into develop
Browse files Browse the repository at this point in the history
This adds basic support for provenance tracking to
IMP and RMF. Relates #976. Operations that alter parts
of the structure (such as reading in from a PDB file,
sampling, filtering, clustering) can now be recorded
directly in the Model itself by means of provenance
decorators, attached to atom::Hierarchy nodes. This
provenance information is also stored in RMF files.
Where possible, IMP and PMI should fill in this information
automatically.
  • Loading branch information
benmwebb committed Oct 18, 2017
2 parents 15a83fe + 992a583 commit 0f67fb8
Show file tree
Hide file tree
Showing 24 changed files with 1,263 additions and 24 deletions.
7 changes: 4 additions & 3 deletions modules/atom/include/Hierarchy.h
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ IMPATOMEXPORT bool get_is_heterogen(Hierarchy h);

//! Clone the Hierarchy
/** This method copies the Bond, Bonded, Atom,
Residue, and Domain data and the particle name to the
Residue, Domain, and provenance data and the particle name to the
new copies in addition to the Hierarchy relationships.
\relates Hierarchy
Expand All @@ -460,7 +460,7 @@ IMPATOMEXPORT Hierarchy create_clone(Hierarchy d);

//! Clone the node in the Hierarchy
/** This method copies the Atom,
Residue, Chain and Domain data and the particle name.
Residue, Chain, Domain, and provenance data and the particle name.
\relates Hierarchy
*/
Expand All @@ -470,7 +470,8 @@ IMPATOMEXPORT Hierarchy create_clone_one(Hierarchy d);
/** All bonds connecting to these atoms are destroyed as are
hierarchy links in the Hierarchy and the particles are
removed from the Model. If this particle has a parent, it is
removed from the parent.
removed from the parent. Any provenance information for this
Hierarchy is also removed.
\relates Hierarchy
*/
IMPATOMEXPORT void destroy(Hierarchy d);
Expand Down
14 changes: 14 additions & 0 deletions modules/atom/src/Hierarchy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <IMP/atom/Molecule.h>
#include <IMP/algebra/Sphere3D.h>
#include <IMP/atom/hierarchy_tools.h>
#include <IMP/core/provenance.h>
#include <IMP/algebra/geometric_alignment.h>
#include <IMP/core/rigid_bodies.h>

Expand Down Expand Up @@ -437,6 +438,11 @@ Hierarchy clone_internal(Hierarchy d,
if (Representation::get_is_setup(d.get_particle())) {
nd = Representation::setup_particle(p, Representation(d.get_particle()));
}
if (core::Provenanced::get_is_setup(d.get_particle())) {
core::Provenanced pd(d.get_particle());
core::Provenance prov = core::create_clone(pd.get_provenance());
core::Provenanced::setup_particle(p, prov);
}

if (nd == Hierarchy()) nd = Hierarchy::setup_particle(p);
using core::XYZ;
Expand Down Expand Up @@ -531,6 +537,14 @@ void destroy(Hierarchy d) {
destroy_bond(b.get_bond(b.get_number_of_bonds() - 1));
}
}
if (core::Provenanced::get_is_setup(all[i])) {
core::Provenance prov = core::Provenanced(all[i]).get_provenance();
while (prov) {
core::Provenance previous = prov.get_previous();
prov.get_model()->remove_particle(prov.get_particle_index());
prov = previous;
}
}
Hierarchy hc(all[i]);
while (hc.get_number_of_children() > 0) {
hc.remove_child(hc.get_child(hc.get_number_of_children() - 1));
Expand Down
12 changes: 10 additions & 2 deletions modules/atom/src/pdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <IMP/atom/CHARMMAtom.h>
#include <IMP/atom/CHARMMParameters.h>
#include <IMP/atom/charmm_segment_topology.h>
#include <IMP/core/provenance.h>
#include <IMP/core/Hierarchy.h>
#include <IMP/core/rigid_bodies.h>
#include <boost/algorithm/string.hpp>
Expand Down Expand Up @@ -244,11 +245,18 @@ Particle* residue_particle(Model* m, const std::string& pdb_line) {
return p;
}

Particle* chain_particle(Model* m, char chain_id) {
Particle* chain_particle(Model* m, char chain_id, std::string filename) {
Particle* p = new Particle(m);
Chain::setup_particle(p, chain_id);
p->set_name(std::string("Chain " + std::string(1, chain_id)));
Molecule::setup_particle(p);

// Set provenance of this chain
core::StructureProvenance sp
= core::StructureProvenance::setup_particle(new Particle(m),
filename, std::string(1, chain_id));
core::add_provenance(m, p->get_index(), sp);

return p;
}
}
Expand Down Expand Up @@ -350,7 +358,7 @@ Hierarchies read_pdb(std::istream& in, std::string name, Model* model,
if (cp == nullptr || chain != curr_chain) {
curr_chain = chain;
// create new chain particle
cp = chain_particle(model, chain);
cp = chain_particle(model, chain, name);
chain_name_set = false;
Hierarchy(root_p).add_child(Chain(cp));
rp = nullptr; // make sure we get a new residue
Expand Down
21 changes: 19 additions & 2 deletions modules/atom/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import IMP
import IMP.test
import IMP.atom
import IMP.core


class Tests(IMP.test.TestCase):
Expand Down Expand Up @@ -46,7 +47,7 @@ def test_read(self):
#! read PDB
mp = IMP.atom.read_pdb(self.open_input_file("input.pdb"),
m, IMP.atom.NonWaterPDBSelector())
self.assertEqual(len(m.get_particle_indexes()), 1132)
self.assertEqual(len(m.get_particle_indexes()), 1133)
# IMP.atom.show_molecular_hierarchy(mp)
IMP.atom.show(mp)
IMP.atom.add_bonds(mp)
Expand All @@ -58,7 +59,7 @@ def test_read(self):
m2 = IMP.Model()
mp = IMP.atom.read_pdb(self.open_input_file("input.pdb"),
m2, IMP.atom.CAlphaPDBSelector())
self.assertEqual(len(m2.get_particle_indexes()), 260)
self.assertEqual(len(m2.get_particle_indexes()), 261)
ps = IMP.atom.get_by_type(mp, IMP.atom.ATOM_TYPE)
self.assertEqual(len(ps), 129)
IMP.atom.add_bonds(mp)
Expand Down Expand Up @@ -218,5 +219,21 @@ def test_indexes(self):
lvs = IMP.atom.get_leaves(hp)
self.assertEqual(IMP.atom.Atom(lvs[2]).get_input_index(), 3)

def test_provenance(self):
"""Test that StructureProvenance is set"""
m = IMP.Model()
fname = self.get_input_file_name("hydrogen.pdb")
mp = IMP.atom.read_pdb(fname, m)
chains = IMP.atom.get_by_type(mp, IMP.atom.CHAIN_TYPE)
self.assertEqual(len(chains), 5)
for c in chains:
self.assertTrue(IMP.core.Provenanced.get_is_setup(c))
p = IMP.core.Provenanced(c).get_provenance()
self.assertTrue(IMP.core.StructureProvenance.get_is_setup(p))
sp = IMP.core.StructureProvenance(p)
self.assertEqual(sp.get_filename(), fname)
self.assertEqual(sp.get_chain_id(), IMP.atom.Chain(c).get_id())


if __name__ == '__main__':
IMP.test.main()
Loading

0 comments on commit 0f67fb8

Please sign in to comment.