I have been developing a simulation tool in grasshopper + python to simulate the spread of a disease in a city, for my architecture masters thesis project.
The model is made up of:
HOME points (where people live, leave and return to each day)
PLACE points (where people go to and come back from each day)
PATH network (curves/polylines connecting them together, representing pavements/sidewalks and paths).
The model works by generating “people” (points) on the HOME points, calculating their closest PLACE (closest point component) and figuring out the route to get there (shortest walk component), the route (curve) is then divided 200 times, and a python script counts from 0 to 2400 (24hrs), moving the point along the curve in 200 “steps” to the PLACE and back at specific times (E.g. 700=>900, 1500=>1700).
PROBLEM:
The problem I have is that the “person” is a new point instance at each step, instead of being the SAME point moving along the curve and back, so if the point gets INFECTED (python script evaluating proximity to an infected point), it doesn’t stay infected, as the next instance is a new point (i.e. noninfected).
Essentially I need a way of the points acting as agents with a state/characteristic which changes over time like:
NONINFECTED => INFECTED => IMMUNE.
So Problem is: I need Points as Agents that move, not copied as new instances
Sorry if this sounds really confusing, but I really hope someone can help me out!
Thanks in advance guys,
Hi.
You didn’t internalize your data… so it is impossible to try your definition.
But, more important: it seems you didn’t use any form of iteration!
For simulations like this one here, you’ll need to make iterations, “each minute” or such.
Without any kind of iteration, i’m not surprised it is not working.
I would suggest you trying a simpler case first.
Even a simple “billiard” with an infected ball that infect other balls as it touches them.
on this epidemic simulation topic, here is a very nice script from the awesome Long Nguyen written in C# (GH definition is downloadable and inspectable, link in the video description)
Hi Riccardo, thank you for your response!
I have attached another version with the curves internalised, which is the only geometry it needs to simulate the points moving. This version is a test before the version I posted before.
The model uses a python script that cycles through the integers 0 → 2400 with each count taking 10ms, each 100 steps represent 60 mins - so these are the iterations I think you’re referring to?
Hi Martyn, yeah I had a look at that a while back, but found it a little limiting as everything refreshes after each loop? I may be wrong, I’ll definitely have another go with it
Hi! yeah I’ve had this downloaded and been referring back to it, although I’m not that great with C# haha.
With this model the points are in fixed locations and don’t move, the problem I have is that my points are moving from place to place, and so new instances are created each time, so if the point gets “infected” - it doesn’t stay infected. Maybe I am just missing something glarringly obvious at this point, I am only just getting to grips with python.
That is just creating a value that change over time, no different from a manual slider.
You need to have some place where to store information and then use that information on the next iteration. That, over and over.
Your definition is not iterative.
Again, I suggest you to try with something really simple first.
Anemone, if you want to do everything with grasshopper.
C# or python if you want to have the iteration happening inside the script.
Generally speaking, when modelling dynamic systems you need at least:
A) Some persistent variable mechanism (i.e. to manage the state of your system/agents)
B) Some update mechanism (i.e. to step the system into the next iteration)
In GHPython, problem A can be solved using at least two methods: Notably the component local if "foo" not in globals() method, and the Rhino global sticky method. Both are covered in this old thread, and I’d recommend using the former, unless you need to read the system from outside the component where you iterate it. Problem B can of course be solved using a timer/trigger, or by scripting the component to update itself (recent example here).
I wrote some more notes in this topic here:
And I’d highly recommend going through @diff-arch’s excellent learning example provided here:
In this case it doesn’t iterate, but the c# simply re-calculates every time the input changes (the points moving) and check for distances and update “infected” statuses if in infection occurs.
Code:
private void RunScript(List<Point3d> Person, List<bool> Initial_status, double Infection_dist, bool Reset, ref object Statuses)
{
if(Reset){
statuses = Initial_status;
return;
}
for(int i = 0;i < Person.Count;i++){
if(statuses[i]){ // if true it means that the person people[i] is infected! So let's search for people to infect!
for(int j = 0;j < Person.Count;j++){ // now we search between all people for adjacency, anyone near enough will become infected
if(i != j){ // skipping if testing a person on itself
double dist = Person[i].DistanceTo(Person[j]);
if(dist < Infection_dist){
statuses[j] = true;
}
}
}
}
}
Statuses = statuses;
}
// <Custom additional code>
public List<bool> statuses;
// </Custom additional code>
}
Hi Riccardo, sorry it’s taken me a while, you’re absolutely right. I went back to the drawing board a little (with my deadline looming, I thought I needed a simpler strategy).
So I ended up not making it a “simulation” at all, as the people had rigid daily routines - I realised I was able to just plot their “journeys” with time in the z axis, similar to a Marey Chart. Where the intersections of each curve (each curve = person) being where interactions take place, therefore potentially = infections.
I’m actually posting a new problem that I’ve run into, I would love your help on that, as I need to now record the infections per day cycle in a more simpler way.
I post my script here, because it’s more appropriate than in the other thread, where you asked something different!
It’s a simple pandemic simulation written in GhPython, where each dot is an agent and its color informs about its general health: light green (mediocre) to bright green (great), and yellow (bad) to red (even worse).
There’s a system of predefined routes (polylines) within a line network (roads, ways, etc.) and initial positions (route start points).
Each agent walks its route from from to back. Many routes intersect and overlap where agents can meet and transmit diseases.
Sick movers have a certain radius (social distancing) proportional to their bad health. If a healthy agent gets within that radius, and it has only mediocre health the risk of infection is high. If it however has good or great health, its immune system only takes a hit, but an infection doesn’t happen.
After the simulation is done, you can display which mover has infected which agents.
I really don’t know what to say! - This in incredible, this is pretty much exactly what we envisaged at the start of the project but due to our skill level with gh+python - weren’t really able to achieve it.
Thank you, your script is ideal for me to go through and learn from, I have spent some time going through it and the python side is particularly interesting, although very complex.
The method of different health states is great although wouldn’t it still be possible for a very healthy person to still catch the virus? Otherwise, I think the only problem is my computer not being able to run it on a large site model haha.
I know this probably a really stupid question but the colours don’t seem to show up when I run it - do you know why that mght be?
No idea, I’m an architect, not a virologist! I just thought it would make sense to make movers with a very good health, immune to some degree, like it turned out to be with COVID. Some people caught the virus, but didn’t manifest any symptoms - up to now at least -, whereas others got servilely ill, and many unfortunately even died from it.
Your observation is also not exactly right. Even very healthy agents take a hit each time they encounter an infected one, to be exact 5% of there health is deducted. This means that if an healthy agent repetitively comes into contact with infect ones, it will eventually get sick, too. In reality, immune people probably can never get sick from the virus strain they are resistant to, unless it mutates.
Depends on the scale, but millions of agents won’t be possible in Rhino (in my opinion).
Currently the nearest neighbour searches that establish closest, healthy movers for the infected ones to contaminate, are probably the slowest operations.
They could however be sped up quite a bit by using a fast algorithm - like r-tree - instead of checking all agents for all agents, like I currently do.
How big are we talking?
No idea? I re-downloaded the file I uploaded earlier, but it works fine for me.
What do you see? Do you see anything? Are you using Rhino 7? What’s your document scale (mine is in mm)? Do you have “preview only selected” on in Grasshopper?
These three components should be turned on. To view the colored particles and the infection radii of the contaminated ones.
Wow, this really shows - even-though it’s not a super scientific simulation - why social distancing, lockdown measures, curfews, masks, increased hygiene, and all of these measures are absurdly necessary!
For a population of 125 agents, a single, infected one managed to contaminate 43.2% of the healthy population!
Hey, sorry I haven’t responded sooner, had a tricky week with things outside this project. The population size for our site has to reach 15,000, although our model is achieving nearer 20,000.
I just realised I was using a different display style, that I don’t shows material colour, that’s all haha my bad.
Otherwise, again, I am super greatful for this, it is really interesting seeing how many different ways there are to tackling the same problem. This one being really intuitive!