Skip to content

Commit

Permalink
Merge pull request #445 from 0ncorhynchus/fix_offlattice
Browse files Browse the repository at this point in the history
Fix get_neighbor* and Reactions related to OffLatticeSpace
  • Loading branch information
0ncorhynchus authored Jan 30, 2020
2 parents cc26717 + 0f3e1c4 commit 67ed134
Show file tree
Hide file tree
Showing 13 changed files with 464 additions and 320 deletions.
27 changes: 25 additions & 2 deletions ecell4/core/VoxelSpaceBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ Integer VoxelSpaceBase::num_molecules(const Species &sp) const
Integer count(0);
SpeciesExpressionMatcher sexp(sp);

{
const auto cnt = sexp.count(vacant_->species());
if (cnt > 0)
{
count += vacant_->size() * cnt;
}
}

for (voxel_pool_map_type::const_iterator itr(voxel_pools_.begin());
itr != voxel_pools_.end(); ++itr)
{
Expand Down Expand Up @@ -62,6 +70,11 @@ bool VoxelSpaceBase::has_voxel(const ParticleID &pid) const

Integer VoxelSpaceBase::num_voxels_exact(const Species &sp) const
{
if (sp == vacant_->species())
{
return vacant_->size();
}

{
voxel_pool_map_type::const_iterator itr(voxel_pools_.find(sp));
if (itr != voxel_pools_.end())
Expand All @@ -87,6 +100,11 @@ Integer VoxelSpaceBase::num_voxels(const Species &sp) const
Integer count(0);
SpeciesExpressionMatcher sexp(sp);

if (sexp.match(vacant_->species()))
{
count += vacant_->size();
}

for (voxel_pool_map_type::const_iterator itr(voxel_pools_.begin());
itr != voxel_pools_.end(); ++itr)
{
Expand All @@ -112,6 +130,11 @@ Integer VoxelSpaceBase::num_voxels() const
{
Integer count(0);

if (vacant_->species().serial() != "")
{
count += vacant_->size();
}

for (voxel_pool_map_type::const_iterator itr(voxel_pools_.begin());
itr != voxel_pools_.end(); ++itr)
{
Expand Down Expand Up @@ -179,7 +202,7 @@ VoxelSpaceBase::list_voxels_exact(const Species &sp) const

boost::shared_ptr<VoxelPool> VoxelSpaceBase::find_voxel_pool(const Species &sp)
{
if (sp.serial() == "")
if (sp == vacant_->species())
return vacant_;

voxel_pool_map_type::iterator itr(voxel_pools_.find(sp));
Expand All @@ -193,7 +216,7 @@ boost::shared_ptr<VoxelPool> VoxelSpaceBase::find_voxel_pool(const Species &sp)
boost::shared_ptr<const VoxelPool>
VoxelSpaceBase::find_voxel_pool(const Species &sp) const
{
if (sp.serial() == "")
if (sp == vacant_->species())
return vacant_;

voxel_pool_map_type::const_iterator itr(voxel_pools_.find(sp));
Expand Down
2 changes: 2 additions & 0 deletions ecell4/core/tests/LatticeSpace_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ BOOST_AUTO_TEST_CASE(LatticeSpace_test_constructor) { ; }
BOOST_AUTO_TEST_CASE(CheckVacantSize)
{
BOOST_CHECK_EQUAL(space.actual_size(), space.vacant()->size());
BOOST_CHECK_EQUAL(space.num_voxels_exact(Species("")),
space.vacant()->size());
}

BOOST_AUTO_TEST_CASE(GetVoxel)
Expand Down
4 changes: 2 additions & 2 deletions ecell4/core/tests/OffLatticeSpace_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct Fixture
for (int i(1); i < 10; ++i)
adjoining_pairs.push_back(std::make_pair(i - 1, i));
space = OffLatticeSpace(voxel_radius, base, positions, adjoining_pairs);
space.make_molecular_type(species, "");
space.make_molecular_type(species, "Base");
}
};

Expand Down Expand Up @@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(OffLatticeSpace_test_voxelspacebase)
BOOST_CHECK_EQUAL(space.list_species().size(), 1);
BOOST_CHECK_EQUAL(space.num_voxels_exact(species), 1);
BOOST_CHECK_EQUAL(space.num_voxels(species), 1);
BOOST_CHECK_EQUAL(space.num_voxels(), 1);
BOOST_CHECK_EQUAL(space.num_voxels(), 10);

BOOST_CHECK(space.has_voxel(pid));
BOOST_CHECK(!space.has_voxel(sidgen()));
Expand Down
178 changes: 94 additions & 84 deletions ecell4/python_api/spatiocyte.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include "python_api.hpp"

#include <ecell4/core/OffLatticeSpace.hpp>
#include <ecell4/spatiocyte/SpatiocyteReactions.hpp>
#include <ecell4/spatiocyte/OffLattice.hpp>
#include <ecell4/spatiocyte/SpatiocyteFactory.hpp>
#include <ecell4/spatiocyte/SpatiocyteReactions.hpp>
#include <ecell4/spatiocyte/SpatiocyteSimulator.hpp>
#include <ecell4/spatiocyte/SpatiocyteWorld.hpp>
#include <ecell4/spatiocyte/Voxel.hpp>
#include <ecell4/spatiocyte/OffLattice.hpp>

#include "simulator.hpp"
#include "simulator_factory.hpp"
Expand All @@ -21,111 +21,116 @@ namespace ecell4
namespace python_api
{

static inline
void define_reaction_info(py::module& m)
static inline void define_reaction_info(py::module &m)
{
using container_type = ReactionInfo::container_type;
py::class_<ReactionInfo>(m, "ReactionInfo")
.def(py::init<const Real, const container_type&, const container_type&>(),
py::arg("t"), py::arg("reactants"), py::arg("products"))
.def(py::init<const Real, const container_type &,
const container_type &>(),
py::arg("t"), py::arg("reactants"), py::arg("products"))
.def("t", &ReactionInfo::t)
.def("reactants", &ReactionInfo::reactants)
.def("products", &ReactionInfo::products)
.def(py::pickle(
[](const ReactionInfo& self)
{
return py::make_tuple(self.t(), self.reactants(), self.products());
[](const ReactionInfo &self) {
return py::make_tuple(self.t(), self.reactants(),
self.products());
},
[](py::tuple t)
{
[](py::tuple t) {
if (t.size() != 3)
throw std::runtime_error("Invalid state");
return ReactionInfo(
t[0].cast<Real>(),
t[1].cast<container_type>(),
t[2].cast<container_type>()
);
}
));
return ReactionInfo(t[0].cast<Real>(),
t[1].cast<container_type>(),
t[2].cast<container_type>());
}));

py::class_<ReactionInfo::Item>(m, "ReactionInfoItem")
.def_readonly("pid", &ReactionInfo::Item::pid)
.def_readonly("species", &ReactionInfo::Item::species)
.def_readonly("voxel", &ReactionInfo::Item::voxel);
}

static inline
void define_spatiocyte_factory(py::module& m)
static inline void define_spatiocyte_factory(py::module &m)
{
py::class_<SpatiocyteFactory> factory(m, "SpatiocyteFactory");
factory
.def(py::init<const Real>(),
py::arg("voxel_radius") = SpatiocyteFactory::default_voxel_radius())
py::arg("voxel_radius") =
SpatiocyteFactory::default_voxel_radius())
.def("rng", &SpatiocyteFactory::rng);
define_factory_functions(factory);

m.attr("Factory") = factory;
}

static inline
void define_spatiocyte_simulator(py::module& m)
static inline void define_spatiocyte_simulator(py::module &m)
{
py::class_<SpatiocyteSimulator, Simulator, PySimulator<SpatiocyteSimulator>,
boost::shared_ptr<SpatiocyteSimulator>> simulator(m, "SpatiocyteSimulator");
simulator
.def(py::init<boost::shared_ptr<SpatiocyteWorld>>(), py::arg("w"))
.def(py::init<boost::shared_ptr<SpatiocyteWorld>, boost::shared_ptr<Model>>(),
py::arg("w"), py::arg("m"))
boost::shared_ptr<SpatiocyteSimulator>>
simulator(m, "SpatiocyteSimulator");
simulator.def(py::init<boost::shared_ptr<SpatiocyteWorld>>(), py::arg("w"))
.def(py::init<boost::shared_ptr<SpatiocyteWorld>,
boost::shared_ptr<Model>>(),
py::arg("w"), py::arg("m"))
.def("last_reactions", &SpatiocyteSimulator::last_reactions)
.def("set_t", &SpatiocyteSimulator::set_t);
define_simulator_functions(simulator);

m.attr("Simulator") = simulator;
}

static inline
void define_spatiocyte_world(py::module& m)
static inline void define_spatiocyte_world(py::module &m)
{
py::class_<SpatiocyteWorld, ecell4::WorldInterface, PyWorldImpl<SpatiocyteWorld>,
boost::shared_ptr<SpatiocyteWorld>> world(m, "SpatiocyteWorld");
py::class_<SpatiocyteWorld, ecell4::WorldInterface,
PyWorldImpl<SpatiocyteWorld>, boost::shared_ptr<SpatiocyteWorld>>
world(m, "SpatiocyteWorld");
world
.def(py::init<const Real3&>(),
py::arg("edge_lengths") = Real3(1.0, 1.0, 1.0))
.def(py::init<const Real3&, const Real&>(),
py::arg("edge_lengths"), py::arg("voxel_radius"))
.def(py::init<const Real3&, const Real&, const boost::shared_ptr<RandomNumberGenerator>&>(),
py::arg("edge_lengths"),
py::arg("voxel_radius"),
py::arg("rng"))
.def(py::init<const Real3 &>(),
py::arg("edge_lengths") = Real3(1.0, 1.0, 1.0))
.def(py::init<const Real3 &, const Real &>(), py::arg("edge_lengths"),
py::arg("voxel_radius"))
.def(py::init<const Real3 &, const Real &,
const boost::shared_ptr<RandomNumberGenerator> &>(),
py::arg("edge_lengths"), py::arg("voxel_radius"), py::arg("rng"))
.def(py::init<const std::string>(), py::arg("filename"))

.def("new_particle", (boost::optional<ParticleID> (SpatiocyteWorld::*)(const Particle&)) &SpatiocyteWorld::new_particle)
.def("new_particle", (boost::optional<ParticleID> (SpatiocyteWorld::*)(const Species&, const Real3&)) &SpatiocyteWorld::new_particle)
.def("new_particle", (boost::optional<ParticleID>(SpatiocyteWorld::*)(
const Particle &)) &
SpatiocyteWorld::new_particle)
.def("new_particle", (boost::optional<ParticleID>(SpatiocyteWorld::*)(
const Species &, const Real3 &)) &
SpatiocyteWorld::new_particle)
.def("remove_particle", &SpatiocyteWorld::remove_particle)
.def("list_structure_particles", &SpatiocyteWorld::list_structure_particles)
.def("list_non_structure_particles", &SpatiocyteWorld::list_non_structure_particles)
.def("list_structure_particles",
&SpatiocyteWorld::list_structure_particles)
.def("list_non_structure_particles",
&SpatiocyteWorld::list_non_structure_particles)
.def("update_particle", &SpatiocyteWorld::update_particle)
.def("add_molecules",
(bool (SpatiocyteWorld::*)(const Species&, const Integer&))
&SpatiocyteWorld::add_molecules)
(bool (SpatiocyteWorld::*)(const Species &, const Integer &)) &
SpatiocyteWorld::add_molecules)
.def("add_molecules",
(bool (SpatiocyteWorld::*)(const Species&, const Integer&, const boost::shared_ptr<const Shape>))
&SpatiocyteWorld::add_molecules)
(bool (SpatiocyteWorld::*)(const Species &, const Integer &,
const boost::shared_ptr<const Shape>)) &
SpatiocyteWorld::add_molecules)
.def("remove_molecules", &SpatiocyteWorld::remove_molecules)
.def("voxel_volume", &SpatiocyteWorld::voxel_volume)
.def("get_volume", &SpatiocyteWorld::get_volume)
.def("get_voxel_at", &SpatiocyteWorld::get_voxel_at)
.def("get_species_at", &SpatiocyteWorld::get_species_at)
.def("has_particle_at", &SpatiocyteWorld::has_particle_at)
.def("set_value", &SpatiocyteWorld::set_value)
.def("new_particle", (boost::optional<ParticleID> (SpatiocyteWorld::*)(const Species&, const Voxel&))&SpatiocyteWorld::new_particle)
.def("new_particle", (boost::optional<ParticleID>(SpatiocyteWorld::*)(
const Species &, const Voxel &)) &
SpatiocyteWorld::new_particle)
.def("new_voxel",
(boost::optional<ParticleID> (SpatiocyteWorld::*)(const Species&, const Voxel&))&SpatiocyteWorld::new_particle,
R"pbdoc(
(boost::optional<ParticleID>(SpatiocyteWorld::*)(const Species &,
const Voxel &)) &
SpatiocyteWorld::new_particle,
R"pbdoc(
.. deprecated::3.0
Use :func:`new_particle` instead.
)pbdoc"
)
)pbdoc")
.def("new_voxel_structure", &SpatiocyteWorld::new_voxel_structure)
.def("voxel_radius", &SpatiocyteWorld::voxel_radius)
.def("size", &SpatiocyteWorld::size)
Expand All @@ -148,54 +153,60 @@ void define_spatiocyte_world(py::module& m)
)pbdoc")
.def("rng", &SpatiocyteWorld::rng)
.def("add_offlattice",
[](SpatiocyteWorld& self, const Species& species, const OffLattice& offlattice)
{
self.add_space(offlattice.generate_space(species));
})
.def_static("calculate_voxel_volume", &SpatiocyteWorld::calculate_voxel_volume)
.def_static("calculate_hcp_lengths", &SpatiocyteWorld::calculate_hcp_lengths)
[](SpatiocyteWorld &self, const Species &species,
const OffLattice &offlattice) {
const auto info = self.get_molecule_info(species);
const auto updated = Species(species.serial(), info.radius,
info.D, info.loc, info.dimension);
self.add_space(offlattice.generate_space(updated));
})
.def_static("calculate_voxel_volume",
&SpatiocyteWorld::calculate_voxel_volume)
.def_static("calculate_hcp_lengths",
&SpatiocyteWorld::calculate_hcp_lengths)
.def_static("calculate_shape", &SpatiocyteWorld::calculate_shape)
.def_static("calculate_volume", &SpatiocyteWorld::calculate_volume);

m.def("create_spatiocyte_world_cell_list_impl", &create_spatiocyte_world_cell_list_impl);
m.def("create_spatiocyte_world_vector_impl", &create_spatiocyte_world_vector_impl);
m.def("create_spatiocyte_world_square_offlattice_impl", &allocate_spatiocyte_world_square_offlattice_impl);
.def_static("calculate_volume", &SpatiocyteWorld::calculate_volume)
.def("list_neighbors",
[](const SpatiocyteWorld &self, const Voxel &voxel) {
std::vector<Voxel> list;
for (auto i = 0; i < self.num_neighbors(voxel); ++i)
{
list.push_back(self.get_neighbor(voxel, i));
}
return list;
});

m.def("create_spatiocyte_world_cell_list_impl",
&create_spatiocyte_world_cell_list_impl);
m.def("create_spatiocyte_world_vector_impl",
&create_spatiocyte_world_vector_impl);
m.def("create_spatiocyte_world_square_offlattice_impl",
&allocate_spatiocyte_world_square_offlattice_impl);

m.attr("World") = world;
}

static inline
void define_voxel(py::module& m)
static inline void define_voxel(py::module &m)
{
py::class_<Voxel>(m, "Voxel")
.def("position", &Voxel::position)
#ifndef NDEBUG
.def_readonly("coordinate", &Voxel::coordinate)
#endif
.def("list_neighbors",
[](const Voxel& self)
{
std::vector<Voxel> list;
for (auto i = 0; i < self.num_neighbors(); ++i)
{
list.push_back(self.get_neighbor(i));
}
return list;
});
.def("position", &Voxel::position);
}

static inline
void define_offlattice(py::module& m)
static inline void define_offlattice(py::module &m)
{
py::class_<OffLattice>(m, "OffLattice")
.def(py::init<const Real, const OffLattice::positions_type, const OffLattice::adjoining_pairs_type>())
.def(py::init<const Real, const OffLattice::positions_type,
const OffLattice::adjoining_pairs_type>())
.def(py::init<const Real, const OffLattice::positions_type>())
.def("voxel_radius", &OffLattice::voxel_radius)
.def("positions", &OffLattice::positions)
.def("adjoining_pairs", &OffLattice::adjoining_pairs);
}

void setup_spatiocyte_module(py::module& m)
void setup_spatiocyte_module(py::module &m)
{
define_reaction_info(m);
define_offlattice(m);
Expand All @@ -205,7 +216,6 @@ void setup_spatiocyte_module(py::module& m)
define_voxel(m);
}

}

}
} // namespace python_api

} // namespace ecell4
Loading

0 comments on commit 67ed134

Please sign in to comment.