I cobbled together a compartmental fitting model for Omicron to try to get a handle on some viral characteristics empirically. It’s not completely polished yet, but this is late enough already, so I figured the speed premium was enough to share this version in a comment before writing up a full-length explanation of some of the choices made (e.g. whether to treat vaccination as some chance of removal or decreased risk by interaction).
You can find the code here in an interactive environment.
https://mybinder.org/v2/gh/pasdesc/Omicron-Model-Fitting/main
I built it to be architecturally pretty easy to tinker with (models are fully polymorphic, cost function can be swapped easily, almost all parameters are tweakable), but my messy code and lack of documentation may jeopardize that. Right now, it’s only loaded with the UK and Denmark, because those are the two nations that had high-resolution Omicron case data available, but if anyone is aware of more sources, it’s just some data parsing in a spreadsheet to add them, which I’m happy to do. It should optimize the viral characteristics across all of the populations simultaneously, i.e. assuming Omicron is identical in all these places. It also doesn’t currently account for prior Delta infection, because there was a full OOM variation in those statistics, and the ~20% protection offered didn’t seem 100% crucial to incorporate in an alpha version. Similarly, NPIs are not included.
With those disclaimers out of the way, here are some results!
In full moderately high-resolution optimization mode, the numbers I’ve found are something along the lines of Beta: 1.15-1.7 Gamma: 0.7-0.85 Alpha: 10+ (varies significantly, implies a very short pre-infectious exposure period). The implied serial interval is on the order of ~16 hours, which is short enough to strain plausibility (Very roughly, R_0=beta/gamma, serial interval=1/beta. Better estimates for these are another v2 thing.). However, these numbers can’t be quite taken at face value as the “best” solution, because the numeric “grid” I’m using to evaluate different options can’t evaluate the depth of local minima in a first pass, meaning that the program could privilege certain spots on a roughly level accuracy curve because the test point chosen happens to coincide with the bottom of the trough.
Note that in both cases, observed cases flatten as time goes on/cases rise. I strongly suspect this is due to testing failure, and will likely modify the error function to prioritize mid-case data or adjust for positivity rate. If anyone has rigorous suggestions about how to do that, I’d be very interested. These fits also look not-very-impressive because they’re pretty exponential at the moment; they aren’t perfect, but the similarity between the UK and Denmark is suggestive, and if you tweak things slightly accounting for both of these factors, you can get visually better fits—see below for why.
I’m not aware of a way to do fully numeric gradient descent, but in v2 of this, I’m going to improve the iteration element of the optimization algorithm to slide to an adjacent “square” if appropriate and/or add numeric discrete-direction descejnt. In the meantime, it’s more appropriate to look at the points within a threshold of optimal, which form clouds as shown below (note that because many of these variables are at least partially inverted when considered in terms of viral characteristics, bigger clouds further from the origin are to be expected.
Please let me know if anyone’s interested in any specific scenarios, confused, or having issues—there’s a known bug where if any of the coefficients is greater than 1/resolution, things go to hell very quickly.
See my above comment, where I was trying to get a handle on this. It increasingly seems like the answer is that most of it comes from breakthrough+serial intervals