NF: add fileslice implementation draft

Function to calculate slice out of array stored in file-like object.
NF: trying to work out memory / time tradeoffs

A first pass at thinking out timings.  The next step is to try some
actual timings to see whether this is worth the trouble, compared to
some rule-of-thumb default thresholds.
BF: correct fileslice test logic

Using the wrong names (n_dim, not meaning number of dimensions) and
failed to notice that only 3 of the four dimensions being tested.
NF: add benchmarks for file slicing

Benchmarks for some variations of slicing an array inside a file.
RF: change fancy skip algorithm to hard threshold

Benchmarking showed that the fancy algorithm was doing a bad job, and
that a 2K skip threshold seemed to be reasonable.
NF: script to study seek / read tradeoffs

Script to get times for seek / read compared to full read for different
gaps and sizes.
RF: move printable_table into main nibabel code

Add tests
Refactor benchmarks
WIP: working out algorithm some more
RF+TST+BF: refactor _analyze_slice and heuristic

Fix some bugs in the heuristic and extend tests.

Add special rule for last (slowest changing) dimension to save memory
(probably only relevant for very small images)
TST: add half-step slice for benchmarking

Revealing a bottleneck
RF: refactor _read_segments to use mmap

Using ctypes string was proving to be horribly slow even compared to
using numpy arrays wrapping the read bytes.  mmap was the fastest.
Maybe it is compatible with windows.

Drop memory threshold for skip by following results of
``bench_fileslice``
RF: remove commented print statement
RF: remove redundant return arg from _analyze_slice

_analyze_slice was returning a label saying whether the returned
read_slice was 'full', 'contiguous' or None; it's easy to work this out
from the returned slice.  Refactor to do this.
RF: remove goofy comments from fileslice

Comments from way back when fileslice was just a gleam in my eye.
RF: refactor _get_segments to 2 smaller functions

Make _get_segments a little easier to test and think about by
refactoring into to two functions.  Add tests for the new functions.

Results of::

    nosetests -s --match '(?:^|[\\b_\\.//-])[Bb]ench' /path/to/bench_fileslice.py

on my 1.8 GHz 2GB 2008 MacBook air with standard hard drive.

=============================================================================
Bytes slice - raw (ratio)
=============================================================================
                |   mid int    |    step 1    | half step 1  | step mid int |
-----------------------------------------------------------------------------
axis 0, len 64  |  0.18 (1.01) |  0.19 (1.02) |  0.18 (1.01) |  0.18 (1.01) |
axis 1, len 64  |  0.04 (0.21) |  0.18 (1.00) |  0.14 (0.76) |  0.08 (0.41) |
axis 2, len 32  |  0.01 (0.04) |  0.18 (1.00) |  0.09 (0.50) |  0.01 (0.08) |
axis 3, len 100 |  0.00 (0.01) |  0.18 (1.00) |  0.09 (0.51) |  0.01 (0.03) |
-----------------------------------------------------------------------------
Base time: 0.18

=============================================================================
File slice - raw (ratio)
=============================================================================
                |   mid int    |    step 1    | half step 1  | step mid int |
-----------------------------------------------------------------------------
axis 0, len 64  |  0.18 (1.02) |  0.18 (0.99) |  0.18 (0.99) |  0.18 (0.99) |
axis 1, len 64  |  0.13 (0.72) |  0.18 (0.98) |  0.23 (1.27) |  0.26 (1.42) |
axis 2, len 32  |  0.01 (0.06) |  0.18 (0.98) |  0.11 (0.60) |  0.02 (0.11) |
axis 3, len 100 |  0.00 (0.01) |  0.18 (0.98) |  0.09 (0.50) |  0.01 (0.03) |
-----------------------------------------------------------------------------
Base time: 0.18

=============================================================================
gz slice - raw (ratio)
=============================================================================
                |   mid int    |    step 1    | half step 1  | step mid int |
-----------------------------------------------------------------------------
axis 0, len 64  |  4.24 (0.90) |  4.26 (0.91) |  4.38 (0.93) |  4.31 (0.92) |
axis 1, len 64  |  5.29 (1.13) |  4.38 (0.93) |  4.83 (1.03) |  5.59 (1.19) |
axis 2, len 32  |  5.44 (1.16) |  4.45 (0.95) |  5.57 (1.19) |  5.73 (1.22) |
axis 3, len 100 |  2.80 (0.60) |  4.65 (0.99) |  2.43 (0.52) |  2.86 (0.61) |
-----------------------------------------------------------------------------
Base time: 4.69
ok

----------------------------------------------------------------------
Ran 1 test in 93.879s