def test_assert_two_trees_non_overlapping(self): non_overlapping = [2, 5, 6, 12, 13, 15] ifgs_non_overlapping = [ifg for i, ifg in enumerate(self.ifgs) if i+1 in non_overlapping] edges, is_tree, ntrees, _ = mst.mst_from_ifgs(ifgs_non_overlapping) self.assertFalse(is_tree) self.assertEqual(2, ntrees)
def test_assert_two_trees_overlapping(self): overlapping = [3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17] ifgs_overlapping = [ifg for i, ifg in enumerate(self.ifgs) if (i+1 in overlapping)] edges, is_tree, ntrees, _ = mst.mst_from_ifgs(ifgs_overlapping) self.assertFalse(is_tree) self.assertEqual(2, ntrees)
def _time_series_setup(ifgs, mst, params): """ Convenience function for setting up time series computation parameters """ if len(ifgs) < 1: msg = 'Time series requires 2+ interferograms' raise TimeSeriesError(msg) # if mst is not a single tree then do interpolation interp = 0 if mst_module.mst_from_ifgs(ifgs)[1] else 1 # Parallel Processing parameters parallel = params[cf.PARALLEL] # Time Series parameters tsmethod = params[cf.TIME_SERIES_METHOD] pthresh, smfactor, smorder = _validate_params(params, tsmethod) epochlist = get_epochs(ifgs)[0] nrows = ifgs[0].nrows ncols = ifgs[0].ncols nifgs = len(ifgs) span = diff(epochlist.spans) nepoch = len(epochlist.dates) # epoch number nvelpar = nepoch - 1 # velocity parameters number # nlap = nvelpar - smorder # Laplacian observations number mast_slave_ids = master_slave_ids(epochlist.dates) imaster = [mast_slave_ids[ifg.master] for ifg in ifgs] islave = [mast_slave_ids[ifg.slave] for ifg in ifgs] imaster = min(imaster, islave) islave = max(imaster, islave) b0_mat = zeros((nifgs, nvelpar)) for i in range(nifgs): b0_mat[i, imaster[i]:islave[i]] = span[imaster[i]:islave[i]] # change the sign if slave is earlier than master isign = where(imaster > islave) b0_mat[isign[0], :] = -b0_mat[isign[0], :] tsvel_matrix = np.empty(shape=(nrows, ncols, nvelpar), dtype=float32) ifg_data = np.zeros((nifgs, nrows, ncols), dtype=float32) for ifg_num in range(nifgs): ifg_data[ifg_num] = ifgs[ifg_num].phase_data if mst is None: mst = ~isnan(ifg_data) return b0_mat, interp, pthresh, smfactor, smorder, tsmethod, ifg_data, \ mst, ncols, nrows, nvelpar, parallel, span, tsvel_matrix
def test_default_mst(self): # default MST from full set of Ifgs shouldn't drop any nodes ifgs = small5_mock_ifgs() dates = [(i.master, i.slave) for i in ifgs] res = mst.mst_from_ifgs(ifgs)[0] num_edges = len(res) self.assertEqual(num_edges, len(ifgs)) # test edges, note node order can be reversed for edge in res: self.assertTrue(edge in dates or (edge[1], edge[0]) in dates) # check all nodes exist in this default tree mst_dates = set(res) mst_dates = list(sum(mst_dates, ())) for i in ifgs: for node in (i.master, i.slave): self.assertIn(node, mst_dates)
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)
def test_small_data_tree(self): self.assertTrue(mst.mst_from_ifgs(self.ifgs)[1])
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)
def time_series_setup(ifgs, mst, params): """ Convenience function setting up time series computation parameters. :param ifgs: xxxx :param mst: xxxx :param params: xxxx :return xxxx """ if len(ifgs) < 1: msg = 'Time series requires 2+ interferograms' raise TimeSeriesError(msg) # if mst is not a single tree then do interpolation interp = 0 if mst_module.mst_from_ifgs(ifgs)[1] else 1 # Parallel Processing parameters parallel = params[cf.PARALLEL] # Time Series parameters tsmethod = params[cf.TIME_SERIES_METHOD] if tsmethod == 1 and params[cf.TIME_SERIES_SM_ORDER] is None: missing_option_error(cf.TIME_SERIES_SM_ORDER) else: smorder = params[cf.TIME_SERIES_SM_ORDER] if tsmethod == 1 and params[cf.TIME_SERIES_SM_FACTOR] is None: missing_option_error(cf.TIME_SERIES_SM_FACTOR) else: smfactor = np.power(10, params[cf.TIME_SERIES_SM_FACTOR]) if params[cf.TIME_SERIES_PTHRESH] is None: missing_option_error(cf.TIME_SERIES_PTHRESH) else: pthresh = params[cf.TIME_SERIES_PTHRESH] if pthresh < 0.0 or pthresh > 1000: raise ValueError( "minimum number of coherent observations for a pixel" " TIME_SERIES_PTHRESH setting must be >= 0.0 and <= 1000") epochlist = get_epochs(ifgs)[0] nrows = ifgs[0].nrows ncols = ifgs[0].ncols nifgs = len(ifgs) span = diff(epochlist.spans) nepoch = len(epochlist.dates) # epoch number nvelpar = nepoch - 1 # velocity parameters number # nlap = nvelpar - smorder # Laplacian observations number mast_slave_ids = master_slave_ids(epochlist.dates) imaster = [mast_slave_ids[ifg.master] for ifg in ifgs] islave = [mast_slave_ids[ifg.slave] for ifg in ifgs] imaster = min(imaster, islave) islave = max(imaster, islave) b0_mat = zeros((nifgs, nvelpar)) for i in range(nifgs): b0_mat[i, imaster[i]:islave[i]] = span[imaster[i]:islave[i]] # change the sign if slave is earlier than master isign = where(imaster > islave) b0_mat[isign[0], :] = -b0_mat[isign[0], :] tsvel_matrix = np.empty(shape=(nrows, ncols, nvelpar), dtype=float32) ifg_data = np.zeros((nifgs, nrows, ncols), dtype=float32) for ifg_num in range(nifgs): ifg_data[ifg_num] = ifgs[ifg_num].phase_data if mst is None: mst = ~isnan(ifg_data) return b0_mat, interp, pthresh, smfactor, smorder, tsmethod, ifg_data, \ mst, ncols, nrows, nvelpar, parallel, span, tsvel_matrix