Andrew Cooke | Contents | RSS | Twitter | Previous


Welcome to my blog, which was once a mailing list of the same name and is still generated by mail. Please reply via the "comment" links.

Always interested in offers/projects/new ideas. Eclectic experience in fields like: numerical computing; Python web; Java enterprise; functional languages; GPGPU; SQL databases; etc. Based in Santiago, Chile; telecommute worldwide. CV; email.

Personal Projects

Lepl parser for Python.

Colorless Green.

Photography around Santiago.

SVG experiment.

Professional Portfolio

Calibration of seismometers.

Data access via web services.

Cache rewrite.

Extending OpenSSH.

C-ORM: docs, API.

Recent Threads

Garmin Forerunner 35 v 230

[Link, Politics, Internet] Government Trolls

[Link, Politics] Why identity politics benefits the right more than the left

A Specification For Repeating Events

[Science, Book, Link] Lost In Math

OpenSuse Leap 15 Network Fixes

[Book] Galileo's Middle Finger

[Bike] Chinese Carbon Rims

[Bike] Servicing Shimano XT Front Hub HB-M8010

[Bike] Aliexpress Cycling Tops

[Computing] Change to ssh handling of multiple identities?

[Bike] Endura Hummvee Lite II

[Computing] Marble Based Logic

[Link, Politics] Sanity Check For Nuclear Launch

[Link, Science] Entropy and Life

[Link, Bike] Cheap Cycling Jerseys

[Link, Music] Music To Steal 2017

[Link, Future] Simulated Brain Drives Robot

[Link, Computing] Learned Index Structures

[Bike] Exercise And Fuel

[Maths, Link] Dividing By Zero

Recent Replies

Update - Garmin Express / Connect

GPS Vehicle Tracking for Cat Soft LLC

SSH Forwarding

Low Cost Payroll Service for Cat Soft LLC

A Fight for the Soul of Science


Solo Air Equalization

Update: Higher Pressures


Continental Race King 2.2

Removing Lowers


Mass Hysteria


Update: Lower Pressures

Farellones Bike Park

Update: Second Ride

Chutney v6


C++ - it's the language of the future

Learning From Trump

© 2006-2015 Andrew Cooke (site) / post authors (content).

[Link, Book] Logic Book

From: andrew cooke <andrew@...>

Date: Sun, 12 Aug 2018 19:58:02 -0300


Permalink | Comment on this post

Previous Entries

For comments, see relevant pages (permalinks).

Garmin Forerunner 35 v 230

From: andrew cooke <andrew@...>

Date: Fri, 10 Aug 2018 08:09:12 -0400

These are my initial impressions of a Forerunner 35 after having used
a 230 for some time.

The Forerunner 230 had a huge impact on my cycling - it was the first
GPS or HRM device I owned and key to the wonderful worlds of Strava
and structured training.  When it was damaged in an accident I looked
at what I actually used on the watch and felt that a model 35 would
probably be sufficient as a replacement.

I received the 35 yesterday, so these are my initial impressions on the
physical construction, appearance, and software.  I haven't used it on
a ride yet (decent rides are still several months off, as I slowly
recover from the same accident that damaged the old watch).

Let's start with the watch as a physical object.  The face is a
rounded square, while the 230 was round.  Both look attractive to me -
both look like "sports watches" rather than the newer aesthetic that
Garmin seems to be moving towards (metal bezels and a "someone with no
taste might think this is classy" appeal).  Buttons are slightly
easier to find and use on the round face, but that may be just
experience / practice.  The strap on the 35 seems thinner and
"stretchier" than on the 230.  This may be so that the LEDs on the
back of the 35 make better contact with the skin to measure the heart
rate (more on that later) - it's more annoying to put on because the
strap is floppy and the loop that holds the "free end" is tight.

The 230 had 5 buttons, while the 35 has only 4.  This is annoying -
there is no way on the 35 to move "up" when selecting from menus (or
selecting numerical values).  If you miss your aim you have to
laboriously loop round.

The screen of the 35 is light grey LCD when powered off, which was a
surprise - the 230 looks black.  But when powered on the LCD of the 35
is (usually) "reverse video" so looks similar to the 230.  Some
screens are normal LCD, though, and look uglier.  Also, the 35 may
have slightly lower resolution (looks a little blockier).  I have not
missed the "colour" of the 230 at all (a feature that always seemed
pretty useless).  The body of the 35 is thicker, I think (I don't have
the 230 with me as I type this, so everything about that is from
memory) to include the LEDs.

Both watches are light and comfortable, although I prefer wearing the
watch looser than is recommended with the 35 heart rate sensor.  Both
watches appear to use the same USB connector (a "clothes peg" clip at
the watch end).

Maybe the largest difference between the two watches is the software.
The 35 appears to have completely different software to the 230, which
hints at how they are seen as different products.  The 35 is much
less customizable than the 230.  For example, on the 35 I can find no
way to set which profiles are available, but the previously used
profile is taken as default.  The number of screens is limited (2),
their format does not seem to be variable (3 fields only), and the
variety of values that can be displayed on the screens is reduced.  So
I can find no way to display altitude (from the GPS) or compass
direction (maybe the 35 has no internal compass).

In fact, this is my biggest disappointment with the 35 - I use both
compass and altitude when navigating new routes with contour maps.
Since this is a an obscure, out-dated pass-time I guess it won't affect
most people.

On the plus side, the functionality that the 35 does have is easier to
use.  It was obvious how to set an alarm on the watch, for example
(something that must be possible with the 230, but that I had never
worked out how to do).

When used "as a watch" the 35 measures heart rate automatically.  The
values are generally OK, although I have seen some odd numbers and
it's possible that they trend a little low (after wearing it overnight
it has my average resting heart rate as 39, which seems odd, since I
have done little exercise this last 5 months and my minimum a year ago
- when in much better shape - was 37, according to a medical device
worn for 24 hours).

As I said above, I prefer to wear my watch loose.  When I try this
with the 35 it appears to continue to measure pulse rate (even when on
the inside of the wrist).  So perhaps tightness is not so important.
Anyway, I will probably continue to use my old chest strap when on the

Also, the 35 appears to have a bunch of "lifestyle" features.  This
morning (while in bed, asleep, recovering from a 31 hour trip from S
America to the UK) it beeped at me and told me to "start moving".
Easily visible from the front screen is a step count and a calorie
count (no wonder so many people post to Reddit asking about calorie
use - it's presented like something absolute and reliable, rather than
some random number pulled out of Garmin's ass).

So, how to summarise the differences?  The 35 feels less
"professional" than the 230.  Less like it's intended for one specific
exercise, and more for "general fitness".  The lack of customization,
the extra "lifestyle" features, integrated HRM, and the easier to use
but simplified interface all point in this direction.  Which is all
consistent with how it's promoted and sold by Garmin.

But for the basic use case I want - tracking rides - I think it will
work.  I see no reason why the GPS will not work, or the HRM.  I
probably won't use it day-to-day as a watch, though (I didn't use the
230 this way either) - the HRM makes it bulky and the extra "lifestyle
features" are annoying.



[Link, Politics, Internet] Government Trolls

From: andrew cooke <andrew@...>

Date: Thu, 19 Jul 2018 18:34:56 -0400



[Link, Politics] Why identity politics benefits the right more than the left

From: andrew cooke <andrew@...>

Date: Sat, 14 Jul 2018 18:25:01 -0400



A Specification For Repeating Events

From: andrew cooke <andrew@...>

Date: Thu, 5 Jul 2018 16:21:50 -0400


Calendars need to specify repeating events - things like "the second
Tuesday in every month".  I give a way to specify these, with a simple
text format, and also consider some efficiency issues.

Frames and Locations

Repeating events usually consist of a repeating frame and some
location within that frame.  For example, in "the second Tuesday in
every month", the repeating frame is the month and the location is the
second Tuesday.

Frames may repeat with spacing.  For example, "the second Tuesday in
alternate months".  And there may be multiple locations.  For example
"the first Monday and second Tuesday in ...".


I am only considering day / week / month repetition, but I think
things should extend to finer granularities if needed.

Date Formats and Timezones

I am ignoring timezones (because of the granularity), but if needed a
timezone code could be appended to the following formats.

Calendar dates are ISO format: YYYY-MM-DD.

It is useful to define ordinals for days, weeks and months.  I base
these on the Unix epoch, so day 0 is 1970-01-01, week 0 is the week
(Mon-Sun) that includes that, month 0 is Jan 1970.  To identify the
frame type, when necessary, I used d/w/m.  So 10d is 1970-01-11, 1m is
Feb 1970, etc.

To label days of the week I use the first two letters of the English
name (Mo, Tu etc).  Code should be case agnostic.

Frame Specification

The specification has the form:

  Offset / Repetition FrameType

where offset can be a general data or epoch ordinal that includes a
typical frame or (in the normalized case) the reduced epoch ordinal
(modulo the repetition).  The repetition can be omitted if 1 and
"Offset /" can be omitted if the offset is zero.

So, for example,

   1970-02-01/3m  is a frame that repeats ever three months and
                  includes Feb 1970.

   1/3m  is the normalized form for the above.

More examples:

  d  is a frame that repeats every day.

  1/2d  is a frame for alternate days, starting on 1970-01-02

Nested Frames

At this point a design decision is necessary.  How do we identify
weekdays within a month?  This could be handled with nested frames,
which locate a week within the month, and which could be extended to
locating months within years if the framework were extended to have
years as frames.

Instead, for readability and simplicity of the specification, I will
use a special syntax for this case (see below).

Location Specification

These are grouped in square brackets, comma-separated.

Days of the week or month are numbered, with an optional trailing "d".
So [15] or [15d] is the 15th day of the month.  Monday is the first
day of the week.

It is also possible to identify a week relative to a month using a
number (optional when 1) followed by "w".  So [2w] is the second week.

The above could be extended to included ordinal years, with month
locations.  I don't plan to support this, but the location would be
[3m] for the third month.

For both days and weeks, the number is optional when 1 except in the
case when the "d" is also omitted (so the first day must be either [d]
or [1]).

Days of the week are named, with an ordinal prefix (again, optional
for first).  So [1Mo] or [Mo] is the first Monday, [2Mo,3Tu] is second
Monday and third Tuesday.  This is the special syntax mentioned earlier.

Range Constraints

A specification may only apply for a certain range of dates.  This is
specified as two dates separated by a dash.  Either date is optional
(indicating open ranges) and the dash may be omitted when no dates are

The first date is inclusive, the second exclusive.

The dates are typically in ISO format, but could also be epoch
ordinals.  Since these must match the type (day, week etc) for the
frame they are specified as simple integers.

So 1970-01-01-1970-01-02 and 0-1 are both valid for a frame of days.

Complete Specification

Combining the above in order, here are some examples:

  m[2Tu]  second Tuesday in every month

  2m[2Tu]  second Tuesday in alternate months (Jan, Mar, ...)

  1/2m[2Tu]  second Tuesday in alternate months (Feb, Apr, ...)

  m[2Tu]1970-01-01-1971-01-01  second Tuesday of each month in 1970

  m[2Tu]0-12  second Tuesday of each month in 1970

  0/1m[2Tu]0-12  second Tuesday of each month in 1970

  2018-07-05/5d[1d]  every fifth day, including 2018-07-05

In the above, the location is arguably redundant.  An empty location
specification (ie "[]") means that the whole frame is used:

  2018-07-05/5d[]  every fifth day, including 2018-07-05


In the normalized form the specification exposes information that
allows many candidates to be discarded:

  * Specifications with a date range that exclude the date of

  * Specifications with a reduced offset that does not match the date
    of interest.

  * Locations that do not match the day of interest.

In addition, it appears that an implementation that expands
specifications to dates should be relatively efficient providing there
is an efficient method to calculate epoch ordinals (which must surely
be possible).



* Removed ordinal type from range (must match repeat).


[Science, Book, Link] Lost In Math

From: andrew cooke <andrew@...>

Date: Sun, 1 Jul 2018 15:51:22 -0400



OpenSuse Leap 15 Network Fixes

From: andrew cooke <andrew@...>

Date: Sat, 23 Jun 2018 14:58:34 -0400

I just updated from Leap 42.3 to 15.0 (no idea why the numbering

Since I have had the same config that is updated over the years things
slowly slide into disuse.  This time the networking side took a hit.
Here's what I had to do to get things working again:

* ifconfig has disappeared, so use "ip a" instead.

* My network is pppoe (yeah).  That seems to need restarting explcitly
  but still works (systemd start ppp@...).  I still need to
  understand why this doesn't auto-start.

* Both named and dhcpd seemed to be uninstalled.  So I re-installed
  them and restarted them.  The dhcpd config was moved so had to be
  copied back (/etc/dhcpd.config.rpmsave or similar).

* /etc/resolv.conf seemed to have changed, so copied the netconfig
  version into its place.

* The Firewall has changed.  Yast now delegates to firewalld, but there
  is no text GUI so Yast gives a disturbing message.  What you need to
  do is:

  * Install firewalld, firewall-config and firewall-cmd

  * systemctl start firewalld

  * Run firewall-config and put the local interface in internal
    (the one running and the remote interface (ppp0 in
    my case) in external.  Then enable approriate services in
    internal (and none in external).  Enable masquerading on the
    internal too.

  * There's a "runtime" and "permanent" mode.  You do things in
    runtime first to make sure it works but then seem to have to
    duplicate everything in permanent to make it stick across
    firewall restarts.

  * To get full masquerading you need to follow the incantations

    firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -o eth_ext -j MASQUERADE
    firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i eth_int -o eth_ext -j ACCEPT
    firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i eth_ext -o eth_int -m state --state RELATED,ESTABLISHED -j ACCEPT

    To make those stick, once they appear to work:

    firewall-cmd --direct --permanent --add-rule ipv4 nat POSTROUTING 0 -o eth_ext -j MASQUERADE
    firewall-cmd --direct --permanent --add-rule ipv4 filter FORWARD 0 -i eth_int -o eth_ext -j ACCEPT
    firewall-cmd --direct --permanent --add-rule ipv4 filter FORWARD 0 -i eth_ext -o eth_int -m state --state RELATED,ESTABLISHED -j ACCEPT

With all that, things seem to work.


PS Also, the schumacher clean font has changed, making terminals ugly.


[Bike] Chinese Carbon Rims

From: andrew cooke <andrew@...>

Date: Sun, 6 May 2018 21:25:43 -0300

Carbonfan has 50mm asym, but 19mm internal.



[Bike] Servicing Shimano XT Front Hub HB-M8010

From: andrew cooke <andrew@...>

Date: Tue, 3 Apr 2018 07:45:13 -0300

A quick note because the dealer's manual is unclear, and there's a lot
of confusion on the 'net (every hub being slightly different).

These have caged bearings (plastic cages; lighter on the smaller disk
side).  That means that you have to remove the seal to get the
bearings out.  The seal comes out fairly easilly if you prise with a
broad screwdriver - try a few different spots around the rim until it
pops out.  I have had no problems doing this twice now.

Push the seals back in with your thumbs.

Also, only one cone unscrews (with the 22mm flats, non-disk side).
The other end stays on the axle which pulls out to give access to the
seals / bearings.

Other than that, easy as pie to service.  Lovely hubs.



[Bike] Aliexpress Cycling Tops

From: andrew cooke <andrew@...>

Date: Tue, 27 Mar 2018 16:36:15 -0300

This is a list of cycling clothing I have bought from Aliexpress - the
aim is to collect together sizing information for my own use and also
to provide some guidance to others.

For a discussion of how Aliexpress clothing differs from more
expensive equipment, see

I'm 143cm (5'8"), 64kg (140lb).  50 yo.  Fairly decent shape (gym
regular; no six pack, but no belly either).  Chest measures 94-96cm
(not sure how tight the tape should be).


Miloto (thin, short sleeve, full zip, summer top) - actually bought
from Amazon (for $22), but shipped from China and available in many
Aliexpress stores (from $13).  Asymmetric coloured triangles on black
background (design slightly different from advertised - more text on
one shoulder).

Size S (92cm, measured 96cm).  Close fit (slightly stretched across

Basic cut, but well made with vibrant inks that haven't faded over
several washes.

51 days delivery via China Post.
[example url - not actual store]

No-name Morvelo knock-off from A+Service Store on Aliexpress for $16
(thin, short sleeve, full zip, summer top).  Light blue, green and
black bands with text.  Design is "retro" and original Morvelo was
probably in subdued / aged colours, but this is very bright.

Size M (98cm, measured 99cm).  Normal fit (not tight, but not baggy

Basic cut, with several loose threads, but vibrant inks haven't faded
over several washes.

17 days delivery via 4PX (Aliexpress).
[select third shirt - black/green/blue]

Spexcel from Spexcel Official Store for $20 (thin, short sleeve, full
zip, summer top).  Flower print on black.

Size M (94cm, measured 98cm).  Loose fit (very slightly too large).

Different fabric to others - more stretchy - which would have been
good on a tighter fitting jersey, but with the loose fit the rear
pockets sag and everything feels a little floppy.  More detailing
(cuffs, collar, plackett), well made.

66 days delivery via SF Express.

Jiashuo from Jiashuo Official Store for $23 (thin, long sleeve, full
zip, spring/autumn top).  Coloured bands from dark blue to white.

Size S (93cm, measured 94cm).  Normal to loose fit (sleeves lightly

Like the design - I think it's original, looks very clean.  Basic cut,
but well finished with no loose threads.

44 days delivery via 4PX.

Spexcel from Spexcel Official Store for $29 (fleece, long sleeve, full
zip, winter).  Black w black stripes.  

Size M (94cm, measured 94cm).  Normal fit.

Surprisingly thick / warm and still stretchy material.  Decent length
sleeves.  Good detailing (full inner placket, top of zip fits in
"triangle", zippered chest pocket; zippered rear pocket).

63 days delivery via SF Express.

Spexcel from Spexcel Official Store for $23 (windbreaker, long sleeve,
full zip).  Black.

Size M (96cm, measured 96cm).  Normal to loose fit (good for going
over something and wouldn't want to be tighter because front doesn't
stretch - see below).

Interesting design.  Very lightweight, either (windproof) nylon or
stretchy gauze - gauze on side panels and upper back to allow fit
while cycling.  No pockets.  Very simple, clean, windbreaker.

63 days delivery via SF Express.

Runchita from For Your Service 508 Store for $24 (thin wool mix; long
sleeve; half zip; spring/autumn top

Size M (90cm; mesaure 88cm).  Tight fit (size reocmmended by store for
weight / height; should have used measured sizes and gone with L).

Very good quality.  Nice material (natural feel) with good details.
No pockets and half zip, so not really a cycling top.  Stripe on front
is printed (and not reflective afaict) - does not match cloth stripe
on back.

22 days delivery via 4PX.

Runchita from For Your Service 508 Store for $25 (fleece, long sleeve,
full zip, winter).  Red with black/white stripes on chest.

Size M (96cm, measured 97cm).  Fitted fit (tapers to tight).  Very
long sleeves.

I thought this was an original Runchita design (one image shows a
Runchita tag), but it turns out it's a copy of a Cafe du Cycliste
jersey (although the original is Merino wool).  Still, it's well made
with a placket, zipped pocket, etc.

13 days delivery via Aliexpress

Aoster from HFhaosi-01 Store for $24 (thin, long sleeve, full zip,
spring/autumn top).  Maroon with white arm band.

Size M (94cm, measured 98cm).  Loose fit.

Not as shown on site.  No pocket at neck for zip (a small detail but
shows quality); arm band narrower.  Otherwise fine.

20 days delivery via Aliexpress.


Thin, short sleeves
 Miloto   $22  S/92/96cm  51 days  Close fit   
 No-name  $16  M/98/99cm  17 days  Normal fit  Bright coloured Morvelo
 Spexcel  $20  M/94/98cm  66 days  Loose fit   Stretchy, slow delivery

Thin, long sleeves
 Jiashuo  $23  S/93/94cm  44 days  Normal / loose fit.
 Runchita $24  M/90/88cm  23 days  Tight fit   Great quality, too small
 Aoster   $24  M/94/98cm  20 days  Loose fit   Not as shown on site

Fleece, long sleeves
 Spexcel  $29  M/94/94cm  63 days  Normal fit  Warm, nice details
 Runchita  $25  M/96/97cm  18 days  Fitted fit  Nice details, knock-off

 Spexcel $23  M/96/96cm  63 days  Loose fit   Light / compact

Avoiding Copies

Many shirt designs are copies of products from other companies.  You
may not care, but if you want to avoid these, here are some tips:

* Anything featuring the figure 6 is probably Twin Six

* Morvelo often include their name in the design.  They also have a 
  distinctive zig-zag logo (often on the rear pocket)

* Void often include their name in the design

* Gobik Wear designs often include the text "the custom wear company"

* Rapha often feature either "Rapha" or "RCC"

* Ale have a distinctive logo that is the stylised company name

* MAAP designs often include MAAP in fairly small letters

* The Black Sheep logo is a sheep's head silhouette in a circle

* This Is Cambridge often include a TIC CC logo

More generally, if a design features a particular word, google for
that word plus "cycle wear" and see if you get any hits (this would
have helped me avoid M??rvelo back in the day...)

Also, if the product images are particularly good try a erverse image
search.  And search for unusual names.

Sometimes a shop displays several designs on a single page.  If you
recognise one as a copy then it's likely the others on that page are
also copies of the same company's designs.

Pay attention to all the details.  Even some normally OK brands have
occasional copies (for example, there are some Spexcel bibs stamped

There's also a grey area between a "direct copy" (including logo) and
a "similar design" (eg Spexcel v Rapha).

Related to the above, some brands seem to be "native" to Aliexpress.
For example, my impression is that Runchita and Miloto jerseys are
genuine (with original designs).

Santic is somewhat odd, in that it seems to be priced very high on
Aliexpress, yet sold lower on Amazon (perhaps not the same items).  My
partner bought a pair of their shorts and liked them, but I felt the
padding could have been better for the price.


* All "delivery" times are from placing order to receiving parcel.

* SF Express have the shittiest most unreliable tracking.  

* Given the possibility of copies / fakes, any "make" is only a guess.

* Measured chest is twice width under armpits when laid flat.  I don't
  have an explanation for why measured width and fit aren't more
  closely correlated.



[Computing] Change to ssh handling of multiple identities?

From: andrew cooke <andrew@...>

Date: Thu, 22 Feb 2018 16:53:19 -0300

Just in case anyone else has hit this (only applicable if you have
multiple github accts and use the HostName hack to select keys).

I have multiple github accounts (personal use and work), and each has
a separate ssh key.  This is described at

And that has always worked fine, until today.

Today I saw:

  > ssh -T git@...-isti
  Hi andrewcooke! You've successfully authenticated, but GitHub does not provide shell access.

which is WRONG.  with and the "trick" above, I should
be identified as andrewcooke-isti (and so cannot clone or pull or push
to any work code...)

The fix is to add "IdentitiesOnly yes" to the ssh config:

  > cat ~/.ssh/config

       User git
       IdentityFile ~/.ssh/id_rsa-isti
       IdentitiesOnly yes

I have no idea what changed (could this be OpenSuse config specific?),
but hopefully this will save someone else the pain of debugging...