def halton_cost_func_t(N, vol1, vol2, t, arg, mask=False):
    '''
    N: Number of Halton Sampling Points
    vol1: original image
    vol2: volume to be rotated
    theta: rotation by degrees
    t: list of translations to try
    arg: string for plot titles
    '''
    cost_func = np.zeros(len(t))
    t0 = time.time()
    # generate Halton Sequence in the 32*32*32 grid
    sequencer = ghalton.GeneralizedHalton(ghalton.EA_PERMS[:3])
    sequencer.reset()
    points = sequencer.get(N)
    pts = np.array(points)
    x1 = 31 * pts[:,0]
    y1 = 31 * pts[:,1]
    z1 = 31 * pts[:,2]
    #x1, y1, z1 = np.meshgrid(x1, y1, z1)
    for idx, th in enumerate(t):
        v2 = translation(vol2, x1+th[0], y1+th[1], z1+th[2])
        v1 = translation(vol1, x1, y1, z1)
        #new_vol2 = translation(v2, th)
        cost_func[idx] = cf_ssd(v2,v1)
    t1 = time.time()
    print 'Time for %s halton samples is %s seconds' % (N,t1-t0) 
    return cost_func
def bessel_cost_func(vol1_org, vol2_org, thetas, axis, mask=False, smooth = False, mode = 1):
    '''
    vol1: original image
    vol2: volume to be rotated
    thetas: list of degress to try
    cf: cost function
    arg: string for plot titles
    '''
    vol1 = vol1_org.copy()
    vol2 = vol2_org.copy()
    cost_func = np.zeros([len(thetas),])
    if(mask):
        for i in xrange(len(vol1)):
            if(axis == 0):
                vol1[i,:,:] = circle_mask(vol1[i,:,:], smooth, mode)
            elif(axis == 1):
                vol1[:,i,:] = circle_mask(vol1[:,i,:], smooth, mode)
            else:
                vol1[:,:,i] = circle_mask(vol1[:,:,i], smooth, mode)

    for idx, t in enumerate(thetas):
        print t,
        new_vol2 = np.zeros(vol2.shape)
        for i in xrange(len(vol2)):
            if(axis == 0):
                new_vol2[i,:,:] = bessel_rotate(vol2[i,:,:], t, mask, smooth, mode)
            elif(axis == 1):
                new_vol2[:,i,:] = bessel_rotate(vol2[:,i,:], t, mask, smooth, mode)
            else:
                new_vol2[:,:,i] = bessel_rotate(vol2[:,:,i], t, mask, smooth, mode)
        cost_func[idx] = cf_ssd(new_vol2, vol1)
    return cost_func
def rot_cost_func_3d(vol1, vol2, thetas, mask=False):
    '''
    vol1: original image
    vol2: volume to be rotated
    thetas: list of degress to try
    arg: string for plot titles
    '''
    cost_func = np.zeros([len(thetas),3])

    for idx, t in enumerate(thetas):
        new_vol2 = volrotate(vol2, t[0],t[1],t[2], mask)
        cost_func[idx,0] = cf_ssd(new_vol2,vol1)
        cost_func[idx,1] = cf_L1(new_vol2,vol1)
        cost_func[idx,2] = cf_L2(new_vol2,vol1)
    return cost_func
def rot_halton_cost_func(vol1_org, vol2_org, N, thetas, axis, interpolation='bilinear', smooth = True, mode = 1):
    '''
    vol1: original image
    vol2: volume to be rotated
    thetas: list of degress to try
    cf: cost function
    arg: string for plot titles
    '''
    vol1 = vol1_org.copy()
    vol2 = vol2_org.copy()

    cost_func = np.zeros([len(thetas),])
    # generate Halton sample points
    s = (len(vol1)-1)/2.
    sequencer = ghalton.GeneralizedHalton(ghalton.EA_PERMS[:3])
    sequencer.reset()
    points = sequencer.get(N)
    pts = np.array(points)
    xx1 = (len(vol1)-1) * pts[:,0] - s
    yy1 = (len(vol1)-1) * pts[:,1] - s
    mask = np.sqrt(xx1**2+yy1**2) < s*0.7
    x1 = xx1[mask]
    y1 = yy1[mask]
    new_vol1 = np.zeros([len(vol1),len(x1)])
    print len(x1),
    for i in xrange(len(vol1)):
        if(axis == 0):
            sub1 = circle_mask(vol1[i,:,:], smooth = True, mode = 1)
        elif(axis == 1):
            sub1 = circle_mask(vol1[:,i,:], smooth = True, mode = 1)
        else:
            sub1 = circle_mask(vol1[:,:,i], smooth = True, mode = 1)
        rot = imrotate(sub1, 0, interpolation, True, smooth, mode, x1, y1)
        new_vol1[i] = rot
    for idx, t in enumerate(thetas):
        new_vol2 = np.empty([len(vol2),len(x1)])
        for i in xrange(len(vol2)):
            if(axis==0):
                sub2 = circle_mask(vol2[i,:,:], smooth = True, mode = 1)
            elif(axis==1):
                sub2 = circle_mask(vol2[:,i,:], smooth = True, mode = 1)
            else:
                sub2 = circle_mask(vol2[:,:,i], smooth = True, mode = 1)
            rot = imrotate(sub2, t, interpolation, True, smooth, mode, x1, y1)
            new_vol2[i] = rot
        cost_func[idx] = cf_ssd(new_vol2,new_vol1)
    return cost_func
def bessel_halton_cost_func(vol1_org, vol2, N, thetas, axis):
    '''
    vol1: original image
    vol2: volume to be rotated
    thetas: list of degress to try
    cf: cost function
    arg: string for plot titles
    '''
    vol1 = vol1_org.copy()
    # initialize vector to store cost
    cost_func = np.zeros([len(thetas),])
    # generate Halton sample points
    s = (len(vol1)-1)/2.
    sequencer = ghalton.GeneralizedHalton(ghalton.EA_PERMS[:3])
    sequencer.reset()
    points = sequencer.get(N)
    pts = np.array(points)
    x1 = (len(vol1)-1) * pts[:,0] - s
    y1 = (len(vol1)-1) * pts[:,1] - s
    new_vol1 = np.empty([len(vol1),N])
    for i in xrange(len(vol1)):
        if(axis == 0):
            sub1 = circle_mask(vol1[i,:,:])
        elif(axis == 1):
            sub1 = circle_mask(vol1[:,i,:])
        else:
            sub1 = circle_mask(vol1[:,:,i])
        rot = bessel_rotate_halton(sub1, 0, x1, y1)
        new_vol1[i] = rot
    for idx, t in enumerate(thetas):
        print t, 
        new_vol2 = np.empty([len(vol2),N])
        for i in xrange(len(vol2)):
            if(axis==0):
                sub2 = circle_mask(vol2[i,:,:])
            elif(axis==1):
                sub2 = circle_mask(vol2[:,i,:])
            else:
                sub2 = circle_mask(vol2[:,:,i])
            new_vol2[i] = bessel_rotate_halton(sub2, t, x1, y1)
        cost_func[idx] = cf_ssd(new_vol2,new_vol1)
    return cost_func
def vol_cost_func_t(vol1, vol2, t):
    '''
    vol1: original image
    vol2: volume to be rotated
    thetas: list of degress to try
    t: list of translation to try
    cf: cost function
    arg: string for plot titles
    '''
    x = np.linspace(0, vol1.shape[1]-1, vol1.shape[1]).astype(int)
    y = np.linspace(0, vol1.shape[0]-1, vol1.shape[0]).astype(int)
    z = np.linspace(0, vol1.shape[2]-1, vol1.shape[2]).astype(int)
    xx, yy, zz = np.meshgrid(x, y, z)
    
    cost_func = np.zeros(len(t))
    for idx, th in enumerate(t):
        new_vol2 = translation(vol2, xx-th[1], yy-th[0], zz-th[2])
        #new_vol2 = translation1(vol2, th)
        cost_func[idx] = cf_ssd(new_vol2,vol1)
    return cost_func
def rot_cost_func(vol1_org, vol2_org, thetas, axis, interpolation='bilinear', mask=False, smooth=False, mode=1, x=None, y=None):
    '''
    vol1: original image
    vol2: volume to be rotated
    thetas: list of degress to try
    arg: string for plot titles
    '''
    vol1 = vol1_org.copy()
    vol2 = vol2_org.copy()
    if(mask):
        for i in xrange(len(vol1)):
            if(axis == 0):
                vol1[i,:,:] = circle_mask(vol1[i,:,:], smooth, mode)
            elif(axis == 1):
                vol1[:,i,:] = circle_mask(vol1[:,i,:], smooth, mode)
            else:
                vol1[:,:,i] = circle_mask(vol1[:,:,i], smooth, mode)

    cost_func = np.zeros([len(thetas),])
    for idx, t in enumerate(thetas):
        new_vol2 = np.ones(vol2.shape)
        for i in xrange(len(vol2)):
            if(axis == 0):
                sub = vol2[i,:,:]
            elif(axis == 1):
                sub = vol2[:,i,:]
            else:
                sub = vol2[:,:,i]
            
            rot = imrotate(sub, t, interpolation, mask, smooth, mode, x, y)

            if(axis == 0):
                new_vol2[i,:,:] = rot
            elif(axis == 1):
                new_vol2[:,i,:] = rot
            else:
                new_vol2[:,:,i] = rot
        cost_func[idx] = cf_ssd(new_vol2,vol1)
    return cost_func