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.

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

[Computing] Super Potato Bruh

From: andrew cooke <andrew@...>

Date: Wed, 19 Sep 2018 19:48:49 -0300

This is written in Python!


Permalink | Comment on this post

Previous Entries

For comments, see relevant pages (permalinks).

[Computing] Extending Jupyter

From: andrew cooke <andrew@...>

Date: Sat, 15 Sep 2018 22:02:51 -0300

Looking at Jupyter for the GUI for choochoo.  This is a very useful



[Computing, Bike] Activities in ch2

From: andrew cooke <andrew@...>

Date: Sun, 2 Sep 2018 19:34:30 -0300

I'm writing a "training diary" to track cycling.  I've just got to the
point where I can import FIT files and calculate stats:

(env) andrew@...:~/project/ch2/choochoo> dev/ch2 --dev add-activity Cycling /archive/fit/ -f
    INFO: Using database at /home/andrew/.ch2/database.sqlb
    INFO: Creating tables
    INFO: Scanning /archive/fit/
    INFO: Active distance: 19767.220000 m
    INFO: Active time: 3463.000000 s
    INFO: Active speed: 20.549232 km/h
    INFO: Median 5km time: 886.707799 s
    INFO: Median 10km time: 1771.227461 s
    INFO: Median 15km time: 2635.282504 s
    INFO: Percent in Z1: 1.266916 %
    INFO: Percent in Z2: 13.273827 %
    INFO: Percent in Z3: 49.582494 %
    INFO: Percent in Z4: 35.876764 %
    INFO: Percent in Z5: 0.000000 %
    INFO: Time in Z1: 43.873308 s
    INFO: Time in Z2: 459.672617 s
    INFO: Time in Z3: 1717.041751 s
    INFO: Time in Z4: 1242.412324 s
    INFO: Time in Z5: 0.000000 s

Which is for this ride:



[Books, Link] Modern Japanese Lit

From: andrew cooke <andrew@...>

Date: Tue, 21 Aug 2018 16:59:36 -0300



[Link, Book] Logic Book

From: andrew cooke <andrew@...>

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



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 use 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 (bot not the frame type) can
be omitted if 1 and "Offset /" can be omitted if the offset is zero.

So, for example,

   1970-02-01/3m  is a monthly frame that repeats every 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 had years as frames.

Instead, for readability and simplicity of the specification, I will
use a special syntax for this case (see below) [also, "the second
sunday in the month" is more common, and not identical to, "the sunday
in the second week of the month"].

Location Specification

These are grouped in square brackets, comma-separated.

Days of the month or week (1-7) are numbered.  So [15] is the 15th day
of the month (also, remember that weeks start on Mondays).

Days of the week can also be named, with an ordinal prefix (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

Locations outside the frame are ignored (this may be an error or an
expected dependency on context - the 31st day, for example).

A missing location is equivalent to [1] (this is mainly useful for

Range Constraints

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

Both dates are inclusive.  If a single date and no dash is given, then
the event is for a single day.

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-1970-12-31  second Tuesday of each month in 1970

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

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

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

  d2018-07-05  the day of 2018-07-05 (only)


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).

* Removed ordinals from range completely (only dates).  The range
  constrains the expanded locations, not the frame.

* Removed the possibility of locations being anything other than days.

* Allowed [1] to be omitted and a single date as range.


[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.