I am currently working on creating an ABM of the the dynamics of a bacterial infection within a population of individuals. Individuals in the model can transmit aiming bacteria to one another, while interacting in a continuous space. The probabilities of bacteria being transmitted are governed by the within-host dynamics of multiple bacterial strains within each individual (each host has n strains of bacteria, which change over time, depending on host-level factors). The bacteria interact with each other in a grid space.
The model I am trying to develop requires that, for each time step, the individuals in the population interact with each other, and each individual has an ABM describing its bacterial dynamics at each timestep. The bacterial level model would be influenced by host-level factors (such as the age of the individual, its contact with others and its treatment history), and the interaction between hosts influenced by the attributes of the host’s bacterial population (such as whether its bacterial population was predominantly pathogenic at the time of its interaction with another host).
So far, I have two independent models, one of host interactions and one of within-host bacterial interactions. What I think I need to do is to nest the bacterial model within the host model so that the bacterial ABM evolves with each timestep the host experiences.
I am new to Julia, and fairly new to ABMs. Is what I am describing conceptually feasible, or am I missing the point somewhere? Are there any approaches that I can use to nest my bacterial model within the host model?
This is more of a conceptual question, so I don’t have a code example that would really bring anything to the party.
Any pointers from the ABMers out there would be greatly appreciated.
We’ve had discussions about mixed spaces before, which ended up getting us to a point in Agents.jl that they were not needed for any use case we could think of at the time.
More recently, we’ve been getting requests again about this (ant world examples). Although we haven’t closed out that PR yet, the consensus of the Agents.jl dev team is that having two spaces in one model is still not so worthwhile—the alternate is to use model properties.
Your case may indeed be slightly different, but maybe not. We’d be happy to work through the idea though and see what makes the most sense. What we’re finding is that Grid and Continuous space end up being conflated in Netlogo (patches are grids, turtles lie on those grids but have continuous coordinates: both of these are agent types not spaces in the way Agents.jl defines them). So those who are familiar with Netlogo syntax have a bit of a conceptual barrier when moving to Agents.jl. This is something we are working on…
Code would of course help us here. You say you have two independent models at the moment - are they two conceptual models or models implemented in another ABM framework? If it’s the latter, we can work with that as a start.
Thanks so much for the great reply.
I will have a look at the ant world examples. I haven’t used NetLogo. I’ve mostly used R up to this point to implement equation based models using ODEs. It looked like Julia would be a better language to implement an ABM in so here we are.
The models I’ve made so far are on git. HostModel.jl is the host level model and within_gridspace.jl the bacteria level model. I’ve sort of bodged them together with some inspiration from the Agents.jl examples. They are a bit messy (the Julia learning curve has been steep so far) but both should run independently.
I’m just nutting out a concept, so the outputs aren’t biologically plausible. I’m aiming to model the development of antimicrobial resistance in animals, so I’d like to have a population of multiple strains sitting within each host, which in turn are influenced by things that happen to the host over time (treatment with antibiotics being the major event of interest).
The hosts are in a continuous space because they move around and interact, thereby acquiring infection from each other. That isn’t really necessary for the bacteria, which are minimally motile. The only spatial event for them is plasmid transfer of resistance when they are next to each other, which is why they are currently on a grid.
It might be possible to achieve a similar outcome by either putting them in a continuous space with minimal movement, or by putting the hosts in a grid space and defining their movements differently?
A really interesting case! (@Datseris, take a look)
Since you’re not adding / killing / moving the bacteria, just searching for neighbors - you would be perfectly fine to use Continuous space for the merged model.
Under the hood of Continuous space we do use a Grid space to do efficient nearest neighbor searches - and that’s the only aspect of the space you’re using at present.
Take a shot at doing that and if you get stuck, please reach out with specific questions!
This repo is empty, but we’re planning to fill it with examples like this if you’re interested in submitting it once you are finished Agents.jl_Example_Zoo.
I’ll give that a go. I will have to add in killing and adding bacteria at some point so I can account for the some of the fitness costs of expressing resistance at some point, but I think this should still be possible in a continuous space.
Hopefully I’ll get it to a point where I’m happy enough with it to be added to the collection in the example zoo.
Thanks again for the help, appreciated.
This sounds like a multiscale model. One thing you might do is run a large ensemble of bacterial models on a grid space, and develop a summary statistical description of the details. Then just run that summary description within each mobile “animal” agent in your main model. The details of which exact bacteria swap which plasmids with which other bacteria … INSIDE each animal is surely irrelevant to the infection dynamics, whereas the summaries such as how many of each type of bacteria are in each animal and whether they do or don’t have resistance plasmids are going to be important.
That’d be how I would proceed, and it’ll save you an enormous amount of computation.
Yeah, a decent way of thinking about it!
We have some discussion around similar concepts in advanced stepping, but a true multi-scale model is something we haven’t got in our zoo yet.
There is no reason why you can’t build a model within a model by storing it in the
model.properties actually, calling its
step! function from the parent model when you need to.
In one of my own research models. It’s actually make a copy of my current model state, do some modifications and throw it at an optimisation process. So there are plenty of ways you can approach this problem conceptually.
I’ve had a play with creating a union of agent types in same space, but I think the multi-scale approach makes the most sense to me. Modelling the within host population and passing a summary of that back to the host at each time step is in line with what I’d like to achieve. The specifics of what is happening with each bacteria isn’t of great relevance, but the overall trend of what is going on in the bacterial population is.
I’ll have a look at the examples, and have go at building a multi-scale model and report back when I (somewhat inevitably) get stuck!