예제 #1
0
def plot_num_triplet_with_nonzero_integer_ambiguity(fname, display=False, font_size=12, fig_size=[9,3]):
    """Plot the histogram for the number of triplets with non-zero integer ambiguity

    Fig. 3d-e in Yunjun et al. (2019, CAGEO).
    """

    # read data
    data, atr = readfile.read(fname)
    vmax = int(np.nanmax(data))

    # plot
    fig, axs = plt.subplots(nrows=1, ncols=2, figsize=fig_size)

    # subplot 1 - map
    ax = axs[0]
    im = ax.imshow(data, cmap='RdBu_r', interpolation='nearest')

    # reference point
    if all(key in atr.keys() for key in ['REF_Y','REF_X']):
        ax.plot(int(atr['REF_X']), int(atr['REF_Y']), 's', color='white', ms=3)

    # format
    pp.auto_flip_direction(atr, ax=ax, print_msg=False)
    fig.colorbar(im, ax=ax)
    ax.set_title(r'$T_{int}$', fontsize=font_size)

    # subplot 2 - histogram
    ax = axs[1]
    ax.hist(data[~np.isnan(data)].flatten(), range=(0, vmax), log=True, bins=vmax)

    # axis format
    ax.set_xlabel(r'# of triplets w non-zero int ambiguity $T_{int}$', fontsize=font_size)
    ax.set_ylabel('# of pixels', fontsize=font_size)
    ax.xaxis.set_minor_locator(ticker.AutoMinorLocator())
    ax.yaxis.set_major_locator(ticker.LogLocator(base=10.0, numticks=15))
    ax.yaxis.set_minor_locator(ticker.LogLocator(base=10.0, numticks=15,
                                                 subs=(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9)))
    ax.yaxis.set_minor_formatter(ticker.NullFormatter())

    for ax in axs:
        ax.tick_params(which='both', direction='in', labelsize=font_size,
                       bottom=True, top=True, left=True, right=True)

    fig.tight_layout()

    # output
    out_fig = '{}.png'.format(os.path.splitext(fname)[0])
    print('plot and save figure to file', out_fig)
    fig.savefig(out_fig, bbox_inches='tight', transparent=True, dpi=300)

    if display:
        plt.show()
    else:
        plt.close(fig)

    return
예제 #2
0
def flip_map():
    global inps, atr

    if inps.auto_flip:
        inps.flip_lr, inps.flip_ud = pp.auto_flip_direction(atr)
    else:
        inps.flip_ud = False
        inps.flip_lr = False
예제 #3
0
def flip_map():
    global inps, atr

    if inps.auto_flip:
        inps.flip_lr, inps.flip_ud = pp.auto_flip_direction(atr)
    else:
        inps.flip_ud = False
        inps.flip_lr = False
예제 #4
0
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
예제 #5
0
def update_inps_with_file_metadata(inps, metadata):
    # Subset
    # Convert subset input into bounding box in radar / geo coordinate
    # geo_box = None if atr is not geocoded.
    coord = ut.coordinate(metadata)
    inps.pix_box, inps.geo_box = subset.subset_input_dict2box(
        vars(inps), metadata)
    inps.pix_box = coord.check_box_within_data_coverage(inps.pix_box)
    inps.geo_box = coord.box_pixel2geo(inps.pix_box)
    # Out message
    data_box = (0, 0, inps.width, inps.length)
    vprint('data   coverage in y/x: ' + str(data_box))
    vprint('subset coverage in y/x: ' + str(inps.pix_box))
    vprint('data   coverage in lat/lon: ' + str(coord.box_pixel2geo(data_box)))
    vprint('subset coverage in lat/lon: ' + str(inps.geo_box))
    vprint(
        '------------------------------------------------------------------------'
    )

    # DEM contour display
    if max(inps.pix_box[3] - inps.pix_box[1],
           inps.pix_box[2] - inps.pix_box[0]) > 2e3:
        inps.disp_dem_contour = False
        if inps.dem_file:
            vprint(
                'area exceed 2000 pixels, turn off default DEM contour display'
            )

    # Multilook, if too many subplots in one figure for less memory and faster speed
    if inps.multilook_num > 1:
        inps.multilook = True

    # Colormap
    inps.colormap = pp.check_colormap_input(metadata,
                                            inps.colormap,
                                            datasetName=inps.dset[0],
                                            cmap_lut=inps.cmap_lut,
                                            print_msg=inps.print_msg)

    # Reference Point
    # Convert ref_lalo if existed, to ref_yx, and use ref_yx for the following
    # ref_yx is referenced to input data coverage, not subseted area for display
    if inps.ref_lalo and inps.geo_box:
        inps.ref_yx = [
            coord.lalo2yx(inps.ref_lalo[0], coord_type='lat'),
            coord.lalo2yx(inps.ref_lalo[1], coord_type='lon')
        ]
        vprint('input reference point in lat/lon: {}'.format(inps.ref_lalo))
        vprint('input reference point in y  /x  : {}'.format(inps.ref_yx))

    # ref_lalo
    if inps.ref_yx and inps.geo_box:
        inps.ref_lalo = [
            coord.yx2lalo(inps.ref_yx[0], coord_type='y'),
            coord.yx2lalo(inps.ref_yx[1], coord_type='x')
        ]
    elif 'REF_LAT' in metadata.keys():
        inps.ref_lalo = [
            float(metadata['REF_LAT']),
            float(metadata['REF_LON'])
        ]
    else:
        inps.ref_lalo = None

    # Points of interest
    inps = pp.read_point2inps(inps, coord)

    # Unit and Wrap
    inps.disp_unit, inps.wrap = pp.check_disp_unit_and_wrap(
        metadata,
        disp_unit=inps.disp_unit,
        wrap=inps.wrap,
        wrap_range=inps.wrap_range,
        print_msg=inps.print_msg)

    # Min / Max - Display
    if not inps.vlim:
        if (any(i in inps.key.lower() for i in ['coherence', '.cor'])
                or (inps.key == 'ifgramStack'
                    and inps.dset[0].split('-')[0] in ['coherence'])
                or inps.dset[0] == 'cmask'):
            inps.vlim = [0.0, 1.0]
        elif inps.key in ['.int'] or inps.wrap:
            inps.vlim = inps.wrap_range

    # Transparency - Alpha
    if not inps.transparency:
        # Auto adjust transparency value when showing shaded relief DEM
        if inps.dem_file and inps.disp_dem_shade:
            inps.transparency = 0.8
        else:
            inps.transparency = 1.0

    # Flip Left-Right / Up-Down
    if inps.auto_flip:
        inps.flip_lr, inps.flip_ud = pp.auto_flip_direction(
            metadata, print_msg=inps.print_msg)

    # Figure Title
    if not inps.fig_title:
        inps.fig_title = pp.auto_figure_title(metadata['FILE_PATH'],
                                              datasetNames=inps.dset,
                                              inps_dict=vars(inps))
    vprint('figure title: ' + inps.fig_title)

    # Figure output file name
    if not inps.outfile:
        inps.outfile = ['{}{}'.format(inps.fig_title, inps.fig_ext)]

    inps = update_figure_setting(inps)
    return inps
예제 #6
0
def read_init_info(inps):
    # Time Series Info
    atr = readfile.read_attribute(inps.file[0])
    inps.key = atr['FILE_TYPE']
    if inps.key == 'timeseries':
        obj = timeseries(inps.file[0])
    elif inps.key == 'giantTimeseries':
        obj = giantTimeseries(inps.file[0])
    elif inps.key == 'HDFEOS':
        obj = HDFEOS(inps.file[0])
    else:
        raise ValueError('input file is {}, not timeseries.'.format(inps.key))
    obj.open(print_msg=inps.print_msg)
    inps.seconds = atr.get('CENTER_LINE_UTC', 0)

    if not inps.file_label:
        inps.file_label = []
        for fname in inps.file:
            fbase = os.path.splitext(os.path.basename(fname))[0]
            fbase = fbase.replace('timeseries', '')
            inps.file_label.append(fbase)

    # default mask file
    if not inps.mask_file and 'msk' not in inps.file[0]:
        dir_name = os.path.dirname(inps.file[0])
        if 'Y_FIRST' in atr.keys():
            inps.mask_file = os.path.join(dir_name, 'geo_maskTempCoh.h5')
        else:
            inps.mask_file = os.path.join(dir_name, 'maskTempCoh.h5')
        if not os.path.isfile(inps.mask_file):
            inps.mask_file = None

    ## date info
    inps.date_list = obj.dateList
    inps.num_date = len(inps.date_list)
    if inps.start_date:
        inps.date_list = [i for i in inps.date_list if int(i) >= int(inps.start_date)]
    if inps.end_date:
        inps.date_list = [i for i in inps.date_list if int(i) <= int(inps.end_date)]
    inps.num_date = len(inps.date_list)
    inps.dates, inps.yearList = ptime.date_list2vector(inps.date_list)

    (inps.ex_date_list,
     inps.ex_dates,
     inps.ex_flag) = read_exclude_date(inps.ex_date_list, inps.date_list)

    # reference date/index
    if not inps.ref_date:
        inps.ref_date = atr.get('REF_DATE', None)
    if inps.ref_date:
        inps.ref_idx = inps.date_list.index(inps.ref_date)
    else:
        inps.ref_idx = None

    # date/index of interest for initial display
    if not inps.idx:
        if (not inps.ref_idx) or (inps.ref_idx < inps.num_date / 2.):
            inps.idx = inps.num_date - 2
        else:
            inps.idx = 2

    # Display Unit
    (inps.disp_unit,
     inps.unit_fac) = pp.scale_data2disp_unit(metadata=atr, disp_unit=inps.disp_unit)[1:3]

    # Map info - coordinate unit
    inps.coord_unit = atr.get('Y_UNIT', 'degrees').lower()

    # Read Error List
    inps.ts_plot_func = plot_ts_scatter
    inps.error_ts = None
    inps.ex_error_ts = None
    if inps.error_file:
        # assign plot function
        inps.ts_plot_func = plot_ts_errorbar

        # read error file
        error_fc = np.loadtxt(inps.error_file, dtype=bytes).astype(str)
        inps.error_ts = error_fc[:, 1].astype(np.float)*inps.unit_fac

        # update error file with exlcude date
        if inps.ex_date_list:
            e_ts = inps.error_ts[:]
            inps.ex_error_ts = e_ts[inps.ex_flag == 0]
            inps.error_ts = e_ts[inps.ex_flag == 1]

    # Zero displacement for 1st acquisition
    if inps.zero_first:
        inps.zero_idx = min(0, np.min(np.where(inps.ex_flag)[0]))

    # default lookup table file and coordinate object
    if not inps.lookup_file:
        inps.lookup_file = ut.get_lookup_file('./inputs/geometryRadar.h5')
    inps.coord = ut.coordinate(atr, inps.lookup_file)

    ## size and lalo info
    inps.pix_box, inps.geo_box = subset.subset_input_dict2box(vars(inps), atr)
    inps.pix_box = inps.coord.check_box_within_data_coverage(inps.pix_box)
    inps.geo_box = inps.coord.box_pixel2geo(inps.pix_box)
    data_box = (0, 0, int(atr['WIDTH']), int(atr['LENGTH']))
    vprint('data   coverage in y/x: '+str(data_box))
    vprint('subset coverage in y/x: '+str(inps.pix_box))
    vprint('data   coverage in lat/lon: '+str(inps.coord.box_pixel2geo(data_box)))
    vprint('subset coverage in lat/lon: '+str(inps.geo_box))
    vprint('------------------------------------------------------------------------')

    # calculate multilook_num
    # ONLY IF:
    #   inps.multilook is True (no --nomultilook input) AND
    #   inps.multilook_num ==1 (no --multilook-num input)
    # Note: inps.multilook is used for this check ONLY
    # Note: multilooking is only applied to the 3D data cubes and their related operations:
    # e.g. spatial indexing, referencing, etc. All the other variables are in the original grid
    # so that users get the same result as the non-multilooked version.
    if inps.multilook and inps.multilook_num == 1:
        inps.multilook_num = pp.auto_multilook_num(inps.pix_box, inps.num_date,
                                                   max_memory=inps.maxMemory,
                                                   print_msg=inps.print_msg)

    ## reference pixel
    if not inps.ref_lalo and 'REF_LAT' in atr.keys():
        inps.ref_lalo = (float(atr['REF_LAT']), float(atr['REF_LON']))
    if inps.ref_lalo:
        # set longitude to [-180, 180)
        if inps.coord_unit.lower().startswith('deg') and inps.ref_lalo[1] >= 180.:
            inps.ref_lalo[1] -= 360.
        # ref_lalo --> ref_yx if not set in cmd
        if not inps.ref_yx:
            inps.ref_yx = inps.coord.geo2radar(inps.ref_lalo[0], inps.ref_lalo[1], print_msg=False)[0:2]

    # use REF_Y/X if ref_yx not set in cmd
    if not inps.ref_yx and 'REF_Y' in atr.keys():
        inps.ref_yx = (int(atr['REF_Y']), int(atr['REF_X']))

    # ref_yx --> ref_lalo if in geo-coord
    # for plotting purpose only
    if inps.ref_yx and 'Y_FIRST' in atr.keys():
        inps.ref_lalo = inps.coord.radar2geo(inps.ref_yx[0], inps.ref_yx[1], print_msg=False)[0:2]

    # do not plot native reference point if it's out of the coverage due to subset
    if (inps.ref_yx and 'Y_FIRST' in atr.keys()
        and inps.ref_yx == (int(atr.get('REF_Y',-999)), int(atr.get('REF_X',-999)))
        and not (    inps.pix_box[0] <= inps.ref_yx[1] < inps.pix_box[2]
                 and inps.pix_box[1] <= inps.ref_yx[0] < inps.pix_box[3])):
        inps.disp_ref_pixel = False
        print('the native REF_Y/X is out of subset box, thus do not display')

    ## initial pixel coord
    if inps.lalo:
        inps.yx = inps.coord.geo2radar(inps.lalo[0], inps.lalo[1], print_msg=False)[0:2]
    try:
        inps.lalo = inps.coord.radar2geo(inps.yx[0], inps.yx[1], print_msg=False)[0:2]
    except:
        inps.lalo = None

    ## figure settings
    # Flip up-down / left-right
    if inps.auto_flip:
        inps.flip_lr, inps.flip_ud = pp.auto_flip_direction(atr, print_msg=inps.print_msg)

    # Transparency - Alpha
    if not inps.transparency:
        # Auto adjust transparency value when showing shaded relief DEM
        if inps.dem_file and inps.disp_dem_shade:
            inps.transparency = 0.7
        else:
            inps.transparency = 1.0

    ## display unit ans wrap
    # if wrap_step == 2*np.pi (default value), set disp_unit_img = radian;
    # otherwise set disp_unit_img = disp_unit
    inps.disp_unit_img = inps.disp_unit
    if inps.wrap:
        inps.range2phase = -4. * np.pi / float(atr['WAVELENGTH'])
        if   'cm' == inps.disp_unit.split('/')[0]:   inps.range2phase /= 100.
        elif 'mm' == inps.disp_unit.split('/')[0]:   inps.range2phase /= 1000.
        elif 'm'  == inps.disp_unit.split('/')[0]:   inps.range2phase /= 1.
        else:
            raise ValueError('un-recognized display unit: {}'.format(inps.disp_unit))

        if (inps.wrap_range[1] - inps.wrap_range[0]) == 2*np.pi:
            inps.disp_unit_img = 'radian'
        inps.vlim = inps.wrap_range
    inps.cbar_label = 'Displacement [{}]'.format(inps.disp_unit_img)

    ## fit a suite of time func to the time series
    inps.model, inps.num_param = ts2vel.read_inps2model(inps, date_list=inps.date_list)

    # dense TS for plotting
    inps.date_list_fit = ptime.get_date_range(inps.date_list[0], inps.date_list[-1])
    inps.dates_fit = ptime.date_list2vector(inps.date_list_fit)[0]
    inps.G_fit = time_func.get_design_matrix4time_func(
        date_list=inps.date_list_fit,
        model=inps.model,
        seconds=inps.seconds)

    return inps, atr
예제 #7
0
파일: tsview.py 프로젝트: watpet/MintPy
def read_init_info(inps):
    # Time Series Info
    ts_file0 = inps.file[0]
    atr = readfile.read_attribute(ts_file0)
    inps.key = atr['FILE_TYPE']
    if inps.key == 'timeseries':
        obj = timeseries(ts_file0)
    elif inps.key == 'giantTimeseries':
        obj = giantTimeseries(ts_file0)
    elif inps.key == 'HDFEOS':
        obj = HDFEOS(ts_file0)
    else:
        raise ValueError('input file is {}, not timeseries.'.format(inps.key))
    obj.open(print_msg=inps.print_msg)

    if not inps.file_label:
        inps.file_label = [str(i) for i in list(range(len(inps.file)))]

    # default mask file
    if not inps.mask_file and 'masked' not in ts_file0:
        dir_name = os.path.dirname(ts_file0)
        if 'Y_FIRST' in atr.keys():
            inps.mask_file = os.path.join(dir_name, 'geo_maskTempCoh.h5')
        else:
            inps.mask_file = os.path.join(dir_name, 'maskTempCoh.h5')
        if not os.path.isfile(inps.mask_file):
            inps.mask_file = None

    # date info
    inps.date_list = obj.dateList
    inps.num_date = len(inps.date_list)
    if inps.start_date:
        inps.date_list = [
            i for i in inps.date_list if int(i) >= int(inps.start_date)
        ]
    if inps.end_date:
        inps.date_list = [
            i for i in inps.date_list if int(i) <= int(inps.end_date)
        ]
    inps.num_date = len(inps.date_list)
    inps.dates, inps.yearList = ptime.date_list2vector(inps.date_list)
    (inps.ex_date_list, inps.ex_dates,
     inps.ex_flag) = read_exclude_date(inps.ex_date_list, inps.date_list)

    # initial display index
    #if atr['REF_DATE'] in inps.date_list:
    #    inps.ref_idx = inps.date_list.index(atr['REF_DATE'])
    #else:
    #    inps.ref_idx = 0

    if inps.ref_date:
        inps.ref_idx = inps.date_list.index(inps.ref_date)
    else:
        inps.ref_idx = 3

    if not inps.idx:
        if inps.ref_idx < inps.num_date / 2.:
            inps.idx = inps.num_date - 3
        else:
            inps.idx = 3

    # Display Unit
    (inps.disp_unit,
     inps.unit_fac) = pp.scale_data2disp_unit(metadata=atr,
                                              disp_unit=inps.disp_unit)[1:3]

    # Map info - coordinate unit
    inps.coord_unit = atr.get('Y_UNIT', 'degrees').lower()

    # Read Error List
    inps.ts_plot_func = plot_ts_scatter
    inps.error_ts = None
    inps.ex_error_ts = None
    if inps.error_file:
        # assign plot function
        inps.ts_plot_func = plot_ts_errorbar
        # read error file
        error_fc = np.loadtxt(inps.error_file, dtype=bytes).astype(str)
        inps.error_ts = error_fc[:, 1].astype(np.float) * inps.unit_fac
        # update error file with exlcude date
        if inps.ex_date_list:
            e_ts = inps.error_ts[:]
            inps.ex_error_ts = e_ts[inps.ex_flag == 0]
            inps.error_ts = e_ts[inps.ex_flag == 1]

    # Zero displacement for 1st acquisition
    if inps.zero_first:
        inps.zero_idx = min(0, np.min(np.where(inps.ex_flag)[0]))

    # default lookup table file
    if not inps.lookup_file:
        inps.lookup_file = ut.get_lookup_file('./inputs/geometryRadar.h5')
    inps.coord = ut.coordinate(atr, inps.lookup_file)

    # size and lalo info
    inps.pix_box, inps.geo_box = subset.subset_input_dict2box(vars(inps), atr)
    inps.pix_box = inps.coord.check_box_within_data_coverage(inps.pix_box)
    inps.geo_box = inps.coord.box_pixel2geo(inps.pix_box)
    data_box = (0, 0, int(atr['WIDTH']), int(atr['LENGTH']))
    vprint('data   coverage in y/x: ' + str(data_box))
    vprint('subset coverage in y/x: ' + str(inps.pix_box))
    vprint('data   coverage in lat/lon: ' +
           str(inps.coord.box_pixel2geo(data_box)))
    vprint('subset coverage in lat/lon: ' + str(inps.geo_box))
    vprint(
        '------------------------------------------------------------------------'
    )

    # reference pixel
    if not inps.ref_lalo and 'REF_LAT' in atr.keys():
        inps.ref_lalo = (float(atr['REF_LAT']), float(atr['REF_LON']))
    if inps.ref_lalo:
        if inps.ref_lalo[1] > 180.:
            inps.ref_lalo[1] -= 360.
        inps.ref_yx = inps.coord.geo2radar(inps.ref_lalo[0],
                                           inps.ref_lalo[1],
                                           print_msg=False)[0:2]
    if not inps.ref_yx and 'REF_Y' in atr.keys():
        inps.ref_yx = [int(atr['REF_Y']), int(atr['REF_X'])]

    # Initial Pixel Coord
    if inps.lalo:
        inps.yx = inps.coord.geo2radar(inps.lalo[0],
                                       inps.lalo[1],
                                       print_msg=False)[0:2]
    try:
        inps.lalo = inps.coord.radar2geo(inps.yx[0],
                                         inps.yx[1],
                                         print_msg=False)[0:2]
    except:
        inps.lalo = None

    # Flip up-down / left-right
    if inps.auto_flip:
        inps.flip_lr, inps.flip_ud = pp.auto_flip_direction(
            atr, print_msg=inps.print_msg)

    # Transparency - Alpha
    if not inps.transparency:
        # Auto adjust transparency value when showing shaded relief DEM
        if inps.dem_file and inps.disp_dem_shade:
            inps.transparency = 0.7
        else:
            inps.transparency = 1.0

    # display unit ans wrap
    # if wrap_step == 2*np.pi (default value), set disp_unit_img = radian;
    # otherwise set disp_unit_img = disp_unit
    inps.disp_unit_img = inps.disp_unit
    if inps.wrap:
        inps.range2phase = -4. * np.pi / float(atr['WAVELENGTH'])
        if 'cm' == inps.disp_unit.split('/')[0]: inps.range2phase /= 100.
        elif 'mm' == inps.disp_unit.split('/')[0]: inps.range2phase /= 1000.
        elif 'm' == inps.disp_unit.split('/')[0]: inps.range2phase /= 1.
        else:
            raise ValueError('un-recognized display unit: {}'.format(
                inps.disp_unit))

        if (inps.wrap_range[1] - inps.wrap_range[0]) == 2 * np.pi:
            inps.disp_unit_img = 'radian'
        inps.vlim = inps.wrap_range
    inps.cbar_label = 'Displacement [{}]'.format(inps.disp_unit_img)
    return inps, atr
예제 #8
0
def detect_unwrap_error(ifgram_file, mask_file, mask_cc_file='maskConnComp.h5', unwDatasetName='unwrapPhase',
                        cutoff=1., min_num_pixel=1e4):
    """Detect unwrapping error based on phase closure and extract coherent conn comps
    based on its histogram distribution

    Check:
    https://en.wikipedia.org/wiki/Otsu%27s_method
    from skimage.filters import threshold_otsu
    
    Parameters: ifgram_file : string, path of ifgram stack file
                mask_file   : string, path of mask file, e.g. waterMask.h5, maskConnComp.h5
                mask_cc_file: string, path of mask file for coherent conn comps
                cutoff : float, cutoff value for the mean number of nonzero phase closure
                    to be selected as coherent conn comps candidate
                min_num_pixel : float, min number of pixels left after morphology operation
                    to be determined as coherent conn comps
    Returns:    mask_cc_file : string, path of mask file for coherent conn comps
    """
    print('-'*50)
    print('detect unwraping error based on phase closure')
    obj = ifgramStack(ifgram_file)
    obj.open(print_msg=False)
    C = obj.get_design_matrix4triplet(obj.get_date12_list(dropIfgram=False))

    num_nonzero_closure = get_nonzero_phase_closure(ifgram_file, unwDatasetName=unwDatasetName)

    # get histogram of num_nonzero_phase_closure
    mask = readfile.read(mask_file)[0]
    mask *= num_nonzero_closure != 0.

    fig, ax = plt.subplots(nrows=1, ncols=2, figsize=[12, 4])
    num4disp = np.array(num_nonzero_closure, dtype=np.float32)
    num4disp[mask == 0] = np.nan
    im = ax[0].imshow(num4disp)
    ax[0].set_xlabel('Range [pix.]')
    ax[0].set_ylabel('Azimuth [pix.]')
    ax[0] = pp.auto_flip_direction(obj.metadata, ax=ax[0], print_msg=False)
    cbar = fig.colorbar(im, ax=ax[0])
    cbar.set_label('number of non-zero phase closure')

    print('2. extract coherent conn comps with unwrap error based on histogram distribution')
    max_nonzero_closure = int(np.max(num_nonzero_closure[mask]))
    bin_value, bin_edge = ax[1].hist(num_nonzero_closure[mask].flatten(),
                                     range=(0, max_nonzero_closure),
                                     log=True,
                                     bins=max_nonzero_closure)[0:2]
    ax[1].set_xlabel('number of non-zero phase closure')
    ax[1].set_ylabel('number of pixels')

    if 'Closure' not in unwDatasetName:
        print('eliminate pixels with number of nonzero phase closure < 5% of total phase closure number')
        print('\twhich can be corrected using phase closure alone.')
        bin_value[:int(C.shape[0]*0.05)] = 0.
    bin_value_thres = ut.median_abs_deviation_threshold(bin_value, cutoff=cutoff)
    print('median abs deviation cutoff value: {}'.format(cutoff))

    plt.plot([0, max_nonzero_closure], [bin_value_thres, bin_value_thres])
    out_img = 'numUnwErr_stat.png'
    fig.savefig(out_img, bbox_inches='tight', transparent=True, dpi=300)
    print('save unwrap error detection result to {}'.format(out_img))

    # histogram --> candidates of coherence conn comps --> mask_cc
    # find pixel clusters sharing similar number of non-zero phase closure
    print('searching connected components with more than {} pixels'.format(min_num_pixel))
    bin_label, n_bins = ndimage.label(bin_value > bin_value_thres)

    mask_cc = np.zeros(num_nonzero_closure.shape, dtype=np.int16)
    # first conn comp - reference conn comp with zero non-zero phase closure
    num_cc = 1
    mask_cc1 = num_nonzero_closure == 0.
    mask_cc1s = ut.get_all_conn_components(mask_cc1, min_num_pixel=min_num_pixel)
    for mask_cc1 in mask_cc1s:
        mask_cc += mask_cc1

    # other conn comps - target conn comps to be corrected for unwrap error
    for i in range(n_bins):
        idx = np.where(bin_label == i+1)[0]
        mask_cci0 = np.multiply(num_nonzero_closure >= bin_edge[idx[0]],
                                num_nonzero_closure <  bin_edge[idx[-1]+1])
        mask_ccis = ut.get_all_conn_components(mask_cci0, min_num_pixel=min_num_pixel)
        if mask_ccis:
            for mask_cci in mask_ccis:
                num_cc += 1
                mask_cc += mask_cci * num_cc
    
                fig, ax = plt.subplots(nrows=1, ncols=2, figsize=[8, 4])
                im = ax[0].imshow(mask_cci0)
                im = ax[1].imshow(mask_cci)
                fig.savefig('mask_cc{}.png'.format(num_cc),
                            bbox_inches='tight', transparent=True, dpi=300)

    # save to hdf5 file
    num_bridge = num_cc - 1
    atr = dict(obj.metadata)
    atr['FILE_TYPE'] = 'mask'
    atr['UNIT'] = 1
    writefile.write(mask_cc, out_file=mask_cc_file, metadata=atr)

    # plot and save figure to img file
    out_img = '{}.png'.format(os.path.splitext(mask_cc_file)[0])
    fig, ax = plt.subplots(figsize=[6, 8])
    im = ax.imshow(mask_cc)
    ax = pp.auto_flip_direction(atr, ax=ax, print_msg=False)
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", "3%", pad="3%")
    cbar = plt.colorbar(im, cax=cax, ticks=np.arange(num_bridge+2))
    fig.savefig(out_img, bbox_inches='tight', transparent=True, dpi=300)
    print('save to {}'.format(out_img))

    return mask_cc_file
예제 #9
0
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
예제 #10
0
def detect_unwrap_error(ifgram_file,
                        mask_file,
                        mask_cc_file='maskConnComp.h5',
                        unwDatasetName='unwrapPhase',
                        cutoff=1.,
                        min_num_pixel=1e4):
    """Detect unwrapping error based on phase closure and extract coherent conn comps
    based on its histogram distribution

    Check:
    https://en.wikipedia.org/wiki/Otsu%27s_method
    from skimage.filters import threshold_otsu
    
    Parameters: ifgram_file : string, path of ifgram stack file
                mask_file   : string, path of mask file, e.g. waterMask.h5, maskConnComp.h5
                mask_cc_file: string, path of mask file for coherent conn comps
                cutoff : float, cutoff value for the mean number of nonzero phase closure
                    to be selected as coherent conn comps candidate
                min_num_pixel : float, min number of pixels left after morphology operation
                    to be determined as coherent conn comps
    Returns:    mask_cc_file : string, path of mask file for coherent conn comps
    """
    print('-' * 50)
    print('detect unwraping error based on phase closure')
    obj = ifgramStack(ifgram_file)
    obj.open(print_msg=False)
    C = obj.get_design_matrix4triplet(obj.get_date12_list(dropIfgram=False))

    num_nonzero_closure = get_nonzero_phase_closure(
        ifgram_file, unwDatasetName=unwDatasetName)

    # get histogram of num_nonzero_phase_closure
    mask = readfile.read(mask_file)[0]
    mask *= num_nonzero_closure != 0.

    fig, ax = plt.subplots(nrows=1, ncols=2, figsize=[12, 4])
    num4disp = np.array(num_nonzero_closure, dtype=np.float32)
    num4disp[mask == 0] = np.nan
    im = ax[0].imshow(num4disp)
    ax[0].set_xlabel('Range [pix.]')
    ax[0].set_ylabel('Azimuth [pix.]')
    ax[0] = pp.auto_flip_direction(obj.metadata, ax=ax[0], print_msg=False)
    cbar = fig.colorbar(im, ax=ax[0])
    cbar.set_label('number of non-zero phase closure')

    print(
        '2. extract coherent conn comps with unwrap error based on histogram distribution'
    )
    max_nonzero_closure = int(np.max(num_nonzero_closure[mask]))
    bin_value, bin_edge = ax[1].hist(num_nonzero_closure[mask].flatten(),
                                     range=(0, max_nonzero_closure),
                                     log=True,
                                     bins=max_nonzero_closure)[0:2]
    ax[1].set_xlabel('number of non-zero phase closure')
    ax[1].set_ylabel('number of pixels')

    if 'Closure' not in unwDatasetName:
        print(
            'eliminate pixels with number of nonzero phase closure < 5% of total phase closure number'
        )
        print('\twhich can be corrected using phase closure alone.')
        bin_value[:int(C.shape[0] * 0.05)] = 0.
    bin_value_thres = ut.median_abs_deviation_threshold(bin_value,
                                                        cutoff=cutoff)
    print('median abs deviation cutoff value: {}'.format(cutoff))

    plt.plot([0, max_nonzero_closure], [bin_value_thres, bin_value_thres])
    out_img = 'numUnwErr_stat.png'
    fig.savefig(out_img, bbox_inches='tight', transparent=True, dpi=300)
    print('save unwrap error detection result to {}'.format(out_img))

    # histogram --> candidates of coherence conn comps --> mask_cc
    # find pixel clusters sharing similar number of non-zero phase closure
    print('searching connected components with more than {} pixels'.format(
        min_num_pixel))
    bin_label, n_bins = ndimage.label(bin_value > bin_value_thres)

    mask_cc = np.zeros(num_nonzero_closure.shape, dtype=np.int16)
    # first conn comp - reference conn comp with zero non-zero phase closure
    num_cc = 1
    mask_cc1 = num_nonzero_closure == 0.
    mask_cc1s = ut.get_all_conn_components(mask_cc1,
                                           min_num_pixel=min_num_pixel)
    for mask_cc1 in mask_cc1s:
        mask_cc += mask_cc1

    # other conn comps - target conn comps to be corrected for unwrap error
    for i in range(n_bins):
        idx = np.where(bin_label == i + 1)[0]
        mask_cci0 = np.multiply(num_nonzero_closure >= bin_edge[idx[0]],
                                num_nonzero_closure < bin_edge[idx[-1] + 1])
        mask_ccis = ut.get_all_conn_components(mask_cci0,
                                               min_num_pixel=min_num_pixel)
        if mask_ccis:
            for mask_cci in mask_ccis:
                num_cc += 1
                mask_cc += mask_cci * num_cc

                fig, ax = plt.subplots(nrows=1, ncols=2, figsize=[8, 4])
                im = ax[0].imshow(mask_cci0)
                im = ax[1].imshow(mask_cci)
                fig.savefig('mask_cc{}.png'.format(num_cc),
                            bbox_inches='tight',
                            transparent=True,
                            dpi=300)

    # save to hdf5 file
    num_bridge = num_cc - 1
    atr = dict(obj.metadata)
    atr['FILE_TYPE'] = 'mask'
    atr['UNIT'] = 1
    writefile.write(mask_cc, out_file=mask_cc_file, metadata=atr)

    # plot and save figure to img file
    out_img = '{}.png'.format(os.path.splitext(mask_cc_file)[0])
    fig, ax = plt.subplots(figsize=[6, 8])
    im = ax.imshow(mask_cc)
    ax = pp.auto_flip_direction(atr, ax=ax, print_msg=False)
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", "3%", pad="3%")
    cbar = plt.colorbar(im, cax=cax, ticks=np.arange(num_bridge + 2))
    fig.savefig(out_img, bbox_inches='tight', transparent=True, dpi=300)
    print('save to {}'.format(out_img))

    return mask_cc_file