def test_orb_error(self, orbfit_method, orbfit_degrees): self.params[cf.ORBITAL_FIT_METHOD] = orbfit_method self.params[cf.ORBITAL_FIT_DEGREE] = orbfit_degrees multi_paths = self.params[cf.INTERFEROGRAM_FILES] self.ifg_paths = [p.tmp_sampled_path for p in multi_paths] remove_orbital_error(self.ifg_paths, self.params) # test_orb_errors_written orb_error_files = [MultiplePaths.orb_error_path(i, self.params) for i in self.ifg_paths] assert all(p.exists() for p in orb_error_files) last_mod_times = np.array([os.stat(o).st_mtime for o in orb_error_files]) # run orbit removal again remove_orbital_error(self.ifg_paths, self.params) orb_error_files2 = [MultiplePaths.orb_error_path(i, self.params) for i in self.ifg_paths] # if files are written again - times will change last_mod_times_2 = np.array([os.stat(o).st_mtime for o in orb_error_files2]) # test_orb_error_reused_if_params_unchanged assert all(a == b for a, b in zip(last_mod_times, last_mod_times_2)) # change one of the params _degrees = set(cf.ORB_DEGREE_NAMES.keys()) _degrees.discard(orbfit_degrees) # test_orb_errors_recalculated_if_params_change self.params[cf.ORBITAL_FIT_DEGREE] = _degrees.pop() remove_orbital_error(self.ifg_paths, self.params) orb_error_files3 = [MultiplePaths.orb_error_path(i, self.params) for i in self.ifg_paths] last_mod_times_3 = np.array([os.stat(o).st_mtime for o in orb_error_files3]) assert all(a != b for a, b in zip(last_mod_times, last_mod_times_3))
def independent_orbital_correction(ifg, 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 """ degree = params[cf.ORBITAL_FIT_DEGREE] offset = params[cf.ORBFIT_OFFSET] orbfit_correction_on_disc = MultiplePaths.orb_error_path( ifg.data_path, params) if not ifg.is_open: ifg.open() shared.nan_and_mm_convert(ifg, params) if orbfit_correction_on_disc.exists(): log.info( f'Reusing already computed orbital fit correction for {ifg.data_path}' ) orbital_correction = np.load(file=orbfit_correction_on_disc) else: # 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) if not orbfit_correction_on_disc.parent.exists(): shared.mkdir_p(orbfit_correction_on_disc.parent) offset_removal = nanmedian(np.ravel(ifg.phase_data - fullorb)) orbital_correction = fullorb - offset_removal # dump to disc np.save(file=orbfit_correction_on_disc, arr=orbital_correction) # subtract orbital error from the ifg ifg.phase_data -= orbital_correction # set orbfit meta tag and save phase to file _save_orbital_error_corrected_phase(ifg) ifg.close()
def _remove_network_orb_error(coefs, dm, ifg, ids, offset, params): """ remove network orbital error from input interferograms """ saved_orb_err_path = MultiplePaths.orb_error_path(ifg.data_path, params) orb = dm.dot(coefs[ids[ifg.second]] - coefs[ids[ifg.first]]) orb = orb.reshape(ifg.shape) # offset estimation if offset: # bring all ifgs to same base level orb -= nanmedian(np.ravel(ifg.phase_data - orb)) # subtract orbital error from the ifg ifg.phase_data -= orb # save orb error on disc np.save(file=saved_orb_err_path, arr=orb) # set orbfit meta tag and save phase to file _save_orbital_error_corrected_phase(ifg)
def __check_and_apply_orberrors_found_on_disc(ifg_paths, params): saved_orb_err_paths = [ MultiplePaths.orb_error_path(ifg_path, params) for ifg_path in ifg_paths ] for p, i in zip(saved_orb_err_paths, ifg_paths): if p.exists(): orb = np.load(p) if isinstance(i, str): # are paths ifg = Ifg(i) ifg.open(readonly=False) shared.nan_and_mm_convert(ifg, params) else: ifg = i ifg.phase_data -= orb # set orbfit meta tag and save phase to file _save_orbital_error_corrected_phase(ifg) return all(p.exists() for p in saved_orb_err_paths)
def _remove_network_orb_error(coefs, dm, ifg, ids, offset, params): """ remove network orbital error from input interferograms """ saved_orb_err_path = MultiplePaths.orb_error_path(ifg.data_path, params) orb = dm.dot(coefs[ids[ifg.second]] - coefs[ids[ifg.first]]) orb = orb.reshape(ifg.shape) # Estimate the offset of the interferogram as the median of ifg minus model # Only needed if reference phase correction has already been applied? if offset: # brings all ifgs to same reference level orb -= nanmedian(np.ravel(ifg.phase_data - orb)) # subtract orbital error from the ifg ifg.phase_data -= orb # save orb error on disc np.save(file=saved_orb_err_path, arr=orb) # set orbfit meta tag and save phase to file _save_orbital_error_corrected_phase(ifg, params)
def independent_orbital_correction(ifg_path, 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 dict params: dictionary of configuration parameters :return: None - interferogram phase data is updated and saved to disk """ log.debug(f"Orbital correction of {ifg_path}") degree = params[C.ORBITAL_FIT_DEGREE] offset = params[C.ORBFIT_OFFSET] intercept = params[C.ORBFIT_INTERCEPT] xlooks = params[C.ORBITAL_FIT_LOOKS_X] ylooks = params[C.ORBITAL_FIT_LOOKS_Y] ifg0 = shared.Ifg(ifg_path) if isinstance(ifg_path, str) else ifg_path # get full-resolution design matrix fullres_dm = get_design_matrix(ifg0, degree, intercept=intercept) ifg = shared.dem_or_ifg(ifg_path) if isinstance(ifg_path, str) else ifg_path multi_path = MultiplePaths(ifg.data_path, params) orb_on_disc = MultiplePaths.orb_error_path(ifg.data_path, params) if not ifg.is_open: ifg.open() shared.nan_and_mm_convert(ifg, params) fullres_ifg = ifg # keep a backup fullres_phase = fullres_ifg.phase_data if orb_on_disc.exists(): log.info( f'Reusing already computed orbital fit correction: {orb_on_disc}') orbital_correction = np.load(file=orb_on_disc) else: # Multi-look the ifg data if either X or Y is greater than 1 if (xlooks > 1) or (ylooks > 1): exts, _, _ = __extents_from_params(params) mlooked = _create_mlooked_dataset(multi_path, ifg.data_path, exts, params) ifg = Ifg(mlooked) # multi-looked Ifg object ifg.initialize() shared.nan_and_mm_convert(ifg, params) # vectorise phase data, keeping NODATA vphase = reshape(ifg.phase_data, ifg.num_cells) # compute design matrix for multi-looked data mlooked_dm = get_design_matrix(ifg, degree, intercept=intercept) # invert to obtain the correction image (forward model) at full-res orbital_correction = __orb_correction(fullres_dm, mlooked_dm, fullres_phase, vphase, offset=offset) # save correction to disc if not orb_on_disc.parent.exists(): shared.mkdir_p(orb_on_disc.parent) np.save(file=orb_on_disc, arr=orbital_correction) # subtract orbital correction from the full-res ifg fullres_ifg.phase_data -= orbital_correction # set orbfit meta tag and save phase to file _save_orbital_error_corrected_phase(fullres_ifg, params)