Introducing GANce

In collaboration with Won Pound for his forthcoming album release via minaret records I was recently commissioned to lead an expedition into latent space, encountering intelligences of my own haphazard creation.

A word of warning:

This and subsequent posts as well as the GitHub etc. should be considered toy projects. Development thus far has been results-oriented, with my git HEAD following the confusing and exciting. The goal was to make interesting artistic assets for Won’s release, with as little bandwidth as possible devoted to overthinking the engineering side. This is a fun role-reversal, typically the things that leave my studio look more like brushes than paintings. In publishing this work, the expected outcome is also inverted from my typical desire to share engineering techniques and methods; I hope my sharing the results shifts your perspective on the possible ways to bushwhack through latent space.

So, with that out of the way the following post is a summary of development progress thus far. Here’s a demo:

There are a few repositories associated with this work:

  • GANce, the tool that creates the output images seen throughout this post.
  • Pitraiture, the utility to capture portraits for training.

If you’re uninterested in the hardware/software configurations for image capture and GPU work, you should skip to Synthesizing Images.

Continue reading →

The Silent Dripper

The first revision of this project was shipped in November of 2020, but the subsequent redesign was commissioned and completed the following summer in 2021. This post primarily a journey through that second revision, and it’s publication comes some time after the deliverable was shipped to the client.

Engineering requirements that arrive downstream from artistic intent are my favorite constraints to work inside of. It forces the engineer to assume the role of the artist, considering the feelings and ideas that will be communicated to the audience with the piece. The engineer also has to become an audience member to understand other factors about how viewing will take place, if the environment will change such that the piece needs to respond in kind. The space in between these to roles needs to be projected into the standard space of product requirements, weights, tolerances, latencies etc. that are common in the profession.

As a part of my freelance practice, interdisciplinary artist Sara Dittrich and I recently collaborated on a series of projects, adding to our shared body of work. The most technically challenging part of these most recent works was a component of her piece called The Tender Interval. I urge you to go read her documentation on this project, there is a great video overview as well.

Two performers sit at a table across from each other, above them is an IV stand with two containers full of water. Embedded in the table are two fingerprint sensors, one for each of the people seated at the table. Performers place their hands on the table, with their index fingers covering the sensors. Each time their heart beats, their container emits a single drop of water, which falls from above them into a glass placed next to them on the table. Once their glass fills, they drink the water. Optionally, virtual viewers on twitch can take the place of the second performer by sending commands on twitch that deposit water droplets into the second glass.

Design and manufacture of table and this insert were completed by Sara Dittrich

The device responsible for creating the water droplets (the dripper) ended up being a very technically demanding object to create. The preeminent cause of this difficulty was the requirement that it operate in complete silence. Since the first showings of this piece were done virtually due to the pandemic, we were able to punt this problem and get the around noisy operating levels of V1 using strategic microphone placement. However, this piece would eventually be shown in a gallery setting, which would require totally silent operation.

The following is a feature overview and demonstration of the completed silent dripper:

If you’re interested in building one of these to add to your own projects, there is a github organization that contains the:

Per usual, please send along photos of rebuilds of this project. Submit PRs if you have improvements, or open issues if your run into problems along the way.

The rest of this post will be a deep dive into earlier iterations of this project, and an closer look at the design details and challenges of the final design. It’s easier to understand why a second iteration was needed after reviewing the shortcomings of version 1, so that’s where we’ll start.

Continue reading →

High performance GPU cooler for the NVIDIA Tesla K80

Here’s a (long winded) video overview of this project:


Rendered desperate for VRAM by a forthcoming stylegan-related project, I recently had to wade thermistor first into the concernedly hot and strange world of GPUs without video outputs to design a high performance cooler for the NVIDIA Tesla K80.

Too esoteric to game on, and too power hungry to mine cryptocurrencies with, the K80 (allegedly the ‘The World’s Most Popular GPU’) can be had for under $250 USD on ebay, a far cry from it’s imperial MSRP of $5000. By my math, the card is one of the most cost-efficient ways to avail one’s self of video ram by the dozen of gigabytes.

This sounds great on paper, but actually getting one of these configured to do useful work is a kind of a project in, and of itself. I’ll eventually get to this in the aforementioned upcoming post. Today’s topic however, is upstream of all that: the task of keeping these things cool.

Continue reading →

3D Printed Pen + Notebook Organizer

There have been a few posts on this blog about the functional benefits of using printed parts to join existing objects in a reliable and precise way. Most of the time my printed parts themselves look strange. The goals are usually printability and a clean assembly of printed and non-printed. As an attempt to buck this trend,  I recently designed and manufactured a desktop organizer that showcases the medium’s ability to bond objects and also look great.

Created as a birthday project for a family member, this piece is designed to poke fun at the concept of a desktop organizer. We’ll typically deploy this type of item in trying to declutter our workspaces, filing away assorted pens, paperclips, calculators etc. I actually created a really simple one some time ago to do just this, containing the mess rather than dealing with it.

This new design, however, is deliberately designed only to hold one type of pen and one type of notebook and absolutely nothing else. This denies the user the ability to create more chaos and enforces organization.

The pens and notebooks are a favorite brand of the recipient and myself.

I  printed the parts out of PLA. The green rim and white base are two different parts, held together with hot glue.

I printed the parts on my close-to-death Prusa i3 MK2S.


Thanks for reading! As this project was a gift I’m hesitant to release CAD like I typically do. However if you absolutely must have one, send me a note and we can work something out.

A 3D printed solution for storing a Valve Index on a wire shelf

Looking for a wall mounted version of the HMD mount? Check out this remix on thingiverse (thanks Sean)!

Here’s a video going over the design:

The printed parts can all be found on thingiverse here. Please let me know if you use any of these! I’d love to talk about potential improvements that could be made.

For fastening hardware, everything is available on McMaster:

This is most likely the shelf at the center of the design: I purchased it years and years ago, so things about the design could have changed. In any case, the pole hooks could be redesigned to fit almost any shelf.

Valve has done an amazing thing by publishing these files to GitHub for all of us to use. The existence of these files informed my decision to go with the index more than any of the technical specifications did. You should go star the repo if you enjoyed this video to show that Valve is doing a good thing by publishing these designs. The repo is here:

Here are some more photos showing additional angles of the printed parts:

This is the transcript used in the video. Thanks for reading:

Here’s my 3D printed solution for storing a Valve Index on a wire shelf.

It features:

  • A charging station for the knuckles.
  • Uniform support for the HMD that also protects against light damage without using lens covers.
  • A very sophisticated cable bucket
  • And strain relief for the connection between the HMD and my graphics card.

And is all way-way-way over-engineered.

The purpose of this video is to run through the design highlights for each of these components, but if you’re just interested in the CAD files there’s a link to a blog post with all of that and more in the description of this video.

Right… Let’s start with the HMD mount.

As I record this, the model that Valve published on GitHub was for the plastic piece that mates to the head mounted display, it did not include the cushion that sits on the user’s face.

Reason being is because the cushion piece is probably what Valve anticipates people wanting to re-design. So, for 99% of the reasons why you’d want this model in the first place, this is totally adequate. But in this case, trying to model an inverted version of the foam piece, there was a lot of guesswork involved, hundreds of hours of print time worth of guesswork.

Even once it was clear that the HMD was fitting correctly, it didn’t really “slot” into place the way it fits on my head.

That’s what the purpose of the “bubble” across the middle is. When loaded, the cushion material collects around the base of the bubble forcing a more concentric mate.

If you’re considering working on a project like I urge you to just copy this geometry. It’s really tough to get the feel of this part right.

The shelf part was much easier, I don’t know if I love the look of the ribs but they were quick to print and will be able to easily support the load over time.

The two components are held together with threaded inserts and m3 machine screws.

The next part I designed was the Knuckles slots.

The huge swept semicircle on the outside of the controller is amazing. It moves the center of gravity right to where it needs to be.

These controllers are without a doubt the most elegant way I’ve ever interacted with a machine. The sensors, motors batteries, every element of the design leap’s out of the way of the user’s experience.

This semicircle is also the basis for the slots on this part. It was a nice constant geometry that was easy to understand and model around.

Having these swept cuts continue through the base of the plate allows access to the USB ports. Conceptually, this keeps the front facing experience clean of wires, but my shelf is so busy with those anyways that it doesn’t really matter at all.

Next is what I’m calling “The Bucket”

Originally this was going to be something akin to a marine cleat, but that idea didn’t make it onto the printer and even saying that out loud at this point sounds kinda dumb.

Using a loose coil like this makes sure the cable doesn’t get kinked or twisted while in storage. It also comes out quickly when you have a few minutes between work calls.

The clamp at the bottom of the plate holds the PC side of the cable in place.

In my opinion, this is the part of the index’s design that could use the most improvement. It seems dangerous to have high end PCs connected without mechanical relief to people running away from headcrabs or dodging laser blasts.

This way the replaceable cable will get damaged before the graphics card or motherboard attached to it does.

The last part of the design is the pole hooks. These attach the plates for each of the other components to the wire rack.

The fitting took a few design iterations, the goal was to be able to install these by hand, but make it really difficult to remove so they wouldn’t fall off.

They’re angled away from the shelf, making the plates come out of the shelf which looks nice, and makes it easy to grab the peripherals.

Instead of two through holes to mate the two pieces together, I used a through hole and a slot here that provides a little bit of wiggle room to compensate for fitting problems shelf to shelf.

Also, I don’t know if the shelf I have is a standard size or anything, but having these pieces be discrete means all you’d have to do is re-design this part for your shelf rather than the whole system.

This part will also get used in other projects around the studio, I’ve been meaning to build a huge filament spool holder for a while and these will be able to provide the mechanical load for that no problem.

So that does it. Like I mentioned earlier, there’s a link to a blog post with the CAD files and links to the fastening hardware used in the build if this is something you’re interested in making yourself.

If you end up using these parts, particularly the HMD mount in another build let me know – it would be exciting to see.

If you don’t have a printer, shoot me a note and I’ll see if I can mail you some parts or something.

Alright! Thanks for watching!

Quickly drawing grids of rectangles, and updating their colors with VisPy

Here’s a demo run of the code:


From the VisPy website:

VisPy is a Python library for interactive scientific visualization that is designed to be fast, scalable, and easy to use.

While looking for a near real time data visualization alternative to the venerable matplotlib, I came across this jaw dropping demo:

Absolutely insane, achieving that kind of performance in python is amazing to say the least. This demo in particular seems like it would be more likely to come from a pygame application at the least, but looks more like it would be a Unity project.

The VisPy project is massive, but luckily, there is a set of really good examples included in the repo. Reminds me of the Arduino standard library in this way. After through all of running these, I didn’t find exactly what I was looking for.

For how simple the finished product looks, the learning curve on the way there was surprisingly steep. Hopefully this post saves you some time.

Code + Explanation

I’d like to be able to draw a grid n * n rectangles, and control their side lengths and the amount of space between them. Being able to update the color of the rectangle is also a requirement.

The goal is to be able to visualize audio signals on a low resolution grid of LEDs.
This software is to be the basis for iterating on ideas and working out bugs without having to redesign hardware.

This example uses a single vispy.visuals.collections.PolygonCollection object to draw the rectangles rather than using a bunch of RectangleVisual objects. Moreover, I found that once there were hundreds of these RectangleVisual objects, I could not achieve the FPS range I was after.  Searching online, I found an explanation for this here:

Any solution that requires more than 10 visuals will perform terribly as it requires a separate GL program for each visual. Each program is drawn sequentially so it takes the GPU a long time to get through each one. It would be best to have one visual that draws all of these rectangles with the appropriate color (I’d never heard of a wafermap before)

So reader, if you’re working on something similar, I hope this snippet is a good starting point:

With a grid of 100 x 100, I’m able update the visual at ~30 FPS, which is way more that I would ever need for my application. If you wanted to extend this to more objects, it seems like the bet approach is to use markers.

Thanks for reading.

How to host private Python packages on Bitbucket for free, AND how to use them in a circleci pipeline

Bitbucket is great for hosting private git repos. Turns out, it can also be used to turn those repos into python packages that you can integrate into your projects with pip. This took a bit of trial and effort to make happen, let me know if there is anything additional you had to do to get things working on your end and I can add them to the guide.


This whole process is built on pip’s ability to install packages from common VCS’s using SSH keys for access credentials. The syntax for doing that looks like this:

Pretty slick, you can even specify a branch or tag:

Since this repo is public, let’s try installing the package into a python virtual environment:

No dice. It didn’t work because our development environment isn’t configured correctly. Let’s get started with the guide.

Using private repo packages locally

Note: I’m on ubuntu 18.04, but I will leave Windows notes in each step if applicable.

Step 1: Make sure your repo CAN be installed as a python package

The key here is a proper file. Here are best the best set of docs I’ve found on how to make this file.
You can also look at the test repo for this project (, it contains an example This repo will also be the standard example for this post.
To make sure things are working correctly, you can try installing the package into your local python environment, or into a virtual one like I’m doing. Using sample_project as an example, we can do this like so:

If your package behaves as expected when installed like this locally, you’re all set to push the changes to your bitbucket repo and continue with the rest of the guide.

Step 2: Create SSH keys and add them to bitbucket

Note: at a few places in this step I use my own email as a reference, Make sure whenever you see that, to substitute email address associated with your bitbucket account.
If you already have ssh keys created on your computer or whatever you’re developing on, they should be located at ~/.ssh. If you don’t see both id_rsa and files in that directory, create them with:

Leave passphrase blank.
Now, copy the contents of ~/.ssh/ to bitbucket. The following images should walk you through the steps, make sure to give the key a memorable name.
Now, the ssh key of whatever dev environment you’re on is added to bitbucket.

Windows steps to create ssh keys

I followed these two (1, 2) guides to create ssh keys on windows.
The short version goes something like this:

Then follow the step above to add the keys to your bitbucket account.

Step 3: Make sure your account can read from the private repo with your python package

This is a simple, but a trap for young players. Make sure the account you’re trying to install the module with has at least read settings on the repo.

Since the Devon account is an owner of the repo, it will be allowed to read from the repo. The account ci_bot will also be able to read from the repo because it has read permissions.

Step 4: Install the package from bitbucket

With the bitbucket repo permissions set, and your SSH key added to your bitbucket account, you should be able to re-run the installation command from earlier and use the package.

Fantastic! Remember, your pip command git+ssh:// will be different for your package. It will look something like this: git+ssh://{your username}/{your project}.git.

Any user that you give read permissions to on the repo will be able to install your package as well. This includes a machine user, so your CI builds can use your private package as well, which I’ll show you how to do next.

Using private repo packages in circleci

Bitbucket and circleci go together like peanut butter and chocolate. Adding CI to a bitbucket project is made fast and easy using circleci.

Step 5: Create a “machine user” in bitbucket

This user should have read only access to the package repo that you want to add to ci, so in this example it’s the sample_project repo.
You can accomplish this very easy through the BB ui, just make sure to keep track of whatever username and password you decide on.
Just to be clear, a machine user is just a regular bitbucket user that is only used by machines.

Step 6: Create SSH keys and add them to your machine user’s account

On whatever you system you have been using so far, enter the following commands and remember to leave passphrase blank.

Add the contents of ~/.ssh/ci_bot_keys/ to bitbucket while signed in as your machine user like we did in step 2.

Step 7: Try git+ssh key insertion locally

(Note: you can skip this step, but if things don’t work when you add the step to your CI build start looking for errors here.)

By setting the environment variable GIT_SSH_COMMAND you can select which SSH key gets used by pip when doing an ssh pull.
Let’s try out the concept, and try out our new key locally. Run these two commands:

And then install your project like you did before. The package should install no problem, and you should see the same output as step 4.

Step 8: Set the $KEY environment variable in circleci

We now want to make the private key we made for our ci bot (~/.ssh/ci_bot_keys/id_rsa) available to the circle build process.
The only tricky part here is that the private key will contain newlines. For simplicity, we can replace them with underscores, and add the newlines back in the circle build.
Copy the output of this command to your clipboard:

The output ends after -----END RSA PRIVATE KEY-----_ in case your terminal doesn’t wrap correctly.
Now we need to set this value to the env var $KEY in the circleci build that we are trying to use our private package (sample_project) in.
Click the gear on the project page for your project in circle. For me, this brought me to, where crossbow is the name of my project.
Go to build settings -> Environment Variables and then set the variable like so:

Now that the variable is set, we need to change our circle config to use it.

Step 9: Add the step to your /.circleci/config.yml file

This does the same thing that we just tried locally, but in circle.
You have to make sure that the export GIT_SSH_COMMAND step happens in the same step as any pip commands. Your full  dependencies  installation circle step may look something like this:

Make sure you select a circle image that has a git version of 2.17.0 or later, or this step will fail without an explanation. I found that the python image of circleci/python:3.7-buster worked when testing.

Try running your job, with this step added, it should be able to pull the package from your private repo. Let me know if you run into issues and I can try to help you out. Maybe donate the money you saved on hosting fees to me via paypal? 🤷💖

Thanks to


How to panelize KiCAD designs for free

Panelization is the process of taking two or more PCB designs and combining them using tabs or v-scores that you would then separate into individual boards once they come back from manufacturing. It’s a way to get more than one design made in a single order.

There are a few forum posts or other snippets on how to accomplish this out there already, but not a real guide. For my own sake, this is how you can do this panelization using all free tools. Here are some photos of a board I had fabricated by OSH Park using this panelization method:

I implement this technique whenever I’m creating closely-related PCBs.

The design highlighted in this blog post is a transmitter/receiver pair, meaning that there would never be a transmitter without a receiver, or vice-versa.

Design is made simple by doing the layouts individually, and manufacturing is made simple by getting them made as a single board, not having to coordinate multiple orders. Let’s get started with the guide.

1. Download The Tools

You probably already have KiCAD. Next, make sure to download GerberPanelizer by This is not Rocket Science (site link) from GitHub. This guide uses the 2018-08-10 snapshot release.

2. Export your designs from KiCAD

Your designs have to be completely ready for production before starting this process. Components placed, tracks laid, zones poured etc. It is very “one-way” in that it is impossible to update an already panelized design once it has been exported.

Here’s one of the designs that will be added to the panel.

You’ll want to add a grid origin that is really close to your design. In KiCAD, select placegrid origin to do this. I am putting it in the top left hand corner of the board.

Grid origin placed

In pcbnew, select fileplot to adjust the gerber export settings.

  1. Make sure Output directory is set to an empty directory somewhere on your disk. In this example, it’s set to tx-gerbers.
  2. Check Use auxiliary axis as origin
  3. Check Use Protel filename extensions
  4. *Optional* Since I’m not using them in this design, I’ve unchecked F.Paste and B.Paste.

And then click Plot.

You should be greeted with a directory of files with dissimilar extensions:

Next, you need to export the .drlfiles.

Select filefabrication outputsDrill (.drl) File...

These settings will automatically be set to match the previous export, but make sure the output folder and the drill origin match the previous settings. Mine looked like this:

Here is my resulting output directory with all of the files:

3. Modify the exported files

This step is weird. You need to change the extension of all .gm1 files to .gko. For this example, flail-tx-kicad-Edge_Cuts.gm1 needs to be renamed to flail-tx-kicad-Edge_Cuts.gko as this is what GerberPanelizer expects. Here is my resulting directory:

Notice the .gko file

4. Load the designs into Gerber Panelizer

Open up GerberPanelizer, you will be greeted with this screen:

Select filenew to create a new project. Next, select board placementadd gerber folder and navigate to the output folder from KiCAD. In this example, it was tx-gerbers.

You should be seeing something like this:

Where is the board?! Select board placementautopack: native and your design will leap into view:

Now, re-do the guide up until this point for however many unique designs you want to add to this panel. If you want to duplicate your design multiple times in the same panel, you can add an instance by right clicking on the instance in the right hand view and then clicking add instance.

5. Arrange designs and add tabs

Since you’ve been hitting board placementautopack: native after each board add, your designs should be properly arranged at this point. You can manually move the designs by clicking and dragging them, but I’ve found that using the autopack works really really well. Here’s what my design looks like at this point:

To join the designs together, you need to add breaktabs.

Select breaktabsinsert breaktab, and a small red circle will appear in the top left hand corner of the workspace:

Click and drag the tab between the two designs. Make sure black dots appear on either edge of the design:

Continue to add tabs in the same manner until the text turns a bright green color, this lets you know that the boards will be secured.

There is no way to automatically add the proper tabs, so make sure you use your best judgement.

Now we’re ready to export!

6. Export the panelized design

It’s a good idea to first save the design in GerberPanelizer so you can edit the layout later without having to start from scratch. Once you export the final merged gerber files, they cannot be edited or re-arranged. Select filesave as to save the project.

Now to export the gerbers.

Again, in GerberPanelizer, select fileexport merged gerbers and choose an empty output directory. The directory has to be empty because you typically send a zip archive of all gerbers to the manufacturer to get made, and this zip archive should just include this export. You should see this window pop up:

The contents of the merged output directory should look like this:

The merged output directory will include several image renderings of your merged designs, this is a great first check to make sure that everything went well.

Looks good! However before you send any critical designs off for manufacturing it’s best practice to visually inspect the layers with a gerber viewer. Save the merged output directory as a .zip file.

7. Verify using GerbView

KiCAD ships with a program called GerbView to inspect gerber files. Open that gerbview and then open your zipped merged output directory with fileopen zip archive file.

There will be an error message which you can ignore.

You should see something like this:

There’s the design as we expect it, you can uncheck the different layers on the right pane just like in pcbnew to inspect them one by one. I’ve uploaded this design to oshpark (a domestic PCB fab service) to see if their preview also looks correct and again, there are no problems.

You’re now ready to send your panelized designs out for manufacturing. Congrats!

8. Wrap up

Thanks for reading! Did this guide work for you? Let me know in the comments below this post.

Note: This is confirmed to work with KiCAD 4 and 5.


Play multiple sound files on multiple output devices with Python and sounddevice

Ever wanted to have multiple different sound files playing on different output devices attached to a host computer? Say you’re writing a DJing application where you want one mix for headphones and one for the speakers. Or you’re doing some sort of kiosk or art installation where you have many sets of speakers that need to all be playing their own sound file but the whole thing needs to be synchronized. This would even be cool for something like an escape room.

The ladder example is where I needed this bit of code. I’ve been working with interdisciplinary artist Sara Dittrich on a few projects recently and she asked if I could come up with a way to play 8 different mono sound files on 8 different loudspeakers. Here’s a video of the whole setup in action, and an explanation of the project:

I’ve wrapped up all of the code for the art installation project, and that can be found in a github repo here. It includes the startup functionality etc. If you’re interested in recreating the video above, that repo would be a good starting place. The following is a list of the parts used to make that build happen:

Multi-Audio Example

It is worth it to give a simple example of how to play multiple files on multiple audio devices using python. I couldn’t find an examples on how to do this online and had to spend some time experimenting to make it all come together. Hopefully this saves you the trouble.

To install sounddevice on my Raspberry Pi, I had to run the following commands:

For this example, let’s say there are 4 audio files in the same directory as , so the directory looks like this:

The code is based on the sounddevice library for python, whose documentation is pretty sparse. This script will find the audio files, and then play them on as many devices as there are attached. For example, if you have 3 sound devices it will play 1.wav, 2.wav and 3.wav on devices 1-3. If you have any questions, feel free to ask:

Here are some more photos of the build: