Archive for October, 2019

One week with the reMarkable tablet

Spoiler: I like it a lot because it fits my workflow.

Why get an e-paper tablet?

I used to keep a small spiral notebook next to my laptop. In this I wrote notes on everything: todo lists for each day, notes from team meetings, notes while debugging some issue, notes from phone calls from friends or family with things to follow up; notes about travel or short story ideas or anything else. It all went into this notebook, in the order of arrival, with no indexing system other than “this probably was a couple weeks ago, let me search about 10 pages back”.

I have about 15 or 20 of these notebooks filled right now, with no dates and no way to retrieve the information once it’s been added and the notebook put away.

What finally pushed me over the edge was the pile of carefully cut pages I kept from the last notebook on unit testing, which I needed to refer to for current work. Inconvenient, if I dropped the pile they would be in random order (because of course not only do I not date the pages in these paper notebooks, I don’t number them either because that would be far too much work). And then I saw a reference to a tablet for writing things down, and reading ebooks. Only for that. Not that I cared
about reading ebooks, I have a laptop for that. But, hey, maybe that added feature would come in handy. And being able to scribble notes on some paper I was reading, that seemed useful, if not my primary use case.

Internet investigations, review scourings and repo perusals followed, and finally one day in a pique of fed-upness I placed the order.

First impressions

It ws quick to arrive, save for passing through customs in my country. I had expected a long delay after seeing a notice about a backlog on their web site. But here was the box, in my hands, several days early. Nice!

The packaging of some products annoys me; it comes off as ostentatious, or wasteful, or bulky for no good reason. The reMarkable’s packaging is low-key, with a tab and ribbon-style opener that reminds one of old hardbound books and slower more thoughtful times. I like it; I kept the box.

There was neither a CD nor a full-fledged user’s guide inside; it took a little time for me to find one online for the current version of the firmware (1.8.1.1). I decided to charge the tablet fully before playing, and set it aside. It felt light in the hand, the cable fit snugly, and the pen looked and felt like any stylus pen, a tool for the work and
nothing more. I did notice approvingly the hidden spare nib under the cap.

First use

Of course I didn’t really read the user’s guide right away, are you kidding? Instead I checked for the basics: how to create a folder, how to create a notebook, how to create a page. Then I created a few folders to organize my work; never again all my notes in order in one giant blob! and I started writing.

The writing experience really is superb, not at all the slick uncontrollable gliding all over the surface that so many tablets provide.

For whatever reason, I found that my grip on the stylus caused discomfort and hand cramping after a time. That’s no longer true after a week; my hand must have naturally adjusted to a proper position.

I found that the pencil without tilt and a medium tip, on the narrow-lined template, works very well for my style of note-taking. My style is basically “fit in as much as you can on one page, writing all the way up to the margins, and with bullets or indentation for lists, while keeping it legible.”

That last part about keeping it legible is a lie; often in my paper notebooks I would refer back to some scribbled note later only to discover that I had no idea what it said. I write just a bit slower on the tablet, whether due to the stylus-screen interaction or because I’m kinder to expensive electronic devices than paper. In either case,
my notes remain legible when I go back to review them, and I find I cheerfully erase if the letters turn into a blob from hurried scribbling.

I did not make a cloud account, since I don’t really want to be dependent on a third party cloud to store and retrieve my backups.

Discoveries

In page overview mode, the top part of the page is not visible, and my handwriting is much too small and uniform to be a guide to which content is where. I needed headers, a few inches down in the page. The brush, with a medium tip, was perfect for this.

I discovered the partial and full toolbar hide buttons. Now I almost exclusively work with all toolbar buttons hidden. I’d like the page overview and move buttons to be visible in the partial toolbar, but other than that I have no complaints.

I discovered that if you are at the last page of a notebook, pressing the right button on the bottom of the tablet to take you to the (non-existent) next page creates a new page for you, saving the trouble of unhiding the toolbar, pressing the new page button, and hiding it again.

I discovered that the last page you viewed is the page you see during light sleep mode. Most of the time I make sure that’s my todo list for the day.

Hardware functionality

The battery drains pretty quickly the way I use the tablet. I’ve turned off WiFi, since I don’t need it on for regular use, and that helps.

After a week, the stylus nib has “mushroomed“, i.e. the tip has squashed flat and the edges hang over the sides like a mushroom cap. It doesn’t (yet) seem to affect ease and feel of writing on the screen, so I’ll keep using the nib as is for now.

During the first several days I found I needed to press harder on the stylus than I would with pencil on paper. That too seems to have improved over time; whether wearing down the nib or unconscious adjustment of the hand position made the difference, writing now takes a relatively light touch, without the slipping and sliding on smooth glass so common on most tablets.

The previous and next buttons don’t always work; sometimes I have to press very firmly and deliberately in the center of the button after the first slapdash push fails to elicit a response. Dunno if that’s hardware or software but I can shrug it off for now.

Workflow

I have a todo list for each day; I have two notebooks per month of these, one for the first half and one for the second half. (The reason I don’t keep one per month is that I’ve read that at around 30 pages, page turning gets slow. This could be true only for pdfs; I haven’t tested it yet.)

If I need notes from some todo item that I know are temporary, I’ll create a page after the day’s todo list and work there. When I’m done with the work, I’ll either summarize it and put it in a separate file in the right folder, or more often, delete the scratch page(s).

For entertainment I follow political developments, and these notes go in pages with separate headings in the QuickSheets file. At the end of a day or a few days, when speculation about a pending event has resolved, I delete a bunch of stuff and write a summary of the event, deleting any now unneeded
pages.

Notes for work that I know I’ll need to reference again get put in a notebook in a subfolder somewhere under my work folder. We’ll see how effective this is after 6 months or a year; a week is not nearly enough time to see how the retrieval system will hold up.

My paper notebook is sitting on the shelf and I’ve not touched it at all save to copy over those unit testing notes into the tablet.

Customization

I used to run a bleeding edge kernel on my laptop, with a custom build. I used to maintain my own xterminal key mappings for my editor. I used to customize anything and everything. Years go by and one gets bored of constant tweaking, so I had planned not to mess with anything that couldn’t be done in the
tablet configuration settings via the UI.

Heh. The best-laid plans, etc.

I now have a custom full sleep screen, a custom power off screen, rsync on my tablet (built via the official toolchain from a clone of the rsync repo at samba), a script to rsync all of /home/root to the laptop, and I’m working on extending it to be able to upload pdfs to the tablet from my laptop.

Oh and of course I don’t use the annoying generated password to ssh into the tablet, I have a public key over there, which makes the rsync script nicer.

I have been looking at available templates shared by tablet users and thinking about what might be handy to have. No new templates uploaded yet, however.

I plan a script that will copy back in all custom files after any software update, runnable from the home directory. A one line command after each firmware update is pretty painless, and I’m happy to live with that for the huge gain in functionality with rsync on the device, and the smile that seeing one of my photos as the sleep image brings.

Proposed improvements

Copy-paste of a selected area from one page to another would be a huge win. I often want this when cleaning up temporary notes and distilling out of them the few pieces of information I want to save permanently.

Move and Page Overview icons on the partial menu view, so I don’t have to open the full menu to get to them.

A stylus with an eraser on the back end. I might get the MobiScribe stylus (I hear it takes the reMarkable nibs) just for this reason. I like to be able to stop and erase that e that I just wrote that looks like an ink blot, without having to open up the partial menu to get to the eraser.

Cheaper or longer-lasting nibs, without sacrificing one iota of the writing experience.

A much cheaper price for the tablet when it goes truly mass market. That would be a game-changer.

A public site to submit and follow bug reports, with user comments permitted. Right now there’s the reddit group where some issues are discussed (and sometimes solved!) but it would be nice to have an official site.

A published spec for the .rm files. Folks have reverse engineered them, but a published spec means a commitment to updating that spec when and if the format of these files changes. This would be encouraging to the third party app developer community, a group of people that not only add functionality to the device, but help to publicize it as well. That’s free marketing, always a good thing!

Warning

This tablet is like paper, in that if someone has access, they can read whatever you wrote. Oh sure, I put a pin code on there, but it feels like a very flimsy chain on one’s front door that someone really determined can just shoulder their way through.

So, no sensitive data on the tablet. No notes about vendor contracts, no notes about personal matters that I wouldn’t mind being leaked to the world, etc. This is fine; for those limited instances there’s always editing files on the laptop.

Final verdict

This tablet doesn’t play video and I don’t want it to. Ditto for web surfing, reading email, having a calculator app, and so on. All those things are activities for my laptop. The tablet is for taking and reading notes. It does that very well, so far. It is pricey as a device, but if your workflow is like mine, and you are not too tight on funds, it’s worth it.

Disclaimer

I don’t have any affiliation with any company that produces any tablets or phones or any of that. I’ve never gotten a review copy of any such thing. No one paid me, gave me chocolate or did anything else for me so that I would write a positive (or negative!) review.

If you get the device after reading this review, and it doesn’t meet your expectations, I’m sorry. BUT I am also not responsible in any way. Happy writing!

Digging into Structured Data for Media on Commons

Commons: Not a tragedy

Commons. What Commons?

If you are a contributor to Wikipedia or one of the other Wikimedia projects, you probably already know. If you aren’t, even as a frequent Wikipedia reader (and aren’t we all?), you may not know that almost all of the photographs and other images in the articles you read are hosted in a media repository, commons.wikimedia.org.

These images are generally free to reuse, modify, and share, for any purpose including commercial use. You can also create an account there and upload your own photographs, as long as they have educational value.

Image from Commons

Searching for cats on Commons

Structured Data is GREAT

But let’s suppose you want to sort through the media for some reason; maybe you want to find all of the photographs of edible wild mushrooms in your region, with the name of each species. Or maybe you want cute cat pictures. You could try the search tab and hope for the best, but all of the information about an image is in a blob of unstructured text and formatted any sort of random way. You could look at the categories and see if you’re lucky enough that one category covers your needs, but odds are that for anything except the simplest of queries, you’ll come up empty-handed.

What about getting that information in a language other than English? Good luck with that; although the project is shared among speakers of many different languages, the predominant language of contribution and of category names is still English.

Suppose you want to monitor newly uploaded images for any of the above, via a script. How can you do that? With difficulty.

Until now.

Structured data allows contributors to add a caption or information about what is depicted, to each uploaded media file, in any language, or in multiple languages. While the file description is still an unstructured string of text per language, descriptions in multiple languages can be specified and descriptions can be extracted for a media file independently of anything else. The same holds true of captions, and more data is likely to be added in the future.

Why am I writing about this? I produce dumps, so what do I care?

Introducing Mediainfo entities

Ah ha!  Someday () we will be producing dumps of this data. You’ll have files that contain all Mediainfo entities, much as there are now files containing the various sorts of Wikidata entities (see ) for download every week. And since we’re going to be dumping it, we need to understand the data: what is its format? How can we retrieve it via the MediaWiki api? How can we set it?

Mediainfo entities are similar-but-different from Wikibase entities. They are similar in that they have a special format (json) and cannot be edited directly via the wiki ‘edit source’ or ‘edit’ tabs. They both rely on the Wikibase extension as well. But Mediainfo entities are not stored in a set of separate tables, as Wikibase entities are. Instead, Mediainfo entities are stored in a secondary slot of the revision of the File page.

Wait, wut? What are slots? And what the devil is a ‘secondary slot’?

A side trip to Multi-Content Revisions

Time for a crash course in ‘Multi-Content Revisions’, also known as MCR. Until last year, MediaWiki had the following data model, as tweaked for use at Wikimedia:

  • Each article, template, user page, discussion page, and so on, is represented by a record in the ‘page’ table.
  • Each edit to a page is represented by a new record in the revision table.
  • Once a revision is added to the table, it never changes. It can be hidden from public view but never really removed.
  • A revision contains a pointer to a record in the text table.
  • The text table record contains a pointer to a record in a blobs table on one of our external storage servers.
  • The blob record contains the (usually gzipped) content of the revision as wikitext or json or css or whatever it happens to be.

So: one revision, one piece of content. And for articles (and File pages), that means one blob of wikitext with whatever formatting various editors have decided to give it.

But suppose…. just suppose that we could attach pieces of data to that page, also editable by contributors, and that could be displayed in a nice table or some other good data display format. A caption for an image, who or what’s in the image, maybe the creation date, maybe the name of the photographer, maybe EXIF data right from the image. Wouldn’t that be nice? Imagine if all of that data was available via the MediaWiki api, or easily searchable. Wouldn’t that be just grand?

That’s what Multi-Content Revisions are all about. That ‘extra data’ has to live somewhere and still be attached to a revision. So: slots. The ‘main slot’ contains wikitext or json or css or whatever the page normally has, that a contributor can edit the usual way. ‘Secondary’ slots, as many as we define, can have other data, like captions or descriptions or whatever else we decide is useful.

Now each edit to a page is represented by a new record in the revision table, but a revision contains a pointer to one or more entries in the slots table.

Each slot table entry contains a field indicating which slot it’s for (main? some other one?) and a pointer to an entry in the content table.

Each content table entry contains a pointer to a record in the text table, but at some point it will likely point directly to a blob on one of our external storage servers.

Back to Mediainfo entities

A Mediainfo entity, then, is a kind of Wikibase entity, structured data, in json format, that is stored in the ‘mediainfo’ slot for revisions of File pages on Commons.

Structured data tab for a file

This is easier to wrap one’s head around with an example.

If you look at https://commons.wikimedia.org/wiki/File:Marionina_welchi_(YPM_IZ_072302).jpeg you can see below the image that there is a ‘Structured Data’ tab. ‘Items portrayed in this file’ has a name listed.

If you look at the edit history for the file, ‎you can see an entry with the following comment:

Created claim: depicts (d:P180): (d:Q5137114)

This means that someone entered the depiction information by clicking ‘Edit’ next to the ‘Items portrayed in this file’ message, and added the information. You can do the same, in any language, or you can modify or remove existing depiction statements.

JSON for “Depicts” data

Let’s see what the raw content behind a ‘depicts statement’ is.

We can get the content of a Mediainfo entity by providing the Mediainfo id to the MediaWiki api and doing a wbgetentities action. But first we need to get that id. How do we do that?

Here’s the trick: the Mediainfo id for a File page is ‘M’ plus the page id! So first we retrieve the page id via the api:

https://commons.wikimedia.org/w/api.php?action=query&prop=info&titles=File:Marionina_welchi_(YPM_IZ_072302).jpeg&format=json

There’s the page id: 82858744. So now we have the Mediainfo id M82858744 we can pass to wbgetentities:

https://commons.wikimedia.org/w/api.php?action=wbgetentities&ids=M82858744&format=json

And here’s the output, prettified for human readers like you and me:

{
  "entities": {
    "M82858744": {
      "pageid": 82858744,
      "ns": 6,
      "title": "File:Marionina welchi (YPM IZ 072302).jpeg",
      "lastrevid": 371114515,
      "modified": "2019-10-19T08:11:24Z",
      "type": "mediainfo",
      "id": "M82858744",
      "labels": {},
      "descriptions": {},
      "statements": {
        "P180": [
          {
            "mainsnak": {
              "snaktype": "value",
              "property": "P180",
              "hash": "bfa568e1a915cc36538364c66cbfeea50913feea",
              "datavalue": {
                "value": {
                  "entity-type": "item",
                  "numeric-id": 5137114,
                  "id": "Q5137114"
                },
                "type": "wikibase-entityid"
              }
            },
            "type": "statement",
            "id": "M82858744$21beba99-41e7-a211-66ac-1cacc78b806d",
            "rank": "preferred"
          }
        ]
      }
    }
  },
  "success": 1
}

You can see the depicts statement under ‘statements’, where ‘P180’ is the property ‘Depicts’, as seen on Wikidata. ‘Q5137114’ is Marionina welchi, as seen also on Wikidata. The P-items and Q-items are available from Wikidata by virtue of Mediainfo’s use of “Federated Wikibase”; see https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/Wikibase/+/master/docs/federation.wiki for more on that.

Note!! Since the page id of the File page is effectively embedded in the Mediainfo text blob as stored in the database, any change to the page id can break things. See https://phabricator.wikimedia.org/T232087 for an example!

Raw content of “Depicts” statement

What is the raw content of the slot for that revision in the database, you ask? I’ve got a little script for that. (Link: https://github.com/apergos/misc-wmf-crap/blob/master/get_revision.py) Here’s what I get when I run the script:

{"type":"mediainfo","id":"M82858744","labels":[],"descriptions":[],"statements":{"P180":[{"mainsnak":{"snaktype":"value","property":"P180","hash":"bfa568e1a915cc36538364c66cbfeea50913feea","datavalue":{"value":{"entity-type":"item","numeric-id":5137114,"id":"Q5137114"},"type":"wikibase-entityid"}},"type":"statement","id":"M82858744$21beba99-41e7-a211-66ac-1cacc78b806d","rank":"preferred"}]}}

That’s right, all that mainsnak and snaktype and other stuff is right there in the raw slot content.

How statements work

A statement (in Wikidata parlance, a “claim”), is an assertion about a subject that it has a certain property (Pnnn) with a certain value. If the value turns out to be a person or a place or something else with a Wikidata entry (Qnnn), then that id can be used in place of the text value.

Here’s an example:

Boris Johnson holds the position (P39 “position held”) of Prime Minister of the UK (Q14211). But this hasn’t always been true and it won’t be true forever. This statement therefore needs qualifiers, such as: P580 (“start time”) with value 24 July 2019.

A “snak” (chosen as the next largest data item after “bit” and “byte”) is a claim with a property and value but no qualifiers.

In our case, an image can depict (P180) some person or thing (Q-id for the person/thing if there is one, or the name otherwise). Or it can have been created by (P170) some person. Or it can have been created (P571) on a certain date. The point is that statements (claims) of any sort can be added to a Mediainfo entity. However, some care should be taken before adding statements involving properties other than P180 and P170, preferably after discussion and agreement with the community. See https://commons.wikimedia.org/wiki/Commons_talk:Structured_data/Modeling for some of the discussion around use of properties for Commons media files.

For a note on the terminology “statements” vs. “claims”, see https://phabricator.wikimedia.org/T149410.

For more about snaks and snaktypes, see https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/Wikibase/+/master/docs/json.wiki#261.

Looking at Captions

Let’s find a File which has a caption. I’ve already found one so we’ll just use it as an example:

https://commons.wikimedia.org/wiki/File:Stra%C3%9Fenbahn_Haltestelle_Freizeit-_und_Erholungszentrum-3.jpg

Underneath the image, in the ‘File Information’ tab, you can see the entry ‘Captions’, and there are some! If you select ‘See 1 more language’ you can see that there are two captions, one in English and one in German.

Let’s get the Mediainfo id for that file:

https://commons.wikimedia.org/w/api.php?action=query&prop=info&titles=File:Straßenbahn_Haltestelle_Freizeit-_und_Erholungszentrum-3.jpg&format=json

Great, it’s 83198284. Let’s plug M83198284 into our wbgetentities query:

https://commons.wikimedia.org/w/api.php?action=wbgetentities&ids=M83198284&format=json

{
  "entities": {
    "M83198284": {
      "pageid": 83198284,
      "ns": 6,
      "title": "File:Straßenbahn Haltestelle Freizeit- und Erholungszentrum-3.jpg",
      "lastrevid": 371115009,
      "modified": "2019-10-19T08:16:04Z",
      "type": "mediainfo",
      "id": "M83198284",
      "labels": {
        "en": {
          "language": "en",
          "value": "Tram stop in Berlin, Germany"
        },
        "de": {
          "language": "de",
          "value": "Straßenbahn Haltestelle in Berlin"
        }
      },
      "descriptions": {},
      "statements": []
    }
  },
  "success": 1
}

Captions are called ‘labels’ and are returned by language with a simple text value for each caption. What’s the raw data, you ask?

{"type":"mediainfo","id":"M83198284","labels":{"en":{"language":"en","value":"Tram stop in Berlin, Germany"},"de":{"language":"de","value":"Stra\u00dfenbahn Haltestelle in Berlin"}},"descriptions":[],"statements":[]}

Pretty much as we expect, the entity type and id are stored along with the labels, with one entry per language.

Looking at Descriptions

Just kidding!  More seriously, there’s a placeholder for descriptions but that’s due to be removed (see https://phabricator.wikimedia.org/T213502) since captions suffice.

Looking at anything else

I’ve got a script. It’s crap because all code is crap, and all code not written for production is especially crap, and code witten for personal use just to get the job done is extra especially crap. Nonetheless, I use this python script to get the Mediainfo entity for a given File on Commons: https://github.com/apergos/mw-scripts-crapola/blob/master/get_mediainfo.py and it gets the job done.

The Big Payoff: Search

Let’s find some images on Commons using this data. Go to the main page and let’s search for any media with a “depicts” (P180) statement, by entering “haswbstatement:P180” in the search bar.You can check the Structured Data tab below the image of any of the files in the result, and see what’s depicted.

But that’s not all! You can specify what you want depicted: haswbstatement:P180=Q146 will find any media file marked as depicting a… https://www.wikidata.org/wiki/Q146 just by entering it into the search bar.

And that’s still not all! You can specify that you want only those pictures with captions in English and that depict Q146’s by entering hasdescription:en haswbstatement:P180=Q146. Note!! Captions used to be specified by the keyword “hascaption” but this has been changed, though you may see it referenced in older documentation or blog posts.

But there’s more! You can specify that you want pictures that depict something, created by someone else, with captions in some languages but not others, and CirrusSearch will serve that right up to you. Try it by searching for haswbstatement:P170=Q34788025 haswbstatement:P180=Q158942 hasdescription:en -hasdescription:fr and check the results.

But… you guessed it, that’s still not all. You can search for all media files that have a specified text in the caption, in addition to any other search criteria! Try it by searching for incaption:dog hasdescription:fr and check any file in the results.

Bonus: Editing!

I’ve got a script. It just updates captions because the format of those is the easiest, but if you look at it and the api help docs you can figure out the rest.

Script: https://github.com/apergos/misc-wmf-crap/blob/master/glyph-image-generator/set_mediainfo.py

MediaWiki api help: https://commons.wikimedia.org/w/api.php?action=help&modules=wbeditentity

Further Reading

There’s lots more to explore, so here’s some links to get you started.

Credits