Arduino Air Swimmers Shark
When SCALE approved my talk proposal, Fun with Linux and Devices, I had a challenge: I needed some good, visual Arduino demos that would work in front of an audience.
In particular, I wanted something that moved. A little toy truck? A moving penguin? A rotating sunflower? I fiddled with this and that, not fully satisfied with anything. And then suddenly I realized what I needed. Something cool. Something BIG. Something I'd been wanting an excuse to buy anyway.
I'd seen these things on video, but never in person. They're available all over, even on Amazon, so I put in an order there and got a shark in a few days.
These things are rediculous and cool. It's huge, about 5 feet long, and filled with helium. It takes maybe half an hour to assemble. It has a small motor to beat the tail, an infrared transmitter, and a weighted receiver that moves back and forth on a track to tilt the fish up or down as it swims.
Once it's assembled, you can get it filled with helium at a party store (which costs $3 to $6 depending on where you go). Once the shark is filled, you add clay as ballast until the shark is neutrally buoyant, neither rising nor sinking. It's quite sensitive: you'll find yourself needing to add or remove pea-sized chunks of clay as the temperature in the room changes, but being a little over- or under-ballasted doesn't hurt it much. With its tail beating, the shark really does look like it's swimming through the air.
My shark is named Bruce, after the mechanical shark used for the movie "Jaws". My Bruce, I'm happy to say, has been much more tractable than his famously intemperate namesake.
Okay, now how do we turn this ridiculous-but-cool thing into an Arduino
project?
Hacking the transmitter
There were two possible approaches. First, mount an Arduino directly on the shark, and let it be totally self-directed. Second, patch the Arduino into the shark's transmitter and control it from Linux. I chose the second option, for several reasons. First, I was fairly sure it would be easier, and less invasive (the shark would still be usable with manual control). I also liked the idea of keeping the transmitter as a manual override, in case my control program didn't work right. Finally, I liked the idea of keeping a Linux machine in the loop -- the shark would actually be controlled by Linux, not just by the Arduino.
So the first thing I did was take the transmitter apart (4 Philips screws).
Inside are 4 pushbuttons, for right, left, up, and down, and the circuit
board is nice and simple. Whew -- this might be doable!
Four more screws and I had access to the back of the board, which was equally simple. Now I could get my voltmeter on the contacts while I pushed buttons.
It turned out the contacts (indicated with arrows on the photo) on the downstream side of each switch were normally high (4.5 volts -- the transmitter uses 3 AAA batteries). When I pushed the button, the contact went to ground. Okay, so what I needed was some way for the Arduino to ground those contacts at will.
First I needed to solder some wires to the contacts. (How do you tell which side of the pushbutton is the one you need to solder? Well, one side changes voltage when you press the button, and the other side stays constant. The one that changes is the one you need to connect to the Arduino, so the Arduino can change it too.)
I figured I needed 6 wires: ground, power, and one for each switch. (It turned out I didn't need the power wire, but I figured it didn't hurt to include it just in case.) I wanted to have a nice small connector on the side of the transmitter, but I couldn't find any 6-pin connectors that didn't look big and bulky, so I gave up and decided I'd just let my ribbon cable dangle from the transmitter. If I got a nice multi-colored one, maybe it would look festive.
I couldn't find any 6-conductor ribbon cable, so I got a wider one and separated 6 wires from the rest. Then I soldered the six wires to the appropriate places (marked by arrows in the photo). On the other end, I tinned the six wires with solder so I could plug the stranded wires into my breadboard. Simulating button presses
I've done enough reading to know of three ways to simulate a button press. You can put a relay between the two contacts of the switch; you can do the same thing, but with an optocoupler (opto-isolator) instead of a relay; or you can do some magic with a transistor. I was fuzzy on the transistor magic bit, so a relay sounded easiest.
I played around with a relay and a spare switch and convinced myself I knew how to wire them up. Then it was off to my local parts store to buy four matched relays small enough to fit on my little mini breadboard.
There followed a several-day fiasco wherein I bought lots of relays that turned out not to be suitable, and got increasingly frustrated at how large and clunky all the available relays were. There are smaller ones, but I couldn't get them to work. And I learned that relays mostly come without documentation on which pin does which, so there's a lot of experimenting with each new type.
Frustrated, I tried some optocouplers I'd bought on a whim last year.
No dice ... couldn't get them to work either.
Desperate, I turned to IRC, #arduino on Freenode. The folks there are mostly electronics wizards, and I'm sure my questions must have seemed very dumb, but they were patient with me, and pointed me toward a very simple circuit, LED4dummies, that was just what I needed. (They also suggested Wikipedia's Open collector article, but I found that less clear.)
It took me some
experimenting with a transistor, an LED and a couple of resistors
(I blew out a couple of transistors before I realized I had the R2 resistor
in the wrong place) but eventually I got it working, and felt confident
enough to try it with the real shark transmitter. The key was to simplify
the circuit so it had no extra parts, then once it was working, add more
parts to build it up to what I needed.
At left, the circuit I ended up with. For each button, I have one
transistor and one resistor (I don't need the second resistor from the
LED4dummies circuit, since that was just to keep the LED from burning out).
At right is the circuit assembled on a mini-breadboard on top of the proto-shield. Note that the ends of the ribbon cable are plugged in to a spare header I had lying around; a header makes a passable connector, so I can plug it in fairly easily right before a talk. The green and blue wires in the back are going to Arduino digital output pins 3 through 6 (leaving 0 and 1 for serial I/O). The red wires go from the transistors back to the ribbon cable wires that go to the shark's transmitter buttons. The software side
Now I could make the shark think I'd pressed a button on its transmitter. How do I control that from Linux?
On the Arduino side, I wrote a simple program that reads and parses commands coming over the USB cable. So from the computer, I might send a line like L 300, and the Arduino would "press" the Left button for 300 milliseconds. I had already written something like this for a couple of other Arduino programs. That program is shark.pde.
On the Linux side, first I needed something that established a serial connection and sent commands to the Arduino. I wrote a Python class for that, shark.py. That let me send commands from the Python console to test the shark.
Then I needed something more visual, something I could show during a talk. In particular, the shark doesn't swim unless someone's pressing left, right, left, right buttons over and over. Of course I wanted the computer to handle that part.
So I wrote a little Python-GTK application that keeps the shark swimming, and lets me drag a mouse around to adjust its left/right up/down direction: sharkwindow.
Purely by coincidence, the week before SCALE, Scott Adams introduced a roboshark character: Dilbert, Jan 11 2012. Nice timing for the debut of my own roboshark!
Sadly, I don't have any photos or video of the shark in action.
But if you're a LWN subscriber, there's an article on my talk
with a couple of great pictures:
Robots rampage (in a
friendly way) at SCALE 10X.
And you can see my slides and notes at
Arduino notes.
Converting HTML pages into PDF
I've long wanted a way of converting my HTML presentation slides to PDF. Mostly because conference organizers tend to freak out at slides in any format other than Open/Libre Office, Powerpoint or PDF. Too many times, I've submitted a tarball of my slides and discovered they weren't even listed on the conference site. (I ask you, in what way is a tarball more difficult to deal with than an .odp file?) Slide-sharing websites also have a limited set of formats they'll accept.
A year or so ago, I added screenshot capability to my webkit-based presentation program, Preso, do "screenshots", but I really needed PDF, not images.
Now, creating PDF from HTML shouldn't be that hard. Every browser has a print function that can print to a PDF file. So why is it so hard to create PDF from HTML in any kind of scriptable way?
After much searching and experimenting, I finally found a Python code snippet that worked: XHTML to PDF using PyGTK4 Webkit from Alex Dong. It uses Python-Qt, not GTK, so I can't integrate it into my Preso app, but that's okay -- a separate tool is just as good.
(I struggled to write an equivalent in PyGTK, but gave up due to the complete lack of documentation of Python-Webkit-GTK, and not much more for gtk.PrintOperation(). QWebView's documentation may not be as complete as I'd like, but at least there is some.) Printing from QtWebView to QPrinter
Here are the important things I learned about QWebView from fiddling around with Alex's code to adapt it to what I needed, which is printing a list of pages to sequentially numbered files:
- To print, you need to wait until the page has finished loading, so connect a function to SIGNAL("loadFinished(bool)"), then load(QUrl(url)).
- That loadFinished function remains registered, so as you load new pages, it will be called each time. So you can load() the next URL as the last step in your loadFinished callback.
- If you get confused about callbacks and connect more than one of them, bad things happen, and only the last page gets printed, or QApplication.exit() doesn't exit at all.
Things I learned about QPrinter():
- All the examples I found online set the page size with lines like QPrinter.setPageSize(QPrinter.A4) or setPaperSize(QPrinter.A4) (setPageSize is apparently deprecated in favor of setPaperSize); but
- If you want to set a specific size, you can do that with a line like QPrinter.setPaperSize(QSizeF(1024, 768), QPrinter.DevicePixel) The second argument (DevicePixel) is a unit, from this list.
- That line gives you the right aspect ratio. But if you think "DevicePixels" means the size will correspond to pixels in your browser window (just because the documentation says so), you're sadly mistaken.
- If you want a PDF page that actually corresponds to the size of your browser window, you can get it by calling QWebView.setZoomFactor(z) You'll have to experiment to find the right value of z; I found I needed about 1.24 if I wanted to capture my full 1366x768 slides, or exactly 2.0 if I wanted to restrict the saved PDF to only the 1024x758 part that shows up in the projector.
Anyway, it's a little hacky with that empirical zoom factor ... but it works! The program is here: qhtmlprint: convert HTML to PDF using Qt Webkit.
And it does produce reasonable PDF, with the text properly vectorized, not just raster screenshots of each page. Printing the slides in the right order
Terrific -- now I can feed a list of slides to qhtmlprint and get a bunch of PDF files back. How do I print the right slides?
My slides are listed in order in an array inside a Javascript file, one per line. If I grep .html navigate.js, I get a list like this: "arduino.html", "img.html?pix/arduinos/arduino-clones.jpg", "getting_started.html", "img.html?pix/projects/led.jpg", //"blink.html", "arduino-ide.html",
To pass that to qhtmlprint, I only need to remove the commented-out lines (the ones with //) and strip off the quotes and commas. I can do that all in one command with a grep and sed pipeline: qhtmlprint ` fgrep .html navigate.js | grep -v // | sed -e 's/",/"/' -e 's/"//g' `
And voiaà! I have a bunch of fileNNN.pdf files. Creating a multi-page slide deck
Okay, great! Now how do I stick those files all together into one slide deck I can submit to conference organizers?
That part's easy -- Ghostscript can do it. gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=slidedeck.pdf -dBATCH file*.pdf
And now slidedeck.pdf contains my whole presentation, ready to go.
HTML and Javascript Presentations
When I give talks that need slides, I've been using my Slide Presentations in HTML and JavaScript for many years. I uploaded it in 2007 -- then left it there, without many updates.
But meanwhile, I've been giving lots of presentations, tweaking the code, tweaking the CSS to make it display better. And every now and then I get reminded that a few other people besides me are using this stuff.
For instance, around a year ago, I gave a talk where nearly all the slides were just images. Silly to have to make a separate HTML file to go with each image. Why not just have one file, img.html, that can show different images? So I wrote some code that lets you go to a URL like img.html?pix/whizzyphoto.jpg, and it will display it properly, and the Next and Previous slide links will still work.
Of course, I tweak this software mainly when I have a talk coming up. I've been working lately on my SCALE talk, coming up on January 22: Fun with Linux and Devices (be ready for some fun Arduino demos!) Sometimes when I overload on talk preparation, I procrastinate by hacking the software instead of the content of the actual talk. So I've added some nice changes just in the past few weeks.
For instance, the speaker notes that remind me of where I am in the talk and what's coming next. I didn't have any way to add notes on image slides. But I need them on those slides, too -- so I added that.
Then I decided it was silly not to have some sort of automatic reminder of what the next slide was. Why should I have to put it in the speaker notes by hand? So that went in too.
And now I've done the less fun part -- collecting it all together and documenting the new additions. So if you're using my HTML/JS slide kit -- or if you think you might be interested in something like that as an alternative to Powerpoint or Libre Office Presenter -- check out the presentation I have explaining the package, including the new features.
You can find it here: Slide Presentations in HTML and JavaScript
Parsing HTML in Python
I've been having (mis)adventures learning about Python's various options for parsing HTML.
Up until now, I've avoided doing any HTMl parsing in my RSS reader FeedMe. I use regular expressions to find the places where content starts and ends, and to screen out content like advertising, and to rewrite links. Using regexps on HTML is generally considered to be a no-no, but it didn't seem worth parsing the whole document just for those modest goals.
But I've long wanted to add support for downloading images, so you could view the downloaded pages with their embedded images if you so chose. That means not only identifying img tags and extracting their src attributes, but also rewriting the img tag afterward to point to the locally stored image. It was time to learn how to parse HTML.
Since I'm forever seeing people flamed on the #python IRC channel for using regexps on HTML, I figured real HTML parsing must be straightforward. A quick web search led me to Python's built-in HTMLParser class. It comes with a nice example for how to use it: define a class that inherits from HTMLParser, then define some functions it can call for things like handle_starttag and handle_endtag; then call self.feed(). Something like this: from HTMLParser import HTMLParser class MyFancyHTMLParser(HTMLParser): def fetch_url(self, url) : request = urllib2.Request(url) response = urllib2.urlopen(request) link = response.geturl() html = response.read() response.close() self.feed(html) # feed() starts the HTMLParser parsing def handle_starttag(self, tag, attrs): if tag == 'img' : # attrs is a list of tuples, (attribute, value) srcindex = self.has_attr('src', attrs) if srcindex < 0 : return # img with no src tag? skip it src = attrs[srcindex][1] # Make relative URLs absolute src = self.make_absolute(src) attrs[srcindex] = (attrs[srcindex][0], src) print '<' + tag for attr in attrs : print ' ' + attr[0] if len(attr) > 1 and type(attr[1]) == 'str' : # make sure attr[1] doesn't have any embedded double-quotes val = attr[1].replace('"', '\"') print '="' + val + '"') print '>' def handle_endtag(self, tag): self.outfile.write('</' + tag.encode(self.encoding) + '>\n')
Easy, right? Of course there are a lot more details, but the basics are simple.
I coded it up and it didn't take long to get it downloading images and changing img tags to point to them. Woohoo! Whee! The bad news about HTMLParser
Except ... after using it a few days, I was hitting some weird errors.
In particular, this one:
HTMLParser.HTMLParseError: bad end tag: ''
It comes from sites that have illegal content. For instance, stories
on Slate.com include Javascript lines like this one inside
<script></script> tags:
document.write("<script type='text/javascript' src='whatever'></scr" + "ipt>");
This is technically illegal html -- but lots of sites do it, so protesting that it's technically illegal doesn't help if you're trying to read a real-world site.
Some discussions said setting self.CDATA_CONTENT_ELEMENTS = () would help, but it didn't.
HTMLParser's code is in Python, not C. So I took a look at where the errors are generated, thinking maybe I could override them. It was easy enough to redefine parse_endtag() to make it not throw an error (I had to duplicate some internal strings too). But then I hit another error, so I redefined unknown_decl() and _scan_name(). And then I hit another error. I'm sure you see where this was going. Pretty soon I had over 100 lines of duplicated code, and I was still getting errors and needed to redefine even more functions. This clearly wasn't the way to go. Using lxml.html
I'd been trying to avoid adding dependencies to additional Python packages, but if you want to parse real-world HTML, you have to. There are two main options: Beautiful Soup and lxml.html. Beautiful Soup is popular for large projects, but the consensus seems to be that lxml.html is more error-tolerant and lighter weight.
Indeed, lxml.html is much more forgiving. You can't handle start and end tags as they pass through, like you can with HTMLParser. Instead you parse the HTML into an in-memory tree, like this: tree = lxml.html.fromstring(html)
How do you iterate over the tree? lxml.html is a good parser, but it has rather poor documentation, so it took some struggling to figure out what was inside the tree and how to iterate over it.
You can visit every element in the tree with for e in tree.iter() : print e.tag
But that's not terribly useful if you need to know which tags are inside which other tags. Instead, define a function that iterates over the top level elements and calls itself recursively on each child.
The top of the tree itself is an element -- typically the <html></html> -- and each element has .tag and .attrib. If it contains text inside it (like a <p> tag), it also has .text. So to make something that works similarly to HTMLParser: def crawl_tree(tree) : handle_starttag(tree.tag, tree.attrib) if tree.text : handle_data(tree.text) for node in tree : crawl_tree(node) handle_endtag(tree.tag)
But wait -- we're not quite all there. You need to handle two undocumented cases.
First, comment tags are special: their tag attribute, instead of being a string, is <built-in function Comment> so you have to handle that specially and not assume that tag is text that you can print or test against.
Second, what about cases like <p>Here is some <i>italicised</i> text.</p> ? in this case, you have the p tag, and its text is "Here is some ". Then the p has a child, the i tag, with text of "italicised". But what about the rest of the string, " text."?
That's called a tail -- and it's the tail of the adjacent i tag it follows, not the parent p tag that contains it. Confusing!
So our function becomes: def crawl_tree(tree) : if type(tree.tag) is str : handle_starttag(tree.tag, tree.attrib) if tree.text : handle_data(tree.text) for node in tree : crawl_tree(node) handle_endtag(tree.tag) if tree.tail : handle_data(tree.tail)
See how it works? If it's a comment (tree.tag isn't a string),
we'll skip everything -- except the tail. Even a comment
might have a tail:
<p>Here is some <!-- this is a comment --> text we want to show.</p>
so even if we're skipping comment we need its tail.
I'm sure I'll find other gotchas I've missed, so I'm not releasing this version of feedme until it's had a lot more testing. But it looks like lxml.html is a reliable way to parse real-world pages. It even has a lot of convenience functions like link rewriting that you can use without iterating the tree at all. Definitely worth a look!
Open the X selection in a browser window, from any desktop
Like most Linux users, I use virtual desktops. Normally my browser window is on a desktop of its own.
Naturally, it often happens that I encounter a link I'd like to visit while I'm on a desktop where the browser isn't visible. From some apps, I can click on the link and have it show up. But sometimes, the link is just text, and I have to select it, change to the browser desktop, paste the link into firefox, then change desktops again to do something else while the link loads.
So I set up a way to load whatever's in the X selection in firefox no matter what desktop I'm on.
In most browsers, including firefox, you can tell your existing browser window to open a new link from the command line: firefox http://example.com/ opens that link in your existing browser window if you already have one up, rather than starting another browser. So the trick is to get the text you've selected.
At first, I used a program called xclip. You can run this command: firefox `xclip -o` to open the selection. That worked okay at first -- until I hit my first URL in weechat that was so long that it was wrapped to the next line. It turns out xclip does odd things with multi-line output; depending on whether it thinks the output is a terminal or not, it may replace the newline with a space, or delete whatever follows the newline. In any case, I couldn't find a way to make it work reliably when pasted into firefox.
After futzing with xclip for a little too long, trying to reverse-engineer its undocumented newline behavior, I decided it would be easier just to write my own X clipboard app in Python. I already knew how to do that, and it's super easy once you know the trick: mport gtk primary = gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY) if primary.wait_is_text_available() : print primary.wait_for_text()
That just prints it directly, including any newlines or spaces. But as long as I was writing my own app, why not handle that too?
It's not entirely necessary on Firefox: on Linux, Firefox has some special code to deal with pasting multi-line URLs, so you can copy a URL that spans multiple lines, middleclick in the content area and things will work. On other platforms, that's disabled, and some Linux distros disable it as well; you can enable it by going to about:config and searching for single, then setting the preference editor.singlelinepaste.pasteNewlines to 2.
However, it was easy enough to make my Python clipboard app do the right thing so it would work in any browser. I used Python's re (regular expressions) module: #!/usr/bin/env python import gtk import re primary = gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY) if not primary.wait_is_text_available() : sys.exit(0) s = primary.wait_for_text() # eliminate newlines, and any spaces immediately following a newline: print re.sub(r'[\r\n]+ *', '', s)
That seemed to work fine, even on long URLs pasted from weechat with newlines and spaces, like that looked like http://example.com/long- url.html
All that was left was binding it so I could access it from anywhere. Of course, that varies depending on your desktop/window manager. In Openbox, I added two items to my desktop menu in menu.xml: <item label="open selection in Firefox"> <action name="Execute"><execute>sh -c 'firefox `xclip -o`'</execute></action> </item> <item label="open selection in new tab"> <action name="Execute"><execute>sh -c 'firefox -new-tab `xclip -o`'</execute></action> </item>
I also added some code in rc.xml inside <context name="Desktop">, so I can middle-click or control-middle-click on the desktop to open a link in the browser: <mousebind button="Middle" action="Press"> <action name="Execute"> <execute>sh -c 'firefox `pyclip`'</execute> </action> </mousebind> <mousebind button="C-Middle" action="Press"> <action name="Execute"> <execute>sh -c -new-tab 'firefox `pyclip`'</execute> </action> </mousebind>
I set this up maybe two hours ago and I've probably used it ten or fifteen times already. This is something I should have done long ago!
Plotting the Analemma
My SJAA planet-observing column for January is about the Analemma and the Equation of Time.
The analemma is that funny figure-eight you see on world globes in the middle of the Pacific Ocean. Its shape is the shape traced out by the sun in the sky, if you mark its position at precisely the same time of day over the course of an entire year.
The analemma has two components: the vertical component represents the sun's declination, how far north or south it is in our sky. The horizontal component represents the equation of time.
The equation of time describes how the sun moves relatively faster or slower at different times of year. It, too, has two components: it's the sum of two sine waves, one representing how the earth speeds up and slows down as it moves in its elliptical orbit, the other a function the tilt (or "obliquity") of the earth's axis compared to its orbital plane, the ecliptic.
The Wikipedia page for
Equation of
time includes a link to a lovely piece of
R code by
Thomas Steiner showing how the two components relate. It's labeled
in German, but since the source is included, I was able to add English
labels and use it for my article.
But if you look at photos of real analemmas in the sky, they're always tilted. Shouldn't they be vertical? Why are they tilted, and how does the tilt vary with location? To find out, I wanted a program to calculate the analemma. Calculating analemmas in PyEphem
The very useful astronomy Python package PyEphem makes it easy to calculate the position of any astronomical object for a specific location. Install it with: easy_install pyephem for Python 2, or easy_install ephem for Python 3. import ephem observer = ephem.city('San Francisco') sun = ephem.Sun() sun.compute(observer) print sun.alt, sun.az
The alt and az are the altitude and azimuth of the sun right now. They're printed as strings: 25:23:16.6 203:49:35.6 but they're actually type 'ephem.Angle', so float(sun.alt) will give you a number in radians that you can use for calculations.
Of course, you can specify any location, not just major cities. PyEphem doesn't know San Jose, so here's the approximate location of Houge Park where the San Jose Astronomical Association meets: observer = ephem.Observer() observer.name = "San Jose" observer.lon = '-121:56.8' observer.lat = '37:15.55'
You can also specify elevation, barometric pressure and other parameters.
So here's a simple analemma, calculating the sun's position at noon on the 15th of each month of 2011: for m in range(1, 13) : observer.date('2011/%d/15 12:00' % (m)) sun.compute(observer)
I used a simple PyGTK window to plot sun.az and sun.alt, so once it was initialized, I drew the points like this: # Y scale is 45 degrees (PI/2), horizon to halfway to zenith: y = int(self.height - float(self.sun.alt) * self.height / math.pi) # So make X scale 45 degrees too, centered around due south. # Want az = PI to come out at x = width/2. x = int(float(self.sun.az) * self.width / math.pi / 2) # print self.sun.az, float(self.sun.az), float(self.sun.alt), x, y self.drawing_area.window.draw_arc(self.xgc, True, x, y, 4, 4, 0, 23040)
So now you just need to calculate the sun's position at the same time of day but different dates spread throughout the year.
And my 12-noon analemma came out almost vertical! Maybe the tilt I saw
in analemma photos was just a function of taking the photo early in
the morning or late in the afternoon? To find out, I calculated the
analemma for 7:30am and 4:30pm, and sure enough, those were tilted.
But wait -- notice my noon analemma was almost vertical -- but it wasn't exactly vertical. Why was it skewed at all? Time is always a problem
As always with astronomy programs, time zones turned out to be the hardest part of the project. I tried to add other locations to my program and immediately ran into a problem.
The ephem.Date class always uses UTC, and has no concept of converting to the observer's timezone. You can convert to the timezone of the person running the program with localtime, but that's not useful when you're trying to plot an analemma at local noon.
At first, I was only calculating analemmas for my own location. So I set time to '20:00', that being the UTC for my local noon. And I got the image at right. It's an analemma, all right, and it's almost vertical. Almost ... but not quite. What was up?
Well, I was calculating for 12 noon clock time -- but clock time isn't
the same as mean solar time unless you're right in the middle of your
time zone.
You can calculate what your real localtime is (regardless of what politicians say your time zone should be) by using your longitude rather than your official time zone: date = '2011/%d/12 12:00' % (m) adjtime = ephem.date(ephem.date(date) \ - float(self.observer.lon) * 12 / math.pi * ephem.hour) observer.date = adjtime
Maybe that needs a little explaining. I take the initial time string, like '2011/12/15 12:00', and convert it to an ephem.date. The number of hours I want to adjust is my longitude (in radians) times 12 divided by pi -- that's because if you go pi (180) degrees to the other side of the earth, you'll be 12 hours off. Finally, I have to multiply that by ephem.hour because ... um, because that's the way to add hours in PyEphem and they don't really document the internals of ephem.Date.
Set the observer date to this adjusted time before calculating your
analemma, and you get the much more vertical figure you see here.
This also explains why the morning and evening analemmas weren't
symmetrical in the previous run.
This code is location independent, so now I can run my analemma program
on a city name, or specify longitude and latitude.
PyEphem turned out to be a great tool for exploring analemmas.
But to really understand analemma shapes, I had more exploring to do.
I'll write about that, and post my complete analemma program,
in the next article.
Calculating the Solstice and shortest day
Today is the winter solstice -- the official beginning of winter.
The solstice is determined by the Earth's tilt on its axis, not anything to do with the shape of its orbit: the solstice is the point when the poles come closest to pointing toward or away from the sun. To us, standing on Earth, that means the winter solstice is the day when the sun's highest point in the sky is lowest.
You can calculate the exact time of the equinox using the handy Python package PyEphem. Install it with: easy_install pyephem for Python 2, or easy_install ephem for Python 3. Then ask it for the date of the next or previous equinox. You have to give it a starting date, so I'll pick a date in late summer that's nowhere near the solstice: >>> ephem.next_solstice('2011/8/1') 2011/12/22 05:29:52 That agrees with my RASC Observer's Handbook: Dec 22, 5:30 UTC. (Whew!)
PyEphem gives all times in UTC, so, since I'm in California, I subtract 8 hours to find out that the solstice was actually last night at 9:30. If I'm lazy, I can get PyEphem to do the subtraction for me: ephem.date(ephem.next_solstice('2011/8/1') - 8./24) 2011/12/21 21:29:52 I used 8./24 because PyEphem's dates are in decimal days, so in order to subtract 8 hours I have to convert that into a fraction of a 24-hour day. The decimal point after the 8 is to get Python to do the division in floating point, otherwise it'll do an integer division and subtract int(8/24) = 0. The shortest day
The winter solstice also pretty much marks the shortest day of the year. But was the shortest day yesterday, or today? To check that, set up an "observer" at a specific place on Earth, since sunrise and sunset times vary depending on where you are. PyEphem doesn't know about San Jose, so I'll use San Francisco: >>> import ephem >>> observer = ephem.city("San Francisco") >>> sun = ephem.Sun() >>> for i in range(20,25) : ... d = '2011/12/%i 20:00' % i ... print d, (observer.next_setting(sun, d) - observer.previous_rising(sun, d)) * 24 2011/12/20 20:00 9.56007901422 2011/12/21 20:00 9.55920379754 2011/12/22 20:00 9.55932991847 2011/12/23 20:00 9.56045709446 2011/12/24 20:00 9.56258416496 I'm multiplying by 24 to get hours rather than decimal days.
So the shortest day, at least here in the bay area, was actually yesterday, 2011/12/21. Not too surprising, since the solstice wasn't that long after sunset yesterday.
If you look at the actual sunrise and sunset times, you'll find that the latest sunrise and earliest sunset don't correspond to the solstice or the shortest day. But that's all tied up with the equation of time and the analemma ... and I'll cover that in a separate article.
Convert patterns in only some lines to title case
A friend had a fun problem: she had some XML files she needed to import into GNUcash, but the program that produced them left names in all-caps and she wanted them more readable. So she'd have a file like this: <STMTTRN> <TRNTYPE>DEBIT <DTPOSTED>20111125000000[-5:EST] <TRNAMT>-22.71 <FITID>**** <NAME>SOME COMPANY <MEMO>SOME COMPANY ANY TOWN CA 11-25-11 330346 </STMTTRN> and wanted to change the NAME and MEMO lines to read Some Company and Any Town. However, the tags, like <NAME>, all had to remain upper case, and presumably so did strings like DEBIT. How do you change just the NAME and MEMO lines from upper case to title case?
The obvious candidate to do string substitutes is sed. But there are several components to the problem. Addresses
First, how do you ensure the replacement only happens on lines with NAME and MEMO?
sed lets you specify address ranges for just that purpose. If you say sed 's/xxx/yyy/' sed will change all xxx's to yyy; but if you say sed '/NAME/s/xxx/yyy/' then sed will only do that substitution on lines containing NAME.
But we need this to happen on lines that contain either NAME or MEMO. How do you do that? With \|, like this: sed '/\(NAME\|MEMO\)/s/xxx/yyy/' Converting to title case
Next, how do you convert upper case to lower case? There's a sed command for that: \L. Run sed 's/.*/\L&/' and type some upper and lower case characters, and they'll all be converted to lower-case.
But here we want title case -- we want most of each word converted to lowercase, but the first letter should stay uppercase. That means we need to detect a word and figure out which is the first letter.
In the strings we're considering, a word is a set of letters A through Z with one of the following characteristics:
- It's preceded by a space
- It's preceded by a close-angle-bracket, >
So the pattern /[ >][A-Z]*/ will match anything we consider a word that might need conversion.
But we need to separate the first letter and the rest of the word, so we can treat them separately. sed's \( \) operators will let us do that. The pattern \([ >][A-Z]\) finds the first letter of a word (including the space or > preceding it), and saves that as its first matched pattern, \1. Then \([A-Z]*\) right after it will save the rest of the word as \2.
So, taking our \L case converter, we can convert to title case like this: sed 's/\([ >][A-Z]\)\([A-Z]*\)/\1\L\2/g
Starting to look long and scary, right? But it's not so bad if you build it up gradually from components. I added a g on the end to tell sed this is a global replace: do the operation on every word it finds in the line, otherwise it will only make the substitution once, on the first word it sees, then quit. Putting it together
So we know how to seek out specific lines, and how to convert to title case. Put the two together, and you get the final command: sed '/\(NAME\|MEMO\)/s/\([ >][A-Z]\)\([A-Z]*\)/\1\L\2/g'
I ran it on the test input, and it worked just fine.
For more information on sed, a good place to start is the sed regular expressions manual.
Costume
Tudo bem que esse inverno tá sendo meia-boca – um ano atrás estava rolando Snowpocalypse e eu estava com neve quase na altura dos joelhos – pois até agora as ruas estão secas e o máximo que eu vi foi meia dúzia de floquinhos que dissolvem no dia seguinte. Mas, ainda assim, é fato que inverno é uma coisa à qual você se acostuma. Eu sou carioca, nascida num sábado de sol, quando todo mundo estava curtindo uma praia. E tenho ficado surpresa com minha reação de acordar, olhar a previsão do tempo, ver “hm… -5 é? Ah, não tá tão ruim assim”.
Claro que dá uma certa preguiça se desenrolar do edredom e vestir o uniforme de inverno. Meu truque tem sido tomar um bom banho à noite porque meu banheiro é meio frio (não tem aquecimento) e me desestimula de tomar banho de manhã. Eu também durmo melhor depois de um banho quentinho, claro. Para temperaturas entre 0 e -10, em geral duas camisas, calça e meia calça ou legging, meias grossas e um moletom, casaco de neve e cachecol compõem o tal uniforme. Eu não costumo usar luvas nessa temperatura, só enfio a mão no bolso. Quando fica mais frio que isso (não é muito comum em Toronto) eu acrescento mais camisas e mais meias, é a técnica Photoshop de aquecimento – camadas.
Sapato é um lance à parte. Tenho uma bota de couro bonita, mas ela é escorregadia pra andar na neve. Comprei uma galocha peludinha Tretorn ROSA e adoro. Ganhei uma nova de aniversário da Sula, ROXA, combina bem com um suéter igualmente ROXO que tenho, infelizmente tivemos pouca neve (é, eu gosto de neve, com moderação) e usei galocha exatamente DUAS VEZES esse ano, uma no dia em que a sensação térmica chegou a MENOS 25 e eu te digo, isso É FRIO PACAS – o problema é o vento, que não raramente chega a 40km/h, por causa do lago e da ausência de montanhas. Alguém precisa construir umas montanhas nessa cidade. Da última vez que pedalei – à noite, 10km! – estava fazendo -3 com ventos de 40km/h. Fiquei doente dois dias depois, surpreendente, não?
Vamos ver se eu vejo algum dia de Snowpocalypse esse ano. Depois de uma nevasca, quando abre o sol, o parque e as redondezas ficam lindíssimos, eu tenho fotos do ano passado – deve ser por isso que gosto de neve. A nevasca em si não me incomoda muito e acho tão bonitos os dias seguintes que fico empolgada durante. Mas, janeiro tem sido tão meh em termos de inverno – tem até chovido, e detesto chuva – que não estou levando muita fé.
Related posts:
It's a boy!
We have started to tell Ada that I have a baby in my tummy. She usually responds by pointing at her own tummy or by saying the baby is in my pants. But the other day she started putting raisins into my belly button, claiming that the baby was hungry. And then picked them out again to eat them. At least she shows some understanding of anatomy and the use of navels...
As for pregnancy as such it's going ok. It's much tougher this time than the first time, and I am still sick. Morning sickness (or rather evening sickness) is not fun at all, and eating is the only thing that helps. I am also rather exhausted, but I can manage that. Going to work is ok, the three hours between work and someone's bedtime not so fun - but I manage that, too, and Ada can live fine with a mum on the couch and a dad who does the reading, feeding and bathing with her.
We're still breastfeeding - after all the struggle to get her started I am not in for giving up yet! Or at least I don't want to initiate weaning - she can do that. She only nurses about twice a day, and I don't have much milk. I am pretty sure I have started to have colostrum, the kind of milk that's in the breasts until the milk "comes in" a couple of days after birth. Production usually starts in the 5th month of pregnancy. The milk is not stored in the breast until birth, like other bodily fluids milk is absorbed by the body if it's not drained/secreted, and the production is continuously. It's driven by hormones, not by demand (even though I guess the production even of colostrum may increase by demand even if the lactation process is not yet "there" - "there" being the processes that happen during and after birth, with the actual birth, the release of placenta etc).
Colostrum is fascinating stuff, I may write more about it later. It has a laxative effect, which helps the body dispose of meconium, the waste product made in the bowel during pregnancy when the baby swallows water. After birth the bowels should be empted of meconium, and colostrum helps with this. This also work with older kids. I am pretty sure I started making colostrum in the middle of last week, as Ada started having looser stools then. The reason why I make this connection is that they went back to normal when I was away for 36 hours - then the looser ones returned again when I was back. It's potent!
Feed a fever, starve a cold
I was very excited to have my flu shot early in December so I would be bug-free for this winter and would be able to enjoy outdoor winter activities – like skating, I’ve gone skating exactly twice last year before the rinks were closed – could do more yoga, well, many things. I even enjoyed a few days of higher temperatures by cycling to work. THEN everybody around me started getting sick with this annoying cold, which is a different virus, and I finally got it too. End of story, two weeks of sore throat, coughing, and the only activities I’ve been doing are going to the drugstore to buy more syrup and cold medicine. Now, you, tell me, isn’t that REALLY EXCITING?
Today, after two weeks, I don’t seem to be coughing anymore, although my throat is still a bit sensitive – I will keep eating right, drinking tea and taking meds, as I am travelling to Montréal this weekend and I don’t want to stay in the hotel during the trip. Wish me luck! It is indeed colder there and I want to walk and try some snow activities we couldn’t have this year in Toronto (because there was no snow :D). Stay tuned!
Related posts:
Moving on – the journey continues
Today is a complicated day. I’m both sad and excited in equal measure about what this year may hold in store.
I’m sad because this is my last day working for Senator Kate Lundy as her IT Policy Advisor and inhouse geek. Kate headhunted me almost 3 years ago at BarCamp Canberra, though we had known each other for a few years beforehand from when she was the Shadow Minister for IT. I was quite wary of going to work in a political office, but my curiosity about how the machine works combined with a desire to help make good tech policy and an immense amount of respect for Kate brought me into one of the most interesting, fun and challenging jobs I’ve ever had.
I particularly wanted to better understand the legislative and executive arms of government. How ideas turn into policy and policy into implementation. As a result, along with doing my job I’ve spent time researching the history of democracy, of Australian politics, of the ideological and historical premise of all the major Australian parties and the interaction between party politics and democracy over the years. I’ve also spent time coming to understand some of the layout, responsibilities and challenges of a multi-tiered system of government.
I have learnt a great deal in this job about government, but also about human nature. Working in an electoral office gives one some insight to the difficulties faced by many, but also some insight to the challenge in maintaining a constructive and respectful dialogue. I think it is human nature to try to boil issues down to black and white. But we are essentially grey creatures with enormous complexity, and I think democracy is about finding ways to have a transparent, informed, respectful and constructive dialogue with all the people on complex policies and implementation, so governments can best implement the best policies for the communities they serve.
I have been lucky to work for a politician who is passionate and knowledgeable about technology and good policy. She has been a valuable teacher and mentor. I shall always be thankful for the wisdom, patience, compassion, critical thinking, strategy and policy development I have learnt in this role and from Kate. I’m sure these skills will continue to serve me well.
My work on Kate’s website, the Public Spheres, Open Government, assisting Kate in linking together different tech policies across a variety of portfolios are all things I am proud of. I also feel very lucky to have met and worked with such inspirational people from many different walks of life through this role and in Kate’s office.
Meanwhile, having developed some understanding of the legislative and executive arms of government, I realised that I wanted to have more experience in the administrative arm of government. I had done some tech work in a previous life within departments but always as the outsourced person. I knew I wanted to really get in and contribute to the public service, as well as learn more about the implementation of policy and the delivery of government services to citizens.
As such, I’m excited to say I am hopefully moving into a role in the APS in the coming weeks and I hope my efforts there will be broadly useful to others in the APS. I can’t say more at this stage as it is being finalised at the moment, but I’ll update this post in the weeks ahead with more information.
By working within the APS, I hope to get a better personal understanding of the specific challenges facing the APS with regards to technology, and hopefully assist in developing strategies to be a more agile, responsive and citizen-centric public service. I will also continue helping to move the Open Government agenda ahead both in my own time and, where appropriate, within my new role. My commitment to Open Government (and Gov 2.0) lies in my understanding that it provides a path to a public service and democracy that is most relevant to, engaged with, responsive to, representative of and accountable to its citizens.
I’ll finish by saying that after three years in her office, my respect for Kate has only grown. She is a person who has engaged fully in her role with integrity, responsibility, grace and a firm grip on her own principles. She is a politician that makes me believe politics isn’t just a dirty word and I wish we had more like her. Even in spite of the fact the last time I socialised with her, I ended up with a fractured scaphoid! I have learnt a keen respect for the torque of a 2 stroke, especially on a motocross track.
My shiny black carbon fibre cast. Shiny!
So, I’m diving into the deep end and I look forward to seeing how well I swim. Wish me luck
Melbourne: Free Software Melbourne discussion on encouraging women
The next Free Software Melbourne meeting is about encouraging women in the free software community, all the details are on the website.
One (Common) Marketing Tactic That Can Ruin Your Business…

Scott McNealy, former Sun Microsystems CEO, and
Larry Ellison of Oracle announce a closer partnership
in 2006, which led to Oracle acquiring Sun in 2009. There’s one (unfortunately common) marketing tactic out there that can actually take down your entire business. This is the true story of how I watched it unfold at a Fortune 500 company…
Back in 2000, the company that I worked for, Cobalt Networks, was acquired by Sun Microsystems. I interviewed, and was accepted for, a position in Sun’s marketing department, working on Sun.com. As part of Sun’s marketing department, I got to see some of the advertisements Sun created to sell products to potential customers.
Sun’s potential customers were mainly large government agencies and giant corporations. These government agencies and corporations were used to buying products from IBM, Oracle, and the like. (Imagine a customer so large that your billion-dollar company is still considered a “startup”!)
The TacticSun’s main tactic was to go negative in its advertising. One ad I remember them being so proud of (they actually photographed it in the San Francisco office I worked out of) was a shot of a man in a suit. He had dollar bills in his pockets, and the ad made it appear as if they were being “vacuumed” out of his pockets. The tagline was, essentially, “This is what IBM does to your company.”
The request for a negative campaign like this came straight from the top–from Scott McNealy, who was CEO at the time. Sun was negative toward everyone else in the industry. IBM? Hated ‘em. Microsoft? The devil! Apple? A joke! Oracle? Pfft!
At the same time I was working there, I was studying sales psychology. The books verified something I had already suspected: When you go negative in your advertising, the net effect is that the potential customer thinks more about the thing you’re being so negative about. (That explains why the “War on Drugs” actually increased usage of many drugs during its lifespan.)
I also made a friend in the sales department. Over lunch at In-N-Out Burger one day, he told me something interesting. He said, “I hear this over and over again–a large organization requests Sun, IBM, and others to make a presentation about their products. IBM is first. They show a great presentation about their product line. Then comes another vendor. They show up and do another fantastic presentation about how amazing their products are. Then it’s Sun’s turn. Sun does a presentation–about how awful everyone else’s products are!”
He continued, “The net effect is this. Most of these people have bought products from the company Sun’s presentation is bashing. So they get to thinking, ‘Well, IBM’s product isn’t as bad as Sun makes it out to be.’ And then, they go buy from IBM. We lose the sale, again and again and again.”
I was stunned. “Haven’t you taken this up with Sun’s management?” I asked. (Scott McNealy in particular practiced an “open door strategy” where he appeared to be responsive to suggestions.)
“Oh, yes,” he said. “But they don’t care. They like this sales strategy.”
Leading from the EgoIt was then that I realized two things: One, Sun was leading from an egotistical perspective of “we’re better than everyone else, and we’re going to prove it by bashing everyone else.” And it wasn’t making them many sales. Two, if they didn’t change, they weren’t going to survive as a company. Not only was the sales culture bad, but it created rot within the company as well. The company culture was oppressively negative, and it attracted people who enjoyed complaining and bashing others.
More importantly, though, I realized I had to take this to heart. When I ran my hosting company, I remembered this clearly. People loved to ask me, “Why are you better than [a competitor's name]?”
In response, I would always ask who they were hosting with now. If it was the same competitor they just named, I was careful to not bash the competitor–because that would be bashing the choice that they made. Instead of indulging my ego, I said, “I completely understand why you’ve made the choice you have. You wanted a good deal.”
Then I would find out what had happened that made them want to change hosting providers. If they were just shopping around for a better deal, I’d tell them honestly that we probably weren’t the best fit. But if something had happened–they’d had an outage recently, or they needed room to grow–that’s when I’d be able to go into my preferred sales strategy, which was showing them why we were a much better choice for them. I’d point out our redundant power, have them meet our employees, and do a datacenter tour. By the end of the tour, 90% of the time, they were ready to sign up with us. Then I wouldn’t hesitate to collect their credit card information and get them set up!
Despite its questionable company culture, working at Sun taught me a valuable lesson. You can’t serve your customers effectively when you’re busy bashing your competitors. And you can’t survive as a business (or as an ideal) if your main issue is “We’re not this other thing.”
What are you saying to your customers? Are you presenting your business in the best possible light–or inadvertently turning your customers toward a potential competitor?
Recommended Reading:
- One Million Dollars, The Hard Way. Ever wonder how I sold a business for $1.1 million? This post gives all the details.
- Are You Making This Common Mistake (That Could Ruin Your Business)? Here’s another big mistake (and a true story) that could really kill your business.
- How Writing a Story Could Strangle Your Business. What is “writing the story”? Are you doing it? If so, you could be leaving a lot of money on the table…
This feed is for personal, non-commercial use only.
The use of this feed on other websites breaches copyright. If this content is not in your news reader, it makes the page you are viewing an infringement of the copyright. (Digital Fingerprint:
ca01ca7aefbdcac4b8bbfff1994a3b42)
Linux / Open Source For Kids: A Feast of Riches
From Zero to OpenVPN in 30 Minutes
First Pic! Penguin Balloons at LinuxChixLA SCALE10x Exhibition Booth.
Neighboring exhibition booth, and Los Angeles area development and networking group Python Ladies, took this picture of our walking penguins at SCALE10x. Thanks and kudos to LinuxChix Los Angeles group member Betty for both original idea and the overall organization of ‘project inflatable’ for our LinuxChixLA booth’s popular give-aways.
You Don’t Lose When You Lose Fake Facebook Friends
Weekend Project: Loading Programs Into Arduino
Twitter Weekly Updates for 2012-01-22
- Saw the US Girl with the Dragon Tattoo movie. Apart from the gratuitous (but beautiful) intro, it was fantastic. Really well done
# - Yays!
RT @gavintapp: RT @maxious: Linux.conf.au 2013 Canberra (successful) bid website @ http://t.co/1xZykNtS #lca2012 # - #lca2012 was amazing. So many wonderful, inspiring, thought provoking, awesome ppl & discussions. Thx organisers, LA & every person there
# - Yes. I wanna red one
RT @emmajeans: @piawaugh This! http://t.co/rjCdKzUP # - Great point from @ioerror, encrypting data before you store it online helps with privacy/security issues of trusting the #cloud #lca2012 #
- "I have nothing to hide" is a fallacy or a matter of privilege. — @ioerror #lca2012 #
- .@ioerror talking about the panopticon and how people tend to self censor when they are under surveillance. See also Foucault. #lca2012 #
- .@ioerror just took a photo of the crowd. Obviously to identify ALL THE PEOPLE. #lca2012 #gettingparanoid #
- For those interested, the book ref'd last night is War on the Internet by @BernardKeane. I highly recommend. http://t.co/mltRTFp0 #lca2012 #
- Last night I had a dream. A dream my cast was on the wrong hand. I woke up trying to pull it off *over* fractured scaphoid. Ouch
#lca2012 # - .@nurhussein thanks, it's fantastic! Great content, ppl, discussions. It is wonderfully inspiring. #lca2012 #
- I didn't mean it quite like how it came out
RT @mibus: "With a name like Rusty, we had to get some type of tool…" — @piawaugh #lca2012 # - Cool RT @willozap: @piawaugh Ok, new way to start: Fun + Sarkozy: #society5 http://t.co/cVdh02nm http://t.co/t9d0dLbm http://t.co/sWaVur5L #
- Interesting article by @dannolan on the scope creep (im)balance of policing http://t.co/QiUsXlmZ #
- Elizabeth Garbee giving gr8 talk on astronomers trying to measure gravitational waves using millisecond pulsars. Ref'd Au SKA
#lca2012 # - RT @kim_weatherall: Paper shows patents impact scientific research http://t.co/7Kb3xYGd (scientists avoid projects impacted) #lca2012 #
- RT @kim_weatherall: This paper finds patents don't significantly help commercialization of inventions: http://t.co/Z5egwKiq #lca2012 #
- In open data BoF @aimee_maree talked about Got Gastro, great website. http://t.co/sOtiQTK1 #lca2012 #gov2au #
- Achieving open data: step 1) just publish, step 2) quality data (compliant systems, etc), step 3) collaborate #lca2012 http://t.co/x6EBDucM #
- Hey @kim_weatherall, @felix42 said you have some research/stats around patents in Australia. Anything you can share?
#lca2012 # - The Free Software Act, interesting idea. http://t.co/jJcvMe9U #lca2012 #
- Tridge says independent invention as a defense & interoperability as fair use are two mods that would improve patents system #lca2012 #
- Grin RT @patentology: FOSS headlines you will never see? What abt 'Blackburn decline Samba transfer request' http://t.co/2MIKrp2G #truestory #
- Powerful statement on #SOPA from xkcd. Nice. http://t.co/YIglzRMQ #
- Ta RT @trevclarke: @joshgnosis @j_hutch @gusworldau Slowest search ever, results for "open source" Herald Sun: http://t.co/UZ41UbkP #lca2012 #
- Handy tip from @gusworldau: press releases are useful but personalise them, tell the journo why they'd be interested #lca2012 #
- Handy tip for dealing with the press, press releases are useful but personalise them, tell the journo why they'd be interested #lca2012 #
- Point from @gusworldau on falsity of broad assumption ads always dictate content in tech media. #lca2012 #
- Linus' response to a media question from @gusworldau on how much it'd cost to get him to come to a geek party. #lca2012 http://t.co/Ypig34cD #
- "journalists like free speech, they like free beer, but don't always want to get into the complexities in between." @gusworldau #lca2012 #
- Fascinating, the top 10 tech media websites in Australia by @gusworldau #lca2012 http://t.co/9a7kxqIK #
- I think we have a good community of tech journos in Australia. Doesn't always translate to coverage says @gusworldau #lca2012 #
- Totally, voting now
RT @chrisjrn: Hey, @gusworldau's talk on tech journalism is fantastic. #lca2012 # - Angus' talk about FOSS & media. Hilarious & informative. Gets my vote
"The only way Linux would make the Sun Herald" http://t.co/Anqa5YCZ # - .@chrisjrn Hah! "With all due respect…" http://t.co/G4IEoSmp #talledaganights #lca2012 #
- Whenever people start effectively with "no offense, but…" I am entertained and mildly annoyed. Thanks audience member
#lca2012 # - Haha, jokes OH in @allisonrandal's talk: "man house", "apropos flush" #lca2012 #
- Accidentally stumbled across this surprisingly interesting article on "Australian egalitarianism", starting w language http://t.co/anAwrkvn #
- Karen's talk this morning has reminds me to turn off bluetooth/wireless on my phone now, and on my heart monitor later
#lca2012 # - Cool, RT to #lca2012 @lukeweston: @piawaugh: http://t.co/kAccnvxj #
- .@Alegrya Big difference between striving for great user experience (similarity) & lock-in Apple imposes vs what FOSS tries to do #lca2012 #
- .@ioerror Cool, thanks. Hey @supersat @aczeskis, is there a blog post or something about your car hacks?
/cc @lukeweston # - Scary RT @ej_butler: @hackuador @piawaugh Did you see this story last year? Insulin Pump hacked http://t.co/if6ngxwD #medtronic #lca2012 #
- Really enjoying the talk by Karen Sandler at #lca2012 Bring home the importance of software freedom to everyday life, esp health apps. #
- Hand is aching today. Too much typing & Tweeting
Retiring early to write blog & prepare for Martial Arts BoF tmrw morn at #lca2012
#fb # - Thanks @chrisjrn @kathyreid & @jaimekristene #
- OK, I've forgotten and can't quickly find this on the wiki, how do I vote for talks for the "Best Of" slots at #lca2012
# - Fantastic talk by Bdale Garbee about FreedomBox, a great idea to make privacy easy for people online. This gets my vote
#lca2012 # - Wikipedia has gone dark to protest SOPA. Fascinating. Be great to get stats after the blackout on how many click throughs & such #lca2012 #
- For those I've chatted to about #society5 I've some early thoughts in my blog last year http://t.co/CWgkLcZt #lca2012 More coming v soon
# - Hey @paulzee, you can see most tech related stuff from the last federal budget here http://t.co/HhJVwtrt #lca2012 #
- OMG PWNIES!
#lca2012 @caseopaya: @piawaugh link for you http://t.co/lEVUHaym # - If ppl want to read great book on critical thinking & failure (even in science!) read @tribalscientist's book http://t.co/q7sOuFAX #lca2012 #
- Actually, bridge experiment isn't taking into account the variable of person type choosing to take a scary bridge vs safe bridge. #lca2012 #
- Playing Tetris interferes with long term memory, scientifically proven apparently. Wow. That will be useful
#lca2012 # - Listening to @pjf reminds me of Gladwell's Tipping point. Recognising different traits helps your project "connectors, mavens & salespeople" #
- Hey @tribalscientist, @pjf is giving kenote (now) at #lca2012 & referencing the chicken and shovel split brain experiment
You might enjoy # - Interesting analogy between taxes and club membership. Comments are quite diverse too. http://t.co/CPqmRWLz #
- Also for @chrisjrn, other #lca2012 peeps may enjoy the Glenn Beck Conspiracy Theory Generator
http://t.co/5d1UxIHM # - Yo @chrisjrn, you can find that song in my soundcloud favs http://t.co/Z5lhNzm3 "Burn (Angel of Destruction Mix) by TweakerRay" #
- POLICY CIRCLES is interesting (made for Pacific consultation). Ppl might also be interested in #publicsphere http://t.co/zvI5NUPu #lca2012 #
- Hearing about Pacific Institute of Public Policy http://t.co/V5XK93fL & Policy Circles http://t.co/Ky9UinMB Interesting projects #lca2012 #
- Excited about the mix of martial arts lined up for the Martial Arts BoF. Come along if you are interested
http://t.co/Ar5Y3aPi #lca2012 # - Interesting point from POLICY CIRCLES talk at #lca2012 "People are torn between the desire for peace and desire for justice". #
- .@purserj Ah, BOFH culture, it is a dangerous and seductive path to darkness. Resist the user-hate people!
/cc @shorebuck # - I think there's something in that for all of us. RT @shorebuck as a user you can hate an editor. As tech support you can hate all of them (: #
- Whenever I use OpenOffice I am reminded how annoying it can be. For the smug out there MSOffice is no better. I should stick to vim #lca2012 #
- For @ajtowns, this is stunning! Manual 3D printing of fish -> painted layers between layers of resin. http://t.co/VVAXyEy5 #lca2012 #
- Interesting read "APS employees have the same right to freedom of expression as other members of the community" http://t.co/aneyG1gd #gov2au #
- Just linking to the Sarkozy speech for ppls interest, which I'm going over again for research. http://t.co/tA6y0EDM /cc @willozap #society5 #
- Yes! RT @kattekrab: RT @rillian: #lca2012 remains an awesome group of people. #
- Watching movie reader that describes video content as it plays. Demo is Elephants Dream which is hard to understand regardless
#lca2012 # - Really excited about @ioerror's talk Friday. Might feed into a project I'm working on atm so hoping to chat. Watch this space
#lca2012 # - Martial arts geeks at #lca2012 - Come to the Martial Arts BOF Thurs morn to train & share
http://t.co/bjjOzUyY # - In multimedia miniconf. Jan makes a good point: DRM fundamentally flawed because limiting access to content you want ppl to access. #lca2012 #
- Relevant to Haecksen #lca2012 RT @PennySharpemlc: From US: why women don't want to run for elected office. Worth a read http://t.co/5WjeEQmP #
- Stunning RT @neerav: wow 1 of my photos (full moon last wk) http://t.co/ao3RR66Z was featured on the Flickr "Interesting" page. 1515 views #
- Awesomes RT @BronyRT: RT @nekonoir: Linux + Bronies = all the squee #lca2012 #mylittlepony http://t.co/30RPmfV7 #
- Tmrw I will bring my pwnies tshirt
RT @Tempestrix: Why are there ponies? #lca2012 #sysadminconf # - .@weezmgk ah, thanks
and to the rest of you too
# - In Haecksen miniconf at #lca2012 listening to stats on female representation at lca & of speakers. We have gone from 0% to 23% speakers
# - Arrived at #lca2012 in time for the conf opening. Yays! I'll be tweeting this week about the conf, mostly just thoughts/links/blogs
# - Interesting. Kind or kid? RT @bengrubb: Aussie wunderkind gets $US250k for technology that could revolutionise web http://t.co/1ds0Qtsr #
- Hah!
RT @linuxconfau: @piawaugh Safe travels Pia! We'd say break a leg, but we don't want to risk it
# - One for @johnf
Moosli from the plane. http://t.co/O1ynQDPo # - One for @johnf
Moosli from the plane. null # - Now just a bus ride away from #lca2012 Woot! #
- On my way to #lca2012 Early start but it's a long way to Ballarat
Will blog the week as usual. #

