EU flag minus UK star


I think, therefore I am.


I'm a lecturer on sabbatical at De Montfort University (DMU) where I've been teaching various modules such as front-end web development, functional programming, and research to a variety of students from different courses across the Faculty of Computing, Engineering, and Media.

I also spend time programming for Ecovisum.

I'm a transdisciplinary creative generalist. I have passion for what I do, and what I think is right. Sometimes that involves saying "no".

My sense of purpose is my own - I'm an introvert.


I have a PhD in Software Engineering/Computer Science. The title of my thesis is Algorithmic Meta-Creativity and it's available as HTML or PDF at

My research interests revolve around studying human and computer creativity and how they are evaluated, the absurd pseudo philosophy pataphysics and its applications, and the development of creative exploratory search algorithms inspired by pataphysical concepts.

Although the PhD wasn't classed as "practice-based" research, an artefact was submitted alongside the thesis. The software for this was written (mostly) in Python.


Internal: Home About Bookmarks Images Haskell Cheats
External: GitHub Teaching CodePen Dave


Code and Art Projects

Magic Squares
Classes of magic squares shown in overlapping sets

Magic Squares

The magic square app can visualise the magic line in various different artistic styles.

The magic lines are drawn using SVG.

Node, intersection observers, service workers, Couch backend.

Also uses Haskell algorithms for generation of sets.

Basheau Poems
Screenshot showing interface of Basheau Poems

Basheau Poems

Basheau Poems is a mashup of Bashō's haikus and Quenueau's hundred thousand billion poems mechanism.

It is a fully responsive website hosted on my own server.

A prototype can be found on codepen.

Magic Carpet Visualiser
Magic carpet and magic square highlighted within

Magic Carpet Visualiser

A (theoretically infinite) magic carpet can be constructed from a single magic square of a special kind of class. Demonstrates magical properties of carpet and draws the magic line of any magic square within.

Uses HammerJs, SVG, and JavaScript. Source code can be found on GitHub.
Screenshot of sonnet called "conspiracy"

Pataphysics WTF

The website is a poetic search engine produced as part of wider PhD research.

The app is written in Python and uses Natural Language Processing, WordNet, various APIs, and custom written search algorithms.

Art image by Sally Wilson

Dr Physics WTF

This website:, is an online version of my PhD thesis (pdf).

The original thesis was written fully in LaTeX, and the conversion to HTML was partially completed with Pandoc but then checked and amended by hand.

gallery screenshot
Classic three panel sliding gallery

Responsive Gallery Template

Source code on GitHub.

Fully responsive, easy-to-use-code using CSS variables, optimised for touch (HammerJS).

presents screenshot
Screenshot of How-to presentation

Fania presents

A blank reveal presentation that loads in an external markdown file via the url (hosted on GitHub).

This project was created to make lecturing easier.

Source code.

Screenshot of image gallery
Screenshot of image gallery on

Image Gallery

The handwritten image gallery on my personal homepage is based on responsive CSS grids, CSS filters, lazyloading, and efficient modals.

Source code.

Screenshot of Personal Space
Screenshot of Personal Space

Personal Space

An online artwork extracting individual diary entries containing words selected according to the intensity of live space weather data.

This was a collaboration between Alice Tuppen-Corps, Dave Everitt and myself.

Basic sentiment analysis and natural language processing in JavaScript, source code.

Screenshot of Kittens-R-Us
Screenshot of Kittens-R-Us


This was a responsive, browser, local-storage shop demo for computer science students.

Source code.

Screenshot of LocalStorage Hearts
Screenshot of LocalStorage Hearts

LocalStorage Hearts

This was another very small browser, local-storage like-button demo for computer science students.

Screenshot of Multi-coloured SVG line with Dasharray
Screenshot of Multi-coloured SVG line with Dasharray

Multi-coloured SVG line with Dasharray

This is demo of how to create multi-coloured SVG lines using a magic square example. Uses a similar technique to animation (e.g. Very simple SVG Line Animation) but produces a better/different look to masking (e.g. Multi-coloured SVG line with Mask).

Solutions Log

Inspired by the infinite solutions log

DEAR PEOPLE FROM THE FUTURE: Here's what we've figured out so far ...



Core commands:

  • Create repository in folder git init
  • Clone existing repository git clone URL
  • Add any new files git add .
  • Commit changes git commit -m 'Message'
  • Push changes git push origin master or git push
  • Force push changes (overwrites stuff) git push --force
  • List all local branches git branch
  • List all branches (incl. remote) git branch -a
  • Create branch (but don't checkout) git branch NAME
  • Create branch (and checkout) git checkout -b NAME
  • Switch branch git checkout NAME
  • Delete local branch git branch -d NAME
  • Force delete local branch git branch -D NAME
  • Delete remote branch git push origin --delete NAME
  • See log git log
  • Nicely formatted log log --graph --date=short --pretty=format:"%h%x09%ad%x09%s"
  • Purge file from commit history with BFG Repo-Cleaner
  • Remove "ignored" files that were added before the gitignore was created git rm -rf --cached . and then git add . (make sure gitignore is uptodate)
  • Delete "cached" files that were previously deleted from cache but are still in history git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch "FILENAME"' -f HEAD (DANGEROUS - MAKE BACKUP)
  • Git Deployment

    January 2020

    1. On local machine

    • add ssh key to server's authorised keys ssh-copy-id -i ~/.ssh/ user@server
    • add ssh key to server's authorised keys ssh-copy-id -i c:\users\name\.ssh\ user@server
    • these might need a port too -p 1234

    2. On server

    • live site: /home/user/site
    • bare repo: /home/user/site.git
    • initialise bare repo: git init --bare
    • enter hooks folder: cd hooks
    • create "post-receive" file: touch post-receive
    • add the following script using nano post-receive:
      git --work-tree=/home/user/site --git-dir=/home/user/site.git checkout -f
    • or use the post-receive script mentioned in this article: Simple automated GIT Deployment using GIT Hooks
    • fix permissions of post-receive script: chmod +x post-receive

    3. On local machine

    • add new remote: git remote add server user@server:site.git
    • add new remote (with port including via git config file setup): git remote add server ssh://user@server/full/path/to/site.git
    • check remotes: git remote -v
    • add the following lines to the local git config file (i.e. in .git/config as opposed to the global config in c:\users\name\.gitconfig):
        pushall = !git push origin master && git push server master
    • make changes and push to both remotes: git pushall

    Specify port:

    • git remote set-url server ssh://user@server:port/absolute/path/to/site.git
    • (if cmd complains about caching key and you can't click yes, run putty itself so you can click yes there)

    Multiple users pushing to same repo on server:

    • Create user account for "git": sudo adduser git
    • su git
    • cd
    • mkdir .ssh && chmod 700 .ssh
    • touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
    • Each user wanting to push to the server needs to add their public ssh key to the "git" user's authorized_keys file:
    • From local machine: ssh-copy-id -i ~/.ssh/ git@server
    • From local machine: ssh-copy-id -i c:\users\name\.ssh\ git@server

    More info

    Pandoc & Git Hooks

    Add the following code to a pre-commit hook in the .git/hooks folder of your repo. This will generate html files from markdown content every time just before you commit.

    Make sure you add styles inside a <style> block to a file called "styles". See pandoc command in script below.

    echo "Converting markdown files to html with Pandoc..."
    for file in markdown/*.md 
      echo "Processing $file"
      name=$(basename ${file%%.*})
      # echo $name
      pandoc $file -f markdown -t html -o html/$name.html -s -H styles --quiet
      # --quiet = suppress warning messages
      # -s = standalone (full htmlm not snippet)
      # -H = include file in header
    git add .
    echo "... and stage generated html files."


    August 2019

    Secure Sockets Layer

    Nginx + Debian Stretch 9

    • certbot for Nginx on Debian 9 (Stretch)
    • install certbot: sudo apt-get install certbot python-certbot-nginx -t stretch-backports
    • create certificate: sudo certbot --nginx
    • certificates are found in: /etc/letsencrypt/live
    • check certificates: certbot certificates
    • renew certificates test:certbot renew --dry-run
    • force renew certificates certbot renew --force-renewal
    • expand/update certificates certbot certonly --cert-name -d,
    • revoke/delete certificates certbot revoke --cert-path /etc/letsencrypt/live/CERTNAME/cert.pem
    • check crontab: crontab -l
    • edit crontab: crontab -e
    • restart cron: sudo /etc/init.d/cron restart
    • certbot logs: /var/log/letsencrypt/letsencrypt.log
    • cron job for auto-renew: 0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew (unconfirmed)

    Nginx + Debian Jessie 8

    • Forum autorenew question
    • certificates are found in: /etc/letsencrypt/live
    • wget
    • chmod a+x certbot-auto
    • check certificates: /etc/certbot-auto certificates
    • might need to add flag:--no-bootstrap
    • renew certificates test:sudo /etc/certbot-auto renew --dry-run
    • cron job for auto-renew: 0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && /etc/certbot-auto renew --pre-hook "service nginx stop" --post-hook "service nginx start"

    fix ssl labs server rating ubuntu nginx link

    Server Management

    August 2019


    • pm2
    • pm2 GitHub source
    • pm2 Ecosystem File
    • Running Your Python Script with PM2
    • Install pm2: npm i -g pm2
    • Start a process via custom config: pm2 start app.json
        "name": "name-of-app",
        "script": "name-of-script.js",
        "cwd": "./",
        "watch": true,
        "ignore_watch": ["node_modules", "logs", ".git", "data"],
        "error_file": "./logs/pm2errors.log",
        "out_file": "./logs/pm2out.log",
        "log_date_format": "YYYY-MM-DD HH:mm Z"
    • Start a process: pm2 start app.js
    • List all processes: pm2 list
    • Setup startup script: pm2 startup
    • Stop a process: pm2 stop NUM/NAME
    • Restart a process: pm2 restart NUM/NAME
    • Delete a process: pm2 delete NUM/NAME
    • Forever
    • Example conf file for Forever
    • Running Node Apps with Forever
    • See also: forever-service
    • Install Forever: npm i -g forever
    • List all processes: forever list
    • List all configs: forever config
    • Start a process: forever start app.js
    • Start a process with logs: forever start -l foreverLog.log -o foreverOutput.log -e foreverErrors.log app.js
    • Stop a process: forever stop app.js
    • Restart a process: forever restart app.js
    • Start a process via forever.json: forever start forever.json
          "uid": "name-of-node-app",
          "append": true,
          "watch": true,
          "watchIgnore": ["/absolute/path/logs",
          "colors": true,
          "script": "server.js",
          "sourceDir": "/absolute/path",
          "logFile": "/absolute/path/logs/forever.log",
          "outFile": "/absolute/path/logs/foreverout.log",
          "errFile": "/absolute/path/logs/forevererror.log"
          "uid": "name-of-python-app",
          "append": true,
          "watch": false,
          "colors": true,
          "script": "",
          "command": "venv/bin/python",
          "sourceDir": "/absolute/path",
          "logFile": "/absolute/path/logs/forever.log",
          "outFile": "/absolute/path/logs/foreverout.log",
          "errFile": "/absolute/path/logs/forevererror.log"
    • Add to git post-receive hook: forever restart uid-of-process
    • Might need to make sure you run these on the same user.


    • Securing a VPS
    • Mozilla server sec checker: observatory.mozilla
    • Cross origin resource sharing (CORS):
    • get Debian version lsb_release -d
    • get Kernel version cat /proc/version
    • When upgrading remember to re-install nginx, git, certbot, couch, python 3.8, etc
    • Check free disk space in human readable form df -h
    • Check what is using space in human readable form du -h
    • As above but as summary du -h -s *
    • Show running processes: ps -ef


  • sudo adduser name
  • Change user permissions chown user file
  • Change user permissions for all chown -R user folder
  • Change group permissions chgrp group file
  • Change group permissions for all chgrp -R group folder
  • Edit access rights nano /etc/ssh/sshd_config
  • Restart ssh client after change /etc/init.d/ssh restart
  • Add user to sudo group usermod -aG sudo username

    • /etc/nginx/sites-available
    • /etc/nginx/sites-enabled
    • /etc/nginx/snippets
    • stop nginx: service nginx stop
    • restart nginx: service nginx restart
    • get nginx status (incl pid): service nginx status
    • test settings: nginx -t
    • create symlink from sites-available to sites-enabled: ln -s /etc/nginx/sites-available/name /etc/nginx/sites-enabled/name
    • Nginx not restarting
    • check running processes of nginx: ps aux | grep [n]ginx
    • kill process: kill -9 1234 for each process!
    • then start nginx again: service nginx start


    • show all running screens: screen -ls
    • start new screen with name: screen -S name
    • attach to a running session: screen -x
    • attach to session name: screen -r name
    • detach from a session: Ctrl-a d
    • kill a screen: screen -S NUMBER -X quit


    show ports used: netstat -plutn


    Command-line Interfaces


    • Curl Manual
    • Open cmd as admin 'Right-click' cmd executable
    • Edit files with nano


    Open at location

    • 'Shift-right-click' folder to open CMD there
    • Use the 'Open-In-Terminal' script

    Finding things

    • Show all locations of file type -a NAME
    • Show location of file or folder which NAME
    • Show location of file or folder (if virtualenvwrapper-win is installed) whereis <NAME>


    • Reload terminal source ~/.bash_profile
    • Reload cmd SET PATH=%PATH%;C:\CmdShortcuts (unconfirmed)

    Running Scripts

    • Make sure Execution Policy is set appriately Set-ExecutionPolicy RemoteSigned
    • Check Execution Policy with Get-ExecutionPolicy
    • See How to allow scripts to run







    • Reference SASS
    • How to setup Sublime
    • Edit scss file and then Command+B to compile
    • Edit init.js file to use sass or css files; or if scripts are disabled edit individual import statements in html files



    • Official Node.js website
    • npm init to create package.json
    • npm i XYZ or npm install XYZ to install XYZ into local "node_modules" folder
    • node app.js` or node app` to run app
    • npm rm XYZ to remove XYZ
    • npm uninstall XYZ to remove XYZ
    • process.stdout.write("Downloading " + data.length + " bytes\r"); to print to console in same line as before...
    • process.stdout.write("Downloading " + data.length + " bytes\033[0G"); to print to console in same line as before...


    Cross references - see also Pandoc & Git Hooks.

    • Dillinger: For creating, editing and exporting markdown files in html.

    Web Development

    March 2020

    General Guides / Checklists / Roadmaps

    Tools / Resources

    Service Workers

    Intersection Observers


    • No Code: The best way to write secure and reliable applications. Write nothing; deploy nowhere.

    Search Engine Optimasation (SEO)





    Responsive Web Design


    Social / Sharing / Structured Data

    Interesting Sites


    October 2017

    • Texcount fix, Perl, Texcount.Perl - Comment out section on win stuff at top
    • Table Generator: For creating, editing tables in Latex, html, markdown, etc.
    • Latex Equation Editor: For creating, editing Latex equations.


    March 2020



    • How to connect: sudo mysql -u USERNAME -p (enter sudo pw first, and then the mysql user pw)

    VS Code

    October 2017



    October 2017


    October 2017


    • Reference WordNet Interface for NLTK
    • Import wordnet from nltk.corpus import wordnet as wn
    • Loop through lemmas for l in synset.lemmas():
    • Lemma name as string str(
    • Antonyms synset.lemmas()[0].antonyms()
    • Install NLTK 3.0.0b1 pip install -Iv


    • Reference NLTK Data
    • Install nltk data: (1) python
    • Install nltk data: (2) import nltk
    • Install nltk data: (3)
    • or'stopwords') and'wordnet')
    • add path of nltk_data folder to system path
    • or better yet add it to the local repo and code:
    • import nltk


    April 2020

    See also info on screen

    Install Python 3.8

    Python WSGI ('Whiskey') Server

    Switch the /usr/bin/python link to point to current python link

    • cd /usr/bin
    • rm -f python
    • ln -s /Library/Frameworks/Python.framework/Versions/Current/bin/python python


    • Reference Pip
    • Upgrade pip pip install -U pip
    • Upgrade pip python -m pip install -U pip
    • Install NAME pip install NAME
    • Install NAME version 1.0.4 pip install NAME==1.0.4
    • Install specific version pip install -Iv Link-to-tar.gz
    • Uninstall NAME pip uninstall NAME
    • Show installed packages pip list
    • Show out-of-date packages pip list --outdated
    • Upgrade NAME pip install --upgrade NAME
    • To freeze local requirements pip freeze --local > requirements.txt
    • To freeze requirements pip freeze > requirements.txt
    • To install from requirements pip install -r requirements.txt


    • Python 3 reference Virtualenv
    • Old reference Virtualenv
    • Python 3: create a new venv python -m venv NAME
    • Old: Create a new venv virtualenv NAME
    • Activate NAME . NAME/bin/activate
    • Activate NAME NAME\scripts\activate
    • Deactivate deactivate


    • Reference Virtualenvwrapper-win
    • Reference Virtualenvwrapper
    • Make a new venv mkvirtualenv ENVNAME
    • List all virtualenvs workon or lsvirtualenv
    • Activate a virtualenv workon ENVNAME
    • Deactivate virtualenv deactivate
    • Remove virtualenv deactivate and then rmvirtualenv ENVNAME
    • Bind ENVNAME to project setprojectdir <project_path>
    • Bind ENVNAME to project setvirtualenvproject [virtualenv_path project_path]
    Virtualenvwrapper-win not finding
    • Edit C:\PythonXY\scripts\mkvirtualenv.bat with the following changes on lines 47, 48
    • Line 47 virtualenv.exe %*
    • Line 48 REM python.exe "%PYHOME%\Scripts\" %ARGS%


    • C:\Python27;C:\Python27\Scripts;
    • Set folder for virtualenvs export WORKON_HOME=$HOME/.virtualenvs
    • Set folder for virtualenv projects export PROJECT_HOME=$HOME/Desktop/PhD_Offline/Git_code
    • source /Library/Frameworks/Python.framework/Versions/2.7/bin/
    • PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
    • PYTHONPATH="/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/:${PYTHONPATH}"
    • export PATH

    Surface Pro 4

    October 2017

    • Get battery report: powercg /batteryreport


    • Dashboard Login
    • Install the toolbelt
    • Python Flask Guide
    • Login heroku login (needs authenticator code)
    • Git Push git push heroku master only in git bash !
    • make sure reqs.txt is called requirements.txt

    Acrobat Reader

    October 2017

    • Forum Help
    • Uncheck preference located under Edit > Preferences > Documents "Open Tool pane for each document"


    Category Filters





    Yuki & Aya and her kittens :)