Empty Pipes



Scaled Colormap in Matplotlib

  • 05 Sep 2014
  • |
  • matplotlib
  • python
  • colormap
  • |

I often have to create plots where the color of some element reflects an underlying value. This mapping of color -> value is generally easily accomplished by using colormaps in matplotlib. The standard provided colormaps (such as cm.jet or cm.cool) map values over the interval [0,1]. Often times, however, our data will have a different range and will need to be normalized in order for it to be mapped to the full range of available colors.

The example below illustrates what the color range looks like without the normalization (top two plots) and with the normalization (bottom plot).

import numpy as np
import matplotlib.cm as cm

# create two input value ranges
gradient1 = np.linspace(0, 1, 256)
gradient2 = np.linspace(-1, 1, 256)

# taken from matplotlib's very own colormap_referency.py example
#http://matplotlib.org/examples/color/colormaps_reference.html
fig, axes = plt.subplots(nrows=3, figsize=(5,1))
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99)

# plot the gradients given the colormaps
for g1,g2 in zip(gradient1, gradient2):
    # the first two are plotted without normalization
    # the input values are mapped directly to colors using cm.jet
    axes[0].axvline(g1, color=cm.jet(g1))
    axes[1].axvline(g2, color=cm.jet(g2))
    
    # add a normalizing function to map the input values to the range [0,1]
    # and then use that with ScalarMappable to get the appropriate colors
    norm = mpl.colors.Normalize(vmin=min(gradient2), vmax=max(gradient2))
    axes[2].axvline(g2, color=cm.ScalarMappable(norm=norm, cmap=cm.jet).to_rgba(g2))

# add the labels, also from:
#http://matplotlib.org/examples/color/colormaps_reference.html
for name, ax in zip(["[0,1]", "[-1,1]", "Normalized [-1,1]"], axes):
    pos = list(ax.get_position().bounds)
    x_text = pos[0] - 0.01
    y_text = pos[1] + pos[3]/2.
    fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)
    ax.set_axis_off()

Mapping different value ranges to colors

Notice how the unnormalized [-1,1] input values have a dark blue color over the left half of the second plot. This is because cm.jet(-1) = cm.jet(-.5) = cm.jet(0.) Values outside of cm.jet’s accepted input range of [0,1] all return the same color. By using the Normalize class, the input values are scaled to the [0,1] input range and the output colors span the entire range of the colormap (third plot).


Fast 3D Vector Operations in Cython

  • 26 Feb 2014
  • |
  • python
  • cython
  • vector
  • |

The numpy library provides a plethora of fast functionality using for vectors. The question is, can we improve upon it by using cython and assuming vectors in three-dimensional space. Let’s take the following two functions which are not provided by numpy, but easily implemented. The first simply calculates the magnitude of a vector, while the second calculates the distance between two vectors.

import math as m
import numpy as np

def magnitude(vec):
    '''
    Return the magnitude of a vector (|V|).

    @param vec: The vector in question.
    @return: The magnitude of the vector.
    '''

    return m.sqrt(np.dot(vec, vec))
    
def vec_distance(vec1, vec2):
    v = vec2 - vec1
    return m.sqrt(np.dot(v, v1))

Now let’s take the equivalent implementation in cython. The only major difference from the pure code is the definition of the data types and the handling of each value individually without any loops.

cimport numpy as np

ctypedef np.double_t DTYPE_t
#print dir(np)
#from math import sin, cos, sqrt

from libc.math cimport sin,cos, sqrt, acos, atan2, pow

def vec_distance(np.ndarray[DTYPE_t, ndim=1] vec1, np.ndarray[DTYPE_t, ndim=1] vec2):
    cdef double d0 = vec2[0] - vec1[0]
    cdef double d1 = vec2[1] - vec1[1]
    cdef double d2 = vec2[2] - vec1[2]
    
    return sqrt(d0 * d0 + d1*d1 + d2*d2)
    
def magnitude(np.ndarray[DTYPE_t, ndim=1] vec):
    cdef double x = sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2])

    return x

Finally, the timing:

In [2]: import cytvec as cv

In [3]: a = np.array([1.,2.,3.])

In [4]: %timeit vec_distance(a, a)
1000000 loops, best of 3: 1.44 us per loop

In [5]: %timeit magnitude(a - a)
1000000 loops, best of 3: 1.48 us per loop

In [6]: %timeit cv.vec_distance(a,a)
1000000 loops, best of 3: 554 ns per loop

In [7]: %timeit magnitude(a)
1000000 loops, best of 3: 656 ns per loop

In [8]: %timeit cv.magnitude(a)
1000000 loops, best of 3: 287 ns per loop

Using the cython implementation leads to a nearly three-fold decrease in the running time for the vec_distance function and an almost two-fold decrease in the running time for the magnitude function. The cytvec implementation can simply be copied into a file (let’s say cytvec.pyx) and compiled into a module by following the instructions in the cython tutorial.

python setup.py build_ext --inplace

An already compiled implementation can be found in the forgi package under forgi.threedee.utilities.cytvec.


My Linux and Xfce Customizations

  • 15 Nov 2013
  • |
  • linux
  • xfce
  • |
Xfce Keyboard Shortcuts

Both at home and at work I use some distribution of linux with Xfce as the window manager. Over the years, I’ve added various shortcuts to speed up the things I do often. The most important of them are the keyboard shortcuts for launching applications. These are set by going to Settings -> Keyboard and then opening the Application Shortcuts tab. In there, my three most used programs are assigned the following shortcuts:

Command Shortcut
gnome-terminal <Alt> F1
chromium-browser <Alt> F3
thunar <Alt> F5
Speaker Volume

My speakers are further away than my keyboard. Changing the volume using the knob requires me to lean forward. Too much work. Moving the mouse is also annoying. Thankfully, I can add the following keybindings in Xfce and control the volume from my keyboard and subsequently raise the volume using <Ctrl><Alt> + and lower the volume using <Ctrl><Alt> - . Pretty convenient!

Command Shortcut
amixer set Master 4%- -q <Primary> <Alt> minus
amixer set Master 4%+ -q <Primary> <Alt> plus

Instead of pressing the up-arrow to repeat a command I’ve entered previously, I commonly hit <Ctrl> R to search for a particular command. This is generally really efficient except when I’m searching for something far back in time by repeatedly hitting <Ctrl> R and I end up missing the command I was looking for. Woe is me if there were a lot of commands between my target and the one I’m currently on. Ideally, I would like to just hit <Ctrl> S to go to the next occurance of my search string in my history file. Alas, <Ctrl> S is already bound and needs to be freed before I can use it this way. To do this, I added the following line to my .bashrc file:

stty stop ^X

Now when I search for an old command using <Ctrl> R, I can reverse the search (and search forward) in the command history list by pressing <Ctrl> S.

BASH Aliases

There’s some command-option combinations that I use so often that I’ve assigned them aliases in my .bashrc file. This allows me to substitue a short command for a longer one. Listed below are my most used aliases in order of their importance.

  1. List the files in the directory in reverse-time sorted order:

    alias lt='ls -lhtr'

    This is my most used command, period. I’m almost always most interested in my recently accessed files. This command provides those at the bottom, along with all the information about them.

  2. Shortcut for logging into my work computer:

    alias work-login='ssh user@workcomputer.com'

    My username and computer name don’t change very often at work. Why re-type them every time?

  3. Create and attach to tmux windows:

    alias tattach='tmux attach -t' alias tnew='tmux new -s'

    I’m a big fan of the screen multiplexer tmux. These aliases allow me to quickly create new sessions and attach to old ones.

  4. Get the size of a folder and all its subfolders:

    alias dum='du --max-depth=1 -h'

    Comes in handy for finding out which directories are the biggest from the command line.

  5. Get summary statistics for a list of numbers:

    alias fivestats="awk '{if(min=="'""'"){min=max=\$1}; if(\$1>max) {max=\$1}; if(\$1<min) {min=\$1}; \ total+=\$1; count+=1} END {print total/count, max, min, count}'

    I often want to compare two sets of numbers. This command allows me to get the mean, max, min, and count of the list without creating (or finding) an awk script every time.

Turn off google’s top ten most visited web pages

Get the Chrome Extension New Tab Redirect and set the redirect option for a new tab to “about:blank”.