Emission pattern of Sr90 disk

As part of my Black Box project, I purchased a small sample of Strontium-90. Targeted at the testing/educational markets, these samples are license exempt (in the US, at least), and can be purchased from an educational retailer for ~80$. To make them safe to handle, a common form-factor for these samples is an acrylic disk measuring 1″ in diameter, and 1/8″ thick. A hole is drilled partway through the center of the disk, where the radioactive source is evaporated/condensed and potted in place with epoxy. This yields a thin disk of source material, completely encased and safe to use.


While I was experimenting with it for the Black Box, I developed a hunch that this sample did not emit uniform radiation. That is, some viewing angles would produce higher count-rates than others. This wasn’t an issue for the project, and thus I did not spend the time to investigate. But now that its done, and I have more time, I figured I’d investigate.

I collected this information by mounting the sample on a spinning arm in front of a MightyOhm Geiger counter. Since the Geiger tube is physically larger than the sample, I placed an aluminum shield with an 1/8″ pinhole between the sample and the counter. This ensures that the counter only ever observes a single angle at a time, making for finer, less “averaged” data. The counter is connected to a computer via its serial header and an FTDI adapter.


I collected counts for 5 minutes at 7.5 degree rotation increments. The CPM values were computed from the counter’s CPS values, to avoid having to wait an extra minute between samples for the buffers to roll. After ~6 hours of data collection and fighting with gnuplot, here’s what I found:


As I had guessed, the distribution is non-uniform, though I had no idea it was that non-uniform. There is close to no radiation emitted from the sides of the disk (for reference, the white hole in the center of the graph is my measurement of background radiation). I presume this is a combination of the extra acrylic acting as a shield, and the reduced surface area of the Strontium due to viewing it end-on. Curiously, the sample also emits more radiation from its bottom (non-label side) than it does from it’s top. Either the hole was drilled further than half-way through the acrylic, or the epoxy and label may be a better shielding material than the acrylic. Or both.

You can find my data and my plot file in this gist.

Inspecting Qt’s object hierarchy

Coming from web development, one of the most frustrating things about writing QSS (Qt’s version of CSS) is the lack of an inspector. In a browser, it’s trivial to design selectors by simply pawing through the DOM. Qt arranges its QObjects in a similar hierarchy, but the only way I’ve found to display it (in its entirety) is to load everything into QtCreator. This is slow and sometimes painful, when all I want is a simple text dump. So I built a small tool specifically for recursing a given QObject, and dumping it’s hierarchy to the terminal. Here is an example of using it to print the structure of an entire Qt application:

#include "mainwindow.h"
#include <QApplication>
#include "inspect.h" //you'll need this

int main(int argc, char *argv[])
    QApplication app(argc, argv);

    MainWindow win;
    inspect(&win); //prints hierarchy to stderr

    return app.exec();

Enabling QDebug on Fedora Linux

When writing Qt applications, it’s helpful to use a qDebug() statement once in a while. However, I’ve recently found that qDebug() on stock Fedora no longer prints, while qWarning() does. The first thing that the internet tells you is to add CONFIG += console to your .pro file, but alas, this is not the solution. It turns out, because of the way Qt is setup on Fedora, debug output is no longer emitted on stderr (by design). Thanks to this bug report, the solution is to create the following file in either of these locations:

  • ~/.config/QtProject/qtlogging.ini (for your user only)
  • /etc/xdg/QtProject/qtlogging.ini (system-wide)

The first rule enables all debug output, while the second disables Qt’s internal debug statements. This prevents a deluge of output from Qt when debugging your application.

Automating your homework with OpenCV

As an elective during my senior year of college, I chose to take Introduction to Geospatial Technologies. A mildly interesting class, but one assignment really got on my nerves. The assignment was to digitize the following image


It’s a square-mile slice of Rochester NY, just north of my campus, showing specifications for that regions sewer system. The image above is scaled down considerably; The original is 11249×9152 pixels. Our assignment was to digitize the entirety of the sewer details in this image. If you look closely, you’ll see lines (pipes) with dots (manholes) running down the centers of each street. Yup, we were supposed to digitize all of that, including all associated numbers, by hand.

I don’t like being used as a click farm under the guise of “education.” I learned how to plot points and draw lines in middle school, thank you very much. Besides, whenever I see lots of repetitive work, my automation alarms start going off. So I decided to try and tackle the problem with computer vision.

Along with this image, we were given a vector centerlines file describing the configuration of the roads. Since most of the sewer pipes stay inline with the roads, I thought it best to locate the manholes first, and use them to split the centerlines into segments.

Before going into computer vision, it’s worth a little time to pre-process the image. I brought the massive TIFF into gimp, where I applied a slight blur, and tweaked the levels until it was truly black & white. The purpose of the blur was to fight significant noise in the image that was akin to dithering patterns. Since I’ll be doing blob detection later, it helps to have everything be as contiguous as possible.

Then, in an OpenCV application, the image is inverted, and a distance transform is applied. In a nutshell, a distance transform is an operation that leaves thicker (lit) regions shaded brighter, causing thin features to receed into the dark background. Its effect, from a color-value standpoint, is extremely subtle, but with some simple ranging, you can use it to produce images such as this:


You can see that it does a decent job at locating the manhole dots I was after. With some additional ranging, you can eleminate the darker background information, leaving only the bright manhole dots. These can then be fed into OpenCV’s SimpleBlobDetector to get pixel coordinates.

After some value-tweaking, I got this working suprisingly well, and sucessfully located 689 blobs. However, it would still produce the occassional false positives, ussually having to do with the arrows on the lines between manholes. To weed these out, I wrote another quick application that shows me each potential manhole, and allows me to accept or reject it. This went quicker than I thought it would (about 5 minutes), and gave me a final list of 519 manholes. Not a great false-positive rate, but I intentionally set the detector with wider margins, hoping to miss less true positives.

After putting these pixel coordinates into a GeoJSON file as “Features”, I then took to ArcMap for its georeferencing facilities. Georeferencing is the act of matching up the pixel values of an image with the coordinates (feet) of the real world (which are specified in the centerlines file). Using 4 anchor points, you can compute the affine transform that maps your image onto the world. After aligning and finding these anchor points in ArcMap, I used GDAL’s ogr2ogr utility to process my GeoJSON file.

ogr2ogr -f "GeoJSON" world_nodes.json \
-gcp 2431 241 1396527.486 1156707.409 \
-gcp 10592 247 1402186.618 1156770.797 \
-gcp 2396 8909 1396559.438 1150970.182 \
-gcp 10931 8908 1402226.101 1151037.144 \

Now, with my manholes in world-space, I wrote a small python script to slice up the centerlines file into individual segments of sewer pipe. This involved finding the manholes on a given line (using perpendicular distance), and subdividing that line into smaller segments, starting or ending on a manhole.

Augmented Reality Sandbox

I recently got the opportunity to help setup an Augmented Reality Sandbox. Written by some folks at UC Davis, the AR Sandbox is an interactive tool for teaching topographic maps. It consists of a projector and a Microsoft Kinect mounted above a ~3×4 foot sandbox. Using depth information from the Kinect, the topography of the sand is scanned, and the correct contour lines are projected onto the sand’s surface.


The software consists of a VR toolkit, a Kinect driver, and the Sandbox itself, all of which are open source (GPL v2). So far, we’ve successfully installed it on Linux Mint and Fedora. Massive thanks to the guys at UC Davis for making a great teaching tool, and for releasing it open source.

And yes, it is exactly as much fun to play with as it looks.

Building a spot welder

Over christmas break, me and my family attempted to turn a cheap, off the shelf stick welder into a spot welder for home use.


The original welder in question was a 70 Amp Vaper Arc Welder, purchased for ~80$ at Pep Boys on a whim. It’s terrible at its intended function, so there was no harm in trying to get it to perform another. After popping the lid, it was fairly easy to rip out the existing secondary coil. We rewound it with 3 turns of some spare 4 gauge cable.


We measured the dead-short current to be 995 Amps. The meter at right shows the welder’s input current to be a solid ~20 Amps. Plenty happy with that figure, and after some promising trials at welding thin sheet metal, we decided to build our own electrode jaw assembly.


Trying to keep it fairly small and portable, we opted to build off to the side of welder (it’s plenty heavy enough to serve as a base). The arms are made of 1/2″ aluminum U-channel, with a simple plastic cam mechanism to open and close the top arm. While the aluminum is electrified, we decided to add runs of 4 gauge wire to carry the bulk of the current.


The tips we used are from a MIG welder, as these turned out to be markedly cheaper than bonefied spot welding tips. They are attached to the arms and the 4 gauge with copper grounding lugs.

While we had some small success with welding thin scraps of sheet steel before, this did not translate into our final setup. We saw a dramatic decrease in amperage and welding ability, presumably due to the extra losses incurred by the extra copper/fittings/cable now in the mix. Either the original machine was too small to begin with, or we need one or two more turns of 4 gauge on the secondary coil (or both).

Either way, still a lot of high voltage fun.

Compiling LemmaGen on Linux

I recently ran into a few problems compiling LemmaGen v2.2 (C++) on my linux machine. Turns out, it was a bunch of simple fixes, so I made a patch file. I’ve sent word to the project maintainer, but haven’t heard anything as of yet. So, in the mean time, I’ll post it here:


To apply the patch, go to the project’s root directory, and run:
$ patch -p1 < [path_to_patch_file]


  • Missing a few includes for C functions (such as cstring, and climits)
  • Fixed the case on InterXVal files (windows ignores filename case, but linux does not)
  • (RAND_MAX + 1) caused an overflow, using plain RAND_MAX instead