Archive for the 'Code' Category

mtpath

When working in Matlab, I usually create small projects that rely on different toolboxes. In order not to add all the toolboxes I want to load in the $MATLAB_PATH environment variable, I wrote a couple of functions that help me including what I need when needed.

Example

Let’s imagine we are working on two projects:

  1. Project1 in ~/tmp/project1
  2. Project2 in ~/tmp/project2

Let’s also imagine that Project2 requires alls the functions of Project1.

By using mtpath, we can then write an initialization file for Project1 (~/tmp/project1/project1_init.m):

1
2
3
4
5
6
7
8
9
10
11
12
% Init file for Project1: ~/tmp/project1/project1_init.m
mtpath_include('$CNBI_ROOT/Projects/Classification/Gaussian');
mtpath_include('$CNBI_ROOT/Projects/FeatureSelection/CVA');
mtpath_include('$CNBI_ROOT/Projects/gdfmatlab');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/gkde');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig/t200');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig/t250');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig/t300');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig/t400');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig/t490');
mtpath_include('$CNBI_ROOT/Thirdparty/matlab/biosig/t500');

All the lines above simply add all the toolboxes to the Matlab path. We said that Project2 requires Project1 to work. If Project1 did not need any external toolbox, we could simply do:

>> addpath('~/tmp/project1/');

Since this is not the case, we can use mtpath_include.m to add Project1 to the search path. mtpath_include.m will discover that a file called ~/tmp/project1/project1_init.m exists, and it will execute it, adding all the dependencies of Project1 automatically.

We could use an initialization file for Project2 as well (~/tmp/project2/project2_init.m):

1
2
% Init file for Project2: ~/tmp/project2/project2_init.m
mtpath_include('~/tmp/project1/');

mtpath_init.m can be used to call automatically the *_init.m file in the current directory:

>> cd ~/tmp/project2
>> mtpath_init
[mtpath_include] Adding: /home/mtavella/project1
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Projects/Classification/Gaussian
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Projects/FeatureSelection/CVA
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Projects/gdfmatlab
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/gkde
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig/t200
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig/t250
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig/t300
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig/t400
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig/t490
[mtpath_include] Adding: /tmp/cnbi-root/trunk/Thirdparty/matlab/biosig/t500

This is a simple example of how mtpath could be used to recursively include toolboxes and their dependencies. The mtpath_include.m function can also add subdirectories recursively. Finally, it never adds duplicate folders to the Matlab search path.

Download

mtpath-0.1.0.tar.gz2 – 2010-08-23

Easy tag creator

I often need to distribute some code to people that do not have access to my SVN/GIT repositories. Furthermore, I create daily tags automatically with cron. Here you have the bash script I normally use.

Please check the example below to understand how it works. Since I run this script for a large number of projects, I fork a tar process for each directory provided as argument. Remove the ampersand (&) at the end of line 22 to disable forking. Lines 28 to 42 wait for all the forked processed before exiting.

Last but not least, if the directories provided as argument contain a .git/ or .svn/ subdirectory, the archive name changes accordingly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash
# 2009-01-09  Michele Tavella <tavella.michele@gmail.com>
 
if [ z"$1" == "z" ]; then
	echo "Error: ctk_tag DIRECTORY..."
	exit;
fi
 
PIDS=""
for x in $@; do
	BASENAME=`basename $x`
	TIMESTAMP=`date +%Y%m%d`
	if [ -e $1/.svn ]; then
		REPO="svn"
	elif [ -e $1/.git ]; then
		REPO="git"
	else
		REPO=""
	fi
	ARCHIVE=${BASENAME}_${REPO}${TIMESTAMP}.tar.bz2 
 
	tar cjf $ARCHIVE $x &
	PID=$!
	echo "[ctk_tag] PID=$PID $x--&gt;$ARCHIVE"
	PIDS="$PID $PIDS"
done
 
while true; do
	TPIDS=""
	for x in $PIDS; do
		PIDCHECK=`ps ax | grep $x | grep -v grep`
		if [ -n "$PIDCHECK" ]; then
			TPIDS="$x $TPIDS"
		fi
	done
 
	if [ "z$TPIDS" == "z" ]; then
		exit 0;
	fi
	PIDS=$TPIDS
	sleep 0.10
done

Example

mtavella@miro cnbitk $ ls -sh1
total 16K
4.0K cnbitkapps
4.0K libcnbicore
4.0K libcnbisyncro
4.0K libtransport
mtavella@miro cnbitk $ ctk_tag lib*
[ctk_tag] PID=11996 libcnbicore-->libcnbicore_git20100810.tar.bz2
[ctk_tag] PID=12000 libcnbisyncro-->libcnbisyncro_git20100810.tar.bz2
[ctk_tag] PID=12004 libtransport-->libtransport_git20100810.tar.bz2
mtavella@miro cnbitk $ ctk_tag cnbitkapps/
[ctk_tag] PID=12594 cnbitkapps/-->cnbitkapps_git20100810.tar.bz2
mtavella@miro cnbitk $ ls -sh1
total 10M
4.0K cnbitkapps
180K cnbitkapps_git20100810.tar.bz2
4.0K libcnbicore
8.8M libcnbicore_git20100810.tar.bz2
4.0K libcnbisyncro
 36K libcnbisyncro_git20100810.tar.bz2
4.0K libtransport
936K libtransport_git20100810.tar.bz2

Download

ctk_tag – 2010-08-10

Simple C++ project with Make

Once a while some colleague of mine is in deep need of Makefiles for compiling some C/C++ code. Although I normally suggest to use Autoconf/Automake or CMake, not everybody is interested in learning how to use those tools. Furthermore, sometimes is just more handy to start writing the code immediately, instead of writing/copying/modifying configuration files.

So, since I believe I dedicated several hours of my life in explaining the mysteries of GNU Make, I decided to spend some time and showing how Make can be use to automagically compile all you need with no extra time spent in writing the Makefile itself.

How it works

The main idea is that you might want to code a small library in C/C++ and write a few executables that rely on the library. I will describe how a Makefile can be used to automatically compile the library without any need of adding the files one by one to the Makefile itself. Once you have downloaded and uncompressed the archive, you will see the following file layout:

bintemplate/
|-- both.cpp
|-- chicken.cpp
|-- eagle.cpp
|-- lib/
|-- Makefile
`-- src/
    |-- Bird.cpp
    |-- Bird.hpp
    |-- Chicken.cpp
    |-- Chicken.hpp
    |-- Eagle.cpp
    `-- Eagle.hpp

The src/ directory contains all the files that are needed to compile the library, so both the included ones (.hpp) and the non-included ones (.cpp). The lib/ directory will contain the library once it will be compiled.
The small capitals .cpp files are the executables that will be linked against the library.
In this example, the project contains tree C++ classes (Bird.*pp, Chicken.*pp and Eagle.*pp) and tree executables (both.cpp, chicken.cpp, eagle.cpp).

As explained later on, the Makefile will compile automatically in the library all the src/*.*pp files and will compile and link against the library all the *.cpp in the root folder. This means that, if you want to add a new class or a new include, or a new executable, you simply create the file at his place, and you call make. Let’s now see how it is possible.

Makefile

Let’s now take a look at the Makefile itself, chunk-by-chunk.

1
2
3
4
5
6
7
8
9
10
# 2010-07-27  Michele Tavella <tavella.michele@gmail.com>
 
PROJECT=bintemplate
VERSION=v0.0.1
AUTHOR=Michele Tavella <tavella.michele@gmail.com>
 
CC=g++
CFLAGS=-Wall -O2
LDFLAGS=-lm 
CTAGS=ctags -R --c++-kinds=+p --fields=+iaS --extra=+q

The first few lines define the project name and version, the compiler, the compiler options, some libraries we normally want to link against and the parameters to build the tags.

12
13
14
15
LOCAL_PATH=~/Paths/playback
CONFIG_CFLAGS=-I$(LOCAL_PATH)/include
CONFIG_LDPATH=-L$(LOCAL_PATH)/lib
CONFIG_LDFLAGS= -lpthread -lstdc++ -Wl,--rpath -Wl,$(LOCAL_PATH)/lib/

The second block is a little more tricky. I always install libraries, headers etc. in a local folder (LOCAL_PATH). This allows me to have different directories with different releases of one or a set of libraries (this becomes very handy when you work on several projects at the same time). BTW, if you have some libraries installed in some weird place, modify lines 13-14 accordingly, otherwise simply remove whatever is on the right of the “=” character. Line 15 specifies the LDFLAGS needed to link against the correct libraries, in this case libpthread and libstrc++.

17
18
19
20
21
22
SRC=src
LIB=lib
LIB_INC=$(wildcard $(SRC)/*.hpp)
LIB_SRC=$(wildcard $(SRC)/*.cpp)
BIN_SRC=$(wildcard *.cpp)
TARGET_LIB=$(LIB)/$(PROJECT).a

Lines 17-18 define the location of the src/ and the lib/ directories, while lines 19-21 use the Make wildcard command to generate a list of the files required to build the library (src/*.*pp) and the files required to build the executables (*.cpp), as it was discusses in the previous section.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.PHONY: library libraryo binaries binarieso
 
default: library binaries
 
binaries: binarieso $(BIN_SRC:.cpp=)
 
binarieso: $(BIN_SRC:.cpp=.o)
 
library: libraryo
	ar r $(TARGET_LIB) $(LIB_SRC:.cpp=.o)
 
libraryo: $(LIB_SRC:.cpp=.o)
 
%.o : %.cpp
	$(CC) -c $(CFLAGS) $(CONFIG_CFLAGS) -I$(SRC) \
            $(CONFIG_LDPATH) $< -o $@ $(CONFIG_LDFLAGS) $(LDFLAGS) 
 
.o:
	$(CC) $(CONFIG_CFLAGS) $(CONFIG_LDPATH) \
            $*.o -o $* $(TARGET_LIB) $(LDFLAGS) $(CONFIG_LDFLAGS)

To understand this chunk, you need to know a little about Make. The main idea is that we define the targets (phony or not) and the rules needed to first compile the library and then to compile the binaries.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
.PHONY: tags install clean info edit
 
clean:
	@echo "[Makefile] Cleaning..."
	@rm -fv $(TARGET_LIB)
	@rm -fv $(BIN_SRC:.cpp=)
	@rm -fv $(BIN_SRC:.cpp=.o)
	@rm -fv $(LIB_SRC:.cpp=.o)
	@rm -fv core*
	@rm -fv vgcore*
	@rm -fv tags
 
install:
	@echo "[Makefile] Running installation"
	@cp -v $(BIN_SRC:.cpp=) $(LOCAL_PATH)/bin
 
tags:
	@echo "[Makefile] Building tags"
	@$(CTAGS) $(LOCAL_PATH)/include/ $(SRC)/ .
 
info:
	@echo "[Makefile] Info:"
	@echo "  Project:   $(PROJECT)"
	@echo "  Version:   $(VERSION)" 
	@echo "  Author:    $(AUTHOR)"
	@echo "  Lib:       $(TARGET_LIB)"
	@echo "  Bin:       $(TARGET_BIN)"
	@echo "  Src:       $(LIB_SRC)"
	@echo "  Inc:       $(LIB_INC)"
 
edit:
	@echo "[Makefile] Editing:"
	@gvim -geom 175x60 -O2 $(LIB_INC) $(LIB_SRC) $(BIN_SRC)

Lines 45-73 define all the phony targets (command, in Make jargon) that I use to make my life easier.

Example

Once you extracted the archive, you can run

make

to compile the libraries and the executables, or similarly you can run:

make clean

to remove all the .o and .a files. Assuming you have GVim and exuberant-ctags installed, you can try to play around with all the other phony targets I briefly discussed above.

Download

bintemplate.tar.bz2 – 2010-07-27

To-do

1. Make phony rules not-phony
2. Improve overall, many important details are missing

On dogs and employees

Back in the days I had a serious problem as a dog owner. The problem was related to the fact that when I was not in my flat, Tito kept jumping and sleeping on the couch. This sucks in several ways. Saliva and hair are usually transferred to your clothes and removing them is incredibly painful. Furthermore, during daytime Tito has to stay home by himself. Tito knew that the couch was forbidden, but guess what happened when I was not home…

By the way, at that time I wrote a dummy Python/OpenCV script to detect brown moving objects (read: dogs) moving on a brighter background (read: the couch). In case of detection, a sound with my voice was played. I have to admit that the thing was working generally well, specially because in a couple of days Tito became really afraid of the couch. I guess the whole trick was done by the dog earing my voice without seeing (smelling?) me.

By the way, this is an example of the detection:

A couple of days ago I was asked by one of my usual contractors if it was possible to use a webcam to detect whether a person is in front of the computer. The whole idea is have a page in the intranet that tells everybody if you are in your office or not. Although I believe that this kind of stuff is generally evil, I started reading this Face Detection using OpenCV howto. It looks like everything is more or less there, so it’s an easy job that can be carried on with the rest.

I will suggest to my contractor to play a track with the voice of the CEO as soon as the employee leaves his computer.

Resize extension for Epiphany

Epiphany is the web browser for the GNOME desktop. The Resize extension is a quick hack to keep Epiphany’s windows at constant size and position. It works perfectly with Epiphany 2.20.1. Few key/values pairs are saved using GConf2 (/apps/epiphany/extensions/resize).

The Resize extension allows you to resize the Epiphany windows to pre-defined sizes and to custom size and position. The user can simply resize the window and place it somewhere on his screen. Then, by pressing the “Save size and position” entry in the Tools menu, the Resize extension will save the user’s settings. Furthermore, the user is able to choose how the Resize extension should behave: check the Resize new windows, Resize new tabs and Resize pop-ups options.

Download
Resize v0.5 – 2008-11-10

Install
Let’s assume you are running Debian/Ubuntu and Epiphany 2.20.*. Uncompress the resize_*.tar.gz archive and run:

sudo apt-get install epiphany-extensions
cp resize.* ~/.gnome2/epiphany/extensions/

Wait for process to terminate

One of my not-so-geek friends that practice couch-surfing in my living room was impressed with my ability to shut down my workstation after watching a movie. Here you have the recipe.

#!/bin/bash
if [ $1 = "" ]; then
 echo "Usage: $0 PROCESS_NAME"
 exit
fi
while pidof $1; do sleep 1; done

Assuming the script is called foo.sh:

$ ./foo.sh mplayer && shutdown