def main():
    '''
    Entry point of script.
    '''
    args = parse_args()

    def get_scales(fg_sizes_path):
        sizes = numpy.loadtxt(fg_sizes_path)
        result = sizes / sizes.max()

        # add a 1.0 for the blank category
        result.resize(result.size + 1)
        result[-1] = 1.0
        return result

    fg_dataset = MemmapDataset(args.fg)
    if args.fg_sizes:
        fg_baseline_scales = get_scales(args.fg_sizes)
    else:
        fg_baseline_scales = None

    fg_renderer = ForegroundRenderer(fg_dataset)

    bg_dataset = MemmapDataset(args.bg)
    bg_renderer = BackgroundRenderer(bg_dataset,
                                     fg_dataset.tensors[0].shape[1:3])

    figure = pylab.figure(figsize=(12, 7))
    figure.canvas.set_window_title(os.path.split(args.fg)[1] +
                                   " and " +
                                   os.path.split(args.bg)[1])

    num_sliders = 9

    text_axes = pylab.subplot(3, 2, 1)
    text_axes.text(-0.5,  # x
                   0.5,  # y
                   "fg image: ",
                   verticalalignment='center',
                   transform=text_axes.transAxes)

    # Hide tick marks
    text_axes.get_xaxis().set_visible(False)
    text_axes.get_yaxis().set_visible(False)

    sliders_axes = [pylab.subplot(num_sliders + 6, 2, 11 + i * 2)
                    for i in range(num_sliders)]


    image_axes = pylab.subplot(1, 2, 2)

    fg_rc_shift = numpy.asarray([0.0, 0.0])
    fg_scale = numpy.asarray(1.0)
    fg_roll = numpy.asarray(0.0)

    bg_frame_number = numpy.asarray(0)
    bg_rc_shift = numpy.asarray([0.0, 0.0])
    bg_scale = numpy.asarray(1.0)
    bg_roll = numpy.asarray(0.0)

    value_arrays = get_value_arrays(fg_dataset.tensors[1])

    # The current indices into value_arrays
    indices = numpy.zeros(4, dtype=int)

    # Which index to edit
    dimension_to_edit = [0]

    max_indices = numpy.asarray([len(value_array) - 1
                                 for value_array
                                 in value_arrays])

    fg_rshift_slider = Slider(sliders_axes[0], 'fg row shift', -50, 50, 0)
    fg_cshift_slider = Slider(sliders_axes[1], 'fg col shift', -50, 50, 0)
    fg_scale_slider = Slider(sliders_axes[2], 'fg scale', 0.5, 1.5, 1.0)
    fg_roll_slider = Slider(sliders_axes[3], 'fg roll', -numpy.pi, numpy.pi, 0)

    bg_frame_slider = Slider(sliders_axes[4],
                             'bg frame',
                             0,
                             bg_dataset.num_examples() - 1,
                             0)
    bg_rshift_slider = Slider(sliders_axes[5], 'bg row shift', -50, 50, 0)
    bg_cshift_slider = Slider(sliders_axes[6], 'bg col shift', -50, 50, 0)
    bg_scale_slider = Slider(sliders_axes[7], 'bg scale', 0.5, 1.5, 1.0)
    bg_roll_slider = Slider(sliders_axes[8], 'bg roll', -numpy.pi, numpy.pi, 0)

    def get_current_values():
        return [value_array[index]
                for value_array, index
                in safe_izip(value_arrays, indices)]

    def draw_indices():
        '''
        Draws the current indices and their corresponding values.
        '''

        values = get_current_values()

        def rad_to_deg(radians):
            return radians / numpy.pi * 180.0

        values[1] = int(rad_to_deg(values[1]))
        values[2] = int(rad_to_deg(values[2]))

        index_names = ['id', 'elev', 'azim', 'light']

        lines = ['{}: {}'.format(index_name, value)
                 for index_name, value
                 in safe_izip(index_names, values)]

        lines[dimension_to_edit[0]] = '==> ' + lines[dimension_to_edit[0]]

        if fg_baseline_scales is not None:
            lines.append('fg baseline scale: {:0.2f}'.format(
                fg_baseline_scales[values[0]]))

        text_axes.clear()

        # "transAxes": 0, 0 = bottom-left, 1, 1 at upper-right.
        text_axes.text(0.1,  # x
                       0.5,  # y
                       '\n'.join(['fg image:', ''] +lines),
                       verticalalignment='center',
                       transform=text_axes.transAxes)


    def draw_image():
        '''
        Draws the image rendered according to <indices>.
        '''
        values = get_current_values()
        values = [numpy.asarray([v]) for v in values]

        fg_baseline_scale = (1.0 if fg_baseline_scales is None
                             else fg_baseline_scales[values[0]])

        fg_images = fg_renderer(fg_ids=values[0],
                                elevations=values[1],
                                azimuths=values[2],
                                lightings=values[3],
                                rc_shifts=fg_rc_shift[numpy.newaxis, :],
                                scales=(fg_scale[numpy.newaxis, ...] *
                                        fg_baseline_scale),
                                rolls=fg_roll[numpy.newaxis, ...])

        bg_images = bg_renderer(bg_frame_number[numpy.newaxis],
                                bg_rc_shift[numpy.newaxis, :],
                                bg_scale[numpy.newaxis],
                                bg_roll[numpy.newaxis])

        composite_images = (fg_images[..., :3] * fg_images[..., 3:] +
                            bg_images[...] * (1.0 - fg_images[..., 3:]))

        image_axes.clear()
        image_axes.imshow(composite_images[0, ...],
                          norm=matplotlib.colors.NoNorm(),
                          aspect='equal')  # match aspect ratio of image

    # Define and connect keyboard callback for choosing fg image, and quitting.

    def on_key_press(event):
        '''
        Key press callback.
        '''

        def increment_dimension_to_edit(increment):
            '''
            Increments or decrements index_dimension[0] by <increment>.
            '''

            assert_in(increment, (-1, 1))
            dimension_to_edit[0] = \
                (dimension_to_edit[0] + increment) % len(indices)

        def increment_index(increment):
            '''
            Increments or decrements inidices[dimension_to_edit[0]]
            '''

            assert_in(increment, (-1, 1))
            max_index = max_indices[dimension_to_edit[0]]
            indices[dimension_to_edit[0]] = \
                (indices[dimension_to_edit[0]] + increment) % (max_index + 1)

        if event.key == 'q':
            sys.exit(0)
        elif event.key == 'up':
            increment_dimension_to_edit(-1)
            draw_indices()
        elif event.key == 'down':
            increment_dimension_to_edit(1)
            draw_indices()
        elif event.key in ('left', 'right'):
            increment_index(-1 if event.key == 'left' else 1)
            draw_indices()
            draw_image()
        else:
            return  # nothing changed, so don't bother drawing

        figure.canvas.draw()

    figure.canvas.mpl_connect('key_press_event', on_key_press)

    # Define and connect fg sliders' callbacks

    def on_fg_r_shift_slider_change(arg):
        fg_rc_shift[0] = arg
        draw_image()

    fg_rshift_slider.on_changed(on_fg_r_shift_slider_change)

    def on_fg_c_shift_slider_change(arg):
        fg_rc_shift[1] = arg
        draw_image()

    fg_cshift_slider.on_changed(on_fg_c_shift_slider_change)

    def on_fg_scale_slider_change(arg):
        fg_scale[...] = arg
        draw_image()

    fg_scale_slider.on_changed(on_fg_scale_slider_change)

    def on_fg_roll_slider_change(arg):
        fg_roll[...] = arg
        draw_image()

    fg_roll_slider.on_changed(on_fg_roll_slider_change)

    # Define and connnect bg sliders' callbacks
    def on_bg_frame_slider_change(arg):
        bg_frame_number[...] = arg
        draw_image()

    bg_frame_slider.on_changed(on_bg_frame_slider_change)

    def on_bg_r_shift_slider_change(arg):
        bg_rc_shift[0] = arg
        draw_image()

    bg_rshift_slider.on_changed(on_bg_r_shift_slider_change)

    def on_bg_c_shift_slider_change(arg):
        bg_rc_shift[1] = arg
        draw_image()

    bg_cshift_slider.on_changed(on_bg_c_shift_slider_change)

    def on_bg_scale_slider_change(arg):
        bg_scale[...] = arg
        draw_image()

    bg_scale_slider.on_changed(on_bg_scale_slider_change)

    def on_bg_roll_slider_change(arg):
        bg_roll[...] = arg
        draw_image()

    bg_roll_slider.on_changed(on_bg_roll_slider_change)

    # Draw initial screen state, start render loop

    draw_indices()
    draw_image()
    pylab.show()
def main():
    '''
    Entry point of script.
    '''

    args = parse_args()

    dataset = MemmapDataset(args.input)
    renderer = BackgroundRenderer(dataset, args.image_shape)

    figure = pylab.figure(figsize=(12, 7))
    figure.canvas.set_window_title(os.path.split(args.input)[1])

    num_sliders = 4
    frame_number_slider_axes = pylab.subplot(1 + num_sliders, 2, 1)
    r_shift_slider_axes = pylab.subplot(1 + num_sliders, 2, 3)
    c_shift_slider_axes = pylab.subplot(1 + num_sliders, 2, 5)
    scale_slider_axes = pylab.subplot(1 + num_sliders, 2, 7)
    roll_slider_axes = pylab.subplot(1 + num_sliders, 2, 9)
    image_axes = pylab.subplot(1, 2, 2)

    frame_number_slider = Slider(frame_number_slider_axes,
                                 'frame number',
                                 0,
                                 dataset.num_examples() - 1,
                                 0)

    assert_equal(dataset.formats[0].axes, ('b', '0', '1', 'c'))

    r_shift_slider = Slider(r_shift_slider_axes,
                            'row shift',
                            -dataset.formats[0].shape[1] / 2,
                            dataset.formats[0].shape[1] / 2,
                            0)

    c_shift_slider = Slider(c_shift_slider_axes,
                            'col shift',
                            -dataset.formats[0].shape[2] / 2,
                            dataset.formats[0].shape[2] / 2,
                            0)

    scale_slider = Slider(scale_slider_axes,
                          'scale',
                          .5,
                          1.5,
                          1.0)

    roll_slider = Slider(roll_slider_axes,
                         'roll',
                         -90,
                         90,
                         0)

    frame_number = numpy.asarray(0)
    rc_shift = numpy.asarray([0, 0])
    scale = numpy.asarray(1.0)
    roll = numpy.asarray(0.0)

    def draw_image():
        '''
        Draws the image rendered according to <indices>.
        '''

        images = renderer(frame_number[numpy.newaxis],
                          rc_shift[numpy.newaxis, :],
                          scale[numpy.newaxis],
                          roll[numpy.newaxis])

        image_axes.clear()
        image_axes.imshow(images[0, ...],
                          norm=matplotlib.colors.NoNorm(),
                          aspect='equal')  # match aspect ratio of image

    def deg_to_rad(arg):
        return arg / 180. * numpy.pi

    def on_frame_number_slider_change(arg):
        frame_number[...] = arg
        draw_image()

    frame_number_slider.on_changed(on_frame_number_slider_change)

    def on_r_shift_slider_change(arg):
        rc_shift[0] = arg
        draw_image()

    r_shift_slider.on_changed(on_r_shift_slider_change)

    def on_c_shift_slider_change(arg):
        rc_shift[1] = arg
        draw_image()

    c_shift_slider.on_changed(on_c_shift_slider_change)

    def on_scale_slider_change(arg):
        scale[...] = arg
        draw_image()

    scale_slider.on_changed(on_scale_slider_change)

    def on_roll_slider_change(arg):
        roll[...] = deg_to_rad(arg)
        draw_image()

    roll_slider.on_changed(on_roll_slider_change)

    def on_key_press(event):
        if event.key == 'q':
            sys.exit(0)

    figure.canvas.mpl_connect('key_press_event', on_key_press)

    draw_image()

    pylab.show()