示例#1
0
def cvd(ifg_path,
        params,
        r_dist,
        calc_alpha=False,
        write_vals=False,
        save_acg=False):
    """
    Calculate the 1D covariance function of an entire interferogram as the
    radial average of its 2D autocorrelation.

    :param str ifg_path: An interferogram file path. OR
    :param Ifg class ifg_path: A pyrate.shared.Ifg class object
    :param dict params: Dictionary of configuration parameters
    :param ndarray r_dist: Array of distance values from the image centre
                (See Rdist class for more details)
    :param bool calc_alpha: If True calculate alpha
    :param bool write_vals: If True write maxvar and alpha values to
                interferogram metadata
    :param bool save_acg: If True write autocorrelation and radial distance
                data to numpy array file on disk

    :return: maxvar: The maximum variance (at zero lag)
    :rtype: float
    :return: alpha: the exponential length-scale of decay factor
    :rtype: float
    """

    if isinstance(ifg_path, str):  # used during MPI
        ifg = shared.Ifg(ifg_path)
        ifg.open()
    else:
        ifg = ifg_path

    shared.nan_and_mm_convert(ifg, params)
    # calculate 2D auto-correlation of image using the
    # spectral method (Wiener-Khinchin theorem)
    if ifg.nan_converted:  # if nancoverted earlier, convert nans back to 0's
        phase = where(isnan(ifg.phase_data), 0, ifg.phase_data)
    else:
        phase = ifg.phase_data

    maxvar, alpha = cvd_from_phase(phase,
                                   ifg,
                                   r_dist,
                                   calc_alpha,
                                   save_acg=save_acg,
                                   params=params)

    if write_vals:
        _add_metadata(ifg, maxvar, alpha)

    if isinstance(ifg_path, str):
        ifg.close()

    return maxvar, alpha
示例#2
0
def pre_prepare_ifgs(ifg_paths, params):
    """
    Open ifg for reading
    """
    ifgs = [Ifg(p) for p in ifg_paths]
    for i in ifgs:
        if not i.is_open:
            i.open(readonly=False)
        nan_and_mm_convert(i, params)
    log.info('Opened ifg for reading')
    return ifgs
示例#3
0
def independent_orbital_correction(ifg, degree, offset, params):
    """
    Calculates and removes an orbital error surface from a single independent
    interferogram.

    Warning: This will write orbital error corrected phase_data to the ifg.

    :param Ifg class instance ifg: the interferogram to be corrected
    :param str degree: model to fit (PLANAR / QUADRATIC / PART_CUBIC)
    :param bool offset: True to calculate the model using an offset
    :param dict params: dictionary of configuration parameters

    :return: None - interferogram phase data is updated and saved to disk
    """
    ifg = shared.Ifg(ifg) if isinstance(ifg, str) else ifg
    if not ifg.is_open:
        ifg.open()
    shared.nan_and_mm_convert(ifg, params)
    # vectorise, keeping NODATA
    vphase = reshape(ifg.phase_data, ifg.num_cells)
    dm = get_design_matrix(ifg, degree, offset)

    # filter NaNs out before getting model
    clean_dm = dm[~isnan(vphase)]
    data = vphase[~isnan(vphase)]
    model = lstsq(clean_dm, data)[0]  # first arg is the model params

    # calculate forward model & morph back to 2D
    if offset:
        fullorb = np.reshape(np.dot(dm[:, :-1], model[:-1]),
                             ifg.phase_data.shape)
    else:
        fullorb = np.reshape(np.dot(dm, model), ifg.phase_data.shape)
    offset_removal = nanmedian(np.ravel(ifg.phase_data - fullorb))
    # subtract orbital error from the ifg
    ifg.phase_data -= (fullorb - offset_removal)
    # set orbfit meta tag and save phase to file
    _save_orbital_error_corrected_phase(ifg)
    if ifg.open():
        ifg.close()
示例#4
0
def independent_correction(ifg, degree, offset, params):
    """
    Calculates and removes orbital correction from an interferogram.
    .. warn:: This will write orbital error corrected phase_data in the interferograms.

    :param ifg: The interferogram to remove remove the orbital error from
    :param degree: PLANAR, QUADRATIC or PART_CUBIC
    :param offset: Boolean
    :param params: Parameter dictionary
    
    :return xxxx
    """
    ifg = shared.Ifg(ifg) if isinstance(ifg, str) else ifg
    if not ifg.is_open:
        ifg.open()
    shared.nan_and_mm_convert(ifg, params)
    # vectorise, keeping NODATA
    vphase = reshape(ifg.phase_data, ifg.num_cells)
    dm = get_design_matrix(ifg, degree, offset)

    # filter NaNs out before getting model
    clean_dm = dm[~isnan(vphase)]
    data = vphase[~isnan(vphase)]
    model = lstsq(clean_dm, data)[0]  # first arg is the model params

    # calculate forward model & morph back to 2D
    if offset:
        fullorb = np.reshape(np.dot(dm[:, :-1], model[:-1]),
                             ifg.phase_data.shape)
    else:
        fullorb = np.reshape(np.dot(dm, model), ifg.phase_data.shape)
    offset_removal = nanmedian(np.ravel(ifg.phase_data - fullorb))
    ifg.phase_data -= (fullorb - offset_removal)
    # set orbfit tags after orbital error correction
    _save_orbital_error_corrected_phase(ifg)
    if ifg.open():
        ifg.close()
示例#5
0
def cvd(ifg_path, params, calc_alpha=False):
    """
    Calculate average covariance versus distance (autocorrelation) and its
    best fitting exponential function.

    :param ifg_path: An interferogram. ifg: :py:class:`pyrate.shared.Ifg`
    :param: params: Dictionary of configuration parameters
    :param calc_alpha: Whether to calculate alpha
    
    :return xxxx
    """
    # pylint: disable=invalid-name
    # pylint: disable=too-many-locals
    if isinstance(ifg_path, str):  # used during MPI
        ifg = shared.Ifg(ifg_path)
        ifg.open()
    else:
        ifg = ifg_path
    # assert isinstance(ifg_path, shared.Ifg)
    # ifg = ifg_path
    shared.nan_and_mm_convert(ifg, params)
    # calculate 2D auto-correlation of image using the
    # spectral method (Wiener-Khinchin theorem)
    if ifg.nan_converted:  # saves heaps of time with no-nan conversion
        phase = where(isnan(ifg.phase_data), 0, ifg.phase_data)
    else:
        phase = ifg.phase_data
    # distance division factor of 1000 converts to km and is needed to match
    # Matlab code output
    distfact = 1000

    nrows, ncols = phase.shape
    fft_phase = fft2(phase)
    pspec = real(fft_phase)**2 + imag(fft_phase)**2
    autocorr_grid = ifft2(pspec)
    nzc = np.sum(np.sum(phase != 0))
    autocorr_grid = fftshift(real(autocorr_grid)) / nzc

    # pixel distances from pixel at zero lag (image centre).
    xx, yy = meshgrid(range(ncols), range(nrows))

    # r_dist is distance from the center
    # doing np.divide and np.sqrt will improve performance as it keeps
    # calculations in the numpy land
    r_dist = np.divide(np.sqrt(((xx-ifg.x_centre) * ifg.x_size)**2 +
                               ((yy-ifg.y_centre) * ifg.y_size)**2), distfact)

    r_dist = reshape(r_dist, ifg.num_cells)
    acg = reshape(autocorr_grid, ifg.num_cells)

    # Symmetry in image; keep only unique points
    # tmp = unique_points(zip(acg, r_dist))
    # Sudipta: Is this faster than keeping only the 1st half as in Matlab?
    # Sudipta: Unlikely, as unique_point is a search/comparison,
    # whereas keeping 1st half is just numpy indexing.
    # If it is not faster, why was this done differently here?

    r_dist = r_dist[:int(ceil(ifg.num_cells/2.0)) + ifg.nrows]
    acg = acg[:len(r_dist)]

    # Alternative method to remove duplicate cells (from Matlab Pirate code)
    # r_dist = r_dist[:ceil(len(r_dist)/2)+nlines]
    #  Reason for '+nlines' term unknown

    # eg. array([x for x in set([(1,1), (2,2), (1,1)])])
    # the above shortens r_dist by some number of cells

    # bin width for collecting data
    bin_width = max(ifg.x_size, ifg.y_size) * 2 / distfact

    # pick the smallest axis to determine circle search radius
    # print 'ifg.X_CENTRE, ifg.Y_CENTRE=', ifg.x_centre, ifg.y_centre
    # print 'ifg.X_SIZE, ifg.Y_SIZE', ifg.x_size, ifg.y_size
    if (ifg.x_centre * ifg.x_size) < (ifg.y_centre * ifg.y_size):
        maxdist = ifg.x_centre * ifg.x_size / distfact
    else:
        maxdist = ifg.y_centre * ifg.y_size/ distfact

    # filter out data where the of lag distance is greater than maxdist
    # r_dist = array([e for e in rorig if e <= maxdist]) #
    # MG: prefers to use all the data
    # acg = array([e for e in rorig if e <= maxdist])
    indices_to_keep = r_dist < maxdist
    r_dist = r_dist[indices_to_keep]
    acg = acg[indices_to_keep]

    if isinstance(ifg_path, str):
        ifg.close()

    if calc_alpha:
        # classify values of r_dist according to bin number
        rbin = ceil(r_dist / bin_width).astype(int)
        maxbin = max(rbin)  # consistent with Matlab code

        cvdav = zeros(shape=(2, maxbin))

        # the following stays in numpy land
        # distance instead of bin number
        cvdav[0, :] = np.multiply(range(maxbin), bin_width)
        # mean variance for the bins
        cvdav[1, :] = [mean(acg[rbin == b]) for b in range(maxbin)]

        # calculate best fit function maxvar*exp(-alpha*r_dist)
        alphaguess = 2 / (maxbin * bin_width)
        alpha = fmin(pendiffexp, x0=alphaguess, args=(cvdav,), disp=0,
                     xtol=1e-6, ftol=1e-6)
        print("1st guess alpha", alphaguess, 'converged alpha:', alpha)
        # maximum variance usually at the zero lag: max(acg[:len(r_dist)])
        return np.max(acg), alpha[0]
    else:
        return np.max(acg), None
示例#6
0
def network_orbital_correction(ifgs,
                               degree,
                               offset,
                               params,
                               m_ifgs=None,
                               preread_ifgs=None):
    """
    This algorithm implements a network inversion to determine orbital
    corrections for a set of interferograms forming a connected network.

    Warning: This will write orbital error corrected phase_data to the ifgs.

    :param list ifgs: List of Ifg class objects reduced to a minimum spanning
        tree network
    :param str degree: model to fit (PLANAR / QUADRATIC / PART_CUBIC)
    :param bool offset: True to calculate the model using offsets
    :param dict params: dictionary of configuration parameters
    :param list m_ifgs: list of multilooked Ifg class objects
        (sequence must be multilooked versions of 'ifgs' arg)
    :param dict preread_ifgs: Dictionary containing information specifically
        for MPI jobs (optional)

    :return: None - interferogram phase data is updated and saved to disk
    """
    # pylint: disable=too-many-locals, too-many-arguments
    src_ifgs = ifgs if m_ifgs is None else m_ifgs
    src_ifgs = mst.mst_from_ifgs(src_ifgs)[3]  # use networkx mst

    vphase = vstack([i.phase_data.reshape((i.num_cells, 1)) for i in src_ifgs])
    vphase = squeeze(vphase)

    B = get_network_design_matrix(src_ifgs, degree, offset)

    # filter NaNs out before getting model
    B = B[~isnan(vphase)]
    orbparams = dot(pinv(B, 1e-6), vphase[~isnan(vphase)])

    ncoef = _get_num_params(degree)
    if preread_ifgs:
        temp_ifgs = OrderedDict(sorted(preread_ifgs.items())).values()
        ids = master_slave_ids(get_all_epochs(temp_ifgs))
    else:
        ids = master_slave_ids(get_all_epochs(ifgs))
    coefs = [
        orbparams[i:i + ncoef] for i in range(0,
                                              len(set(ids)) * ncoef, ncoef)
    ]

    # create full res DM to expand determined coefficients into full res
    # orbital correction (eg. expand coarser model to full size)

    if preread_ifgs:
        temp_ifg = Ifg(ifgs[0])  # ifgs here are paths
        temp_ifg.open()
        dm = get_design_matrix(temp_ifg, degree, offset=False)
        temp_ifg.close()
    else:
        dm = get_design_matrix(ifgs[0], degree, offset=False)

    for i in ifgs:
        # open if not Ifg instance
        if isinstance(i, str):  # pragma: no cover
            # are paths
            i = Ifg(i)
            i.open(readonly=False)
            shared.nan_and_mm_convert(i, params)
        _remove_network_orb_error(coefs, dm, i, ids, offset)
示例#7
0
def network_correction(ifgs,
                       degree,
                       offset,
                       params,
                       m_ifgs=None,
                       preread_ifgs=None):
    """
    Calculates orbital correction model, removing this from the interferograms.
    .. warn:: This will write orbital error corrected phase_data in the interferograms.

    :param ifgs: Interferograms reduced to a minimum tree from prior
        MST calculations
    :param degree: PLANAR, QUADRATIC or PART_CUBIC
    :param offset: True to calculate the model using offsets
    :param params: Parameter dictionary
    :param m_ifgs: Multi-looked orbfit interferograms (sequence must be mlooked
        versions of 'ifgs' arg)
    :param preread_ifgs: Parameters dict corresponding to config file
    
    :return xxxx
    """
    # pylint: disable=too-many-locals, too-many-arguments
    src_ifgs = ifgs if m_ifgs is None else m_ifgs
    src_ifgs = mst.mst_from_ifgs(src_ifgs)[3]  # use networkx mst

    vphase = vstack([i.phase_data.reshape((i.num_cells, 1)) for i in src_ifgs])
    vphase = squeeze(vphase)

    B = get_network_design_matrix(src_ifgs, degree, offset)

    # filter NaNs out before getting model
    B = B[~isnan(vphase)]
    orbparams = dot(pinv(B, 1e-6), vphase[~isnan(vphase)])

    ncoef = _get_num_params(degree)
    if preread_ifgs:
        temp_ifgs = OrderedDict(sorted(preread_ifgs.items())).values()
        ids = master_slave_ids(get_all_epochs(temp_ifgs))
    else:
        ids = master_slave_ids(get_all_epochs(ifgs))
    coefs = [
        orbparams[i:i + ncoef] for i in range(0,
                                              len(set(ids)) * ncoef, ncoef)
    ]

    # create full res DM to expand determined coefficients into full res
    # orbital correction (eg. expand coarser model to full size)

    if preread_ifgs:
        temp_ifg = Ifg(ifgs[0])  # ifgs here are paths
        temp_ifg.open()
        dm = get_design_matrix(temp_ifg, degree, offset=False)
        temp_ifg.close()
    else:
        dm = get_design_matrix(ifgs[0], degree, offset=False)

    # TODO: remove this import from tests suite
    from tests.common import MockIfg
    for i in ifgs:
        # open if not Ifg instance
        if not (isinstance(i, Ifg)
                or isinstance(i, MockIfg)):  # pragma: no cover
            # are paths
            i = Ifg(i)
            i.open(readonly=False)
            shared.nan_and_mm_convert(i, params)
        _remove_networkx_error(coefs, dm, i, ids, offset)