This function implements the  FDMT algorithm.
    Input: Input visibility array (nints, nbl, nchan, npol)
           f_min,f_max are the base-band begin and end frequencies.
                   The frequencies should be entered in MHz 
           maxDT - the maximal delay (in time bins) of the maximal dispersion.
                   Appears in the paper as N_{\Delta}
                   A typical input is maxDT = N_f
           dataType - a valid numpy dtype.
                      reccomended: either int32, or int64.
    Output: The dispersion measure transform of the Input matrix.
            The output dimensions are [Input.shape[1],maxDT]
    
    For details, see algorithm 1 in Zackay & Ofek (2014)

def FDMT(data, f_min, f_max, maxDT, dataType):
    """
    This function implements the  FDMT algorithm.
    Input: Input visibility array (nints, nbl, nchan, npol)
           f_min,f_max are the base-band begin and end frequencies.
                   The frequencies should be entered in MHz 
           maxDT - the maximal delay (in time bins) of the maximal dispersion.
                   Appears in the paper as N_{\Delta}
                   A typical input is maxDT = N_f
           dataType - a valid numpy dtype.
                      reccomended: either int32, or int64.
    Output: The dispersion measure transform of the Input matrix.
            The output dimensions are [Input.shape[1],maxDT]
    
    For details, see algorithm 1 in Zackay & Ofek (2014)
    """

    nint, nbl, nchan, npol = data.shape
    niters = int(np.log2(nchan))

    assert nchan in 2**np.arange(30) and nint in 2**np.arange(30), "Input dimensions must be a power of 2"

    logger.info('Input data dimensions: {0}'.format(data.shape))
    data = FDMT_initialization(data, f_min, f_max, maxDT, dataType)

    logger.info('Iterating {0} times to calculate to maxDT of {1}'.format(niters, maxDT))
    for i_t in range(1, niters+1):
        data = FDMT_iteration(data, maxDT, nchan, f_min, f_max, i_t, dataType)

    [nint, dT, nbl, nchan, npol] = data.shape
    assert nchan == 1, 'Channel axis should have length 1 after all FDMT iterations.'

    # put dT axis first and remove chan axis
    return np.rollaxis(data[:,:,:,0,:], 1)