• Mid-Summer Update

    1. Now that the weather has gotten really hot, I am working on knitting a sweater. This is not the best timing, but maybe this means that I will finish it by the time that it gets cold again. sweater

    2. I had hoped to make more progress on the sweater this weekend, but we have been house-hunting, and that has been taking up so much of my time. Now that writing software at home is better than writing software in an office, I need a larger home in which to write software.

    3. My notes are missing some key measurements for the sweater’s sleeves, so I am going to have to wait until I can reconstruct my plan. My plan might also keep changing. At one point I was far too into the concept of raglan-dolman, even though I kind of knew that it wasn’t the best idea. I don’t remember what I had planned for the sleeves of this sweater.

    4. We found a house that I am very, very, very interested in. It’s an older home in the “they don’t build them like they used to” sense (mid 20th century). It has amazing details and a huge amount of character (in the good way). I don’t want to say too much about it here because I don’t want to jinx it! Unlike a previous older home that I lived in, this one is not a “fixer,” so I will probably not have to spend my time scouring archetectural salvage to find period-appropriate replacement parts. (But those who know me can guess that I will never stop looking for amazing hardware and fixtures.)

    5. Speaking of attention to detail and pride in workmanship, you might notice that my sweater-in-progress has a sewn hem with a picot turning row. What you don’t see is that my previous attempt at the back of the sweater needed to be ripped all the way back because it flared out to an unacceptable degree. And since I’m knitting at such a loose gauge, I’m using seams to provide structure to the piece. We’ll see how the next steps turn out – once I remember how long I wanted to make the sleeves.

  • More Adventures with Machines

    The knitting machine had thought that this was going to be its weekend to shine. I had all sorts of plans queued up to follow-up on my two-color brioche knitting as well as a sweater pattern that is mostly rectangles. But then Line-us arrived.

    Line-us is a little robot that holds a pen and draws with it.

    Of course, you need to tell Line-us what to draw. Line-us uses a language that is also used by a lot of CNC machines. You can send the pen to a particular (x, y, z) point within its reach, and then you send it to the next point and so on and so forth.


    While this is a delightfully simple file format, it’s not something that you are going to write by hand. Fortunately, there is an Inkscape extension that lets you convert Inkscape paths to robot instructions. Unfortunately, it does not work with the current version of Inkscape. Now I have two versions of Inkscape installed on my computer so that I can use various features that are only in one or the other but not both and sling svg files between them. Also I spent far too much of Saturday trying to rewrite the extension that works with Inkscape 0.92 to see if I could get it to work with Inkscape 1.0. Despite not actually knowing Python, I was able to get it to minimally communicate with the robot but not to actually do anything useful.

    I will take this opportnity to mention that the knitting machine hacking software is also written in Python. You would think that this would motivate me to learn Python so that I could talk to all my machines in their prefered language. But, no, I can not motivate myself to learn Python.

    But as I do have a short attention span and flit about from project to project, I will take a moment to say WHY DIDN’T ANYONE TELL ME ABOUT BOBBIN LACE? Also, once it is safe to go to conferences again, what do I need to do in order to meet Veronika Irvine? In my exploration of Inkscape extensions, I discovered one that makes the most amazing patterns for bobbin lace. And it describes the math well enough that I might be able to steal some of its ideas for cool circular knitting.

    circular symmetry

  • Two Color Brioche Knitting with my Knitting Machine

    Instead of spending the time working on my COVID-19 tracking website (which shows that the number of new cases of COVID-19 in San Diego County have been decreasing for zero days in a row), I devoted the weekend to playing with my knitting machine.

    I have been spending a lot of time sitting on the couch and reading about knitting. One of the things that I’ve been reading a lot about is brioche knitting. Some people use the name “English rib” or “Fisherman’s rib” to refer to this stitch; others insist that those names apply to something similar but different. In any event, brioche knitting is a squishy fabric with prominent ribs. The defining feature of creating it with hand-knitting is that you slip a stitch while simultaneously doing a yarn-over. Morally this is equivalent to doing a regular knit stitch but giving up halfway through and moving on to the next stitch on the needle. In machine knitting, this is called “tuck,” and there is a button on the carriage to tell it that you want to do tuck stitches rather than knit stitches. Do not be confused by the name tuck; it doesn’t seem to have any connection to the other meanings of that word in English.

    Due to the tuck button, it is pretty easy to make one-color brioche knits on a double-bed knitting machine. You cast on for 1x1 rib (or full needle rib if your machine is happy with that – mine is not). Then you set one carriage to knit in one direction and tuck in the other and the other carriage to do the reverse. Easy peasy, brioche knitting. (Fun fact, if you watch machine knitting YouTube videos with the Google auto-captions, when the speaker refers to the knitting machine’s “ribber bed,” the captions will say “river bed.”)

    With hand knitting, once you know how to do brioche knitting, then you can do two-color brioche knitting, in which the ribs on one side are one color and the ribs on the other side are the other color. When knitting in the round, you need to go around once with each color to knit the full round: You do the knits with one color and then the purls with the other color. In flat knitting you do one color then you slide the work back so that you can do the row again with the other color. Neither of these strategies work particularly well with home knitting machines. These machines don’t do any sort of ribbing in the round. The operation of “slide the work back” is super annoying because you need to take the yarn out of the carriage, switch how the buttons are set, put the yarn back in, and then reset the buttons correctly.

    This weekend I found an alternative. And I mean “found” in the sense of “Columbus discovered America.” Lots of people must know about it already, but I was previously unaware of it. I was able to use a stitch pattern that was relatively easy to knit on my knitting machine and that looks a lot like two-color brioche.


    Note that this swatch no longer exists. I have ripped it out and rewound the yarn. This yarn is Noro, and the knitting machine was not happy about the thick-thin texture and all of the leaves and twigs and whatnot.

    In order to make this work, I did two rows with each color. Work the main color across and back, then switch to the contrasting color. Work the contrasting color across and back and then switch back to the main color. In machine knitting lingo, I set one carriage to knit both directions and the other to tuck both directions (KK/TT) and knit back and forth with the main color. Then I set the first carriage to tuck and the second to knit (TT/KK) and used the contrasting color. I repeated this pattern until the machine started crying about how Noro yarn is impossible to work with.

    In term of hand knitting what this would mean for flat knitting of brioche is that you would use one color to go across and back, then you would use the next color to go across and back, like normal knitting (no sliding the work to the other end of the needle). The strategy would be to start with the main color and knit a row of brioche like normal. And then on the way back, work the normal stitches normally and for the doubled-stitches (stitch + yo), do that again: slip again and add another yarn over. Switch to the contrasting color. This is sort of like normal brioche stitch again, only instead of working a stitch together with its yo, you work the stitch together with both of its yarn overs and do the slip+yo to the other stitches like in regular brioche. And on the way back, work the normal stitches normally and add another yo to the slip+yo stitches.

    It’s hard to explain for hand knitting without pictures or a video or something, and I don’t have time now for either of them right now. Much easier to describe for the machine. Too bad the machine hates Noro so much.

  • Someone on the Internet is Wrong

    There was an article in the local paper about the spread of COVID-19 in the county. They have a paywall, so you might or might not be able to read the article. It was posted several days ago, and Letters To The Editor are no longer A Thing (being replaced by comment sections where everyone argues), so my thoughts about this article are going to have to go in my blog.

    The gist of the story is that they claim that the number of cases of COVID-19 is growing the fastest in ZIP code 92154, an upside-down U shaped ZIP code right on the Mexican border. This is true, in one sense, because this is the ZIP code in San Diego County that has the most COVID-19 cases overall. You need to have, on average, the highest rate of cases per day in order to end up with the highest number of cases.

    The paper notes:

    To determine average growth rates, The San Diego Union-Tribune first calculated a change in cases between each day from March 31 through May 31, and then averaged these totals for an overall daily growth rate.

    Assuming that I am understanding what they mean here, this is equivalent to taking the number of cases on May 31, subtracting the number of cases on March 31 and then dividing by 61. They are not taking into account any changes in the rate of growth over the course of the pandemic. Also, they are assuming that the growth rate is linear, which is fine because since the middle of April it has been fairly linear. I would have been happier if they had calculated growth rates over shorter time intervals. I haven’t yet built out the analysis to look at growth rates over time, but the data that I’ve seen suggests that a naive model of “92154 is growing the fastest” does not tell the whole story. Once I run all the data, I’ll have a better story to tell, but mine would probably be “Things were pretty bad near the border, especially in San Ysidro, but all the other places that you think of as ‘poor’ or ‘Mexican’ or ‘immigrants’ are starting to catch up pretty quickly.” Not as catchy of a hot take, I know. I’m planning on changing my “new cases GIF” to show a moving average rather than the daily data, so we’ll see what that shows.

    One thing that the newspaper’s analysis entirely ignores is population. The population of 92154 is 81,645. On the day that the paper did its reporting (June 3), there were 707 reported cases in that ZIP code. This meant that 86.6 per 10,000 people in the ZIP code had contracted the disease. However, this ZIP code surrounds San Ysidro (92173), which had 339 cases out of a population of 27,741, or a rate of 122.20 cases per 10,000 population. You can see this by going to my COVID-19 tracking site and setting the map to June 3.

    By neglecting how the rate of growth changed over time (what we in the math biz would call the second derivative) as well as the relative populations, the newspaper article misses the fact that both San Ysidro and its surrounding ZIP code both had roughly the same number of cases per capita in early May (in fact, San Ysidro had a slightly lower rate) but that San Ysidro now has significantly more cases per capita. Based on this information, I would say that COVID-19 is spreading faster in San Ysidro than it is in nearby areas.

    I know that the local newspaper can’t get too sophisticated in terms of the math that it uses in articles for the general public, but I would have liked for them to acknowledge that the growth rate changes over time and that the impact on a ZIP code depends both on the number of cases as well as the population.

  • Robots Stealing Our Blogs

    Since I don’t do much, I don’t have much to write about. You might have heard that AI will advance to such a point that robots will steal our jobs. So I asked an AI system to write a blog post for me. This is what it came up with.

    1. I finished the knitting project that I’d been working on. And it’s ready for blocking! It’s taken me a really long time to knit this, mostly because I’m usually too busy with deadlines to work on non-profitable knitting projects. It was fun to do something a little different, though. :)

    2. I’ve set up one of my cameras exclusively for taking cat photos. Before, I couldn’t get any decent pictures of him. Today I have at least eight great ones. He’s not the brightest bulb in the cage, you see, so I need the flash to freeze him. When the camera comes near him, he freezes and opens his mouth. His expression says he’s saying something along the lines of “Hey, don’t you know you’ve been caught?” I’m a little sad. We had great hopes for at least one of our cats,

    3. I started sewing another mask. I own a lot of homemade masks for someone who never goes outside. Most of them are the foam and latex kind of masks. Some of them have eye and nose holes but they have little in the way of ventilation. I added some ventilation holes to my latest version but it is still too heavy to wear in public. After all of the previous attempts I came to the conclusion that the only option left to me is the simple surgical mask. With its big eye and nose holes and small chin strap it provides me with a full face mask that is light enough

    4. I’m taking a break from working on web page with the COVID data. I want to post another video that you all may find very funny. #thesearchcontinues #johnlennon #thebeatles #peace The Beatle Bible: The Fab Four’s Guide to the Good Life A good read if you want to learn about the Beatles. Many different viewpoints are given in this book. The Beatle Bible is written as a biographical yet informative look at their history, sound and content. The

  • Tales from the Bugmaster

    1. Our students do online homework and then they spend a lot of time kvetching about points in the bug reports. They seem to believe that they already own all the points and then the problems steal the points from the students; students will get a problem wrong due to what the student considers a minor oversight and then write in “GIVE ME BACK MY POINTS.” In a work-related conversation yesterday, I had to explain to a colleague that there is a good reason why I am not the Jay Powell of points. I think that in the students’ minds the problems are some sort of wealth tax on points and solving the homework problems is the equivalent of finding the correct tax loopholes.
    2. Every time a student in one of our programming classes submits a bad bug report (“The thing is not working.”), I hope that karma is keeping score. I imagine this student’s future self having to deal with bug reports just as bad.
    3. Bug report with TMI. Starts fine; goes dark. I’m fuzzing the details quite a bit, but the bug report went something like:

      I don’t remember me doing that many problems . oooooooooohhhhhhhhh I remember me doing those problems !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I love math ! it is so fun !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I mean ssssssssoooooooooooooo muchhhhhhhhhhhhhhhhhhhhhhhh ffffffffuuuuunnnnnnnnnnnnnnnnnn !!!!!!!!!!!!!!!!!!!!!! my house burned down in August 2019 so my family is living with my grandma . she is really sick !!!!!!!!!!!!!!!!!! please write back very soon!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! math is so fun !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I love writing bug reports !!!!!!!!!!!!!!!!!!!!!!! it is so fun writing bug reports !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I just love writing … …and reading!!!!!!!!!!!!!!!!!!!!!! it is fun writing bug

  • Making GIFs in My Free Time

    We’ll see if this GIF stays animated once I put it on the web. It might depend on your browser and the whims of ImageMagick. It’s animated on Facebook, which is something.


    This GIF should be showing you the spread of COVID-19 through San Diego County, based on the total denisity of people infected (number of total cases per 10,000 population) by ZIP code. Orange-based colors are for ZIP codes with more than 10,000 people and more than 5 cases. Other ZIP codes are in gray-scale. Darker colors means a greater density of cases. Yes, this is total cases (not new cases). Yes, I might work on the GIF for new cases at some point, but this GIF was already kind of annoying to make.

    Instead of devoting my recreational screen time to writing blog posts or watching TV or browsing knitting patterns that I might never make, I have been putting the infrastructure in place to make GIFs like the one I linked above. (But if it is not animating itself, I hope that the next version of it will stay animated.)

    You might think: “Take some images, toss them in a directory, and then run ImageMagick over them all to get a GIF.” If you don’t know ImageMagick, it is the best ever command line tool for making images do things without having to open up some GUI-based software and click on things. You can script all sorts of amazing things with images.

    Let me tell you about what it has taken me to create the images. I guess we’ll work backwards.

    Each image comes from an SVG (scalable vector graphics file) that is created by the d3 data visualization library. For those outside of this field, this is a JavaScript library meant for displaying data on the web. My data is a tangled JSON object, and the array of ZIP code data holds an array of total number of cases in the ZIP code, by date. I can tell d3 to alter the fill color for each ZIP code based on the number of cases. Easy? Well, that is fine if you are showing the map on a web page (which d3 was designed for) and having the map update itself when you click a button on something, but I want to have this all work on in the background in the middle of the night and have a new GIF waiting for me each morning. We’re not there yet. I still need to meddle with the process in order to produce the GIF automatically.

    Enter nodejs, which will let me run JavaScript on the server instead of in the browser. Also I needed a virtual DOM because there is no web page displaying the map when it is all running in the mind of the server, so I need to tell JavaScript that it should pretend that there is a web page so it would know where to put things. Also, JavaScript has some sort of weird stuff going on about things running synchronously vs. asynchronously, so I couldn’t just put my mapping function in a for loop and loop over all of the possible dates. I guess I could, but I didn’t really want to use Promises, which is how JavaScript deals with such things.

    Can’t loop over all the dates inside JavaScript? Rewrote the JavaScript script to take a command line argument and then wrote a bash script to call the JavaScript via node at the command line. Each call to the JavaScript script writes out a frame. OK, now we have a way to make all the images. And then I can have the bash script call ImageMagick over the directory full of images and then move the finished GIF to the right place so that it can be served by the webserver.

    Where does my JavaScript mapping script get the data from? It reads in a JSON file from disk. Where does this JSON file come from? The bash script tells a PHP script to make it. How does the PHP script make the JSON data? Well, it has a connection to a MySQL database that contains the information that it needs in order to build the JSON file. Eventually all the data came from the County’s data service.

    The PHP script is a bit more than I’ve mentioned above. What it does is it checks the MySQL database to find the timestamp of the most recent update that it has from the County. If that timestamp is long enough ago that the County should have published more data by now, it makes an API call (this is a very annoying API, btw) to get the new data and processes it to save in the database. The PHP script can use all of the data (both new and old) in order to create the JSON object. Note that the County’s API limits the amount of information that it will send you in a single call so you can’t get all of the data over all time by sending one query to the API. You either need to do a bunch of calls (SLOW!) and string them all together, or else you need to cache the older data so that you only need to get a little bit from the County. I went with caching because this data is only updated once a day, so it seems silly to keep looking for it in The Cloud if you know that there won’t be any new data for many hours.

    (Since I’m doing all this on a server that a friend lent me, not some sort of professional hosting, I had to install the webserver, the database server, etc. and configure them all to play nice together.)

    I should clarify here, the County API provides the case count per day per ZIP code. It doesn’t tell me anything about the ZIP code boundaries. These I got from a shapefile from a different part of the County’s data stores. Did you know that professional geographers have all sorts of ways to encode locations on the surface of the planet? Those of us outside of the geography biz probably use latitude and logitude for this purpose. I know that the d3 mapping functions use latitude and longitude. There are several geographic coordinate systems that use latitude and longitude. The County’s ZIP code shapefile does not use one of them. Not only did I need to convert the shapefile to a data format that could be read in by d3 in JavaScript, but I also needed to convert the coordinate system to WGS84. I tossed this geographic information into a different table in my database, and whenever I get new data about COVID-19 case counts in the various ZIP codes in the County, I can join the data up on the ZIP code and then write out a JSON object that contains everything that my script needs to make the map: Boundaries of the ZIP code, population of the ZIP code (found in a different data source published by the County), and an array of the total number of COVID-19 cases in that ZIP code (since the County started publishing this).

    Now I just need to put the finishing touches on the bash script and set it to run on a cron so that I can have a fresh GIF each morning. And this is why I have not been blogging. Once the code is nice enough that I’m not embarrassed by it, I might make the GitHub repo public so that other people can make their own GIFs in a similar way.

subscribe via RSS