• Bingo zur Wahl

    Bullshit Bingo-Karten zur Wahl

    Wer solche Bingo-Karten haben will: Das Wahlbingo-CGI macht sie euch gerne. Jeder Reload macht neue Karten!

    Auch wenn verschiedene Posts der letzten Zeit etwas anderes suggerieren mögen: Ich will gewiss nicht in die von Plakatwänden und aus Radiolautsprechern quellende Wahlaufregung einstimmen. Aber ein wenig freue ich mich doch auf die Bundestagswahl am nächsten Sonntag: ich kann nämlich wieder mein Wahlbingo spielen. Ihr kriegt bei jedem Reload der Bingo-Seite andere Karten, und zumindest Webkit-Browser sollten das auch so drucken, dass auf einer A4-Seite zwei Bingokarten rauskommen.

    Die Regeln sind dabei: Wer in der Wahlkampfberichterstattung eine hinreichend ähnliche Phrase aufschnappt, darf ein Feld abkreuzen (die Hälfte vom Spaß ist natürlich die lautstarke Klärung der Frage, ob eine Phrase ähnlich genug war). Wer zuerst vier…

    Nachtrag (2022-03-07)

    Die Erfahrung zeigt, dass es mit drei mehr Spaß macht.

    …Felder in horizonaler, vertikaler, oder diagonaler Richtung hat, hat gewonnen. Dabei gelten periodische Randbedingungen, mensch darf also über den Rand hinaus verlängern, als würde die eigene Karte die Ebene parkettieren.

    Das Ganze ist übrigens ein furchtbar schneller Hack an irgendeinm Wahlabend gewesen. Ich habe den gerade noch geschwinder für das Blog in ein CGI gewandelt. Wer darauf etwas Aufgeräumteres aufbauen will: die Quellen. Spenden für den Phrasenkorpus nehme ich sehr gerne per Mail.

  • Ad hominem

    Die Ideenwelt der repräsentativen Demokratie hat etliche Ungereimtheiten – was an sich nicht notwendig katastrophal[1] ist, siehe RiwaFiw. Speziell zu Wahlkampfzeiten muss ich aber doch manchmal meinen Kopf bis an die Grenze zum Schleudertrauma schütteln.

    Derzeit ist in Heidelberg etwa das hier plakatiert:

    Wahlplakat mit eigenartigem Brustportrait und einem Slogan

    Klar, mensch könnte das einfach mit „selbst schuld“ wegnicken und weiterfahren. Aber für mich will diese Sorte Plakat einfach nicht zusammengehen mit der öffentlichen Ächtung von Attacken auf die Person von KandidatInnen und PolitikerInnen („ad hominem“), und das nicht nur, weil das Plakat recht unbestreitbar eine ad hominem-Selbstattacke ist.

    Schön, das ad hominem-Tabu war schon immer mehr deklariert als gelebt (was gerade die zugeben müssen, die sich gerne öffentlich nach Herbert Wehner und Franz Josef Strauß sehnen), aber als normative Richtschnur des Handelns ist es im Wesentlichen unbestritten. Wenn also Kritik ad hominem nicht statthaft ist: Warum zeigt dann die Mehrheit der Wahlplakate „ernstzunehmender“ Parteien die Portraits der KandidatInnen und nicht etwa, sagen wir, eine politische Position oder wenigstens ein hübsches Bild zur Aufwertung des Straßenraums, Dinge jedenfalls, die anzugreifen nicht Tabu ist?

    Der „Digitalturbo“ im Plakat oben zählt übrigens mangels Bedeutung nicht als politische Position. „Digitalisierung“ ist Antisprache, versucht also aktiv, nichts zu sagen. „Turbo“ hingegen ist eine dämliche Autometapher, der positiv nur die radikale Selbstentlarvung zuzurechnen ist. Der Kluge führt unter dem Lemma Turbine aus:

    1. turbo (-inis) m. „Wirbel; alles, was sich im Kreis dreht“

    Ich erfinde das nicht.

    Eine politische Position, die tatsächlich etwas bedeutet, wäre etwa public money, public code gewesen, oder vielleicht „hohe Hürden bei Zugriff auf Tk-Bestandsdaten“ (cf. Post vom 2021-01-31). Doch, sowas passt auf ein Plakat, und mit etwas Mühe kriegt mensch auch Muggels erklärt, was das jeweils bedeutet. Allerdings müsste ich bei einem „Master of Public Policy“ (was Nusser ausweislich seiner Online-Biografie ist) zunächst noch überzeugt werden, dass der Kandidat tatsächlich Einsicht hätte in das, was er da sagen würde.

    Da seine Parole leer ist: was eigentlich soll mensch kritisieren als das Restplakat, also das Bild? Wenn das Bild nur die Person zeigt, wird die Kritik notwenig ad hominem. Das ist besonders bitter, wenn der Kandidat aussieht, als habe er starke Schwierigkeiten bei der Ablösung von der Mutter (oder jedenfalls bei der Impulskontrolle). Hand aufs Herz: Wer hatte bei Nussers Foto nicht gleich das Bild im Kopf vom pummeligen Einzelgänger in der Schule, der Verachtung und Hänselei der Mitschülis jetzt durch Dampfplaudern im Machoclub FDP kompensiert? [Mitschülis von Nusser: wie irrig ist diese Fantasie?]

    Wer solche, eingestandermaßen üblen, Reflexe nicht haben will: Wie gesagt, thematische Bilder statt Köpfe auf Plakaten würden sich anbieten, bei der selbsternannten Wachstumspartei FDP vielleicht viele Autos und viel Beton oder so. Weniger ansprechend als die Portraits der KandidatInnen wird das in der Regel auch nicht sein, solange nicht gerade Rana Plaza oder Union Carbide in Bhopal als Symbole für die Segnungen des Freihandels herhalten müssten.

    Besser wärs aber wahrscheinlich, ganz auf Fotos zu verzichten, etwa nach US-Vorbild:

    Vorgarten mit Wahlschildern, auf denen nur Namen stehen

    Um euch die Arbeit zu ersparen, anhand der Namen herauszubekommen, wann und wo die Szene spielt: Das Foto entstand 2002 in Massachussetts, und die schon etwas extreme Botschaftsdichte mag damit zusammenängen, dass der Vorgartenbesitzer im liberalen Jamaica Plain Werbung für alle möglichen Kandidaten der Republicans machte. Mensch sieht: Rechte Trolle sind keine Erfindung des facebook-Zeitalters.

    So oder so: Wahlwerbung in den USA ist, soweit ich das sehe, immer noch, wenn Leute die Namen ihrer LieblingskandidatInnen in den Vorgarten stellen (ok, und am Straßenrand mit Namenschildern winken). Keine Fotos, keine leeren Slogans.

    Ich glaube ja, das ist weit mehr im Geist der repräsentativen Demokratie, bei der Menschen ja genau nicht etwa die wählen sollen, die aussehen wie sie selbst; von Lookismus-Prävention will ich gar nicht anfangen. Der größte Vorteil aber: ästhetische Tiefschläge wie der folgende aus dem Jahr 1998 unterbleiben:

    Wahlplakat von Karl A. Lamers
    [1]Nur zur Vorsicht sollte ich wohl sagen, dass ich damit natürlich mitnichten repräsentative Demokratie befürwortet haben will; eine dahingehende Beurteilung aus informationstheoretischer Sicht verspreche ich schon mal für demnächst.
  • Reading a zyTemp Carbon Dioxide Monitor using Tkinter on Linux

    Last weekend I had my first major in-person conference since the SARS-2 pandemic began: about 150 people congregated from all over Germany to quarrel and, more importantly, to settle quarrels. But it's still Corona, and thus the organisers put in place a whole bunch of disease control measures. A relatively minor of these was monitoring the CO2 levels in the conference hall as a proxy for how much aerosol may have accumulated. The monitor devices they got were powered by USB, and since I was sitting on the stage with a computer having USB ports anyway, I was asked to run (and keep an eye on) the CO2 monitor for that area.

    A photo of the CO2 meter

    The CO2 sensor I got my hands on. While it registers as a Holtek USB-zyTemp, on the back it says “TFA Dostmann Kat.Nr. 31.5006.02“. I suppose the German word for what's going on here is “Wertschöpfungskette“ (I'm not making this up. The word, I mean. Why there are so many companies involved I really can only guess).

    When plugging in the thing, my syslog[1] intriguingly said:

    usb 1-1: new low-speed USB device number 64 using xhci_hcd
    usb 1-1: New USB device found, idVendor=04d9, idProduct=a052, bcdDevice= 2.00
    usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    usb 1-1: Product: USB-zyTemp
    usb 1-1: Manufacturer: Holtek
    usb 1-1: SerialNumber: 2.00
    hid-generic 0003:04D9:A052.006B: hiddev96: USB HID v1.10 Device [Holtek USB-zyTemp] on usb-0000:00:14.0-1/input0
    hid-generic 0003:04D9:A052.006C: hiddev96: USB HID v1.10 Device [Holtek USB-zyTemp] on usb-0000:00:14.0-1/input0
    

    So: The USB is not only there for power. The thing can actually talk to the computer. Using the protocol for human interface devices (HID, i.e., keyboards, mice, remote controls and such) perhaps is a bit funky for a measurement device, but, on closer reflection, fairly reasonable: just as the mouse reports changes in its position, the monitor reports changes in CO2 levels and temperatures of the air inside of it.

    Asking Duckduckgo for the USB id "04d9:a052" (be sure to make it a phrase search with the quotes our you'll be bombarded by pages on bitcoin scams) yields a blog post on decrypting the wire protocol and, even better, a github repo with a few modules of Python to read out values and do all kinds of things with them.

    However, I felt like the amount of code in that repo was a bit excessive for something that's in the league of what I call a classical 200 lines problem – meaning: a single Python script that works without any sort of installation should really do –, since all I wanted (for now) was a gadget that shows the current values plus a bit of history.

    Hence, I explanted and streamlined the core readout code and added some 100 lines of Tkinter to produce co2display.py3, showing an interface like this:

    A co2display screenshot

    This is how opening a window (the sharp drop of the curve on the left), then opening a second one (the even sharper drop following) and closing it again while staying in the room (the gentle slope on the right) looks like in co2display.py. In case it's not obvious: The current CO2 concentration was 420 ppm, and the temperature 23.8 degrees Centigrade (where I'm sure the thing doesn't measure to tenths of Kelvins; but then who cares about thenths of Kelvins?) when I took that screenshot.

    If you have devices like the zyTemp yourself, you can just download the program, install the python3-hid package (or its equivalent on non-Debian boxes) and run it; well, except that you need to make sure you can read the HID device nodes as non-root. The easiest way to do that is to (as root) create a file /etc/udev/rules.d/80-co2meter.rules containing:

    ATTR{idVendor}=="04d9", ATTR{idProduct}=="a052", SUBSYSTEM=="usb", MODE:="0666"
    

    This udev rule simply says that whenever a device with the respective ids is plugged in, any device node created will be world-readable and world-writable (and yeah, it does over-produce a bit[2]).

    After adding the rule, unplug and replug the device and then type python3 co2display.py3. Ah, yes, the startup (i.e., the display until actual data is available) probably could do with a bit of extra polish.

    First Observations

    I'm rather intrigued by the dynamics of CO2 levels measured in that way (where I've not attempted to estimates errors yet). In reasonably undisturbed nature at the end of the summer and during the day, I've seen 250 to 280 ppm, which would be consistent with mean global pre-industrial levels (which Wikipedia claims is about 280 ppm). I'm curious how this will evolve towards winter and next spring, as I'd guess Germany's temporal mean will hardly be below the global one of a bit more than 400 (again according to Wikipedia).

    In a basically empty train I've seen 350 ppm yesterday, a slightly stuffy train about 30% full was at 1015 ppm, about as much as I have in my office after something like an hour of work (anecdotically, I think half an hour of telecon makes for a comparable increase, but I can hardly believe that idle chat causes more CO2 production than heavy-duty thinking. Hm).

    On a balcony 10 m above a reasonably busy road (of order one car every 10 seconds) in a lightly built-up area I saw 330 ppm under mildly breezy conditions, dropping further to 300 as the wind picked up. Surprisingly, this didn't change as I went down to the street level. I can hardly wait for those winter days when the exhaust gases are strong in one's nose: I cannot imagine that won't be reflected in the CO2.

    The funkiest measurements I made on the way home from the meeting that got the device into my hands in the first place, where I bit the bullet and joined friends who had travelled their in a car (yikes!). While speeding down the Autobahn, depending on where I measured in the small car (a Mazda if I remember correctly) carrying four people, I found anything from 250 ppm near the ventilation flaps to 700 ppm around my head to 1000 ppm between the two rear passengers. And these values were rather stable as long as the windows were closed. Wow. Air flows in cars must be pretty tightly engineered.

    Technics

    If you look at the program code, you'll see that I'm basically polling the device:

    def _update(self):
      try:
        self._take_sample()
        ...
      finally:
        self.after(self.sample_interval, self._update)
    

    – that's how I usually do timed things in tkinter programs, where, as normal in GUI programming, there's an event loop external to your code and you cannot just say something like time.wait() or so.

    Polling is rarely pretty, but it's particularly inappropriate in this case, as the device (or so I think at this point) really sends data as it sees fit, and it clearly would be a lot better to just sit there and wait for its input. Additionally, _take_sample, written as it is, can take quite a bit of time, and during that time the UI is unresponsive, which in this case means that resizes and redraws don't take place.

    That latter problem could easily be fixed by pushing the I/O into a thread. But then this kind of thing is what select was invented for, or, these days, wrappers for it (or rather its friends) usually subsumed under “async programming“.

    However, marrying async and the Tkinter event loop is still painful, as evinced by this 2016 bug against tkinter. It's still open. Going properly async on the CO2monitor class in the program will still be the next thing to do, presumably using threads.

    Ah, that, and recovering from plugging the device out and in again, which would also improve behaviour as people suspend the machine.

    Apart from that, there's just one detail I should perhaps highlight in the code: The

    self.bind("<Configure>", lambda ev: self._update_plot())
    

    in the constructor. That makes the history plot re-scale if the UI is re-sized, and I've always found it a bit under-documented that <Configure> is the event to listen for in this situation. But perhaps that's just me.

    Nachtrag (2021-10-19)

    I've updated co2display.py3 as published here, since I've been hacking on it quite a bit in the meantime. In particular, if you rename the script co2log.py (or anything else with “log” in it), this will run as a plain logger (logging into /var/log/co2-levels by default), and there's a systemd unit at the end of the script that lets you run this automatically; send a HUP to the process to make it re-open its log; this may be useful together with logrotate if you let this run for weeks your months.

    You can also enable logging while letting the Tk UI run by passing a -d option …

  • Ehrlichkeit in Parteiprogrammen

    Über einen Artikel in der Wochenzeitung Kontext bin ich auf eine Kleinstudie des Zentrums für europäische Wirtschaftsforschung (ZEW) gestoßen, auf die ich vor allem im Hinblick auf eine spätere Nutzung zur Mythenstörung kurz eingehen möchte.

    Zu bedenken ist zunächst, dass das ZEW gewiss in keinem Verdacht steht, irgendwelche fortschrittlichen Ideen zu hegen. So gehört zu deren aktuellen „Empfehlungen für die Wirtschaftspolitik“ offensichtlicher Quatsch der Art „Standardisierte Altersvorsorgeprodukte einführen“ oder Deflektorschilde gegen eine entspanntere, arbeitsärmere und umweltfreunlichere Gesellschaft des Typs „Kostengerechte Aufteilung der CO2-Reduktionen zwischen den Sektoren“; aktuelle Pressemitteilungen beten marktradikale Wirrnisse herunter wie „Lokale Preisanreize im Strommarkt setzen“ (Faustregel: „Anreiz“ heißt im Klartext: Geld von unten nach oben umverteilen) oder „Bundesnetzagentur sollte weiterhin auf Auktionen setzen“, ganz als sei 1998.

    Ausgerechnet diese Leute haben in ihrer Kleinstudie zu den fiskalischen und ökonomischen Folgen der aktuellen Parteiprogramme herausgefunden, dass das Programm der Linken den Staathaushalt um 37 Milliarden Euro entlasten würde, während die FDP den Haushalt mit 88 Millarden Euro belasten würde und die CDU immer noch 33 Millarden Euro mehr Staatsdefizit ansagt.

    So viel zur Frage fiskalischer Verantwortung in der Theorie, soweit also mensch Wahlprogramme ernstnehmen will. Zumindest sollte die Studie traugen, um die Erzählungen von „wirtschaftlicher Vernunft“ bei den Rechtspartien als Legenden zu entlarven.

    Die Studie liefert weiter Hinweise zum Thema „Turkeys voting for Christmas“, also Armen, die Rechtsparteien wählen (davon gibt es augenscheinlich einen ganzen Haufen): Das VEW hat nämlich auch die Folgen der Programme für den Gini-Koeffizienten abgeschätzt, also einer Metrik für die Ungleichheit der Einkommen in einer Gesellschaft, der mit wachsender Ungleichheit wächst. Souveränder Spitzenreiter dabei ist die AfD, die die Ungleichheit in dieser Metrik um 3.8% verschärfen würde, wo selbst die FDP die Dinge nur 3.4% schlimmer machen will (und die CDU um 1.6%). Demgegenüber würde das Wahlprogramm der Linken – take this, ExtremismustheoretikerInnen! – die Ungleichheit um knapp 15% reduzieren. Wenn denn irgendwas davon umgesetzt würde, käme sie an die Regierung; spätestens nach der Katastrophe der Schröder-Administration dürfte klar sein, dass das ungefähr so wahrscheinlich ist wie ein ernsthaftes Aufbegehren gegen den permanenten Bürgerrechtsabbau durch eine FDP in der Regierung. Die Grünen würden laut VEW die Ungleichheit um 6.5% reduzieren, und selbst die vom für Cum Ex und Hartz IV bekannten Scholz geführte SPD wäre noch mit -4.3% dabei.

    Klar: das Ganze ist eine stark zirkuläre Argumentation, denn Programme der Parteien haben viel mit den Methoden des ZEW und Metriken wie dem Gini-Koeffizienten gemein, alle drei aber sicher nicht viel mit irgendwelchen Realitäten. In der gemeinsamen, wenn auch hermetischen Logik bleibt festzuhalten: die bekennenden Rechtspartien betreiben unzweifelhaft die Umverteilung von unten nach oben auf Kosten des Staatshaushalts.

    Und das taugt ja vielleicht später nochmal für ein Argument innerhalb dieser hermetischen Welt.

  • Vom Töten und Massenschlachten

    Heute morgen hat der Deutschlandfunk das IMI-Urgestein Tobias Pflüger interviewt (Informationen am Morgen, 14.9.), und die Art, in der der Interviewende versucht hat, Tobias dazu zu bringen, sich für einen „Mangel“ an Bellizismus zu entschuldigen, war erwartbar empörend. Umgekehrt aber war Tobias schon sehr zahm, verglichen jedenfalls mit dem militanten Pazifismus, den ich von ihm eigentlich kenne; nun ja, er trat auch als stellvertretender Vorsitzender der Linken auf, und die will erkennbar regieren[1].

    Das – wie natürlich auch das ultrazynische Rührstück um die „Ortskräfte“, die die Bundeswehr aus dem gleichen Afghanistan „rettete“, in das die Regierung in den Vormonaten noch mindestens 167 Menschen abschieben hat lassen – wiederum gibt mir den Vorwarnd, endlich ein paar politische Gegenstücke zum Tucholsky-Klassiker „Soldaten sind [meinethalben potenzielle] Mörder“ zu formulieren, die ich schon lang irgendwo unterbringen wollte (auch wenn ich anerkenne, dass sie vermutlich nicht sehr originell sind und bestimmt schon oft ganz ähnlich von PazifistInnen, AnarchistInnen und anarchistischen PazifistInnen formuliert wurden; ich sollte vermutlich mehr von solchen Leuten lesen).

    Erste Behauptung: Eine Regierung, die sich ein Militär hält, will für die eigene Macht Menschen töten.

    Für den Fall, dass jemand das nicht unmittelbar offensichtlich findet, will ich ein paar Ableitungsschritte nennen. Erstens ist nämlich Militär schicht dafür da, Krieg zu führen oder Aufstände zu unterdrücken. Ich gebe zu, dass die Bundeswehr auch schon Dämme ausgebessert, Brunnen gebohrt, und in Impfzentren ausgeholfen hat. Sie war dabei aber immer ausnehmend schlecht, bis hin zur Unfähigkeit, die Impfunterlagen korrekt und halbwegs gestapelt zusammenzutackern. Das ist soweit erwartbar, denn sowohl das Rumgeballer als auch die Gehorcherei sind bei nichttödlichen Einsätzen klar störend. Wer Personal für „humanitäre“ Einsätze vorhalten will, würde selbstverständlich keine Gewehre und Waffen kaufen und viel Geld dafür ausgeben, den Leuten den Umgang damit (statt mit Baggern, Bohrern und Büroklammern) beizubringen.

    Mithin geht es beim Militär um Personal zum Bedienen von Kriegswaffen, und das heißt zum Führen von Krieg (bei der Aufstandsbekämpfung ist das der Sonderfall des Bürgerkriegs).

    Was aber ist Krieg? Krieg ist auf der einen Seite der Versuch einer Regierung, eine andere Regierung zu ersetzen, entweder durch sich selbst („Eroberungskrieg“) oder durch eine der eigenen Machtausübung weniger hinderliche („Nation Building“). Und entweder komplett oder nur in einem Teil des Machtbereichs der anderen Regierung.

    Auf der anderen Seite ist Krieg der Versuch einer Regierung, die eigene Macht gegen eine andere Regierung oder Teile der Bevölkerung (beim Bürgerkrieg) zu halten. Wie herum es im Einzelfall auch sein mag: Es geht allein darum, Macht auszuweiten oder zu erhalten.

    Selbst wenn mensch der eigenen Regierung wider jede Evidenz (die Bundeswehr hat derzeit in, wievielen?, zwanzig oder so, anderen Ländern Waffen) unterstellt, sie sei dabei in der Rolle der machterhaltenden, quasi verteidigenden Regierung: Sie könnte jede Menge Blutvergießen verhindern, wenn sie einfach zurücktreten würde und sagen, die „angreifende“ Regierung könne ja gerne versuchen, ob sie es besser kann. Es gäbe dann keinen Krieg, und ob die Regierungsführung am Boden wirklich wesentlich schlechter wäre, ist überhaupt nicht ausgemacht. Ich z.B. würde es wahrscheinlich begrüßen, wenn die Schweiz die Regierung in Baden übernehmen würde. Oder Luxemburg: soweit es mich betrifft, könnten die mich schon erobern, denn sooo viel unethischer und steuerparadiesiger als meine gegenwärtige Regierung sind die auch nicht, aber ich glaube, deren Sozialsystem macht schon ein wenig mehr her.

    Ach, wenn nicht gerade Macron regiert, würde jetzt auch ein Überfall aus Frankreich nicht offensichtlich zu einem Rückschritt führen, wenn die Machtübergabe hinreichend friedlich passiert. Ich versuche ohnehin im Augenblick, ein wenig Französisch zu lernen.

    Also: Regierungen, die ein Militär unterhalten, sagen damit klar an, dass sie für ihre Macht töten wollen. Auf jeden Fall mal die Soldaten der anderen Regierungen.

    Es kommt aber noch schlimmer: Wie ich in meinem Furor über die Weigerung der deutschen Regierung, dem Atomwaffenverbotsvertrag TPNW beizutreten, argumentiert habe, sind Kernwaffen nur einsetzbar, um Hunderttausende oder Millionen von Untertanen einer (na ja: in der Regel) anderen Regierung zu töten. Es gibt schlicht keine anderen glaubhaften Einsatzszenarien.

    Mithin ist, wer die Bombe werfen will, gewillt, für die eigene Macht Städte in Schlachthäuser zu verwandeln. Alle deutschen Regierungen meiner Lebenszeit waren ganz wild auf die „nukleare Teilhabe“ und hatten damit diesen Willen. Die zweite Behauptung, die ich hier machen will, ergibt sich damit unmittelbar: Wer in der BRD lebt, wird regiert von Menschen, die für ihre Macht Städte ausradieren werden.

    Es wäre also schon ein großer zivilisatorischer Fortschritt, wenn sich die nächste Regierung durchringen könnte zum Statement, sie könne sich schon vorstellen, zwecks Machterhalt ein paar hundert, tausend, oder zehntausend Menschen zu töten (also: sie löst die Bundeswehr nicht einfach auf, was natürlich der erfreulichste Ausgang wäre); der eigene Machterhalt würde aber doch nicht rechtfertigen, dutzendweise Städte einzuäschern (weshalb sie den Spuk der nuklearen Teilhabe beenden und dem TPNW beitreten würde).

    Ich wette dagegen.

    [1]Da ich wild entschlossen bin, niemals mit meiner Zustimmung regiert zu werden und also nie der künftigen Regierung meine Stimme geben will – das ist mir bisher auch nicht schwer gefallen –, konnte ich daher leider den Linken nicht meine Stimme geben. Repräsentative Demokratie ist schon manchmal kompliziert, denn im Parlament will ich die Linke selbstverständlich schon haben: Wo wären wir heute ohne ihre parlamentarischen Anfragen?
  • Kopfzahlen: Kohlendioxid

    Es gibt eine Handvoll Zahlen, die ich versuche, so ungefähr im Kopf zu haben. Ich nenne die gerne Kopfzahlen, auch wenn das Wort laut Duden was ganz anderes bedeutet.

    Die klassische Kopfzahl ist natürlich die Zahl der Sekunden in einem Jahr, mit guter Genauigkeit π ⋅ 1e7 (ich schreibe hier aus Bequemlichkeit und Computergewohnheit 107 als 1e7). Überlegungen des Typs „ich habe eine Milliarde Datensätze und schaffe 3000 pro Sekunde, also brauche ich für das ganze Ding ungefähr 300000 Sekunden oder halt 3e5/3e7, also ein hundertstel Jahr oder vier Tage“ finde ich sehr hilfreich. Würde ich Mathematik an einer Schule unterrichten, würde ich Depressionen kriegen, wenn meine Schülis sowas nicht hinkriegen würden, nachdem ich ein Jahr auf sie eingeredet habe. Gut, dass ich kein Schullehrer bin.

    Heute nun hat mich die Deutsche Umwelthilfe (DUH) angeschrieben, weil sie Spenden haben will für Klagen gegen BMW, Daimler und Wintershall[1]. Die Brücke zu den Kopfzahlen: sie sagen darin, Wintershall sei allein für rund 80 Megatonnen CO2 im Jahr verantwortlich.

    Um solche Angaben ein wenig einordnen zu können, hatte ich mir vor zehn Jahren zwei Kopfzahlen zurechtgelegt: Die BRD emittierte rund eine Gigatonne, die Welt rund dreißig Gigatonnen CO2. Demnach macht Wintershall rund 8% des CO2-Ausstoßes der BRD aus; das ist nicht unplausibel, aber ich dachte mir, das ist ein guter Anlass, meinen schon etwas länger gehegten Plan umzusetzen, solche Kopfzahlen im Blog zu notieren und zu aktualisieren. Wie steht es nun also, zehn Jahre nach 1 und 30 Gigatonnen?

    Für halbwegs überschaubare Infos zu den BRD-Emissionen hatte ich ganz naiv auf die Publikationen zum Emissionshandel des UBA gehofft, aber zumindest der Juli-Bericht ist in der Hinsicht nicht sehr ergiebig: Was genau heißt es, dass in der Kalenderwoche 27 Emissionsrechte über 280 Millionen Tonnen gehandelt wurden (außer, dass ein Haufen Leute nicht sehr nützliche Arbeit hatten)?

    Aber das Umweltbundesamt hat glücklicherweise eine andere Seite mit nicht marktkontaminierten Informationen. Demnach wären 2020 in der BRD 644 Millionen Tonnen CO2 emittiert worden. Auf drei Stellen genau ist das natürlich lächerlicher Unfug; ich wäre überrascht, wenn das auf 10% irgendeiner sinnvollen Definition von Emission entspräche. Aber dennoch: 2/3 Gigatonnen klingen nach einer brauchbaren Kopfzahl für die aktuelle Kohlendioxid-Emission direkt aus der BRD. Natürlich wären dazu die importierten Emissionen (z.B. aus brasilianischem Sojaanbau für „unser“ Fleisch oder chinesischer Zement- und Stahlproduktion für „unsere“ Häuser und Elektronik) zu rechnen, aber das wird dann kompliziert und letztlich spekulativ.

    Neu merken sollte ich mir den Quellen-Split, den sie dort aufmachen, wieder bereinigt um allzu mutige Claims bezüglich Genauigkeit: Energie 1/3, Haushalte 1/5, Straßenverkehr ein gutes Fünftel, Industrie (wozu dann auch z.B. Hausbau gehört) 1/4.

    Für die globale Emission gibt der einschlägige Artikel der Wikipedia 57 Gigatonnen CO2-Äquivalent an, wo dann allerdings jede Menge tiefes Voodoo reingerechnet ist („including 5 Gt due to land use change“).

    Um dem tiefen Voodoo zu entkommen (und nur das Einsteiger-Voodoo der Emissionsschätzung zu behalten), kann mensch zum aus meiner Sicht relativ vertrauenswürdigen Our World in Data gehen, das eine Kohlendioxid-Seite anbietet, die wiederum auf github-Daten verweist, wo schließlich CO2 und Treibhausgas-Äquivalente separat ausgewiesen sind. Deutschland hat dabei für 2019 700 Mt; das passt im Rahmen meiner Erwartungen gut zu unseren 2/3 Gt für 2020 von oben. Für die Welt (freundlicherweise gibt es die in dem Datensatz schon vorkumuliert unter „World“) und 2019 stehen da mit absurden acht Stellen 36441.388 Mt. Schon zwei Stellen Genauigkeit sind da sicher überoptimistisch, und so wäre meine Kopfzahl für die Weltemission jetzt „um die 35 Gt“.

    Mein Spickzettel für diese Runde Kopfzahlen ist also:

    • Emission in der BRD: 2/3 Gt, davon anteilig 1/3 Energie, 1/4 Industrie, je rund 1/5 Verkehr und Haushalte.
    • Emission in der Welt: 35 Gt, womit die BRD direkt ungefähr 1/50 der Welt-Emission ausmacht.
    [1]Dass mich die DUH immer noch in ihrem CRM-System hat, obwohl ich ihnen eigentlich nur vor Jahren mal gespendet habe – die erfolgreichen Fahrverbots-Klagen haben mich schon sehr begeistert – finde ich jetzt nicht so großartig, aber wer sich so effektiv dem Autowahnsinn entgegenstellt, darf in menem Buch auch mal nicht ganz so korrekt mit Daten umgehen.
  • Die Intensiv-Antwort

    Ich habe ja immer noch nicht so recht meinen Frieden gemacht mit dem Schluss von 66 ist das neue 50 vom letzten Freitag, dass nämlich die Impfkampagne bisher fast keinen Unterschied macht für unsere Fähigkeit, hohe Inzidenzen – die wir praktisch sicher bald haben werden, wenn wir nicht wieder viel weiter zumachen als derzeit – zu ertragen, ohne dass die Intensivstationen zu einem Schlachtfeld werden.

    Die Frage lässt sich zurückführen auf: „Wie viele Intensivbetten waren eigentlich relativ zur jeweiligen Inzidenz durch SARS-2-Erkrankte belegt?“ (bei allen berechtigten Zweifeln an der zuverlässigen Messung letzterer). Diese Antwort der Intensivbelegung auf das Infektionsgeschehen – ich taufe es mal int/inc, weil ich zu faul bin, nachzusehen, wie die Profis das nennen – kriege ich mit dem Besteck vom Coronafilm-Post und meiner DIVI-Auswertung relativ schnell ausgerechnet, und wenn ich dann das Verhältnis von DIVI-Belegung (gezogen jeweils aus den RKI-Berichten der Zeit) zur bundesweiten Inzidenz (auf der Basis der Referenz-Daten des RKI) plotte, sieht das so aus:

    Ein großes Maximum im Juli 2021

    Ich habe die y-Achse wieder logarithmisch eingeteilt, in dem Fall nicht, weil ich irgendwelche exponentiellen Verläufe erwarten würde, sondern weil mir im Wesentlichen der Verlauf im unteren Teil des Wertebereichs am Herzen liegt.

    Das dominierende Feature Anfang Juli 2021 nämlich ist schnell erklärt: Hier waren die Inzidenzen sehr niedrig, die langwierigen Fälle blieben aber auf den Intensivstationen. Und so ging es bis zu 120 IntensivpatientInnen pro Punkt Inzidenz. Ähnlich reflektiert das zweithöchste Feature rund um den Februar 2021 lediglich die fallende Inzidenz und also quasi vorauseilend kleine Nenner zwischen zweiter und dritter Welle.

    Wenn mensch sich diese großen Features mal rausdenkt, kommt als Basis etwas heraus zwischen 20 und 40 Intensivpatient_innen pro Inzidenzpunkt während der Wellen. Mitte August, als die Inzidenzen kräftig anzogen, haben wir vielleicht auch mal 10 touchiert, was zu erwarten wäre, wenn die Basisrate 30 wäre und um die zwei Drittel der Leute geimpft sind. Angesichts der dramatischen Altersabhängigkeit der Hospialisierung von SARS-2 sind solche Überlegungen aber ohne demographische Betrachtungen unsinnig.

    Der Anstieg ganz am rechten Rand des Graphen dürfte übrigens zumindest in diesem Ausmaß ein Artefakt sein, denn ich rechne hier wie gesagt mit dem, was das RKI als Referenzdatum angibt (wo das Infektionsdatum das Meldedatum ersetzt, wenn das rauszukriegen ist), und es kann so sein, dass aus den letzten zwei Wochen Fälle in die weitere Vergangenheit gewandert sind, die, die sie in Zukunft aus der Gegenwart bekommen werden, aber noch nicht da sind; das würde die Inzidenz unterschätzen und mein int/inc überschätzen.

    Nehmen wir trotzdem an, wir hätten mit der derzeitigen Virenpopulation, Infektionsdemographie und Impfquote im Gleichgewicht 20 Intensivpatient_innen pro Indizenzpunkt. Wenn wir dann unter 6000 Intensivpatient_innen bleiben wollen, ist eine 300er-Inzidenz das äußerste, was mit viel Glück zu stemmen wäre. Wenn also nicht mein int/inc drastisch runtergeht – als Faustregel dürfte taugen, dass jede Halbierung des Anteils der ungeimpften Erwachsenen auch eine Halbierung von int/inc nach sich ziehen würde –, wird es noch lang dauern, bis die (relativ) strikte Kontrolle von SARS 2 aufhören kann.

    Eine 300er-Inzidenz in der RKI-Rechnung heißt ja, dass jede Woche 300 von 100000 Menschen SARS-2 hinter sich bringen. Bis dann alle mal SARS-2 hatten (und alle werden es irgendwann gehabt haben, dauerhaft sterile Impfungen gibts bei Atemwegserkrankungen nicht), dauert es logischerweise 100000/300, also gut 300 Wochen. Oder grob sechs Jahre.

    Sorry, liebe Ungeimpfte: so lange will ich echt nicht warten, bis ich nicht mehr an jeder Ecke damit rechnen muss, Namen und Geburtsdatum (im Impfzertifkat) von mir nicht annähernd kontrollierbaren Rechnern überantworten zu müssen.

    Technics

    Der Code, der das erzeugt, ist nicht spannend; mit corona.py sieht die Inzidenzberechnung so aus:

    def get_incidences(tuples):
        """returns a mapping of dates to 7-day incidences from RKI tuples
        as yielded by corona.iter_counts.
        """
        tuples.sort(key=lambda r: r[0])
        incidences = {}
        queue = collections.deque([0], maxlen=7)
        cur_date = None
    
        for tup in tuples:
            if tup[0]!=cur_date:
                if len(queue)==7:
                    incidences[cur_date] = sum(queue)/830
                queue.append(0)
                cur_date = tup[0]
    
            queue[-1] += tup[2]
    
        incidences[cur_date] = sum(queue)/83e4
        return incidences
    
       with open(corona.DATA_DIR
              +"Aktuell_Deutschland_SarsCov2_Infektionen.csv") as f:
          all_rows = list(corona.iter_counts(f, True))
      incidences = get_incidences(all_rows)
    

    Das Zusammenfummeln mit den DIVI-Daten nimmt meine aus den RKI-Berichten gescreenscrapten Daten. Das ist an sich Quatsch, und ihr solltet die Daten einfach von der DIVI selbst ziehen, wenn ihr das reproduzieren wollt.

    Mit dem zusammengefummelten Daten (Spalten: Datum, int/inc, Intensivbelegung und referenzdatenbasierte Inzidenz) könnt ihr aber selbst Plots machen. Das Bild oben kommt aus diesem Gnuplot-Skript:

    set size ratio 0.375
    set key inside left top
    set xdata time
    set yrange [5:200]
    set ytics (10,22,47,100)
    set timefmt "%Y-%m-%d"
    set xrange ['2020-08-01':'2021-08-31']
    set logscale y
    set xtics format "%Y-%m-%d" time
    set term svg size 800,300
    set out "int-vs-inc.svg"
    plot "int-vs-inc.txt" using 1:2 with lines title "int/inc"
    

    ElektronikbastlerInnen werden die Ticks auf der y-Achse wiedererkennen. Logarithmen sind überall.

  • 66 ist das neue 50

    Ich sage es nicht gerne, aber: Entweder wir machen im Winter wieder einen Lockdown oder wir kriegen ein übles Gemetzel.

    Ich hatte ja schon im Januar erzählt, warum ich die Intensivbelegung für die aussagekräftigste Zahl halte, die in den RKI-Berichten vorkommt (natürlich mit dem Nachteil, dass sie für Echtzeitsteuerung nicht taugt, weil sie so weit nachläuft). Und die sieht seit ein paar Wochen übel aus, nämlich praktisch so wie im letzten Oktober:

    Im September 2021 siehts aus wie im Oktober 2020

    SARS 2-Intensivbelegung seit Mitte letzten Jahres in einem Log-Plot (also: exponentielle Entwicklung ist eine Gerade). Zur Verdeutlichung habe ich die Kurve seit diesem Juli nochmal weiß unterlegt neben die Gesamtkurve seit August 2020 gestellt: mensch sieht, wie sich die Verläufe ähneln, abgesehen von der höheren Ausgangsbasis in diesem Jahr. Die grüne Kurve ist übrigens die Zahl der invasiv Beatmeten. Sie hört mittendrin auf, weil der RKI-Tagesbericht die entsprechenden Daten nicht mehr berichtet hat.

    Die Verdopplungszeit ist derzeit so rund drei Wochen; 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.

    In der Tat scheint es, als habe die Impfkampagne enttäuschend wenig Einfluss auf diese Zahlen. Heute ist die SARS 2-Intensivbelegung laut RKI-Bericht 1169 bei einer Inzidenz von 80. Eine vergleichbare Belegung war am 23.10.2020 mit 1121 bei einer Inzidenz von 60. Von einer Entkopplung der Intensivbelegung von der Inzidenz kann also keine Rede sein, und schon gar nicht vom „200 ist das neue 50“, das Gesundheitsminister Spahn vor ein paar Wochen wagte. Dazu kommt, dass die Dunkelziffer angesichts des immer noch relativ engen Testregimes in diesem Jahr vermutlich niedriger ist als letztes Jahr und mithin die damalige Inzidenz nach oben korrigiert werden müsste, um mit aktuellen Zahlen vergleichbar zu sein. Selbst ohne so eine Korrektur ist allenfalls 50 ⋅ (80/60) = 66 das neue 50.

    Warum kaum ein Impfeffekt sichtbar ist in diesen Zahlen: Tja, das ist eine spannende Frage, und ich bin neugierig auf Christian Drostens Kommentare dazu, wenn es heute abend wieder ein neues Coronavirus-Update gibt (endlich!). Mein persönlicher Verdacht ist etwas gruselig. Wahrscheinlich stimmen die anekdotischen Berichte, dass aus den Alten- und Pflegeheimen in den ersten drei Wellen kaum Menschen in Intensivstationen überwiesen wurden und sie in aller Regel einfach an Ort und Stelle starben. Die jüngeren Menschen hingegen, die es jetzt vermehrt erwischt (auch wenn der Altersmedian weniger schwankt als ich glaubte), erhalten vermutlich erheblich häufiger Intensivpflege. Ich bin nicht sicher, ob ich da ein „hoffe ich“ dazu schreiben möchte.

    Ohne einen „Delta-Effekt“ wird diese Erklärung jedoch nicht auskommen, denn von den rund 1000 relativ jungen Menschen, denen im letzten Juni bei Tönnies SARS-2 reingedrückt wurde, landeten, soweit ich weiß, keine auf Intensivstationen – und jedenfalls starben keine. Bei vor drei Wochen (als sich heute eingelieferte so plusminus angesteckt haben werden) rund 30000 RKI-aktiven SARS-2-Fällen und einer derzeit vermutlich mit der Tönnies-Belegschaft vergleichbaren Demographie dürften die Intensivstationen eigentlich nicht volllaufen, wenn das Virus nicht eine ganze Ecke fieser geworden wäre.

    Wie dem auch sei: Meine Hoffnung, dass mit jüngeren Kranken und vielen Geimpften höhere Inzidenzen ohne Gemetzel durchhaltbar sind, war klar unbegründet. Das aber macht erneute Notbremsen ab Oktober (und vielleicht schon früher) zu einer praktischen Gewissheit. Ich vermute stark, dass diese Geimpfte anfangs ausnehmen werden. Ich nehme keine Wetten an zur Frage, ob das ausreichen wird. So'n Mist.

  • Wenn LektorInnen schlafen

    Als jemand, dem es schon in der BRD zu frömmelnd zugeht, bin ich ziemlich sicher nicht in Gefahr, allzu große Sympathien für die neue afghanische Regierung („Taliban“) zu hegen. Und trotzdem schmerzt so gut wie die gesamte Berichterstattung über das Regime, gerade im Vergleich zum doch recht gemäßigten Umgang mit Saudi-Arabien. Dort nämlich geht es nach innen hin wohl ziemlich ähnlich zu, doch die Taliban führen immerhin keinen Krieg nach außen, schon gar nicht einen in der Liga des Gemetzels im Jemen.

    Aber selbst wenn sich JournalistInnen in patriotischer[1] Botmäßigkeit verpflichtet fühlen, den Krieg zu rechtfertigen, den unsere Regierungen mit breiter publizistischer Unterstütztung in den letzten zwanzig Jahren „am Hindukusch“ geführt haben: Wenigstens etwas Sorgfalt sollten sie walten lassen. Auf Seite 9 der taz vom 24.8.2021 ist das ganz offenbar nicht passiert. Während Finn Mayer-Kuckuk vierspaltig einen „Rückfall in den Handel mit Drogen“ drohen sieht, stellt der Agenturartikel in der fünften Spalte klar, dass bereits das von „uns“ befreite Afghanistan 85% des Weltbedarfs an Opiaten gedeckt hat:

    Oben: „Es droht ein Rückfall in den Handel mit Drogen“.  Unten: „Afghanistan produziert UN-Angaben zufolge rund 85 Prozent des weltweit hergestellten Opiums“

    Rechte bei der taz; hier verwendet unter… Satireprivileg?

    EinE gutE LektorIn hätte es gemerkt.

    Wo ich schon über Afghanistan spreche, möchte ich noch kurz ein Standbild aus der Tagesschau vom 28.8.2021 zeigen:

    Eingang zum „Hamid Karzai International Airport“

    Rechte wahrscheinlich bei der Tagesschau.

    Das entscheidende Detail hier ist: Das alte Regime war unbescheiden genug, den Flughafen nach dem immerhin noch lebenden und (z.B. nach der Lebenserwartung der Untertanen bemessen) gewiss nicht sehr erfolgreichen Ex-Präsidenten Hamid Karzai zu benennen. Nur mal so als ein Datenpunkt zur Erklärung, warum die Regierung, die „wir“ dort 20 Jahre lang installiert hatten, noch vor „unserem“ Abzug so ostentativ kollabiert ist.

    Zum Abschluss hätte ich einen Buchtipp in dem Zusammenhang: Cockburn, A. und St. Clair, J., 1998: „Whiteout: The CIA, Drugs, and the Press“, London, New York: Verso (verfügbar in der Imperial Library of Trantor). Der Guardian hat es damals rezensiert mit:

    A history of hypocrisy and political interference the like of which only Frederick Forsyth in a dangerous caffeine frenzy could make up.

    Dem kann ich zustimmen.

    [1]Wo ich es schon von Patriotismus habe, will ich einen Aufkleber lobend erwähnen, den ich neulich in Hamburg-Wilhelmsburg gesehen habe: „Wer als Patriot*in losläuft, kommt als Faschist*in an“. Wenn nur das Wetter nicht so lausig wäre in der Gegend – mensch könnte da fast hinziehen wollen.
  • Lieblingsgesetze

    Ich bin in den letzten Tagen unabhängig voneinander zwei Mal auf Gesetze gestoßen, die nach Titel oder Inhalt großartig sind, so großartig, dass ich bestimmt mal irgendwann auf sie werde zurückgreifen wollen, um etwas wie „…geregelt in, sagen wir, §42 Käseverordnung“ zu sagen. Das waren:

    • Käseverordnung: Laut Wikipedia hat es so eine schon 1934 gegeben; und nur so lässt sich wohl erklären, dass sie Marketroids anbietet, mit Wörtern wie „Vollfettstufe“ (§5 Käseverordnung) zu werben für ihre „frische[n] oder in verschiedenen Graden der Reife befindliche[n] Erzeugnisse, die aus dickgelegter Käsereimilch hergestellt sind“ (aus §1 Käseverordnung). Großartig ist das übrigens nicht nur wegen der Parallelbildung zu Käseblatt, sondern auch, weil in Jasper Ffordes großartigen Thursday Next-Romanen Käseschmuggel aus Wales eine große Rolle spielt und §30 Käseverordnung manchmal schon nach der Bookworld dieser epochalen Werke klingt.
    • Bundeskleingartengesetz: Das geht immerhin bis §22, wobei allerdings ein Paragraph weggefallen ist und §19 lediglich aus „Die Freie und Hansestadt Hamburg gilt für die Anwendung des Gesetzes auch als Gemeinde“ besteht, es dafür aber allen Ernstes zwei Buchstabenparagraphen gibt (§20a, „Überleitungsregelungen aus Anlaß der Herstellung der Einheit Deutschlands“, passt schon vom Titel her großartig zum bierernsten Ton der Gartenregeln). Eingestanden: So albern, wie Gesetze für KleingärtnerInnen zunächst wirken, wird das wohl am Ende nicht sein. Oder doch? Ich kann mich einfach nicht entscheiden, auch nicht, nachdem ich den DLF-Hintergrund vom 18.8. gehört habe (full disclosure: ich weiß nur aufgrund dieser Sendung überhaupt von der Existenz des BKleingG).
  • Corona-Film, Teil 2

    Am Ende meines Posts zum Corona-Inzidenzfilm hatte ich zuversichtlich gesagt, der RKI-Datensatz gebe durchaus auch Plots von Altersmedianen her. Tja… da habe ich den Mund etwas zu voll genommen, denn was wirklich drinsteht, sind Altersgruppen, und die sind so grob, dass eine halbwegs seriöse Schätzung hinreichend dekorativer (also: mit mindestens 256 verschiedenen Werten) Mediane doch einige Überlegung erfordert.

    Die Altersgruppen reichen aber auch ohne Sorgfalt, um eine Art Score auszurechnen (ich verrate gleich, wie ich das gemacht habe), und damit ergibt sich zum Beispiel dieser Film:

    (sollte euer Browser das vermurksen: Download).

    Nachtrag (2021-11-03)

    Nur damit sich niemand wundert, wie Herbst-Zahlen in einen Post vom August kommen: Ich habe den Film bis November 2021 fortgesetzt und werde ihn künftig wohl noch ein paar Mal aktualisieren.

    Was ist da zu sehen? Die Farbskala gibt etwas, das ich Alters-Score genannt habe. Dabei habe ich die Altersgruppen aus den RKI-Daten so in Zahlen übersetzt:

    A00-A04 2
    A05-A14 10
    A15-A34 20
    A35-A59 47
    A60-A79 70
    A80+ 85
    unbekant ignoriert

    Das, was dabei rauskommt, mittele ich für alle berichteten Fälle innerhalb von 14 Tagen. Die robustere und ehrlichere Alternative wäre wahrscheinlich, da einen interpolierten Median auszurechnen, aber das habe ich schon deshalb gelassen, weil ich dann möglicherweise eine obere Grenze bei A80+ hätte annehmen müssen; so, wie es ist, ist es allenfalls ein Score, dessen Vergleichbarkeit zwischen Kreisen angesichts wahrscheinlich recht weit auseinanderliegender Altersverteilungen so la-la ist. Mehr Substanz als Uni- oder Mensarankings hat er aber auf jeden Fall (was kein starker Claim ist).

    Wirklich fummelig an dieser Visualisierung war, dass für weite Zeiträume in vielen Kreisen entweder gar keine Daten vorliegen, einfach weil es keine Infektionen gab, oder die Schätzung auf so wenigen Fällen beruht, dass sie recht wenig Bedeutung hat. Letzteres würde ein starkes Blubbersignal liefern, das in Wirklichkeit nur das Rauschen schlechter Schätzungen beziehungsweise schlecht definierter Verteilungen ist.

    Deshalb habe ich die Inzidenz in die Transparenz gesteckt; zwecks Abstand vom Hintergrund-Weiß fange ich dabei aber gleich bei 20% an, und weil mir 100 Fälle robust genug erscheinen, setze ich ab einer 14-Tage-Inzidenz von 100 auch 100% Deckung. Wo Daten ganz fehlen, male ich nur die Umrisse der Kreise.

    Was habe ich aus dem Film gelernt? Nun, offen gestanden erheblich weniger als aus dem Inzidenzfilm im letzten Post. Ich hatte eigentlich gehofft, dass (mit der derzeitigen Colourmap) ein dramatischer Umschwung von rötlich nach bläulich stattfindet, wenn Anfang 2021 die Impfungen in den großen Altenpflegeeinrichtungen anlaufen. Das ist aber allenfalls dann sichtbar, wenn mensch genau drauf aufpasst. Überhaupt hat mich überrascht, wie niedrig die Alters-Scores doch meist sind. Hätte ich vorher nachgedacht, hätten sowohl die Inzidenz-Heatmap des RKI wie auch einige Prosa zu den Altersverteilungen das allerdings schon stark nahegelegt, so etwa im letzten Wochenbericht des RKI:

    Von allen Todesfällen waren 79.101 (86%) Personen 70 Jahre und älter, der Altersmedian lag bei 84 Jahren. Im Unterschied dazu beträgt der Anteil der über 70-Jährigen an der Gesamtzahl der übermittelten COVID-19-Fälle etwa 13 %.

    – Corona war zwar von den Folgen her vor allem ein Problem ziemlich alter Menschen, getragen haben die Pandemie aber praktisch durchweg die jüngeren.

    Aufschlussreich ist vielleicht, dass die Kreise meist von Blau nach Rot gehen, Ausbrüche also bei relativ jungen Personen anfangen und sich zu älteren hinbewegen. Das ist schon beim Heinsberg-Ausbruch zu sehen, der mit einem Score von 36 anfängt (das hätte ich für einen Kappenabend nie vorhergesagt) und recht monoton immer weiter steigt. Bei etwa 55 habe ich ihn aus den Augen verloren. Diese, wenn mensch so will, Rotverschiebung ist ein recht häufig zu beobachtendes Phänomen in dem Film. Mein unheimlicher Verdacht ist ja, dass dabei die outgesourcten Putz- und Pflegekräfte, die im Namen der Kostenersparnis nicht selten als Kolonne durch mehrere Altenpflegeeinrichtungen hintereinander gescheucht werden, eine große Rolle gespielt haben.

    Recht erwartbar war, dass bei den „jungen“ Kreisen regelmäßig Unistädte auftauchen, Göttingen z.B. im ansonsten ruhigen Juni 2020, während gleichzeitig in Gütersloh die Tönnies-Wanderarbeiter deutlich höhere Alters-Scores haben – beeindruckend, dass diese die Schinderei in unseren Schlachthöfen in das bei diesem Ausbruch starke A35-A59-bin durchhalten.

    In dieser Ausprägung nicht erwartet hätte ich die grün-rot-Trennung zwischen West- und Ostdeutschland in der zweiten Welle, besonders deutlich im Januar 2021. Ein guter Teil davon wird sicher die Basisdemographie sein, denn arg viele junge Leute, die überhaupt krank werden könnten, gibt es in weiten Teilen Ostdeutschlands nicht mehr. Aber so viel anders dürfte das in vielen ländlichen Kreisen Westdeutschlands auch nicht sein. Hm. Ich brauche gelegentlich nach Alter und Kreis aufgelöste Demographiedaten für die BRD.

    Nehmen wir mal den Landkreis Hof, der im Juni 2021 in den fünf jüngsten Kreisen mitspielt: da würde ich eigentlich eine recht alte Bevölkerung erwarten. Der niedrige Score in der Zeit ist also be-stimmt Folge von, jaklar, den wilden Parties der Jugend, von denen wir schon im Sommer 2020 so viel gehört haben. Naughty kids.

    Mit anderen Worten: Ich habe leider keine sehr tiefen Erkenntnisse aus der Visualisierung gezogen. Wenn das, was da gezeigt ist, nicht ziemlich ernst wäre, könnte mensch sich immerhin an der lavalampenähnlichen Erscheinung freuen.

    Technics

    Nachtrag (2022-10-27)

    Der Code ist jetzt am Codeberg

    Das Umschreiben des Codes vom vorigen Post war eine interessante Übung, die insbesondere eine (vor dem Hintergrund der Empfehlung der Gang of Four, normalerweise eher über Komposition als über Vererbung nachzudenken) recht natürliche Anwendung von Vererbung mit sich brachte, nämlich in der Plotter-Klasse. Auch die Parametrisierung dessen, worüber iteriert wird (_iter_maps, iter_freqs, iter_age_scores) war, nun, interessant.

    Das Programm hat dabei eine (fast) ordentliche Kommandozeilenschnittstelle bekommen:

    $ python3 mkmovie.py --help
    usage: mkmovie.py [-h] [-d] [-i N] [-m ISODATE] {inc,age}
    
    Make a movie from RKI data
    
    positional arguments:
      {inc,age}             select what kind of movie should be made
    
    optional arguments:
      -h, --help            show this help message and exit
      -d, --design_mode     just render a single frame from a dict left in a
                            previous run.
      -i N, --interpolate N
                            interpolate N frames for one day
      -m ISODATE, --min-date ISODATE
                            discard all records earlier than ISODATE
    

    Damit entsteht der Film oben durch:

    $ python3 mkmovie.py --min-date=2020-02-20 -i 7 age
    

    Der aktuelle Code: mkmovie.py und corona.py.

  • Corona als Film

    Inzidenzen mögen nicht mehr das ideale Mittel sein, um die aktuelle Corona-Gefährdungslage zu beschreiben, auch wenn es zumindest so lange kaum ein schnelleres Signal geben wird, wie nicht flächendeckend PCR auf Abwässer läuft. Aber sie ist bei allen auch hier angemäkelten Defiziten und Ungenauigkeiten doch kaum zu schlagen, wenn es um ein nach Zeit und Ort aufgelöstes Bild davon geht, was das Virus – Verzeihung, die Viren – so getrieben haben.

    Und nachdem ich neulich angefangen hatte, mit dem großen Infektions-Datensatz des RKI zu spielen, ist mir aufgefallen, dass es ausgehend von dem dort diskutierten Code nicht schwierig sein sollte, einen Film zu basteln, der die Inzidenzverläufe auf Kreisebene visualisiert. Nun, das habe ich gemacht:

    (sollte euer Browser das vermurksen: Download; Kreispolygone: © GeoBasis-DE / BKG 2021). Im Unterschied zu den bekannten Bildern aus dem RKI-Bericht (die die Inzidenz nach dem Meldedatum rechnen) verwende ich hier übrigens das Referenzdatum, also wenn möglich das Datum der Infektion und nur andernfalls das Meldedatum.

    Nachtrag (2021-11-03)

    Nur damit sich niemand wundert, wie Herbst-Zahlen in einen Post vom August kommen: Ich habe den Film bis November 2021 fortgesetzt und werde ihn künftig wohl noch ein paar Mal aktualisieren.

    Ein paar Dinge, die ich daraus gelernt habe:

    • Es gab offenbar schon vor Heinsberg einiges an Corona-Rauschen in der Republik (am Anfang vom Video). Wie viel davon einfach Tippfehler sind, ist natürlich schwer zu sagen. Aber einiges wird schon real sein, und dann ist sehr bemerkenswert, dass es in keiner dieser Fälle zu einem klinisch auffallenden Ausbruch gekommen ist. Das wäre eine sehr deutliche Illustration der hohen Überdispersion zumindest des ursprünglichen Virus: fast alle Infizierten steck(t)en [1] niemanden an, so dass, solange die Ausbrüche klein sind, sie schnell wieder verschwinden.
    • Ich hatte ganz vergessen, wie schnell am Anfang der Pandemie die Folgen des Bierfests in Tirschenreuth die des Kappenabends in Heinsberg überrundet hatten (nämlich so um den 10.3. rum). Es lohnt sich, im März 2020 Ostbayern im Blick zu halten.
    • Die etwas brodelnde Erscheinung des Bildes speziell in ruhigeren Phasen – wie ein träge kochender Brei vielleicht, bei dem an mehr oder minder zufälligen Stellen immer mal wieder eine Blase hochkommt – zeigt wieder, dass sich Corona vor allem in Ausbrüchen ausbreitet. Das tut es bestimmt auch in weniger ruhigen Phasen, aber dann sind überall Blasen („sprudelnd kochend“), so dass das nicht mehr auffällt.
    • Die großen Ausbrüche des Sommers 2020 (vor allem Gütersloh und Dingolfing) waren erstaunlich allein stehende Ereignisse. Wenn mensch bedenkt, dass es ja schon einen Haufen Schlachthöfe und andere ähnlich furchtbare Betriebe in der BRD gibt, fragt sich schon, warum es nicht mehr Ausbrüche im Tönnies-Stil gab. Waren die anderen Läden alle vorsichtiger? Oder hatten die einfach Glück, weil niemand mit hoher Virusausscheidung in ihre Betriebshallen gekommen ist? Sind vielleicht Ausbrüche übersehen worden? Rein demographisch nämlich waren beispielsweise die Tönnies-Leute so jung und fit, dass nur wenige im Krankenhaus landeten und keineR gestorben ist.
    • Auch in den zweiten und dritten Wellen blieb erstaunlich viel Struktur im Infektionsgeschehen – mehr, als ich nach Betrachtung der statischen RKI-Plots und der relativ parallelen Bundesländer-Inzidenzen erwartet hätte, vor allem aber entgegen der Einlassung, das Geschehen sei „diffus“. Angesichts des weiter bestehenden „Brodelns“ würde mich eigentlich überraschen, wenn sich B.1.1.7 oder die B.1.617.x so viel anders ausbreiten würden als der ursprüngliche Wildtyp.
    • Insbesondere gibt es auch in den späteren Wellen Kreise, die kurz „hochbubbeln“ und dann auch wieder rasch unauffällig werden. Es wäre bestimmt aufschlussreich, wenn mensch wüsste, warum das mit dem Rasch-Unauffällig-Werden in den Kreisen in Südsachsen und -thüringen über lange Zeit nicht passiert ist.

    Technics

    Nachtrag (2022-10-27)

    Der Code ist jetzt am Codeberg.

    Es war übrigens doch nicht so ganz einfach, diesen Film zu machen, und zwar vor allem, weil ich eine Weile mit den Polygonen für die Kreise gerungen habe. Mein erster Plan war, die einfach aus der Openstreetmap zu ziehen. Ich wollte aber nicht an einem kompletten OSM-Dump herumoperieren, und so war ich sehr angetan von osm-boundaries. Mit diesem Dienst ließen sich eigentlich recht leicht die „administrative boundaries“ von Kreisen (das wäre dort Level 6) in geojson bekommen.

    Abgesehen davon aber, dass die interaktive Auswahl gerne mit „cannot download tree“ scheiterte, mein Webkit lange am Javascript kaute, und Cloudflare die Downloads regelmäßig zu früh abbrach (die MacherInnen von osm-boundaries verstehen das selbst nicht so ganz), sind die Label der Kreise doch sehr verschieden von dem, was das RKI hat: „Solingen (Klingenstadt)“ auf RKI-Seite war ebenso lästig wie fehlende Unterscheidung zwischen Stadt- und Landkreisen in den Bezeichnungen der Openstreetmap (was immerhin durch Betrachtung der Flächen zu umgehen war).

    Aber auch, als ich mir die Abbildung zwischen den verschiedenen Bezeichnern zusammengehackt hatte, blieben einige weiße Flecken, Kreise also, die ich in der Openstreetmap schlicht nicht finden konnte. An dem Punkt bin ich zur offiziellen Quelle gegangen, nämlich dem Bundesamt für Kartographie und Geodäsie, speziell zum VG2500-Datensatz, der zu meiner großen Erleichterung auch die Kreis-Identifier des RKI (1001 etwa für Flensburg-Stadt) enthält. Na ja, abgesehen von Berlin, das das RKI aufteilt, was wiederum etwas Gefummel zur Wiedervereinigung von Berlin im Code braucht.

    Aber leider: Der Kram kommt als Shape, wie das BKG sagt ein „De-facto-Industriestandard“, mit dem allerdings ich noch nie etwas zu tun hatte und der als über einige Dateien verteilte Binärsoße daherkommt. Immerhin: das Debian-paketierte Cartopy kann damit umgehen. Puh. Nur: frech add_geometries auf die Geometrien loslassen, die aus dem Reader herausfallen, führt zu einer leeren Karte.

    Im Folgenden bin ich etwas untergegangen in all den Referenzsystemen, mit denen sich die GeographInnen so rumschlagen müssen. Ach, haben wir es gut in der Astronomie. Ja, klar, auch wir haben einen Haufen verschiedene Äquatoren und Nullpunkte (z.B. zwei verschiedene Systeme für galaktische Koordinaten, und haufenweise historische äquatoriale Systeme, die zudem durch verschiedene Sternkataloge definiert waren): Aber letztlich sind das im Wesentlichen Drehungen mit winzigen Knitterungen, und schlimmstenfalls kommen die Dinge halt am falschen Platz raus, was für meine gegenwärtigen Zwecke völlig wurst gewesen wäre.

    Aber hier: Nichts auf der ganzen Karte. Es braucht beim Plotten zwingend das richtige Quell-Bezugssystem, hier (wie aus dem .prj des VG2500 hervorgeht) das EPSG-System Nummer 25832 (Fünfundzwanzigtausenachthundertzweiundreißig! Holy Cow!). Damit kann Cartopy sogar umgehen, aber es zieht dann bei jedem Programmlauf die Beschreibung des Systems erneut von einem Onlinedienst, und das geht in meiner Welt gar nicht. Deshalb habe ich mir geschwind eine Proj4Projection-Klasse gefummelt, die den String, der von dem Online-Dienst kommt, händisch in die zugrundeliegende Bibliothek packt. Warnung: Das ist ohne Sachkenntnis geschrieben; dass ich da die Gültigkeitsgrenzen völlig fake, ist vermutlich Gift außerhalb dieser spezifischen Anwendung.

    Der Rest des Codes ist harmloses Python, das die Eingabedaten hinmassiert. Weil die RKI-Daten leider nach Kreis und nicht nach Datum sortiert sind, muss ich den kompletten Datensatz ins RAM nehmen; auf nicht völlig antiker Hardware ist das aber kein Drama.

    Was für den optischen Eindruck noch ziemlich wichtig ist: Ich interpoliere linear zwischen den Tagen (die iter_interpolated-Funktion). Das ist nützlich, weil damit die Übergänge nicht so hart sind, und auch, damit der Film nicht nur 25 Sekunden (also rund 600 Frames) lang ist, sondern etwas wie zwei Minuten läuft.

    Wers nachbauen will oder z.B. Altersgruppen-spezifische Filme machen will oder welche mit dem Median des Alters – das würde der Datensatz durchaus hergeben – oder welche, die nicht alles über 350 saturiert darstellen oder so etwas, braucht mkmovie.py und corona.py. Die Quelldaten werden in einem in corona.py definierten externen Verzeichnis erwartet (DATA_DIR); welche, und woher die kommen, steht am Kopf von mkmovie.py.

    [1]Bei den späteren Virusvarianten mag es eingestandenermaßen nicht mehr ganz so einfach sein, weshalb ich hier so ein vorsichtiges Präteritum schreibe.
  • Keine Mauern mehr

    Das, was in Heidelberg wohl als „Heimatzeitung“ zu bezeichnen ist, die Rhein-Neckar-Zeitung, hat es in die heutige Deutschlandfunk-Presseschau geschafft, und zwar mit folgender patriotischen Erbauung:

    Es [was „es“ ist, bleibt im DLF-zitierten Kontext unklar] sollte auch Ansporn sein, diese Republik als den Idealzustand zu sehen. Wir leben im besten aller bisherigen deutschen Staaten – das bedeutet nicht, dass man ihn nicht verbessern kann. Aber Mauern müssen keine mehr eingerissen werden.

    Nun...

    Polizeigeschützte Mauer

    Der Abschiebeknast von Ingelheim, Stand 2009. Und auch wenn diverse Regierungen in Rheinland-Pfalz diese Mauern schon mal einreißen wollten, ist da zumindest bis 2019 nichts draus geworden.

  • Motivlage im Rassismus

    Unter den tiefautoritären Gesetzen, die die Parlamente in den letzten Jahren so durchgewunken haben, sind das Netzwerkdurchsetzungsgesetz und das daran angehängte „Gesetz zur Bekämpfung des Rechtsextremismus und der Hasskriminalität“ (vgl. hier im Januar) insoweit stilbildend, als sie das Konzept von Gedankenverbrechen weiter verdichten. Klar hat es schon vorher allerlei Gesetzgebung zur „Ehrabschneidung“ gegeben – die ganze Gegend von §185 bis §199 StGB etwa – aber in freieren Zeiten war eigentlich klar, dass das Gesetze sind, mit denen sich lediglich ewig gestrige Altverleger, humorlose Prälaten und vertrocknete Politiker gegen lustigen Kram der Titanic wehren und dabei nur noch blöder aussehen.

    Das NetzDG nun erklärt das alberne Rumposen wenig reflektierter Facebook-Produkte zur staatsgefährdenden Tat, ganz so, als sei das die Ursache für hunderte Nazimorde oder die allzu berechtigten Sorgen nicht ganz so Deutscher, in den Randgebieten der Zivilisation aufs Maul zu kriegen. Wegen dieser Fehlanalyse werden kommerzielle Plattformen als Hilfssherriffs eingespannt, fordert der Staat Zugriff auf Passwörter.

    Wie unsinnig das Narrativ von Facebook als Ursache rassistischer Gewalt ist, wird schön im Deutschlandfunk-Hintergrund vom 6.8. deutlich. Facebook ist, das jedenfalls nehme ich (nicht nur) aus dieser Geschichte mit, allenfalls die Echokammer. Die Quelle der Ressentiments hingegen sind Innenministerien, eine erschreckend breite Mehrheit der sich als „bürgerlich“ definierenden klassischen Medien, und leider auch nicht zu knapp viele Staatsanwaltschaften.

    Es lohnt sich durchaus, den ganzen Beitrag zu lesen (oder zu hören), aber die Geschichte in Kürze ist: Die Behördenleiterin des BAMF in Bremen hat tatsächlich die auch mit Rücksicht auf internationale Verpflichtungen relativ (zur Praxis) menschenfreundlichen Regelungen aus der Migrationsgesetzgebung umgesetzt. Daraufhin ist sie von der „lass uns das so rechtswidrig machen wie die anderen auch“-Fraktion in der eigenen Behörde abgesägt und durch wen ersetzt worden, die eher auf der menschenrechtsfeindlichen Linie der Innenministerien liegt.

    Um das ordentlich über die Bühne zu kriegen, wurde die korrekte Vorgängerin noch ein wenig angeschwärzt, was dann von der Staatsanwaltschaft begeistert und von der breiten Presse enthusiastisch aufgenommen wurde. Ein Skandal war geboren, der letztlich alle rassistischen und sexistischen Ressentiments bedient: Eine Bürokratin macht AusländerInnen zu Deutschen, wahlweise für Geld oder weil sie mit – klar: ausländischen – Anwälten anbandeln wollte[1].

    Diese abstruse Geschichte aus der rechten Mottenkiste („großer Bevölkerungstausch“ oder wie diese Leute das auch immer nennen) beschäftigte die Nation samt ihrer öffentlichen VertreterInnen für Wochen, und eigentlich niemand traute sich zu sagen, dass das schon von Anfang an rassistische Kackscheiße ist, denn selbst wenn jemand mal einen Hauch großzügiger duldete oder gar einbürgerte: Für wen – von verstockten RassistInnen mal abgesehen – wäre das eigentlich ein Problem, geschweige denn eines, für das irgendwer ins Gefängnis sollte?

    Wer solche Diskurse anfängt und lautstark anheizt, wer die rassistische Denke als Staatsraison markiert, darf sich nicht wundern, wenn autoritäre Charaktere die Logik dieser Staatsraison in private Gewalt umsetzen.

    Dass diese Umsetzung in private Gewalt stattfindet, ist seit dem Lübcke-Mord immerhin ansatzweise ins öffentliche Bewusstsein gelangt (mit 30-jähriger Verspätung). In dieser Situation und nachdem das ganze rechte Phantasma ums Bremer BAMF implodiert ist, wäre das Mindeste für die ProtagonistInnen der öffentlichen Hassrede damals, allen voran Stefan Mayer und Horst Seehofer, nun Familienpackungen von Asche auf ihre Häupter streuen. Aber nichts davon. Stattdessen, das kann ich zuversichtlich vorhersagen, folgt ganz gewiss der nächste Menschenrechtsabbau im Stil des NetzDG. Was weniger ärgerlich wäre, wenn die Vorlagen dazu nicht eben von den Hassrednern („hochkriminell, kollusiv und bandenmäßig“) in diesem Fall kommen würden.

    [1]Dass sich die Staatsanwaltschaft zu diesem rechten Urmotiv von „uns“ die Frauen raubenden Ausländermännern hat hinreißen lassen, ist übrigens nochmal ein ganz spezieller Skandal. Findet da auch 250 Jahre nach Kant überhaupt keine Aufklärung statt?
  • Post-Wettbewerb: Echt jetzt?

    Unter den Branchen, in denen Privatisierung am alleroffensichtlichsten Quatsch ist, sehe nicht nur ich die Post ganz vorne. Denn: Alle sollen die Post nutzen können, aber die Kosten für die Infrastruktur schwanken um Größenordnungen zwischen Metropole und Provinz. Unter solchen Bedingungen eine halbwegs gleichmäßige Abdeckung mit privatwirtschaftlichen Unternehmen herzustellen, wäre ein regulatorischer Kraftakt, der abgesehen von viel Zeitverschwendung am Schluss wieder darin enden würde, dass die Gewinne privatisiert und die Verluste sozialisiert werden – wovon nun wirklich niemand[1] was hat.

    Aber auch wer in der Stadt wohnt, muss sich fragen, welchen Zweck es wohl haben könnte, wenn statt des einen zuverlässigen, halbwegs ordentlich bezahlten und beamteten Postboten im Dienst der weiland Bundespost nun fünf arme Schlucker die Viertel abfahren, die alle mehr oder minder am Mindestlohn kratzen, im Akkord arbeiten und entsprechend unzuverlässig sind: Noch nicht mal die verbohrtesten Marktpriester wollten das rechtfertigen, wenn ich sie darauf angesprochen habe.

    Und dabei fange ich noch nicht mal beim Kulturverlust an. Vor der Privatisierung konnte das Postamt als Ausspielstelle des Staates fungieren, praktisch wie die Bürgerämter unserer Zeit, nur dichter gespannt. Heute korrelieren die Außenposten der Post im Wesentlichen mit Branchen wie Glücksspiel oder Restposten.

    Kurz: Wäre ich Marktpriester, der Postdienst wäre das letzte, über das ich reden wollte.

    Um so mehr hat mich der DLF-Hintergrund vom 4.8. überrascht, in dem Mischa Ehrhardt versucht, ein Problem auszumachen, weil „die Deutsche Post den Markt dominiert“, natürlich ohne zu sagen, wie ausgerechnet mehr Markt irgendeines der angesprochenen Probleme lösen könnte – und genau keine Stimme den offensichtlichen Weg nach vorne, nämlich die Rückverstaatlichung des Postdienstes, auch nur anspricht.

    Stattdessen wird Walther Otremba – nach einer Karriere als CDU-Mann, Staatsekretär im Finanz- und Militärministerium und Bahn-Aufsichtsrat jetzt Frühstücksdirektor und Lobbyist für die nichtpostigen Postklitschen, also die, die ihre AusträgerInnen im Schnitt noch mieser behandeln als die privatisierte Post – zitiert mit:

    Ich kann ja eigentlich die Deutsche Post AG nicht kritisieren. Die tut halt, was sie machen muss, nämlich versuchen, möglichst hohe Gewinne zu erzielen.

    Öhm… Warum genau soll die Post möglichst hohe Gewinne machen müssen? Ist nicht eigentlich völlig offensichtlich, dass Aufgabe der Post ist, möglichst flott und mit wenig gesellschaftlichem Aufwand Briefe zu transportieren (und dann vielleicht noch Postsparbücher zu betreiben und ggf. mit Postämtern in der Fläche auch ein paar staatliche Aufgaben in die Hand zu nehmen)? Wer, außer ein paar AnlegerInnen, hätte umgekehrt etwas davon, wenn sie möglichst hohe Gewinne machen würde? Wer also könnte das wollen oder die Post gar dazu zwingen?

    Wohlgemerkt, der Otremba, der da solche Klopfer durchs Radio schickt, war in seinen großen Zeiten (z.B. im „Finanzmarktstabilisierungsfonds“) einer der ganz großen Mover und Shaker. Bei derart verwirrten Gedanken muss wohl nicht mehr verwundern, was für eine Lachnummer (zuletzt bei Cum-Ex und Wirecard) die BaFin zumindest in Wirtschaftskreisen ist. Immerhin haben er und seine KollegInnen die ja erfunden.

    Es gäbe noch einige weitere komplett auf dem Kopf stehende Argumente in dem DLF-Beitrag zu korrigieren, so etwa die abseitige Kritik an der Quersubventionierung; natürlich will mensch z.B. Briefe durch Telefon quersubventionieren, wenn das gesellschaftlich geboten ist, was es zumindest früher mal war. Aber wichtiger wäre mir, noch Otrembas nächsten Satz zu prüfen, denn der spiegelt einen verbreiteten Irrglauben wider:

    Es sind die Rahmenbedingungen, die nicht geliefert wurden rechtzeitig, um im Briefgeschäft ähnliche Erfolge, wie zum Beispiel in der Telekommunikation, die ja parallel liberalisiert wurde, zu erzeugen

    „Erfolge“? In der Telekommunikation, in der halb-betrügerische Verträge mehr die Regel sind als die Ausnahme und die Verbraucherzentralen gar nicht mehr aus dem Klagen rauskommen? In der drei (oder sind es wieder vier?) Mobilfunknetze konkurrieren, so dass es die gleiche Infrastruktur in den Metropolen dreifach und dafür gar keine am Land gibt?

    „Aber es ist doch alles viel billiger geworden,“ höre ich euch einwenden. Nun – das ist es bereits vor der Privatisierung.

    Es gibt dazu eine ganz interessante Untersuchung von A. Michael Noll, in Telecommunications Policy 18 (5), 255f (1994): „A study of long distance rates. Divestiture revisted“ (DOI 10.1016/0308-5961(94)90051-5; sorry, ist Elsevier). Wohlgemerkt: das ist 1994 erschienen; wir hätten also in der BRD vor der Zerschlagung der Bundespost davon lernen können. Jaja, die Auflösung von AT&T in den USA, die Noll da untersucht, war nicht exakt eine Privatisierung, aber sie war in Anlage und Ziel nicht wesentlich anders, und sie war auch die Blaupause für all die anderen marktradikalen Kreuzzüge gegen staatliche Daseinsvorsorge im Kommunikationsbereich.

    Ein Ergebnis seiner Arbeit: Die Preise für Ferngespräche folgten über fast 100 Jahre einem Abwärtstrend, nur kurz unterbrochen von einer Panikphase vor der Öffnung des Wettbewerbs im Jahr 1984:

    Fallender Graph

    Fig. 1 aus doi:10.1016/0308-5961(94)90051-5: Kosten für Ferngespräche in den USA, 1910 bis ca. 1995. Der Wettbewerb hat nicht für rascher fallende Preise gesorgt. Rechte leider bei Elsevier.

    Wenn ihr in anderen Papern seht, dass nach der Zulassung von Konkurrenz die Preise ganz schnell gefallen sind: hier ist der Hintergrund. Dazu kommt übrigens noch, wie die Wikipedia zum Ende des Bell-Systems schreibt:

    One consequence of the breakup was that local residential service rates, which were formerly subsidized by long-distance revenues, began to rise faster than the rate of inflation.

    Also: Nicht nur sind die Ferngespräche nicht schneller billiger geworden als vorher – Überschüsse aus ihnen sind auch nicht mehr in die Grundversorgung geflossen, so dass diese teuerer wurde. Statt dieser (ebenfalls sinnvollen) Quersubventionierung ging das Geld stattdessen an InvestorInnen (also: „die Reichen“) und öffentliche Belästigung (also: „Werbung“). Bei Noll sieht das so aus:

    Steigender Graph

    Fig. 4 aus doi:10.1016/0308-5961(94)90051-5: Marketingkosten von AT&T zwischen 1970 und 1993. Mit der Ende staatlicher Regulierung ging Geld statt in die Grundversorgung in die Werbung. Rechte leider bei Elsevier.

    Die Geschichte von den fallenden Preisen durch Privatisierung kehrt sich also in ihr Gegenteil.

    Nein: Was dafür gesorgt hat, dass Leute jetzt für in etwa das gleiche Geld viel mehr telefonieren können als, sagen wir, 1995, nennt sich technischer Fortschritt, in diesem Fall insbesondere die (von öffentlich finanzierten Unis und Instituten aufs Gleis gesetzte) stürmische Entwicklung paketvermittelter Netze – was nicht nur das Internet war. Ja, kann sein, dass deren Einführung mit der alten Bundespost etwas länger gedauert hätte, zumal, wenn Leute wie Otrembas Parteifreund Christian Schwarz-Schilling sie als Selbstbedienungsladen nutzten.

    Aber wärs wirklich so schlimm gewesen, wenn wir das Klingelton-Zeitalter übersprungen hätten und stattdessen nicht Öko- und Sozialkatastrophen (die Mobiltelefone nun mal sind) als Werbegeschenke windiger Knebelvertraghöker abwehren müssten?

    [1]Außer ein paar AnlegerInnen, UnternehmensberaterInnen und GeschäftsführerInnen; aber das darf guten Gewissens als Fehlsteuerung durch Marktkräfte eingeordnet werden.
  • 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.

  • Long live PGP

    The other day I ran into two rants against PGP, What's the matter with PGP?, which still is relatively reasonable, and then the raving PGP Problem by people running a security consulting shop called Latacora. It's this second diatribe that made me write this post, because the amount of badmouthing of PGP done there, on the blog of a company promising to teach startups “security“ on top, is not only unwarranted, it's also actively damaging to meaningful encryption.

    Let me start with what I think are the fundamental fallacies of the Latacora folks is: They seem to think that identity, and hence key management, is something that others can do for you, and that thinking about crypto is “bad user experience“. In contrast, I'd argue that crypto you don't notice isn't crypto at all (but instead somewhere on the obfuscation spectrum), and that identity management done by others is equivalent to them encrypting for you.

    You see, if you're encrypting something, you're encrypting it for someone. In public key encryption, this “someone“ has two aspects: a real-world entity (your friend, a bank, whatever), and a public key. Any crypto system that does not make this separation transparent and asks you the question of how well you think the two things match (and whether you care), is fundamentally broken. That's because that question plainly has to be answered. If it's not you who answers it, it's someone else. And hence that someone else is free to change the mapping from key to real-world entity, and hence they determine which real-world entity gets to read what you've encrypted.

    This, by the way, is how https is regularly subverted by businesses, anti-virus software, and occasionally state actors, who simply make your browser trust their word on who is what. At that moment, they can inspect everything your browser exchanges with the rest of the world, be it in “anti-virus portals” or bluntly in surveillance systems. This is also why very few users of “encrypted” messengers would even notice if the operating company snooped on them.

    The big advantage of PGP is what the Latacora people call „obnoxious UX“. Yes, you have to make up your mind on keys, yes, you have to explicitly manage them: but that is what you need to understand if you want meaningful encryption, and plastering abstractions on top of that only gives extra levels people have to understand – and that can break. No: if you want to do encryption, you'll have to understand key management, and PGP makes that as explicit and transparent as any crypto system I've ever seen. That's a feature, not a bug.

    Actually, this one thing is far more important than regular key rotation (as an aside: I'm not aware of anyone ever having broken a PGP secret key because too much material has been encrypted using it; it's certainly not a major reason for failing encryption) or the latest cryptographic primitives (even 1024 bit RSA keys still require serious investment to break, 20 years after they've been state of the art).

    More generally, the scenarios requiring frequent key rotation mostly imagine a targeted attack from a state actor, following you into hotel rooms to steal your secret key and install key loggers to skim your passphrase (or similar). Frankly: it's an illusion to believe a muggle (or even normal wizards doing their daily work) could withstand such a determined and comptentent state actor for a long time.

    But that's not necessary. It's already great progress if Google, the (normal) police, and the people at your employer's computation centre can't read the content of your mails unless they really try hard. Actually, most “adversaries” are not terribly determined and/or terribly competent. You hence don't need a perfect cryptosystem. It just needs to withstand the most basic of man-in-the-middle attacks (which fends off the not terribly competent adversaries), and it needs to require at least a bit of individual effort to break each person's crypto (which fends off the not terribly determined ones). Any system with centralised identity management fails at least on the side of the individual effort – get the central entity to collude, or break it, and you have it all. And given the central entity at least legally sits somewhere if it's commercial, at least for the state of residence it fails the withstand-most-basic criterion as well: The average state has no trouble obtaining court orders as soon as it moans “terrorism”.

    PGP, on the other hand, does a fairly good job on both counts once people have grokked it, at least a much better one than anything SSL-based I've ever seen. People can understand the basic operations of PGP if they want, something that is much harder with SSL and X.509. The problem is that few people want to understand that. But in that case, any kind of crypto is doomed. Hence, the problem isn't PGP, it is, as so often, education. Working on that is effort well spent, as once people have understood PGP to the level of confidently using it, they have a much better chance of being able to competently use other, less explicit crypto systems.

    Having said that: sure, PGP and its UIs could be improved. But you can't get around PGP's long-term keys for e-mail, and whatever alternative you'd come up with, you'll still need keyrings and reasonable UIs to mark up the trust in there. And, in particular, you'll still need open standards so you don't have to take a single company's word for what it does.

    That's basically where I think Latacora's arguments are harmful. But since most of the claims in the article are fairly outrageous, I can't resist commenting them, too:

    • “Absurd Complexity“ – that's not a terribly credible charge given the page comes over HTTPS, which in many ways is a lot more complex than OpenPGP, in particular because it contains the nightmare that is X.509. But really: Much as I am all for reducing complexity, I'm even more for maintaining backward compatibility. Being able to read encrypted mails I got in the 1990ies matters to me, and anything flexible enough to at least support modern crypto and deal with archive data will have to have a certain amount of complexity. Start something new, and in 10 years it'll look the same. Or worse. Only it won't be able to read archival data, and it'll have repeated the history of early bugs software simply has, in particular when you have to worry about side channel attacks.
    • “Swiss Army Knife“ – that would be more convincing if they said how exactly PGP signatures are “mediocre“ or the encryption is a “pretty bad job“. I accept the argument they make a bit down that people may want to have forward secrecy in IM and it's easy to have there, so going for PGP alternatives may be a good idea there. But then I can't remember the last time I used PGP over XMPP, so these alternatives have existed for a long time, without any need to kill PGP.
    • “Mired in Backwards Compatibility“ – well, as said above, backwards compatiblity is great if your systems live a long time. And OpenPGP is doing a reasonable job to have both backwards compatiblity and evolvability. That rolling out new features isn't instantaneous, in particular for a federated, largely volunteer effort, is useless criticism: Build another distributed, open, volunteer effort, and it'll go the same way. Oh, and just incidentally: HTTPS is from the nineties, too, and the X.509 standard was published in 1988.
    • ”Obnoxious UX“, “Long-Term Secrets“, “Incoherent Identity“ – these are the core of Latacora's fallacies; see above.
    • “Broken Authentication“ – I can't say I've thought through the problem they're pointing to here; if it is as bad as they claim, there's no reason not to fix it within OpenPGP rather than invent something entirely new.
    • “Leaks Metadata“ – sure. As long as there's SMTP, there's no way around having quite a bit of cleartext: intermediate mail servers will have an idea who's mailing whom (though of course there's still Mixmaster). Having e-mail, or at least something that doesn't require me to be always online, is so important that the metadata leaks are an almost negligible price to pay, at least compared to the fine-grained activity profile you leak when you leave your phone online all the time, or the loss of control when you (or people you trust) can't run the necessary infrastructure components (as in: a mail server) any more.
    • ”No Forward Secrecy“ – fair enough, but again that's hard to have in store-and-forward e-mail, in particular when you'd like to have mailing lists and the like. Of course, it's true that »[a]gainst serious adversaries and without forward secrecy, breaches are a question of “when”, not “if”.« But on the other hand, most serious adversaries lose interest in the cleartext hours, weeks, or at worst a few years after the communication, or at least stop being terribly serious. So, for these intents and purposes holding …
  • Ökumenische Linke

    Ich bin bekennender Fan von David Rovics. Klar fühlen sich seine Palästinasoli-Songs in der postantideutschen Linken zumindest mal gewagt an, sein Lied vom besseren Anarchisten entschuldigt vielleicht etwas sehr viel, und mein antimilitaristisches Herz blutet an einigen Stellen vom Song for Hugh Thompson (der übrigens schon am Deutschlandfunk lief). Aber in allen Kämpfen, in denen es eine richtige Seite gibt, steht er konsequent auf dieser, und ich finde viele seiner Lieder ernsthaft mitreißend, angefangen wohl mit dem Bluegrass-Reißer When the Minimum Wage Workers Went on Strike, das eine (letztlich leider wenig erfolgreiche) Organisierung von MindestlöhnerInnen an der Harvard University begleitete, während ich so um 2000 rum in der Gegend gearbeitet habe. Damals wurde ich auf David aufmerksam, und es spricht für seine Umtriebigkeit, dass später ganz unabhängig davon Bekannte von mir Auftritte von ihm in Heidelberg organisiert haben.

    Nun, David hat jetzt einen Blogpost geschrieben, der mir in vielerlei Hinsicht aus der Seele spricht: Confessions of an Ecumenical Leftist. Wer hinreichend gut Englisch kann und sich für linke Politik interessiert, sollte das, finde ich, lesen.

  • Die Gewinne privatisieren, die Verluste sozialisieren

    Selbst die verbohrtesten Marktradikalen erinnern sich plötzlich an „die Gesellschaft“, wenn irgendwo Verluste drohen; die Privatisierung von Profiten (z.B. Mobiltelefonie oder Postdienst in Städten) bei Sozialisierung von Verlusten (z.B. Mobiltelefonie oder Postdienst auf dem Land) ist Grundpfeiler des „Neoliberalismus“[1].

    Ein schönes und halbwegs aktuelles (November 2019) Beispiel ist die „Mobilfunkstrategie“ des Bundes, der 1.1 Milliarden Euro ins Schließen von Funklöchern stecken will; vernünftig wäre ja, statt dreier löchriger privater ein flächendeckendes öffentliches Netz zu betreiben, bei dem die TelefoniererInnen in den Städten die am Land subventionieren würden. Aber das würde die religiösen Gefühle der Marktgläubigen verletzen. Das geht nicht.

    Das Prinzip der Sozialisierung von Verlusten hat heute morgen ein Jörg Asmussen, seines Zeichens „Hauptgeschäftsführer beim Gesamtverband der Deutschen Versicherungswirtschaft” (was tut eigentlich ein Hauptgeschäftsführer, das ein Geschäftsführer nicht tut?), in entwaffnender Ehrlichkeit illustriert, als er in einem Deutschlandfunk-Interview erklärte:

    Um von hinten anzufangen: Ein Prozent der Gebäude ist in der Tat nicht versicherbar gegen Elementarschäden. Da muss man sicher eine gesamtgesellschaftliche Lösung finden. 99 Prozent sind versicherbar und, ich glaube, auch zu akzeptablen Kosten. [...] Das Ein-prozent-Problem ist in der Tat existent.

    Im Klartext: Mit 99% der Häuser können wir ein Geschäft machen – zumal wir bei denen ohnehin nur sehr selten bezahlen müssen –, das restliche Prozent – die nämlich, bei denen erwartbar Schäden eintreten, die Einzelpersonen regelmäßig überfordern – lohnt sich nicht für uns, die soll der Staat übernehmen. Klingt das nur in meinen Ohren so dreist?

    Wobei Versicherungen natürlich insgesamt so ein Thema sind. Das Land Baden-Württemberg zum Beispiel hat sich, als ich das letzte Mal damit zu tun hatte, grundsätzlich nicht versichert, und die Argumentation ging etwa so: Wir sind so groß, dass jede Sorte Schadensfall fast sicher auftritt. Damit kann uns aber eine Versicherung gar keine Wette gegen dessen Eintreten[2] anbieten, die für uns vorteilhaft ist. Daher gleichen wir solche Schäden lieber gleich intern aus. Das spart Geld, weil zwischen Geldquelle (Land BaWü) und Geldsenke (Land BaWü) nicht noch die Versicherung ihre Kosten und ihren Profit abschöpft.

    Das ist (modulo Bürokratiedefizite) exakt richtig: Versicherungen sind ganz schlicht eine kostspielige Art, Mängel im gesellschaftlichen Solidarsystem auszugleichen. Wenn das Land den Solidargedanken von seinem Apparat auf alle BügerInnen ausweiten würde, könnten wir einen Haufen Arbeitsplätze einsparen: Die von VersicherungsvertreterInnen, von den Leuten, die deren Werbung designen, die vieler der Leute, die die „Schadensregulation“ behandeln, die der Leute, die die hässlichen Versicherungs-Hochhäuser bauen und so fort.

    Zugegeben: Dieser klare Gedanke wird bei, sagen wir, Haftpflicht-Versicherungen in der Realität an sinnlosen, aber bis zum Ausbau des Bildungswesens wahrscheinlich unvermeidlichen Neid- und Missgunstdebatten („was muss der Typ auch heimwerken?“) scheitern. Speziell bei Naturkatastrophen ist das jedoch ersichtlich kein (großes) Problem: Die generelle Hilfsbereitschaft ist eigentlich immer so groß, dass der Staat in diesen Fällen weit besser und billiger arbeiten wird als Versicherungen, während zwischen Katastrophen keine Grundkosten für den Verkauf und die Verwaltung von Policen anfallen.

    Tatsächlich ist aber die Ablehnung, die 1% zu versichern, die es wirklich bräuchten, nicht nur frech, sondern auch ganz realistisch. Denn angenommen, wir haben die Fluten der letzten Wochen und noch einen Faktor 10 drauf – sowas kommt ganz sicher irgendwann, und wenn es ein explodierendes Eifelmaar ist: Selbst eine Allianz würde damit nicht fertig. Das kann nur eine Gesellschaft als Ganzes schultern, und das Aufräumen und Wiederaufbauen ist nicht durch Sparen und Kapitalanlage hinzubekommen. Sowas geht nur durch aktuelle Arbeitskraft und mithin dem, was bei der Rente „Umlageverfahren“ heißt.

    Die Versicherer können also mit größeren Naturkatastrophen gar nicht wirklich umgehen. Verlangt ja auch niemand, der/die ganz bei Trost ist. Nur sollen sie dann bitte auch nicht daran (und der Angst vor ihnen) verdienen wollen.

    [1]Das steht hier in Anführungszeichen, weil der – ganz nebenbei von sehr autoritären HerrscherInnen wie Pinochet, Thatcher und Reagan durchgesetzte „Neoliberalismus“ dem zwar schon etwas ramponierten, aber an sich doch ganz akzeptablen „liberal“ einen wirklich hässlichen Klang gibt. Das ist übrigens eine interessante Sorte von missglückter Antisprache, die auch mal einer Untersuchung harrt.
    [2]Ja, eine Versicherungspolice kann sehr gut als Wette analysiert werden: Die Versicherung wettet, dass ein Ereignis nicht eintritt (z.B. ein Unfall bei einer Unfallversicherung; oder ein später Tod bei einer Rentenversicherung). Wenn sie gewinnt, streicht sie die Prämien ein. Verliert sie die Wette, muss sie die Versicherungssumme zahlen. In diesem Sinne wären Versicherungen, die einen großen Zirkus bei der Schadensregulierung machen, einfach schlechte Verlierer…
  • Sport ist rechts

    Die titelgebende These wirkt in dieser knappen und etwas apodiktischen Form vermutlich etwas steil, zumal blütenreine Linke wie Klaus Theweleit Fußballfieber gestehen und weniger prominente, aber nicht minder glaubhafte Linksradikale als Ultras hingebungsvoll Fahnen schwingen. Zwischen den sportlichen Großevents des Jahres – Männerfußball in Europa und Südamerika sowie die Olympiade – möchte ich dennoch gerne für sie argumentieren, engelszünglend eintretend für jedenfalls ein wenig ironische Distanz zu Leistungshunger und Hymnenkult.

    Zu meiner Untersuchung der These braucht es eigentlich nur eine Arbeitsdefinition von „links“ oder „fortschrittlich“. Spätestens seit der französischen Revolution hat sich da „den Grundwerten Freiheit, Gleichheit und Solidarität[1] zu gleichen Teilen verpflichtet“ bewährt. Vorsorglich: Natürlich gibt es vieles, das diese Grundwerte fast gar nicht berührt. Die Entscheidung zwischen Musik von Richard oder einem der Johann Sträuße zum Beispiel, oder die zwischen Toast- und Vollkornbrot. Das ist dann „unpolitisch“, jedenfalls, solange mensch nicht allzu tief bohrt.

    „Sport“ allerdings – im durch Sportfernsehen und -vereine bestimmten Sinn – kollidiert recht fundamental mit jedem einzelnen Grundwert. Das erklärt auch zwanglos, warum SportfunktionärInnen ziemlich durchweg rechts denken (Ausnahmen wie die Crew St. Pauli bestätigen die Regel eben durch ihre Exotik) und auch entsprechend organisiert sind. Mein Lieblingsbeispiel dafür bleibt Gerhard Mayer-Vorfelder, zu verschiedenen Zeiten seines Lebens DFB-Chef und persönlicher Referent des Nazirichters Filbinger.

    Gegen Freiheit

    Der erste Gedanke bei Sport vs. Freiheit könnten die vielen barocken Regeln der meisten Sportarten sein. Um mal eine Maßstäbe setzende Norm zu erwähnen: bis 2012 durften Frauen nur in Bikins mit auf ein paar Zentimeter begrenzter Breite des Beinstegs Beachvolleyball spielen (kein Scheiß). Aber nein, solange Menschen sich freiwillig auf Regeln einigen, wäre daran wenig zu kritisieren. Wo Menschen gezwungen werden, Sport zu treiben und die Regeln deshalb keine Gegenstände von Aushandlung mehr sind, ist das Problem nicht im Sport, sondern in den externen Zwangssystemen.

    Nein, wer über Freiheit und Sport nachdenken will, möge ans Heidelberger Neckarufer kommen, wenn gerade Rudertraining ist: Der Kasernenhofton der TrainerInnen lässt keinen Raum für Zweifel[2]. Das ist am Fußballplatz nicht anders als in der Gymnastikhalle oder im Schwimmbad: Der Ton ist immer der von Befehl und Gehorsam. Bei Mannschaftssportarten kommen auch mal zusätzliche Befehlsebenen hinzu, Kapitäne im Fußball etwa, die Gehorsam erwarten und im Zweifel durchsetzen müssen, wenn sie ihren Job behalten wollen.

    Der militärische Drill skaliert zu den bedrückenden Masseninzenierungen sich synchron bewegender TurnerInnen bei Feierlichkeiten autoritärer Regimes zwischen IOK und SED. Das hat, a propos Turnen, Methode; Turnvater Jahn war glühender Patriot und Militarist und verstand seine Turnerei durchaus als paramilitärisches Training mit dem Ziel der Ablösung der ja noch halbwegs fortschrittlichen Potentaten von Napoleons Gnaden durch – nun, de facto jedenfalls die erzreaktionären Regierungen des Vormärz.

    Gehorsam und Schleiferei als Antithesen zur Freiheit sind im Sport kein Einzelfall. Sie sind von Anfang an dabei und prägen das Geschehen um so mehr, je mehr etwas Sport (und nicht vielleicht Spiel, Spazierengehen, Wohinfahren, Beetumstechen, Staubwischen) ist.

    Gegen Gleichheit

    Zum Gegensatz von Sport und Gleichheit ist zunächst wegen Offensichtlichkeit nicht viel zu sagen: in praktisch jeder Sportart geht es darum, wer der/die „BessereN“ sind. Tatsächlich könnte der Wettkampf geradezu als Definition von Sport gelten: Es ist nicht sehr übertrieben, die Grenze zwischen auf Schlittschuhlaufen (kein Sport) und Eiskunstlauf (Sport) dort zu ziehen, wo RichterInnen mit ihren Zahlentäfelchen auftauchen und jedenfalls letztendliche AdressatInnen der Handlungen auf dem Eis sind.

    Wettbewerb charakterisiert Sport auch dann, wenn das private „Sport machen“ – joggen gehen, vielleicht auch mal in die Muckibude – davon eingestandenermaßen nur peripher betroffen sein mag. Selbst dabei scheint die Motivation allerdings oft genug in der Besserstellung in diversen Konkurrenzsituationen (im Zweifel bei der Brautwerbung) zu liegen.

    Sport als Verpackung für Wettbewerb hat übrigens Auswirkungen auf die Gesamtgesellschaft, beispielsweise wenn das positive Image von Sport über schräge Metaphern regelmäßig ansonsten offensichtlich schädliche Politiken („Exportweltmeister“ ist vielleicht das furchtbarste Beispiel) rechtfertigt.

    Die Übersteigerung von Ungleichheit ist der Heldenmythos, bei dem ein einzelner (meist) Mann alle anderen hinter sich lässt und breiteste Bewunderung erfährt. Selbst in China bin ich schon auf Franz Beckenbauer angesprochen wurden, und selbst wenn die Beatles nicht beliebter als Jesus sein sollten, Diego Maradona ist es garantiert. Diese Malaise des Sportbetriebs zumindest haben die ArbeitersportlerInnen während der Weimarer Republik erkannt. Diese betrieben damals im Fußballbereich eine breite alternative Liga gegen den bereits gewohnt rechtslastigen DFB und bemühten sich in der Berichterstattung um mehr Gleichheit:

    man lehnte den „Starkult“ ab, verweigerte „Rekordjagden“, wollte keine „Kanonenzuchtanstalt“ sein. Deshalb wurden viele Jahre gar keine Spielernamen veröffentlicht. In der Presse nannte man stattdessen z. B. „den Rechtsaußen“ oder „den Mittelstürmer“.

    Zu August Postler auf arbeitersport.de

    Empfehlen möchte ich in diesem Zusammenhang die SWR2 Wissen-Sendung vom 29.6.2012, aus der ich von der Existenz der Arbeiterfußball-Liga und ihren journalistischen Mindeststandards erfahren habe.

    All das hatte mit der Machtübergabe an die Nazis ein Ende, zumal sich der DFB bereitwillig gleichschaltete, wenn er schon 1933 erklärte:

    Wir haben mit den ganzen Sozialdemokraten und Kommunisten nichts zu tun und wir sorgen auch dafür, dass weder Juden noch Arbeiter-, ehemalige Arbeitersportler bei uns im Verband offiziell Mitglied werden.

    DLF vom 27.10.2018

    Dem Vorbild des Arbeitersports zu folgen wäre, so schlage ich engelszüngelnd vor, schon mal ein erster Schritt zur Entpolitisierung des Sports: Keine Namen, keine Nationen. Wer sich erinnert, wie Boris Becker quasi im Alleingang die Tennisclubs der Republik gerettet hat, mag sich fragen, wie viel „Breitensport“ ohne nationalen Enthusiasmus eigentlich übrig bleiben würde. Und was davon. Das dürfte dann der unpolitische Teil sein.

    Gegen Solidarität

    Was „Solidarität“ angeht, kann ich mir speziell von meinen Ultra-FreundInnen den empörten Einwand vorstellen: „Aber du hast ja gar keine Ahnung, wie toll der Zusammenhalt bei uns ist. Solidarischer gehts gar nicht.“

    Nun ja. In Abwandlung des Luxemburg-Klassikers ist dazu zunächst festzustellen, dass Solidarität immer die mit den anderen ist, also nicht mit den Leuten der eigenen Gruppe und schon gar nicht denen der eigenen „Nation“. Und dass Solidarität auf jeden Fall mal kritisch ist – Solidarität mit, sagen wir, Bahnchefs heißt eben nicht, bedingungslos zu rechtfertigen, was diese so tun, sondern zu kritisieren, wie sie, neben vieler anderer Menschenfresserei, Leute hinter Autotüren treiben. Das also, was Fangruppen zusammenhält, ist keine Solidarität, es ist Abgrenzung, es ist Gruppenidentität, also das, was so gut wie alle Massenverbrechen der Geschichte – Kriege, Pogrome, Unterdrückung – erst ermöglicht hat (vgl. in diesem Zusammenhang das Minimalgruppenparadigma).

    Solidarität ist genau das Gegenteil von der Bildung von Untergruppen, die sich zu be(wett)kämpfen haben, und sei es über die Ausdeutung von StellvertreterInnen wie in der Leichtathletik. Wer anfängt, Mannschaften zu bilden, wer anfängt, für, was weiß ich, Angelique Kerber zu fiebern, weil sie ja „zu uns“ gehört, hat angefangen, sich aus der Solidarität mit den „anderen“ zu verabschieden statt, wie es Gebot der Solidarität ist, weniger Othering (ist das noch ein populärer Begriff?) zu betreiben.

    Und nun?

    Nach all dem verwundert wohl nicht, dass sich so gut wie alle rechten Ideologeme recht direkt im Sport wiederfinden, von Nationalismus (die Hymnendebatten scheinen ja mal wirklich aus einem anderen Jahrhundert zu kommen) über Homophobie (eine kommerzielle Fußballseite dazu) bis Sexismus (selbst wenn mensch an zwei Geschlechter und das Wundermittel Testosteron glaubt, kann wohl niemand die Geschlechtertrennung beim Schießen plausibel machen).

    Heißt das, dass Linke besser nicht joggen sollten? Am besten jede Anstrengung meiden? Nö, sicher nicht. Es geht hier nicht um Fleißpunkte oder moralische Reinheit. Wer mag, darf ja auch an James Bond-Streifen Spaß haben, die vergleichbar viele rechte Ideologeme bedienen. Zumindest aber im Kopf sollte mensch schon haben, dass Sportkonsum schlüpfriger Boden ist – nicht umsonst fanden die ersten größeren Angriffe auf Geflüchtete in der „neuen“ BRD nach dem Endspiel der Männerfußball-WM 1990 statt.

    Wer selbst läuft oder tritt, ist vielleicht in geringerer Gefahr. Aber dennoch: im Hinblick auf die Welt nach uns wärs schon besser, die Alltagswege mit dem Fahrrad zurückzulegen und das Gemüsebeet zu hacken als mit dem Auto in den Wald oder die Muckibude zu fahren.

    Klar, die soziale Symbolik dabei muss mensch aushalten wollen: „Ist der so arm, dass er kein Auto hat?“ Dazu will ich abschließend kurz auf den Ursprung unseres modernen Sportbegriffs eingehen, soweit ich ihn überblicke. Die gehobenen britischen Kreise im 18. Jahrhundert nämlich kamen wohl zur Einsicht, es gehe nicht so ganz ohne Bewegung und Anstrengung. „Nützliche“ Bewegung, körperliche Arbeit zumal, würde aber den Verdacht erregen, mensch habe es nötig, sei also nicht wirtschaftlich erfolgreich, mit anderen Worten: arm.

    Sport wäre dann schon im Ursprung die Demonstration von Wohlstand, wichtiger: Nicht-Armut. Ich muss nicht körperlich arbeiten, ich habe immer noch genug Zeit, mich sinnlos auszutoben, aber auch die Disziplin, mich dabei klaren Regeln zu unterwerfen, und ich habe obendrein das Geld für die tollen Accessoires, die es für Sport X braucht. Wenn ich vor allem am Wochenende durch die Berge hier radele und die Ausrüstung vieler anderer RadlerInnen ansehe, gewinnt diese These massiv an Plausibilität, bis hin zu den Fahrrädern, die oft demonstrativ alltagsuntauglich sind. Die Nachricht scheint zu sein: „Ich habe natürlich wie jeder anständige Mensch ein Auto, dieses Ding hier ist für mich nur Sportgerät.“

    Die damit verbundene zusätzliche Warenproduktion schadet dann aber schon, der …

  • Adieu, RKI-Berichte

    Oh je! Im RKI-Bericht von heute heißt es:

    Ab Montag, 19.07.2021, wird die Berichterstattung umgestellt: Eine tägliche kürzere Berichterstattung wird ergänzt mit einer ausführlichen Berichterstattung donnerstags.

    Ich gestehe offen: ich finde das ein wenig bitter. Auch wenn die Berichte nie wirklich das sagten, was sich wohl alle gefragt haben („Wo stecken sich diese Leute denn nun an? Was für Ausbrüche gibts im Land?“), waren die Zahlen und Grafiken, die da jeden Tag kamen (na ja, seit ein paar Wochen schon nicht mehr am Wochenende) durchaus ein beruhigendes und strukturierendes Element der Coronazeit.

    Die RKI-Deutschlandkarte mit farbkodierten Inzidenzen

    Gerade, wo die Karte wieder bunter wird, strafft das RKI seinen täglichen Corona-Bericht. Hm.

    Die sich windenden Inzidenzlinien der Bundesländer, die bunt gefärbten Landkreise, bei denen Extreme oft gute und manchmal auch gar keine guten Erklärungen hatten, das Schwingen der R-Wert-Schätzungen und natürlich die nach Wochentag wechselnden Features vom Wochenvergleich am Dienstag bis zur Mortalitätsstatistik am Freitag: Mir wird das fehlen, jedenfalls, solange Corona rein ethisch nicht ignorierbar ist.

    Wann ich Corona ethisch ignorierbar finde, habe ich indes noch nicht ganz klar. Wahrscheinlich werde ich irgendwann im September finden, wer dann noch nicht geimpft ist, kann es entweder nicht (und dann hat Zuwarten auch keinen Wert) oder wollte es nicht (und kann dann von mir keine Rücksicht erwarten).

    Aber wie das wirklich aussieht, wenn die Inzidenzen irgendwo jenseits der 1000 liegen – und das würden sie, wenn die IgG-Spiegel der meisten Leute wieder halbwegs normal sind und Schulen, Büros, Kneipen und Discos offen – ach, wer weiß?

    Als Abschiedsbetrachtung zu den gewohnten RKI-Berichten noch etwas aus den Tabellen zu „Betreuung, Unterbringung und Tätigkeit in Einrichtungen“ (die ich eingestandenermaßen meist überblättert habe): Dort werden ja unter anderem nach §36 IfSG „Untergebrachte“ diskutiert, was Pflegeeinrichtungen, Obdachlosenunterkünfte, Lager für (oder gegen) Geflüchtete und auch Gefängnisse umfasst. Genau dabei überrascht mich die Zeile „Sonstige“, die nach Lage der Dinge insbesondere die Gefängnis-Zahlen enthalten müsste. Dort stehen heute 1512 Fälle (seit Pandemie-Anfang), von denen 210 älter waren als 60, 132 ins Krankenhaus mussten und 27 gestorben sind.

    Das kann, nach allem, was so aus den Gefängnissen zu hören ist, schlicht nicht sein; deutsche Haftanstalten haben wahrscheinlich keine Positivraten wie Townships in Südafrika, aber sehr weit dürften sie auch nicht davon entfernt sein. Das aber würde bedeuten, dass Fälle aus Gefängnissen fast durchweg unter die 138284-85924 = 52360 Fälle nach §36 ohne „differenzierte Angaben“ fallen müssen. Und das ist schon irgendwo auf dem Skandalspektrum: Wie schwierig kann es sein, Fälle aus Gefängnissen auch so zu labeln?

  • Impfpass ohne App, Apple und Google

    Morgen werden zwei Wochen seit meiner zweiten Corona-Impfung vergangen sein. Damit wird die Impfpassfrage für mich relevant: Mit so einem Ding könnte ich wieder in die Mensa gehen!

    Allerdings habe ich, soweit ich das sehe, keinen Zugang zur offiziellen Covpass-App, weil ich mich von Apples Appstore und Googles Playstore fernhalte und eigentlich auch die Toolchains der beiden nicht auf meinem Rechner haben will. Immerhin gibt es (es lebe der Datenschutz-Aktivismus, der für offene Entwicklung von dem Kram gesorgt hat) die Quellen der Apps (wenn auch leider auf github). Wie kompliziert kann es schon sein, das ohne den ganzen proprietären Zauber nachzubauen?

    Stellt sich raus: schon etwas, aber es ist ein wenig wie eine Kurzgeschichte von H.P. Lovecraft: Die Story entwickelt sich wie beim Schälen einer Zwiebel. Schale um Schale zeigt sich, dass die Wahrheit immer noch tiefer liegt.

    Bei Lovecraft sind nach dem Abpulen der letzten Schale meist alle ProtagonistInnen tot oder wahnsinnig. Im Fall der Covpass-App hingegen ist der Kram sogar dokumentiert: So finden sich die halbwegs lesbare Dokumentation des Datenstroms im QR-Code und das JSON-Schema – leider schon wieder auf github.

    Schale 1: QR-Code scannen

    Ich dachte mir, zum Nachbauen der Covpass-App sollte ich erstmal ihre Eingabe verstehen, also die Daten aus den beiden Impfzertifikaten lesbar darstellen. Der erste Schritt dazu ist etwas, das QR-Codes lesen kann. Ich hatte anderweitig schon mit zbar gespielt, für das es das Debian-Paket python3-zbar gibt. Damit (und mit der unverwüstlichen Python Imaging Library aus python3-pillow) geht das so, wenn das Foto mit dem Zertifikat in der Datei foto.jpeg liegt:

    def get_single_qr_payload(img):
      img = img.convert("L")
    
      scanner = zbar.ImageScanner()
      scanner.parse_config('enable')
      image = zbar.Image(img.size[0], img.size[1], 'Y800', data=img.tobytes())
      if not scanner.scan(image):
        raise ValueError("No QR code found")
    
      decoded = list(image)
      if len(decoded)>1:
        raise ValueError("Multiple QR codes found")
    
      return decoded[0].data
    
    encoded_cert = get_single_qr_payload(Image.open("foto.jpeg"))
    

    Im Groben wandele ich in der Funktion das Bild (das wahrscheinlich in Farbe sein wird) in Graustufen, denn nur damit kommt zbar zurecht. Dann baue ich eine Scanner-Instanz, also das Ding, das nachher in Bildern nach QR-Codes sucht. Die API hier ist nicht besonders pythonesk, und ich habe längst vergessen, was parse_config('enable') eigentlich tut – egal, das ist gut abgehangene Software mit einem C-Kern, da motze ich nicht, noch nicht mal über diesen fourcc-Unsinn, mit dem vor allem im Umfeld von MPEG allerlei Medienformate bezeichnet werden; bei der Konstruktion des zbar.Image heißt „8 bit-Graustufen“ drum "Y800". Na ja.

    Der Rest der Funktion ist dann nur etwas Robustheit und wirft ValueErrors, wenn im Foto nicht genau ein QR-Code gefunden wurde. Auch hier ist die zbar-API vielleicht nicht ganz preiswürdig schön, aber nach dem Scan kann mensch über zbar.Image iterieren, was die verschiedenen gefundenen Barcodes zurückgibt, zusammen mit (aus meiner Sicht eher knappen) Metadaten. Das .data-Attribut ist der gelesene Kram, hier als richtiger String (im Gegensatz zu bytes, was ich hier nach der python3-Migration eher erwartet hätte).

    Schale 2: base45-Kodierung

    Das Ergebnis sieht nach üblichem in ASCII übersetzten Binärkram aus. Bei mir fängt der etwa (ich habe etwas manipuliert, das dürfte so also nicht dekodieren) so an: HC1:6B-ORN*TS0BI$ZDFRH%. Insgesamt sind das fast 600 Zeichen.

    Als ich im Wikipedia-Artikel zum Digitalen Impfnachweis gelesen habe, das seien base45-kodierte Daten, habe ich erst an einen Tippfehler gedacht und es mit base85 versucht, das es in Pythons base64-Modul gibt. Aber nein, weit gefehlt, das wird nichts. War eigentlich klar: die Wahrscheinlichkeit, dass was halbwegs Zufälliges base85-kodiert keine Kleinbuchstaben enthält, ist echt überschaubar. Und base45 gibts wirklich, seit erstem Juli in einem neuen RFC-Entwurf, der sich explizit auf QR-Codes bezieht. Hintergrund ist, dass der QR-Standard eine Kodierungsform (0010, alphanumeric mode) vorsieht, die immer zwei Zeichen in 11 bit packt und dafür nur (lateinische) Großbuchstaben, Ziffern und ein paar Sonderzeichen kann. Extra dafür ist base45 erfunden worden. Fragt mich bloß nicht, warum die Leute nicht einfach binäre QR-Codes verwenden.

    Es gibt bereits ein Python-Modul für base45, aber das ist noch nicht in Debian bullseye, und so habe ich mir den Spaß gemacht, selbst einen Dekodierer zu schreiben. Technisch baue ich das als aufrufbares (also mit einer __call__-Methode) Objekt, weil ich die nötigen Tabellen aus dem globalen Namensraum des Skripts draußenhalten wollte. Das ist natürlich ein Problem, das verschwindet, wenn sowas korrekt in ein eigenes Modul geht.

    Aber so gehts eben auch:

    class _B45Decoder:
      chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
      code_for_char = dict((c, i) for i, c in enumerate(chars))
      sig_map = [1, 45, 45*45]
    
      def __call__(self, str):
        raw_bytes = [self.code_for_char[s] for s in str]
        cooked_bytes = []
    
        for offset in range(0, len(raw_bytes), 3):
          next_raw = raw_bytes[offset:offset+3]
          next_bytes = sum(w*v for w,v in
            zip(self.sig_map, next_raw))
          if len(next_raw)>2:
            cooked_bytes.append(next_bytes//256)
          cooked_bytes.append(next_bytes%256)
    
        return bytes(cooked_bytes)
    
    b45decode = _B45Decoder()
    

    Die b45decode-Funktion ist, wenn mensch so will, ein Singleton-Objekt der _B45Decoder-Klasse (so hätten das jedenfalls die IBMlerInnen der CovPass-App beschrieben, vgl. unten). Ansonsten bildet das den Grundgedanken von base45 ziemlich direkt ab: Immer drei Bytes werden zur Basis 45 interpretiert, wobei die Wertigkeit der verschiedenen Zeichen im Dictionary code_for_char liegt. Die resultierende Zahl lässt sich in zwei dekodierte Bytes aufteilen. Nur am Ende vom Bytestrom muss mensch aufpassen: Wenn die dekodierte Länge ungerade ist, stehen kodiert nur zwei Byte.

    Und ja: vielleicht wärs hübscher mit dem grouper-Rezept aus der itertools-Doku, aber die next_raw-Zuweisung schien mir klar genug.

    Schale 3: zlib

    Ein b45decode(encoded_cert) gibt erwartungsgemäß wilden Binärkram aus, etwas wie b'x\x9c\xbb\xd4\xe2\xbc\x90Qm!… Das sind, ganz wie die Wikipedia versprochen hat, zlib-komprimierte Daten. Ein zlib.decompress wirkt und führt auf etwas, in dem zum ersten Mal irgendetwas zu erkennen ist; neben viel Binärkram findet sich etwa:

    ...2bdtj2021-07-01bistRobert Koch-InstitutbmamOR...
    

    Keine Frage: Ich mache Fortschritte.

    Schale 4: CBOR/COSE

    An dieser Stelle bin ich auf mir unbekanntes Terrain vorgestoßen: CBOR, die Concise Binary Object Representation (Nerd-Humor: erfunden hat das Carsten Bormann, weshalb ich auch sicher bin, dass das Akronym vor der ausgeschriebenen Form kam) alias RFC 7049. Gedacht ist das als so eine Art binäres JSON; wo es auf die Größe so ankommt wie bei QR-Codes, habe ich schon Verständnis für diese Sorte Sparsamkeit. Dennoch: Sind Protocol Buffers eigentlich tot?

    Praktischerweise gibt es in bullseye das Paket python3-cbor2. Munter habe ich cbor2.loads(raw_payload) geschrieben und war doch etwas enttäuscht, als ich etwas wie:

    CBORTag(18, [b'\xa1\x01&',
      {4: b'^EVf\xa5\x1exW'},
      b'\xa4\x01bDE...',
      b'\xf9\xe9\x9f...'])
    

    zurückbekommen habe. Das ist deutlich mehr viel Binärrauschen als ich erhofft hatte. Aber richtig, das Zeug sollte ja signiert sein, damit die Leute sich ihre Impf- und Testzertifikate nicht einfach selbst schreiben. Die hier genutzte Norm heißt COSE (nämlich CBOR Object Signing and Encryption, RFC 8152 aus dem Jahr 2017). Ich habe das nicht wirklich gelesen, aber Abschnitt 2 verrät gleich mal, dass, wer an einer Signaturprüfung nicht interessiert ist (und das bin ich nicht, solange ich nicht vermuten muss, dass meine Apotheke mich betrogen hat), einfach nur aufs dritte Arrayelement schauen muss. Befriedigenderweise ist das auch das längste Element.

    Ein wenig neugierig war ich aber schon, was da noch so drinsteht. Die 18 aus dem CBORTag heißt nach Abschnitt 4.2, dass das eine Nachricht mit nur einer Unterschrift ist, und der letzte Binärkram ist eben diese eine Unterschrift. Das erste Array-Element sind Header, die mit unterschrieben werden, wieder CBOR-kodiert. Dekodiert ist das {1: -7}, und Überfliegen der COSE-Spezifikation (Tabellen 2 und 5) schlägt vor, dass das heißt: der Kram ist per ECDSA mit einem SHA-256-Hash unterschrieben.

    Tabelle 2 von COSE erklärt auch das nächste Element, die Header, die nicht unterschrieben werden (und über die mensch also Kram in die Nachrichten einfummeln könnte). Das sieht auch erstmal binär aus, ist aber ein „entpacktes“ Dictionary: In meiner Nachricht steht da nur ein Header 4, was der „Key Identifier“ ist. Der Binärkram ist schlicht eine 64-bit-Zahl, die angibt, mit welchem Schlüssel die Unterschrift gemacht wurde (bei PGP wären das die letzten 8 byte des Fingerabdrucks, viel anders wird das bei COSE auch nicht sein).

    Schale 5: CBOR lesbar machen

    Zurück zu den Zwiebelschalen. Wenn also die Nutzdaten im dritten Element des Array von oben sind, sage ich:

    cbor_payload = cbor2.loads(cose_payload.value[2])
    

    Heraus kommt dabei etwas wie:

    {1: 'DE', 4: 1657705736, 6: 1626169736,
    -260: {1: {'v': [{'co': 'DE', 'dn': 2, 'dt': '2021-07-01',
    'is': 'Robert Koch-Institut', 'ma': 'ORG-100030215',
    'mp': 'EU/1/20/1528', 'sd': 2, 'tg': '840539006',...}]}}}
    

    – das ist ziemlich offensichtlich die Datenstruktur, die der Zauber liefern sollte. Nur sind die Schlüssel wirklich unklar. v könnte wohl „Vaccination“ sein, is der Issuer, also der Herausgeber des Impfpasses; die Werte von 4 und 6 sehen verdächtig nach Unix-Timestamps in der nächsten Zeit aus (ja, es sind schon sowas wie 1,6 Milliarden Sekunden vergangen seit dem 1.1.1970).

    Aber Raten ist doof, wenn es Doku gibt. Wie komme ich also zu …

  • Javascript Local Storage

    Es gibt eine große Zahl gruseliger APIs (also: „Kram, den ein Programm tun kann“) in modernem Javascript, von Sensor APIs (zur Abfrage von Beschleunigung und Orientierung des Geräts und des Umgebungslichts) bis Websocket (mit dem weitgehend beliebige Server dauernd mit dem Client reden können, und das auch noch „im Hintergrund“ in Web Workers) – gruselig ist das, weil in aktuellen und nicht weiter modifizierten Browsern jede Webseite dieses Zeug nutzen kann, wobei eingestandenermaßen ein paar besonders dramatische APIs (Mikrofon und Kamera z.B.) noch durch Rückfragen abgesichert sind. Oh: Webseiten können das nicht nur nutzen, viel zu viele brauchen Javascript und gehen nicht, wenn mensch es abdreht.

    Der breite Zugriff auf fast alles von Javascript aus ist der Grund, warum ich des Öfteren ziemlich unwillig auf „please enable Javascript“-Banner (und noch mehr auf ihre Abwesenheit trotz Abhängigkeit von Javascript) reagiere. Javascript erlauben bedeutet spätestens seit XMLHTTPRequest (mit dem Javascript an der NutzerIn vorbei mit dem Ursprungsserver kommunizieren konnte; kam in der ersten Hälfte der Nullerjahre) und CORS (was XMLHTTPRequest und jetzt fetch auf beliebige Server ausweitete, solange die kooperieren; im Firefox tauchte das 2009 auf) einen recht weitgehenden Zugriff auf die eigene Maschine zu erlauben, und das noch ganz ohne Spectre und Freunde – die übrigens ohne ubiquitäres Javascript auf privaten Rechnern weitgehend bedeutungslos wären.

    Eine API, die ziemlich gruselig ist, weil sie Webseiten ein unendlich langes Gedächtnis in eurem Browser gibt, ist Local Storage; damit können Webseiten ernsthafte Datenmengen in eurem Browser speichern und sie wiederfinden, wenn sie das nächste Mal Javascript ausführen dürfen. Dass das zunächst lokal gespeichert wird, hilft nicht viel – per Websocket oder zur Not einem fetch mit Payload ist der Kram auch (wieder) auf jedem Server, der bereit ist, sich das anzuhören. Wohlgemerkt: ohne dass NutzerInnen irgendwas mitbekommen.

    Wenn ihr mein Gruseln nachfühlen wollt, könnt ihr hier mal Javascript einschalten (ihr lasst mich doch sonst kein Javascript ausführen, oder?). Ihr bekommt dann unter diesem Absatz ein Eingabefeld, in das ihr Kram tippen könnt. Wenn ihr einen hinreichend modernen Browser habt (technisch: er muss das storage-Signal schicken; Firefox 78 tut das z.B., Webkit 4.0.37 nicht), könnt ihr eure Nachricht in der Javascript-Warnung am Fuß der Seite sehen, schockierenderweise auch in anderen Fenstern, die ihr auf blog.tfiu.de offen habt. Auf allen halbwegs aktuellen Großbrowsern erscheint der Text jedenfalls nach dem nächsten Reload. Und bleibt auch da. Aufauf, schreibt eurem künftigen Selbst eine Nachricht in den Fuß dieser Seite:

    Gut. Du hast Javascript aus.

    Nennt mich paranoid, aber lustig ist das nicht.

    Und so ärgern mich noch viel mehr als Seiten, die Javascript fordern, Seiten, die ohne Local Storage leer bleiben oder sonst irgendwie undurchschaubar kaputt gehen.

    Was tun?

    Für die großen Browser gibt es allerlei Erweiterungen, die das Management von Local Storage erlauben; im Firefox sehe ich gerade Forget Me Not oder StoragErazor (was gleich noch die IndexedDB-API mit abdeckt, die ähnlich schrecklich ist, aber noch nicht viel genutzt wird); soweit ich erkennen kann, erlaubt das unverzichtbare noscript nicht, Javascript ohne Local Storage laufen zu lassen.

    Für meinen Haupt-Browser, den Luakit (verdammt, schon wieder ein Link von hier in github rein), habe ich eine kleine Erweiterung geschrieben, mit der ich mit der Tastenkombination ,tq schnell local storage ein- und ausschalten kann; auf die Weise kann ich normalerweise ohne Local Storage browsen, wenn dann aber mal wirklich eine Seite kaputt ist (gitlab ist da derzeit so ein ganz schlechtes Beispiel), braucht es nur ein paar Anschläge. Eine Anzeige in der Fußleiste (q/Q für Storage aus/an) kommt auch mit:

    -- Web storage control
    
    -- @module webstorage_control
    -- @copyright Public Domain
    
    local _M = {}
    
    local window = require("window")
    local theme = require("theme")
    local settings = require("settings")
    local modes = require("modes")
    local add_binds = modes.add_binds
    
    function update_webstorage_disp(w)
        if settings.get_setting("webview.enable_html5_database") then
            w.sbar.r.webstorage_d.text = "Q"
        else
            w.sbar.r.webstorage_d.text = "q"
        end
    end
    
    function toggle_local_storage(w)
        local local_storage_enabled =
            settings.get_setting("webview.enable_html5_database")
    
        settings.set_setting("webview.enable_html5_database",
            not local_storage_enabled)
        settings.set_setting("webview.enable_html5_local_storage",
            not local_storage_enabled)
        update_webstorage_disp(w)
    end
    
    window.add_signal("init", function (w)
        local r = w.sbar.r
        r.webstorage_d = widget{type="label"}
        r.layout:pack(r.webstorage_d)
        r.layout:reorder(r.webstorage_d, 1)
        r.webstorage_d.font = theme.font
        update_webstorage_disp(w)
    end)
    
    add_binds("normal", {
        { "^,tq$", "Enable/disable web local storage", toggle_local_storage},
    })
    
    return _M
    
    -- vim: et:sw=4:ts=8:sts=4:tw=80
    

    Wer auch den luakit verwendet, kann das nach .config/luakit/webstorage_control.lua packen und dann:

    require("webstorage_control")
    

    an geeigneter Stelle (z.B. in .config/luakit/rc.lua) unterbringen. Wenn dermaleinst so viele Seiten ohne Local Storage kaputtgehen wie derzeit ohne Javascript, müsste das wahrscheinlich eher wie in der noscript-Erweiterung automatisiert werden.

    Auch wenn ich mal Local Storage erlaube, will ich natürlich nicht, dass der Kram persistent bleibt. Deshalb habe ich noch folgendes kleine Python-Programm geschrieben:

    #!/usr/bin/python
    """
    Clear luakit web local storage and cookies
    
    There's a whitelist applied to both.
    """
    
    
    import fnmatch
    import glob
    import os
    import re
    import sqlite3
    
    
    class Whitelist:
        """A fnmatch-based whitelist.
    
        Test as in "domain in whitelist".  It's not fast, though.
        """
        def __init__(self,
                src_path=os.path.expanduser("~/.config/luakit/cookie.whitelist")):
            with open(src_path) as f:
                self.patterns = [s.strip() for s in f.read().split("\n")]
    
        def __contains__(self, domain):
            for pattern in self.patterns:
                if fnmatch.fnmatch(domain, pattern):
                    return True
            return False
    
    
    def clear_cookies(whitelist):
        """removes cookies from domains not in whitelist from luakit's
        cookies db.
        """
        conn = sqlite3.connect(
            os.path.expanduser("~/.local/share/luakit/cookies.db"))
    
        try:
            all_hosts = list(r[0]
                for r in conn.execute("select distinct host from moz_cookies"))
            for host in all_hosts:
                if host in whitelist:
                    continue
                conn.execute("delete from moz_cookies where host=?",
                    (host,))
        finally:
            conn.commit()
            conn.execute("VACUUM")
            conn.close()
    
    
    def try_unlink(f_name):
        """removes f_name if it exists.
        """
        if os.path.exists(f_name):
            os.unlink(f_name)
    
    
    def clear_local_storage(whitelist):
        """removes luakit's local storage files unless their source
        domains are whitelisted for cookies.
        """
        for f_name in glob.glob(os.path.expanduser(
                "~/.local/share/luakit/local_storage/*.localstorage")):
            mat = re.match("https?_(.*?)_\d+.localstorage",
                os.path.basename(f_name))
            if not mat:
                print("{}???".format(f_name))
                continue
    
            if mat.group(1) in whitelist:
                continue
    
            try_unlink(f_name)
            try_unlink(f_name+"-shm")
            try_unlink(f_name+"-wal")
    
    
    def main():
        whitelist = Whitelist()
        clear_cookies(whitelist)
        clear_local_storage(whitelist)
    
    
    if __name__=="__main__":
        main()
    

    Das Programm liest eine Liste von Shell-Patterns (also etwas wie *.xkcd.com) aus einer Datei ~/.config/luakit/cookie.whitelist und löscht dann alle Cookies und Local Storage-Einträge im Luakit, die nicht von Servern kommen, die in dieser Ausnahmeliste erwähnt sind. Das Ganze läuft bei mir jeden Morgen aus meiner Crontab:

    01 09 * * * ~/mybin/clear_luakit_cookies.py
    

    Aber: Besser wärs, das wäre alles nicht da. In einem Browser, also etwas, mit dem mensch Webseiten anschauen will, hat eine API wie Local Storage mit Persistenz und Signalisierung eigentlich nichts verloren.

    Oh: Der Javascript-Quellcode für den ganzen Spaß mit euren Notizen in der Fußzeile ist erschreckend klein. Für den Fall, dass ich das mal anders schreibe und das so nicht mehr im Seiten-Quellcode zu finden sein wird, hier zunächst der Code für das Eingabefeld oben:

    <div id="textarea-container">
      <p><em>Gut.  Du hast Javascript aus.
      </em></p>
    </div>
    
    <script deferred="deferred">
      function setUp() {
        document.querySelector("#textarea-container").innerHTML =
          `<textarea id="to-store" style="width:100%; height:6cm"
          placeholder="Tippt kram, den ihr im Fuß der Seite sehen wollt."
          ></textarea>`;
        let textSource = document.querySelector("#to-store");
        if (!window.localStorage) {
          textSource.value = "Ah, gut.  Du hast local storage aus.  Dann\n"
            +"geht das hier nicht.  Wie gesagt, das ist gut.";
           return;
        }
    
        if (window.localStorage.savedText) {
          textSource.value = window.localStorage.getItem("savedText");
        }
    
        textSource.addEventListener("input", () => {
          window.localStorage.setItem("savedText", textSource.value);
        });
    
        window.addEventListener("storage", (ev) => {
          textSource.value = ev.newValue;
        });
      }
    
      setUp();
    </script>
    

    Und dann noch der fürs Management der Fußzeile (der sitzt jetzt gerade im head-Element):

    if (window.localStorage) {
      target.innerHTML +=
        `<div id="ls-warning"><p><strong>Schlimmer noch:</strong>
        Dein Browser lässt mich
        auch local storage machen.  Wenn du dir in
        <a href="/javascript-local-storage.html">diesem Artikel</a>
        eine Nachricht hinterlässt, bekommst du sie bei deinem nächsten
        Besuch unten zu sehen; du kannst da sogar dein eigenes
        HTML und Javascript unterbringen und ausführen lassen.</p>
        <p id="user-message"/></div>`;
    
      if (window.localStorage.savedText) {
        document.querySelector("#user-message").innerHTML =
          window.localStorage.savedText;
      }
    
      window.addEventListener("storage", (ev) => {
        document.querySelector("#user-message").innerHTML = ev.newValue;
      });
    }
    
  • Geistesgegenwart um Mitternacht: Tut sie aber nicht

    Ich bin ja eigentlich niemand, der „Handarbeit“ als Qualitätsprädikat sonderlich schätzt, aber es ist gerade bei Radio schön, wenn sich zeigt, dass der Kram zwar aus dem Computer kommt, aber doch noch Menschen vor dem Computer sitzen.

    So ging das am letzten Samstag (3.7.), kurz nach Mitternacht. Mein Rechner schneidet da immer den Mitternachtskrimi aus dem Live-Programm des Deutschlandfunks mit und hat dabei dieses großartige Stolpern aufgenommen:

    (um die Bediengeräusche besser herauszubringen, habe ich das Audio etwas komprimiert). Ich muss sagen, dieses kurze Selbstgespräch fand ich sehr beeindruckend – und ich habe mich wiedererkannt, denn in dieser Sorte experimentellen Diskurses mit der Maschine versuche auch ich mich dann und wann.

    Zu diesem schönen Ausschnitt habe ich zwei Einwürfe zu bieten.

    Erstens war die dann doch noch folgende Sendung eine leicht expressionistische Hörspielfassung des Kleist-Klassikers Das Erdbeben in Chili, die ich hier liebend gerne verteilen würde, weil sie schön zeigt, was für ein garstiges Gift reaktionäre Hetzerei ist; ich kann mir nur schwer vorstellen, dass, wer das gehört hat, noch auf das Gift von, sagen wir, Innenminister Seehofer hereinfallen könnte.

    Aber nun, das Urheberrecht hindert mich daran, was mein Argument von neulich gegen das „geistige Eigentum“ schön illustriert: Das Hörspiel, vermutlich eine öffentlich-rechtliche Produktion, gäbe es natürlich auch, wenn ich es jetzt verteilen dürfte, und die Leute, die das damals gemacht haben, sind hoffentlich schon dabei ordentlich bezahlt worden und werden kaum auf ein paar Cent für einen Download durch euch angewiesen sein. Die Existenz des Textes hat offensichtlich nichts mit Urheberrecht zu tun, denn zu Kleists Zeiten gab es gar keins. Hier wirken die heutigen („Post-Micky-Maus“) Regelungen diametral gegen den ursprünglichen Zweck des Urheberrechts, nämlich, der Gesellschaft eine möglichst reichhaltige Kultur zur Verfügung zu stellen.

    Der zweite Einwurf: Über die vergangenen 20 Jahre hatte ich verschiedene Hacks, um Radio-Streams mitzuschneiden – ich schaudere, wenn ich an die schlimmen Tage von RealAudio und das Rausfummeln des Signals über preloaded libraries zurückdenke, die das write der libc überschrieben haben. Nun, der proprietäre Client wollte kein Speichern der Streams zulassen (schon wieder das Copyright-Gift!).

    Inzwischen ist das Mitschneiden dank ffmpeg und offener Standards auf der Seite der Radiostationen nur noch ein schlichtes Shellscript. Ich verwende seit ein paar Jahren das hier:

    #!/bin/bash
    
    if [ ! $# -eq 3 ]; then
            echo "Usage $0 time-to-record m3u-url output-file"
            exit 1
    fi
    
    
    case "$2" in
            dlfhq)
                    stream=https://st01.sslstream.dlf.de/dlf/01/high/opus/stream.opus
                    oopts=""
                    ;;
            dlf)
                    stream=https://st01.sslstream.dlf.de/dlf/01/low/opus/stream.opus
                    oopts="-ac 1 -ar 22500"
                    ;;
            dradio)
                    stream=`curl -s http://www.deutschlandradio.de/streaming/dkultur_lq_ogg.m3u | head`
                    ;;
            *)
                    stream="$2"
                    ;;
    esac
    
    ffmpeg -y -nostdin -loglevel error -i "$stream"  $oopts -start_at_zero -to $1  -c:a libvorbis "$3"
    

    (wahrscheinlich ist die dradio-Regel kaputt, aber das ist sicher leicht repariert). Das lege ich an eine passende Stelle, und cron sorgt für den Rest. Die crontab-Zeile, die mir schon viele Mitternachtskrimis und eben auch die Perle von oben mitgeschnitten hat, sieht so aus:

    05 00 * * sat /path/to/oggsnarf 1:00:00 dlf ~/media/incoming/mitternachtskrimi`date +\%Y\%m\%d`.ogg
    

    Nachtrag (2021-11-01)

    Nach ein paar Monaten fällt mir auf, dass nur ganz kurz nach diesem Post und meiner zustimmenden Erwähnung der Mitternachtskrimis (die allerdings schon damals zu „blue crime“ geworden waren) der Deutschlandfunk den seit mindestens meiner späten Kindheit den Krimis gehörenden Programmplatz am Samstag um 0:05 auf aktuelle Kulturberichterstattung („Fazit“) umgewidmet hat. Die Crontab-Zeile hat also nicht mehr viel Wert (und ist längst aus meiner crontab verschwunden). Ich glaube, die Idee der ProgrammplanerInnen wird gewesen sein, den Krimi Hörspiel-Podcast als Ersatz anzubieten.

« Seite 14 / 17 »

Letzte Ergänzungen