This tutorial describes how to integrate computable R code (and outputs) in a LaTeX documents in a such a way that a single file can generate two (or more) PDF files. This trick is particularly useful for creating worksheets for R courses.</p>

A very small introduction to integrating R code in LaTeX files

R code is easily embedded in LaTeX documents using Sweave. Using Sweave is easy: you create a standard LaTeX file with the extension .Rnw and you can include R code chunks using special delimiters:
minimalSweaveExample
When the file is compiled (the best way to do it is to rely on the R package knitr under a RStudio environment because the production and compilation of Sweave files are integrated in a very handy manner), the R chunks are evaluated and the results (screen prints and figures) directly included in a .tex which is generated and can be itself compiled to obtain a PDF files including comments, R code and results. R chunks can include various options such as a chunk’s name, cache (to cache the results from one compilation), echo (to show/hide the R code), results (to specify how the results must be printed or even if they must be printed)…

A very small introduction to producing different PDF files from a single LaTeX file

I have been using different tricks for creating worksheets with a teacher/student versions (including or excluding the solutions) for a while. These include in particular:

  • the use of LaTeX package ifthen: this package can handle conditional instructions in LaTeX. To produce a two-version document, a variable \version<code> is first defined: <pre lang="LaTeX"> \def\version{prof} </pre> <p> that can take two values (say "prof" and "etud" in this example, for "teacher" and "student"). Then two new environments corresponding respectively, to the text specific to the teacher and to the student versions, are made:</p> <pre lang="LaTeX"> \newcommand{\profVersion}[1]{\ifthenelse{\equal{\version}{prof}}{#1}{}} \newcommand{\etudVersion}[1]{\ifthenelse{\equal{\version}{etud}}{#1}{}} </pre> <p> The first command <code>\profVersion{truc} tests if the variable \version is equal to "prof" and if so it prints truc. If \version is not equal to "prof", nothing is printed. The second command does the same with the value "etud". Changing the definition of the variable \version in the header of the file yields to change the PDF file obtained while compiling the LaTeX document;
  • the use of LaTeX package comment: this package can print/hide some specific parts of a LaTeX document during compilation at will. This is done by using the commands
    \includecomment{prof}
    \excludecomment{etud}
    

    which, respectively, include/exclude the text written between

    \begin{prof}
      teacher's version
    \end{prof}
    

    and

    \begin{etud}
      students' version
    \end{etud}
    

Unfortunately, none of these two solutions work combined with R chunks in Sweave files because of the way the R chunks are embedded in special environments in the output LaTeX file.

Solution to combine both needs

To combine both needs, a simple solution consists in using direct TeX script. A variable \version is first defined, like when the ifthenelse package is used:

\def\version{1}

In our example, this variable can take two values: 1 (teacher version) and 0 (student version). Teacher specific text is included after the \if command testing the value of \version:

\if \version1
  \emph{This is the teacher's version...}
\fi

and similarly for the student specific text. A complete example (in which I included several tricks with LaTeX, Sweave files and chunk options) is provided at the end of this tutorial, which can be compiled to give this document for students and this document for the teacher.

conditionalSweave.Rnw

</div>


Le but de ce tutoriel est de décrire l’automatisation de la sauvegarde des données d’un serveur web (fichiers présents sur le serveur et contenu de bases de données MySQL) sur un autre. Le serveur contenant les données à sauvegarder dispose d’un accès sFTP par login/mot de passe et le serveur de stockage dispose d’un accès sFTP par clé publique/privée (accès qui n’est pas utilisé dans le tutoriel). Les deux serveurs seront appelés respectivement :

  • padawan pour le serveur contenant les données à sauvegarder (Debian, hébergement OVH mutualisé)
  • master pour le serveur de stockage (Ubuntu Server, 14.04 LTS)

Sauvegarde des fichiers du serveur padawan

Les données sont sauvegardées en utilisant une tâche CRON hebdomadaire sur master qui invoque le programme rsync pour synchroniser le répertoire distant à sauvegarder sur padawan avec un répertoire local sur master ; dans la suite, ces deux répertoires seront notés saveme. Pour autoriser rsync à utiliser la connexion par login/mot de passe de manière non interactive, il faut installer le package Ubuntu suivant sur master :

sudo apt-get install sshpass

La tâche CRON est ensuite créée en utilisant la commande

sudo crontab -e

puis en insérant en fin de fichier la ligne suivante :

30 01 * * 3 rsync -ratlz --rsh="/usr/bin/sshpass -p PWD ssh -o StrictHostKeyChecking=no -l LOGIN" padawan.fr:saveme/  /home/saveme/

qui permet de synchroniser automatiquement :

  • tous les troisièmes jours de la semaine (3)
  • à 1h30 (30 01)
  • les données trouvées sur le serveur padawan.fr qui se trouve dans le fichier saveme à la racine du répertoire utilisateur
  • pour l’utilisateur LOGIN et le mot de passe PWD
  • dans le répertoire /home/saveme/ du serveur master

Sauvegarde des bases de données

Les bases de données sont copiées dans un fichier SQL dans un dossier situé dans le répertoire saveme de padawan (et donc ainsi, elles mêmes copiées toutes les semaines sur master. Cette opération est effectuée à l’aide d’un script PHP présent sur padawan et automatisé par une tâche CRON sur ce même serveur via l’utilitaire de OVH. Le script PHP qui assure la sauvegarde est :

function sauve($host, $user, $pass) {
  system(sprintf(
    'mysqldump --no-tablespace --opt -h%s -u%s -p"%s" %s | gzip > %s/'.$host.'.sql.gz',
    $host,
    $user,
    $pass,
    $user,
    getenv('DOCUMENT_ROOT')
  ));
  echo '+DONE'.$host;
}
 
sauve("SERVEUR", "USER", "PASS");

dans laquelle le serveur SQL est “SERVEUR”, le nom d’utilisateur et la base de données à sauvegarder sont “USER” et le mot de passe de connexion est “PASS” (le script est aisément modifiable pour prendre en compte le cas où le nom d’utilisateur et le nom de la base de données diffèrent). La tâche CRON est ensuite configurée via l’interface manager de OVH : dans le menu Plateformes/CRON, cliquer sur “Ajouter une planification” (à droite). La commande à exécuter est le chemin vers le script PHP précédent, le langage est PHP (n’importe quelle version). L’écran suivant définit la périodicité de la tâche (par exemple, tous les jours, heures fixes à 23h) comme dans l’exemple ci-dessous : cron_ovh


Ce post recense deux alternatives libres à doodle : dudle et Framadate et détaille leur installation sur Ubuntu server, 14.04 LTS.

dudle

dudle est une application web écrite en JavaScript et ruby. Les différentes étapes de l’installation sont les suivantes :

1. Récupérer le code source

Le code source doit être récupéré avec l’application bazaar qui s’intalle avec

sudo apt-get install bzr

En super-utilisateur, placez vous ensuite dans le dossier dans lequel vous souhaitez installer l’application et entrer

bzr branch https://dudle.inf.tu-dresden.de/ dudle
chown www-data:www-data -R dudle
chmod o- -R dudle

Les instructions pour l’installation se trouvent dans le fichier README mais quelques conseils pas à pas sont fournis ci-dessous.

2. Installer les dépendances

Le logiciel nécessite également l’installation de ruby et de diverses librairies :

sudo apt-get install ruby ruby-gettext rubygems ruby-dev libxml2-dev zlib1g-dev
sudo gem install ratom

Au niveau du serveur apache, le module auth_digest doit être activé :

a2enmod auth_digest
service apache2 reload

Pour utiliser les différentes langues, vous devez aussi les télécharger depuis internet avec les lignes de commande suivantes :

cd dudle
for i in locale/??; do
  wget -O $i/dudle.mo https://dudle.inf.tu-dresden.de/locale/`basename $i`/dudle.mo
done

3. Préparer l’hôte virtuel

Dans le répertoire /etc/apache2/site-available, créez (en super-utilisateur) un fichier dudle.conf contenant les instructions suivantes : dudle_apache La directive ScriptAlias permet d’activer l’interprétation des scripts cgi et la directive AllowOverride autorise la prise en compte des fichiers .htaccess. N’oubliez pas d’ajouter dudle.server-name.org à votre liste d’hôtes /etc/hosts. Ensuite, vous devez éditer le fichier .htaccess qui se situe dans le répertoire d’installation de dudle et ajoutez-y la ligne suivante :

SetEnv RUBYLIB /DIR-VERS-INSTALL/dudle

Enfin, pour finaliser le fonctionnement de l’installation, vous entrez

a2ensite dudle
service apache2 reload

Dudle est fonctionnel à http://dudle.server-name.org. Remarque : L’installation n’est pas particulièrement facile et très mal documentée, l’interface est plutôt peu conviviale et j’ai des problèmes importants avec l’encodage : l’application semble incapable d’interpréter le moindre accent.

Framadate

Framadate est une application PhP/MySQL basé sur le logiciel STUdS qui est lui-même développé par l’université de Strasbourg.

1. Récupérer le code source

Le code source doit être récupéré avec l’application git qui s’intalle avec

sudo apt-get install git

En super-utilisateur, placez vous ensuite dans le dossier dans lequel vous souhaitez installer l’application et entrer

git clone https://github.com/framasoft/OpenSondage.git opensondage
chown www-data:www-data -R opensondage
chmod o- -R opensondage

Les instructions pour l’installation se trouvent dans le fichier INSTALL mais quelques conseils pas à pas sont fournis ci-dessous.

2. Installer les dépendances

Framadate demande l’installation des extensions ADOdb et gettext :

apt-get install php5-adodb php-fpdf php-gettext

Les langues peuvent être configurées via l’installation des locales correspondantes, par exemple :

locale-gen fr_FR
locale-gen fr_FR.UTF-8
dpkg-reconfigure locales

pour installer le français.

3. Configurer la base de données

J’ai choisi une BD MySQL mais d’autres alternatives sont possibles. Pour la base de données MySQL, créer sur le serveur une nouvelle base avec un utilisateur dédié puis initialisez-là à l’aide du script install.mysql.sql. Les paramètres de la base (nom de la base, nom du serveur, nom de l’utilisateur, mot de passe, type de base…) sont à entrer dans un fichier variables.php dont un exemple se trouve dans le fichier variables.php.template

cp variables.php.template variables.php
chown www-data:www-data variables.php
chmod o- variables.php

Éditez le fichier variables.php et mettez à jour toutes les variables. J’ai laissé non configurées les variables const LOGOBANDEAU et const LOGOLETTRE.

4. Configurer la partie admin

Dans le dossier admin de l’application, créer un fichier .htaccess que vous éditez en ajoutant les instructions suivantes

AuthType Basic
AuthName "Restricted area: please provide username and password"
AuthBasicProvider file
AuthUserFile /CHEMIN-APPLI/opensondage/admin/passwd/.htpasswd
Require user opensondage

Créez ensuite un dossier passwd dans le dossier admin puis un fichier .htaccess dans ce dossier contenant l’instruction

deny to all

pour prémunir la lecture du mot de passe de la partie administration de l’application. Enfin, créez le fichier mot de passe .htpasswd dans le dossier passwd en copiant le résultat de la commande

htpasswd -mnb opensondage MOT-DE-PASSE

dans celui-ci. Assurez-vous que tous ces fichiers et dossiers créés soient lisibles par le serveur.

5. Configurer l’hôte virtuel

Dans le répertoire /etc/apache2/site-available, créez (en super-utilisateur) un fichier framadate.conf contenant les instructions suivantes : famadate_apache AllowOverride autorise la prise en compte des fichiers .htaccess pour l’authentification. N’oubliez pas d’ajouter dudle.server-name.org à votre liste d’hôtes /etc/hosts. Le fichier variables.php doit être proprement configuré pour son URL

const STUDS_URL = 'framadate.server-name.org';

Enfin, pour finaliser le fonctionnement de l’installation, vous entrez

a2ensite framadate
service apache2 reload

Framadate est fonctionnel à http://framdate.server-name.org. Remarque : L’installation est facile et l’interface est vraiment conviviale. Les accents passent sans problème. J’ai donc finié par opter pour cette solution.


Sous une distribution Kubuntu fraîchement installée, le message d’erreur suivant apparaît au lancement d’un DVD avec vlc

libdvdread: Encrypted DVD support unavailable.
************************************************
**                                            **
**  No css library available. See             **
**  /usr/share/doc/libdvdread4/README.css     **
**  for more information.                     **
**                                            **
************************************************
libdvdnav: DVD Title:...

On a freshly installed Kubuntu distribution, I had the following error while trying to read a dvd with vlc

libdvdread: Encrypted DVD support unavailable.
************************************************
**                                            **
**  No css library available. See             **
**  /usr/share/doc/libdvdread4/README.css     **
**  for more information.                     **
**                                            **
************************************************
libdvdnav: DVD Title:...

This problem is solved by activating the medibuntu repository: to do so, as a super-user, edit the file /etc/apt/sources.list and add the following lines:

deb http://packages.medibuntu.org/ precise free non-free
deb-src http://packages.medibuntu.org/ precise free non-free

(if you’re using Ubuntu 12.04 LTS (precise): these lines must be adapted to your own distribution). Then add the following gpg signatures:

wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add -

and update the package list:

sudo apt-get update

Finally, install the package to read CSS encrypted DVD:

sudo apt-get install libdvdcss2

Mise à jour (août 2014)

La bibliothèque medibuntu n’existe plus. Il faut maintenant, installer le package ubuntu-restricted-extras (ou Xubuntu-restricted-extras où “X” dépend de votre distribution : kubuntu, xubuntu…) et lancer la ligne de commande

sudo sh /usr/share/doc/libdvdread4/install-css.sh

Avant…

Ce problème est résolu par l’installation de la bibliothèque medibuntu : pour cela, dans un terminal, éditer en super-administrateur le fichier /etc/apt/sources.list et ajoutez-y les lignes suivantes :

deb http://packages.medibuntu.org/ precise free non-free
deb-src http://packages.medibuntu.org/ precise free non-free

(donné ici pour Ubuntu 12.04 LTS (precise) et à adapter selon votre distribution). Puis mettez à jour les clés gpg du système :

wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add -

et rechargez la liste des packages

sudo apt-get update

avant d’installer les packages permettant de lire ce type de DVD :

sudo apt-get install libdvdcss2


(this tutorial can also by used dummies in geography…)

This tutorial explains how to build a map from a matrix containing city names and corresponding country codes, as well as, eventually a frequency attached to each country. The script

  • first find thanks to the nice open projet Open Street Map the coordinates of the corresponding cities. This step uses the R package RJSONIO to parse the result of the query performed on open street map;
  • from this query, the map is made, using the R package OpenStreetMap (see my previous post for an example of how to use this package and indications on how to install it).

The data

The data I used for this application were coming from Avner (a colleague who must now forget all he knows about this sh*** Go*** Map…) and are highly confidential! I thus provide you a toy example with a data frame with city names, country codes (all cities located in France) and frequencies.

cities = data.frame(nom=c("Toulouse", "Paris", "Égletons", "Marseille", 
                           "Clermont Ferrand"), pays=rep("FR",5),
                     effectif=c(20,5,15,3,3))
print(cities)

that gives the following data frame:

               nom pays effectif
1         Toulouse   FR       20
2            Paris   FR        5
3         Égletons   FR       15
4        Marseille   FR        3
5 Clermont Ferrand   FR        3

Note that some of the names of the cities are a bit tricky to handle (with accents on letters or spaces in the names).

Find the coordinates of the cities

Using the R package RJSONIO, I made a function which, using city name and country code, first sends a query to OpenStreetMap for locating the city and then downloads the city coordinates (in terms of latitude and longitude). City names are simplified replace white spaces with the HTML code “%20”. If the city is not found, the function returns a double NA for both coordinates.

locateCountry = function(nameCity, codeCountry) {
  cleanCityName = gsub(' ', '%20', nameCity)
  url = paste(
    "http://nominatim.openstreetmap.org/search?city="
    , cleanCityName
    , "&countrycodes="
    , codeCountry
    , "&limit=9&format=json"
    , sep="")
  resOSM = fromJSON(url)
  if(length(resOSM) > 0) {
    return(c(resOSM[[1]]$lon, resOSM[[1]]$lat))
  } else return(rep(NA,2)) 
}

The function is then applied to all my cities:

coord = t(apply(cities, 1, function(aRow) locateCountry(aRow[1], aRow[2])))

to obtain a matrix with 5 rows (the cities) and 2 columns (longitude and latitude, in that order).

Draw the map!

This part uses the R package OpenStreetMap.

First, the map is set with proper boundaries (I focused on France, since I only had French countries): the coordinates of the border must be given with two vectors corresponding to the upper left corner and to the down right corner, respectively. I personally use OpenStreetMap to set these values properly:

frenchMap = openmap(c(51.700,-5.669), c(41,11), type="osm")
plot(frenchMap, raster=TRUE)

Then, the coordinates obtained in the previous section are transformed into coordinates suited to OpenStreetMap:

xy = SpatialPoints(apply(coord,2,as.numeric))
proj4string(xy) = CRS("+proj=longlat +ellps=WGS84")
spCities = spTransform(xy, CRS("+proj=merc +a=6378137
  +b=6378137 +lat_ts=0.0+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m
  +nadgrids=@null +no_defs"))

and all cities are finally represented with dots having a radius proportional to the square root of their frequency. I reduced the alpha chanel of the color to allow for transparency (which is very usefull if some of your cities are overlapping):

sapply(1:nrow(cities), function(ind) {
  plot(spCities[ind,], add=TRUE, col=heat.colors(20,alpha=0.5), lwd=2, pch=19,
       cex=sqrt(as.numeric(cities[ind,3]))/nrow(cities)*2)})

The result is:

mapEx