an ascent through different scales called "octaves"

def deepdream(
    net,
    base_image,
    iter_n       = 10,
    octave_n     = 4,
    octave_scale = 1.4, 
    end          = "inception_4c/output",
    clip         = True,
    **step_params
    ):
    '''
    an ascent through different scales called "octaves"
    '''    
    # Prepare base images for all octaves.
    octaves = [preprocess(net, base_image)]
    for i in xrange(octave_n-1):
        octaves.append(
            nd.zoom(
                octaves[-1], (1, 1.0 / octave_scale, 1.0 / octave_scale),
                order = 1
            )
        )

    src = net.blobs["data"]
    # Allocate image for network-produced details.
    detail = np.zeros_like(octaves[-1])
    for octave, octave_base in enumerate(octaves[::-1]):
        h, w = octave_base.shape[-2:]
        if octave > 0:
            # Upscale details from the previous octave.
            h1, w1 = detail.shape[-2:]
            detail = nd.zoom(
                detail,
                (1, 1.0 * h / h1, 1.0 * w/w1),
                order = 1
            )
        # Resize the network input image size.
        src.reshape(1, 3, h, w)
        src.data[0] = octave_base+detail
        for i in xrange(iter_n):
            make_step(net, end = end, clip = clip, **step_params)
            
            # visualisation
            vis = deprocess(net, src.data[0])
            # If clipping is disabled, adjust image contrast.
            if not clip:
                vis = vis*(255.0 / np.percentile(vis, 99.98))

            log.info("octave: {octave}, index: {index}, blob/layer: {end}, dimensions: {shape}".format(
                octave = octave,
                index  = i,
                end    = end,
                shape  = vis.shape,
            ))
            
        # Extract details produced on the current octave.
        detail = src.data[0] - octave_base
    # Return the resulting image.
    return deprocess(net, src.data[0])