A contact matrix is a representation of contacts between individuals. For instance, in order to model the spread of rumors on social media, you ideally have to rely on contact matrices to compute the strength of bonds between types of individual agents. In the infectious disease world, a contact matrix is used to approximate contacts between individuals, e.g. between grand-parents and grand-children.
In this blog post, after a short explanation of POLYMOD contact matrices, I will show how to get the data, process it and 3D print these matrices. Ready?
1. Finding contact matrices
The most used contact matrices in epidemiological modelling are coming from the POLYMOD study, published by Mossong et al. in 2008. The study is a population-based prospective survey of mixing patterns in eight European countries (Belgium, Germany, Finland, Great Britain, Italy, Luxembourg, The Netherlands, and Poland). For that purpose their method consisted in common paper-diaries used by individuals to record information about their daily contacts (you might think this is so old fashion but nobody reproduced this study or did better so far!).
So what does it look like (I’ll take Belgium as an example here)?
You can see above a heatmap of physical contacts between participants and their contacts. The more towards the blue indicates fewer contacts. The more towards white indicates more contacts. Therefore the diagonal towards the top right shows that most Belgian participants have contacts with people of the same age. And this diagonal has two “wings”, representing interactions between parents in their 30s and their children. There are also two “bumps”, representing interactions between grand-parents and their grand-children.
So these heatmaps are already something pleasant to the eye. But what if you could actually touch them? Can you actually physically play with them? This was made possible thanks to 3D printing, a manufacturing process that transform practically any custom 3D model created on a computed into a physical artifact.
We’ll first need to get the data, process it in a suitable format and finally print it …
2. Getting and processing the data
The dream would be a simple transformation between the image above into a physical object. But this is unfortunately not possible (for now – there are some good software that approaching that process).
We’ll have to go back to the raw data. In Mossong et al., all the contact matrices are in the section Supporting Information, in Table 5. Unfortunately the data is in Word: it’s very convenient for a human reader but not at all for our purpose. Therefore I placed here the raw data for table S5-b) (physical contacts for Belgium) in plain csv format (1kb).
Esthetically, since I want only values between 0 and 1, I will do a small processing step in R (because it’s easy for me and reproducible – but you could easily do it in a spreadsheet):
data <- read.csv(file="140800-Mossong-BEPhys.csv", header=FALSE) newdata <- data / max(data)*10 write.table(newdata, file="140800-Mossong-BEPhys3.ssv", sep=" ", row.names=FALSE, col.names=FALSE, fileEncoding = "UTF-8")
I will now transform the resulting file into a 3D model. For that purpose I use OpenSCAD, a free software available on Linux, Mac and Windows. In OpenSCAD, you don’t model your object with the mouse but you rather program it in the left part of the screen. But its syntax is very simple (especially for the simple object we want to make):
scale([10, 10, 10]) surface(file = "140800-Mossong-BEPhys3.ssv", center = true);
As you can see, the “code” is very simple and already produce an interesting result.
Here is the result in OpenSCAD:
If you want to explore it, you can play with it on Sketchfab.
3. Printing it in 3D!
The last step before bringing it to the print shop is to export to .stl format (menu File -> Export -> Export as STL…). Here is the resulting STL file. Usually most of these STL files would need some further processing to be suitable for 3D printing; here we’ll assume either it was done or it didn’t need it.
If you decide to go to a Fablab, the interesting thing is that you’ll be coached by volunteers to become able to print most design by yourself. You’ll also meet a lot of interesting people tinkering and making stuff (with 3D printers but also with other devices). And the price can’t be beaten (scaled down at 50% in polyamide natural white, it costed only 5€!).
Now if you don’t have a FabLab nearby, you can send your design to a print shop (scaled down at 50% in polyamide natural white, it costs about 30€ at i.Materialise + shipping). The link between i.Materialise and this contact matrix is they are established in Belgium for the first one and resulting from a study in Belgium for the second 😉
And voila! Here is the result:
The result looks pretty good. We clearly see the three main groups of contacts: with people of the same age, with children and with parents / grand-parents. Having scaled it to a side of ~ 7cm, it feels pretty nicely in an adult’s hand, it looks real now, one can put her/his finger on peaks or in valleys and actually feel the contact matrix. Of course it depends of the resolution of the original 2D file but peaks and valleys are “big” (or solid/strong) enough (on the other side it may look artistically interesting if the original 2D file has less pixels: it would look like a Minecraft field ;-)).
I was a bit afraid that the highest peaks would be too fragile. Too fragile to be printed (they would fall during the additive process) or too fragile to be transported (I finally printed this via i.Materialise). But I must say their customer support did a very good job, checking the file before printing, spotting the potential problem and contacting me to check if I would take the risk. But the best part is the way they found a way to try to protect the highest peaks during transport: on top of the box, the air cushions, the soft wrapping, they added 2 pieces of styrofoam around (see below) and it came perfectly in place!
I’ve added it to Thingverse (thing 438939).
Next steps: paint the white contact matrix or … print it in colors, directly! 😉