Schlagwort-Archive: Medieninformatik

Schoenere Karten mit R und ggplot2

Vor einiger Zeit hatte ich hier schon einmal beschrieben, wie sich mit R einfache Karten und Visualisierungen herstellen lassen. Das geht natuerlich noch deutlich komplexer — aber eben auch schoener. Edward Tufte sollte eigentlich allen ein Begriff sein, die sich mit Visualisierung und grafischer Aufbereitung von Information beschaeftigen; „The Visual Display of Quantitative Information“ empfehle ich immer wieder gerne (Amazon-Affilliate-Link; alternativ ISBN 0961392142).

Neben Tufte gibt es noch ein weiteres grosses Werk, auf das ich bei der ganzen Kartiererei in R gestossen bin: „The Grammar of Graphics“ (Amazon-Affilliate-Link, alternativ ISBN 0387245448). „Gestossen“ ist hier weit ausgelegt, ich habe das Buch nicht einmal gelesen. Ich kenne aber die auf ihm basierende R-Library ggplot2, die die Grammar of Graphics fuer ihre Plots verwendet — und sie dabei aesthetisch ansehlich werden laesst.

Ich verwende im folgenden Beispiel wieder das ESRI-Shapefile der Stadt mit den integrierten Altersquotienten pro Stadtviertel. Prinzipiell laesst sich hier noch viel mehr machen, naemlich auch mit Daten aus Drittquellen. Dazu komme ich in einem spaeteren Post.

Zuerst holen wir uns einige Bibliotheken, setzen das Arbeitsverzeichnis und lesen das Shapefile ein. Ich binde in diesem Tutorial die Libraries immer erst dann ein, wenn eine ihrer Funktionen zum Einsatz kommt. Ich hoffe, so ist halbwegs nachzuvollziehen, was wozu gehoert. Die rgdal-Library erfordert PROJ.4, das einige Zeit lang in Debian und seinen Derivaten in einer kaputten Version daher kam; unter Ubuntu lohnt hier ein Blick auf UbuntuGIS.

library(sp)
library(rgdal)
setwd("/media/home/opendata/altersquotient")
ulm <- readOGR(".", "G_Altersquotient_311210")

Mit einem Blick in die ersten Zeilen des Datenteils unseres Shapefiles faellt auf, dass die Codierung (wieder) etwas gelitten hat. Das laesst sich durch Konvertierung und Ueberschreiben der urspruenglichen Spalten beheben.

head(ulm@data)
ulm@data$STT_Name <- iconv(ulm@data$STT_Name, "ISO_8859-1", "UTF-8")
ulm@data$STTV_Name <- iconv(ulm@data$STTV_Name, "ISO_8859-1", "UTF-8")

Im Folgenden trennen wir den Datenteil vom eigentlichen Shape und wandeln letzteres in Koordinatenreihen um. Um hinterher die einzelnen Teile wieder sinnvoll zusammenfuehren zu koennen, verpassen wir dem ulm-Objekt eine Spalte id, die einfach der Zeilennummer entspricht. Anschliessend speichern wir den Datenteil von ulm nach ulm.df

ulm@data$id <- rownames(ulm@data)
ulm.df <- as.data.frame(ulm)

Die bekannte Library maptools hilft uns nun mit seiner fortify()-Methode, aus dem Shapefile Koordinatenreihen zu machen. Leider ist das nicht so ganz GNU-konform, so dass wir erst einmal mit gpclibPermit() die Erlaubnis geben muessen, diese Teilfunktion auch zu benutzen. (Danke an diese Tutorials und Beispiele, die mich auf die Sache mit dem fortify() gebracht haben)

library(maptools)
gpclibPermit()
ulm_fort <- fortify(ulm, region="id")

Nun muessen ulm.df und ulm_fort wieder zu einem gemeinsamen Data Frame kombiniert werden. Das uebernimmt die join()-Funktion aus der plyr-Library, die wie ein SQL-Join funktioniert. Bei komplexeren Verknuepfungen sollte man das im Kopf behalten und gegebenenfalls explizit einen left oder right oder inner join machen, um nicht zu verzweifeln 😉

Wichtig ist natuerlich, dass beide Teile eine gemeinsame Spalte haben, anhand derer sie verbunden werden koennen. Mit einem head() sehen wir, dass das wunderbar der Fall ist.

library(plyr)
head(ulm.df)
head(ulm_fort)

ulm_merged <- join(ulm_fort, ulm.df, by=“id“)

Nun wird geplottet — mit dem altbekannten RColorBrewer und der ggplot2-Library. Wir fuegen hinzu:

  • Eine Aesthetikangabe: Welche Werte sollen fuer x, y und die Fuellung der Flaechen verwendet werden? Wir faerben anhand des Altersquotienten ein.
  • Die Angabe, aus den Koordinatenreihen Polygone zu zeichnen
  • Zusaetzlich weisse Umrisse um die Stadtviertel
  • Eine Farbskala fuer die Altersquotientenfuellung. colours = brewer.pal(9,“Greens“) wuerde schon reichen, dann gaebe es aber nur fuenf Abstufungen. Stattdessen definieren wir die breaks in Zehnerabstaenden, indem wir einen geeigneten Vektor uebergeben.

library(ggplot2)
library(RColorBrewer)
ggplot(ulm_merged) +
aes(long, lat, group=group, fill=ALTQU) +
geom_polygon() +
geom_path (color="white") +
scale_fill_gradientn(colours = brewer.pal(9, "Greens"), breaks = c(10, 20, 30, 40, 50, 60, 70, 80, 90)) +
coord_equal()

Et voila — eine wunderbare Karte mit schoenem, unaufdringlichem Gitternetz und abgesetztem Hintergrund 🙂

R ist jedoch nicht „nur“ dazu da, bunte Karten zu plotten, zumal ohne raeumlichen Bezug und (in diesem Fall) im Gauss-Krueger-Koordinatensystem. Die hier verwendeten Libraries koennen jedoch noch viel mehr: Komplexe Kombinationen von Daten, und vor allem auch die Ausgabe in verschiedensten Formaten. Google Fusion Tables? GeoJSON? Kein Problem.

Mehr dazu irgendwann demnaechst 😉

Karten mit R

Ich haette mich in den letzten Tagen eigentlich mit etwas voellig anderem beschaeftigen muessen. Deswegen habe ich mich in R eingearbeitet. Prokrastination, level: 14. Semester. Und weil mir das Spass gemacht hat, moechte ich meine Erfahrungen festhalten und teilen.

Am Ende dieses kleinen Durchlaufs steht eine Choroplethenkarte — also eine in Subregionen unterteilte Karte, deren Flaechenfaerbung gewisse Kennzahlen anzeigen kann. So etwas geht heutzutage auch schoen als Overlay-Karte mit OpenStreetMap, mich interessierte aber der Prozess in R, und wie man ueberhaupt einmal zu den passenden Farben kommt 😉

0: R installieren

R gibt es fuer Win, MacOS und Linux; ich habe mich mit der letzteren Variante beschaeftigt. Eigentlich ginge das wunderbar mit sudo apt-get install R, dann wird aber bei einigen Distributionen erst einmal eine aeltere Version installiert, die viele Dinge nicht kann, die wir spaeter noch brauchen. Hier ist beschrieben, wie man die passenden Paketquellen einbindet, sofern man nicht ohnehin aus dem Source heraus kompilieren moechte.

Wenn man moechte, kann man auch eine GUI verwenden. Ich habe ein wenig mit RKward gespielt, mit dem man schoen die zu erledigenden Schritte in eine Skriptdatei schreiben und Zeile fuer Zeile abarbeiten kann — das hilft, die eigenen Schritte hinterher auch festzuhalten. Prinzipiell geht aber alles auch in der Konsole → R ausfuehren und anfangen. Mit q() geht’s wieder zurueck in die Shell.

(Mittlerweile bin ich auch auf Deducer gestossen, der recht vielversprechend aussieht, dazu vielleicht spaeter noch etwas)

1: Erste Schritte

Ich werde nicht grossartig auf die R-Grundlagen eingehen — die eignet man sich am besten dann bei, wenn man irgendwo auf ein Problem stoesst. Das kurze Grundlagenhandbuch von Thomas Petzold hat mir hierfuer gut getaugt.

Die Uebersicht aller Ulmer Stadtviertel liegt auf ulmapi.de als ZIP-Archiv mit einem ESRI-Shapefile vor. Und von dort zur ersten primitiven Karte sind es eigentlich nur vier Zeilen:

library(maptools)
setwd("/media/home/opendata/stadtviertel")
ulm <- readShapePoly("Stadtviertel_Gesamt_270209.shp")
plot(ulm)

Falls die maptools- (oder eine beliebige andere) Bibliothek nicht vorhanden ist, kann sie aus R heraus mit install.packages("maptools") nachinstalliert werden. Gegebenenfalls ist hierfuer noch der gcc- und gfortran-Compiler zu installieren. Das Argument in setwd() sollte natuerlich das eigene Arbeitsverzeichnis sein, in dem die Shapes aus dem ZIP-Archiv liegen.

Mit diesen wenigen Zeilen haben wir also eine erstens zum schreien haessliche und zweitens vollkommen informationsfreie Karte mit den Umrissen der Ulmer Stadtviertel hinbekommen. Dieser Schritt bringt uns also ueberhaupt nichts nuetzliches, aber zumindest einmal das gute Gefuehl, dass da etwas geklappt hat 🙂

2: Farbe!

Interessanter wird es, wenn tatsaechlich auch Farbe ins Spiel kommt. Die Shapefiles bringen (in der Regel) eine DBase-dbf-Datei mit, in denen mit den Umrissen verknuepfte Daten mitgebracht werden. Die liegen nun im Datenslot der Variable ulm, die wir vorhin mit dem Shape gefuellt haben. Ein einfaches

ulm

wirft uns den kompletten Inhalt dieser Variable um die Ohren — also auch alle Koordinaten. Mit

names(ulm)

sehen wir die Namen der Datenvektoren, und mit

ulm@data

bekommen wir diese als „Tabelle“ angezeigt. Einzelne Spalten (bzw. Vektoren) koennen wir mit einem angehaengten $Spaltenname selektieren; so gibt

ulm@data$ST_NAME (oder einfach ulm$ST_NAME)

alle Eintraege im Datenvektor der Stadtteilnamen aus. Nach diesen Eintraegen koennen wir nun arbeiten — zum Beispiel, indem wir einfach einmal die Karte nach Stadtteilen faerben. Das geht in zwei Zeilen:

col <- rainbow(length(levels(ulm@data$ST_NAME)))
spplot(ulm, "ST_NAME", col.regions=col, main="Stadtviertel Ulms", sub="cc-by-sa, Datensatz der Stadt Ulm", lwd=.8, col="white")

rainbow() erzeugt hier einfach einen Farbverlauf — oder besser gesagt, einen Zeichenvektor mit so vielen (length()) RGB-Farben, wie es eindeutige Werte (levels()) im Vektor ST_NAME gibt. spplot() plottet hier ulm, faerbt die durch ST_NAME bezeichneten Regionen mit der vorhin erstellten Palette ein, setzt Titel und Untertitel und die Grenzen zwischen den einzelnen Flaechen auf weisse Linien.

(Zusammengebastelt anhand dieser Tutorials)

Auch diese Darstellung ist in der Darstellung eher unspannend — dargestellt werden so nur Raumordnungsdaten, keine statistischen Werte. Dazu kommen wir nun.

3: Malen nach Zahlen

Eigentlich sollen Zahlenwerte dargestellt werden, wie im R Choropleth Challenge demonstriert. Hierzu brauchen wir aber erst einmal die darzustellenden Daten samt Schluesseln, um sie den passenden Regionen zuordnen zu koennen.

Die Tutorials und Anleitungen, die ich durchgeackert habe, gehen von zwei Praemissen aus — entweder werden RData-Objekte aus der GADM-Datenbank verwendet, wie in diesem Tutorial ueber die Einwohnerdichte indischer Bundesstaaten. Oder es geht um ESRI-Shapefiles, die in ihrem dbf-Anhaengsel deutlich mehr Nutzdaten mitbringen als unsere Stadtteilekarte. Schoene Beispiele hierfuer finden sich auf dieser Uebersichtsseite sowie in diesem weiterreichenden Beispiel, beides von der University of Oregon, an der gerade (Fruehling 2012) offenbar eine passende Vorlesung laeuft.

Die Zuordnung von Shape und geschluesselten CSV-Dateien greife ich (vielleicht ^^) in einem Folgeartikel noch einmal auf. Stattdessen gibt es nun was ganz exklusives, eine UlmAPI-Sneak-Preview quasi: Einen nagelneuen Datensatz der Stadt, bevor er auf ulmapi.de landet. Wow!

Es handelt sich um *trommelwirbel* ein Shapefile, das neben den Schluesseln und Namen auch den Altersquotienten fuer das jeweilige Viertel beinhaltet. Wow! 😀

Der Altersquotient gibt das Verhaeltnis von Personen ab 65 zu Personen von 14–64 an und kann somit als Indikator fuer die Altersstruktur der Bevoelkerung dienen. Und das laesst sich natuerlich gut farbig darstellen 🙂

Wir fangen wieder mit unseren bisherigen Bibliotheken und dem Einlesen an:

library(sp)
library(maptools)
setwd("/media/home/opendata/altersquotient")
ulm <- readShapePoly("G_Altersquotient_311210.shp")
# Inhalte kontrollieren
names(ulm)
ulm@data

Na hoppla, da ist was schiefgegangen, oder? Die Chancen sind gross, dass hier nun etwas wie „ M\xe4hringen“ steht. Das ist aber nichts, was man nicht schnell beheben koennte — wir konvertieren die betroffenen Vektoren korrekt nach UTF-8 und ersetzen die Originale damit:

ulm@data$STT_Name <- iconv(ulm@data$STT_Name, "ISO_8859-1", "UTF-8")
ulm@data$STTV_Name <- iconv(ulm@data$STTV_Name, "ISO_8859-1", "UTF-8")

Um nun die Daten aus der Spalte ALTQU in Farben umzusetzen, verwenden wir das Paket RColorBrewer, das einige fuer Diagrammvisualisierungen praktische Farbverlaeufe mitbringt, und die Bibliothek classInt, um die Werte unseres Altersquotientenvektors zu klassieren:

library(RColorBrewer)
library(classInt)

plotvar <- ulm@data$ALTQU
nclr <- 7
plotclr <- brewer.pal(nclr,"Greens")
class <- classIntervals(plotvar, nclr, style="equal")
# class <- classIntervals(plotvar, nclr, style="quantile")
colcode <- findColours(class, plotclr)

in diesem Beispiel sind die Klassenbreiten konstant; classIntervals() laesst jedoch natuerlich auch noch andere Optionen zu.

Diese Vorbereitung reicht schon, um die oben abgebildete Karte anzuzeigen:

spplot(ulm, "ALTQU", col.regions=plotclr, at=round(class$brks, digits=2), main = "Altersquotient nach Stadtvierteln in Ulm", sub="Stand 31.12.2010 nach Daten der Stadt Ulm, cc-by-sa", lwd=.8, col="white")

Weiteres Tuning waere beispielsweise durch die Anzeige der Stadtviertelnamen moeglich, was aber angesichts der teilweise dichten Haeufung nur zur groben Orientierung taugt:

spplot(ulm, "ALTQU", col.regions=plotclr, at=round(class$brks, digits=2), main = "Altersquotient nach Stadtvierteln in Ulm", sub="Stand 31.12.2010 nach Daten der Stadt Ulm, cc-by-sa", lwd=.8, col="white", sp.layout = list("sp.text", coordinates(ulm), as.character(ulm$STTV_Name), cex=0.6))

So weit so gut…

Dieser Einstieg kratzt leider wirklich nur an der Oberflaeche — und auch die Darstellung mit spplot laesst ein wenig zu wuenschen uebrig. Ebenfalls nicht behandelt habe ich das „Problem“, Shapefiles mit ganz anderen Daten zu verknuepfen. Die verlinkten Tutorials helfen hier teilweise schon weiter — ich hoffe aber, die naechsten Tage zwischen Barcamporga und Arbeiten noch ein wenig Zeit fuer ein weiteres Posting ueber ggplot2 und weitere Beispiele hinzubekommen 🙂

Viele weitere Datensaetze und vor allem auch Visualisierungsjunkies findest du ausserdem auf dem OpenCityCamp am 12. und 13. Mai 2012 an der Uni Ulm 😉

(edit: peinliche Typos gefixt)

Diffie-Hellman mit Farben erklaert

Schoenes Fundstueck: Ein Youtube-Channel voller Erklaerungen rund um Kryptographie — und hier die Erklaerung, wie der Diffie-Hellman-Schluesselaustausch funktioniert, mit dem zwei Kommunikationspartner ueber einen unsicheren Kanal einen gemeinsamen geheimen Schluessel vereinbaren koennen — mit Farben als Beispiel 🙂

Via Securology: Teaching Public Key Crypto.

Von der Zukunft der Mensch-Maschine-Interaktion

Addendum: Gerrit van Aaken hatte sich vor einiger Zeit schon von etwas anderer Warte aus ueber die Zukunft der Appleschen Picture-under-Glass-UIs ausgelassen — irgendwie hatte ich bislang uebersehen, dass das auch hier verlinkt werden kann und soll.

Vor einiger Zeit ging ein Microsoft-Research-Video (hauptsaechlich) durch Google+ und sorgte fuer durchwachsene Reaktionen — teilweise war da auch Microsoft-Baeh-Apple-toll-Meinung dabei, ich fuer mich fand es wegen der allzu „slicken“ und wenig „menschlichen“ Interaktion eher abschreckend als inspirierend.

Bret Victor hat nun einen extrem lesenswerten und mit schoenen Bildern (wie dem hier dreist geklauten) illustrierten Rant geschrieben, der einen sehr wesentlichen Kritikpunkt dieser Visionen hervorhebt — der mir nicht aufgefallen war, obwohl er so hervorragend zu der hier schon erwaehnten Keynote von Aaron Marcus auf der MuC 2011 passt:

I call this technology Pictures Under Glass. Pictures Under Glass sacrifice all the tactile richness of working with our hands, offering instead a hokey visual facade.

[…]

Pictures Under Glass is an interaction paradigm of permanent numbness. It’s a Novocaine drip to the wrist. It denies our hands what they do best. And yet, it’s the star player in every Vision Of The Future.

Victor bittet — nein, er fleht schon beinahe — darum, weitere Interaktionsmoeglichkeiten mit menschlichen Haenden zu erforschen, von Grund auf. Das iPad sei letztlich die logische Konsequenz aus 40 Jahren Forschung rund um die Idee eines Pads (wie das Mark Weiser dann spaeter, in den 1990ern, nennen wuerde).

That’s the kind of ambitious, long-range vision I’m talking about. Pictures Under Glass is old news. Let’s start using our hands.

Ein augenoeffnender Rant (samt kommentiertem Feedback), der mich wieder zurueck zu der Frage bringt, die Aaron Marcus in Chemnitz aufwarf: Wie werden wohl zukuenftige Rituale im Umgang mit Maschinen aussehen?

(via Kris Koehntopp auf g+ und letztendlich Kosmar)

Usability-Tester gesucht

Falls jemand Lust hat, direkt im Entwicklungszyklus von Nutzerinteraktionskonzepten eingebunden zu sein: Nokia macht gerade regelmaessig Interaktionsstudien mit Smartphonenutzern im Ulmer Science Park II. Die Versuche wechseln wohl quasi woechentlich; Kollegen von mir haben Bedienkonzepte am Papiermodell getestet, ich durfte die Bedienung von Geraeteprototypen im Vergleich zu am Markt erhaeltlichen Telefonen testen.

Das Ganze macht einen Haufen Spass, den Einblick in den Entwicklungsprozess fand ich ziemlich spannend, und es gibt ganze 30 EUR Verguetung fuer eine knappe Stunde „Arbeit“.

Falls jemand Lust zur Teilnahme hat und mir dabei auch noch etwas Gutes tun will, kann er sich bei der Probandenregistrierung auf mich beziehen — pro Weiterempfehlung komme ich dem Ziel „Kindle“ 20 EUR naeher, fuer die ich mich dann auch erkenntlich zeigen werde. Wer mich nicht mag oder mir kein Geld goennt, kann Dodo, Henning oder JuKa als Werber*in angeben, dann bekommen eben die einen Gutschein 😉

Der Weichert und die Social Networks (und das Geld und so)

Thilo Weichert ist nicht nur Chef des ULD, sondern auch Evangelist. Lars Reineke vergleicht ihn nicht zu Unrecht mit einem „religioesen Fundamentalisten“, wobei man sich das „religioes“ sparen und gegebenenfalls bei der Ueberarbeitung der zugehoerigen Wikipedia-Seite helfen kann. Letzten Herbst hatte Weichert beispielsweise mal eben den ueberwiegenden Teil des anwesenden Publikums in der Boell-Stiftung als „dumm“ bezeichnet, weil sie Google benutzen, und nun will er Kraft seines Datenschuetzeramtes schleswig-holsteinische Firmen ins Visier nehmen, wenn sie Facebook-„like“-Buttons verwenden.

Wenn man sich in die weigertsche Logik einmal eindenkt, ist das auch gar nicht mal so bescheuert, wie es im ersten Moment klingt. Trotz vielfaeltiger Kritik aus dem gewohnt gut funktionierenden Empoerungskombinat gibt es demnach auch einige unterstuetzende Kommentare zu diesem Schritt, und insgesamt scheint es, als seien alle Reaktionen recht gut vorhersehbar gewesen. Selbst der Jarvis schreibt in so vorhersehbarer Tonalitaet und Schlagrichtung, dass man mittlerweile versucht ist, saemtliche Internetdebatten zukuenftig doch einfach von rudimentaeren KIs ausfechten zu lassen, damit man die Zeit sinnvoller am Baggersee verbringen kann, wozu man eigentlich nur noch saemtliche dort umliegenden Mobilfunkmasten faellen muesste.

Die gesamte Datenschutzdebatte um die Geschichte ist mir gerade ziemlich Wurscht (was im spaeteren Verlauf fuer Veraegerung sorgen sollte), vielmehr war da ein kleines Detail, das mich zum Nachdenken brachte. Es schrob Jarvis folgendermassen:

“Google’s only interest is to earn money,” he said, as if shocked. That theme continues in his Facebook attack, where he complains that the company is worth more than $50 billion. No, he’s not from the Communist part.

„Googles einziges Ziel ist es, Geld zu verdienen.“

Es ist irgendwie seltsam, das so stehen zu sehen, weil es eine eigene Wahrnehmungsverzerrung aufdeckt. Natuerlich ist es das Ziel Googles (und auch Facebooks), ordentlich Reibach zu machen — das sind schliesslich profitorientierte Unternehmen, innerhalb eines kapitalistischen Marktes — aber das zu schreiben wirkt fuer mich aehnlich, als wuerde mein fuenfjaehriges Selbst auf einen Zettel krakeln, dass es das Christkind nicht gibt. Wir wussten das alle irgendwie, aber es macht aus golden und rot glitzernden Weihnachtsbaeumen einfach nur bedampfte Kunststoffstreifen und in China geblasene Glaskugeln, und natuerlich hat die Mama die Glocke gelaeutet, und keine anthropomorphe Jahresendfluegelfigur.

(Ich fange ausserdem an, Google und Facebook mit Weihnachten zu vergleichen. Ich muss Weichert mal fragen, was er so gegen seine Wahnvorstellungen nimmt und ob ich etwas abhaben kann.)

Worauf ich hinaus will: Abgesehen von der gesamten Datenschutzdebatte und was man in diesem Zusammenhang anstellen kann, fehlt mir ein wesentlicher Punkt in der Diskussion, der mir seit der Einfuehrung von Google Plus und allerspaetestens seit den nerd-typischen Profilloeschungsamoklaeufen ebenda irgendwo am Hinterkopf nagt (oben, eher links am Rand).

Erstens.

Anfangs war das alles fuer mich eher ein Usability-Problem: Wohin soll ich eigentlich den Mist giessen, der staendig durch meinen Kopf wabert? Zur grossen Erleichterung einer grossen Menge an Bahnfahrern gibt es ja mittlerweile das Internet, so dass ich das nicht mehr zufaelligen Nebensitzern erzaehlen muss — allein, welcher Kanal ist der beste? Facebook? Google Plus? Eigenes Blog? Youtube? Twitter?

Ja, solche Fragen treiben mich um, und deswegen habe ich mir zur weiteren Verkomplizierung erst einmal eine Soup angelegt. Noch ein Kanal mehr. Prima, du Pfeife.

Eine Variante ist ja, einfach alles _ueberall_ abzuladen: Kurze Gedankenflatulenzen passen optimal auf Twitter, der Rest kommt ins eigene Blog und wird dann in alle sozialen Netzwerke gekuebelt, die nicht schon von vorneherein meine Seite blocken. Sowas nervt dann erfolgreich all diejenigen, die einem auf mehreren Netzwerken folgen, wodurch sich dann der virtuelle Bekanntenkreis solange verkleinert, bis man mit allen Social-Media-Beratern alleine ist.

Die naechste logische Konsequenz waere also ein Meta-Netzwerk: Eine Seite, auf der ich mich einloggen kann, und auf der alles zusammengefuehrt wird, was ich irgendwie auf welchem Datensilo auch immer sehen kann. XY ist online, und ich kann mit XY Instant Messaging betreiben — egal, ob XY nun auf ihrer Seite den Facebook-Chat, OTR oder Brieftauben verwendet. Kommentare auf einen meiner Beitraege werden aggregiert angezeigt — egal ob sie nun in Google Plus, als Twitter-Reply oder als Blogkommentar aufgelaufen sind.

Also habe ich Google Scholar angeworfen und nach Papers ueber dezentrale soziale Netzwerke gesucht. Und wurde von einer Flut an Papers ueber Privacy in Social Networks erschlagen. Verdammte Privacy-Forscher. Es gab aber auch Lichtblicke — ich bin momentan so etwa 10% durch einen dicken Stapel mehr oder weniger aktueller Papers und habe einen Wust an Notizen gesammelt, deren Bedeutung ich zum Teil sogar noch verstehe.

Aber.

Zweitens.

Es gibt einen wesentlichen Punkt, der vermutlich zum Grossteil dafuer verantwortlich ist, dass heute beispielsweise immer noch kaum jemand Mails verschluesselt. Oder der Oma ein GNU/Linux auf ihrem Surfrechner installiert (Ubuntu hat hier einiges geaendert, aber trotzdem). Es ist immer wieder dasselbe, sobald man ein fesches neues Projekt entdeckt, das technisch (und wissenschaftlich) sehr sexy ist: Man kann getrost diverse Kisten Bier darauf wetten, dass das UI grottig sein wird. Grausig. Abschreckend.

Das faengt mit simplen Dingen an. Ich kann in Sekunden ein Bild vom iPhone nach Twitter kuebeln. Oder nach Facebook. Mit Beschreibung, zack, fertig. Vielleicht habe ich einfach nicht den richtigen Client dafuer, aber wenn ich dieselbe Nummer mit meinem Blog veranstalten will, habe ich auf Facebook schon droelf Likes und acht Kommentare, bis das Bild ueberhaupt mal (im falschen Format) auf dem Blog gelandet ist. Und nach Facebook und Google Plus muss ich es dann haendisch verlinken, weil… ach… lassen wir das halt. So etwas nervt.

Mit den Facebook-Alternativen ist es nicht anders. In einigen Papers wird FOAF als Modellbeispiel fuer dezentrale Netze herangezogen. Auf dem cccamp 2011 gab es einen Workshop dazu, und schon die Anleitung zeigt, dass wir auf eine Akzeptanz in der breiten Masse ebenso hoffen duerfen wie auf ein Bekenntnis der CSU zu freiem Internet und einem bedingungslosen Grundeinkommen.

Ich werde jetzt erst einmal den Stapel Papers zu Ende lesen. Egal, was da aber drinsteht, und egal, was in den naechsten Jahren (nicht nur) zu unabhaengigen Social Networks kommen wird: Die Akzeptanz hierfuer steht und faellt mit der User Experience. Man sieht, wie wichtig mir das ist, wenn ich tatsaechlich „User Experience“ schreibe.

Wir schliessen mit den Worten von Stephan Urbach ueber Software fuer Aktivisten. Gut, dass er beschlossen hat, bei uns zu bleiben.

First, please make good UIs. Make them that anyone can use the tool. You will not believe, how many people out there would use your great software if it was usable. Please remember, that not everyone outside who is on the ground is in the position to have the knowledge on how their machines work and how they get configured proper. Please do not create security problems because of a shitty UI. There might be a great algorithm but if most of the targeted user base is not able to use it the goal is not reached. […]

Make good error messages that the users understand. Yeah, for you might a big NULL be enough but for the users it is not. Catch exceptions and translate them that normal people understand. It is not a problem if an error occurs, but it needs to be understandable.
Please, when you do the UI – do it like the last Hello Kitty App – without Hello Kitty. Do not write „Activists Messaging System“ on it. Use Nyancat in it if appropiate. Make it hipsterglitter without hipsters and glitter. You get the point. […]
Conclusion: Be awesome. Make it easy. Test. Crowdsource. Review. Make it more secure. Test. Be still awesome. Thank you.

„The Computer Girls“

Ein netter Artikel im Blog von Fog Creek Software beschreibt die „typischen“ Programmierer-Geschlechterrollen… der 1960er, inklusive eines Scans einer damaligen Cosmopolitan:

Now have come the big, dazzling computers—and a whole new kind of work for women: programming. Telling the miracle machines what to do and how to do it. […]
And if it doesn’t sound like woman’s work—well, it just is.

Schoen zu lesen, auch die weitere Entwicklung ab 1984, in deren Zug immer weniger Frauen Informatik attraktiv zu finden schienen — vermutlich nicht zuletzt dem Bild des einsamen, sozial inadaequaten Nerds vor dem Rechner geschuldet.

Der Trend scheint sich aber wieder umzukehren: In Harvard habe sich die Quote von Informatikabsolventinnen von 13% auf 25% beinahe verdoppelt (bis zu den 37% von 1984 noch ein Stueck hin), und persoenlich habe ich den Eindruck, dass die Quote vor allem in der Medieninformatik noch steiler steigt.

Der Artikel ist jedenfalls lesenswert, nicht zuletzt wegen des Interviews mit einer der Fog-Creek-eigenen Informatikerinnen:

My friends who are girls ask for help to fix their computers normally because it’s acceptable for them not to be able to do it. They don’t realize that I’m just going to google the answer anyway! They think I already know the answer! Whereas I think most guys would be embarrassed to admit that they can’t fix their computers.

(via @newsycombinator/@fasel)

Leseempfehlung (3)

Ganz klassisches Medieninformatikthema zuerst: Welche Navigationsloesung fuer Touchgeraete (lies momentan: iPad) ist die bessere — scrollen oder durch Tabs rotieren? Es stellt sich heraus, dass diese Frage uralt ist und bereits 1987 behandelt wurde. Mehr dazu bei den informationarchitects. (via @gerritvanaaken)

Schoenes Zitat:

It’s a touch screen device. Touch SCREEN device. The fact that you touch it doesn’t mean that it’s like print. As a matter of fact it’s lightyears away from print.

A propos Print. Christian Jakubetz springt auf den Zug mit den gerade so beliebten Thesen auf und postuliert zehn Thesen zur Zukunft der Zeitung.

TLDR: Es sieht duester aus.

Stellen, an denen ich ganz besonders heftig genickt habe:

  • Die Wochenzeitung wird die neue Tageszeitung – und nicht umgekehrt
  • Die Tageszeitungen sparen sich zu Tode
  • Die Tageszeitungen vergreisen in den Redaktionen
  • Als nächstes wandert der Lokaljournalismus ins Netz ab

Wer dagegenhalten will, darf gerne bei meiner mittlerweile zwei Jahre alten Print-Wette mitmachen: 500 EUR Einsatz fuer Studierende, ueber den Einsatz von Verdienern muessten wir uns dann nochmal unterhalten.

    Und wie zur Unterstreichung der These vom abwandernden Lokaljournalismus hier ein Stueck aus der RZ ueber den neulich hier schon beschriebenen @tilman36, der mal eben mit Laptop, Webcam und UMTS zwei Stunden lang sein eigenes Sendestudio aufmachte: „Mobiles Kamera-Einsatzkommando“

    Manche setzen weiterhin auf Print und die Bedeutung der gedruckten Zeitung fuer die Bildung. Die SWP startete gestern die Serie „Wir lesen“, auf deren Projektseite mit Video ich einfach mal kommentar- und wertungslos verlinken moechte.

    Anwendungsfach bestanden!

    Jetzt kann der Backburner wieder geleert werden: Gestern Mittag wurde endlich das Anwendungsfach weggeprueft, und damit ein Jahr diretto zumindest aus Sicht der Uni beendet. Mit uns haben auch die drei anderen Teams vorgestellt, und ich war dann doch recht beeindruckt, was in dieser Runde des Anwendungsfaches so alles zustande gekommen ist.

    Kurze Videos der Projekte — und natuerlich auch unseres — nach dem Sprung.

    Weiterlesen

    GPS und Java: NMEA-Daten auswerten (1)

    Bild: GPS Recorder von andyp_uk, cc-by-nc

    Irgendwann kommt die Zeit im Leben jedes Menschen, an der er GPS-Daten automatisiert verarbeiten will. Vertraut mir, was das angeht. Das passiert jedem.

    Unter C++ ist sowas sicher viel simpler und toller. Ich hatte aber die fixe Idee, das unter Java zu machen, weil das ja gewohntes und damit vermeintlich sicheres Terrain fuer mich sei. Das lassen wir jetzt mal so dahingestellt.

    Schritt 1: Daten holen

    Die Idee, hier java.io verwenden zu wollen, kann man sich ziemlich in die Haare schmieren. Gleich gnu.io.rxtx zu verwenden, spart Aerger. Weil wir NMEA-Daten ueber die serielle Schnittstelle haben wollen, setzen wir die Parameter entsprechend: setSerialPortParams(4800, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

    Hier kommt jetzt alles moegliche NMEA-Zeug heraus, das man theoretisch direkt parsen koennte. Alternativ kann man mit der Java NMEA API gezielt nach den interessanten NMEA-Saetzen lauschen. Kurz deren Doku ueberfliegen lohnt sich auf jeden Fall, da sich auch ein Beispiel findet, wie man ein GPS-Geraet ueber die serielle Schnittstelle einliest.

    PS: Viele GPS-Maeuse kommen heute mit einem integrierten Serial-to-USB-Konverter daher, damit man sie per USB anschliessen kann. Sollte RxTx unter Linux zwar einen USB-Port (a la /dev/ttyUSB0) erkennen, darauf aber nicht zugreifen koennen („No such port“), helfen unter Umstaenden chown unsinn! chmod 666 /dev/ttyUSB0 und chgrp tty /dev/ttyUSB0 weiter.

    Schritt 2: Was brauchen wir da eigentlich?

    Wenn man sich mal direkt ansieht, was da ueber die Konsole rauscht, dann ist das ziemlich viel. Beispiel:

    $GPRMC,101836.000,A,4825.1856,N,00956.8032,E,0.23,226.38,230710,,*07
    $GPVTG,226.38,T,,M,0.23,N,0.4,K*68
    $GPGGA,101837.000,4825.1857,N,00956.8023,E,1,04,1.4,567.4,M,48.0,M,,0000*5E
    $GPGSA,A,3,17,05,08,18,,,,,,,,,8.6,1.4,8.5*36
    $GPRMC,101837.000,A,4825.1857,N,00956.8023,E,0.57,292.18,230710,,*09
    

    Das sieht auf den ersten Blick wenig einladend aus, im Endeffekt aber ziemlich simpel. „$GP“ bedeutet, dass es sich um GPS-Daten handelt. „RMC“, „VTG“, „GGA“, „GSA“ und Co. sind verschiedene Satztypen, die hierzu gehoeren. RMC muss jeder GPS-Empfaenger koennen, idealerweise nehmen wir uns aber die GGA-Saetze her, weil die in einem Satz alle fuer uns wichtigen Informationen bereitstellen.

    Durch Kommas getrennt finden sich hier:

    • Uhrzeit in UTC
    • Breite und Bezeichner N oder S fuer die Breite
    • Laenge und Bezeichner W oder E fuer die Laenge
    • Qualität der Messung (0 == ungueltig, 1 == GPS, 2 == DGPS)
    • Anzahl der gemessenen Satelliten
    • Horizontal Dilution Of Precision (mehr dazu im naechsten Post)
    • Hoehe ueber Meer mit Einheit
    • Hoehe ueber Geoid minus Hoehe ueber Ellipsoid, mit Einheit

    …gefolgt zum Schluss von einer Pruefsumme, die ich aber nie irgendwie beruecksichtigt habe. Bis auf das aktuelle Datum ist hier also alles vorhanden, was man braucht, es muss nur noch die Zeichenkette aufgetrennt und die WGS84-Koordinate in ein Format umgerechnet werden, mit dem man weiterarbeiten kann.

    Schritt 3: Koordinaten umrechnen

    Umrechnen? Ja. In den NMEA-Saetzen steht naemlich folgendes:

    4825.1857,N,00956.8023,E

    Das sind also 48° 25.1857′ noerdlicher Breite und 9° 56.8023′ oestlicher Laenge. In Minuten wollen wir aber nicht rechnen, wir wollen zwei glatte Dezimalbrueche — in diesem Fall etwa 48.4197616 und 9.946705. Dazu muessen wir aber erst einmal unsere NMEA-Saetze in ihre Bestandteile zerlegen.

    In einigen Tutorials, die ich gefunden hatte, war hier immer vom StringTokenizer die Rede, um die Zeichenkette zu zerlegen. Das ist aber nicht immer eine gute Idee, da der NMEA-Output direkt nach dem GPS-Start oder beim Fix-Verlust (z.B. in einem Tunnel) so aussehen kann:

    $GPGGA,103927.819,,,,,0,00,,,M,0.0,M,,0000*58

    Schoener geht das alles mit der split()-Methode, um die Zeichenkette an den Kommas zu trennen:

    String sentence_parts[] = e.getContent().split(",");

    Nun ist klar definiert, an welcher Stelle was zu erwarten ist. Sollten wir keinen Fix haben, koennen wir das ganz einfach herausfinden:

    if (sentence_parts[6].equals("0")) {
        System.err.println("No fix!");
        // TODO: Handle this further, if needed
     }

    Gehen wir aber mal davon aus, dass wir einen Fix haben. Dann hilft uns der Algorithmus aus dem oben genannten Tutorial weiter, mit dem wir die Minutenangabe der NMEA-Koordinate in den Dezimalbruch nach dem Komma der Gradangabe umwandeln koennen:

    float lat_val = convertLat(sentence_parts[2], sentence_parts[3]);
    float lon_val = convertLon(sentence_parts[4], sentence_parts[5]);
    
    public float convertLat (String raw_latitude, String lat_direction) {
    
      String lat_deg = raw_latitude.substring(0, 2);
      String lat_min1 = raw_latitude.substring(2, 4);
      String lat_min2 = raw_latitude.substring(5);
      String lat_min3 = "0." + lat_min1 + lat_min2;
      float lat_dec = Float.parseFloat(lat_min3)/.6f;
      float lat_val = Float.parseFloat(lat_deg) + lat_dec;
    
     // Direction of latitude. North is positive, south negative
      if (lat_direction.equals("N")) {
        // no correction needed
      } else {
        lat_val = lat_val * -1;
      }
     return lat_val;
     }
    
    public float convertLon(String raw_longitude, String lon_direction) {
     // Conversion of longitude to floating point values
    
      String lon_deg = raw_longitude.substring(0, 3);
      String lon_min1 = raw_longitude.substring(3, 5);
      String lon_min2 = raw_longitude.substring(6);
      String lon_min3 = "0." + lon_min1 + lon_min2;
      float lon_dec = Float.parseFloat(lon_min3)/.6f;
      float lon_val = Float.parseFloat(lon_deg) + lon_dec;
    
      //direction of longitude, east is positive
      if (lon_direction.equals("E")) {
        // No correction needed
      } else {
        lon_val = lon_val * -1;
      }
     return lon_val;
     }

    Jetzt haben wir unseren Standort. Naja, eigentlich nicht, sondern nur eine Annaeherung unserer Position. Hier kommt noch eine bestimmte Abweichung ins Spiel, die in Metern auszudruecken gar nicht so leicht ist. Wie man damit umgehen kann und wie das generell mit Genauigkeit, Praezision und Verfahren wie DGPS und SBAS geht, schreibe ich dann demnaechst mal.

    Nachtrag: Waehrend ich das hier schreibe, faellt mir auf, dass ich bei den Vorzeichen automatisch das vom UTM-Koordinatensystem her bekannte Nordwert-Ostwert-Paradigma verwendet habe — bin mir aber aktuell nicht sicher, ob bei WGS84-Koordinaten nicht doch der Westwert ein positives Vorzeichen hat.

    Nach-Nachtrag: Gpsvisualizer hat meine Annahme bestaetigt. Puh 🙂