#!/usr/bin/env python
"""nanscroll.py
This implements a command-line utility (installed as nanscroll) which will create
a video scrolling through one axis of an image. This is installed by PIP as ``nanscroll``.
The majority of options are the same as :py:mod:`~nanslice.nanslicer`.
"""
import argparse
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.animation import FuncAnimation
from .box import Box
from .slicer import Slicer, Axis_map
from .layer import Layer, blend_layers
from .util import add_common_arguments
[docs]def main(args=None):
"""
The main function for the utility.
Parameters:
- args -- The command line-arguments
"""
parser = argparse.ArgumentParser(
description="Makes a video scrolling through an image")
add_common_arguments(parser)
parser.add_argument('output', help='Output image name', type=str)
parser.add_argument('--slice_axis', type=str, default='z',
help='Axis to slice along (x/y/z)')
parser.add_argument('--slice_lims', type=float, nargs=2, default=(0.01, 0.99),
help='Slice between these limits along the axis, default=0.1 0.9')
parser.add_argument('--figsize', type=float, nargs=2, default=(6, 6),
help='Figure size (width, height) in inches')
parser.add_argument('--dpi', type=int, default=150,
help='DPI for output figure')
parser.add_argument('--fps', type=int, default=8,
help='Framerate for video (default 8)')
args = parser.parse_args()
print('*** Loading files')
print('Loading base image: ', args.base_image)
layers = [Layer(args.base_image, cmap=args.base_map, clim=args.base_lims, mask=args.mask,
interp_order=args.interp_order), ]
if args.overlay:
layers.append(Layer(args.overlay, cmap=args.overlay_map, clim=args.overlay_lims,
mask=args.overlay_mask, mask_threshold=args.overlay_mask_thresh,
alpha=args.alpha, alpha_lims=args.alpha_lims,
interp_order=args.interp_order))
print('*** Setup')
if layers[0].mask_image:
bbox = Box.fromMask(layers[0].mask_image)
else:
bbox = Box.fromImage(layers[0].image)
print(bbox)
args.slice_axis = Axis_map[args.slice_axis]
slices = layers[0].image.shape[args.slice_axis] * \
(args.slice_lims[1] - args.slice_lims[0])
slice_pos = bbox.start[args.slice_axis] + \
bbox.diag[args.slice_axis] * np.linspace(args.slice_lims[0], args.slice_lims[1],
slices)
if args.orient == 'preclin':
origin = 'upper'
else:
origin = 'lower'
gs1 = gridspec.GridSpec(1, 1)
gs1.update(left=0.01, right=0.99, bottom=0.01,
top=0.99, wspace=0.01, hspace=0.01)
fig = plt.figure(facecolor='black', figsize=(6, 6))
print('*** Init Frame')
axes = plt.subplot(gs1[0], facecolor='black')
slicer = Slicer(
bbox, slice_pos[0], args.slice_axis, args.samples, orient=args.orient)
sl_final = blend_layers(layers, slicer)
image = axes.imshow(sl_final, origin=origin,
extent=slicer.extent, interpolation=args.interp)
axes.axis('off')
def update_frame(frame):
"""Draws the next frame"""
print('Slice pos ', slice_pos[frame])
slicer = Slicer(bbox, slice_pos[frame], args.slice_axis,
args.samples, orient=args.orient)
sl_final = blend_layers(layers, slicer)
image.set_data(sl_final)
print('*** Animate Frame')
ani = FuncAnimation(fig, update_frame, frames=len(slice_pos))
print('*** Save')
ani.save(args.output, fps=args.fps, bitrate=2048,
savefig_kwargs={'facecolor': 'black'})
if __name__ == "__main__":
main()