Tag Hut essen

Dieser Tag bezeichnet Posts, in denen ich irgendwas aus vorherigen Posts zurücknehmen muss. Leider habe ich vergessen, woher der Spruch „Wenn das nicht hinkommt, esse ich meinen Hut” kommt. Aber ich fand ihn immer gut.

  • Neurasthenie und Post-Covid

    Neulich hatte ich es schon von der Russischen Grippe, einer Pandemie, deren große Wellen zwischen 1889 und 1895 rollten und die plausiblerweise die jüngste große Coronapandemie vor SARS-2 gewesen sein könnte (Forschung aktuell dazu). Zwischenzeitlich ist mir nun aufgefallen, dass es einen weiteren Datenpunkt für Parallelen zwischen der Russischen Gruppe und SARS-2 geben könnte: Die Neurasthenie.

    Bis zu dieser Einsicht hatte ich die aktuelle Einschätzung der Wikipedia geteilt:

    Neurasthenie gehörte im ausgehenden 19. und beginnenden 20. Jahrhundert zu den Modekrankheiten einer gehobenen Gesellschaftsschicht.

    Im Fin de Siécle schien es in der Tat zum guten Ton zu gehören,

    Erschöpfung und Ermüdung, die entweder durch eine zu geringe Belastbarkeit durch äußere Reize und Anstrengungen oder auch durch zu geringe oder zu monotone Reize selbst verursacht sein kann

    an den Tag zu legen. Florian Illies schreibt dazu in seinem Zeitportrait „1913 – der Sommer des Jahrhunderts“:

    1913 fasste man das zusammen unter dem Begriff: »Neurasthenie«. Spötter sangen: »Raste nie und haste nie, sonst haste die Neurasthenie«.

    Was aber, wenn „wir“ (also die, die sich in der Einschätzung „Modekrankheit“ gefielen) den Betroffenen unrecht getan haben? Was, wenn das in Wirklichkeit das Äquivalent von Long Covid, sagen wir Long Russische Grippe, also die neurologischen oder immunologischen Spätfolge einer im höheren Alter ersterworbenen Coronainfektionen war? Wenn, dann sollten wir nicht die Luft anhalten, bis das alles wieder vorbei ist, denn die Neurastheniewelle ebbte, soweit ich erkennen kann, ähnlich wie Thomas Manns Zauberberg[1] erst mit dem ersten Weltkrieg, zwanzig Jahre nach den großen Wellen, ab.

    Ich bereite mich jedenfalls schon mal vor, mal wieder meinen Hut essen zu müssen. Hat wer Hinweise auf ordentliche Literatur zu dem Thema?

    [1]Ich habe aus gegebenem Anlass nachgesehen: Mann erwähnt im ganzen Zauberberg keine Neurasthenie, obwohl das Topos eigentlich das ganze Buch durchzieht. Ob es daran liegt, dass das Buch zehn Jahre nach dem Ende seiner Handlung erschien und es nichts Anrüchigeres gibt als die Mode von gestern?
  • Wieder falsch vorhergesagt

    Also gut. Ich sehe es ein. Und gebe es auf. Vor neun Tagen hatte ich vorhergesagt, heute müssten so in etwa 4700 Intensivbetten mit SARS-2-PatientInnen belegt sein. In Wahrheit liegt die DIVI-Zahl im RKI-Bericht von heute bei 3987, also gut 15% darunter. Das wäre bei meinen sonstigen Handwerks-Abschätzungen kein Drama. Hier aber sagt es klar: Meine Methode taugt (erstmal) nicht (mehr).

    Hintergrund war mein Artikel von vor 18 Tagen, in dem ich (für Verhältnisse dieses Blogs sorgfältig) die Verzögerung zwischen steigenden Inzidenzen und in der Folge steigender Intensivbelegung abgeschätzt habe. Das Ergebnis für die vierte Welle waren neun Tage. Doch schon die daraus folgende Abschätzung der Intensivbelegung vor neun Tagen lag weit daneben.

    Und nun liege ich eine weitere Verzögerungsperiode später wieder falsch. Das ist also ganz offenbar alles Quatsch. Während ich mich bei der letzten falschen Vorhersage noch mit einer Fehlanwendung des heuristischen Modells herausreden konnte, ist das bei zwei falschen Vorhersagen nicht mehr drin. Nein. Die Prämisse ist falsch. Die Instensivbelegung folgt nicht mehr, wie noch in den zweiten und dritten Wellen, ganz brauchbar der Inzidenz. Die beiden Kurven haben sich inzwischen sehr deutlich entkoppelt:

    Graph: Entkoppelte Entwicklungen

    Meldezahlen des RKI vs. DIVI-Zahlen (Quellen vgl. Halbwegs gute Nachrichten). Auf der Zeitachse Sekunden seit 1.1.2020; 5⋅107 entspricht dabei dem 1.8.2021. Die Intensivbelegung ist um neun Tage nach vorne gezogen, um den wahrscheinlichsten Verzug auszugleichen und die Kurven übereinanderzubringen. Die y-Achse ist wie immer bei solchen Wachstumsplots von mir logarithmisch (also: exponentielles Wachstum ist eine Gerade). Die Skalierung der Intensivbelegung ist frei Auge, aber egal, wie mensch das macht: die Kurven passen nicht übereinander.

    Ganz offensichtlich reagiert die Intensivbelegung „weicher“ als die Inzidenz, und zwar nicht nur, wie aufgrund längerer Liegezeiten zu erwarten, nach unten, sondern auch nach oben. Es ist eben derzeit nicht so, dass aus einer gegebenen Zahl von Infizierten eine leicht vorhersehbare Zahl von IntensivpatientInnen wird. Daher ist vorläufig jede Vorhersage, die von einem konstanten Verhältnis von Intensivbelegung zu Inzidenz ausgeht, eine schlechte und ziemlich sicher falsche Vorhersage.

    Das richtige Vorgehen wäre jetzt, nachzusehen, was eigentlich diese Annahme kaputt macht (wobei: wie ich im September herausgefunden habe, war sie so ganz richtig ohnehin nie). Leider gibt es eine große Zahl möglicher Gründe, allen voran ist das natürlich die Demographie. Solange sie nicht ihre Eltern und Großeltern anstecken, können sich sehr viele Kinder mit SARS-2 infizieren, bevor das irgendwo in Intensivstatistiken sichtbar wird, während umgekehrt ein einziger Ausbruch in einem Pflegeheim mit gebrechlichen Menschen einige dutzend Intensivbetten belegen mag, was auch bundesweit schon eine Veränderung im einstelligen Prozentbereich ausmachen würde.

    Dazu kommen dann regional und nach Altersgruppen recht deutlich schwankende Impfquoten: Rasant steigende Inzidenzen in Bremen mit einer relativ stark durchimpften Bevölkerung geben ziemlich sicher ein deutlich schwächeres Signal auf Intensiv als eine rollende Welle in Sachsen, wo immer noch viele Menschen im mittleren Altersbereich ungeimpft sind und damit weit eher langwierige und kritische Verläufe nehmen werden

    Nachtrag (2021-11-25)

    Zum Thema Sachsen ist in der taz vom 25.11. zu lesen, von den dortigen 14000 PolizistInnen seien derzeit 519 SARS-2-positiv. Das ist eine 100000er-Wocheninzidenz zwischen 1500 und 4000, je nach dem, wie die zählen, und damit selbst für sächsische Verhältnisse (RKI-Inzidenz heute 1075) ziemlich sportlich.

    Mein int/inc-Maß (IntensivpatientInnen pro Inzidenzpunkt) ist aber auch empfindlich für Auswahleffekte. So wird es immer dann stark sinken, wenn systematisch getestet wird: Wenn die Dunkelziffer unerkannt Infizierter runtergeht, geht die Inzidenz im Hellfeld und damit mein Nenner hoch, ohne dass sich an der im Zähler reflektierten Realität etwas ändert. Besonders verzerrend werden sich solche Effekte auswirken, wenn systematische Tests nur demographisch oder impfstatistisch sehr auffällige Teile der Bevölkerung erreichen (sagen wir: SchülerInnen).

    In Summe: Wer derzeit aus der Inzidenzkurve Vorhersagen über die Intensivbelegung machen will, musss Impfquoten und Demographie, und damit auch die geographische Verteilung der Inzidenz, berücksichtigen, wenn das irgendwie hinkommen soll. Und das mutiert zu mehr Arbeit als ich in der Kategorie handwerk tun will.

    Bestimmt macht das irgendwer auch richtig. Aber dann: die Zahlenspielereien ändern nichts daran, dass wir Inzidenzen um 5000 haben müssten, wenn wir im nächsten Frühling durch sein wollen (100000/(5000 pro Woche) entspricht 20 Wochen oder einem knappen halben Jahr, mit Dunkelziffer also vielleicht einem Vierteljahr oder so), und auch nicht daran, dass das mit unseren augenblicklichen Techniken und Politiken ein furchtbares Gemetzel werden würde. Seufz.

  • Keine guten Nachrichten

    Und wieder muss ich meinen Hut essen im Zusammenhang mit meinen Corona-Zahlenspielen. Ich hatte nämlich vor neun Tagen zuversichtlich vorhergesagt, so etwa jetzt sollten knapp 3500 Intensivbetten in der BRD mit SARS-2-PatientInnen belegt sein, mit dem Argument, dass sich die entsprechenden Zahlen derzeit neun Tage hinter der Inzidenz herbewegen. Da (und das war, wie unten diskutiert, ein Fehlschluss) die Inzidenz in den neun Tagen vor dem 6.11. um 44% gestiegen war, sah ich die Intensivbelegung heute bei 2332⋅1.44 ≈ 3350. Tatsächlich aber berichtet das RKI heute von nur 3034 SARS-2 IntensivpatientInnen, also um die 10% weniger als meine Vorhersage – oder 30% weniger Anstieg, um die Fehleinschätzung mal deutlicher zu machen.

    Ein Metafehler und einige Nicht-Fehler

    Es war schon ein paar Tage abzusehen, dass ich falsch liegen würde, und ich habe mir bereits letzte Woche ein paar lose Gedanken gemacht, wo wohl mein Fehler liegen könnte. Nicht angreifen konnte ich meine Argumentation aus dem Artikel, nach der die Leute, die in den vergangenen neun Tagen intensivpflichtig geworden sind, damals bereits krank waren und in diesem Sinn nicht mehr viel zu ändern sein würde.

    Ich hatte dann kurz überlegt, ob vielleicht bei der Normalisierung der Ableitungen (das incs /= sum(abs(incs)) irgendwas schief gegangen sein kann. Aber nein, eine Angabe wie „44%“ ist natürlich selbst normalisiert („pro hundert“). Der Verdacht jedoch führte schon mal in die richtige Richtung: Nachdenken über die Ableiterei und was dabei so passiert.

    Bevor ich da weiterknoble, zunächst die eigenliche Selbstbezichtung, denn was ich vor neun Tagen zumindest hätte tun sollen, wäre eine simple Validierung an den bestehenden Daten, nämlich am unmittelbar vorhergehenden 9-Tage-Intervall. Am 27.10. war die Intensivbelegung bei 1707, in den neun Tagen vor dem 6.11. war die Intensivbelegung also um 37% gestiegen. Es wäre ganz leicht gewesen, gleich nachzusehen, ob auch die Meldezahlen des RKI in den neun Tagen davor um etwas wie 37% gestiegen sind. Ich hätte festgestellt, dass sie das nicht sind – am 27.10. lag die RKI-Meldeinzidenz bei 118, am 18.10. bei 74, ein Anstieg also um satte 59% –, und das hätte mir gesagt, dass ich einen Fehler gemacht habe.

    Auch dann hätte ich vermutlich, wie heute auch, den nächsten Verdacht auf die heftige Kontamination der tageweisen Inzidenzschätzungen des RKI durch Wochenenden und Co gelenkt – schon in meinem allerersten Corona-Post hatte ich die bejammert. Vielleicht ist es ja das? Im Programm von neulich glätte ich deshalb vor der Ableitung. Die geglättete Kurve kommt am 18.10. auf 75, am 27.10. auf 120, und für den 6.11. habe ich noch keine geglätteten Daten, weil da noch zu viele Randeffekte dabei sind. Das ist sehr nah an den ungeglätteten Daten. Also, nein: Das macht repariert meine Fehlvorhersage nicht.

    Der wirkliche Fehler

    Das tatsächliche Problem liegt in der Methode, und zwar nicht in dem komplizierten Teil. Die Berechnung des Verzuges mit all dem Glätten und Ableiten ist völlig in Ordnung. Das Problem ist vielmehr, und ein wenig Nachdenken über Schulmathematik hätte mich darauf bringen können, in der Natur der Ableitung. Bei der gehen Konstanten nämlich verloren: (d)/(dx)(f(x) + C) = (d)/(dx)f(x). Ein hoher Sockel von Langzeit-IntensivpatientInnen wird bei meiner Verzögerungsrechnung einfach wegdifferenziert. Das ist ja sogar der Sinn der Differenziererei.

    Nur: Wenn ich am Schluss blind „44% mehr“ rechne, wird der Sockel (das C) mitmultipliziert, und genau da wird es falsch. Die richtige Rechnung wäre gewesen, die Differenz der Inzidenzen über die neun Tage vor dem 27.10. (von 74 auf 118) zu vergleichen mit der Differenz der Intensivbelegung der neun Tage vor dem 6.11 (von 1707 auf 2332) – dabei geht der Verzug ein, irgendwelche konstanzen Sockel spielen aber keine Rolle.

    Dieser Vergleich ergibt einen, sagen wir, 9-Tage-Übersetzungfaktor von 625 ⁄ 44 ≈ 14. In diesem stecken die Demographie der Erkrankten, die Eigenschaften des Virus, das Verhalten der Bevölkerung, und alles andere, was die mittlere Wahrscheinlichkeit bestimmt, mit einer SARS-2-Infektion intensivpflichtig zu werden. Unter der Annahme jedoch, dass der Übersetzungsfaktor über kurze Zeiten in etwa kontant ist, kann mensch jetzt die Entwicklung korrekt vorhersagen. Und zwar übersetzt sich demnach die Inzidenzentwicklung zwischen 27.10. und 6.11. (von 118 auf 164) 14-fach in die Intensivbelegung der jetzt gerade vergangenen neun Tage (das ist letztlich etwas wie ein Momentanwert von meiner int/inc-Metrik aus dem September).

    Ich hätte damit am 6.11. vorhergesagt, die Intensivbelegung würde um 46⋅16 = 644 zunehmen oder eben auf 2332 + 644 = 2976, in guter Übereinstimmung mit dem berichteten Wert von 3034.

    Blöd, dass ich nach meinen Zahlen- und Interpolationsspielen beim Zusammenbau der Vorhersage nicht aufgepasst habe. Aber es zeigt mal wieder, dass Mathe voll ist mit Fallen und ein Moment der Unaufmerksamkeit ziemlich unausweichlich zu zwanghaftem Vertilgen von Hüten führt. Und dabei hätte ich mir durch einfache Versuche, die Zukunft der Verangenheit vorherzusagen – ein sehr probates Mittel, wann immer mensch Zeitreihen analysiert – diese wenig erfreuliche Mahlzeit sparen können. Rülps.

    Aus eine physikalischen Betrachtung heraus ist diese Methode auch nicht so arg befriedigend, denn natürlich gibts bei den Meldezahlen keinen Sockel. Die sind ja selbst schon Ableitungen[1], nämlich die der Gesamtzahl der Infizierten. Die Intensivbelegung ist von der Genese her noch komplexer, da dort Zu- wie Abgänge eingehen. Insofern ist die Sache mit dem Übersetzungsfaktor zutiefst phänomenologisch und kann also aus vielen Gründen brechen.

    Schauen wir also mal, wie es in neun Tagen, am 24.11., aussieht. Meine Vorhersage wäre 3034 + (303 − 184)⋅14 = 4700. Das ist auch von der Dynamik her nicht mehr weit weg von der Höchstbelegung am 3.1.2021 (5762), und ohne ziemlich deutliche „Maßnahmen” werden wir wohl recht bald an der vorbeirauschen.

    [1]Wobei: Solange die Entwicklung exponentiell ist, ist das mit der Ableitung in diesem Kontext quasi wurst, denn die Exponentialfunktion ex ist ihre eigene Ableitung. Reale Wachstumsfunktionen über der Zeit t sehen aus wie N(1 + r)t = Neln(1 + r)⋅t, wobei r die Wachstumsrate ist (mit RKI-Zahlen R-Wert minus 1). Die Ableitung solcher Funktionen sind sie selbst mal einem konstanten Faktor, und der würde bequem in unserem Übersetzungfaktor 14 aufgehen. Wie gesagt: alles erstmal phänomenologisch.
  • Corona: Neue Filme, Alte Zahlen

    Weil sich sowohl bei Inzidenz als auch bei Altersstruktur der Corona-Meldungen gerade viel tut, habe ich meine beiden Coronafilme neulich neu rechnen lassen. Dabei habe ich beim Inzidenzfilm noch darauf verzeichtet, den Wertebereich über die 350 hinaus zu erweitern, auch wenn das bewirkt, dass sowohl der Kreis mit der höchsten Inzidenz gestern (Miesbach mit 715 Fällen/100'000) als auch der Kreis mit der 33st-höchsten und mithin nur halb so hohen Inzidenz (Ostallgäu mit 350/100'000) saturiert erscheinen.

    Irgendwas werde ich da bei der nächsten Aktualisierung tun müssen, denn, wie z.B. ich im September ausgeführt habe: eine 300-er Inzidenz bedeutet, dass es sechs Jahre dauert, bis alle mal SARS-2 hatten. Es wird im anderen Worten Inzidenzen in den Tausendern brauchen, wenn SARS-2 in nächster Zeit zu einem der anderen humanen Coronaviren werden soll, mit denen zu leben wir alle schon als Kinder schniefend gelernt haben.

    XKCD-cartoon

    Randall Munroe hat mir in der Woche mal wieder aus dem Herzen gesprochen. CC-BY-NC xkcd

    Schniefend, so wie ich jetzt, denn seit letztem Freitag habe ich meine erste richtige Erklältung seit Corona. Ich hatte ganz vergessen, wie doof sowas ist (und nein, ausweislich zweier Antigentests gleich am Freitag und dann am Montag nochmal ist es kein SARS-2). Schon deshalb habe ich gestern mit viel Interesse den Wochenbericht des RKI gelesen, in dem ja immer die Ergebnisse der Influenzasurveillance (Seite 13) berichtet werden. Über die Proben von an respiratorischen Infekten erkrankten Personen steht dort gestern:

    In der virologischen Surveillance der AGI wurden in der 43. KW 2021 in insgesamt 118 von 204 eingesandten Proben (58 %) respiratorische Viren identifiziert. Darunter befanden sich 61 Proben mit Respiratorischen Synzytialviren (RSV) (30 %), 31 mit Rhinoviren (15 %), 20 mit humanen saisonalen Coronaviren (hCoV) (10 %), acht mit SARS-CoV-2 (4 %), sechs mit Parainfluenzaviren (3 %) sowie eine Probe mit humanen Metapneumoviren (0,5 %). Influenzaviren wurden in der 43. KW 2021 nicht nachgewiesen.

    Wenn das irgendwie repräsentativ ist, habe ich eine gute Chance, dass meine derzeitige Pest RSV ist und ich den Rhinoviren Unrecht getan habe, wenn ich sie schon am Freitag mit den saftigsten Flüchen belegt habe. Tatsächlich habe ich aber schon vor dem oben gezeigten XKCD 2535 überlegt, wer mich da wohl gerade quält. Ich glaube jedenfalls, Randall Munroe ist gerade auch erkältet.

    Aber zurück zu meinen Überlegungen vom September: Ich hatte damals ja bejammert, dass wir seit Anfang der Pandemie, von steilen Inzidenzflanken nach oben (etwas niedrigeres int/inc) und unten (deutlich höheres int/inc) abgesehen, eigentlich immer so 20 SARS-belegte Intensivbettern pro Inzidenzpunkt (int/inc) hatten und das grob bedeutet, dass Inzidenzen über 300 ein Gemetzel werden.

    Ich muss leider sagen, dass sich das nicht wesentlich geändert hat. An der stark steigenden Flanke am 2.11.2020 lag int/inc nach RKI-Zahlen bei 2243 ⁄ 120 ≈ 19, derzeit, ebenfalls an einer stark ansteigenden Flanke ist das 2226 ⁄ 155 ≈ 15. Seufz.

    Etwas einschränkend dazu zwei Punkte:

    • Mein Plot neulich hat, wo verfügbar, mit Referenzdaten gerechnet, also, wo rekonstruierbar, den Ansteckungs- und nicht den Meldedaten. Damit kommt mensch für Anfang November 2020 auch auf ein int/inc von rund 15; mit den aktuellen Daten geht das aber nicht, einfach weil von den jetzigen Daten viele Daten aus der Zukunft fehlen, deren Referenzdaten irgendwann mal heute sein werden. Deshalb vergleiche ich hier ganz blind in beiden Fällen die instantanen RKI-Meldezahlen und vergesse meine raffiniertere Technik vom September.
    • Ein wesentlicherer Einwand ist, dass wir in diesem Jahr von einem weitaus höheren Sockel kommen und deshalb in Wirklichkeit die Flanke in der Intensivantwort wesentlich weniger steil ist als im letzten Jahr und sie wahrscheinlich auch in Zukunft vermutlich nicht gleich auf 20 oder sowas zurücklaufen wird, wenn die Inzidenzentwicklung abflacht.

    Das mag so sein, aber qualitativ ändert das alles nicht viel: Unser int/inc ist um mindestens eine Größenordnung zu groß, als dass „wir“ entspannt auf 1000er-Inzidenzen hinlaufen könnten; ob bei 300 (sechs Jahre bis zur Endemisierung) oder bei 500 (vier Jahre) Schluss ist, ist in dieser Betrachtung eher nebensächlich.

    Mein told you so (auch schon im Juli, vierter Absatz) wäre vielleicht befriedigender, wenn das auch im September nicht eigentlich jedeR gesagt hätte, der/die nicht woandershin geschaut hat (was bis neulich sehr populär war, und nur so ist irgendwie plausibel zu machen, warum es ausgereicht jetzt hektische Krisentreffen gibt). Andererseits hatte ich damals auch gesagt:

    wir dürften also, wenn nicht ein Wunder geschieht, in sechs Wochen, Mitte Oktober, deutlich über 4000 liegen und damit in der Gegend der Notbremsenbelastung rund um Neujahr 2021.

    – und damals geschah ein Wunder, denn aus mit dem Sommerreiseverkehr endete auch die damalige exponentielle Füllung der Intensivstationen mit SARS-2-PatientInnen; in DIVI-Zahlen aus den RKI-Tagesberichten:

    Steigende Kurve mit langem Atemholen zwischen Mitte September und Mitte Oktober

    Was zwischen Mitte September und Mitte Oktober – oder, unter der Annahme, dass die Intensivantwort zwei, drei Wochen verzögert auf ihre Ursachen kommt, einfach im September – anders war als davor und danach, das würde mich wirklich interessieren.

  • Math with ReStructuredText and Pelican

    I recently wrote a piece on estimating my power output from CO₂ measurements (in German) and for the first time in this blog needed to write at least some not entirely trivial math. Well: I was seriously unhappy with the way formulae came out.

    Ugly math of course is very common as soon as you leave the lofty realms of LaTeX. This blog is made with ReStructuredText (RST) in pelican. Now, RST at least supports the math interpreted text role (“inline”) and directive (“block“ or in this case rather “displayed“) out of the box. To my great delight, the input syntax is a subset of LaTeX's, which remains the least cumbersome way to input typeset math into a computer.

    But as I said, once I saw how the formulae came out in the browser, my satifsfaction went away: there was really bad spacing, fractions weren't there, and things were really hard to read.

    In consequence, when writing the post I'm citing above, rather than reading the docutils documentation to research whether the ugly rendering was a bug or a non-feature, I wrote a footnote:

    Sorry für die hässlichen Formeln. Vielleicht schreibe ich mal eine Erweiterung für ReStructuredText, die die ordentlich mit TeX formatiert. Oder zumindest mit MathML. Bis dahin: Danke für euer Verständnis.

    (Sorry for the ugly formulae. Perhaps one of these days I'll write an RST extension that properly formats using TeX. Or at least MathML. Until then: thanks for your understanding.)

    This is while the documentation clearly said, just two lines below the example that was all I had initially bothered to look at:

    For HTML, the math_output configuration setting (or the corresponding --math-output command line option) selects between alternative output formats with different subsets of supported elements.

    Following the link at least would have told me that MathML was already there, saving me some public embarrassment.

    Anyway, when yesterday I thought I might as well have a look at whether someone had already written any of the code I was talking about in the footnote, rather than properly reading the documentation I started operating search engines (shame on me).

    Only when those lead me to various sphinx and pelican extensions and I peeked into their source code I finally ended up at the docutils documentation again. And I noticed that the default math rendering was so ugly just because I didn't bother to include the math.css stylesheet. Oh, the miracles of reading documentation!

    With this, the default math rendering suddenly turns from ”ouch” to “might just do”.

    But since I now had seen that docutils supports MathML, and since I have wanted to have a look at it at various times in the past 20 years, I thought I might as well try it, too. It is fairly straightforward to turn it on; just say:

    [html writers]
    math_output: MathML
    

    in your ~/.docutils (or perhaps via a pelican plugin).

    I have to say I am rather underwhelmed by how my webkit renders it. Here's what the plain docutils stylesheet works out to in my current luakit:

    Screenshot with ok formulae.

    And here's how it looks like via MathML:

    Screenshot with less ok formulae.

    For my tastes, the spacing is quite a bit worse in the MathML case; additionally, the Wikipedia article on MathML mentions that the Internet Explorer never supported it (which perhaps wouldn't bother me too much) and that Chromium withdrew support at some point (what?). Anyway: plain docutils with the proper css is the clear winner here in my book.

    I've not evaluated mathjax, which is another option in docutils math_output and is what pelican's render_math plugin uses. Call me a luddite, but I'll file requiring people to let me execute almost arbitrary code on their box just so they see math into the big folder labelled “insanities of the modern Web”.

    So, I can't really tell whether mathjax would approach TeX's quality, but the other two options clearly lose out against real TeX, which using dvipng would render the example to:

    Screenshot with perfect formulae

    – the spacing is perfect, though of course the inline equation has a terrible break (which is not TeX's fault). It hence might still be worth hacking a pelican extension that collects all formulae, returns placeholder image links for them and then finally does a big dvipng run to create these images. But then this will mean dealing with a lot of files, which I'm not wild about.

    What I'd like to ideally use for the small PNGs we are talking about here would be inline images using the data scheme, as in:

    <img src="data:image/png;base64,AAA..."/>
    

    But since I would need to create the data string when docutils calls my extension function, I in that scheme cannot collect all the math rendering for a single run of LaTeX and dvipng. That in turn would mean either creating a new process for TeX and dvipng each for each piece of math, which really sounds bad, or hacking some wild pipeline involving both, which doesn't sound like a terribly viable proposition either.

    While considering this, I remembered that matplotlib renders quite a bit of TeX math strings, too, and it lets me render them without any fiddling with external executables. So, I whipped up this piece of Python:

    import base64
    import io
    import matplotlib
    from matplotlib import mathtext
    
    matplotlib.rcParams["mathtext.fontset"] = "cm"
    
    def render_math(tex_fragment):
        """returns self-contained HTML for a fragment of TeX (inline) math.
        """
        res = io.BytesIO()
        mathtext.math_to_image(f"${tex_fragment}$",
          res, dpi=100, format="png")
        encoded = base64.b64encode(res.getvalue()).decode("ascii")
        return (f'<img src="data:image/png;base64,{encoded}"'
            f' alt="{tex_fragment}" class="math-png"/>')
    
    if __name__=="__main__":
        print(render_math("\int_0^\infty \sin(x)^2\,dx"))
    

    This prints the HTML with the inline formula, which with the example provided looks like this: \int_0^\infty \sin(x)^2\,dx – ok, there's a bit too much cropping, I'd have to trick in transparency, there's no displayed styles as far as I can tell, and clearly one would have to think hard about CSS rules to make plausible choices for scale and baseline – but in case my current half-satisfaction with docutils' text choices wears off: This is what I will try to use in a docutils extension.

  • Falscher Instinkt

    Ausschnitt aus dem RKI-Bericht von heute

    Anlass meiner Paranoia: Im RKI-Bericht von heute drängeln sich verdächtig viele Kreise gerade unter der 50er-Inzidenz.

    Mein Abgesang auf die RKI-Berichte von neulich war wie erwartet etwas voreilig: Immer noch studiere ich werktäglich das Corona-Bulletin des RKI. Es passiert ja auch wieder viel in letzter Zeit. Recht schnell schossen die ersten Landkreise im Juli über die 50er-Schwelle, während die breite Mehrheit der Kreise noch weit von ihr entfernt war. Das ist, klar, auch so zu erwarten, wenn die „Überdispersion“ (find ich ja ein komisches Wort für „die Verteilung der Zahl der von einem_r Infizierten Angesteckten hat einen langen Schwanz nach oben hin“, aber na ja) noch irgendwie so ist wie vor einem Jahr, als, wie im inzwischen klassischen Science-Artikel von Laxminarayan et al (DOI 10.1126/science.abd7672) auf der Grundlage von Daten aus Indien berichtet wurde, 5% der Infizierten 80% der Ansteckungen verursachten (und umgekehrt 80% der Infizierten gar niemanden ansteckten): SARS-2 verbreitete sich zumindest in den Prä-Alpha- und -Delta-Zeiten in Ausbrüchen.

    Nachdem aber die ersten Landkreisen die 50 gerissen hatten, tat sich für eine ganze Weile im Bereich hoher Inzidenzen nicht viel; auch heute sind nur drei Landkreise über der 50er-Inzidenz, während sich knapp darunter doch ziemlich viele zu drängen scheinen.

    Und da hat sich ein Verdacht in mir gerührt: Was, wenn die Gesundheitsämter sich mit Händen und Füßen wehren würden, über die vielerorts immer noch „maßnahmenbewehrte“ 50er-Schwelle zu gehen und ihre Meldepraktiken dazu ein wenig… optimieren würden? Wäre das so, würde mensch in einem Histogramm der Inzidenzen (ein Häufigkeit-von-Frequenzen-Diagram; ich kann die nicht erwähnen ohne einen Hinweis auf Zipfs Gesetz) eine recht deutliche Stufe bei der 50 erwarten.

    Gibt es die? Nun, das war meine Gelegenheit, endlich mal mit den Meldedaten zu spielen, die das RKI bereitstellt – zwar leider auf github statt auf eigenen Servern, so dass ich mit meinen Daten statt mit meinen Steuern bezahle (letzteres wäre mir deutlich lieber), aber das ist Jammern auf hohem Niveau. Lasst euch übrigens nicht einfallen, das ganze Repo zu klonen: Das sind ausgecheckt wegen eines gigantischen Archivs krasse 24 GB, und was ihr tatsächlich braucht, sind nur die aktuellen Zahlen (Vorsicht: das sind auch schon rund 100 MB, weil das quasi die ganze deutsche Coronageschichte ist) und der Landkreisschlüssel (vgl. zu dem Update unten).

    Auch mit diesen Dateien muss mensch erstmal verstehen, wie aus deren Zeilen die Inzidenzen werden, denn es ist nicht etwa so, dass jede Zeile einer Erkrankung entspricht: Nein, manche berichten mehrere Fälle, es wird nach schon gemeldeten und ganz neuen Fällen unterschieden, und eventuell gibts auch noch Korrekturzeilen. Dazu findet ein in-band-signalling zu Gestorbenen und Genesenen statt. Lest das README aufmerksam, sonst verschwendet ihr nur (wie ich) eure Zeit: EpidemiologInnen denken ganz offenbar etwas anders als AstronomInnen.

    Das Ergebnis ist jedenfalls das hier:

    unverdächtig aussehendes Histogramm

    Ich muss also meinen Hut essen: Wenn da irgendwo Hemmschwellen sein sollten, dann eher knapp unter 40, und das ist, soweit ich weiß, in keiner Corona-Verordnung relevant. Na ja, und der scharfe Abfall knapp unter 25 könnte zu denken geben. Aber warum würde jemand bei der 25 das Datenfrisieren anfangen? Der Farbe im RKI-Bericht wegen? Nee, glaub ich erstmal nicht.

    Wenn ihr selbst mit den RKI-Daten spielen wollt, kann euch das Folgende vielleicht etwas Fummeln ersparen – hier ist nämlich mein Aggregationsprogramm. Ich werdet die Dateipfade anpassen müssen, aber dann könnt ihr damit eure eigenen Inzidenzen ausrechnen, ggf. auch nach Altersgruppen, Geschlechtern und was immer. In dem großen CSV des RKI liegt in der Tat auch die Heatmap, die jetzt immer im Donnerstagsbericht ist. Reizvoll fände ich auch, das gelegentlich zu verfilmen…

    Hier jedenfalls der Code (keine Abhängigkeiten außer einem nicht-antiken Python). So, wie das geschrieben ist, bekommt ihr eine Datei siebentage.csv mit Landkreisnamen vs. Inzidenzen; die entsprechen zwar nicht genau dem, was im RKI-Bericht steht, die Abweichungen sind aber konsistent mit dem, was mensch von lebenden Daten erwartet:

    # (RKI-Daten zu aktuellen 7-Tage-Meldeinzidenzen: Verteilt unter CC-0)
    import csv
    import datetime
    import sys
    
    LKR_SRC = "/media/incoming/2020-06-30_Deutschland_Landkreise_GeoDemo.csv"
    INF_SRC = "/media/incoming/Aktuell_Deutschland_SarsCov2_Infektionen.csv"
    LANDKREIS = 0
    MELDEDATUM = 3
    REFDATUM = 4
    NEUER_FALL = 6
    ANZAHL_FALL = 9
    
    
    def getcounts(f, n_days=7):
        counts = {}
        collect_start = (datetime.date.today()-datetime.timedelta(days=n_days)
            ).isoformat()
        sys.stderr.write(f"Collecting from {collect_start} on.\n")
    
        row_iter = csv.reader(f)
        # skip the header
        next(row_iter)
    
        for row in row_iter:
            if row[MELDEDATUM]>=collect_start:
                key = int(row[LANDKREIS])
                kind = row[NEUER_FALL]
                if kind!="-1":
                    counts[key] = counts.get(key, 0)+int(row[ANZAHL_FALL])
    
        return counts
    
    
    def get_lkr_meta():
        lkr_meta = {}
        with open(LKR_SRC, "r", encoding="utf-8") as f:
            for row in csv.DictReader(f):
                row["IdLandkreis"] = int(row["IdLandkreis"])
                row["EW_insgesamt"] = float(row["EW_insgesamt"])
                lkr_meta[row["IdLandkreis"]] = row
    
        return lkr_meta
    
    
    def main():
        lkr_meta = get_lkr_meta()
        with open(INF_SRC, "r", encoding="utf-8") as f:
            counts = getcounts(f)
    
        with open("siebentage.csv", "w", encoding="utf-8") as f:
            f.write("Lkr, Inzidenz\n")
            w = csv.writer(f)
            for lkr in lkr_meta.values():
                w.writerow([lkr["Gemeindename"],
                    1e5*counts.get(lkr["IdLandkreis"], 0)/lkr["EW_insgesamt"]])
    
    
    if __name__=="__main__":
        main()
    

    Nachtrag (2021-08-13)

    Eine Woche später ist der Damm definitiv gebrochen. Von drei Landkreisen über dem 50er-Limit sind wir laut aktuellem RKI-Bericht jetzt bei 39, wobei allein seit gestern 10 dazukamen. An die aktuelle Verteilung würde ich gerne mal eine Lognormalverteilung fitten:

    noch unverdächtiger aussehendes Histogramm

    Nicht, dass ich eine gute Interpretation hätte, wenn das lognormal wäre. Aber trotzdem.

    Nachtrag (2021-09-08)

    Das RKI hat die Landkreis-Daten (2020-06-30_Deutschland_Landkreise_GeoDemo.csv) aus ihrem Github-Repo entfernt (commit cc99981f, „da diese nicht mehr aktuell sind“; der letzte commit, der sie noch hat, ist 0bd2cc53). Die aus der History rausklauben würde verlangen, das ganze Riesending zu clonen, und das wollt ihr nicht. Deshalb verteile ich unter dem Link oben die Datei unter CC-BY 4.0 International, mit Namensnennung… nun, Destatis wahrscheinlich, oder halt RKI; die Lizenzerklärung auf dem Commit ist nicht ganz eindeutig. Als Quelle der Geodaten war vor der Löschung https://www.destatis.de/DE/Themen/Laender-Regionen/Regionales/Gemeindeverzeichnis/Administrativ/Archiv/ angegeben, aber da finde ich das nicht.

  • Es waren die Läden

    Na gut, und/oder die Schulen. Meine Vorhersage vom 16.1. jedenfalls, nach der sich der damas fast zwei Wochen alte Abwärtstrend bei der Intensivbelegung (als hierzulande einzige halbwegs zuverlässige Maßzahl fürs Infektionsgeschehen) in etwa in der Folgewoche nach oben wenden würde, war falsch. Die fallende Intensivbelegung setzt sich fort, plusminus exponentiell mit einer Halbierungszeit von gut sechs Wochen:

    Plot: Gerade in Log/log

    (die Achsen wären ähnlich wie am 16.1., aber darauf kommts mir hier nicht an).

    Nachdem vor drei oder vier Wochen zumindest anekdotisch und von hier aus gesehen nicht viel mehr Heimarbeit lief als vor Weihnachten, bleibt dann wohl nur der Schluss, dass meine Überzeugung, Ansteckungen fänden vor allem in den Betriebe und beim Berufspendeln statt, falsch war – während sich die Schätzung von einer Verzögerung von rund drei Wochen zwischen Ansteckungen und Intensivzahlen wohl als recht robust erweist.

    Denn dann reflektiert die Wende von wachsender zu fallender Intensivbelegung vom 4.1. ziemlich klar die weitgehende Schließung der Läden und Schulen rund um den 16.12. Schade, dass beides wieder so parallel lief, denn so bleibt es schwierig, rauszufinden, was dann was ausgemacht hat.

    Und: Dann war der große Ausbruch Anfang Dezember wirklich das Weihnachtsshopping? Tödlicher Konsum my ass.

Seite 1 / 1

Letzte Ergänzungen