def plot_init_map(ax, d_v, inps, metadata): # prepare data if inps.wrap: if inps.disp_unit_v == 'radian': d_v *= inps.range2phase d_v = ut.wrap(d_v, wrap_range=inps.wrap_range) # Title and Axis Label disp_date = inps.dates[inps.init_idx].strftime('%Y-%m-%d') inps.fig_title = 'N = {}, Time = {}'.format(inps.init_idx, disp_date) # Initial Pixel if inps.yx and inps.yx != inps.ref_yx: inps.pts_yx = np.array(inps.yx).reshape(-1, 2) if inps.lalo: inps.pts_lalo = np.array(inps.lalo).reshape(-1, 2) else: inps.pts_lalo = None inps.pts_marker = 'ro' # call view.py to plot ax, inps, im, cbar = view.plot_slice(ax, d_v, metadata, inps) return ax, im
def get_nonzero_phase_closure(ifgram_file, out_file=None, thres=0.1, unwDatasetName='unwrapPhase'): """Calculate/Read number of non-zero phase closure Parameters: ifgram_file : string, path of ifgram stack file out_file : string, path of num non-zero phase closure file Returns: num_nonzero_closure : 2D np.array in size of (length, width) """ if not out_file: out_file = 'numNonzeroPhaseClosure_{}.h5'.format(unwDatasetName) if os.path.isfile(out_file) and readfile.read_attribute(out_file): print('1. read number of nonzero phase closure from file: {}'.format( out_file)) num_nonzero_closure = readfile.read(out_file)[0] else: obj = ifgramStack(ifgram_file) obj.open(print_msg=False) length, width = obj.length, obj.width ref_phase = obj.get_reference_phase(unwDatasetName=unwDatasetName, dropIfgram=False) C = obj.get_design_matrix4triplet( obj.get_date12_list(dropIfgram=False)) # calculate phase closure line by line to save memory usage num_nonzero_closure = np.zeros((length, width), np.float32) print( '1. calculating phase closure of all pixels from dataset - {} ...'. format(unwDatasetName)) line_step = 10 num_loop = int(np.ceil(length / line_step)) prog_bar = ptime.progressBar(maxValue=num_loop) for i in range(num_loop): # read phase i0, i1 = i * line_step, min(length, (i + 1) * line_step) box = (0, i0, width, i1) pha_data = ifginv.read_unwrap_phase(obj, box, ref_phase, unwDatasetName=unwDatasetName, dropIfgram=False, print_msg=False) # calculate phase closure pha_closure = np.dot(C, pha_data) pha_closure = np.abs(pha_closure - ut.wrap(pha_closure)) # get number of non-zero phase closure num_nonzero = np.sum(pha_closure >= thres, axis=0) num_nonzero_closure[i0:i1, :] = num_nonzero.reshape(i1 - i0, width) prog_bar.update(i + 1, every=1, suffix='{}/{} lines'.format((i + 1) * line_step, length)) prog_bar.close() atr = dict(obj.metadata) atr['FILE_TYPE'] = 'mask' atr['UNIT'] = 1 writefile.write(num_nonzero_closure, out_file=out_file, metadata=atr) return num_nonzero_closure
def update_time_slider(val): """Update Displacement Map using Slider""" idx = np.argmin(np.abs(np.array(inps.yearList) - tslider.val)) disp_date = inps.dates[idx].strftime('%Y-%m-%d') ax_v.set_title('N = {n}, Time = {t}'.format(n=idx, t=disp_date)) d_v = np.array(ts_data[0][idx, :, :]) if inps.wrap: if inps.disp_unit_v == 'radian': d_v *= inps.range2phase d_v = ut.wrap(d_v, wrap_range=inps.wrap_range) im.set_data(d_v) fig_v.canvas.draw()
def correct_unwrap_error(ifgram, C, Dconstraint=True, thres=0.1, alpha=0.25, rcond=1e-5): """Estimate unwrapping error from a stack of unwrapped interferometric phase Parameters: ifgram : 2D np.array in size of (num_ifgram, num_pixel) of unwrap phase C : 2D np.array in size of (num_triangle, num_ifgram) triangle design matrix Dconstraint : bool, apply zero phase jump constraint on ifgrams without unwrapping error. This is disabled in fast option thres : float, threshold of non-zero phase closure beyond which indicates unwrap error alpha : float, Tikhonov factor, regularization parameter rcond : float, cut-off value for least square estimation Returns: ifgram_cor : 2D np.array in size of (num_ifgram, num_pixel) of unwrap phase after correction U : 2D np.array in size of (num_ifgram, num_pixel) of phase jump integer Example: ifgram_cor, U = estimate_unwrap_error(ifgram, C) """ num_tri, num_ifgram = C.shape ifgram = ifgram.reshape(num_ifgram, -1) U = np.zeros(ifgram.shape, np.float32) I = np.eye(num_ifgram, dtype=np.float32) A = np.vstack((C, alpha*I)) # Use Tikhonov regularization (alpha*D0) to solve equation in ill-posed scenario: # e.g.: network is not dense enough AND a lot of unwrapping error exist, # then A.shape[0] < A.shape[1]: number of unknown > number of observations if Dconstraint: # get D # 1. calculate phase closure for all ifgram triangles --> identy those with unwrap error # 2. identy ifgrams involved in at least 1 triangle with unwrap error # 3. get D for ifgram 'without any unwrap error' or 'correctly unwrapped' pha_closure = np.dot(C, ifgram) pha_closure = np.abs(pha_closure - ut.wrap(pha_closure)) idx_nonzero_closure = (pha_closure >= thres).flatten() idx_err_ifgram = np.sum(C[idx_nonzero_closure, :] != 0., axis=0) >= 1. D = I[~idx_err_ifgram, :] A = np.vstack((A, D)) # Eq 4.4 (Fattahi, 2015) try: A_inv = linalg.pinv2(A, rcond=rcond) L = np.zeros((A.shape[0], ifgram.shape[1]), np.float32) L[0:num_tri, :] = np.dot(C, ifgram) / (-2.*np.pi) U = np.round(np.dot(A_inv, L)) except linalg.LinAlgError: pass ifgram_cor = ifgram + 2*np.pi*U return ifgram_cor, U
def update_time_slider(self, val): """Update Displacement Map using Slider""" idx = np.argmin(np.abs(np.array(self.yearList) - self.tslider.val)) # update title disp_date = self.dates[idx].strftime('%Y-%m-%d') self.ax_img.set_title('N = {n}, Time = {t}'.format(n=idx, t=disp_date), fontsize=self.font_size) # read data data_img = np.array(self.ts_data[0][idx, :, :]) data_img[self.mask == 0] = np.nan if self.wrap: if self.disp_unit_img == 'radian': data_img *= self.range2phase data_img = ut.wrap(data_img, wrap_range=self.wrap_range) # update data self.img.set_data(data_img) self.fig_img.canvas.draw() return
def plot_init_image(self, img_data): # prepare data if self.wrap: if self.disp_unit_img == 'radian': img_data *= self.range2phase img_data = ut.wrap(img_data, wrap_range=self.wrap_range) # Title and Axis Label disp_date = self.dates[self.init_idx].strftime('%Y-%m-%d') self.fig_title = 'N = {}, Time = {}'.format(self.init_idx, disp_date) # Initial Pixel if self.yx and self.yx != self.ref_yx: self.pts_yx = np.array(self.yx).reshape(-1, 2) if self.lalo: self.pts_lalo = np.array(self.lalo).reshape(-1, 2) else: self.pts_lalo = None # call view.py to plot self.img, self.cbar_img = view.plot_slice(self.ax_img, img_data, self.atr, self)[2:4] return self.img, self.cbar_img
def get_common_region_int_ambiguity(ifgram_file, cc_mask_file, water_mask_file=None, num_sample=100, dsNameIn='unwrapPhase'): """Solve the phase unwrapping integer ambiguity for the common regions among all interferograms Parameters: ifgram_file : str, path of interferogram stack file cc_mask_file : str, path of common connected components file water_mask_file : str, path of water mask file num_sample : int, number of pixel sampled for each region dsNameIn : str, dataset name of the unwrap phase to be corrected Returns: common_regions : list of skimage.measure._regionprops._RegionProperties object modified by adding two more variables: sample_coords : 2D np.ndarray in size of (num_sample, 2) in int64 format int_ambiguity : 1D np.ndarray in size of (num_ifgram,) in int format """ print('-' * 50) print( 'calculating the integer ambiguity for the common regions defined in', cc_mask_file) # stack info stack_obj = ifgramStack(ifgram_file) stack_obj.open() date12_list = stack_obj.get_date12_list(dropIfgram=True) num_ifgram = len(date12_list) C = matrix( ifgramStack.get_design_matrix4triplet(date12_list).astype(float)) ref_phase = stack_obj.get_reference_phase(unwDatasetName=dsNameIn, dropIfgram=True).reshape( num_ifgram, -1) # prepare common label print('read common mask from', cc_mask_file) cc_mask = readfile.read(cc_mask_file)[0] if water_mask_file is not None and os.path.isfile(water_mask_file): water_mask = readfile.read(water_mask_file)[0] print('refine common mask based on water mask file', water_mask_file) cc_mask[water_mask == 0] = 0 label_img, num_label = connectComponent.get_large_label(cc_mask, min_area=2.5e3, print_msg=True) common_regions = measure.regionprops(label_img) print('number of common regions:', num_label) # add sample_coords / int_ambiguity print('number of samples per region:', num_sample) print('solving the phase-unwrapping integer ambiguity for {}'.format( dsNameIn)) print( '\tbased on the closure phase of interferograms triplets (Yunjun et al., 2019)' ) print( '\tusing the L1-norm regularzed least squares approximation (LASSO) ...' ) for i in range(num_label): common_reg = common_regions[i] # sample_coords idx = sorted( np.random.choice(common_reg.area, num_sample, replace=False)) common_reg.sample_coords = common_reg.coords[idx, :].astype(int) # solve for int_ambiguity U = np.zeros((num_ifgram, num_sample)) if common_reg.label == label_img[stack_obj.refY, stack_obj.refX]: print('{}/{} skip calculation for the reference region'.format( i + 1, num_label)) else: prog_bar = ptime.progressBar(maxValue=num_sample, prefix='{}/{}'.format( i + 1, num_label)) for j in range(num_sample): # read unwrap phase y, x = common_reg.sample_coords[j, :] unw = ifginv.read_unwrap_phase(stack_obj, box=(x, y, x + 1, y + 1), ref_phase=ref_phase, unwDatasetName=dsNameIn, dropIfgram=True, print_msg=False).reshape( num_ifgram, -1) # calculate closure_int closure_pha = np.dot(C, unw) closure_int = matrix( np.round( (closure_pha - ut.wrap(closure_pha)) / (2. * np.pi))) # solve for U U[:, j] = np.round( l1regls(-C, closure_int, alpha=1e-2, show_progress=0)).flatten() prog_bar.update(j + 1, every=5) prog_bar.close() # add int_ambiguity common_reg.int_ambiguity = np.median(U, axis=1) common_reg.date12_list = date12_list #sort regions by size to facilitate the region matching later common_regions.sort(key=lambda x: x.area, reverse=True) # plot sample result fig_size = pp.auto_figure_size(label_img.shape, disp_cbar=False) fig, ax = plt.subplots(figsize=fig_size) ax.imshow(label_img, cmap='jet') for common_reg in common_regions: ax.plot(common_reg.sample_coords[:, 1], common_reg.sample_coords[:, 0], 'k.', ms=2) pp.auto_flip_direction(stack_obj.metadata, ax, print_msg=False) out_img = 'common_region_sample.png' fig.savefig(out_img, bbox_inches='tight', transparent=True, dpi=300) print('saved common regions and sample pixels to file', out_img) return common_regions
def run_unwrap_error_patch(ifgram_file, box=None, mask_file=None, ref_phase=None, fast_mode=False, thres=0.1, dsNameIn='unwrapPhase'): """Estimate/Correct unwrapping error in ifgram stack on area defined by box. Parameters: ifgram_file : string, ifgramStack file box : tuple of 4 int, indicating areas to be read and analyzed mask_file : string, file name of mask file for pixels to be analyzed ref_pahse : 1D np.array in size of (num_ifgram,) phase value on reference pixel, because: 1) phase value stored in pysar is not reference yet 2) reference point may be out of box definition fast_mode : bool, apply zero jump constraint on ifgrams without unwrapping error. thres : float, threshold of non-zero phase closure to be identified as unwrapping error. Returns: pha_data : 3D np.array in size of (num_ifgram_all, box[3]-box[2], box[2]-box[0]), unwrapped phase value after error correction """ # Basic info stack_obj = ifgramStack(ifgram_file) stack_obj.open(print_msg=False) num_ifgram = stack_obj.numIfgram # Size Info - Patch if box: num_row = box[3] - box[1] num_col = box[2] - box[0] else: num_row = stack_obj.length num_col = stack_obj.width num_pixel = num_row * num_col C = stack_obj.get_design_matrix4ifgram_triangle(dropIfgram=True) print('number of interferograms: {}'.format(C.shape[1])) print('number of triangles: {}'.format(C.shape[0])) # read unwrapPhase pha_data_all = ifginv.read_unwrap_phase(stack_obj, box, ref_phase, unwDatasetName=dsNameIn, dropIfgram=False) pha_data = np.array(pha_data_all[stack_obj.dropIfgram, :]) # mask of pixels to analyze mask = np.ones((num_pixel), np.bool_) print('number of pixels read: {}'.format(num_pixel)) # mask 1. mask of water or area of interest if mask_file: dsNames = readfile.get_dataset_list(mask_file) dsName = [i for i in dsNames if i in ['waterMask', 'mask']][0] waterMask = readfile.read(mask_file, datasetName=dsName, box=box)[0].flatten() mask *= np.array(waterMask, np.bool_) del waterMask print('number of pixels left after mask: {}'.format(np.sum(mask))) # mask 2. mask of pixels without unwrap error: : zero phase closure on all triangles print('calculating phase closure of all possible triangles ...') pha_closure = np.dot(C, pha_data) pha_closure = np.abs(pha_closure - ut.wrap(pha_closure)) # Eq 4.2 (Fattahi, 2015) num_nonzero_closure = np.sum(pha_closure >= thres, axis=0) mask *= (num_nonzero_closure != 0.) del pha_closure print('number of pixels left after checking phase closure: {}'.format(np.sum(mask))) # mask summary num_pixel2proc = int(np.sum(mask)) if num_pixel2proc > 0: ifgram = pha_data[:, mask] ifgram_cor = np.array(ifgram, np.float32) print('number of pixels to process: {} out of {} ({:.2f}%)'.format(num_pixel2proc, num_pixel, num_pixel2proc/num_pixel*100)) # correcting unwrap error based on phase closure print('correcting unwrapping error ...') if fast_mode: ifgram_cor = correct_unwrap_error(ifgram, C, Dconstraint=False)[0] else: prog_bar = ptime.progressBar(maxValue=num_pixel2proc) for i in range(num_pixel2proc): ifgram_cor[:, i] = correct_unwrap_error(ifgram[:, i], C, Dconstraint=True)[0].flatten() prog_bar.update(i+1, every=10, suffix='{}/{}'.format(i+1, num_pixel2proc)) prog_bar.close() pha_data[:, mask] = ifgram_cor pha_data_all[stack_obj.dropIfgram, :] = pha_data pha_data_all = pha_data_all.reshape(num_ifgram, num_row, num_col) num_nonzero_closure = num_nonzero_closure.reshape(num_row, num_col) return pha_data_all, num_nonzero_closure