Those civil war monuments in the US

I once saw a video suggesting that the US should choose Canada as their next president. They would solve the race-problem. As soon as they figured out why there still was a race-problem. It’s one of those things that are pretty hard to understand for europeans. And apparently for canadians as well.

Anyway, there is a problem, and lately it’s been manifesting in protests against monuments celebrating confederate war-“heroes”. Thats another thing that is difficult to understand from across the atlantic. Those monuments must certainly have been standing there for a very long time. After all, the war ended in 1865. They may be celebrating the losers, but seriously, what’s the problem? Well… Actually there is a problem. Most of the monuments were not erected to commemorate fallen soldiers just after the war. They were erected to show those n******, who was still in charge when they started to organize for rights. And again when those rights were granted (to some degree). There’s a lot more information in this report. And suddenly even europeans begin to understand what all the fuss is about. But still. Seriously? Get over it, you lost, be nice, and treat people like, you know, Jesus said you should.

Okay – that was the introduction. And now for the data. Somewhere in there, there is an interesting datavisualization. The data is here:

https://data.world/datadanlarson/confederatemonument/workspace/file?filename=CivilWarMamorials.csv

What do I want to do with it? I want an animated GIF. Each frame in that gif should represent a year, and show a map of the US, with all the monuments erected up to and including that year. Preferably it should be noticable what monuments where erected that year. A graph showing the development of the number of monuments would be nice as well.

Okay, lets get coding. The data comes from data.world, and they have their own R-package:

  devtools::install_github("datadotworld/data.world-r", build_vignettes = TRUE, force = TRUE)

In order to get to the data, You will need a token. There is excellent help to get at data.world.

data.world::set_config(data.world::save_config(auth_token = "redacted"))

It is a horrible token. Anyway, lets plod on. Load their library, and get the data

library(data.world)
dataset_key <- "https://data.world/datadanlarson/confederatemonument"
tables_qry <- data.world::qry_sql("SELECT * FROM Tables")
tables_df <- data.world::query(tables_qry, dataset = dataset_key)
sample_qry <- data.world::qry_sql(sprintf("SELECT * FROM `%s`", tables_df$tableName[[1]]))
sample_df <- data.world::query(sample_qry, dataset = dataset_key)

This is a simple copy-paste from the examples at data.world. The net result is, that we have all the data in the dataframe sample_df.

We are interested in the year a monument was erected. Not all years are known. And this is of course a serious flaw in the following visualization. Patterns may not be what they appear, when approx. half the data is missing.

Anyway, lets get rid of the rows with missing data:

newdata <- sample_df[complete.cases(sample_df),]

complete.cases returns a logical vector. True if the row is free from NAs, eg. is complete, False if there is an NA in it. newdata is now a dataframe with only the complete cases.

We need coordinates. Google is our friend, however, I’m not going to run that geocoding again. Google allows 2500 calls to their API every day from a given IP-number. It is easy to run out of calls.

library(ggmap)
newerdata <- data.frame(city=character(), state = character(), year = numeric(), status = character(), lat = numeric(), lon = numeric(), stringsAsFactors = FALSE)
for (row in 1:nrow(newdata)){
result <- geocode(paste(newdata[row,2]$city, newdata[row,1]$state, sep=", "), output="latlon", source="google")

    newerdata[nrow(newerdata) + 1,] = c(newdata[row,2]$city,newdata[row,1]$state, as.numeric(newdata[row,5]$year), newdata[row,6]$civilwarstatus, result$lat, result$lon)
  
}
save(newerdata, file="newestdata.rda")

What happens? We call ggmap, which provides the function geocode. A new dataframe, newerdata, is defined. For each row in newdata, I call geogode on the city and state, separated with a “,”, and saves the result in “result”. And then I add the rows I want to the newerdata dataframe. There is probably a better way to do that. But it works. Here there is another thing that should probably be handled. Sometimes Google is not able to determine exactly what location we give it. There may be more than one place in a US state with the same name. I’m just taking the first result google gives me. A bit sloppy, I know. make some plots.

Finally I save the data. Now we should be ready to We are going to need some libraries for that:

library(grid)
library(gganimate)
library(animation)
library(ggplot2)
require(cowplot)

I’ll just make absolutely sure that the data is in the form I need it to be:

load("newestdata.rda")
newestdata <- newestdata[complete.cases(newestdata),]
newestdata <- na.omit(newestdata)
newestdata$year <- as.numeric(newestdata$year)
newestdata$lat <- as.numeric(newestdata$lat)
newestdata$lon <- as.numeric(newestdata$lon)

The coordinates and the year should be numeric. Any rows with missing values should be gone forever.

I get a map to plot on:

us <- get_map("USA", zoom = 4)

And, lets make the first plot:

g <-ggmap(us) +
  geom_point(aes(x=lon, y=lat), data=newestdata, color="red")
g

Theres a lot of red there. I would like to make an animation. The standard way to do it here, or at least the way I usually do it, would be to define a function, that plots what I want to plot as a function of the year. Like this:

singleyear <- function(ye){
  g <-ggmap(us) +
  geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year<(ye)),], color="red")
 g
}

Now, when I make this function call, I should get a map with all the monuments erected before 1890:

singleyear(1890)

I’m missing the monuments erected in 1890. That is because I would like those to be a different color. Lets add to the function, and call it again:

 

 

 

singleyear <- function(ye){
  g <-ggmap(us) +
  geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year<ye),], color="red")+
  geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year==ye),], color="blue")
 g
}
singleyear(1890)

Now, when I plot the map for a given year, all monuments from that year will appear as blue. And for the next year they’ll turn red.

 

 

Lets back up a bit here.

What I’m doing is this: I take the map I retrieved from Google, and plots it with the ggmap function. Then I add points with the geom_point function. I tell the function that the data is “newestdata”, and that the points should be placed at position x,y where x is the longitude, and y the latitude. The color should be red. I am however also telling that the data should be the part of newestdata, where year is smaller than the ye-value I provide to the function. In the next line, I add the same point, just for the part of the data where year is equal to the ye-value i provide to the function. And that the color should be blue.

What I am going to do later, is to call this function for all years from 1860 to 2017, and show those plots one after another. We will get at small movie, where new monuments turn up as blue spots. And then turn red in the next frame.

Everything becomes very red. One way to do something about this, would be to make the dots transparent. Let them fade out. When the monument is just erected, let the dot be blue. The year after, let it be a transparent red dot, the year after that, make it more transparent. Areas with a lot of monuments will still be pretty red, but the new monuments will be more visible. We’ll get at sort of heatmap, where the very red areas are places with at lot of monuments, and the not so red areas have fewer.

I’ll need to have a maximum and a minimum for the transparency. Defined as af function of the year I am plotting, and the year a monument was erected. I’m gonna add it to the dataframe before I plot it. This is the line:

maxp <- 0.8
minp <- 0.3
newestdata$alpha <- (maxp - minp)/(ye-1861)*(as.numeric(newestdata$year)-ye)+maxp

A new column, alpha, is added to the dataframe, and the difference between the year I am plotting, and the year of the row is normalised to the range 0.3 to 0.8. The point begins as blue, turns red with a transparency of 0.8, and will fade to 0.3.

I’m not sure the range is perfect. I’m gonna go with it for now.

Lets add it to the function:

maxp <- 0.8
minp <- 0.3
singleyear <- function(ye){
  newestdata$alpha <- (maxp - minp)/(ye-1861)*(as.numeric(newestdata$year)-ye)+maxp
  g <-ggmap(us) +
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year<ye),], alpha=newestdata[which(newestdata$year<ye),]$alpha, color="red")+ 
  geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year==ye),], alpha=1, color="blue")
 g
}
singleyear(1890)

 

What I also added, was this: “alpha=newestdata[which(newestdata$year<(aar)),]$alpha”. Alpha is the transparency. So each point is plottet with the transparency I calculated.

What next? Lets adjust the plot a bit:

maxp <- 0.8
minp <- 0.3
singleyear <- function(ye){
  newestdata$alpha <- (maxp - minp)/(ye-1861)*(as.numeric(newestdata$year)-ye)+maxp
  g <-ggmap(us) +
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year<ye),], alpha=newestdata[which(newestdata$year<ye),]$alpha, color="red")+ 
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year==ye),], alpha=1, color="blue") +
    theme(plot.title=element_text(hjust=0)) +
    theme(axis.ticks = element_blank(),
        axis.text = element_blank(),
        panel.border = element_blank()) +
    labs(title="Confederate memorials", subtitle=ye, x=" ", y="")
 g
}
singleyear(1890)

 

Labels are left aligned (hjust=0), tickmarks and text is removed (all the element_blank parts). And a title “Confederate memorials” is added, with a subtitle indicating the year we have reached in the plot.

Nice. What more? The interesting part, at least I think it is interesting, is the fact that the number of these memorials increase at certain times. That can be seen on the map. But a line-plot would probably make it more visible. It would also be nice to have it side-by-side with the map. How to do that?

To begin with, I’ll need a set of data with the cumulative count of monuments:

linedata <- as.data.frame(table(newestdata$year), stringsAsFactors = FALSE)

colnames(linedata) <- c("year", "cumsum")
linedata$year <- as.numeric(linedata$year)
linedata$cumsum <- cumsum(linedata$cumsum)

I make a new dataframe, linedata. The content is table(newestdata$year). The table function summarizes the data in newestdata. It gives me a table with all the years, and the number those years occur. Eg. that there are 7 occurences of the year 1870. That corresponds to 7 monuments erected in 1870. I save that as a dataframe. Then I change the names of the colums, and make sure that the years are saved as numeric. And then I call cumsum. That is a function that calculates the cumulative sum. Ie in 1861 2 monuments where erected. None where erected before that. The cumulative sum of all monuments until 1861 was 2. In 1862 3 monuments were erected. The cumulative sum for 1862 is 5. The sum of the 3 monuments erected that year, and all the monuments erected before that.

That in itself is an interesting plot:

ye = 2017
h <- ggplot(linedata[which(linedata$year<=ye),]) +
  geom_line(aes(x=year, y=cumsum))
h

 

Something happens in 1910 and again in 1950. Or somewhere close to those years. At least that is where the graph changes shape.

Lets adjust it a bit:

ye=2017
h <- ggplot(linedata[which(linedata$year<=ye),]) +
  geom_line(aes(x=year, y=cumsum))+
  xlim(1860,2017) +
  ylim(0,850) +
  ylab("Number of confederate memorials") +
  xlab("")
h

Nothing fancy, just freezing the axes, adding a label for the y-axis, and removing it from the x-axis.

Now I can add it to the original plot. I loaded the library cowplot earlier. That gives us the function plot_grid.

 

i <- plot_grid(g,h,align='h')
i

I have two plots, g and h, and combine them in a newplot, horizontally (thats the h in align), to a new plot i. And then I plot i.

 

 

Lets add that to the function:

singleyear <- function(ye){
  newestdata$alpha <- (maxp - minp)/(ye-1861)*(as.numeric(newestdata$year)-ye)+maxp
  g <-ggmap(us) +
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year<ye),], alpha=newestdata[which(newestdata$year<ye),]$alpha, color="red")+ 
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year==ye),], alpha=1, color="blue") +
    theme(plot.title=element_text(hjust=0)) +
    theme(axis.ticks = element_blank(),
        axis.text = element_blank(),
        panel.border = element_blank()) +
    labs(title="Confederate memorials", subtitle=ye, x=" ", y="")
  h <- ggplot(linedata[which(linedata$year<=ye),]) +
    geom_line(aes(x=year, y=cumsum))+
    xlim(1860,2017) +
    ylim(0,850) +
    ylab("Number of confederate memorials") +
    xlab("")
  i <- plot_grid(g,h,align='h')
  i
}
singleyear(1890)

Now I’m getting there! Almost ready for the animation. I would like some annotation on the h-plot. A couple of arrows. And I would like them to show up in the animation. As in, from year 1910 there should be text at a certain place. But not before. It’s not that difficult.

If I add this:

if(ye>1908){

h <- h + annotate(“text”, x =1980, y = 200, label=“NAACP established”) + geom_segment(aes(x=1950, y = 200, xend=1909, yend = 200), size=1, arrow=arrow(length=unit(0.5, “cm”))) }

to the function, every plot, for a year after 1908, will have an annotation on the h-plot, at position 1980,200, with the text “NAACP established”. The next line, geom_segment, will add an arrow, with a size defined by the size and length parameters, beginning at 1950,200 and ending at 1909,200.

It took quite a bit of time to fiddle with those positions!

That is not the only annotation I want. So the complete function is as follows:

singleyear <- function(ye){
  newestdata$alpha <- (maxp - minp)/(ye-1861)*(as.numeric(newestdata$year)-ye)+maxp
  g <-ggmap(us) +
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year<ye),], alpha=newestdata[which(newestdata$year<ye),]$alpha, color="red")+ 
    geom_point(aes(x=lon, y=lat), data=newestdata[which(newestdata$year==ye),], alpha=1, color="blue") +
    theme(plot.title=element_text(hjust=0)) +
    theme(axis.ticks = element_blank(),
        axis.text = element_blank(),
        panel.border = element_blank()) +
    labs(title="Confederate memorials", subtitle=ye, x=" ", y="")
  h <- ggplot(linedata[which(linedata$year<=ye),]) +
    geom_line(aes(x=year, y=cumsum))+
    xlim(1860,2017) +
    ylim(0,850) +
    ylab("Number of confederate memorials") +
    xlab("")
  
  if(ye>1908){
    h <- h + annotate("text", x =1980, y = 200, label="NAACP established") +
       geom_segment(aes(x=1950, y = 200, xend=1909, yend = 200), size=1, arrow=arrow(length=unit(0.5, "cm")))
  }

  if(ye>1910){
    h <- h + annotate("text", x = 1870, y = 500, label="Coincidence?") +
      geom_segment(aes(x=1870, y=490, xend=1905, yend=240), size=1, arrow=arrow(length=unit(0.5, "cm")))
  }

  if(ye>1955){
    h <- h + annotate("text", x =1960, y = 400, label="Beginning of civil rights movement") +
      geom_segment(aes(x=1950, y = 450, xend=1955, yend = 640), size=1, arrow=arrow(length=unit(0.5, "cm")))
  }

  if(ye>1960){
    h <- h + annotate("text", x= 1866, y=515, label="Another") +
      geom_segment(aes(x=1882, y=500, xend=1955, yend=680), size=1, arrow=arrow(length=unit(0.5, "cm")))
  }

  i <- plot_grid(g,h,align='h')
  print(i)
}
singleyear(2017)
## Warning: Removed 1 rows containing missing values (geom_point).

OK. It looks like hell. But! In just a moment, it will look. Well, not exactly perfect, but at least much better.

The way to animate is this: Define a function that gives you the frames you want, as a function of an iterable. That’s already done. Call this:

saveGIF({
  for (ye in 1860:2017){
   singleyear(ye)
  }
}
, interval=0.3, ani.width=1280, ani.height=720)

Enjoy. Oh, and note, that it will crash if you try to animate it a notebook.

Hvor blev jeg af?

Tja. Godt spørgsmål. Der har været meget stille her i et stykke tid.

Det har der været før. Det bliver der sikkert igen. Denne gang har det nok været som reaktion på ændringer på min arbejdsplads. Der jo nok, hvis vi virkelig skal kigge dybt i sjælen, udløste noget der kunne ligne en depression. Ikke noget alvorligt. Afgjort ikke nok til at udløse piller. Men bare en længere periode med – “Fuck. Var det det?” tanker. Og ikke specielt systematiske overvejelser om hvad katten jeg så skulle bruge tiden på.

Det er jeg så nogenlunde ude af. Der begynder at være fod på tingene på hjemmefronten. Arbejdet er, nåja, arbejde. Det virker ikke så håbløst som det har gjort. Og jeg er nok ved at vænne mig til, at identitet er noget der skal findes andre steder end på jobbet. Ligesom anerkendelse og respekt.

Så med lidt held kommer der til at ske lidt mere her. Der er nørdeprojekter undervejs, faktisk godt i gang. Der er køkkenteknikker der skal afprøves. Der er politiske kæpheste der skal luftes. Og så er det fredag, og lige om lidt skal jeg i biografen og se præsentationen af noget et af de projekter jeg har gang i har kastet af sig.

Der findes ikke problemer

Kun udfordringer.

Det har jeg i hvert fald ladet mig fortælle. Og det handler jo om at man skal italesætte tingene på den rigtige måde. Problemer er negativt ladede. Måske endda så meget, at de ikke kan løses. Så det ord må vi ikke bruge. I stedet skal vi bruge ordet udfordring, der ikke er negativt ladet. Ordet udfordring, i stedet for udfordring, skal lissom signalere, at det er noget vi løser. Vi skal bare tage os sammen, så viser det sig at udfordringen slet ikke er en udfordring, men i stedet en udfordring.

Jeg tror bare der er en udfordring med at sige udfordring i stedet for udfordring. Udfordringen består i at vi gør sproget upræcist. Vi skaber en udfordring, når vi mener at skulle bruge et andet ord end udfordring, fordi udfordring er negativt. Du skal ikke komme med udfordringer, du skal komme med løsninger. Ja, selvfølgelig, men hvis jeg havde løsningen på den her udfordring, så ville jeg ikke have behov for at komme med den til dig. Så var det jo ikke en udfordring længere. Det kunne være at der så var en udfordring ved at gennemføre løsningen på udfordringen. Men det ville jo være en anden udfordring.

Udfordringen ved ikke at måtte kalde udfordringer for udfordringer er dobbelt.

Dels er der udfordringen ved at skulle kalde udfordringer for udfordringer i stedet for udfordringer. Det mudrer sproget. Hvis du har læst hertil, vil du vide hvad jeg mener. Det er faktisk udfordrende at skrive udfordring i stedet for udfordring hver gang, og det gør sikkert også at man er ret udfordret når man skal læse teksten. Det spænder ben for udfordringsløsningen hvis man ikke må kalde en udfordring for en udfordring. Det fjerner fokus på, at når vi løser denne udfordring, så er det faktisk fordi det er en udfordring, som er negativ, og derfor skal løses. Vi forfladiger udfordringsstillingen, og dermed bliver det også udfordrende at gennemskue hvori udfordringen egentlig består. Er det overhovedet en udfordring? Er vi sikre på at det ikke bare er en udfordring i stedet? Udfordringer er også noget man kan vælge at tage imod. Det ligger i ordet. Men ikke alle udfordringer er så u-udfordringsatiske, at man kan ignorere dem. Nogen udfordringer er så udfordrende, at man bliver nødt til at gøre noget ved dem.

Den anden udfordring er, at en udfordring jo ikke holder op med at være udfordrende, blot fordi vi kalder det for en udfordring i stedet for en udfordring. Det er lidt ligesom oprindeligt neutrale betegnelser for folk med høj koncentration af melanin i huden. De er ikke længere neutrale (altså betegnelserne), de er blevet negativt ladede. Det er de blevet på grund af racisme. Så nu bruger vi et andet ord, der er neutralt. Men racismen er ikke forsvundet, så om lidt er det nye, neutrale, ord lige så negativt ladet som det gamle, oprindeligt neutrale, men nu negative ord. Udfordring er et pænt nyt ord, som vi kan bruge i stedet for det grimme gamle ord, udfordring. Men fordi virkeligheden nu engang er sådan at udfordringer jo sjældent rent faktisk er positive – hvis de var det, var de jo ikke udfordringer, så virker det kun en kort tid. Inden vi ser os om, er udfordringer noget lige så negativt ladet som udfordringer oprindeligt var. Og så begynder vi at tale om muligheder i stedet for udfordringer.

Har du fået konstateret kræft? Det er ikke en udfordring. Det er nu en mulighed. Den skal du bare gribe. Og så bliver sproget endnu mere absurd. Når man ikke må sige udfordring, men skal sige mulighed i stedet for mulighed, så går det helt galt. Muligheder lyder pænt. Pænere end muligheder. Men fordi vi kalder det for en mulighed, er det jo ikke holdt op med at være en mulighed. Muligheden er stadig negativ. Nu er vi blot begyndt at bruge et ord der i endnu højere grad implicerer en valgmulighed. Så når jeg står med en mulighed, det kunne være at der er et vandrør der er sprunget, så skal jeg forsøge at se mulighedsløsninger i den mulighed jeg har fået fordi gulvet sejler. Min underbo har også fået en mulighed, idet der drypper vand ned fra hans loft. Der må han jo bare se det positive i at han nu har fået mulighed for at løse en mulighed.

Der er også den mulighed, at folk der får at vide at de skal sige mulighed i stedet for mulighed, muligvis begynder at føle sig lidt til grin. De betragter det som muligt at muligheder faktisk er muligstiske, og at de ikke bliver mindre negative af at vi siger mulighed i stedet for mulighed. Jeg er ret sikker på at min underbo vil kigge mærkeligt på mig når jeg fortæller ham at han har en mulighed når hans gulvtæppe er blevet vådt fordi jeg har en mulighed med en oversvømmelse i køkkenet. Muligvis er der en mulighed for at folk der bruger ordet mulighed i stedet for bare at kalde tingene ved deres rette navn, bliver lidt til grin. Eller at de ikke længere bliver taget seriøst. Jeg er ikke helt overbevist om at HR-chefen vil betragte det som en mulighed, hvis hans medarbejdere betragter ham med skepsis hver gang han siger mulighed.

Muligvis skal vi i virkeligheden forsøge at skære udfordringerne ind til benet, og erkende at det ikke kan afvises, at der faktisk er tale om et problem. Hive fat i værktøjskassen med redskaber til problemløsning. Og i stedet for bare at italesætte tingene på en måde der er i overensstemmelse med den sidste managementmode, rent faktisk løse problemerne.

 

Hjemmelavet Gin del II. Hvor kommer farven fra?

Jeg fik ikke rigtigt vist et billede af hvordan resultatet så ud i mit opslag om at lave sin egen gin. Lad os bare sige at det ligner en urinprøve.

Nu er gin normalt ikke farvet. Så hvor kommer farven fra? Fra tidligere eksperimenter med pebersnaps – de gentages ikke – ved jeg at peber kan farve ret godt. Men der kunne være tale om andre ting også. Så det måtte prøves.

Jeg skulle lave sous vide cheesecake alligevel, og det skal gøres ved samme temperatur som når der laves gin. Så det var oplagt lige at køre et lille eksperiment. Bare lidt hurtigt, for jeg var kommet lidt sent igang.

Her er forberedelsen. 

Fra venstre mod højre, 2 enebær, 2 peberkorn og 2 allehånde bær. Dertil 50 ml vodka. Det hele i mine små henkogningsglas, låg på, i vand (80 grader, 10 minutter). Det var i hvert fald planen. Noget gik galt med tidtagningen i appen til Anovaen. Så de fik snarere et kvarter end 10 minutter.

Det gør ikke noget. Det jeg er ude efter er at identificere hvilket krydderi der giver farven. Hvis det allehånde farver mere end de andre efter 15 minutter, så gør allehånde det også efter 10 minutter. Det er den relative forskel jeg er ude efter. Ja, der kan være forskelle hvis det egentlige farvestof ligger dybt i bærret, og først trækker ud sent i forløbet. Men det er så korte tidsrum vi har gang i her, at det næppe gør en forskel.

Og hvordan så det så ud? Således: 

Allehånde – stort set ingen farvning. Peber – en smule. Farven kommer helt klart fra enebærrene. Og da der skal ret mange af dem i, er der nok ingen vej uden om at min gin kommer til at ligne en urinprøve.

Hvorfor er gin så ikke farvet? Det er der også nogen mærker der er. Den primære forskel er nok, at det meste gin vi køber, er destilleret gin. Den rå sprit trækker med de urter der tilsættes. Og så destilleres den igen. Smagsstofferne følger med. Og hvis farvestofferne er tilstrækkeligt “tunge” og ikke følger med, ja så er der ikke meget farve på slutresultatet.

Klistermærker

I kender dem godt – i hvert fald hvis I er nørder. De der klistermærker man får i forskellige sammenhænge, til at sætte bag på sin computer.

Det er bare ikke altid man lige kan få dem man har brug for. Men så må man jo selv bestille dem. Så det gjorde jer. Inkscape hjalp med designet. Nemprint.dk hjalp med trykket (mod betaling). Og forleden kom de. Ret godt timet, men det er en anden historie, der ikke hører hjemme i et offentligt rum.

Lidt dyrt (3,42 stykket) men det var fordi jeg kun bestilte 100. OK kvalitet, ikke helt så tykke som de rigtig lækre, men så afgjort et sted jeg kunne finde på at bestille igen.

Det næste projekt

Men nok med en anden tekst. Der er lidt mere relevant. “Trust no one”. Eller måske lidt meta? “Hanlon’s razor”. Så kan folk selv google og gætte. Anyway – det tager lidt tid før jeg bliver færdig med den.

Pan-tilt with Adafruit

I don’t usually post here in english. But I have the feeling that others might find this useful, so.

OK, I was looking for a DVB-T receiver, I would like to pick up transponder signals from passing airplanes. I went to Pimoroni, and found this: Cooooool!

Bought it, waited for it. Got it. How to control it?

Well, it uses two small servomotors. Those take a PWM-signal. And my Raspberry Pi have only one pin that can handle that.

Luckily other people have wanted to play with this. Richard Hirst have written a kernelplugin to Rasbian, that allows us to add servo control. The plugin is called ServoBlast. And I got it on my Raspberry in this manner:

First I installed Git:

sudo apt-get install git

Then I cloned the servoblaster code

git clone git://github.com/richardghirst/PiBits.git

Got into the directory:

cd PiBits/ServoBlaster

Cursed a lot, and finally found my way into the right directory:

cd user

Ran the make commando:

sudo make install

And that was it! I’ll have to talk to my husband if I want to understand what actually happened. But now I was actually able to control the servos. How did I know that? Well, there is a hardware side as well.

The servos requires 5V, and although the Pi have a 5V pin, I ran it from an Arduino. There are two cables on the assembly. One for each motor. The red lead on both is connected to 5V from the Arduino. The browns to ground. And the yellow ones, which is the data-line, to pin 7 and 11 on the Pi. One of the ground pins on the Pi was connected to the Arduino.

And now, all I have to do write this on the commandline:

sudo echo 1=120 -> /dev/servoblaster

And the servo connected to pin 11 will move. Neato.

Heres a litte Python script to control the two servos graphically:

from subprocess import call
from tkinter import *

master = Tk()

def getSlider(event):
a = “echo 1=”+str(SliderV.get())+” > /dev/servoblaster”
b = “echo 0=”+str(SliderH.get())+” > /dev/servoblaster”
call ([a], shell=True)
call ([b], shell=True)
print(SliderH.get())

SliderH = Scale(master, from_=30, to=250, orient=HORIZONTAL, command=getSlider)
SliderV = Scale(master, from_=30, to=250, orient=VERTICAL, command=getSlider)
SliderH.set(0)
SliderH.pack()
SliderV.set(0)
SliderV.pack()

mainloop()

 

Adjust the “from” and “to” numbers to suit your servos.

Done!

 

En SEP-felt generator

Nåmmen jeg har været leder i tre år. Det er jeg ikke længere. Mit lille bibliotek skulle flyttes sammen med et andet.

Det har været en lang proces, i skrivende stund har det været i støbeskeen i over et år. Og det er ikke faldet på plads endnu. Det har også været en hård proces. Noget af det første vi skulle tale om var hvordan ledelsesgruppen lissom kunne støtte mig i at stå i den håbløse situation de havde placeret mig i, så jeg ikke tabte entusiasmen og gejsten. Den snak venter vi stadig på. Men ledelsen af biblioteket er overdraget. Og nu skal jeg så slippe det, og lære at det ikke er mit bibliotek længere. Det kræver at jeg betragter problemer der som en andens problem. Det er de jo nu.

Det giver mig straks associationer til Douglas Adams SEP-felt generator. Det er den praktiske løsning på hvordan man gør ting usynlige. Man kan godt gøre et gigantisk rumskib der hænger frit i luften ved siden af en cricket-match usynligt. Det er bare besværligt og energikrævende. Det man i stedet kan gøre er, at udforme sit rumskib som en gigantisk lyserød elefant. En gigantisk lyserød elefant kan ikke eksistere, og da slet ikke frit svævende i luften. Hvis den gør, var det noget man ville være nødt til at forholde sig til. Og hvad katten stiller man op med sådan en? Så i selvforsvar bortredigerer ens bevidsthed elefanten. Den er nu for alle praktiske formål usynlig.

Vi kender det godt fra virkeligheden. Den dryppende vandhane er noget man burde gøre noget ved. Men det er besværligt. Hvis nu det er en andens problem, kan man ignorere den. Og mennesker er så gode til at ignorere besværlige ting, at den dryppende vandhane for de fleste praktiske formål reelt ophører med at eksistere.

Tilbage til Håndbog for Vakse Galakseblaffere. Der har man udnyttet konceptet. Man har simpelthen lavet en dims der genererer et “somebody-elses-problem”-felt. Tænd for den, og alt inden for dets rækkevidde bliver automatisk til en andens problem. Og dermed usynligt.

Det er sådan en jeg har brug for. Den må jeg bygge. Jeg kan naturligvis ikke bygge en rigtig. Men jeg kan bygge en symbolsk SEP-felt generator. Som en mentalhygiejnisk foranstaltning.

Hvordan skal den så se ud?

Ja, vi ved lidt fra Adams. Vi ved at den kan køre i mange år blot med et enkelt batteri. Det egentlige arbejde udføres af vores bevidsthed, feltet skal blot overbevise os om at hvad det nu end er, er en andens problem. Vi ved også at det ikke kan slukkes. Jo formentlig fordi generatoren befinder sig inde i feltet, og dermed også bliver usynligt. Og det er egentlig hvad vi ved. Resten er op til min fantasi.

Så. En knap der tænder. Men ikke kan slukke. En lysdiode – der viser at dimsen er tændt. Og som ikke slukker igen. Der skal været et batteri. Og så skal der være et eller andet der siger “feltgenerator”. En antenne eller noget. Der må også godt være andet, der lissom signalerer teknik.

Det var kravene. I næste uge kigger vi på lidt flere detaljer.

Kunstig ældning af træ

Jeg har gang i et lille projekt af mentalhygiejnisk karakter. Det vender jeg tilbage til, men en af tingene jeg godt ville, var at få farvet en trækasse. Jeg var lidt ude efter noget der fik kassen til at se gammel ud. Der skal klart eksperimenteres lidt. Men jeg er egentlig ganske godt tilfreds med det foreløbige resultat.

Opskriften er simpel og let at gå til. Men det lugter fælt. Der er tale om en to-komponent farvning. Først males træet med te. Sort te. Når det er tørret, har træet fået en smule farve. Men den virkelige forskel kommer i andet lag. Den skal man forberede dagen før.

Man tager noget jern. Man kan vist bruge almindelige jernsøm, men jeg hev fat i en skuresvamp af ståluld, og vaskede det værste sæbe ud af den. Svampen røg i et sylteglas, og blev overhældt med eddike. Den almindelige brune sylteeddike. Og der hyggede den sig i 24 timer.

Resultatet var en gullig-grøn væske. Der lugtede aldeles hæsligt. Så det foregår passende under emhætten, eller i frisk luft. Det sidste var det lidt for koldt til. Væske males på træet, og efter kort tid, får det en frønnet grålig farve. Det kan ses her til venstre. Den første pind er ubehandlet. Nummer to har fået te. Der er ikke meget stor forskel, og slet ikke med den dårlige belysning jeg tog billedet ved. Men nummer tre er der helt klart sket ting med. Den skal have et lag eller to til, men det ønskede resultat er opnået.

Det er ikke helt klart for denne kemiker hvorfor en opløsning af jern i eddike burde lugte at ret meget andet end eddike. Men det gør den. Rester af sæbe, og den karamel der er brug til at farve eddiken kunne influere, men de steder på nettet jeg har fundet der også har eksperimenteret med det her, omtaler samstemmende at det lugter fælt. Så jeg tror ikke helt at det kun skyldes karamel og sæbe.

Hvad jeg har bedre styr på er kemien i farvningen. Årsagen til at det skal være sort te er at vi skal have et højt indhold af tanniner. De findes allerede i træet, men er ikke nødvendigvis særligt tilgængelige. Så vi tilfører noget. Og så nytter det ikke noget at bruge blomsterte der ikke har tanniner. Det er i øvrigt dem der binder kalk og lægger sig som belægninger i tekrus.

Tanniner kan også reagere med jern-ioner. Og det er dem vi laver ved at opløse jern i syre. Når jern og tanniner binder til hinanden opstår der et farvet kompleks. Det er tidligere brugt til at lave blæk med, men rester af syre, og især jern-ioner, har en kedelig tilbøjelighed til at ødelægge papiret. Det er et ret stort problem når man ønsker at bevare papir for eftertiden, så lad være med at bruge den slags blæk.