I am closing the blog

I am closing the blog and I will be (slowly) moving the posts to another one which I have started on Github, written with Octopress.

Main reasons :

  • There are now advertisements inside the main body of the blogs on WordPress.com. How lame is that !?
  •   Octopress handles maths and code much better, you can write your post in markdown, its themes are fully customizable for free, and you don’t need an internet access to make your post drafts !
  • This blog can too easily be found when googling my name.
Advertisements

[Doesn’t work anymore, sorry, might fix that one day…] Customize your IPython notebook with CSS

In the coming IPython 1.0 (available on their github) you will be able to change the style of your notebook using a custom CSS file. Here are three attempts, which I will describe in details:

Creating a IPython profile

Credit and many thanks for this part go to Matthias Bussonier for his thorough explanatory blog on the subject.

Creating a profile is easy, you just type this line in a terminal:

ipython profile create yourprofilename

Note that you can send commands to the terminal from within your IPython notebook by writing %%bash in the first line of a code cell:

%%bash
ipython profile create yourprofilename

This has created a folder named profile_yourprofilename in your IPython folder. If you don’t know where this folder is, just type in a terminal

ipython locate

You have now a new profile ! In the future, to launch IPython with this new profile, use the command

ipython notebook --profile yourprofilename

To later rename a profile, go to your .ipython folder, rename the folder “profile_name” into “profile_newname”, then run

ipython profile create newname

For the moment your profile is identical to the default profile. Now go in your profile folder, and create a subfolder profile_yourprofile/static/css/. In this /css folder we will put CSS files and pictures to tune the appearance of the notebook. Start by creating a file custom.css, we will see how to fill it in the next sections. I just learned enough CSS to make the themes, so I am not really in control here. Comments and suggestions are welcome 🙂

Theme 1: A Clean Notebook

My favorite 🙂 . Here is the content of my custom.css . I just hope that the structure and class names of IPynb html pages will not change too much in the future

/* file custom.css for the theme CleanNotebook */
div#notebook { /* centers the page content */
padding-left:20%;
padding-right:20%;
}

div.cell { /* Tunes the space between cells */
margin-top:1em;
margin-bottom:1em;
}

div.text_cell_render h1 { /* Main titles bigger, centered */
font-size: 2.2em;
line-height:1.4em;
text-align:center;
}

div.text_cell_render h2 { /*  Parts names nearer from text */
margin-bottom: -0.4em;
}



div.text_cell_render { /* Customize text cells */
font-family: 'Times New Roman';
font-size:1.5em;
line-height:1.4em;
padding-left:3em;
padding-right:3em;
}

#notebook li { /* More space between bullet points */
margin-top:0.8em;
}

div.cell.code_cell {  /* Areat containing both code and output */
background-color:#F1F0FF; /* light blue */
border-radius: 10px; /* rounded borders = friendlier */
padding: 1em;
}

Bonus: Motivational Penguin

I am really fond of the motivational penguin from chibird.com (thanks Jacqueline !!!).
motivational_penguin

If you want the motivational penguin to cheer you up on the side of your screen while you are coding, put the GIF file in the /css folder and add these few lines to the code above:

#notebook_panel {
background : url('motivational_penguin.gif') no-repeat left center ;
}

Theme 2: Zen of IPython

For this theme you will need to place each of these pictures in your CSS folder (I made all of them from Public Domain pictures from Wikimedia Commons and I put all of them in the Public Domain, where they belong).

The css code is surely far from optimized.

div#notebook {
padding-left:20%;
padding-right:20%;
}

div#ipython-main-app {
background: url('Shotei.jpeg') no-repeat top left;
}

body {
background : url('paper.jpeg') ;
}

div.cell {
margin-top:20px;
margin-bottom:20px;
}


h1 {
text-align:center;
}


div#notebook li {
margin-bottom:20px;
}

p,li,h1 {
line-height:120%;
}

p,ul {
padding-left:10%;
padding-right:10%;
}

.text_cell_render{
font-family: 'Palatino','Arial';
font-size:1.8em;
}

.text_cell h1 {
font-size: 2.2em;
text-align:center;
line-height:120%;
}

.text_cell h2 {
font-size: 1.8em;
margin-bottom:0;
}


div.input_area {
background: url('mountain_paper.png') ;
border-radius: 15px;
overflow:auto;
}


div.CodeMirror {
background: url('mountain.jpeg') repeat-y top right;
background-size: 20%;
padding-right:20%;
font-size: 1.3em;
}

div.CodeMirror-scroll {
padding-bottom:1.01em;
}

.output_wrapper{
background-image: url('sky.jpeg');
border-radius: 15px;
}

div.output {
border-radius: 15px;
background: url('cherryFlower.jpeg') repeat-y right;
background-size: 25%;
}

div.prompt.input_prompt{
display:none;
}

div.code_cell {
background: #e6ddce;
-moz-border-radius: 15px;
border-radius: 15px;
padding: 15px;
font-size:14px;}

Theme 3: Gameboy

For this one you will need the buttons:
buttons

.prompt {display:none;}

div.cell.code_cell {
max-width: 800px;
background-color:white;
background:url('buttons.jpeg') no-repeat center bottom;
background-size:80%;
border-color: black;
border-radius: 30px;
padding-bottom:5px;
padding: 1em 1em 200px 1em;
}

div.output_wrapper {
margin-left:0px;
padding-left:0px;
padding-top:0px;
}

div.input_area, .output_stdout  {
margin-left:110px;
border-style:solid;
max-width:600px;
background-color: #626e02;
border-color: #656e7f;
border-width: 20px;

}

div.output_stdout {
border-top: none;
margin-top:-26px;
padding-top:26px;
}
div.CodeMirror-scroll {
padding-bottom:20px
}

div.CodeMirror, div.output_stdout pre {
padding: 0.5em 0.5em 0.5em 0.8em;
font-size: 1.6em;
font-family:"G.B.BOOT";
}

.cm-s-ipython { color: black; }
.cm-s-ipython span.cm-keyword {color: black;}
.cm-s-ipython span.cm-number {color: black;}
.cm-s-ipython span.cm-operator {color:black;}
.cm-s-ipython span.cm-meta {color: black;}
.cm-s-ipython span.cm-comment {color: black;}
.cm-s-ipython span.cm-string {color: black;}
.cm-s-ipython span.cm-error {color: black;}
.cm-s-ipython span.cm-builtin {color: black;}
.cm-s-ipython span.cm-variable {color: black;}

Typing keyboard + python = Musical instrument !

In this post I will show you how to do this :

I am not the first to do that, but most people who play their computer on Youtube use either very expensive programs, or programs that won’t run on your computer, or not-so-efficient programs with not-that-much possibilities of extension, or cheap programs with a big lag between pressing the key and actually hearing the note.

So here is a very small Python script which will run fine even on a basic netbook. If you are not familiar with Python, you should take online courses , it is really worth it 🙂 !
If you are faminiliar with Python, then you are welcome to improve the code on its Github page.

Transforming your keyboard into a mixtable

My original idea was to transform my computer keyboard into a mixtable, to make something like in this very awesome video:

So my first move was to make a program that would take a configuration file my_configuration.cf containing this:


q, dog.wav
w, cat.wav
e, tarzan.wav
r, scream.mp3

And then if you hit q you would hear a dog from the dog.wav soundfile, if you hit w you’d hear a cat, etc…
This is pretty easy to do with Python’s pygame package. Here is my code (inspired by similar stuff from the package Mingus):


import pygame as pg
import csv
import time


SAMPLE_WIDTH = 16
FPS = 44100
N_CHANNELS = 2
BUFFER = 2**9
    
def minimix(config_file,mode = 'instrument'):
    """
    Opens an interface that lets you press the keys of your keyboard
    to plays the related soundfiles as sepcified in the provided
    configuration file.
    
    Args:
       config_file (str):  A file associating keyboard keys with
                           file names. Each line must be of the form
                           key , filename.
                       
       mode (str) :
            instrument -- causes autorepeat of samples as long
                            as the key is pressed.
            sustain -- causes autorepeat of the samples until its
                       key is pressed again.
            player -- striking the key causes the sound to play once. 
    
    Returns:
       a list of the (time,events).
    """
    
    repeat = 0 if (mode is 'player') else (-1)
    
    pg.mixer.pre_init(FPS,-SAMPLE_WIDTH,N_CHANNELS,BUFFER)
    pg.init()
    screen = pg.display.set_mode((640,480))
    
    
    
    
    ##### READ CONF FILE
    
    key2sound = {}
    key2file = {}
    config = csv.reader(open(config_file, 'rb'), delimiter=',')
    
    for key, soundfile in config:
        
        key,soundfile = key.strip(' '),soundfile.strip(' ')
        
        if key is not '#':
            
            key2file[key] = soundfile
            key2sound[key] = pg.mixer.Sound(soundfile)
    
    events_list = []
    currently_playing = {k : False for k in key2sound.iterkeys()}
    
    
    ##### MAIN LOOP
    
    while True:
        
        event =  pg.event.wait()
      
        if event.type in (pg.KEYDOWN,pg.KEYUP):
            key = pg.key.name(event.key)
              
            if key in key2sound:
                
                if event.type == pg.KEYDOWN:
                    
                    if (mode == 'sustain') and currently_playing[key]:
                        
                        key2sound[key].fadeout(20)
                        currently_playing[key] = False
                        
                    else:
                        
                        key2sound[key].play(repeat) 
                        currently_playing[key] = True
                    
                    events_list.append((time.time(),key2file[key]))
                    
                elif event.type == pg.KEYUP and (mode == 'instrument'):
                    
                    key2sound[key].stop()
                    currently_playing[key] = False
                    
                    events_list.append((time.time(),key2file[key]))
            
            elif event.key == pg.K_ESCAPE:
                
                break
    
    pg.quit()
    
    return events_list

Transforming your keyboard into a musical instrument

If instead of using various noises like cat and dog you use different notes from the same instrument, then you turned your computer into some kind of piano. The problem is that a set of soundfiles with all the notes of an instrument is difficult to find on the internet, so I wrote a script that makes as many notes as you want from just one sound by shifting its pitch up or down. It uses the audio processing program Soundstretch that you will need to install first :

import os

def shift_wav(wavfile,output,shifts,verbose=False):
    """
    Makes new sounds by shifting the pitch of a sound.
    Requires soundstrech installed.
    
    Args:
        wavfile : Name of the file containing the original sound
        output: name to use as a prefix for the output files and for
                the output folder name
        shifts (list of int): specifies of how many half-tones the pitch
                shifts should be. For instance [-2,-1,1,2] will produce
                4 files containing the sound 2 half-tones lower, one
                halftone lower, one halftone higher and two halftones
                higher.
    """
    
    folder = os.path.dirname(output)
        
    if not os.path.exists(folder):
        
        os.makedirs(folder)
        
    for i,s in enumerate(shifts):
        
        outputfile = '%s%02d.wav'%(output,i)
        
        command = 'soundstretch %s %s -pitch=%d'%(wavfile,outputfile,s)
        if verbose:
            print command
        os.system(command)

Going further

There is so much one could do to improve the program.

On the musical side, for instance, finding configurations of the keyboard that are particularly ergonomic. In the video above I used this configuration:

azerty

I called it typewriter because it enables you to play very fast things while moving your hands a minimum (the video is a bad example :P) . But maybe there is better to find !

Also, one could start listing every cool piece of music that can be played on a typing keyboard. I use 46 keys ( almost 4 octaves !), that makes a lot of possibilities !

On the programming side, there is a lot of little things I can think of, like automatizing scale changes, introducing nuances, designing nice interfaces (why not a guitar-hero-like game where you would actually be playing music on a playback ?), writing a script that would take some sheet music (in a nice format, like ABC, MIDI, lylipond) and return the list of the keys you should strike to play it.

I actually wrote a lot more code, for instance to make it easier to write configuration files, for sound processing, etc., but since it is not strictly necessary I am not reporting it here (I’ll certainly put a working version on GitHub, or such, some day).

Philosophy of the musical keyboard

Your typing keyboard is a real instrument. Of course it is not its primary use, but our voice’s primary purpose was not to sing, either. Now do the math : how many people out there have a piano at home ? And how many have a computer ? That gives you an idea of how many people would like to play the piano, cannot, but could play their computers instead.

So promoting computer-keyboardism is ultimately about bringing music to the masses. It is about providing everyone with an instrument that you can practice at home, in the train, at work, and that will be familiar to anyone everywhere in the world.

There is more : how many of you, pianist readers, have started the piano for seduction purposes ? (yeah, sure, me neither…) But public places with a piano on which you could show off your mad skills are getting pretty rare, aren’t they ? Especially since most bars have traded their good old piano for a TV. But think about all these places with a computer at hand ! Yep, time for you to develop a talent that will be useful in real life !

So practice, get good, be one of the first composers for tomorrow’s instrument, impress your friends and spread the good news ! If you are still reading me after so much gibberish , then do not hesitate : you just proved how little you value your free time, you are the right person for the task !

Physics of Harrison’s H1 clock

Today’s post is about a subject I presented a few years back at the entrance exams of the french engineering schools. If you like clocks, boats, adventures and unnecessary complications, this is for you 🙂

Historical notice

During the Renaissance the English realised how good they were on seas, and how much potential there was for some ass-kicking with all these loaded European ships making round trips to America. A very crucial problem in sailing is to know where you are. For that you need

  1. Your latitude : how far north are you from the equator ?
  2. Your longitude : how far west are you from London ?

Getting the latitude is easy:

  • During the day, look at the sun (especially at noon). The higher it is, the nearer you are from the equator
  • At night, look at a pole star : the higher it is, the farther away you are from the equator.

But no such tricks to estimate the longitude existed in the 1700’s. Astronomers had thought of something but it was all very complicated and stuff. So the English did what you do when you are out of ideas: they made a law (the Longitude Act) proposing a huge prize (that they had no intention of giving up too easily) to any subject of his Majesty who would come up first with a method.
That’s were John Harrison comes in, with a beautifully simple idea:

  1. Take a clock indicating London’s time onboard.
  2. During your travel, look at the sun to get the time of the place where you are, and compare it to the clock’s time.
  3. If for instance the sun indicates 12h00, and the clock indicates that it is 10h00 in London, then you know that you are \frac{12-10}{24}*360 = 30 degrees west from London.

The only problem is that, if you take your good old pendulum clock on a boat, it will instantly go mad due to all that pitching, rolling and yawing ! So you need to design a more sophisticated device. But John Harrison had a slight advantage here: he was a professional clockmaker !

John Harrison (1693-1776) Credit: Wikipedia

Shake it baby ! Harrison’s H1 clock

In 1730, Harrison imagines his first marine clock, that he calls H1:

Harrison’s H1. Credit : National Maritime Museum, (Greenwich)

Here is an idealized scheme of the beast’s arms :

I believe that the contact between the two arms is there to make sure that they will always move in symetrical ways (otherwise the movement could get chaotic). A very nice feature of this design is that any force that is applied equally to each of the weights is cancelled out and has no effect on the oscillations !

This makes the clock’s movement independent from gravity (meaning that the clock doesn’t need to be vertical to oscillate properly) and from any translational movement of the boat !
However (and that’s where my study started) I noticed that the centrifuge force induced by the rolling of the ship is not compensated, as the weights are not equally distant from the rotation center:

And my (very fundamental and of much historical importance) question was : how much does the rolling affect the clock ?

A small study

Before getting to the real question, let us study how this clock works when it is not perturbated.
Suppose that the left arm, of radius R makes an angle \theta with its equilibrium position (that we suppose to be vertical):

The other arm is in a symetrical position, so the upper spring is streched by a length 2R\sin(\theta) and thus pulls the upper weight of the left arm with a force equal to 2kR\sin(\theta) (where k is the spring’s rigidity constant). The lower spring is compressed by a length 2R\sin(\theta) and the lower weight undergoes a push of 2kR\sin(\theta). These two forces apply negative torques on the arm, both with a lever equal to R\cos(\theta). Finally, neglecting the mass of the arm’s sticks, the arm’s angular momentum is 2R^2M\dot{\theta} where M is the mass of one weight. Once you have all that, the angular momentum theorem gives

2R^2M\ddot{\theta} = -2Rk\sin(\theta)R\cos(\theta)

which after simplifications gives

\ddot{\theta} + \dfrac{k}{M}\sin(2\theta) = 0

Note that (partly because my model is very simple) the oscillations do not depend on the radius of the arms. If the amplitude of the oscillations if really small, we have \sin(2\theta) \simeq 2\theta and the equation becomes

\ddot{\theta} + 2\dfrac{k}{M}\theta = 0

where we recognize an harmonic oscillator of period T = \pi \sqrt{\dfrac{2M}{k}} . If the oscillations are bigger, one can still simulate the dynamics (here with Python):


from pylab import *
from scipy.integrate import odeint

def H1diff(Y,t,k,M):
    """
    Equations describing the dynamics of the model
    Y is [A,dA/dt], t is the current time, k is the spring's constant,
    M is the mass of the weights.
    Returns [dA/dt, ddA/ddt] according to
    dd(A)/ddt + k/M sin(2A) = 0
    """

    A,dA = Y
    return array([dA, -k / M * sin(2*A)])

k=1.0 ; M=1.0 ; initialAngle = pi/6 # parameters
Y0= [pi/6, 0.0] # initial angle pi/6, initial speed 0
ts=linspace(0,10, 100) # 100 times points between 0 and 10
angles = odeint(H1diff,[initialAngle,0],ts,args=(k,M))[:,0] # solving

# plotting
fig,ax = subplots(1)
ax.plot(ts,angles) # plotting
ax.set_xlabel('time',fontsize = 24)
ax.set_ylabel('angle',fontsize = 24)
show()

Or better 🙂


def makeAnimation(k=1.0,M=1.0,nframes=40,R=1.0,**kwargs):
    """ simulates and creates a GIF of the H1 """

    # default for tmax is one period.
    tmax = kwargs.pop('tmax',2*pi*sqrt(M/k))

    # delay is computed so that the animation actually lasts tmax.
    delay = kwargs.pop('delay',int(100.0*tmax/nframes))

    O1 = array([-1.0,0]) # center of the left pendulum
    O2 = array([1.0,0])  # center of the right pendulum
    R = 1.0

    def drawH1(angle,ax):
        """ draws an Harrison H1 clock given the angle of the arms """

        # compute the coordinates of the four weights:

        s,c = sin(angle), cos(angle)
        LU = O1 + R*array([-s,c])
        LD = O1 + R*array([s,-c])
        RU = O2 + R*array([s,c])
        RD = O2 + R*array([-s,-c])

        # draw the springs

        for w1,w2 in (LU,RU),(LD,RD):
            ax.add_line(Line2D(*zip(w1,w2), linewidth=2,color='b'))

        # draw the sticks

        for w1,w2 in (LU,LD),(RU,RD):
            ax.add_line(Line2D(*zip(w1,w2), linewidth=4,color='k'))

        # draw the joints

        for point in O1,O2:
            ax.add_artist(Circle(point,radius = 0.1, color='grey'))

        # draw the weights

        for point in LU,LD,RU,RD:
            ax.add_artist(Circle(point,radius = 0.2,color='k'))

    Y0 = [pi/6,0]
    ts=linspace(0,tmax,nframes)
    angles = odeint(H1diff,Y0,ts,args=(k,M))[:,0].flatten()

    fig,ax = subplots(1)
    fig.set_size_inches(2.5,2.5)
    ax.set_xlim(-1.8,1.8)
    ax.set_ylim(-1.3,1.3)

    for i,angle in enumerate(angles):
        ax.clear()
        axis('off')
        drawH1(angle,ax)
        fig.savefig('hhh%.3d.jpeg'%i)

    # make the gif

    os.system('convert -delay %f -loop -1 hhh*.jpeg harrison.gif'%delay)

    # remove the temporary files
    for myFile in os.listdir('./'):
        if myFile.startswith('hhh'):
            os.remove(myFile)

H1 simulation

Any role for the Rolling ?

Back to our previous question: how much does the rolling affect the clock’s movement ? Let us just put a few things straight first:

  • It’s impossible to come even close to a solution that I could defend more than one minute.
  • Anyway, who cares ! It’s not like if it was an important problem.

This being said, here is how I went with the modelling. For the clock:

  1. I emailed the Greenwich Museum, where the original H1 is, and they were nice enough to give me a few measures of the clock (length of the arms, radius and material of the weights)
  2. I estimated the maximal angle and checked the period using a video found on the internet.
  3. I then determined the constant k of the springs by simulation and optimisation, as the optimal constant to get a period of one second.

Here is how you do the last step with Python:

from scipy.optimize import fmin

def find_k(T,M,initialAngle):
    """ finds the optimal spring rigidity constant k to obtain an H1
        clock with a period of T given the mass M of the weights
        and the initial angle of the clock """

    def f(k):
        ts=[0,T]
        res = odeint(H1diff,[initialAngle,0],ts,args=(k,M))
        finalAngle = res[-1,0]
        return (finalAngle-initialAngle)**2

    k_init = 2*(pi**2)*M / T**2  # expected for very small oscillations
    return fmin( f ,k_init)

To model the boat:

    1. I found a plan on the internet of the very famous HMS Bounty, which is approximately the kind of ship used in Harrison’s times
  1. Since the plan was accurate enough to make a mesh out of it, I used pens and rulers to get the coordinates of the points of the slices of the ship on the plan. then I used some sort of finite elements method (I had not heard of this at the time) to simulate the oscillations of the boat on still water. This gave me a profile of the ship’s rolling over time.
  2. A cool thing : I found on the internet that some people in Australia had made an exact replicate of the Bounty. So I emailed the captain to see if he could measure how long the ship takes to do one roll. He found exactly the same period, more or less one second !

Putting everything together I was able to see how much the rolling impacts the period of the clock over a few minutes, then how much difference it makes in the estimated time after a few days, and how much this represents in terms of distance… Results that I don’t really remember, but once again, who cares ? Isn’t the most important having fun, squeezing equations and poking people from all around the world ?

Epilogue (with spoilers)

The H1 wasn’t precise enough to compute the longitude as precisely as demanded by the Longitude Act. Further improvements kept Harrison busy for his whole life. He produced three clocks, H1, H2, and H3, until he realised that he had been thinking too big, and that the solution might come from a bleeding edge technology of the time: the chronometer ! With its small size and it’s reliable spiral spring, this ancester of the pocket watch was accurate enough to finally get Harrison his prize, after more than 40 years of research !

Some like it hot

Here is an example of what I believe to be good communications skills in data representation. The Scientific Visualization Studio of the NASA Goddard Space Flight Center made this video showing 130 years of global warming:

As many of its viewers, this sure frightened me, so I went to look for the source. The map shows differences in temperature with the 1950’s. According to the NASA, the world average temperature has increased of 0.51 celcius degrees between 1951 and 2011. This surprised me a little, I would have thought it was more after watching the video ! Then it struck me that the projection of the world map (known as Mercator) gives an exagerated importance to the poles, which partly explains the amount of red in the picture. You can see how grotesquely big the antartic appears. For the artic (which isn’t reported on the map as it is not a land), it is more complicated to see, but think that Greenland is actually four times smaller than Brasil. If you have a look at the world maps you can find on the net you will see that some other solutions exist, and that this projection was a deliberate choice of the vizualization studio.

Now, how big is the distorsion ? I wrote a small script to analyse the 2011 map and found out that the average temperature increase as it appears on the picture is of +0.81°C, which is about 60% higher than the 0.51°C announced on the NASA’s website !

My methods

In case you are interested, I did the analysis with Python. I first took a screenshot of the 2011 frame in high definition, then I extracted a one-pixel high rectangle of the color bar. Finally I painted in black the zones I didn’t want to be considered (country borders, year, colorbar):

Then I used the following Python script (which requires Scipy and Pylab):

from scipy import ndimage
from scipy.interpolate import NearestNDInterpolator
from pylab import *

# load the color bar and the map
colorScale = ndimage.imread('colorScale.bmp')[0]
map2011 = ndimage.imread('map2011.bmp')


# create a function that will attribute a value to a color by looking
# at the nearest color in the colorbar

scaleValues = linspace(-2,2,len(colorScale)) # scale of the colorbar
colorInterpolator = NearestNDInterpolator(colorScale, scaleValues)
color2value = lambda color :  colorInterpolator([color])[0]

# compute the corresponding value and the norm of the colors of all
# points of the map

values = apply_along_axis(color2value, 2,map2011)
norms = apply_along_axis(norm, 2,map2011)

# compute the mean of the values on the non-black pixels

print values[norms != 0].mean()

The first game based on a gene regulation network ! (and it’s boring !)

Do you know the Wikigame ? It is an online game whose goal is to go from one article of Wikipedia to another by only clicking on the hypertext links of the articles (actually quite a lot of fun 🙂 ). In my previous post I showed how to use Python to explore E. coli’s network of gene interactions. Now, why not transpose the Wikigame to this network ? Here is how I would do it :

  1. Get the network
  2. Take its main connected component.
  3. Choose two genes of this component randomly
  4. Compute the shortest path between the two components
  5. Set the maximum number of moves allowed to two times the length of the shortest time
  6. Lead the player through the network, proposing at each nodes to go to any of its neighbors.
  7. End the game if the player reached its goal or if the moves limit has been reached

And here is the code :

import random

def iGame(geneNetwork):
	""" A game in the spirit of the wikiGame : the computer decides of
		two random genes and you must find a way from one to the other
		in a maximum of ten moves. """

	nb_allowed_moves = 10

	# SELECT THE BIGGEST CONNECTED COMPONENT OF THE NETWORK

	undirected_net = geneNetwork.to_undirected()
	component_nodes = nx.connected_components(undirected_net)[0]
	component = geneNetwork.subgraph(component_nodes)

	# SELECT TWO RANDOM GENES INSIDE THIS COMPONENT

	start,goal = random.sample(component,2)

	# COMPUTE THE SHORTEST PATH

	shortest_path = nx.shortest_path(undirected_net,start,goal)
	nb_allowed_moves = 2*len(shortest_path)

	# A RECURSIVE FUNCTION DEFINING THE RULES

	def recursive(gene, countDown):
		""" A recursive function to explore E. coli's network from
			gene to gene """

		if gene == goal:

			print "You win ! Congratulations !"

		elif countDown == 0 :

			print "So sorry, no moves left ! You lose !"

		else :

			regulators = component.predecessors(gene)
			regulated =  component.successors(gene)

			print '\n -- Goal : %s . %d moves left'%(goal,countDown)
			print 'Genes regulating %s : '%(gene), " ".join(regulators)
			print 'Genes regulated by %s : '%(gene), " ".join(regulated)

			playerChoice = ''

			while not playerChoice in ( regulators + regulated ):

				playerChoice = raw_input('Where to move next ?')

			recursive(playerChoice, countDown-1)

	# START THE GAME

	print "\n Welcome to the iGAME, You are a level 1 raider"
	print "located on the gene %s. Your quest, would you choose"%(start)
	print "to accept it, is to reach the gene %s in less"%(goal)
	print "than %d moves. Good luck !"%(nb_allowed_moves)

	recursive(start,nb_allowed_moves)

	# END THE GAME

	print "The shortest path was : "
	print " ".join(shortest_path)

This game ( that I called iGame as a reference to the iGEM competition) is certainly one of the dullest, unfunniest games I ever coded. It’s main drawback is that, without any background information, it comes to a random walk with no visibility in a maze with hundreds of bag-ends. Maybe it would be more fun if it could be played directly on the RegulonDB webpages, which give detailled descriptions on the role and location of each gene. At which case it would be one of the nerdiest games on the internet !