Categories
Review

“Meddling Kids,” or, “alright, who gave Shaggy a gun”

Edgar Cantero
I am a big fan of Scooby-Doo. It’s got something of that James Bond aesthetic to it — every few years, there’s a new one, and we get to see a new take on the tropes. The recent series have been pretty good — What’s New was, basically, a straight modernized version of the original; Mystery Incorporated did some interesting things with the characters; Be Cool is one of the funniest shows I’ve ever watched; and Guess Who is a love letter to the people who watched the original series.12 The movies are a bit more hit-or-miss, but growing up in the 90s meant I had Zombie Island, Witch’s Ghost, Alien Invaders, and Cyber Chase; Alien Invaders is a hilarious concept, Zombie Island is, I’d argue, the best Scooby-Doo media to date, and Witch’s Ghost is part of why I was so excited to visit New England.3
In short, I love the different takes on the same story; there’s nothing new on Earth, but the different ways people combine ingredients are still creative and interesting. So when I saw that somebody had written a Scooby-Doo book with Lovecraftian influence? Alright, I’m interested.4
The writing style is interesting — Cantero switches back and forth between a more conventional novel style and something inspired by a movie script, with labelled dialogue and annotations for Scooby.5 Where it really shines is the occasional action scene; the sentences get longer, flow together, and it feels like a choreographed fight in a movie.
It’s also definitely creepier than anything in my usual reading; the book is set roughly a decade after the gang broke up, and Fred having died in the interim doesn’t stop him from showing up when Shaggy forgets his meds. The interactions between Shaggy and his hallucination of Fred range from hilarious, through bittersweet, and occasionally into the grotesque.
Plot-wise, the book is enjoyable; it gets a bit weird in places, but eventually pulls itself back together, while leaving room for Cantero to come back and write more if he wants.
Which leads me into something that I felt he did excellently: tie-ins. Because, yes, it’s a Scooby-Doo book that can’t say “Scooby-Doo,” or “Fred,” “Daphne,” “Velma,” or “Shaggy.”6 It’s also a Lovecraft book, though — the Necronomicon is explicitly mentioned, and there’s a passing reference to Miskatonic University, as well as several scenes in Arkham. And other bits and pieces makes appearances — Cantero has certainly read more Lovecraftian horror than I have, but based on what I could pick out as references, there were quite a few that I missed. And it’s tied together to give the book the feeling of being part of a larger universe — you could pick up one of Lovecraft’s books, read it, and mentally slot it in to this same continuity without an issue.
So hey, if you want a creepy, fun little romp in the Pacific Northwest, watching Shaggy, Daphne, and Velma try to deal with PTSD and the results of living in a world that has both “some guy dressed up in a costume to scare people away” and the Necronomicon, I can heartily recommend Meddling Kids.


  1. Seriously, it’s artistically gorgeous, and whoever is doing the soundtrack? Give them a raise, it’s excellent. 
  2. Yes, I know I left one out; we don’t talk about Get a Clue
  3. Zombie Island also made my time in Louisiana more enjoyable, and Cyber Chase is set in an amalgamation of MIT, Stanford, and UC Berkeley, two of which I’ve visited. The moral of the story is, I need to go to Roswell to finish my Scooby-Doo Tour of the United States. 
  4. Admittedly, it’s not an official Scooby-Doo book, so everybody has different names, but it’s also clearly meant to tie in to the same “hey, recognize this trope?” pattern, and gains a lot by then subverting them. 
  5. As mentioned in the previous footnote, the dog isn’t named Scooby, but I don’t feel like writing a conversion chart for what’s meant to be a short review, so I’m just going to do the name-swapping myself. 
  6. It’s possible they could get away with “Scrappy,” but didn’t try. 
Categories
Technology Tools

Automatic OCR with Hazel: The Easy Way

I have previously written about how to run OCR (Optical Character Recognition) on a PDF using Hazel and… a complicated pile of Python scripts and other software. Since I wrote that post, several of those pieces of software have been updated, and the core component has been, apparently, entirely abandoned.
Recently, while I was waiting for yet another keyboard replacement on my MacBook, I took another look at the OCR thing and found that there’s a much easier way available: OCRmyPDF.
It’s easy to install, assuming you’ve already got brew: brew install ocrmypdf
From there, it’s just a single action in Hazel. “Run embedded shell script: ocrmypdf $1
Admittedly, you can use some of their many settings to get something a bit nicer than just OCR; personally, I’m using --rotate-pages --deskew --mask-barcodes – the first two to help with variations in the input because I sometimes use a bed scanner, and the latter to help Tesseract, which can have issues with barcodes..
I’ve also paired it with a couple additional actions, just to keep everything organized:

I also took the time to stop using Dropbox as the go-between for my scanner and the Mac running Hazel; I’d forgotten that the scanner has a USB port. Plug in a cheap flash drive, and it’s available as a (very slow) file server. Mount the drive, add it as a Login Item so it’ll auto-mount on boot, and you can set Hazel automations to run right there. I’m not OCRing them there, though — like I said, it’s a very slow server, so it tags them ‘for OCR’ and moves them to my desktop.1


  1. With iCloud Drive handling my desktop, I’ve found it to be a pretty great ‘intake’ folder for all of my Hazel automations. It’s quite nice to be able to save a PDF from my phone, add a tag, and watch it disappear again as it’s auto-sorted, or throw a PDF on my desktop with a tag and see it pop in and out as the OCR runs. 
Categories
Technology Tools

Automatic Playlist Backup

You may have seen my monthly playlist posts on here; I put those together with a Shortcut that grabs the playlist, runs through all the songs, and makes a spirited attempt to fill in all the links off the iTunes Store Search API without hitting their mysterious rate limits.1
It’s not the be-all end-all, though — I’ve been wanting more and more lately to start making more and smaller playlists, things to match different moods. Y’know, the way normal people do playlists.
But, of course, I’m me, and I want to have the history of my music tastes, because, hey, sometimes you feel like reminiscing.
So, what to do? Well, I’ve done some work with the iTunes Library XML file, and while it’s sorta true that just wrapping that in, like, Git or something for version control could work, there are three problems with that:
1. iTunes is a weird, weird piece of software, and I don’t want to mess with its files too much.
2. The result is not at all human-readable.
3. It isn’t an excuse to learn something new.

So, what else can I do? Well, I’ve done a very light bit of tinkering with AppleScript,2 so I know it can interact with iTunes pretty well; there’s gotta be a way to do it there, right?
There is! I’ll share the script in a moment, but the functionality I wanted was “clear out the folder I give you, replicate my playlist hierarchy as directories, and spit out each playlist as a markdown file listing the title, artist, and album for each track, then commit the changes to a git repository.”
It took a while to get working — I’ve learned that AppleScript’s repeat with in loop is hilariously slow, unless you change it to repeat with in (get). I’ve also found out that the way it works with paths is super annoying, and that while it can write to a file, it can’t conceptualize creating a directory. There’s some great workarounds for that.
Now, here’s the script: I’ve left a couple {replace me} type things where you should fill in variables – namely, the path to your home directory (or wherever else you want it), and your own username, to fix some permission issues that can crop up.3

https://gist.github.com/grey280/9b95fdc8c16ec544a214f159bd008bbc

But wait, there’s a caveat: it’ll fail if the folder you gave it isn’t a git repository. Considering that I wanted this as a ‘set it and forget it’ sort of thing, I figured it wouldn’t be worth the effort to write a bunch of conditional code to do the setup. Do it yourself: git init && touch temp.txt && add temp.txt && git commit -m "Initial commit" takes care of all you need.4
Oh, and if you want it to be pushing the changes somewhere, because you’re paranoid and want everything in someone’s cloud, at least, add the remote and set it as the default upstream: git remote add origin {remote URL} && git push --set-upstream origin master

Set It and Forget It

So that’s pretty neat, but it isn’t really “set it and forget it,” now, is it? You’ve gotta open up Script Editor, pull up the script, and run it every time you want it to back up your playlists. Possibly workable for some people, but I don’t have a home server for nothing. Let’s make this truly automated.
From my prior experience with AppleScript, I know that you can set it off through a shell script by way of /usr/bin/osascript, so my first thought was to add a cron job. After a bit of research, though, I found out that Apple would prefer we use launchd instead, so I set about figuring out how to do that.
Now, if this wasn’t all an excuse to learn how to do something, I’d probably have just bought one of the GUI clients for launchd; Lingon looks pretty nice, and seems to work well.5
The process for writing your own launchd process is actually pretty simple: create a .plist file containing some XML, add it to the launchd queue with launchctl, and you’re off to the races!6
(Hint: if you want an easier way to see if your script runs than waiting and checking git log, you can add a line to the start of the AppleScript: display notification "Running playlist export".)
So, creating the XML: you want it to live in ~/Library/LaunchAgents/, and the convention is the usual reverse-TLD. (You can also use local.{your username}.{your script name}, but I’m so used to using net.twoeighty. in bundle identifiers that I just went with that.)
The important parts are the ProgramArguments array and the StartInterval integer. For ProgramArguments, give it the path to osascript,7 and as your second argument, the full path to the .scpt of the AppleScript.
Then, set the StartInterval to the number of seconds between runs; I’m using 3600, because hourly change tracking seems frequent enough for my purposes.
The result:

https://gist.github.com/grey280/f643a159a426ae25eb57139afd4f3cd5

(You can skip the StandardErrorPath and StandardOutPath – they help a little with debugging, more so if you’re running a full shell script and not a wrapper on an AppleScript.)
Finally, add it to the queue:

launctl load ~/Library/LaunchAgents/net.twoeighty.backupPlaylists.plist

And there you go – every hour, your iTunes playlists will get backed up to your Git repo, and you’ll have a nice history of your music tastes over time.


  1. iTunes Search is a really fun API to use, because via Shortcuts you only get a single input to it, and it is really bad at finding anything. Seriously — try to find anything off the top charts. As far as iTunes Search is aware, Billie Eilish doesn’t exist. 
  2. In lieu of Shortcuts having a way to set the volume on a HomePod, I’ve achieved a similar result with “run SSH script: osascript -e tell iTunes ...”. 
  3. Related: don’t put this anywhere with weird macOS access control things. Y’know, places like “Documents”, “Desktop”, anywhere in iCloud Drive or Dropbox, or even “Downloads”, which apparently is a much worse work directory than I thought it was. I eventually configured it to run out of and into my Public directory, because I figured that’d be easier than trying to mess around with the permissions somewhere else. 
  4. Without a file there, the git rm -rf . && git clean -fxd bit at the beginning is unhappy. 
  5. I used the ‘free trial’ version as a viewer for my works in progress; I figured if I’d done something really wrong, it’d complain about it being an invalid file or something. 
  6. He said, glossing over the couple hours of “fight me, macOS, why isn’t this working” 
  7. Probably /usr/bin/osascript, but you can use which osascript in Terminal to check. 
Categories
Review

“Radicalized,” or, “this just keeps getting more upsetting”

Cory Doctorow
One of my favorite concepts in science fiction is making one change and extrapolating it forward. What if Tesla and Edison’s war of the currents had resulted in most of the world outlawing electricity and doubling down on steam power? What if Superman had landed in Soviet Russia? What if somebody invented a machine that let you step between parallel worlds?
What Doctorow has done here is that, but instead of making one change, he doesn’t make a change, and extrapolates. What if we never fix copy right law? What if Juicero hadn’t collapsed? What if we never sort out healthcare?
The result is terrifying, because it feels… so very possible. It’s not the first time he’s done it, either — Little Brother was my first introduction to Doctorow, and it remains a poster child for the concept.
Reading both Little Brother and Radicalized, I didn’t feel like I was reading a novel; I felt like I was reading a warning. “We’re on a path that leads to this, or something just like it,” he’s saying. “I’m worried, and you should be too.”
Worry with me; it’s a good read, and well worth the time.1


  1. It also contains a great take on Superman, and a strangely uplifting story about the apocalypse; seriously, read it. 
Categories
Programming Technology

Publishing a Private Angular Library via Git

So, you’ve built yourself a nice new Angular library and you’re excited to put it to use in your apps! It’s an exciting time. But wait: the code you used is proprietary, and you can’t upload it to NPM.1
Good news: thanks to some features of Git, NPM, and most Git hosts, there’s a way to bypass NPM, and you don’t even need to set up your own repository. Sound good? Let’s go.
Now, I’m assuming that you’ve already (a) created your Angular library, and (b) have it in Git. If you haven’t done (a), there’s a pretty good guide on Angular’s site; if you haven’t done (b), allow me to evangelize source control to you: Git is awesome, and you should be using it. This book, available online for free, is an excellent getting-started guide.
So, you’ve got a version-controlled library; how do we make it available?
1. Build the library. ng build {YourLibrary} spits out your library as a ready-made NPM package.
2. Track the built files. git add dist/{your-library}. If you’ve got that in your .gitignore, you’ll need to remove it, or git add -f. I’d recommend the former; you’ll need to do this every time you update the library. Wrap it up with git commit and a nice message explaining what you’ve changed.
3. Set up a second repository. This is where the NPM package version of your repository will live. Leave it empty; we’ll push to it in a moment.
4. Push the subtree. This is the the magic part: we’re going to treat the built files as their own separate repository. git subtree push --prefix dist/{your-library} {path to the second repository}2
5. Tag the release with a semantic version number.3 While it’s possible to do this via the command line, it’s not fun, so I’d recommend using the GUI for your Git host of choice.
6. Generate a read-only token for the second repository. In GitLab, this is under Settings > Repository > Deploy Tokens. Configure it as you’d like, but be sure to enable read_repository.
7. Add the library to your app’s package.json. Give it the Git address for your second repository, and follow it up with either a tag or branch name to pull from. (For example: "your-library": "git+https://{GitLab token username}:{GitLab token password}@gitlab.com/{your username}/{your-second-repo}#master would pull the latest version from master.)

Et voilà; you’ve got a private Angular library, ready for use.


  1. Or maybe you’ve got issues with the fact that NPM is a private company, and can remove, un-delete, or hand over your packages without your permission
  2. i.e.: git subtree push --prefix dist/my-own-library https://github.com/grey280/my-own-library.git 
  3. This isn’t strictly necessary – I’ll explain a bit more in step 7. 
Categories
Programming Technology

Wrapping UserDefaults

UserDefaults, formerly NSUserDefaults, is a pretty handy thing. Simply put, it’s a lightweight way of storing a little bit of data — things on the order of user preferences, though it’s not recommended to throw anything big in there. Think “settings screen,” not “the image cache” or “the database.” It’s all based up on the Defaults system built into macOS and iOS,1 and it’s a delightfully efficient thing, from the docs:

UserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. When you set a default value, it’s changed synchronously within your process, and asynchronously to persistent storage and other processes.

How handy is that! All the work of writing to disk, abstracted away just like that. Neat!
Now for the downside: it’s got a very limited range of types it accepts.2 Admittedly, one of these is NSData, but it can be a bit annoying to do all that archiving and unarchiving all the time.
One solution I use is writing a wrapper on UserDefaults. Swift’s computed properties are a very neat way to do it, and any code you write elsewhere in your project will feel neater for it.
The basic idea is this:
[gist https://gist.github.com/grey280/82b91e70ef49e087a0aefe3e9374d2b7 /]
There you go: you’ve got an easy accessor for your stored setting.
Of course, we can make this a lot neater; we’ll start by wrapping it up in a class, and make a couple tweaks while we do that:
[gist https://gist.github.com/grey280/ff61d2f31a0c9f3fc2e3595a55ae9de5 /]
First, we made a variable to point at UserDefaults.standard instead of doing it directly. This isn’t strictly necessary, but it makes things a lot easier to change if you want to switch to a custom UserDefaults suite later.3
Secondly, we pulled the string literal out and put in a variable instead. Again, this is more about code maintainability than anything else, but that’s certainly a good thing to be working for. Personally, I tend to wrap all my keys up in a single struct, so my code looks more like this:
[gist https://gist.github.com/grey280/77bccd85bb1843dbd7360f7e9eecc38a /]
That’s a matter of personal taste, though.
You might also have noticed that I made both the keys and the UserDefaults.standard private — I’ve set myself a policy that any access of UserDefaults that I do should be via this Settings class, and I make it a rule that I’m not allowed to type UserDefaults anywhere else in the app. As an extension of that policy, anything I want to do through UserDefaults should have a wrapper in my Settings class, and so private it is: any time I need a new setting, I write the wrapper.
There are a few more implementation details you can choose, though; in the example above, I made the accessors static, so you can grab them with Settings.storedSetting. That’s a pretty nice and easy way to do it, but there’s a case to be made for requiring Settings to be initialized: that’s a great place to put in proper default values.4
[gist https://gist.github.com/grey280/c067ec6f165e498f4a8e0a01164a74eb /]
In that case, accessing settings could be Settings().storedSetting, or
[gist https://gist.github.com/grey280/0080b5a0cfeb3d56e1140c81eec1edb4 /]
You could also give yourself a Settings singleton, if you like:
[gist https://gist.github.com/grey280/e393bc00557a0c24e407d25dc2b4cecb /]
I don’t have a strong feeling either way; singletons can be quite useful, depending on context. Go with whichever works best for your project.
And finally, the nicest thing about writing this wrapper: you can save yourself a great deal of repeated code.
[gist https://gist.github.com/grey280/2395469f039d96ba1e4d3558a74a839f /]
Or, if you don’t want to have a default return, make it optional, it’s not much of a change:
[gist https://gist.github.com/grey280/c03eb527f9ec5d7fb15d519563085875 /]
You can also do similar things with constructing custom classes from multiple stored values, or whatever else you need; mix and match to fit your project.
(Thoughts? Leave a comment!)


  1. If you’ve ever run defaults write from the Terminal, that’s what we’re talking about. 
  2. If it matters, it’s also not synced; the defaults database gets backed up via iCloud, but if you want syncing, Apple recommends you take a look at NSUbiquitousKeyValueStore
  3. If you want your preferences shared between your app and its widget(s), or between multiple apps, you need to create a custom suite; each app has its own sandboxed set of defaults, which is what UserDefaults.standard connects to. 
  4. UserDefaults provides default values, depending on types, but they may not be the same defaults that you want. If you want a stored NSNumber to default to something other than 0, you’ll need to do that initial setup somewhere. 
Categories
Technology

iOS Notification Routing

The other day I was thinking about the way iOS handles notifications; the new Do Not Disturb stuff in iOS 12 is a good start, but it’s still rather lacking. It’s a fun thought exercise: say you’re Jony Ive or whoever, and you’re setting out to redesign the way that notifications work, from a user standpoint.1 How do you make something that offers advanced users more power… but doesn’t confuse the heck out of the majority of your user base?
After a while dancing around the problem, I came to the conclusion that you don’t.23
Instead, imagine something more along the lines of Safari Content Blockers. By default, the existing system stays in place, but create an API that developers can use to implement notification routing, and allow users to download and install those applications as they so desire.4
Obviously, this would have some serious privacy implications — an app that can see all your notifications? But hey, we’re Jony Ive, and Apple has absolute control over the App Store. New policy: Notification routing apps can’t touch the network.5 And, to prevent any conflict of interest stuff, let’s just say that the routing apps aren’t allowed to post notifications at all.
Alright, we’ve hand-waved our way past deciding to do this, so let’s take a look at how to do it, shall we?
Let’s start with the way notifications currently work. From UNNotificationContent we can grab the properties of a notification:
[gist https://gist.github.com/grey280/f12f2abe57826f2b3efdc30cebc3d834 /]
For proper routing, we’ll probably want to know the app sending the notification, so let’s add the Bundle ID in there, and we’ll also give ourself a way to see if it’s a remote notification or local.
[gist https://gist.github.com/grey280/d60ea7481dd312bd6f4e7d6ad3e4ae4a /]
Alright, seems nice enough.6
Next up, what options do we want to have available?
1. Should the notification make a sound?7
2. Should the notification vibrate the phone?
3. Should the notification pop up an alert, banner, or not at all?
4. If the user has an Apple Watch, should the notification go to the Watch, or just the phone?
5. Should the notifications show up on the lock screen, or just notification center?
6. Finally, a new addition, borrowing a bit from Android: which group of notifications should the notification go into?8

Alright, that should be enough to work with, let’s write some code.
[gist https://gist.github.com/grey280/8dac8866a736c886a66079ff58b9d34b /]
Not a complex object, really, and still communicating a lot of information. I decided to make the ‘group’ aspect an optional string — define your own groupings as you’d like, and the system would put notifications together when the string matches; the string itself could be the notification heading.9
And with that designed, the actual routing could just be handled by a single function that an application provides:
[gist https://gist.github.com/grey280/309a5f459dc207542c4f98c27bcd0c2c /]
And with that, I’d be free to make my horrifying spaghetti-graph system for routing notifications, and the rest of the world could make actually sensible systems for it.
Thoughts? There’s a comment box below, I’d love feedback.


  1. I haven’t done much work with the UserNotification framework, so I’m not going to be commenting on that at all. 
  2. I spent a while mentally sketching out a graph-based system, somewhere between Shortcuts and the pseudo-cable-routing stuff out of Max/MSP, but realized pretty quickly that that’d be incredibly confusing to anyone other than me, and would also look very out of place in the Settings app. 
  3. As a side concept, imagine that but implemented in ARKit. “Now where did I put the input from Messages? Oh, shoot, it’s in the other room.” 
  4. Unlike Safari Content Blockers, though, I think this system would work best as a “select one” system, instead of “as many as you like, they work together!” thing. Mostly because the logistics of multiple routing engines put you back in the original mess of trying to design data-flow diagrams, and users don’t want to do that. Usually. 
  5. I’d call this less of an ‘App Store’ policy and more of a specific entitlement type; if you use the ‘NotificationRouting’ entitlement in your app, any attempt to access the network immediately kills the application. 
  6. Of course, those last two additions wouldn’t be things that you’d be able to set while building a UNNotificationContent object yourself, so perhaps we should be writing this as our own class; UNUserNotification perhaps? 
  7. We’ll assume that setting notification sounds is handled somewhere else in the system, not by our new routing setup. 
  8. This would be at a higher level than iOS 12’s new grouped notifications (the stacks), more like the notification channels in Android: categories like ‘Work’, ‘Family’, ‘Health’, and so on. 
  9. Since we’re Jony Ive, and everything has to be beautiful, we’re presumably running it through some sort of text normalization filter so people don’t have stuff going under the heading “WOrk” 
Categories
Technology Tools

Automatic OCR with Hazel

I recently got a copy of Hazel and have been doing a bit of tinkering around with various ways to automate my file management. Because, y’know, I can do it by hand, but why would I when I can make a computer do it for me? That’s the whole point of computers, after all.
I have a great deal of PDFs — something about scanning every paper, handout, receipt, or bit of mail I’ve received in the past six years or so does that. And if you have a commercial-grade scanner, it can be pretty easy to automate that stuff with Hazel, as the scanner will run everything it scans through Optical Character Recognition, and the PDF you’ll get will be nicely searchable.1
Unfortunately, the scanner I’ve got, while a pretty good one, is in a different price tier than the ones that’ll do the automatic OCR, so I needed a way of doing that after the fact.
There are some guides to doing that, such as this one,2 but they tend to require either Acrobat Pro or PDFPen Pro, which both have price tags above the “a couple hours of tinkering and no money” that I was hoping to spend on this project.
Throw a few computer science keywords on what you’re Googling, though, and you’ll find stuff that’s more in that vein.3 So, compiled here after I used Chase as a guinea pig, a guide to putting together automated OCR for free.4

Prerequisites

Before we can automate OCR, we need a few things installed. Open up Terminal, and let’s go.
sudo easy_install pip
(For those of you who didn’t put a few years into classes on computer science, I’ll try to explain as I go along. That first word, sudo, means “super user do”, basically; it’s the Admin Override for terminal commands. Be careful with it, you can make quite a mess tinkering with it. The next bit, easy_install, is part of the version of Python that comes default with macOS. pip is what we’re telling easy_install to install; ironically, pip is the modern version of easy_install.5)
The first time you use sudo in a Terminal session, you’ll be prompted for your password; if you’re not an administrator on the mac you’re using, you’ll need an administrator password. That’s a good opportunity to check with the administrator if this is something you should be doing at all.
Once pip is done installing, we’re going to get another installation helper, Homebrew:
sudo /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Again, this is just installing a piece of software, Homebrew.

Components

Now that we’ve got the infrastructure built, we’re going to install the components that the OCR system uses.
brew install tesseract
brew install ghostscript
brew install poppler
brew install imagemagick
(If any of those fail, you can try to rerun them with sudo added to the front, i.e. sudo brew install tesseract.)
For reference: Tesseract is the actual OCR engine, Ghostscript makes it easier to interact with the PDF format,6 Poppler is similarly PDF-related, and ImageMagick handles conversion between basically any types of images.
Finally, we’ll use pip to install a specific version of another:
sudo pip install reportlab==3.4.0
ReportLab is yet another PDF-related library, but version 3.5.0 has some compatibility issues with the OCR system.

Installation

Finally, we’ll get the actual thing that ties these all together:
sudo pip install pypdfocr
PyPDFOCR is a lovely open-source project that ties all these components together into a single thing. Once it’s installed, you can use it from the terminal:
pypdfocr {filename}, where you replace {filename} with the non-OCR’d version of the file you want in OCR’d form.7 It’ll take a bit to run, but once it’s done, you’ll have a file (named {filename}_ocr.pdf) that contains, hopefully, the text of the document you scanned.89
Go ahead and test it; if you get an error about the file not being found, see if the file name or directory structure included a space. If it did, tweak the command a bit: instead of pypdfocr {filename} you’ll need to do pypdfocr "{filename}".
You may also get an error that mentions File "/Library/Python/2.7/site-packages/pypdfocr/pypdfocr_pdf.py", line 190… and a bit more after that. If it’s AttributeError: IndirectObject…, then you’ll need to tweak part of the code.10
cd /Library/Python/2.7/site-packages/pypdfocr
sudo nano pypdfocr_pdf.py
That’ll open up nano, a very lightweight text editor. Press control+W, type in orig_rotation_angle = int(original_page.get and hit return; this will take you to the line we want to edit. It’ll read orig_rotation_angle = int(original_page.get('/Rotate', 0)) — we want to change it to orig_rotation_angle = int(original_page.get('/Rotate', 0).getObject()) by adding .getObject() before the last close-paren.
Once you’ve done that, press control+X, then hit return again. Try OCRing something again; it should work this time.

Using Hazel

Now all you need to do to have Hazel automatically OCR a PDF is, in the actions, add a “Run shell script” action, use “embedded script”, and in the ‘edit script’ bit, put in pypdfocr "$1".
Keep in mind, this doesn’t replace the PDF in place, it’ll create a copy with _ocr added to the end of the name. If you’d like the original to be deleted once it’s done, rather than having Hazel do it, just add a second line to the embedded script: rm "$1"
You’ll probably want another rule to move the OCR’d versions somewhere else; while you’re building that, you can also use the ‘rename’ action to remove the _ocr bit, just tell it to replace “_ocr” with “”.
Have fun automating!


  1. And, as a result, useable for Hazel sorting by way of the ‘contents’ filter. 
  2. I was hoping to link to Katie Floyd’s original post about it, but her website is down at the moment, so I guess I won’t be doing that. 
  3. Technically speaking, I think all I added was “site:github.com”, but that did the trick. 
  4. This assumes you have a Mac, since you’re working with Hazel, and that you’re willing to do a bit of tinkering in the terminal, which I also kinda assumed, since you’re working with Hazel. 
  5. I think that’s irony; I was a computer science major, not an English major. 
  6. “the Printable Document Format format” 
  7. Tip: you can type pypdfocr  (including the trailing space) and then drag-and-drop the PDF from Finder into the Terminal, and it’ll automatically fill in the filename. If any part of the path includes a space, though, it’ll fail, so for filenames or folders that contain spaces, do pydpfocr "{filename}" – type pypdfocr ", drop in the file, and then ", and then hit enter. 
  8. Caveat: Tesseract isn’t perfect, especially with regard to the formatting, so don’t expect this to give you a perfectly-formatted version of whatever you scanned. That said, the process is lossless: {filename}_ocr.pdf is built by taking the original PDF file and then adding an invisible text layer over the analyzed text, so you won’t lose any information by doing this, you just might not gain anything useful. 
  9. Note that it’ll spit {filename}_ocr.pdf out not necessarily where the original file was, but wherever the Terminal session currently is; if you’re unsure about where that is, you can use pwd to have it displayed, or just open . to open it in Finder. 
  10. Don’t ask me why this is all “you might have to do this”, because I genuinely don’t know why this problem only pops up some of the time. 
Categories
Review

“Post-Capitalist Society,” or, “hindsight is fun”

Peter F. Drucker
This book was published in the early 1990s, and it’s kinda gained something by being dated. Drucker has quite a few “by the 2010s” lines in there, which are about half “wow, how did he know?” and half “oooh that’s not how that went.” To me, at least, there’s a good amount of comedy in that sort of thing, and I rather enjoyed the read.
Beyond that, I don’t have a lot to say about it, so I’ll throw out a couple quotes I pulled while I was reading it.
“Power must always be balanced by responsibility; otherwise it becomes tyranny.”
“The future may we ‘post-Western’; it may be ‘anti-Western.’ It cannot be ‘non-Western.’”
Like I said, a good deal of what he talks about has come to pass, but a good deal hasn’t, and some of what hasn’t is the sort of thing that I wish had. It’s a fun read, give it a go.

Categories
Review

James Baldwin’s Collected Essays

James Baldwin
This is ostensibly supposed to be a book review in the way I normally do them, but that doesn’t feel like the right way to go about it. For a variety of reasons, really: firstly, because most of what I review is fiction, and this was only partially that, if at all; and secondly, because it’s just a different sort of book than I usually do.1
James Baldwin was, I’ve learned, a Figure in the civil rights campaigns. To be honest, before I started the project of reading this book, I hadn’t really heard of him. The first references I got to his work were as quotes in essays I proofread for a friend of mine; it took me a while to catch on to the fact that I was seeing the same name come up over and over. (That friend went on to write a thesis about Baldwin; I believe it’s available online, and I’d recommend reading it, if only so you get a better look at Baldwin’s work than I’ll be able to give here.)
The Essays cover a variety of things, but the core component is the relationship between Black and White in America. Which I’m hardly qualified to talk about; again, I’ll point you to that thesis, or just directly to Baldwin’s writings, because both are far better takes than anything I can come up with.
Content aside, Baldwin is a great writer, and a powerful speaker; if you get a chance, check out some of his speeches, they’re certainly on YouTube by now.
The one caveat I’ll give this book is that you shouldn’t plan on finishing it in one sitting, or even a handful; it’s a book that demands effort. Even just from the physical standpoint — it’s 800-plus pages, in the edition I have, fine print on the Bible-like thin paper. It demands endurance, and you can’t really power through it like I tend to with books; after, at most, 100 pages, I had to put it down and give my brain time to process through things, because after a while you start to feel like a river is pouring through your head, in one ear and out the other.
Which isn’t to say you shouldn’t read it, because you absolutely should. I’m glad I put the time into it, and I suspect I’ll be budgeting time for another run at it again sometime in the future.2


  1. I’ve reviewed one other collection of essays, that I can remember: “The Control of Nature”, which I adored. But that was also different; the essays were about Man’s relationship to Nature, and not Man against Man and Society, or whatnot. I dunno, I’m trying to remember terminology from the last literature class I took, which was either three or four years ago, depending on how you count things. 
  2. And, tacked on here as a footnote because I couldn’t leave it out, but I also couldn’t work it in anywhere else: a couple people who’d read his work before had lead me to believe that he was queer in the way that Shakespeare was — rumored or hinted at, but never really confirmed one way or the other. I can only assume, from that stance, that they hadn’t read the last two essays in the collection, because the final essay includes a description of a young man that begins with “We were never lovers: for what it’s worth, I think I wish we had been.”
    The essay before is even more explicit, I’d say, in that it devotes several pages to talking about Baldwin’s experiences in what are, today, equivalent to gay bars and bathhouses; perhaps my favorite part is the little editorial note at the end that consists of the year it was published and the fact that it was first published in Playboy
Categories
Review

“Openly Straight,” or, “just let this idiot be happy”

Bill Konigsberg
I was genuinely surprised to find this book on my Kindle; I knew it was one I’d been wanting for a while, but I didn’t remember actually buying it. Still, I’m on vacation, trying to work my way through the backlog of books a bit, so I shrugged and started to read.
Here’s the concept, containing no more spoilers than the Amazon blurb: Rafe is an openly gay young man living in Boulder, Colorado. And by ‘openly gay,’ I mean very; he came out in middle school, his parents threw a coming out party, his mom became president of the local PFLAG chapter, and he’s got, like, an internship kind of thing being a speaker at other high schools in the area. Not bad for a sophomore in high school.
That’s where the book starts, and it quickly leaves that point, because Rafe isn’t happy with this life. Sure, everyone accepts him as The Gay Kid, but that’s all he is. He scores the winning goal in a soccer game, and the local newspaper runs a story: “Gay Student Wins Game!” And who really likes being boiled down to one aspect of their personality?
So he leaves; gets himself accepted to an Ivy-prep boarding high school over on the East Coast somewhere. Not mentioned to the very-supporting parents and friends? The fact that he’s not going to be gay there; he’s going to let the ‘straight until proven gay’ aspect of heterosexism1 take over and get to experience life from the other side.2
Which is, honestly, a very interesting concept, but in execution, I didn’t enjoy it all that much. It felt, to me, like the book was trying to be two different things at once, and as a result, failing at both. The beginning and end are in a more literary bent, exploring some of the stuff I’d mentioned earlier. Which is a valid topic to be explored, and the way it’s handled is sufficient that, at the end of this point, I’m still going to recommend the book. Where it falls apart is in the middle; the book gets a bit distracted from that literary style and turns into a bit of a teenage romance fluff pile.
Again, not a bad thing, but the two aspects don’t work well together; the conflict of the book should be either the literary ‘man versus society’ kind of thing, or the romance ‘man versus his own idiotic self being mad at romance’ deal. Instead it’s ‘literary aspirations versus the plot arc of a romance novel,’ and both portions lose out for it. The romance novel falls apart because that’s what the literary aspect demands, and the meaning of the literary component feels cheapened by the collapsing romance.
I wish I could’ve liked this book more, but oh well. Still, it does have some valuable things to say, and I’m going to go ahead and recommend it.3 Give it a read, and maybe do a slightly better job than I did at engaging with the more thought-provoking portions.4


  1. If you don’t know what the word means, read the book, it does a better job explaining it than I can. 
  2. The first few chapters of this are actually very anxiety-inducing; minority stress is a real thing, and imagining going through it without a support network is a stressful concept. 
  3. Because, y’know, this has been such a glowing review. 
  4. Part of the issue for me, I suppose, is that all the thoughts it’s trying to provoke are conclusions I arrived at a while ago; I’m not really the target audience, I suppose. 
Categories
Review

“Smoketown,” or, “post-eco-apocalypse, but weirdly uplifting”

Tenea D. Johnson
I’m normally not a fan of post-apocalyptic stuff, because, y’know, if I want to be depressed about the world I’ll just turn on the news. This, though, wasn’t as depressing as things usually are — things have fallen apart as compared to what we’re used to, but people aren’t letting it stop them. Life goes on, even if that means city-states throughout the remnants of the US cooperating on carbon sequestration projects to try to keep Idaho from sinking.1
This was also one of those books that does an excellent job of setting up a fascinating setting without dropping into mountains of exposition. There’s never an explicit reference to what’s happened, but you can pick things out from background details pretty well; it’s tantalizing, to see little hints of things but not get a full explanation.
The story, too, is interesting, because it doesn’t treat the overall ‘apocalypse’ as the Big Problem. It’s hinted at that the various governments of the world are continuing to adapt to and prevent further problems, but the story focuses on two levels: a personal dilemma, and one enveloping just the city where the story takes place.
The personal is weird and convoluted and makes sense, eventually; the city-level is more neatly tied together. It’s quite satisfying, all told; as I was getting towards the end of the book, keeping an eye on how much of it was left, I wasn’t expecting everything to tie up as well as it did.
And I think I’ll stop there; I don’t like giving away spoilers, and this book did a better job of keeping me from guessing the ending than I usually do. Give it a read.


  1. I believe that’s an incorrect reference, technically — Idaho was mentioned as having become entirely desert, I think, and somewhere else (Louisiana, presumably) had effectively sunk into the ocean. 
Categories
Articles Education Tools

Productivity and Organization

Over time I’ve acquired a reputation for being an organized (and, presumably, productive) person; occasionally, people ask me for tips.

Be as efficient as you can.

In the interest of following my own tips, I’m writing this up as a blog post so I have something I can quickly send to folks when they ask. Automate things where you can; if you’ve got the time to learn it, Workflow is a wonderful tool.1 I’ve got a good chunk of my morning routine compressed into pressing a single button on my phone and, depending on how complex my calendar is for the day, answering a question or two.

Don’t trust your brain to remember things

The human brain is a wonderful machine! Unfortunately, it’s terrible at remembering things, but also convinced that isn’t the case. The good news is, we invented writing, and then computers, both of which make it much easier to remember things. So don’t just put stuff in your head and assume it’ll stay there; it doesn’t matter what you use, but have somewhere permanent that you can put stuff. Depending on what you prefer, you can use a planner or notebook, or go all digital like I have. Personally, I use a combination of the system-default Calendar app, syncing through Google Calendar, with Drafts 42 as my “writing thoughts down in the middle of the night” app, Day One as a journal, and Ulysses for any longer-form writing or note-taking.3

Have a to-do list

Technically speaking, this is an extension of the above, but don’t trust yourself to remember things you have to do in a day. If they’re at a specific time or meeting with someone, they go in your calendar; otherwise, they go on the to-do list. Again, this can be on paper if that’s your style, but if you’re a big ol’ tech nerd, you’ve got a bounty of options. The built-in Reminders app is… there, and it’s not great, but it’s free and meets the bare minimum of functionality. Personally, I’m a big fan of Things 3,4 but Omnifocus is also a big name in the field, if (in my opinion) over-complicated. That said, task management apps like that are a huge market on the iOS and macOS app stores, as well as just online, so you should be able to find something you like.
Once you’ve started using it, I recommend the “vaguely Getting Things Done” style, which consists of “write stuff down as soon as you think of it, and file it away in the proper place when you’ve got time.” The important thing is to not go “oh, I’ll remember that later,” because there’s a really good chance you won’t.

Figure out what you’re spending your time on

You know that feeling like you’ve wasted a whole day? That’s stupid, but it’s also hard to convince your brain you’ve been productive if you don’t actually know what you’ve been spending your time on. Having a to-do list helps with this; you can look at your list for the day and see all the things you’ve checked off.5 Beyond that, you may want to try time tracking; I’m a fan of toggl and use it all the time. I keep the website pinned in a tab on my laptop, and rather than use their app, I’ve got some Workflows built that interact with their web API.6 It works pretty well for me; I know what I’m spending time on, and I can also use it for some very accurate billing, should I need to.

Clean up

Finally, staying organized is not only helpful for quickly finding things, it also just tends to make you feel better about everything. Take time when you can to organize your work and living spaces. If you’re currently in college, you’ve probably got ten thousand pages of various papers drifting around; next time it’s time to buy textbooks, I recommend going digital (it’s slightly cheaper, and then you only have to carry around your laptop/tablet, which you were probably gonna be carrying anyways, and you can search in your books, which is quite helpful). For the zillions of pages of handouts you get, invest in a scanner that can do duplex scanning and a recycle bin; it’s amazing how much space you can save by getting rid of all the papers.7 Once you’ve got things digitized (or, preferably, as you get them digitized), come up with a neat organizational system and stick to it. For school stuff, semester/term lines are a nice dividing line; if you’re doing the whole ‘adult life’ thing, the tax year is a good one.8

I’m going to call it done there. If you skipped to the end, the single most important thing I’d like you to get from this is brains are bad at remembering things; write stuff down. That’s my number one tip, so if you only take one thing from this, that’d be it.
If you’ve got any questions, I’ve recently brought back the ability for people to leave comments, so go ahead and do that.9 And hey, maybe I’ll do more posts like this, I enjoy doing the writing, and it’s fun to be able to support the various apps I use.10


  1. In September 2018, or thereabouts, it’s going to disappear and be replaced by Shortcuts, but from what we’ve seen in public betas, Shortcuts has the same functionality, some new features, and a new coat of paint, so if that link doesn’t work, just search the App Store for ‘Shortcuts.’ 
  2. Drafts 5 has been out and received very good reviews for its automation capabilities, but all I really want from the app is a dark color scheme and the ability to open directly into a new document, so the old version works for me. 
  3. That link is to Ulysses’ iOS app, but thanks to their subscription system, you pay for it on one platform and get it on iPad and Mac as well; mostly I use it on the Mac, but it’s nice to have it available wherever. 
  4. That’s their macOS app; they’ve also got separate iPhone and iPad apps. 
  5. This is why I’ve got Things set up not to sweep things away as soon as I check them off, but to leave them there until the end of the day. If I look at my list and it’s empty, nothing to do and looking like I’ve done nothing, the “oh god I wasted the whole day” feeling gets so much worse
  6. If you’d like to know more about those, leave something in the comments that I’ve just remembered I opened back up. 
  7. You don’t necessarily need to do what I did, which was a roughly five-year-long process of clearing out every paper I own, but then, you’re hopefully less of a pack-rat than I was, too. 
  8. Oh, and don’t leave those files in a single place; the nice thing about being digital is that it’s easy to make copies, and when you’ve got copies, you don’t have to worry that you’ll lose the original. These days, I throw all the current stuff into iCloud Drive, but I used to use Dropbox; older things get moved from whichever cloud to an external hard drive that’s backed up with Backblaze
  9. It’s one of the only ways to get in touch with me. Bonus productivity tip, for those of you reading the footnotes: social media sucks, stop using it. 
  10. Shameless self promotion: as an app developer, I know how danged hard it can be to actually make a living from the App Store. Support the people making the stuff you use. 
Categories
Review

“The Control of Nature,” or, “there’s nothing like finding out 100,000 tons of concrete has no foundation left whatsoever”

John McPhee

I’ve actually had this book for quite a while; one of the essays in it was required reading for a class I took, oh, two years ago or so? Something like that. I quite enjoyed the read at the time, but somehow never thought to read the other essays in the book. I found it again in the whole mess of moving out of campus housing after graduation and decided to toss it into the to-read pile, and I finally got around to it.1

And I’m glad I did; while “Los Angeles Against the Mountains” wasn’t quite as fun to reread as it was to read the first time around, the other two essays were both just as enjoyable on first read as I’d hoped. McPhee’s writing style is beautiful; very visually descriptive, deeply informative, and with well-timed flashes of humor throughout.

I’m going to split this review up a bit and include some excerpts from each of the essays, to try to give you a sense of not only McPhee’s voice, but also the content of the essays.

“Atchafalaya”

The first essay, “Atchafalaya,” follows the US Army Corps of Engineers and their work on the Mississippi River; it’s far more involved than I’d ever thought, and the project is fascinating.

On the outflow side—where the water fell to the level of the Atchafalaya—a hole had developed that was larger and deeper than a football stadium, and with much the same shape. it was hidden, of course, far beneath the chop of wild water. The Corps had long since been compelled to leave all eleven gates wide open, in order to reduce to the greatest extent possible the force that was shaking the structure, and so there was no alternative to aggravating the effects on the bed of the channel. In addition to the structure’s weight, what was holding it in place was a millipede of stilts—steel H-beams that reached down at various angles, as pilings, ninety feet through sands and silts, through clayey peats and organic mucks. There never was a question of anchoring such a fortress in rock. The shallowest rock was seven thousand feet straight down. In three places below the structure, sheet steel went into the substrate like fins; but the integrity of the structure depended essentially on the H-beams, and vehicular traffic continued to cross it en route to San Luis Rey.

Then, as now, LeRoy Dugas was the person whose hand controlled Old River Control—a thought that makes him smile. “We couldn’t afford to close any of the gates,” he remarked to me one day at Old River. “Too much water was passing through the structure. Water picked up riprap off the bottom in front, and rammed it through to the tail bed.” The riprap included derrick stones, and each stone weighed seven tons. On the level of the road deck, the vibrations increased. The operator of a moving crane let the crane move without him and waited for it at the end of the structure. Dugie continued, “You could get on the structure with your automobile and open the door and it would close the door.” The crisis recalled the magnitude of “the ’27 high water,” when Dugie was a baby. Up the alley somewhere, during the ’27 high water, was a railroad bridge with a train sitting on it loaded with coal. The train had been put there because its weight might help keep the bridge in place, but the bridge, vibrating in the floodwater, produced so much friction that the coal in the gondolas caught fire. Soon the bridge, the train, and the glowing coal fell into the water.

One April evening in 1973—at the height of the flood—a fisherman walked onto the structure. There is, after all, order in the universe, and some things take precedence over impending disasters. On the inflow side, facing the Mississippi, the structure was bracketed by a pair of guide walls that reached out like curving arms to bring in the water. Close by the guide wall at the south end was the swirling eddy, which by now had become a whirlpool. There was other motion as well—or so it seemed. The fisherman went to find Dugas, in his command post at the north end of the structure, and told him the guide wall had moved. Dugie told the fisherman he was seeing things. The fisherman nodded affirmatively.

When Dugie himself went to look at the guide wall, he looked at it for the last time. “It was slipping into the river, into the inflow channel.” Slowly it dipped, sank, broke. Its foundations were gone. There was nothing below it but water. Professor Kazmann likes to say that this was when the Corps became “scared green.” Whatever the engineers may have felt, as soon as the water began to recede they set about learning the dimensions of the damage. The structure was obviously undermined, but how much so, and where? What was solid, what was not? What was directly below the gates and the roadway? With a diamond drill, in a central position, they bored the first of many holes in the structure. When they penetrated to basal levels, they lowered a television camera into the hole. They saw fish. (28-30)

“Cooling the Lava”

The next essay is set in a very different clime: a volcanic eruption in Iceland, with occasional detours to a similar eruption in Hawaii. The way he describes these immense forces is amazing; it feels as if he’s trying to make sure you feel the same sense of awe that he does.

The university installed [the seismometer] on Einar’s farm about a year before the Heimaey eruption, its primary purpose being to sense the threats of Katla, an unusually dangerous volcano only fifteen miles away. Hekla is in the area as well—the stratovolcano that appears in early literature as one of the two mouths of Hell. Groans from dead sinners have been heard in the crater. But Hekla is out in the open, observable under the sky. The baleful Katla is covered with ice It lies under Myrdalsjokull—a glacier field of two hundred and seventy square miles. When Katla erupts, as it has about twice a century, it creates a vast chamber of water under the ice. When the water reaches a critical volume, it lifts the ice cap, and one or two cubic miles bursts out as a violent flood—a blurt of water twenty times the discharge of the Amazon River. The outwash plains these floods have left behind are as desolate as the maria of the moon. A town, villages, and farms lie between Katla and the sea. (113-114)

While I’d probably call “they saw fish” my favorite line of the whole book, probably the best example of his sense of humor comes from this description of a golf course:

In 1801, it came down off Hualalai, a lesser volcano eight thousand feet high, and poured into the sea. There on the leeward side of the island, where rainfall is ten inches a year, the lava has remained essentially unchanged. Resorts have sculpted it like movie sets, landscaped wit imported soils. The bunkers of designer golf courses are not concave and full of sand but—lovely in the green surrounding turf—solid black islands of undisturbed basalt. Use your wedge on that. Your hands sting for a year. If a long approach shot lands on one of those, it bounces to Tahiti. (152)

Finally, from a portion of the book where I could feel myself mentally adding a few things to my bucket list:

The rock, being essentially glass, was very sharp. It was also hot, particularly where a tube lay below and molten lava was running there. We came to a skylight and inched toward it. Steam swirled above it but did not close off the view—of the racing orange currents of an incandescent river. By an order of magnitude, this was the most arresting sight I had ever seen in nature. The time spent gazing into it could not be measured.

Gradually, I began to think. Out of curiosity, I asked Christina if we were looking down into the near side of the tube or were standing over the middle and looking at the far side of the tube.

“The far side,” she said.

If my legs still had knees in them, I was unaware of it. (155)

“Los Angeles Against the Mountains”

The last essay of the book is the first one I read. It was interesting; at the time, I found it fascinating, and since that first reading I’ve come back to it again and again in my mind.

Los Angeles is overmatched on one side by the Pacific Ocean and on the other by very high mountains. With respect to these principal boundaries, Los Angeles is done sprawling. The San Gabriels, in their state of tectonic youth, are rising as rapidly as any range on earth. Their loose inimical slopes flout the tolerance of the angle of repose. Rising straight up out of the megalopolis, they stand ten thousand feet above the nearby sea, and they are not kidding with this city. Shedding, spalling, self-destructing, they are disintegrating at a rate that is also among the fastest in the world. The phalanxed communities of Los Angeles have pushed themselves hard against these mountains, an act of aggression that requires a deep defense budget to contend with the results. (184)

It follows the Los Angeles Flood Control District, or, as the locals call it, Flood. Now, controlling floods seems like it’d be easy in Los Angeles, the city of perpetual doubt, but that’s far from the truth; not only is there the occasional bit of torrential rainfall, but also something much more difficult: rockfall.

Many people regard the debris basins less as defenses than as assaults on nature. They are aesthetic disasters. To impose them on residential neighborhoods has been tantamount to creating a Greenwich full of gravel pits, rock quarries at either end of Sutton Place. The residents below Hook East were bitter when the basin was put in. Months later, the bulldozer tracks were still visible, they said, meaning that nothing had happened—no debris had come, and not even enough rain to obliterate the tracks. So why had the county used taxpayers’ money to build something so obviously unnecessary? A form of answer came when the basin overfilled in one night. Afterward, people criticized the county for not building basins of adequate size. (246)

What was most interesting to me, though, wasn’t just the concept of trying to fight against these rockfalls; it was the interrelationships between everything.

When fire comes, it puts the nutrients back in the ground. It clears the terrain for fresh growth. When chaparral has not been burned for thirty years, about half the thicket will be dry dead stuff—twenty-five thousand tons of it in one square mile. The living plants are no less flammable. The chamise, the manzanita—in fact, most chaparral plants—are full of solvent extractives that burn intensely and ignite easily. Their leaves are glossy with oils and resins that seal in moisture during hot dry periods and serve the dual purpose of responding explosively to flame. (209)

It burns as if it were soaked with gasoline. Chaparral plants typically have multiple stems emerging from a single root crown, and this contributes not only to the density of the thickets but, ultimately, to the surface area of combustible material that stands prepared for flame. Hundreds of acres can be burned clean in minutes. In thick black smoke there is wild orange flame, rising through the canyons like explosion crowns. The canyons serve as chimneys, and in minutes whole mountains are aflame, resembling volcanoes, emitting high columns of fire and smoke. The smoke can rise twenty thousand feet. (210)

If you walk in a rainstorm on a freshly burned chaparral slope, you notice as you step on the wet ground that the tracks you are making are prints of dry dust. In the course of a conflagration, chaparral soil, which is not much for soaking up water in the first place, experiences a chemical change and, a little below its surface, becomes waterproof. In a Forest Service building at the foot of the mountains Wade Wells keeps some petri dishes and soil samples in order to demonstrate this phenomenon to passing unbelievers. In one dish he puts unburned chaparral soil. It is golden brown. He drips water on it from an eyedropper. The water beads up, stands there for a while, then collapses and spreads into the soil. Why the water hesitates is not well understood but is a great deal more credible than what happens next. Wells fills a dish with a dark soil from burned chaparral. He fills the eyedropper and empties it onto the soil. The water stands up in one large dome. Five minutes later, the dome is still there. Ten minutes later, the dome is still there. Sparkling, tumescent, mycophane, the big bead of water just stands there indefinitely, on top of the impermeable soil. Further demonstrating how waterproof this burned soil really is, Wells pours half a pound of it, like loose brown sugar, into a beaker of water. The soil instantly forms a homunculus blob—integral, immiscible—suspended in the water.

In the slow progression of normal decay, chaparral litter seems to give up to the soil what have been vaguely described as “waxlike complexes of long-chain aliphatic hydrocarbons.” These waxy substances are what make unburned chaparral soil somewhat resistant to water, or “slightly nonwettable,” as Wells and his colleagues are won’t to describe it. The the wildfires burn, and temperatures at the surface of the ground are six or seven hundred centigrade degrees, the soil is so effective as an insulator that the temperature one centimetre below the surface may not be hot enough to boil water. The heavy waxlike substances vaporize at the surface and reconvenes in the cooler temperatures below. Acting like oil, they coat soil particles and establish the hydrophobic layer—one to six centimetres down. Above that layer, where the waxlike substances are gone ,the veneer of burned soil is “wettable.” When Wells drips water on a dishful of that, the water soaks in as if the dish were full of Kleenex. When rain falls on burned and denuded ground, it soaks the very thing upper layer but can penetrate no further. Hiking boots strike hard enough to break through into the dust, but the rain is repelled and goes down the slope. Of all the assembling factors that eventually send debris flows rumbling down the canyons, none is more detonative than the waterproof soil.

In the first rains after a fire, water quickly saturates the thin permeable layer, and liquefied soil drips downhill like runs of excess paint. These miniature debris flows stripe the mountainsides with miniature streambeds—countless scarlike rills that are soon the predominant characteristic of the burned terrain. As more rain comes, each rill is going to deliver a little more debris to the accumulating load in the canyon below. But, more to the point, each rill—its naturally levees framing its impermeable bed—will increase the speed of the surface water. As rain sheds off a mountainside like water off a tin roof, the rill network, as it is called, may actually triple the peed, and therefore greatly enhance the power of the runoff. The transport capacity of the watershed—how much bulk it can move—may increase a thousandfold. The rill network is prepared to deliver water with enough force and volume to mobilize the deposits lying in the canyons below. With the appearance of the rills, almost all prerequisites have no sequential occurred. The muzzle-loader is charged. For a full-scale flat-out debris flow to burst forth from the mountains, the final requirement is a special-intensity storm. (212-214)

And, again, there’s always that sense of awe, for nature and all the forces involved. But he tempers it well with human stories:

The Harkness house projected from the hillside and had a carport beneath the master bedroom. The debris tore off the master bedroom with Sara and the baby inside. The bedroom fell on the family station wagon. With the bedroom on top of it, the station wagon went down the driveway and on down the street. In what remained of the house, the twins and their sister Claudine were unhurt. Sara and the baby came to the end of their ride unhurt. The station wagon suffered considerably. When the bedroom was taken off it, the car was twenty-six inches high. (263)

At this point, if you’re still reading, I think it’s safe to say you’re as interested by these clips of the essays as I was by the whole things. I can absolutely recommend that you give it a read.

  1. Technically it was the second item on the pile, behind Baldwin’s “Collected Essays”, but that’s a rather dense book that I’ve been working on for a while, and I needed a bit of a break.
Categories
App Portfolio Technology

Fluidics 1.1: The Animation Update

The first major update to Fluidics is now available on the App Store!1 In all honesty, it was largely a ‘bug fixes and performance improvements’ update, but I’ve always hated when app updates list that, so I made sure to include a couple user-facing features so there’d be something fun to talk about, at least.
In this case, those features were animations. The most notable is the background – rather than being drawn once, the ‘water’ in the background is now animated, which I think makes the visual effect much nicer overall. Swiping between the three main pages of the app is also much smoother now; instead of a single ‘swipe’ animation being triggered by any swipe, it directly responds to your swipe, so you can change your mind about which direction to swipe halfway through, and it feels more like you’re moving things around, rather than switching pages.2
The big changes, though, are largely invisible; a whole lot of work on the internals to allow for future features I’m planning.3 The gist of it is that a lot of the internals of the app are now a separate library, which means I can share code between the widget and the main app without needing to copy-and-paste all the changes I make in one place to the other.
Past that, there were a couple little tweaks — the algorithm that calculates the water goal is a bit less aggressive with the way it handles workout time, and there’s now a little “this isn’t a doctor” disclaimer in the Settings page that I put there because the lawyer I don’t have advised that I do that.
And, the bit that turned into more of a project than I thought: VoiceOver support. VoiceOver, for those that don’t know, is one of the core accessibility features of iOS; when enabled, it basically reads the contents of the screen to the user, making it possible for visually-impaired people to use iOS. By default, any app built on UIKit has some support for VoiceOver, but the further you go from the default controls, the more broken that’ll get. The way Fluidics works, it was super broken; technically useable, but downright painful to do. After a day or two of vigorous swearing and arguing with the Accessibility framework, I’m proud to say that Fluidics is now VoiceOver-compatible.
If you’ve already got Fluidics on your phone, it’s a free update from the App Store.4 If not, the whole app is a free download from the App Store, and I’m hoping that you’ll enjoy using it. Leave a review or whatever; I’m trying not to be pushy about that.
Oh, and I’m in the process of updating the app’s website; I got such a good URL for it that I want it to look good to match.


  1. There was a bugfix update earlier, version 1.0.1, but that’s not at all exciting, so I didn’t bother writing anything about it. 
  2. If you’re curious, this involved rebuilding the entire interface, from three separate pages that’re transitioned between to a single page that’s embedded in a scroll view. 
  3. And no, I won’t be telling anybody what those are just yet; I don’t want to promise anything before I know for sure it’ll be possible. 
  4. In fact, it may have already been automatically updated — the easiest way to tell is to open the app and see if the water is moving or not.