Affichage des articles dont le libellé est en. Afficher tous les articles
Affichage des articles dont le libellé est en. Afficher tous les articles

lundi 4 janvier 2021

Recovering set of git repos with new computer

I am a heavy Git user, I use it for mostly... almost everything! I have a lot of repos on my machine, connected to various online accounts (github, gitlab, but also others). Most of these are in kept in some dedicated folder (say /home/myname/dev, for example).

Now, I have a new computer. How do I import all these repos at once? Of course, I don't want having to clone them one by one manually! That would be ok for 1,2 or 3 repos, but I've got dozens.

So I just wrote these 2 scripts to 1-generate a list of remotes in a text file (on the "old" machine), and 2-automate cloning from this file on the new computer.
(Finding something similar on SO or elsewhere seems incredibly hard, thus I rewrote that, probably not the first one...)

First, on the old computer, drop the following script in the folder holding the repos, and run it:

# git_generate_url_list.sh
# Generate a list of git remotes that are in the current folder
# (also logs their sizes)
# S. Kramm - 2020-01-04

#!/bin/bash

a=$(ls -1d */)

echo "# repos list" > url_list.txt
echo "# repos size" > repos_size.txt
for i in $a
do
	echo "Processing $i"
	du $i -hs >> repos_size.txt
	cd $i; git remote get-url --all origin >> ../url_list.txt
	cd ..
done

This also assesses the sizes of each of these, can be useful to detect something going wrong...

Then, take that url list file on new computer, drop it in /home/myname/dev (or whatever location), along with this second script, and run it:

# git_clone_from_url_list.sh
# clone in current folder from a set of urls, from file given as argument
# S. Kramm - 2020-01-04

#!/bin/bash

if [ "$1" == "" ]
then
	echo "Missing filename!"
	exit 1
fi

echo "git cloning from file $1"

while read a
do
	if [[ ${a:0:1} != "#" ]] # if not a comment
	then
		echo "importing repo from $a"
		git clone $a
	fi
done < $1

Of course, if you use https, you will need to provide passwords for the private repos, but only once per online service.

Edit: also checkout the other post about this topic.

jeudi 4 décembre 2014

C++: erasing elements of std::vector using a lambda

Removing elements from a vector is a task that one can encounter pretty often and that isn't as easy as one could think.

The simplest case is when the index of the unwanted element is known. The std::vector class provides a first form of the erase() member function that takes an (const) iterator as argument.

Thus, if I want to remove, say the 10th element, it's as easy as:

    std::vector<whatever> myVec;
//... fill with more than 10 elements
    myVec.erase( myVec.begin() + 9 );

And if you want to remove the 3 elements between positions 10 and 12, it will be the second form of this function, which has two arguments:

    myVec.erase( myVec.begin() + 9, myVec.begin() + 12 );

(Yes, the second argument defines the first one you want to keep)

But what happens when you want to remove elements based on their value ? Say remove all elements that have value foo (assuming that value is of type whatever).

This is a task for std::remove(). It actually does not remove anything, it just switches element around so that the ones to be erased will be at the end, and it returns an iterator pointing on the first element to be erased. The next step is to feed that iterator to std::vector::erase().

The code will using its second form:

    myVec.erase(
        std::remove(            // returns iterator on
            myVec.begin(),      // first element to
            myVec.end(),        // be removed
            foo
        ),
        myVec.end()
    );

(This is known as the Erase–remove idiom.)

Next, what if you want to remove elements based on some property they have ? Consider for example a vector of vectors:

   std::vector<std::vector<Whatever>> myVec2;

And now the task is to remove elements that hold less than 2 elements. Okay, so we need to check every element, and decide to remove it or not.

This is a task for the second form of that same algorithm, remove_if(). Instead of a value, it takes as third argument a predicate, and will "remove" (move, actually) the considered element if that predicate returns "true". A predicate is usually implemented as a functor, which is an object of some class that defines the operator() and that returns a bool, based on the given value.

At first, this seems like a harsh constraint, as no one wants to declare a class for such a trivial task. But before C++11 came out, that was required (unless, maybe, using some Boost library). Or else, we needed to iterate through the vector and test each element, copy it or not, and swap:

   vector<vector<whatever>> newv;
   newv.reserve( myVec.size() ); // to avoid resizing when using push_back
      for( size_t i=0; i < myVec.size(); i++ )
         if( myVec[i].size()<MinSize )
            newv.push_back( myVec[i] );
   std::swap( myVec, newv );

This is where C++11 and lambdas come in. A lambda can be seen as a sort of "anonymous inline function", that captures variables in scope. Here, as the function iterates over all the elements, each of them will be a std::vector.

A lambda is made of three parts:

  • [how capturing variables happens],
  • (the functions arguments),
  • {The body of the function}.

The complete code:

   std::size_t MinSize = ... (some value);
   myVec2.erase(
      std::remove_if(
         myVec2.begin(),
         myVec2.end(),
         [&]( const std::vector<whatever>& vw ) // lambda
            { return vw.size() < minsize; } 
     ),
     myVec2.end()
   );

More on c++ lambdas.

mercredi 14 mai 2014

Subversion: colordiff fo html files

(Mostly a reminder:)

Say you have some software project, hosted on some Subversion repository. You happily edit your files, and before committing you want to have a quick look at the edits you have done.

No problem, as simple as:
> svn diff 

But this outputs lots of text, not easily readable. Ok, lets' go with colordiff:
> svn diff | colordiff

And then you get drowned under floods of nice and flashy colors, and you have to painfully scroll your terminal. Well, what else ? A simple redirecting in a file won't keep the colors.

This is where another magic tool shows up: aha. Yeah, that's his name. It's a "ANSI to HTML" converter. Install it with sudo apt-get install aha, and then, go:
svn diff | colordiff | aha >mydiff.html

For conveniency, you can now add a new target to you makefile:
diff:
     svn diff | colordiff | aha >mydiff.html
     xdg-open mydiff.html
Thus, entering make diff at the shell will show you the current edits you have done up to now.
xdg-open is just the Gnome app that opens the default application associated with a file type. On Windows, just use the file name alone, as this OS has some mechanism to open the file with the default application when given a file name.

Edit 20141224: a small improvement: in order to keep track of all these generated diff files, you can append date/time to the filename so that each new one doesn't erase the previous one. This can be done easily with bash (not that hard for Windows either, but no time at present to figure that out):

ifndef COMPSPEC
NOW=$(shell date +%Y%m%d_%H%M)
BROWSER=xdg-open
endif

diff:
     svn diff | colordiff | aha >mydiff_$(NOW).html
     $(BROWSER) mydiff_$(NOW).html

Notice the conditional, so that this makefile should also work out-of-the-box under Windows (except for the time/date, but if you send it to me, I'll publish it ;-) )

vendredi 11 avril 2014

State machine diagrams with Graphviz

Once in a while, I need to draw a simple state machine diagram. These are a quick way to show in a visual way how a system works.

While these can be drawn with general drawing tools, or even with more dedicated tools, I usually prefer the textual way. Describing a drawing through some design language with an acceptable learning curve and letting some application do the drawing is IMO a better approach: editing the graph afterwards is just a matter of editing the source file.

Okay, so what tool ? Some are... funny (and I mean it!), but are not really usable for anything more than a small graph, or anything that needs to be edited many times.

No, this post is about Graphviz and it's associate set of tools. It does truely have some oddities buts its the best around.
Among its oddities, the default size units are in distance units. For an image, yes, no pixels here. Wait, that's not all ! The default units are inches. Inches !
I suppose this is for historical reasons and it seems that there is no option to change this. After thinking about it, once you go with distance, then, as metrication of image density is still not used, you might as well stay with inches.

Another thing, don't expect to be able to define precisely the position of nodes and edges: these are done by a placement algorithm, and adjusting this is not easy although some commands should help.

Nevertheless, say you want to describe some simple state machine. Just a light bulb connected to a switch.

Elementary graph

The associate state machine can be described by the following text file:
digraph g{
   rankdir="LR";
   edge[splines="curved"]
   ON -> OFF;
   OFF -> ON;
}

Assuming you have Graphviz correctly installed, the following shell command will generate the image:

dot -Tpng:cairo myfile.dot >myfile.png   


Transitions

Ok, now lets add the transitions (the switch action). Lets call it "sw": if sw=1, the light bulb will be on, if 0, it will be off.

Ah. Here some problem appear. In the field of electrical engineering, the transitions between the states are frequently based on some boolean variable. Notation for the complement operation seems to be country-dependent. In France, this is usually expressed by a bar over the expression ("sw barre"), in Latex math-syntax, it will be $\bar{sw}$.

So, how can we manage this issue ?

First (and easiest), forget about the "bar" thing, and just go for plain text:

digraph g{
   rankdir="LR";
   edge[splines="curved"]
   ON -> OFF [label="sw=0"];
   OFF -> ON [label="sw=1"];
}




This is not very satisfying, it clutters the diagram.

Second solution: use Unicode. Graphviz natively supports it, and Unicode provides some special character that is supposed to handle this situation. So just enter:
digraph g{
   rankdir="LR";
   edge[splines="curved"]
   OFF -> ON [label="sw"];
   ON -> OFF [label="s̅w̅"];
}
(sorry, seems that the current hosting of this blog does not correctly display this, this is why the bar isn't exactly over the two letters).
 
In GTK+ based apps (Gedit, for instance), Unicode can be entered by hitting CTRL+SHIFT+U, then entering the desired character code (here '+0305') after each letter. Here, you need to do this manually after each letter of the label .

Unfortunately, the final rendering depends on the font used by the layout engine. It seems that the default png output of Graphviz does not use the Cairo library. Or if it does, it does not provide any control on the used font, so the final result looks quite ugly:


Direct insertion into Latex source file

If the graph image is intended to end up in a Latex source file, then check out the Graphviz package. It allows you to insert directly the graph command into the main Latex document. Unfortunately, this does not mean you suddenly have all the associated formatting power: this package only calls the 'dot' command himself, the only benefit is that you don't have to do it yourself and then import the image file into the Latex document. So for the issue detailed up here, it is of no help.

Another tool, dot2tex, has been specifically designed to have it all: direct editing of dot file inside Latex file and Latex formatting for labels and edges. Basically, it converts the dot file into PSTricks and/or PGF/TikZ format using some Python magic, then process it as regular Latex code.
Unfortunately, installation on my machine seems to suffer from some obscure Python bug, so I can't tell more at present! I hope to be able to try this soon.

Edit 2015/05: for more precise positioning of your nodes and vertices and better rendering, you'd better go off with a Latex-based solution. Tikz seems to be the easiest, see for example this sample.
For my own record, here are some relevant links:

mercredi 3 avril 2013

Writing portable makefiles

Edit 2016-10-21: I notice this post comes on first page of Google "portable makefile" request, so I thought I'd might add some context. This post was written when I was struggling with this kind of stuff, and should be taken as a "proof of concept" post. For me, this is definitely over, as I (almost) completely quit using Windows, being for several years now a happy GNU/Linux user. Readers must be aware that although some tricks are given here, it is certainly not the best approach for setting up a portable build system. If you are in that situation, the best way to go is probably CMake, as it is today the de facto standard tool.

This note is about GNU Make makefiles syntax, and how to write them to keep them OS-independent as much as possible.

1- Introduction: computers and file systems

When it comes to computers and their associated filesystem, there are two worlds on earth.
One that considers that a path to a file spells this way:
path/to/the/file
and the other world that considers that the correct syntax is:
path\to\the\file

This may sound silly (and it is) but it can lead to some complications. Not only because these two worlds use a different symbol, but mostly because they both have a special meaning for the other symbol.

To put it clearly, on a Linux machine (that uses the '/' path separator), the backslash has a special meaning in some situations (shell scripts, makefiles, ...) meaning "I have no more room on this line, lets keep on and continue the current command on next line" (and that trick is very valuable for readability). And it follows what is a convention in C and C++ source files.
 
In the other world (MS Windows), the default shell (cmd.exe) interprets the slash character as the option separator. For example: del /F path\to\file.txt

And, no, at least in XP, the Windows shell DOES NOT accept both path/to/file and path\to\file, as it is frequently said in many places. Try to do something like del path/to/file to check. Maybe this has changed with Windows 7, 8, 11 or 42, I'm not really interested, but with Windows XP's shell, it does-not-work.The cause of that misunderstanding is probably that system calls (that is, the functions you call from inside a program), DO accept forward slashes or backslashes in paths).

Anyway, the two shells (Linux/bash and Windows/cmd.exe) are sooo different, only insane people would consider trying to write a "compatible" script, running equally on both systems (1).

However, there is one situation where a same command semantic must be executed equally in those two different environments: makefiles

Basically, a makefile is a set of commands that are executed by the shell.
Say for one target, we want to erase some file, even "read-only" ones. On one environment, this must be done with the following command:
rm -f path/to/file
while on the other, it will be:
del /F path\to\file

The question is: how can a write that command in my makefile so that it expands in these two different syntaxes at runtime? And more generally, how do I write portable makefiles ?

2 - Handling command names

First, lets manage the different command names (and their options). That's the easiest. Just define a variable holding the name of the command, that will hold different values depending on platform. The easiest way to detect the platform is to check for the existence of a Windows-only environment variable, say ComSpec (but some sources relie on SystemRoot that can be used too).

ifdef ComSpec
    RM=del /F /Q
else
    RM=rm -f
endif


This will be in the upper part of the makefile, before any recipes. Then, in the recipes, just use $(RM) in place of the command.

3 - Handling paths

Secondly, you need to handle the path separator. Two situations need to be handled:
- paths to explicit files (the example above),
- automatic paths, build using make's wildcards and substitution functions.

Remember that you need to care for this only for system calls. Whatever the platform, GNU Make, gcc or other "regular" development tools handle very well paths with forward slashes, whatever the platform. To make it clear, say we have these lines that follow the classical target-prerequisite-command scheme:
mytarget: path/to/file
   $(SOMECOMMAND) path/to/file


The first line will do fine, but the second line will generate an error on Windows if SOMECOMMAND expands to a built-in shell command.

3.1 - Processing explicit paths

First, for the explicit paths, we can proceed with the same trick: define a variable holding the required separator ('\' or '/'), then use this variable in the commands.

ifdef ComSpec
    PATHSEP2=\

else
    PATHSEP2=/
endif

Ha. Unfortunatly, this does not work, because the backslash is interpreted by make as the "keep on same line!" request, and not as a character. Ok, so we need to escape that backslash, in order to fool make:

ifdef ComSpec
    PATHSEP2=\\
else
    PATHSEP2=/
endif

Funilly, this works half ways: the definition is accepted, but the variable holds the two backslashes! Fortunatly, the Windows shell accepts paths that looks like path\\to\\file (don't ask me why...)

Almost done. This still does not work: the above definition adds a trailing space at the end of the variable, i.e. its usage in:
path$(PATHSEP2)file
will expand into:
path/ file  (or  path\ file  on Windows)
and that will not be ok, for sure!

So finally, we need to add the following definition and function call, that removes that ugly trailing space:
PATHSEP=$(strip $(PATHSEP2))

That way, an explicit erasing command in a makefile (for example) can be portably written as:
$(RM) path$(PATHSEP)to$(PATHSEP)file

Ok, now how about paths that are automatically build.

3.2 - Processing generated paths

For example, you usually define a variable holding all the object files, that is build from all the source files. If these are in a folder named src, and the object files are in a folder named obj, then you can define the list of the source files with:
SRC_FILES=$(wildcard src/*.cpp)

and the list of corresponding object files with (2):
OBJ_FILES=$(patsubst src/%.cpp,obj/%.o,$(SRC_FILES))

But heres comes the problem, trying to erase all the object files with:
$(RM) $(OBJ_FILES)
will expand on Windows as something like:
del /F obj/file1.o obj/file2.o obj/file3.o
and that will throw an error, because the shell will consider that what is behind the slash as some option.

Two solutions can be used:
  • either use PATHSEP in the "patsubst" function call above:
OBJ_FILES=$(patsubst src/%.cpp,obj$(PATHSEP)%.o,$(SRC_FILES))
  • either use the "subst function", that replaces some pattern in a string with another:
OBJ_FILES_CORRECT=$(subst \,/,$(OBJ_FILES))

But this latter solution implies the creation of another variable, which can be error-prone in dense makefiles.

4 - Command separator

Another problem that needs to be handled is the command separator. In many make tutorials, you see commands written this way:
cd MyFolder; SomeCommand Some Arguments
which means: "get down into folder MyFolder, and execute SomeCommand with Some Arguments"
This is an invalid syntax on Windows where the command separator is &.
So, again, the variable trick:

ifndef ComSpec
    CMDSEP=;
else
    CMDSEP=&
endif


and the above command will be written:
cd MyFolder $(CMDSEP) SomeCommand Some Arguments

5 - Debugging makefiles

Portable makefiles are also tougher to debug that ordinary makefile. You will run into countless issues, and each one might require some special treatment.

As you may know, you can prefix each make command with the special symbol '@', that will suppress the default echo to terminal. This is useful for the makefile user, that doesn't want to see all the steps of the build process: he just wants to get the job done, as quickly as possible.
But while writing the makefile (an debugging it), you will need all this information, so you don't use that prefix, of course...
   ... until you're done ! Then you want to deliver a nice experience to the makefile user, and you carefully edit your code to prefix each command with '@'
And then... Ah. Something got broken in the makefile when this new build step was added, but where exactly ? So you start again removing all these stupid '@' characters that you spend so much time to add!

Don't. Instead use again the good'ol variable trick. Instead of using the special character '@', prefix right away all of your commands with $(L). For example:
obj/%.o : src/%.cpp
    $(L)$(CXX) -o $@ -c $< $(CFLAGS)


And add the following lines in the first part of the makefile:
ifeq "$(LOG)" ""
    LOG=no
endif

ifeq "$(LOG)" "no"
    L=@
endif



This way, launching make with no special option will run silently, and in case of trouble, just tell your mate to run:
make <target-name> LOG=yes
and all the commands that are launched will (magically) appear on screen (3).

6 - Conclusion

These are some hints that can help you design more portable makefiles. I'll finish with one remark. For "big" projects, maybe you should rely on "makefile generators", that is, programs that do all these low-level tasks (and much more). The most known are CMake and the GNU set of tools, but others can be used.

Finally, one quote from "Managing projects with GNU Make": "... there is no such thing as perfect portability, so it is our job to balance effort versus portability."


(1) Unless you use a non-native modern script langage such as Python of course.
(2) In real life, the folders name would also be stored in variables, i.e. :
OBJ_FILES=$(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
(3) Or in a text file if you redirect it, and that is usually a good idea when output starts to get large.

samedi 30 mars 2013

Octave/Ubuntu: problems installing additional packages

This post started out as a question on SO, but as I finally found the answer, I though it might interest other people.

Consider the following situation: you need to do some function data-fitting, you don't {wan't to use / have access to} Matlab, and think that Octave might be an alternative.

First problem: your version of Octave on you current Ubuntu 12.04 is slightly outdated, and sudo apt-get install doesn't seem to have a more recent version.

You can upgrade using an unofficial ppa, as described on this page.


Then, Octave actually doesn't have data-fitting material. It is provided as additional packages (see here). And according to this page, it is the optim package that you need.

Once downloaded, running the following line in the Octave shell
pkg install optim-1.2.2.tar.gz
tells you that there are additional packages required (`miscellaneous`, `struct` and `general`). And at one point you might hit the following error (or something near), complaining about something called mkoctfile:

make: /usr/bin/mkoctfile: Command not found
    make: *** [__exit__.oct] Error 127
    'make' returned the following error: make: Entering directory `/tmp/oct-P11IKL/general/src'
    /usr/bin/mkoctfile __exit__.cc
    make: Leaving directory `/tmp/oct-P11IKL/general/src'
    error: called from `pkg>configure_make' in file /usr/share/octave/3.6.2/m/pkg/pkg.m         near line 1391, column 9
    error: called from:
    error:   /usr/share/octave/3.6.2/m/pkg/pkg.m at line 834, column 5
    error:   /usr/share/octave/3.6.2/m/pkg/pkg.m at line 383, column 9


If you search about this, you might find this question, where the answer (unaccepted) says that you should sudo apt-get install octave-signal

Don't ! Depending on your ppa settings, this might revert your Octave installation to 3.2, which is not desirable.

The solution requires to install the Octave development packages with :
sudo apt-get install octave-pkg-dev

Finally, It seems that installation of some (?) packages writes stuff in /usr/share/octave/, which can't be done by user (and 'sudo' can't be run from Octave 's shell).
So the easiest it to switch as root before starting Octave (with su), then install the packages, then quit Octave.



lundi 2 avril 2012

GNU Make and the foreach() function

Make is a nice tool for building stuff. Software, of course, but not only, I use it also for building pdf files from Latex sources. However, its usage is not obvious at all, and many pitfalls lie in front of the newcomer. And the manual is not a great help when it comes to learning new features. Joyfully, there are bunches of tutorials out there.

However, some advanced tricks are rarely covered. Here is one trick that can be useful in some situations. Beware, it assumes you already know the basics about Make (GNU flavor), in case not, please go read some tutorial and come back in a while...

Lets say you have a folder containing some source files of type ".in", say foo.in and boo.in. These files need to be processed with some tool (call it "some_tool" for now) to build the output files. This (awesome) thing has a rather classical syntax:
some_tool in_file out_file [option]

Say you need to build these with two different configurations to produce two output files for each input files, say one of type "X" and one of type "Y". Here, from the two input files, you need to build:
foo_X.out
foo_Y.out
boo_X.out
boo_Y.out

How can Make help you so you only build the ones that are needed ? For the example, say that each build process takes several hours, so you really don't want to build them if it's not needed.

First create a variable holding all the input files:
infiles := $(wildcard *.in) 

Then, add a generic rule telling how to build a ".out" file:
%.out: %.in 
    @some_tool $< $@ 
Yes, remember these special variables: $< is the first dependency, and $@ is the target (%.out here), so that will generate the correct command-line. Oh, and for the different output flavors (say, by adding some option), just dupe the generic rule:
%_X.out: %.in
 @some_tool $< $@ X
%_Y.out: %.in
 @some_tool $< $@ Y
Finally, you will try to build the main (all) rule. Its dependencies are all the input files (thats easy, its $(infiles) ) and the output files, so that each of them gets produced only in case it is not present. Ah. Here comes some trouble. How do you create a variable holding all the expected targets ? Well, first, lets get the files names without extension. Easy:
filenames :=$(basename $(infiles))

Okay, and now, how do I automatically generate a string holding all the output files names ? This is a job for the foreach() function. Its description in the manual is (IMHO) mostly unreadable, so lets see this through a simpler example:
what = $(foreach a, ham cheese salad, john likes $(a) )
all:
    @echo "what=$(what)"
produces:
what= john likes ham  john likes cheese  john likes salad
Usually, this is used using some variables, and it would be written:
types= ham cheese salad
what = $(foreach a, $(types), john likes $(a) )

Mmmh, I'm sure you're starting to see the point. The 'types' will be our different output flavors, say, something like:
types= X Y
outfile := $(foreach a, $(types), boo_$(a).out )
     @echo "outfile=$(outfile)"
that will produce:
outfile= boo_X.out boo_Y.out
But this has to be done for each input files, and the following fails:
types= X Y
outfiles := $(foreach a, $(types), $(filenames)_$(a).out )
It gets expanded to:
boo foo_X.out boo foo_Y.out

So the solution is to use nested foreach() loops, just as you would do with some regular procedural programming language.
types:=X Y
outfiles := $(foreach a,$(filenames), \
     $(foreach b,$(types), \
         $(a)_$(b).out ) ) 
Then, the main rule can just get written as follows:
all: $(infiles) $(outfiles)
    @echo "That's all, folks !"

For further reading, check this series of articles on advanced topics on Make.

vendredi 17 février 2012

Changing the monitor on which the GNOME panels are placed

In my job, it is quite common these days to have a dual display setup on your laptop. Either your are at the office and have a larger LDC monitor, either your are teaching or doing some presentation and you have a beamer projector connected.

With the GNOME 2 desktop, the UI is based on 2 toolbars (called "panels") on top and bottom of the screen, that are very handy for launching common apps. With two screens, what happens is that these panels are usually placed on one screen, where you would rather have them on the other one.

The desktop provides a graphical way to move them around with the mouse, by holding the "alt" key down, and moving them around. But this is rather difficult in some lighting situations, when the projector image is bad and you hardly see your mouse pointer. Worse, you might end up with a vertical panel, and then, due to the lack of free space in the panel to click on, you're doomed to use either the graphical editor, either the command line tool.

The other solution is to edit this item directly in the gnome registry. Oh, sorry, I know, GNOME has no registry, only Windows has... Although it can look quite similar as viewed from the corresponding graphical editors, the implementation beneath is completely different. While Windows stores all its configuration information in two HUGE files, on Linux the information is spread over many many files, usually under /etc. It's only the way the information is displayed that makes it look like Windows registry (a tree of pairs key/values). And it is called GConf repository instead of registry.

For the desktops panels, the items to consider are stored under the keys /apps/panel/toplevels/ keys, one is called bottom_panel_screen0, the other top_panel_screen0 (at least on my computer, check on yours).

This can be done graphically with the gconf-editor tool, but when you have the audience waiting, it can be complicated finding and clicking on correct items... The best idea is to use the command-line tool provided, and to have somewhere two scripts, one for switching panels to monitor 0, one for switching to monitor 1.

So just copy/paste these lines in two files that you store whereyouwant, and add two symlinks on them on your desktop. Then, once you are in front of the audience and you have trouble with the panels, just reduce all the opened windows and double-click on one of the links. Changes should apply in less than a second.

file switch_panel_0.sh
#! /bin/bash
# switch top/bottom panels to screen 0
gconftool-2 --set "/apps/panel/toplevels/bottom_panel_screen0/monitor" --type int 0
gconftool-2 --set "/apps/panel/toplevels/top_panel_screen0/monitor" --type int 0

file switch_panel_1.sh:
#! /bin/bash
# switch top/bottom panels to screen 1
gconftool-2 --set "/apps/panel/toplevels/bottom_panel_screen0/monitor" --type int 1
gconftool-2 --set "/apps/panel/toplevels/top_panel_screen0/monitor" --type int 1

To create the symlinks (remember to adjust the path to where you put the files), just "cd" to your desktop folder ($HOME/Desktop usually) and type:
>ln -s $HOME/scripts/screen/switch_panel_0.sh panel_0
>ln -s $HOME/scripts/screen/switch_panel_1.sh panel_1

And don't forget to make your files executable! (chmod)

vendredi 2 décembre 2011

SLIFIS: fuzzy logic C++ library first release

I have just uploaded on sourceforge the SLIFIS library, a long-standing project on which I can say I have spend quite some time... It is a C++ library designed to be used inside scientific software when you need some fuzzy logic stuff (membership functions, fuzzy inference system, ...)

It all started in 2008-2009, when I was in that situation, and had trouble finding what would fit my needs. Since then, the software was more or less in a standby situation, but I fixed some stuff recently, and decided to make a public release. A lot of things still need to be worked on, I hope to clean up things a bit and will keep an eye on this.

Checkout the (reduced) doc here, and the download project page is here.

At present, Windows build is not up to date, as Linux is now my main dev platform, but it shouldn't be too hard to make it work.

As usual with open source, absolutely no warranty is given..., blah blah blah.

Feedback is welcome.

mardi 18 octobre 2011

C++: switch on any data type (part 2)

(See part 1 of this post here.)

In this second version, the idea is to have the same function called on triggering, but with a different argument value for each case.

The class will be very similar to first version. The difference is that here, instead of storing the function in the map, we store the argument value. i.e. instead of having
std::map<KEY, FUNC>, we change to  std::map<KEY, ARG>.

Here is the full class. Don't forget to add the needed headers. And as usual with templated classes, this takes place in a header file.


template < typename KEY, typename FUNC, typename ARG > class SWITCH2
{
   public:
      SWITCH2()
      {
          myFunc = 0;
      }

      void Process( const KEY& key )
      {
         assert( myFunc ); // needed !
         typename std::map<KEY,ARG>::const_iterator it = myMap.find( key );
         if( it != myMap.end() )    // If key exists, call function
            myFunc( it->second );  // with correct argument
         else                       // else, call function with
            myFunc( DefArg );      // default argument
      }

      void AddArgument( const KEY key, ARG value )
      {
         myMap[ key ] = value;
      }
      void SetFunction( FUNC f )
      {
         myFunc = f;
      }
      void SetDefault( ARG def )
      {
         DefArg = def;
      }

   private:
      std::map< KEY, ARG > myMap;
      FUNC myFunc; // the function
      ARG  DefArg; // default value, the type needs
                   //   a default constructor
};

I removed here the uniqueness test, as it seemed less relevant in this situation. But you can write it back if needed.
Also note the 'assert()' checking, to make sure we don't call a function that hasn't been defined. You can easily replace this by some custom error handling function instead (exception, or whatever.)


And again, remember that this trick can only be used in specific cases where either you have to call different functions with the same argument, or the same function with different argument values.

Other solutions to this problem can be found (besides switching to another programming language, I mean...), you could also use function pointers, although this is less natural in C++.

mardi 14 juin 2011

C++: switch on any data type (part 1)

C++ is claimed to be a programming langage that allows Object Oriented programming. But for legacy reasons, it does not always allow "real" objet paradigm in certain situations. Yes, I'm talking about the "switch" statement.
As you might know, you can only switch on data types that can be downcasted to an 'int' type.

This comes of course from its proximity with C (that is sometimes considered as some upgrated assembler), and C++ programmers are now used to it. But from a strict Object Oriented paradigm, I believe this shouldn't be true.

But when would such a feature be needed anyway ? I'll show you an example.

Say you need to read data from a file that can be in two different formats. Say xml, csv, whatever. This will typically be done with two different functions. So the first step is identifying file type (by its extension, lets keep it simple), then call the correct function. So you have the following code:

if( ext == "xml" )
   return ReadFile_xml( ...
else
   if( ext == "csv" )
      return ReadFile_csv( ...
   else
      cerr << "Unrecognised file type !\n"; // or whatever other error handling

Okay, so, yes, this does the job. But what if you need to add two other file types and their associated functions ? The code before will start to look really really ugly and will become error prone. It would be much nicer if one could have this instead:
(for clarity, we have removed the handling of the returned value)

switch( ext )
{
   case "csv" : ReadFile_csv( ... ); break;
   case "xml" : ReadFile_xml( ... ); break;
   case "..." : ...
   ...
   default:
      cerr << "Unrecognized file type !\n";
}
return false;

Unfortunatly, as explained before, you can't do this in C++. No, Nada, Niet.

The example here is for strings, but can be transposed to a lot of similar situations. Say, how about some keyboard shortcut combination that you would want to switch on, or whatever.

What we would like is to have a "generic" solution that can be used for any data type. We present here two class-based solutions, one where you can call different functions for different "cases", the second where it is always the same function called, but with different argument values. They rely on template programming, with a provided class that holds all the necessary logic and can be reused elsewhere, just put the class in some header file and use it anywhere.

These solutions both have limitations at present. For the first flavour, the number of arguments is fixed in the templated class. You can of course edit it, but it is not fully generic at present.

Let's see first how the user code will look using the first solution. We show here an example where the argument to be passed to the function has the type string, but the point here is that this solution is independent of both types used (selector, and argument), as long as they meet certain expectations, see below.

// first, instanciate the class SWITCH with needed types
//                key type        function sig      arg type
    SWITCH mySwitch< string,   void(*)(const string&), string >;
// then, configure the "switch" object
    mySwitch.Add( "csv", ReadFile_csv );
    mySwitch.Add( "xml", ReadFile_xml );
    mySwitch.AddDefault( ReadFile_unknown );

// lets try some keyboard test
    string in;
    do
    {
        cout << "in: ";
        cin >> in;
        mySwitch.Process( in, filename ); // do the switch !
    }
    while( in != "0" );

   ...
}
// this function needs to have the following signature
void ReadFile_csv( const string& filename )
{
 ...
}

Now, lets see the class. It is based on an stl map. It is templated by three types, the key type (the "selector"), the function signature, and the functions argument type:

template < typename KEY, typename FUNC, typename ARG > class SWITCH
{
   public:
      SWITCH()
      {
         Def = 0; // no default function at startup
      }

      void Process( const KEY& key, ARG arg )
      {
         typename std::map< KEY, FUNC >::const_iterator it = my_map.find( key );
         if( it != my_map.end() )  // If key exists, call
             it->second( arg );    // associated function
         else               // else, call
            if( Def )       // default function, if there is one.
               Def( arg );  // Else, do nothing
      }

      void Add( const KEY& key, FUNC my_func )
      {
#ifdef CHECK_FOR_UNIQUENESS
         typename std::map< KEY, FUNC >::const_iterator it = my_map.find( key );
         if( it != my_map.end() )
         {
            cerr << "Already defined !\n";
            throw "Already defined !\n";
         }
#endif
         my_map[ key ] = my_func;
      }

      void AddDefault( FUNC f )
      {
          Def = f;
      }

   private:
      std::map< KEY, FUNC > my_map;
      FUNC Def; // default function
};

Some comments:
  • Please note the CHECK_FOR_UNIQUENESS test. If defined, then execution stops if class user attemps to store twice the same key. You can easily write your own error handler.
  • The KEY and the ARG type need to be copyable. This is a limitation. For instance, you could not use a file stream (std::ifstream for example) as these are not copyable. If you use a non-trivial class, make sure its assignement operator is defined.
  • As you may have noticed, the functions argument can be passed using its reference.

Part 2 is coming soon, in the meanwhile, you can check the following references on the same -or similar- subject:

jeudi 3 mars 2011

Two scripts for packaging a source tree from a local repository

I'm currently maintaining a double build of some software projects, on both Windows and Linux. Svn is of course a great help, because it allows me to easily switch from one machine to another and finding my whole tree unchanged (with a network-hosted repository, of course). I could also use some virtual machine, but I happen to have enough machines available: my main laptop recently switched (more on this later!), and I still have Windows at work and at home. So it is kind of easier to work on separate machines, not to mention that virtual machines can have some specific trouble that you need to deal with, instead of focusing on your project.

Part of the job is letting the users try your code, users that don't necessarily have access to the svn repository, nor have/use the same dev tools you do. So the classical way is to upload somewhere the whole tree as a single archive, and let them fool around with the app.

A well-known post from Joel Spolsky (here in french) covers a list of what is required in dev teams to achieve a high quality level. And point n°2 is "Can you make a build in one step?". Besides the build process, this implies an efficient source tree release step, and that's what I'll talk about here. But what exactly does "release" mean ?

"Releasing" means here going from a source tree, with all binaries compiled and unit-tests done, to a single file uploaded somewhere, so users can download it the next morning. We do not cover here producing the more complex "self-installing" files, (linux .deb or .rpm, or windows .msi or .exe), only a regular archive, containing the whole source tree along with the needed binaries.

You can find below the two scripts, one for windows (.bat), and one for Linux (.sh). The Linux version only needs regular tools that should be available on every distribution, while the Windows versions needs 2 additional tools, the archiver and the svn command-line client. Yes, I know what you think: if you are using svn, then you have the command-line svn client ! Well, no, not necessarily. On windows, I use TortoiseSvn,  really nice and with a perfect shell integration. This gui software is not just a wrapper around the svn command-line client, it has its own binaries. So you need to install some other svn client if you're a TortoiseSvn user (they are available here).
For the archiver, I highly recommend 7-zip: has both GUI and CLI, high performance, good documentation, shell integration... and LGPL'ed ! Can't wait to have it on Linux.

The interesting point is that the two scripts here are project-independent: you just drop them in your root folder... and there you go! A simple double-clic will generate an archive (.zip or .tar.gz), containing a copy of the local repository, with the name like:

XXXXX_YYYYMMDD-HHMM_win32.zip for the windows version
XXXXX_YYYYMMDD-HHMM_linux.tar.gz for the linux version
with XXXXX being the project name, simply extracted from the root folder name. You can also run them from the command-line.

The only tweaking you need to do is edit the additional "upload" scripts, where the ftp command is issued: this is the only part that can not be automatic, as there is no way to automatically determine what the host is.

Inside the scripts, nothing really complicated, but I'm quite happy to achieve some bash scripting as well as I am used to do with windows scripting. I miss the 'goto' command, but I must say that bash is more efficient, even though I am more used to cmd.exe. The scripts mainly do an svn export, add the binaries (that shoudn't be versioned), and compress the whole thing, renaming it with the current date/time. Has been tested on XP-SP3 and Ubuntu 10.10, let me know if you experience some trouble.

Download link

Linux/bash version:

#!/bin/bash
echo Packaging linux archive

curpath=$(pwd)
name=$(basename $curpath)
#echo name=$name

now=$(date +%Y%m%d-%H%M)
fn=${name}_${now}_linux

echo "step 1 : export tree to temp path"
svn export . $HOME/tmp/$name

echo "step 2 : add binaries (not versioned)"
cp bin/* /tmp/$name/bin
cp lib/* /tmp/$name/lib

echo "step 3 : archive and compress"
cd /tmp
tar cfz $curpath/$fn.tar.gz $name
cd $curpath

echo "step 4 : cleanup"
rm -r $HOME/tmp/$name

echo "step 5 : upload"
./upload.sh

echo "done, file $fn.tar.gz available !"
read -p "press a key"


Windows version

@echo off
title Packaging windows archive

:: here, little trick to get the folder's name
set curr_path=%cd%
call :sp %curr_path%
::echo name=%name%

set archiver=C:\Program Files\7-Zip\7z.exe
set svnclient=C:\Program Files\Subversion\bin\svn.exe

:: step 0 : make sure all the tools are available
if not exist "%archiver%" goto err1
if not exist "%svnclient%" goto err2

echo step 1 : export tree to temp path
svn export . %temp%\%name% --native-eol CRLF

echo step 2 : add binaries (not versioned)
copy bin %temp%\%name%\bin > nul
copy lib %temp%\%name%\lib > nul

echo step 3 : compress
set year=%date:~6,4%
set month=%date:~3,2%
set day=%date:~0,2%
set hour=%time:~0,2%
if /I %hour% LSS 10 set hour=0%hour:~1,1%
set mn=%time:~3,2%
set now=%year%%month%%day%-%hour%%mn%
echo now=%now%
pause
"%archiver%" a "%name%_%now%_win32.zip" %temp%\%name% > nul

echo step 4 : cleanup
del /Q /S %temp%\%name%\* >nul
rd /S /Q %temp%\%name%

echo step 5 : upload
call upload.bat

echo done, file %name%_%now%_win32.zip available !
pause
goto :eof
============================================================
:err1
echo FAIL: archiver %archiver% not present !
pause
goto :eof
============================================================
:err2
echo FAIL: svnclient %svnclient% not present !
pause
goto :eof
============================================================
:sp
::echo sp, arg1=%1
set name=%~n1
goto :eof
============================================================

vendredi 12 novembre 2010

La fin des processeurs 8 bits ?

Un point de vue intéressant sur l'état du marché des microcontroleurs. Alors que les industriels poussent en avant les 32 bits et que nombre de gens prédisent depuis des lustres la disparition des 8 bits, le marché démontre au contraire que les processeurs 8 bits se portent mieux que jamais. Pour preuve l'excellente santé de Microchip, dont les ventes restent majoritairement centrées sur le 8/16 bits.

www.eetimes.com/discussion/break-points/4210504/8-bits-is-dead

Cet article est issu de embedded.com, site d'actu sur l'embarqué (qui a été racheté récemment par eetimes.com, l'url est maintenant www.eetimes.com/design/embedded). Je recommande vivement l'abonnement à ce site pour tous ceux qui s'intéressent à l'embarqué.

Voir aussi mes liens sur ce thème ici: www.delicious.com/skramm/embedded.

Edit 20120316: Suis tombé sur un autre billet au point de vue
radicalement différent.

vendredi 5 novembre 2010

Demo video

Just posted a short video I made that demontrates some stuff I have worked on during my PhD. It's about building sparse 3d maps using stereo images produced with unaligned cameras. Watch it directly on youtube for a higher image quality.

vendredi 17 septembre 2010

Running Doxygen

Doxygen is a nice tool, but using it comfortably is not very well explained in its documentation as this is supposed to be a tool used by people who have a little idea of what a console is. So the manual briefly says:
To generate the documentation you can now enter:
doxygen <config-file>
This assumes you have a console opened, in the right path. On a modern OS, it is much simpler to add an extension to the doxygen configuration file type (.dox seems of course appropriate, but its your choice), and to associate this extension to the considered program, so that a simple double click on the file will run doxygen, using this file as input.

With Windows, this association can be done easilly by selecting the .dox file, and selecting the "open with..." entry in the contextual menu. You can then navigate up to the doxygen/bin folder, and select doxygen.exe. I'm sure it is as simple on other OSes. However, this has some disadvantages, particularly on Windows. The default console behaviour that gets opened using the method described here gets closed when the program ends. So ?

Well, some times, things can go wrong. Either your code documentation is not correct, either there is a problem with your configuration file. In these cases, Doxygen outputs on standard error stream (stderr) a list of error messages that are very valuable. As the console closes, you lose all these error messages, not to mention that you can even not notice them. Moreover, even if you launch it from a previously opened console, doxygen is quite verbose on standard output (stdout), so important error messages get drowned under the flood of lines on stdout.

Redirecting is the way to go. Manually, sure, but as you probably need this functionnality through out your projects life, it is better to put this in a script. So the first idea is to add to the root of your project a small script file (say, run_doxygen.bat for Windows), that will look like this: (Nix users will adapt this without any problem)

@echo off
title Running Doxygen...

:: erasing previous files
del /Q html\*.*

:: running doxygen on file 'doxyfile.dox'
doxyfile.dox 1>doxygen_stdout.txt 2>doxygen_stderr.txt

:: showing doc (html) in default browser
html\index.html

:: opening error file in default text editor
doxygen_stderr.txt

This way, you log in two separate files the streams stdout and stderr, the latter being automatically opened when done, so the user can check for errors.

However, this method has two disadvantages:
  • First, doxyfile name is hardcoded. For medium to large size projects, we will often have several configuration files, depending of the current documentation needs. Sure, whe could also duplicate the script, but that's not very practical.
  • Second, this has to be done for every project we handle.

So a better idea is to have a unique script file somewhere, (on windows, c:\program files\_script for instance), and to associate the doxyfile type to this script, and not to the doxygen binary!

This only difference with the previous version is that it needs to explicitly call the doxygen binary, and pass it the script argument (%1) (doxygen configuration file).
@echo off
title Running Doxygen...

:: erasing previous files
del /Q html\*.*

:: running doxygen
"c:\program files\doxygen\bin\doxygen.exe" "%1" 1>doxygen_stdout.txt 2>doxygen_stderr.txt

:: showing doc (html) in default browser
html\index.html

:: opening error file in default text editor
doxygen_stderr.txt

Don't forget the quotes around the doxygen binary path !

Edit: this is for "html" doxygen output, but you can adapt it easily for other output types (tex, man, rtf, ...)

Edit-2 (2010-11-12): Actually, you must not put quotes around the %1 argument. Windows automatically adds quotes to the argument when called through the explorer, and this causes problem if the doxyfile is located from a path that has spaces.
(yes, I know, nobody puts spaces in the path of his personal folders...)

jeudi 8 juillet 2010

Aligned stereovision short note

If anybody is interested, I have written a short note on how to select the parameters of an aligned stereovision system (baseline and focal/field of view).

Nothing too complicated, only some basic geometry and some "gnuplotting".
It is hosted on my labs web site, the link is here.

It will probably be updated in some time, 'cause the plots don't look too nice, specifically when printed on a mochrome printer ;-), I'll let you know

jeudi 11 février 2010

Enhancement to the \todo command with doxygen

I use doxygen for my code development, and use a lot the \todo command: it allows me to quickly mention things that need to be done when I don't have time to do it at the moment. This way things don't get buried into my memory.

The problem is that this produces a list that is not sorted in any way: you can't distinguish between things that are important and things that are just some ideas that need to be tried. Just see an example of what an unordered list looks like, in some random project I came across: www.portaudio.com/docs/v19-doxydocs/todo.html.

If your list has 10 or less items, that's not too bad. However, if you manage a large project, you can easily end up with a list with several dozens of items, and this list then becomes useless: the day you happen to have some spare time, you just can't spot what's really important to do... I thought that there was some kind of feature lacking in doxygen, in order to produce some hierarchical "todo" list using different \todo commands (say, \todo1 for top-priority things to do, \todo2 for less important things, and so on).

So I suggested this feature on the doxygen list, to see if other people find it useful, and if it could be added to the wish-list (again, another "todo" list!)

I discovered that this was already possible, by defining an alias in the doxyfile. Thanks to Clemens Feige, he explained to me how to define new commands that do the job, based on the \xrefitem command.

Using this command is not obvious, so I post here the way to do it.

Using a text editor, open your doxyfile and find the ALIAS line, and add the following lines:
ALIASES += "todo1=\xrefitem todo1 \"High Priority Todo\" \"Todo high priority list\""
ALIASES += "todo2=\xrefitem todo2 \"Medium Priority Todo\" \"Todo medium priority list\""
ALIASES += "todo3=\xrefitem todo3 \"Low Priority Todo\" \"Todo low priority list\""





In your code, you can now use either \todo, that will end up in the classical unsorted "todo" page, or \todo1, \todo2, or \todo3. Run your doxyfile, and that's it!


For more about code documentation, you can check the following pages:

mercredi 9 décembre 2009

Transforming column datafiles into line datafiles on Windows




In the field of computer science, you frequently need to visualize data: it always makes things clearer when you show a chart, the reader gets the picture just by looking at it, without having to read the painfull 15-lines paragraph below.

So you have data. Sometimes lots of data. Sometimes badly organised text data files. For instance, where successive values are not on successive lines, but on successive columns. This might not be clear for everybody, so here is an example. Say you have a file containing temperatures measured every hour, for some period of time (a month, for instance). The usual way of doing is one measure per line:

1/1/2009;0;22
1/1/2009;1;23
1/1/2009;2;22.5
2/1/2009;0;24
...
and so on. And sometimes you run across datafiles where the layout is:

1/1/2009;22;23;22.5
2/1/2009;24; ...
...
While regular people won't find anything bad about this (it does indeed save some disk space!), this type of layout is actually unlogical: columns are supposed to be the different fields of data, not successive values. And it makes things more complicated when it comes to plotting...

I ran across this issue when trying to illustrate my previous post on gnuplot with a nice figure. I wanted to have a fancy "real-world data" illustration, so I downloaded electricity daily consumption datafiles from RTE (you can get those here). They provide Excel files per year, with 365 lines, one per day, and the power consumption for every half-hour (48 values per day). And guess what, the layout is just as described here...

So, first, before writing an adequate gnuplot script file, you need to transform columns into lines. And this is what this post is about, for Windows users. It can also be considered as a demo of what you can do with the Windows command-line interpreter.

A quick search shows some interesting material, mostly based on Linux tools (see here for example). And yes, Windows users, you'll need to get some new software, because Windows lacks some basic tools. At present we will only need the 'cut' tool, a binary can be downloaded through the gnuwin32 coreutils package.

What we need to do here is to process each line of the file, cut it into fields, and write a one datum per line output datafile. So, lets go first for the line-by-line processing, using the for command (you have of course already converted the file to .csv format):

for /F "delims=." %%a in (%file%) do call :sp1 "%%a"
Of course, you will have previously put the file name into the 'file' variable with set file=myfile.csv. The "delims" item is there just to get the whole line of data.

Then, we need to produce one output file for every column that contains a data value. This is done with the "numeric" version of the 'for' command:

--------------------------------------------
:sp1
set line=%~1
echo %line% >line.txt
for /L %%b in (1,1,48) do call :sp2 %%b
goto :eof
--------------------------------------------
Finally, cut the same line 48 times, and add each of the columns to the output files (column 1 is the date, column 2 is some non-significant data, the first value is in column 3):

--------------------------------------------
:sp2
set /A col=2+%1
"%app%" -d; -f1,%col% line.txt >> all.dat
goto :eof
--------------------------------------------
with the variable 'app' containing "c:\program files\gnuwin32\bin\cut.exe"

And that's about it, the output file all.dat will now contain one line per data point. The only thing left is to leave a line between each day, so gnuplot can figure out where the day stops, so sp1 is actually more like:

...
for /L %%b in (1,1,48) do call :sp2 %%b
:: gnuplot needs 1 blank lines to separate records
echo. >> all.dat
goto :eof
--------------------------------------------
Finally, we can plot the thing with some classical gnuplot scripting:

------------------------------------------------------
set title "France power consumption on mondays, 2008\n(data source : RTE)"
set xrange [0:47]
set xlabel "day period"
set ylabel "week"
set yrange [0:51]
set zlabel "MW" offset 0,3
set ztics 30000,10000
set datafile separator ";"
set style data lines
set grid
set pm3d
set surface
set hidden3d
fn="all.dat"
set view 42.0,56.0
unset colorbox
splot fn using 2 every 1:7 notitle
pause -1
set terminal png size 640,480
set output "RTE_2008_monday.png"
replot
------------------------------------------------------
Feel free to comment (english or french) if you'd like more details.


mercredi 25 novembre 2009

A warning on behavior of gnuplot with numerical values


My favorite plotting software is gnuplot. Not that I am an expert in plotting software, it was just the first I really invested time into, after getting tired of ugly Excel plots... But I got used to it, and I like the idea of script-based plotting.

However, I must say it can be quite tricky, and I often stumble upon some things difficult to achieve, or to make them work. Yesterday, after stumbling for several hours (!) through a function plot that did not work as expected, I finally found out why, and discovered a strange "feature" of gnuplot(4.3): it does not treat integer values as floating-point values !

While this seems quite obvious in a programming language (C), I don't understand why it is so in gnuplot. As far as I can see, a plotting app should treat all numbers as "real" numbers (understand "floating-point"). But this seems to be an opinion I don't have in common with the designers of gnuplot.

To make it clear, what I mean is that the value 10*k/3 is NOT the same as k/3*10, if you happen to give k=2
(just plot these two expressions, you'll see what I mean)
To have it correct, you have to type k=2.0
If not, then 10*k/3 will be equal to 6, and k/3*10 will be equal to 0, while you expected to be 6.66. Yep, you got it, integer division striked again...

Maybe this feature is useful in some situations, I have no clue. After searching the manual, this is indeed explained in section 13 ("Expressions"), page 15 for 4.2 version manual. Of course, I discovered this after trying several hours to make the damn thing work...

It must be pointed out that in this case, I knew what the plot was supposed to look like. So I was able to track down where the problem was. In most situations, such an error is most likely to stay undetected most of the time, until one day, with one particular case of data, you get a plot full of nonsense...

mercredi 30 septembre 2009

Integrating a LaTeX/Beamer build system under Windows shell



I'm a LaTeX user for a couple of years now, but I only switched to beamer presentation this summer. I always was quite impressed in conferences or other events by the presentations that were made with beamer. At that time, I was happily using MS PowerPoint, but over the time, I felt more and more unsatisfied with mine.
"Beamer guys" presentations looked always cool, the slides were clean, clear and classy. Woah ! I had to switch...

So I recently gave it a try, and I must say at present, I don't think I will ever come back to MS.

I intend to prepare some kind of a tutorial on Beamer, as there's not that much out there specifically on beamer, and I already know some useful tricks. But today I will focus on another point, not directly LaTeX-related, but about a usability trick for building different pdf files, while needing an identical presentation standard for all the documents, and needing each document in different modes. This happened to me when preparing courses. I do a lot of teaching, and I always give a paper handout to the students, so they can focus on what I'm saying, rather than handwriting notes.

With LaTeX, when you are building several documents that must share the same presentation, keeping a consistent header can quickly become tedious. You often need to tweak it, add a package, change a package option, ... If you are working on several documents at once, it's easy (understand: unavoidable) to end up with differents headers in your different documents. And you get slight (or heavy...) aspects changes in the final documents. Moreover, you are likely to forget which header is the correct one.

One way to handle to this is to concentrate on your part of the document, that is, what starts after \begin{document} and ends before \end{document}. All the rest is about formating information, and should be common to all documents.
Just let an automated script do the painful job (adding the header, and calling the compiler). And as I like fooling around with windows shell, I present here an example of what can be done in such a context. For a quick idea, when I'm done editing my file, I just call the right-clic menu on it, and here it goes...

Before:



After:




And I get my ready-to-use pdf file, with the right formatting, and compiled in the right mode:



For now, three different building modes are available:

  • the standard beamer version, with all overlays,

  • a 4 on 1 handout printable version,

  • and a 1 on 1 version, same as the beamer version, but with no overlays, useful for quickly checking page rendering.


And of course, if I need fine-tuning of the LaTeX stuff, I still have the (generated) .tex file in my folder.

If you only want to get the thing working, you can skip the rest, and go directly at the bottom to download. Else, I'll explain how the trick works. Please be adviced that this needs some knowledge about how an OS and a computer works. In my case, it is MS Windows (XP for me, but should be fine on others) and its standard "cmd" script langage, but Linux users should be able to translate in their own shell (at least, experienced Linux users...)

First, your file. As I said, it starts with
\begin{document}
and ends with
\end{document}
You need a title page, on which will be written your name, date, and... the title. So the first lines of the document will look like:
\begin{document}
\title[small title in footer]{Main Title On First Page}
\begin{frame}
\titlepage
\end{frame}
The date is usually set up automatically, and the authors name isn't something that changes every day, so it can be lying in a the header template. These settings can be of course overridden.
\begin{document}
\title[small title in footer]{Main Title On First Page}
\date{2050}
\author{Gill Bates}
\begin{frame}
\titlepage
\end{frame}
Ok, now, how about compiling ? This is done by a simple batch file, that basically concatenates three files: "mode" header, regular LaTeX header, and your document. On Windows, it goes like this (Linux users will tweak this easily):
copy /A "%mp%\head_beamer.tex"+"%mp%\common_header.tex"+"%fn%.texb" "%fn%.tex" > nul
pdfLaTeX.exe --interaction=batchmode "%fn%.tex" 1> LaTeX_log_stdout.txt 2> LaTeX_log_stderr.txt
'mp' is the path where the script and template headers lie, anf 'fn' is the file name. 'head_beamer.tex' is the short header that defines the mode 'beamer', while 'common_header.tex' is where the "real" header stuff goes.

Ok, and how do you choose the right header ? Well, this is really windows specific, as it is about it's registry, and I don't know how you define this with Linux.

To make it short, with Windows, each file extension defines a "type" of file, and each type gets associated with some things you can do with it. This information is stored in the so-called "registry". This can be (badly) handled through the 'assoc' cmd command, or using the 'regedit' GUI. But the best way is to write a .reg file, that will automated this process.

First, we define a new file extension: ".texb"(.tex + B for beamer), in order to avoid changing the default .tex file behaviour you have on your system :
[HKEY_CLASSES_ROOT\.texb]
@="LaTeX.BeamerBody"
And associate this file type (LaTeX.BeamerBody) with the corresponding commands:
[HKEY_CLASSES_ROOT\LaTeX.BeamerBody\shell\build_B]
@="Build (Beamer version)"
[HKEY_CLASSES_ROOT\LaTeX.BeamerBody\shell\build_B\command]
@="\"C:\\program files\\sk_scripts\\BuildWithBeamer\\BuildWithBeamer.bat\" \"%1\" B"
The 'B' letter at the end of the command is an argument that is passed to the script, so it gets the right header. For example, the 'beamer' header will look like this:
\documentclass{beamer}
\usetheme{Madrid}
the 'handout' version like this:
\documentclass[handout]{beamer}
\usetheme{Madrid}% change this to whatever beamer theme you want
and the 'handout 4 on 1' like this:
\documentclass[handout]{beamer}
\usetheme{default}
\selectcolormodel{gray}
\usepackage{pgfpages}
\pgfpagesuselayout{4 on 1}[a4paper,landscape,border shrink=1mm]
\pgfpageslogicalpageoptions{1}{border code=\pgfsetlinewidth{1.5bp}\pgfusepath{stroke}}
\pgfpageslogicalpageoptions{2}{border code=\pgfsetlinewidth{1.5bp}\pgfusepath{stroke}}
\pgfpageslogicalpageoptions{3}{border code=\pgfsetlinewidth{1.5bp}\pgfusepath{stroke}}
\pgfpageslogicalpageoptions{4}{border code=\pgfsetlinewidth{1.5bp}\pgfusepath{stroke}}

% because the 'default' does not add page numbers
\addtobeamertemplate{footline}{\insertframenumber/\inserttotalframenumber}
All this 'pgf' stuff is there to define a solid border around each slide, as the 'default' beamer theme is quite sober (thanks to all the guys on this excellent french-spoken LaTeX mailing list for this trick.)

So what if you want to have this shell menu available on your system ? Well, all this configuration is provided in this zip file: download, unzip, and launch Install.bat. This will copy everything in convenient places, and import settings in registry. You're ready to go, assuming, of course, you have a working LaTeX installed, and available in the path (I use MikTeX).

And of course, an 'uninstall' is provided, to remove the settings from the registry. Once you have this installed, you can check it by going down in the 'demo' folder, and double-clic the file 'demo.texb': it should produce a nice example pdf !

Q & A

Q: what if I don't like the theme you choose ?
Q: what if I want to change colors ?
Q: what if I want to add a package ?
Q: what if I wan't to remove your stupid badly designed logo I get on every page ?
A: All these questions have the same answer: just edit the file c:\program files\sk_scripts\BuildWithBeamer\common_header.tex as you like. This can be conveniently done with the fourth contextual menu item. If you are english native, you will probably have to, as at present, this header is set for french-written documents. Of course, this needs some LaTeX knowledge.

This command calls notepad++, if you use another editor, just change corresponding lines in the file 'install.reg', et re-import it into the registry. And don't forget: with LaTeX, to get the summary correct, you need to compile twice.

If you like this trick, you can tell me about, add a comment, or just drop me a line (firstname DOT lastname AT univ-rouen DOT fr).