Zippering two pdfs

Sep 1, 2017 Cmd

If for some reason you have two pdfs with separated odd and even pages of a document, the following command zippers them into a single pdf. (Assuming odd.pdf and even.pdf have the same number of pages; in this case 8.)

qpdf --empty --pages $(for i in $(seq 1 1 8); do echo " odd.pdf $i even.pdf $i "; done) -- all.pdf

Re-encoding subtitles in utf-8

Aug 29, 2017 Cmd

Most Slovak/Czech subtitles are encoded in Plex-incompatible windows-1250 (wiki). The following changes the encoding to utf-8.

iconv -f windows-1250 -t utf-8 >

The Rainbow Fog

Jun 27, 2017 Travel

Cold friday night in #sanfrancisco and an enormous plate of fried shrimp 😋

Príspevok, ktorý zdieľa Tibor Stanko (@bbrrck),

Friday dinner with French/German folks at the #fishermanswharf ⚓ gotta love the fried shrimp

Príspevok, ktorý zdieľa Tibor Stanko (@bbrrck),

Compressing papers with ghostscript

May 5, 2017 Research

When searching for ways to compress the size of a ~50MB paper pdf, I’ve discovered the following ghostscript command (askUbuntu, TeX StackExchange)

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf original.pdf

Argument of -dPDFSETTINGS can be any of:

-dPDFSETTINGS=/screen   # lower quality, smaller size.
-dPDFSETTINGS=/ebook    # for better quality, but slightly larger pdfs.
-dPDFSETTINGS=/prepress # output similar to Acrobat Distiller "Prepress Optimized" setting
-dPDFSETTINGS=/printer  # selects output similar to the Acrobat Distiller "Print Optimized" setting

(descriptions copy-pasted from askUbuntu)

I wrote a small script to test the different -dPDFSETTINGS modes.

declare -a pdfsettings=("screen" "ebook" "prepress" "printer" "default")
args="-sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH"
for mode in "${pdfsettings[@]}"
    # output file
   # compress with ghostscript
   gs $args -dPDFSETTINGS=/$mode -sOutputFile=$ofile $file.pdf
   # print size of the compressed file
   du -h $ofile
# output
912K	compressed/paper.screen.pdf
1.2M	compressed/paper.ebook.pdf
3.4M	compressed/paper.prepress.pdf
2.6M	compressed/paper.printer.pdf
9.9M	compressed/paper.default.pdf

comparison of gs pdf compression modes

3d fabricated lilium

Feb 15, 2017 Research

We got this giant plastic lilium for the tests of our sensor surface reconstruction. Looking forward to the experiments!

(The small device in the middle is the Morphorider.)

Array multiplicities via sparse

Feb 6, 2017 Matlab

Multiplicities of array elements can be efficiently computed using sparse. I’ve found this elegant solution in an old Newsgroup thread.

% generate some data
A = randi(10,1,100);
% construct the sparse matrix
S = sparse(A,1,1);
% get unique elements and multiplicities
[uA,~,mult] = find(S);
mult =
   (1,1)        8
   (2,1)       15
   (3,1)       11
   (4,1)        5
   (5,1)       10
   (6,1)        6
   (7,1)       10
   (8,1)       13
   (9,1)       13
  (10,1)        9

This method is faster than other solutions – almost twice as fast as histc.

% test array: 2000 random integers from the set 1:1000
% 1000 iterations
Elapsed time is 0.228704 seconds. % histc
Elapsed time is 1.838388 seconds. % bsxfun
Elapsed time is 0.128791 seconds. % sparse

Nvidia Optimus

Oct 19, 2016 Fedora

Bumblebee on

Fedora 24 version, closed source solution from managed NVidia repo

dnf -y --nogpgcheck install
dnf install bumblebee-nvidia bbswitch-dkms VirtualGL primus kernel-devel

And test

optirun glxgears

I wanted to test optirun with Matlab, so I ran

optirun /usr/local/MATLAB/R2016a/bin/matlab -desktop

which resulted in a bunch of errors

MATLAB is selecting SOFTWARE OPENGL rendering.
version `CXXABI_1.3.8' not found (required by /usr/lib64/VirtualGL/
version `CXXABI_1.3.9' not found (required by /usr/lib64/VirtualGL/

This is caused by matlab loading an old version of A simple solution is to tell matlab where to look for the correct version of the lib.

LD_PRELOAD=/usr/lib64/ optirun /usr/local/MATLAB/R2016a/bin/matlab -desktop

No errors this time!

» disp(opengl('data'))
                      Version: '4.5.0 NVIDIA 367.44'
                       Vendor: 'NVIDIA Corporation'
                     Renderer: 'Quadro K2000M/PCIe/SSE2'
               MaxTextureSize: 16384
                       Visual: 'Visual 0x20, (RGBA 32 bits (8 8 8 8), Z depth 16 bits, Hardware acceleration, Double buffer, Antialias 8 samples)'
                     Software: 0
         HardwareSupportLevel: 'full'
    SupportsGraphicsSmoothing: 1
SupportsDepthPeelTransparency: 1
   SupportsAlignVertexCenters: 1
                   Extensions: {327x1 cell}
           MaxFrameBufferSize: 16384

Screenshot: matlab quaternion filter

Forgotten tabs

Oct 9, 2016 Music

Once upon a time, I heard a song. This one:

Naturally, I had to tab it. And it remained the only tab I’ve ever published.

Then I kind of forgot about it.

Recently, I was searching for some stuff on UG (Ultimate Guitar, not University of Grenoble…) and wondered what happened to my tab. To my surprise, not only did it have some views, it was also rated as excellent! That felt good.

Strange thing, this tabbing. Are you actually creating something new when tabbing somebody else’s song? To put it another way, are you inventing or discovering?

Anyway, I’ll try to post more of tabs from now on. Of this song, for instance.

And I definitely need to practice more.

Selecting extraordinary vertices in Blender

Jul 28, 2016 Blender
selecting extraordinary vertices in blender

Extraordinary vertices in a polygon mesh are the ones which are not regular – their degree is other than 6 in a triangle mesh and other than 4 in a quad mesh. Here’s how to select all extraordinary mesh vertices in Blender:

  1. Select a regular vertex.
  2. Select->Select Similar->Amount of connecting edges.
    This will select all regular vertices.
  3. Hit Ctrl+I to invert the selection.

Bézier surfaces in Matlab

Feb 1, 2016 Matlab

The following code is my attempt for a fast and compact Matlab implementation of Bézier surfaces using three-dimensional arrays. It runs in less than ones second for the teapot dataset with 32 cubic patches and 10 000 surface points per patch. The computation itself (4064 calls to the casteljau function) takes only ⅓ of a second.

%% compute and display a Bézier surface
samples = 100;
dim     = 3;
% teapot data from
patches = readBPT('teapotrim.bpt',dim);
figure(gcf); clf; hold on; axis equal; axis on; grid on;
for i=1:length(patches),
    % patch degree
    degU = patches(i).deg(1);
    degV = patches(i).deg(2);
    % control net
    Net = reshape(patches(i).verts,degU+1,degV+1,dim);
    % parameter grid
    t = linspace(0,1,samples);
    [U,V] = meshgrid(t,t);
    % compute surface points
    S = casteljau(degU,degV,0,0,U,V,Net,dim);
    % plot
    h = surf(...

function S = casteljau(k,l,i,j,u,v,Net,dim)
% S = casteljau(k,l,i,j,u,v,Net,dim)
%   Compute the point V_{i,j}^{k,l}
%   from the De Casteljau's algorithm
%   for parameter values (u,v).
%   V_{0,0}^{degU,degV} is a surface point.
    if k==0 && l==0,
        S = repmat(Net(i+1,j+1,:),size(u)); % size(u)==size(v)
    elseif k > 0,
        uu = repmat(u,1,1,dim);
        A = casteljau(k-1,l,i  ,j,u,v,Net,dim);
        B = casteljau(k-1,l,i+1,j,u,v,Net,dim);
        S = (1-uu).*A + uu.*B;
        vv = repmat(v,1,1,dim);
        A = casteljau(k,l-1,i,j  ,u,v,Net,dim);
        B = casteljau(k,l-1,i,j+1,u,v,Net,dim);
        S = (1-vv).*A + vv.*B;

function patches = readBPT(filename,dim)
% patches = readBTP( filename, dim )
%   Dirty way to read Bezier patches' control nets
%   stored in the BPT format.
%   e.g.:
    file = fopen(filename);
    pcount = fscanf(file,'%i',1);
    patches = struct('deg',[],'cp',[]);
    for i=1:pcount,
        deg = fscanf(file,'%i',2);
        patches(i).deg = deg;
        vcount = (deg(1)+1)*(deg(2)+1);
        V = fscanf(file,'%f',[dim,vcount]);
        patches(i).verts = V';

Fixing Fujitsu UH572 touchpad on Fedora

Oct 12, 2015 Fedora

…that’s a lot of F-words. Here’s the thing. Open the grub config file:

sudo su
vim /etc/default/grub

Find the line starting with GRUB_CMDLINE_LINUX. Add i8042.notimeout i8042.nomux to the parameters; save and close. Finally, update grub and reboot:

grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
#          NOT -o /boot/grub2/grub.cfg

And now the touchpad works as it should!

After a fresh OS install

Oct 6, 2015 Fedora

In the past few months, I’ve experimented with various Linux distros, before sticking with Fedora-based Korora and Gnome 3 desktop. Korora comes with many pre-installed packages, including vlc, audacity, deluge, gimp, inkscape and git, which is great; still, each time I’m reinstalling my laptop, I spend too much time figuring out which additional applications, packages and libraries I need to install. To facilitate this rather tedious process in the future, I’ve compiled the following list, plus some pointers to useful web resources.

Note: Since Fedora 22, the Dnf is the default package manager, replacing the now-deprecated yum. (Dnf actually stands for Dandified Yum.)

First things first

As always, first step after a fresh install is to update everything.

dnf update

Firefox is the default browser in Korora; I prefer Chrome, which is easy to install.

dnf install google-chrome-stable

Next, I use negativo17’s repos to install Nvidia drivers, Skype and Spotify client.

dnf config-manager --add-repo=
dnf config-manager --add-repo=
dnf config-manager --add-repo=
dnf remove \*nvidia\*
dnf install nvidia-driver
dnf install spotify-client skype

Package groups

Dnf provides many useful package groups; to obtain list of available groups:

dnf group list -v

To get the details of a group:

dnf group info 'Group Name'

To install a group:

dnf group install 'Group Name'

To install the optional packages in the group, add parameter with-optional before the name of the group.

dnf group install with-optional 'Group Name'

Now, let’s look at some specific groups.

dnf group install with-optional 'Development and Creative Workstation'

This is actually a metagroup – a group of groups. Includes C Development Tools and Libraries and X Software Development. Optional groups include Python and PHP.

dnf group install with-optional 'Authoring and Publishing'

Includes texlive, pdftk.

dnf group install with-optional 'Engineering and Scientific'

Includes R, gnuplot, maxima, octave, python-matplotlib, texmaker.


dnf install amarok asymptote blender dropbox emacs filezilla guake meshlab

There’s an unofficial google drive client called Grive overGrive. Licence ($4.99) is required. For installing zotero, I’m using Sebastiaan Mathôt’s zotero_installer.

Setting up Git

git config --global "Tibor Stanko"
git config --global [email protected]
git config --global credential.helper cache
git config --global push.default simple


Some additional libraries, mostly for my scientific activities: GLEW, GLFW, Eigen, CGAL, libigl. (See also the libigl tutorial.)

dnf install glew-devel glfw-devel eigen3-devel CGAL-devel
cd ~/Tibb/cplus
git clone --recursive
git clone --recursive
cd libigl/external
git clone --recursive

Setting up Matlab

After installing Matlab from iso, I like to do some additional setting up. First, create a symlink to matlab executable in /usr/bin/:

ln -s /usr/local/MATLAB/R2014b/bin/matlab /usr/bin/matlab

Second, we need to tell Gnome about Matlab by creating a .desktop entry:

vim /usr/share/applications/matlab.desktop

Add the following to matlab.desktop:

[Desktop Entry]
Type = Application
Encoding = UTF-8
Name = Matlab2014b
Comment = Matlab:The Tool of Technical Computing
Exec = /usr/local/MATLAB/R2014b/bin/matlab -desktop
Icon = matlab
Categories = Development;Matlab;

BitBucket stuff

use this script to clone all repos at once

Additional desktops

Having an alternative desktop installed might be handy, in case Gnome gives you the jolly Oops! Something has gone wrong.

dnf group install xfce-desktop

Gnome tweaks

When everything’s installed, let’s make some final adjustements using the Gnome Tweak Tool.

  • increase font size
  • add startup applications (guake)

And we’re good to go!

The perks of Matlab’s column-major order

Sep 17, 2015 Matlab

When working with Matlab, it’s good to remember the data are stored in the column-major order; otherwise, the following (seemingly harmless) code might cause a lot of trouble.

% both Positions and Normals are n x 3 matrices
file = ""
fid = fopen(file,'w');
% print Positions and Normals to file
fprintf(fid, '%f %f %f \t %f %f %f \n', [Positions Normals] );

So what’s the problem?

In this case, we expect the contents of the output file to have the form

Px1 Py1 Pz1   Nx1 Ny1 Nz1
 ⋮  ⋮  ⋮     ⋮  ⋮  ⋮
Pxn Pyn Pzn   Nxn Nyn Nzn

Instead, we get something completely different and meaningless:

Px1 Px2 Px3   Px4 Px5 Px6
 ⋮  ⋮  ⋮    ⋮   ⋮  ⋮
            …         Nzn

In case you forget, good luck debugging this!