So one of my most popular videos is the one with the Herd Immunity Simulator.
Of course, all the anti-vaccers are going crazy about it because it easily and handily
debunks their nonsense, and yet none of them can point to a single problem with the code.
Well, I always wanted a chance to kind of take this to the next step, because there
were certain limitations due to the way I wanted the original to work.
I wanted it to work in a website, and I wanted people to be able to get the code easily by
looking at the HTML source.
That meant I had to write it in Javascript, which is not the best language to do that
sort of thing with, and a lot of the stuff in the code is just taking care of problems
when you do a lot of processing in Javascript.
I was also working with a limited scenario.
Since all of my people--or "nodes," as they're properly termed in programming--had to be
put into an HTML table, I was showing the spread of an infection among people who were
cooperative enough to stay in nice little rows and columns, instead of milling about
all over Disneyland.
Another problem--and this was my big concern--was that, since they could only infect their neighbors,
the R-null--that is, the amount of people an infected person will go on to infect--was
stuck at 8, or 5 for nodes on the sides and 3 for nodes on the corners.
Different pathogens have different R-null values, though; Ebola has an R-null of just
2, whereas measles is more like 15.
So there was no way to test Herd Immunity levels for different pathogens.
So I always wanted a chance to sit down and rewrite this in another language, and I chose
Python because it's an easy one to learn how to use and the code is very clean, so even
if you're not an experienced programmer you can look through it, and we'll do that and
I'll go over what everything does.
Now, if you want to run this on your machine, you'll need a Python interpreter.
I use IDLE--that's "Integrated DeveLopement Environment" (yes, it's camel-cased that way;
what can I say?
It's a backronym) and I've put a download link in the Video Info box.
I used Python 3.4.2, but I wrote the code to spec so it shouldn't matter.
But if you have any problems, just try running it in 3.4.2.
The Herd Immunity Simulator you can get from GitHub, and you really just need the .py file.
So you can download that.
You don't have to download GitHub, although of course you can if you want, and if you
want to make your own version feel free to branch it off of mine.
The code's GPL.
So you can load it up into IDLE, and here it is.
The main thing you want to be concerned about is the part below the first block of comments,
where it says "User can set these values."
I haven't written a user interface yet, if anyone else wants to, feel free.
Like I said, it's GPL.
But for now just modify the text file on your computer.
The first two were things you couldn't change with the Javascript version.
The population size is no longer fixed, so you can set it wherever you want, but be warned:
Python is an interpreted language, and this is a recursive algorithm--I'll show you what
that means a little later--but if you set it too high you may cause the interpreter
to choke and crash.
So if that happens just set a lower value.
1000 seems to work fine even on slower computers.
Then there's Rnull.
I mentioned this earlier.
This is the amount of people an infected person goes on to infect.
I may randomize this a bit in the future, or let people set a range.
But for now we'll just go with the number.
This is another one you don't want to make too high, because it could crash the interpreter.
NatImmunity is the natural level of immunity; just like in the original, you can set this
to whatever you want.
By default I have it set to .1, or 10 percent, just don't set it to 1 or 0 or else you'll
get a Division by Zero error I haven't debugged yet.
VacImmunity is similar; this is .9, or 90 percent, because again vaccines aren't 100%
effective.
Again, set it to whatever you want, in between 1 or 0, but not 1 or 0.
And same with vaccinated, which is the portion of the population that's vaccinated.
I have that defaulting at 90%.
Now, if you want, you can go ahead and run the code; just hit F5 or go to the Run menu
and select Run Module.
This is what you'll see when it runs: the percent vaccinated, which may not be 90% because
there's some randomness there, which you want.
And then healthy versus unhealthy vaccinated and unvaccinated populations.
The big difference here is that we actually calculate whether or not we've achieved Herd
Immunity, which we didn't do in the previous one.
So let's take a look through the code and see how this works.
And by the way, this is all original code, nothing was taken from the Javascript version
because I'm going about this a completely different way.
The main program runs as three functions: initPop, which initializes the population,
initInfect, which starts the infection running, and evalPop, which gives us the results when
it's all over.
All of these are in completely separate functions, so the anti-vaccers can't even PRETEND that
the results are influencing the simulation.
Well, okay, maybe they can pretend it, their capacity for delusion seems to be infinite,
but not with any legitimacy.
Okay, so there's initPop, which is short and simple.
We just run through the population of whatever size we specified; remember the population
variable is what we set above, by default 1000, so it'll run through this 1000 times.
It generates a random number, and then adds that member of the population based on the
result.
If it's less than or equal to our vaccination percentage, it goes in as "True," meaning
that this individual received the vaccine.
Otherwise, it enters "False."
So this is the randomization we saw earlier.
A vaccination rate of .9 doesn't mean we're going to vaccinate 90% of the population,
it means that each individual member has a 90% chance of being vaccinated, so it'll vary
a bit.
Now, no matter what our random number is, we'll set the infection flag for that individual
to be "False."
So we're starting out with a completely healthy population.
Once we have the population generated, we run initInfect.
This gets everything going.
What we're going to do is take a member of this population at random and infect him--and
he's guaranteed to be infected, whether he's vaccinated or not.
That's how we start the simulation.
So here's our infected person coming into Disneyland.
Then it runs infectSpread, which as you might guess spreads the infection.
We set Rnull to 5 by default, remember, so what it's going to do is pick that many people--5
by default--out of our population pool, completely at random.
So no rows or columns or anything else going on.
There's no sense of people being "near" each other.
Imagine a mass of people moving around in a space at random, kind of like Disneyland,
so you don't always have the same people together at the same time.
Now there's a chance we might pull out our infected node, and we don't want to do that.
We want this particular node to infect 5 others, no more, no less.
So we have a quick check to make sure our infected node isn't one of the ones we selected.
If it is, we'll run it again, but this shouldn't happen often.
So we have a new list of 5 nodes.
We'll now run through that list and run our infectNode function on each of them.
So just like the previous simulation, our infected node gets one and only one chance
to infect each of these.
The first thing infectNode does is check to see if this node we've pulled out randomly
is already infected.
If so, we don't want to infect it again.
After all, the algorithm has to stop somehow.
If it's not infected, we generate another random number and check to see if this node
is vaccinated.
If so, we'll check to see if it gets infected by calculating r>vacImmunity.
Remember that by default we have vacImmunity at .9, which means if our random number is
greater than .9 it's infected.
Else, the node isn't vaccinated, and then r just has to be greater than natImmunity,
or .1 by default.
If we didn't manage to infect the node, nothing else happens.
If we did, we set its infection status to True, and we run infectSpread against that
node.
This is the recursive part.
All of the infected nodes will branch out into their own trees until they don't manage
to infect anyone else.
Then the simulation terminates, and we run our final function, evalPop.
All of those "equals zero" things are initializing counters, which are, in order: the number
of unvaccinated people, the number of vaccinated people, the number of infected vaccinated
people, the number of infected unvaccinated people, the number of healthy vaccinated people,
and the number of healthy unvaccinated people.
We'll count all those up in a minute.
Then we calculate what percentage of the population has to be vaccinated, as predicted by the
model, for herd immunity.
I waited to do this here so that no anti-vaccer could claim that it was in any way directing
the process.
We haven't even CALCULATED our prediction until now, so there's no way it could.
Okay, so now we go through our population, and for each node we see whether it's vaccinated
or unvaccinated, and whether or not it's healthy or infected, incrementing the appropriate
counter as we go.
The next line computes whether or not we actually managed to get the level the model predicts
for Herd immunity.
We don't want to count all the vaccinated people, because remember our vacImmunity rate
is only 90%.
So we'll multiply those together.
We'll also do the same for the unvaccinated and natImmunity to include the ones who came
into this with a natural immunity.
Then we divide all of that by the population to get the ratio.
The next line just checks to see if this is above the predicted amount for Herd Immunity.
If it is, isHerd is set to True, if not, it's set to False.
Then it's just a matter of displaying it all.
And you can just keep hitting F5 to run it over and over again to see what happens.
And, of course, you can completely break Herd Immunity by taking the vaccinated rate down
to .1.
NOT a good day to be at Disneyland.
But notice: despite the data points that anti-vaccers like to use to try and show that vaccines
don't work, in each case you're STILL better off if you vaccinate.
Just not as much as you are if there's Herd Immunity.
Now, these default values get us JUST above the level of Herd Immunity.
If you keep everything else at the default but raise Rnull to 6, you'll get just below
the level of Herd Immunity.
And this'll help you notice one important point: that Herd Immunity isn't like a switch.
Even if you're just under Herd Immunity, you'll get very few infections for most of the runs.
But you're also more likely to get the occasional outbreak, like in Disneyland or Swansea.
Oh, and one more thing: you'll notice a lot of runs where one lone vaccinated person gets
infected, with no unvaccinated infected.
Remember that the first node chosen at random ALWAYS gets infected, no matter what.
And if most of your population are vaccinated, chances are, that first person will be vaccinated.
That's that 1 person you're seeing there.
So it'll NEVER be the case that both of those numbers are zero; one of them will ALWAYS
be infected.
Now let's really goose it up: set the vaccinated rate to .99.
I'll also set the population to 10,000 so we'll have a good number of unvaccinated people
to watch.
We have a comfortable amount of herd immunity now, so no more outbreaks.
The more people vaccinate, the better.
You can NEVER rest on your laurels and say, "Well, I guess we got enough."
Squeaking by with barely enough for Herd Immunity will still result in the occasional outbreak
and misery.
Larger vaccination rates will help all the more.
Well, we've been talking about measles, so let's take a look at that.
The Rnull for measles is listed as being between 12 and 18.
Let's take a nice middle-of-the-road 15, and run the sim.
Even with 99% vaccinated, it still isn't enough for Herd Immunity.
Let's do something closer to a best-case scenario: the vaccine works really good and there are
few immunocompromised people and others who can't get it, so the vacImmunity rate is now
.95.
Also, maybe some people had measles as a kid and are now immune, so let's bump natImmunity
up to .2.
Now, in this best-case scenario, we're just barely squeaking buy with Herd Immunity.
So for pathogens with a high R-null like measles and pertussis, THERE IS NO WIGGLE-ROOM.
There is NO ROOM WHATSOEVER for people saying, "Gee, I just won't get myself or my child
vaccinated, because, reasons."
This decision DIRECTLY PUTS OTHERS AT RISK.
The anti-vax lies are LIES THAT KILL.
So, this is better and more flexible for us, but there's still room for improvement.
I mentioned a proper user interface, and maybe even graphic elements that can show the results
visually.
Anyone who wants to fork it and work on that, feel free.
I'll probably fix the Division by Zero bug at some point.
Also, right now R-null can only be integers, but I might update it to where you can put
in floats, so you could make R-null 3.5, and then half the time the infection would spread
to 3 people and 4 the other half.
And even make it a range like how most pathogens are listed.
Lots of room for improvements.
But hey, it's GPL, and as far as I know the only other Herd Immunity Simulator I'm aware
of is the Javascript one I did originally and that Robert Webb modified, although I'm
not sure, it's not like I have every single GitHub repository in my brain, not to mention
all the other software out there, but anyway, feel free to run with this.
And of course, use this one and the original to stop these anti-vax claims in their tracks
before more babies die.
And if you're an anti-vaccer, understand this: YOU HAVE NO MORE COVER.
All of your bogosity is laid to bare.
You can't argue with the math, and that's all computer code is.
If you can't find a flaw in my code, then you have nothing to say, especially now that
we have two different simulators using two different algorithms and they both show the
same results.
It needs to be said, far and wide: anti-vaccination people are LIARS, and their lies KILL BABIES.