XD blog

blog page


2013-10-23 Using pythonnet

I migrated over Windows 8.1 and I realized my version of pythonnet for Python did not work anymore. I got the following error:

ImportError: dynamic module does not define init function (PyInit_clr)
I did not really try to understand but I knew I had to access the sources first because the official website of pythonnet does not provide any version for python 3.x. So I looked for pythonnet on github, I found this. I got the sources which did not compile on the first try unless I apply the three following modifications: After the compilation completed (on Windows 8.1 + Visual Studio 2012, 2013), I could use the two files clr.pyd and Python.Runtime.dll the same way. There were some others modifications I do not remember exactly. Anyway, my version is located here sdpython/pythonnet.

2013-10-20 Quelques restaurants à Paris toujours

Entendu à la radio : Louvre Bouteille. Dans un journal : Aux Deux Amis, L'Ami Louis (> 100€), Chez Nenesse (> 40€), Le Baratin, Au Passage, Autour d'un verre, L'essentiel, Au rendez-vous des chauffeurs, Clandestino.

2013-10-14 Mon PC est mort ce soir

Je fais régulièrement des sauvegardes qui ne servent à rien la plupart du temps à rien sauf quand le disque dur de mon PC me lâche. Là, je suis très content de pouvoir continuer sur un autre portable en recopiant mes données même s'il faut que j'installe une tonne de logiciels (python, latex, office, 7zip, ...). Ca m'est arrivé il y a quelques jours et j'ai appréhendé la situation avec calme même si j'ai été surpris que mon portable lâche après seulement six mois.

Sauvegarder peut être terriblement contraignant. Il y a bien sûr des solutions style stockage distant. Mais l'offre gratuite est limitée à 5 Go et étudiée pour qu'elle soit dépassée dès qu'on y stocke ses photos. De plus, je n'aime pas trop me dire que mes données sont répliquées trois fois à tous les coins du monde.

J'en suis donc revenu aux solutions artisanales. On sauvegarde si cela n'est pas trop coûteux de même qu'on écrit des articles de blogs si cela ne pas prend pas trop de temps de les mettre en ligne. Donc, ça doit se faire en trois clics de souris au plus. Une autre chose utile est la possibilité de garder l'historique des dernières modifications apportées à un document. On efface par mégarde, on supprime un paragraphe qu'on ne voulait pas supprimer...

Pour ces deux raisons, j'en suis venu à utiliser Tortoise SVN. Tous les fichiers que je souhaite conserver y sont archivés. Et je peux récupérer facilement l'historique. Pour le reste, j'ai codé moi-même la sauvegarde (voir synchronize). Elle récupère la liste des fichiers recensés par Tortoise SVN et recopie les fichiers modifiés depuis la dernière sauvegarde sur un disque dur externe.

Toutes mes copies ne sont pas cryptées mais je contrôle les supports sur lesquels mes données sont recopiées. J'utilise malgré tout des services style dropbox ou skydrive pour facilement transbahuter certains depuis mon ordinateur vers mon téléphone portable (la lecture pour le métro).

2013-10-02 Ways to show code in a blog post

I found another way to show code in a blog. It looks nicer than prettify. The only change is to indicate the langage you want to use to highlight you piece of code. It is called SyntaxHighlighter.

You need to insert the following lines in the header:

<link href="/js/shCore.css" rel="stylesheet" type="text/css" />
<link href="/js/shThemeDefault.css" rel="stylesheet" type="text/css" />
<script src="/js/shCore.js" type="text/javascript"></script>
<script src="/js/shAutoloader.js" type="text/javascript"></script>
And those one at the end of the body:
<script type="text/javascript">
SyntaxHighlighter.autoloader(
  'js jscript javascript /js/shBrushJScript.js',
  'applescript /js/shBrushAppleScript.js'
);
 
SyntaxHighlighter.all();
</script>
Then to highlight a piece of code:
<pre class="brush: js">
var your_code_here='simple try';
</pre>

I also tweaked the css style to reduce the size in shCore.css:

.syntaxhighlighter textarea {
  ...
  font-size: 0.98em !important;
  ...
}
And to remove the green question mark, in shThemeDefault.css:
.syntaxhighlighter .toolbar {
  /*color: white !important;
  background: #6ce26c !important;
  border: none !important;*/
  display: none;
}

2013-09-29 Zoomer sur graphe XY avec d3.js

d3.js est un framework écrit en javascript qui permet de visualiser des données. Il est conçu pour des sites web et permet de créer des graphes animés. Le résultat est assez esthétique à en juger par les différentes galleries :

Tout d'abord, je dois dire que ça prend du temps de concevoir un graphe. Mon objectif était de créer un graphe XY et de pouvoir zoomer horizontalemen sur une partie. Quand on découvre l'outil et les spécifités de javascript, il est préférable de partir d'une exemple qui fonctionne déjà sans trop chercher à aggréger des bouts de codes venant de plusieurs graphes. L'exemple que j'ai trouvé pour le zoom vient d'ici : js fiddle. Appliqué à mes données, cela donne :

Les premiers pas sont tout de même assez longs, les erreurs ne sont pas faciles à comprendre, surtout quand on est novice. On espère que ce graphe qu'on est en train de constuire pourra resservir. Cela dit voici, quelques astuces.


more...

2013-09-28 Utiliser l'API Linkedin

J'ai utilisé l'API Linkedin pour voir s'il était possible de récupérer mes contacts et de les mettre dans un fichier Excel. Tout d'abord il faut récupérer une clé d'identification en suivant les instructions décrites REST. Cette clé vous donne la possibilité de consulter votre profil, d'effectuer des recherches, de récupérer la liste des contacts, de faire tout ce que votre compte vous permet de faire excepté que vous pouvez le faire jusqu'à un certain point. Par exemple, je peux récupérer l'intégralité de mes contacts, mais je ne peux effectuer qu'une dizaine de recherches et récupérer pour chacune d'entre elles les 110 premiers résultats. La limite de 110 dépend de votre compte (le mien est un compte gratuit), le nombre de résultats de recherche dépend de votre compte développeur (throttle limits). Il est possible d'étendre cette limite mais il faut devenir Partner (Request for Partnering with LinkedIn) mais je ne suis pas allé jusque là. Cela dit, les compteurs sont remis à zéro tous les jours.

Après avoir effectué quelques essais, on s'aperçoit qu'il est impossible d'accaparer des données auxquels votre compte ne vous donne pas accès. D'un point de vue utilisateur, c'est l'assurance qu'un programmeur n'aura pas accès à d'autres informations que celles dévoilées par votre profil public. Elles le seront simplement sous une autre forme (un second site web, uune feuille Excel...)

La clé que j'ai requise est une clé développeur. Elle permet de développer (un site web par exemple) mais ne permet pas de passer à l'échelle. Pour d'autres usages, il faut regarder le site Linkedin Developers.

Le code que j'ai utilisé est écrit en Python et accessible ici, documentation. Pour des pages, il est préférable d'utiliser les outils javascripts développés par Linkedin.

2013-09-27 Format de compression BZ2

Il existe beaucoup de formats de compression. Le plus connu est dans doute le format zip. Il serait impossible de tous les citer (voir compression). Un des logiciels les plus utilisés sous Windows est 7z. Il permet de compresser / décompresser les formats les plus utilisés pour la compression du texte. Et le format 7-zip est le plus souvent le plus efficace.

Alors pourquoi aurait-on besoin d'autre format de compression ? Ce qui marche pour le texte ne marche pas forcément très bien sur la musique, les images ou la vidéo. Pour le texte, on cherche toujours une compression sans erreur. On accepterait mal qu'un document se retrouve altéré durant les étapes de compression / décompression. Pour les images, on recherche principalement des compressions avec un peu de perte : une déterioration de la qualité de l'image qui soit presque invisible pour l'oeil humain. Le format MP3 est aussi une compression de la musique avec perte. Pour la vidéo qui est très gourmande, on utilise le fait que les images changent peu d'une seconde à l'autre comme le décor en fond d'écran. On ne va donc pas compresser les images directement mais la différence entre une image et sa précédente.

Pour en revenir aux données qu'on compresse sans perte, pourquoi utiliser un autre format de compression si 7-zip est meilleur ? En fait, il est meilleur la plupart du temps mais pour certains usages précis, d'autres formats sont plus adaptés, plus simples ou plus performants. Le format Bzip2 ou Bz2. Pour citer Wikipedia, les avantages de ce format sont : une faible utilisation mémoire à la compression, la robustesse des archives à la corruption et la parallélisation possible sur de nombreux threads.

Pour compresser du texte en Python au format bz2, on utilise le programme suivant :

import bz2

# les lignes de texte à décompresser
lines = ["line1", "line2 é"]

# on ouvre un fichier classique en mode binaire
with open(file,"wb") as f :
    comp = bz2.BZ2Compressor()
    for line in lines :
        tof = line + "\n"  # on ajoute une fin de ligne
                           # puis on encode en utf8 avant de compresser
        c = comp.compress ( tof.encode("utf8")  )
        f.write( c )
    c = comp.flush()   # il ne faut pas oublier car le 
    f.write( c )       # BZ2Compressor fonctionne comme un buffer

Pour le relire :

import bz2
lines = [ ]
with bz2.BZ2File(file, "r") as f :
    for line in f :
        s = str(line, encoding = "utf8")
        lines.append (s)
Avec ses deux exemples, il n'est pas besoin de conserver une version décompressée du fichier. On écrit et lit directement les données au format compressé.

2013-09-26 Busy areas in Paris

During summer, one pleasure is to go to work by bike. Simple option is to take a Velib but most of the time, the closest Velib station is empty. The same thing happens when you leave your work to go back home. No bike is available.

I thought maybe this could be used to draw a map of Paris showing areas where people work. I thought about looking at the distribution of the number of available bikes over a day. I already mentioned that the Velib data was available (see Les stations Vélib à Paris un jeudi soir). Next figure shows it for a couple of stations and one of them is clearly a working station: bikes arrive in the morning and disappear at the end of the working day (it was taken a couple of weeks ago during a week day).

The number of available bikes was measured every five minutes. Knowing that every station does not have the same number of spots, I normalized the previous curve by the sum. I then considered the sum between 10am and 4pm. So for each station, I built the following indicator:

 I(s) =  \frac{\sum_{t=10am}^{4pm} X(s,t) }              { \sum_{t=0am}^{11:59pm} X(s,t) }

I used the information to draw a map of Paris with the Velib stations. If I(s) > 0.25 , I used a red flag and a green otherwise.

Basically, companies offices are located in the center of Paris (districts with one digit) and around the Seine, people live around (districts with two digits). It also shows there are some business areas just outside Paris like Issy-Les-Moulineaux (where I work). You can play with the final result below. It uses OpenStreetMap and OpenLayers.


more...

2013-09-21 Le profile online d'un développeur

Beaucoup de sociétés recherchent de bons développeurs et les dernières années ont changé les façons de les trouver. Il y a d'abord les réseaux sociaux Linkedin, Viadeo, Facebook. Mais ce n'est pas tout, les bons développeurs ont souvent partagé leur code ou contribué à des projets open source. On retrouve leurs traces sur GitHub. Certains ont aussi tenté de résoudre certains des problèmes proposés par kaggle. Ajoutons, un site web, un petit blog pour commenter tous les défis techniques auquel un développeur s'attaque.

Il y a dix ans, le CV et la lettre de motivation était la façon de se vendre. Le CV est aujourd'hui sur Linkedin ou Viadeo, la motivation dans le nombre de commit sur GitHub.

2013-09-15 Python extensions to do machine learning

I started to compare the functionalities of some Python extensions (the list is not exhaustive) :

The first one (scikit-learn) covers many features and its documentation is quite clear. When a model is missing, you can look into PyBrain for Reinforcement Learning, in Gensim for Dirichlet Application (Latent, Hierarchical) and in NLTK for any text processing (tokenization for example). For those who do not want to code, Orange would be a good option. The module Theano does gradient optimization using GPU.

A couple of forums, kind of FAQ for machine learning:

It would be difficult to do machine learning without using visualization tools. matplotlib and ggplot would be a good way to start. We also manipulate tables: numpy and pandas. For a command line: ipython or bpython are two common options.

If you are looking for data UC Irvine Machine Learning Repository. If you work with Windows, many of the presented modules can be downloaded from Unofficial Windows Binaries for Python Extension Packages. It also gives a clear view of what package is available on which Python's version.


more...

2013-09-14 Quelques astuces avec pandas python

Ce n'est pas toujours évident d'apprendre à manipuler un nouveau module. On commence toujours par des trucs simples qu'on peine toujours à faire même après quelques requêtes sur un moteur de recherche. Bref, voici quelques raccourcis (on suppose que df est un DataFrame). Je recommande un rapide coup d'oeil à 10 Minutes to Pandas (et celle-ci aussi : Essential Basic Functionality).

Parcourir tous les éléments (version lente) :

self.header = ['index'] + [ _ for _ in df.columns ]
self.values = []
for i in range(len(df) :
    row = [ df.index[i] ] + [ df.ix[i,j] for j in range(len(self.header)) ]
    self.values.append(row)

Parcourir tous les éléments (version plus rapide) :

self.header = ['index'] + [ _ for _ in df.columns ]
self.values = []
for i,row in enumerate(df.values) :
    row = [ df.index[i] ] + [ x for x in row ]
    self.values.append(row)

Créer un DataFrame à partir d'une matrice (liste de listes) :

df = pandas.DataFrame(liste_de_listes, columns = list_nom_colonnes)


more...

2013-09-13 Burger bio et espérence de vie en bonne santé

Le bio a le vent en poupe, voici un fast food bio : BioBurger. Cela donne envie d'essayer. Et puis après avoir écouté cette émission de radio : Nocifs , les additifs ?, notre espérance de vie augmente chaque année mais l'espérence de vie en bonne santé diminue chaque année aussi (Rupture de tendance : l'espérance de vie en bonne santé diminue pour la première fois. Dans quel état vivons-nous la grande vieillesse ?, Espérance de vie en bonne santé : dernières tendances). Bref, on avale plus de cochonneries qu'il y a trente ans (comme l'aspartame) et la probabilité d'avoir un cancer à la fin de la vie augmente. Bio donc.

2013-09-08 Convertir un tableau Excel au format HTML

Le code suivant convertit un tableau Excel au format HTML puis stocke le résultat dans le presse-papier (il suffit donc de faire CTRC+V pour le coller où on veut). La macro convertit la zone sélectionnée au format HTML. Voici ce qu'elle donne :

objectifPythonVBA
test if / elseif .. Then / else / end if
bouclefor .. in ..for .. = .. to .. / next
fonctiondeffonction / end function

Le code de la fonction doit être copié/collé dans un module (ALT+F11 pour voir le code VBA associé à la feuille). Je n'ai pas implémenté beaucoup de styles mais la fonction est facilement modifiable.

' code à copier dans la feuille Excel
Function ColorToHtml(ByVal value As String) As String
    Dim scolor As String
    scolor = Trim(Hex(value))
    While Len(scolor) < 6
        scolor = "0" + scolor
    Wend
    scolor = Mid(scolor, 3, 4) + Mid(scolor, 1, 2)
    ColorToHtml = "#" + scolor
End Function

Sub range_html_to_cliboard()
    Set rge = Selection
    Dim res, line, ce As String
    res = "<table>" + Chr(10)
    
    For i = 1 To rge.Rows.Count
        line = "<tr>"
        For j = 1 To rge.Columns.Count
            ce = "<td style="""
            If rge(i, j).Interior.color Then
                ce = ce + "background-color:" + ColorToHtml(rge(i, j).Interior.color) + ";"
            End If
            If rge(i, j).Font.color Then
                ce = ce + "color:" + ColorToHtml(rge(i, j).Font.color) + ";"
            End If
            If rge(i, j).Font.Bold Then
                ce = ce + "font-weight:bold;"
            End If
            ce = ce + """>"
            ce = ce + rge(i, j).Text + "</td>"
            line = line + ce
        Next
        line = line + "</tr>"
        res = res + line + Chr(10)
    Next
    
    res = res + "</table>" + Chr(10)
    
    ClipBoard_SetData (res)
End Sub

La fonction ne marche pas tel quel sur les tableaux créés avec des styles, ni même avec une liste filtrée. Pour cela, il faut copier la zone désirée puis faire deux collages spéciaux, le formatting et les valeurs, au même endroit. On sélectionne ensuite la zone collée puis on appelle la macro décrite ci-dessus.


more...

2013-09-07 Quelques restaurants encore

Quelques restaurants encore qui figureront sur une carte un jour si j'arrive à écrire le programme qui me permettra de récupérer leurs adresses depuis leur site web et de les afficher sur une carte.

2013-08-31 Comment travaille un chercheur ?

Pendant les vacances, j'ai lu le livre de Cédric Villani Théorème vivant (Poche) (ou le même chez Grasset). Il y raconte la naissance du théorème qui l'a conduit jusqu'à la médaille Fields. J'aurais pu dire démonstration mais le dernier énoncé est sensiblement différent de la première intuition. Cette recherche est plus une sorte de voyage de plusieurs années dans différents continents des mathématiques et le récit de nombreuses rencontres.

Au delà du fait que le livre est bien écrit et se lit facilement, il fait découvrir ce qu'est le métier de chercheur. C'est aussi un univers qui a ses héros ou ses idoles, et comme tout musicien, ils ont leur domaine de prédilection, des parties des mathématiques avec lesquelles ils jouent plus facilement que d'autres. C'est aussi un métier créatif. Je recommande la lecture du livre à tous ceux qui croient que les mathématiques ne sont qu'une longue série d'exercices à maîtriser.

Il y a peu de chercheurs au sens strict du terme. Cela dit, les métiers sont de moins en moins répétitifs laissant place à une partie créative. On est tous un peu chercheur finalement. Le mot recherche évoque aussi l'échec, on cherche, on cherche mais quand est-ce qu'on trouve ? C'est certes un peu angoissant de se dire qu'il est possible de perdre des journée à essayer de résoudre un problème et de découvrir une semaine plus tard que la solution était devant vos yeux depuis le début voire qu'elle n'y sera jamais. Le livre de Villani raconte une une épopée à succès mais parsemés de chemins explorés puis abandonnés. Chaque échec est pourtant l'occasion de comprendre un peu mieux le problème. Ils nous rapprochent de la solution. Et quel plaisir de partir sur une intuition "je suis sûr que dans cette direction, la solution existe" et d'arriver au bout.

La recherche n'est pas toujours aussi abstraite, il faut voir cette vidéo proposée par L'Institut Henri Poincaré : Modèles en jouet - Tadashi Tokieda. Les sciences sont aussi ludiques que la musique. Et on n'a pas besoin d'être un génie pour en faire (voir le film Bienvenue à Gattaca).

Un des premières vidéos qui m'a enchantée est Le cirque de Calder (partie 2, version longue). Il y a un peu de physique derrière cette marionnette acrobate qui ne rate jamais les anneaux.


<-- -->

Xavier Dupré