Dan Paul Smith

Interface and visualisation developer.

Friday, 19 April 2013


Have been using Wikipedia a lot recently, the text ran too wide. Fixed it up a little bit with some CSS:

You'll need to create a Wikipedia account, then go to Preferences > Appearance > Shared CSS for all themes (common.css) and paste this in.

You might want to adjust the height for the #toc (table of contents). 500px suits my screen.

div#content { font-family: Helvetica; font-size: 18px; background-color: white; border: 1px solid #A7D7F9; color: black; direction: ltr; margin-left: 30% !important; margin-top: -1px; padding: 1em; width: 40%; } #mw-panel { padding-left: 0.5em; visibility: hidden; } #toc, .toc, .mw-warning { left: 10px; position: fixed; top: 80px; } #left-navigation { left: 10px; } #right-navigation { left: 30%; margin-top: 2.5em; position: absolute; } #p-personal ul { list-style-image: none; list-style-type: none; margin: 0; padding-left: 29%; } table#toc.toc tbody tr td > ul { height:500px; overflow-y:auto; }

This guy spent a bit more time than me on his skin, much nicer:

 * Style by Lupurus

@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document domain("wikipedia.org") {


@-moz-document regexp("(.*wikipedia.org/wiki/(?!.*:)(?!Main_Page).*)|(.*secure.wikimedia.org/wikipedia/../wiki/(?!.*:)(?!Main_Page).*)") {

#firstHeading {
    width: 800px !important;
    text-align: center !important;
    font-size: 4em !important;
    -moz-hyphens: auto;
    -webkit-hyphens: auto;
    hyphens: auto;
    font-weight: bold !important;
    text-shadow: 4px 4px 0 #DDD;
#firstHeading i:first-child {
    font-style: normal !important;
#firstHeading, h1, h2, h3, h4 {
    font-family: Palatino !important;

#bodyContent {
    width: 800px !important;
    text-align: justify;
    -moz-hyphens: auto;
    -webkit-hyphens: auto;
    hyphens: auto;
    font-family: Palatino !important;
    font-size: 12pt !important;

 * border around the article
#content {
    -moz-box-shadow: 0px -10px 30px #BBB;
    -webkit-box-shadow: 0px -10px 30px #BBB;
    box-shadow: 0px -10px 30px #BBB;
    margin: auto !important; 
    width: 800px !important;
    padding: 80px !important; 
    padding-top: 20px !important;

body {
    background: #FFFFFF !important;

#content {
    background: #FFF !important;    /* removes the border of the menu */

/* margins */
.infobox, .tright, .vertical-navbox {
    margin: 0 0 0.5em 2em !important;
.tleft {
    margin: 0 2em 0.5em 0 !important;

 * hide things
#mw-head, #mw-head-base, #mw-page-base, #footer, .editsection {
    display: none !important;

#mw-panel {
    opacity: 0;

#mw-panel:hover {
    opacity: 1;

 * numbering of the headings
 body {
    counter-reset: headingOne;
#toctitle h2:before {
    content: "" !important;
    counter-reset: headingOne;
h2 {
 counter-reset: headingTwo;
h2:before {
 counter-increment: headingOne;
 content: counter(headingOne) ".";
h3 {
    counter-reset: headingThree;
h3:before {
    counter-increment: headingTwo;  
 content: counter(headingOne) "." counter(headingTwo) ".";
h4 {
    counter-reset: headingFour;
h4:before {
    counter-increment: headingThree;
    content: counter(headingOne) "." counter(headingTwo) "." counter(headingThree) ".";
h5:before {
    counter-increment: headingFour;
    content: counter(headingOne) "." counter(headingTwo) "." counter(headingThree) "." counter(headingFour) ".";


Wednesday, 27 February 2013

Exporting JSON data as CSV

Struggled a bit with encoding, escaping and headers.

Solution below:


    columnDataToCSV : function(id) {
        var results = typeof columnData[id].results != 'object' ? JSON.parse(columnData[id].results) : columnData[id].results;
        var str = '';
            1            | 2                    | 3                | 4            | 5        | 6                | 7            | 8            |
            Event type    | Content             | Date            | Time        | Notes | Tags             | fromUser     | toUser    |
            Tweet        | I'm eating eggs!    | 01/04/2013    | 18:01:12    | None    | 123764, 41235    | spode        | mled        |
        // Headers
        str += '"Event type","Content","Date","Time","Notes","Tags","fromUser","toUser"\r\n';
        // Loop through column events
        for (var i = 0; i < results.length; i++) {
            var line = '';
            // Event type
            // line += '"' ++ '",';
                line += '"' +results[i].eventType+ '",';
            } else {
                line += ',';
            // Content
               line += '"' +results[i].text+ '",';
            } else {
                line += ',';
            // Date
                // Date
               line += '="' +results[i].occuranceTime.split(" ")[0]+ '",';
               // Time
               line += '="' +results[i].occuranceTime.split(" ")[1]+ '",';
            } else {
                line += ',';
            // Notes
               line += '"' +decodeURIComponent(results[i].notes[0].note)+ '",';
            } else {
                line += ',';

            // Tags
                line += '"';
                for(var x=0; x<results[i].Tags.length; x++){
                    line += Robin.data.tags[results[i].Tags[x].tagId].name + (x==results[i].Tags.length-1 ? '' : ', ' );
                   line += '",';
            } else {
                line += ',';
            // fromUser
               line += '"' +results[i].fromUser+ '",';
            } else {
                line += ',';
            // toUser
               line += '"' +results[i].toUser+ '",';
            } else {
                line += ',';
            // Remove the last comma
            str += line + '\r\n';
        return str;

    exportToCSV: function(id){
        var name = "myCSVFile";
        var csvString = encodeURIComponent(columnDataToCSV(id));
        var form = $('<form />');
        $('<input />').attr('name','filename').val(name).appendTo(form);
        $('<input />').attr('name','csvdata').val(csvString).appendTo(form);



$csvdata = $_REQUEST['csvdata'];
$filename = $_REQUEST['filename'];

header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=$filename.csv");
header("Pragma: no-cache");
header("Expires: 0");

function utf8_urldecode($str) {
    $str = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;", urldecode($str));
    return html_entity_decode($str,null,'UTF-8');
echo utf8_urldecode($csvdata);


Monday, 5 November 2012

Maps at the Affordable Art Fair

A friend of mine had a spare ticket to the opening night of the Affordable Art Fair this year. It was situated inside a pop-up building (like a giant gazebo) on Hampstead Heath and by "affordable", they mean that there's artwork in the range of £40-£4,000 on sale.

It took about 3 hours to walk around the place (very slowly, while squinting and taking pictures of things) - it was split into 6 aisles I think, with paintings, prints and sculptures tucked into every nook and cranny. It was enjoyable, there was some amazing art there. I'm usually very peculiar about what I like / don't like, and have to say that I was enjoying myself massively, talking to exhibitors while trying to avoid leading anyone on to think I was there to buy something.

What caught me by surprise, and is the reason for this post, was the amount of map related art. I've just started a masters degree that heavily involves maps and mapping things, so here I was in an art gallery with the art world and tech world once again colliding for me.

I managed to snap them all.


Start up idea: a clothing company that let's you order custom-printed jumpers/t-shirts of a segment of a map. I think maps would look cool on people, not just walls.

Animal Garden

Maps made out of animals. Not sure if they're related to the countries they're forming.

Currency map

I really like this map. Shame it cost a few grand. A country's currency slices through it (as well as overlapping into any neighbouring countries) along with time zone separations and a bit of a colour boost I guess - currency isn't that colourful is it?

Debt map

A map made of credit cards from different countries.

 Postcode map

A piece of work from my friend's gallery. Nice use of colour, not quite my thing though, I'm usually after a pattern or two.

Great Britain currency map

Shiny currency map for GB.

Gold leafed New York map

Really nice monochrome, highly detailed map of New York. No matter where I stood, the fantastically placed spotlights got in the way.

Modern London

This looks like an old map of London, but features modern landmarks like the London Eye. Weird chymera-like animal things dotted around. Couple of butterflies thrown in.

The lost rivers

London's lost rivers printed on porcelain. Not sure if it's accurate. Definitely creative. Porcelain usage related to us flushing toilets? I forsee a 3D printer plugin for ArcMap.

World cow map

Can't quite remember this one. The map's got numbers on it, relating to the cows I think. I think it's a map that shows you what type of patterned cow you get in different countries? Only a guess.

London A-Z cutouts

How cool are these? The amount of effort that's gone into these is admirable. They've all had spatial features that aren't roads, rivers or bridges sliced out, especially the third picture that's had 6 pages sliced and overlaid on top of each other while still in the original book (which looks really old as it is). I noticed people standing next to me were tracing the newly formed routes. I think I overheard someone explaining to their mate that if they left their house in Primrose Hill, they could turn left, right and be in Paddington. Magical. I would actually quite like to build my own London map, using just the places and things that interest me. And then download or print it. Or wear it.

Blurred boundaries

This is infact a county, I - and the gallery assistant - didn't know which country this was, they seemed to think it was in the Carribean somewhere despite the snowy background. People as a continuous field? I like it.

So yeah, there we have it. Loads right? Good old maps. Always intersting, whether you're a lamp post or a person.

Monday, 23 April 2012

Bathing Water Quality visualisation

Using the Environment Agency's bathing water quality data provided by DEFRA and UK Location, I've whipped up a very quick visualisation of my own - showing off indicators for faecal bacteria at the bathing sites.

The data source:


Notable parameters I used:
  • view = "basic" view
  • properties = lat, long, total coliform count, faecal coliform count, faecal streptococci count
  • page size = 500
  • sort = by faecal streptococci count (descending)
The steps to create the visualisation:
  • Realised I was quite interested in seeing where the bathing sites were that contained the most faecal bacteria (Blackpool area by the looks of it)
  • Tailored my own API call using instructions from the API documentation.
  • Tried using Yahoo Pipes and other connecting API thingys to see what I could do within about 5-10 minutes.
  • Decided to use Googles Fusion Tables as it can create maps from spreadsheet data
  • The Enviroment API offers several formats, so I just changed my API call to include ".csv" intsead of ".html".
  • Then, after spending the last half year developing the LinkedGov extension for Google Refine - I immediately thought of it as the first go-to tool to shape the data and make it fit for importing into some sort of mapping API.
  • I used Google Refine's faceting & number range features to decide how to split the bacteria counts into low, medium and high.
  • I exported the data from Refine as CSV to my computer.
  • I uploaded the CSV into Fusion Tables - and all the hard work was done for me!
  • Time taken = 15 minutes (I have experience with the Linked Data API - otherwise it would have taken me a little while longer to tailor the API call I wanted)
Please note: I have manually adjusted the banding points for the levels of bacteria so the visualisation showed a visually pleasing number of red, yellow and green markers. While a site may have a red marker - it could actually be of quite high water quality.

Total Coliform Count
Low-temperature electron micrograph of a clust...
Low-temperature electron micrograph of a cluster of E. coli bacteria, magnified 10,000 times. Each individual bacterium is oblong shaped. (Photo credit: Wikipedia)

Faecal Coliform Count

Faecal Streptococci Count
Gram-stained smear of streptococci
Gram-stained smear of streptococci (Photo credit: Wikipedia)

Monday, 5 December 2011

Government posts visualisation with Isotope

I found this visualisation on my server this morning - hadn't looked around the directory structure for ages and forgot I'd made it. I think it's quite cool, might think about carrying on with it in some way or another.

You can play with it here:


You can replace "dft" with a department acronym (e.g. co, dfe, hmrc...).

Ten years of road deaths (visualisation)

BBC have plotted the road incidents resulting in death for the last ten years in the UK.

I'm sure I've come across this before, but it's a good visualisation.

Simple, meaningful and accurate.

Link: http://www.bbc.co.uk/news/uk-15975720.

Wednesday, 5 October 2011

Interface fail - iCal (Lion)

After I've carefully and lovingly filled out a calendar entry, I go ahead and click "Delete".

Tuesday, 16 August 2011

London Tube Station passenger counts - 2009

Transport for London have just released a set of APIs that return various types of transport information for the city. Below is a little bar chart of London tube stations using the Passenger count API. Looking forward to using the APIs in the future!

Monday, 15 August 2011

Interface evolution - Football Manager

This is what will hopefully be the first in many posts on a particular evolving interface - an interface that people use, offline or online. I'm not quite sure what I aim to be talking about, but they'll basically be to express my thoughts and share my observations on what I think are interesting interfaces.

Thursday, 30 June 2011

MAudio Audiophile - An ongoing saga

I'm not sure how long I've had this piece of kit, but damn it's been a nightmare. It's literally a matter of luck whether it works and I've always spent just long enough for me to hit a lucky setting or switch that seems to touch it's sweet spot.

I'm documenting what I've done incase anyone else out there is Googling away while pulling their hair out.