Ejemplo n.º 1
0
def read_baseline_info(baseline_file, reference_file):
    """Read date, bperp and/or DOP info
    Parameters: baseline_file : str, path of bl_list.txt file
                reference_file : str, path of ifgramStack.h5 file
    Returns:    date_list : list of str in YYMMDD format
                tbase_list : list of int in days
                pbase_list : list of float in meter
                dop_list : None, list of 1D array in size of (3,)
    """
    dop_list = None
    if baseline_file:
        date_list, pbase_list, dop_list = pnet.read_baseline_file(
            baseline_file)[0:3]
        date_list = ptime.yymmdd(date_list)
        tbase_list = ptime.date_list2tbase(date_list)[0]

    elif reference_file:
        obj = ifgramStack(reference_file)
        date12_list_all = obj.get_date12_list(dropIfgram=False)
        date12_list_all = ptime.yymmdd_date12(date12_list_all)
        m_dates = [i.split('-')[0] for i in date12_list_all]
        s_dates = [i.split('-')[1] for i in date12_list_all]
        date_list = sorted(list(set(m_dates + s_dates)))
        tbase_list = ptime.date_list2tbase(date_list)[0]

        pbase_list = obj.get_perp_baseline_timeseries(
            dropIfgram=False).tolist()
    return date_list, tbase_list, pbase_list, dop_list
Ejemplo n.º 2
0
def select_pairs_delaunay(date_list, pbase_list, norm=True, date12_format='YYMMDD-YYMMDD'):
    """Select Pairs using Delaunay Triangulation based on temporal/perpendicular baselines
    Inputs:
        date_list  : list of date in YYMMDD/YYYYMMDD format
        pbase_list : list of float, perpendicular spatial baseline
        norm       : normalize temporal baseline to perpendicular baseline
    Key points
        1. Define a ratio between perpendicular and temporal baseline axis units (Pepe and Lanari, 2006, TGRS).
        2. Pairs with too large perpendicular / temporal baseline or Doppler centroid difference should be removed
           after this, using a threshold, to avoid strong decorrelations (Zebker and Villasenor, 1992, TGRS).
    Reference:
        Pepe, A., and R. Lanari (2006), On the extension of the minimum cost flow algorithm for phase unwrapping
        of multitemporal differential SAR interferograms, IEEE TGRS, 44(9), 2374-2383.
        Zebker, H. A., and J. Villasenor (1992), Decorrelation in interferometric radar echoes, IEEE TGRS, 30(5), 950-959.
    """
    # Get temporal baseline in days
    date6_list = ptime.yymmdd(date_list)
    date8_list = ptime.yyyymmdd(date_list)
    tbase_list = ptime.date_list2tbase(date8_list)[0]

    # Normalization (Pepe and Lanari, 2006, TGRS)
    if norm:
        temp2perp_scale = (max(pbase_list)-min(pbase_list)) / (max(tbase_list)-min(tbase_list))
        tbase_list = [tbase*temp2perp_scale for tbase in tbase_list]

    # Generate Delaunay Triangulation
    date12_idx_list = Triangulation(tbase_list, pbase_list).edges.tolist()
    date12_idx_list = [sorted(idx) for idx in sorted(date12_idx_list)]

    # Convert index into date12
    date12_list = [date6_list[idx[0]]+'-'+date6_list[idx[1]]
                   for idx in date12_idx_list]
    if date12_format == 'YYYYMMDD_YYYYMMDD':
        date12_list = ptime.yyyymmdd_date12(date12_list)
    return date12_list
Ejemplo n.º 3
0
def velocity2timeseries(date_list, vel=0.03, display=False):
    '''Simulate displacement time-series from linear velocity
    Inputs:
        date_list - list of string in YYYYMMDD or YYMMDD format
        vel        - float, velocity in meter per year
        display    - bool, display simulation or not
    Output:
        ts         - 2D np.array in size of (date_num,1), displacement time-series in m
    Example:
        date_list = pnet.read_baseline_file('bl_list.txt')[0]
        ts0 = simulate_timeseries(date_list, vel=0.03, display=True)
    '''
    tbase_list = ptime.date_list2tbase(date_list)[0]
    ts = vel / 365.25 * np.array(tbase_list)
    ts = ts.reshape(-1,1)

    if display:
        dates = ptime.date_list2vector(date_list)[0]
        ## Display
        marker_size = 5
        plt.figure()
        plt.scatter(dates, ts*100.0, s=marker_size**2)
        plt.xlabel('Time (years)')
        plt.ylabel('LOS Displacement (cm)')
        plt.title('Displacement time-series with velocity = '+str(vel)+' m/yr')
        plt.show()
    return ts
Ejemplo n.º 4
0
def velocity2timeseries(date_list, vel=0.03, display=False):
    '''Simulate displacement time-series from linear velocity
    Inputs:
        date_list - list of string in YYYYMMDD or YYMMDD format
        vel        - float, velocity in meter per year
        display    - bool, display simulation or not
    Output:
        ts         - 2D np.array in size of (date_num,1), displacement time-series in m
    Example:
        date_list = pnet.read_baseline_file('bl_list.txt')[0]
        ts0 = simulate_timeseries(date_list, vel=0.03, display=True)
    '''
    tbase_list = ptime.date_list2tbase(date_list)[0]
    ts = vel / 365.25 * np.array(tbase_list)
    ts = ts.reshape(-1, 1)

    if display:
        dates = ptime.date_list2vector(date_list)[0]
        ## Display
        marker_size = 5
        plt.figure()
        plt.scatter(dates, ts * 100.0, s=marker_size**2)
        plt.xlabel('time [years]')
        plt.ylabel('LOS displacement [cm]')
        plt.title('displacement time-series with velocity = ' + str(vel) +
                  ' m/yr')
        plt.show()
    return ts
Ejemplo n.º 5
0
def select_master_date(date_list, pbase_list=[]):
    """Select super master date based on input temporal and/or perpendicular baseline info.
    Return master date in YYYYMMDD format.
    """
    date8_list = ptime.yyyymmdd(date_list)
    if not pbase_list:
        # Choose date in the middle
        m_date8 = date8_list[int(len(date8_list)/2)]
    else:
        # Get temporal baseline list
        tbase_list = ptime.date_list2tbase(date8_list)[0]
        # Normalization (Pepe and Lanari, 2006, TGRS)
        temp2perp_scale = (max(pbase_list)-min(pbase_list)) / (max(tbase_list)-min(tbase_list))
        tbase_list = [tbase*temp2perp_scale for tbase in tbase_list]
        # Get distance matrix
        ttMat1, ttMat2 = np.meshgrid(np.array(tbase_list),
                                     np.array(tbase_list))
        ppMat1, ppMat2 = np.meshgrid(np.array(pbase_list),
                                     np.array(pbase_list))
        ttMat = np.abs(ttMat1 - ttMat2)  # temporal distance matrix
        ppMat = np.abs(ppMat1 - ppMat2)  # spatial distance matrix
        # 2D distance matrix in temp/perp domain
        disMat = np.sqrt(np.square(ttMat) + np.square(ppMat))

        # Choose date minimize the total distance of temp/perp baseline
        disMean = np.mean(disMat, 0)
        m_idx = np.argmin(disMean)
        m_date8 = date8_list[m_idx]
    return m_date8
Ejemplo n.º 6
0
def select_pairs_delaunay(date_list, pbase_list, norm=True, date12_format='YYMMDD-YYMMDD'):
    """Select Pairs using Delaunay Triangulation based on temporal/perpendicular baselines
    Inputs:
        date_list  : list of date in YYMMDD/YYYYMMDD format
        pbase_list : list of float, perpendicular spatial baseline
        norm       : normalize temporal baseline to perpendicular baseline
    Key points
        1. Define a ratio between perpendicular and temporal baseline axis units (Pepe and Lanari, 2006, TGRS).
        2. Pairs with too large perpendicular / temporal baseline or Doppler centroid difference should be removed
           after this, using a threshold, to avoid strong decorrelations (Zebker and Villasenor, 1992, TGRS).
    Reference:
        Pepe, A., and R. Lanari (2006), On the extension of the minimum cost flow algorithm for phase unwrapping
        of multitemporal differential SAR interferograms, IEEE TGRS, 44(9), 2374-2383.
        Zebker, H. A., and J. Villasenor (1992), Decorrelation in interferometric radar echoes, IEEE TGRS, 30(5), 950-959.
    """
    # Get temporal baseline in days
    date6_list = ptime.yymmdd(date_list)
    date8_list = ptime.yyyymmdd(date_list)
    tbase_list = ptime.date_list2tbase(date8_list)[0]

    # Normalization (Pepe and Lanari, 2006, TGRS)
    if norm:
        temp2perp_scale = (max(pbase_list)-min(pbase_list)) / (max(tbase_list)-min(tbase_list))
        tbase_list = [tbase*temp2perp_scale for tbase in tbase_list]

    # Generate Delaunay Triangulation
    date12_idx_list = Triangulation(tbase_list, pbase_list).edges.tolist()
    date12_idx_list = [sorted(idx) for idx in sorted(date12_idx_list)]

    # Convert index into date12
    date12_list = [date6_list[idx[0]]+'-'+date6_list[idx[1]]
                   for idx in date12_idx_list]
    if date12_format == 'YYYYMMDD_YYYYMMDD':
        date12_list = ptime.yyyymmdd_date12(date12_list)
    return date12_list
Ejemplo n.º 7
0
def select_master_date(date_list, pbase_list=[]):
    """Select super master date based on input temporal and/or perpendicular baseline info.
    Return master date in YYYYMMDD format.
    """
    date8_list = ptime.yyyymmdd(date_list)
    if not pbase_list:
        # Choose date in the middle
        m_date8 = date8_list[int(len(date8_list) / 2)]
    else:
        # Get temporal baseline list
        tbase_list = ptime.date_list2tbase(date8_list)[0]
        # Normalization (Pepe and Lanari, 2006, TGRS)
        temp2perp_scale = (max(pbase_list) - min(pbase_list)) / (
            max(tbase_list) - min(tbase_list))
        tbase_list = [tbase * temp2perp_scale for tbase in tbase_list]
        # Get distance matrix
        ttMat1, ttMat2 = np.meshgrid(np.array(tbase_list),
                                     np.array(tbase_list))
        ppMat1, ppMat2 = np.meshgrid(np.array(pbase_list),
                                     np.array(pbase_list))
        ttMat = np.abs(ttMat1 - ttMat2)  # temporal distance matrix
        ppMat = np.abs(ppMat1 - ppMat2)  # spatial distance matrix
        # 2D distance matrix in temp/perp domain
        disMat = np.sqrt(np.square(ttMat) + np.square(ppMat))

        # Choose date minimize the total distance of temp/perp baseline
        disMean = np.mean(disMat, 0)
        m_idx = np.argmin(disMean)
        m_date8 = date8_list[m_idx]
    return m_date8
Ejemplo n.º 8
0
def threshold_temporal_baseline(date12_list, btemp_max, keep_seasonal=True, btemp_min=0.0):
    """Remove pairs/interferograms out of min/max/seasonal temporal baseline limits
    Inputs:
        date12_list : list of string for date12 in YYMMDD-YYMMDD format
        btemp_max   : float, maximum temporal baseline
        btemp_min   : float, minimum temporal baseline
        keep_seasonal : keep interferograms with seasonal temporal baseline
    Output:
        date12_list_out : list of string for date12 in YYMMDD-YYMMDD format
    Example:
        date12_list = threshold_temporal_baseline(date12_list, 200)
        date12_list = threshold_temporal_baseline(date12_list, 200, False)
    """
    if not date12_list:
        return []
    # Get date list and tbase list
    m_dates = [date12.split('-')[0] for date12 in date12_list]
    s_dates = [date12.split('-')[1] for date12 in date12_list]
    date8_list = sorted(ptime.yyyymmdd(list(set(m_dates + s_dates))))
    date6_list = ptime.yymmdd(date8_list)
    tbase_list = ptime.date_list2tbase(date8_list)[0]

    # Threshold
    date12_list_out = []
    for date12 in date12_list:
        date1, date2 = date12.split('-')
        idx1 = date6_list.index(date1)
        idx2 = date6_list.index(date2)
        tbase = int(abs(tbase_list[idx1] - tbase_list[idx2]))
        if btemp_min <= tbase <= btemp_max:
            date12_list_out.append(date12)
        elif keep_seasonal and tbase/30 in [11, 12]:
            date12_list_out.append(date12)
    return date12_list_out
Ejemplo n.º 9
0
def threshold_temporal_baseline(date12_list, btemp_max, keep_seasonal=True, btemp_min=0.0):
    """Remove pairs/interferograms out of min/max/seasonal temporal baseline limits
    Inputs:
        date12_list : list of string for date12 in YYMMDD-YYMMDD format
        btemp_max   : float, maximum temporal baseline
        btemp_min   : float, minimum temporal baseline
        keep_seasonal : keep interferograms with seasonal temporal baseline
    Output:
        date12_list_out : list of string for date12 in YYMMDD-YYMMDD format
    Example:
        date12_list = threshold_temporal_baseline(date12_list, 200)
        date12_list = threshold_temporal_baseline(date12_list, 200, False)
    """
    if not date12_list:
        return []
    # Get date list and tbase list
    m_dates = [date12.split('-')[0] for date12 in date12_list]
    s_dates = [date12.split('-')[1] for date12 in date12_list]
    date8_list = sorted(ptime.yyyymmdd(list(set(m_dates + s_dates))))
    date6_list = ptime.yymmdd(date8_list)
    tbase_list = ptime.date_list2tbase(date8_list)[0]

    # Threshold
    date12_list_out = []
    for date12 in date12_list:
        date1, date2 = date12.split('-')
        idx1 = date6_list.index(date1)
        idx2 = date6_list.index(date2)
        tbase = int(abs(tbase_list[idx1] - tbase_list[idx2]))
        if btemp_min <= tbase <= btemp_max:
            date12_list_out.append(date12)
        elif keep_seasonal and tbase/30 in [11, 12]:
            date12_list_out.append(date12)
    return date12_list_out
Ejemplo n.º 10
0
def simulate_coherence_v2(date12_list,
                          decor_time=200.0,
                          coh_resid=0.2,
                          inc_angle=40,
                          sensor_name='Sen',
                          display=False):
    """Simulate coherence version 2 (without using bl_list.txt file).
    Parameters: date12_list - list of string in YYYYMMDD_YYYYMMDD format, indicating pairs configuration
                decor_time  - float, decorrelation rate in days, time for coherence to drop to 1/e of its initial value
                coh_resid   - float, long-term coherence, minimum attainable coherence value
                inc_angle   - float, incidence angle in degrees
                sensor_name - string, SAR sensor name
                display     - bool, display result as matrix or not
    Returns:    coh         - 2D np.array in size of (ifgram_num)
    """
    num_pair = len(date12_list)
    date1s = [x.split('_')[0] for x in date12_list]
    date2s = [x.split('_')[1] for x in date12_list]
    date_list = sorted(list(set(date1s + date2s)))
    tbase_list = ptime.date_list2tbase(date_list)[0]

    SNR = 22  # NESZ = -22 dB from Table 1 in https://sentinels.copernicus.eu/web/sentinel/
    coh_thermal = 1. / (1. + 1. / SNR)

    # bperp
    rng = np.random.default_rng(2)
    pbase_list = rng.normal(0, 50, num_pair).tolist()
    pbase_c = critical_perp_baseline(sensor_name, inc_angle)

    coh = np.zeros(num_pair, dtype=np.float32)
    for i in range(num_pair):
        date1, date2 = date12_list[i].split('_')
        ind1, ind2 = date_list.index(date1), date_list.index(date2)
        tbase = tbase_list[ind2] - tbase_list[ind1]
        pbase = pbase_list[ind2] - pbase_list[ind1]

        coh_geom = (pbase_c - abs(pbase)) / pbase_c
        coh_temp = np.multiply(
            (coh_thermal - coh_resid), np.exp(
                -1 * abs(tbase) / decor_time)) + coh_resid
        coh[i] = coh_geom * coh_temp

    if display:
        print(('critical perp baseline: %.f m' % pbase_c))
        coh_mat = coherence_matrix(date12_list, coh)
        plt.figure()
        plt.imshow(coh_mat, vmin=0.0, vmax=1.0, cmap='jet')
        plt.xlabel('Image number')
        plt.ylabel('Image number')
        cbar = plt.colorbar()
        cbar.set_label('Coherence')
        plt.title('Coherence matrix')
        plt.show()

    return coh
Ejemplo n.º 11
0
def select_master_interferogram(date12_list,
                                date_list,
                                pbase_list,
                                m_date=None):
    """Select reference interferogram based on input temp/perp baseline info
    If master_date is specified, select its closest slave_date, which is newer than master_date;
        otherwise, choose the closest pair among all pairs as master interferogram.
    Example:
        master_date12   = pnet.select_master_ifgram(date12_list, date_list, pbase_list)
        '080211-080326' = pnet.select_master_ifgram(date12_list, date_list, pbase_list, m_date='080211')
    """
    pbase_array = np.array(pbase_list, dtype='float64')
    # Get temporal baseline
    date8_list = ptime.yyyymmdd(date_list)
    date6_list = ptime.yymmdd(date8_list)
    tbase_array = np.array(ptime.date_list2tbase(date8_list)[0],
                           dtype='float64')
    # Normalization (Pepe and Lanari, 2006, TGRS)
    temp2perp_scale = (max(pbase_array) - min(pbase_array)) / (
        max(tbase_array) - min(tbase_array))
    tbase_array *= temp2perp_scale

    # Calculate sqrt of temp/perp baseline for input pairs
    idx1 = np.array(
        [date6_list.index(date12.split('-')[0]) for date12 in date12_list])
    idx2 = np.array(
        [date6_list.index(date12.split('-')[1]) for date12 in date12_list])
    base_distance = np.sqrt((tbase_array[idx2] - tbase_array[idx1])**2 +
                            (pbase_array[idx2] - pbase_array[idx1])**2)

    # Get master interferogram index
    if not m_date:
        # Choose pair with shortest temp/perp baseline
        m_date12_idx = np.argmin(base_distance)
    else:
        m_date = ptime.yymmdd(m_date)
        # Choose pair contains m_date with shortest temp/perp baseline
        m_date12_idx_array = np.array([
            date12_list.index(date12) for date12 in date12_list
            if m_date + '-' in date12
        ])
        min_base_distance = np.min(base_distance[m_date12_idx_array])
        m_date12_idx = np.where(base_distance == min_base_distance)[0][0]

    m_date12 = date12_list[m_date12_idx]
    return m_date12
Ejemplo n.º 12
0
def select_pairs_mst(date_list, pbase_list, date12_format='YYMMDD-YYMMDD'):
    """Select Pairs using Minimum Spanning Tree technique
        Connection Cost is calculated using the baseline distance in perp and scaled temporal baseline (Pepe and Lanari,
        2006, TGRS) plane.
    Inputs:
        date_list  : list of date in YYMMDD/YYYYMMDD format
        pbase_list : list of float, perpendicular spatial baseline
    References:
        Pepe, A., and R. Lanari (2006), On the extension of the minimum cost flow algorithm for phase unwrapping
        of multitemporal differential SAR interferograms, IEEE TGRS, 44(9), 2374-2383.
        Perissin D., Wang T. (2012), Repeat-pass SAR interferometry with partially coherent targets. IEEE TGRS. 271-280
    """
    # Get temporal baseline in days
    date6_list = ptime.yymmdd(date_list)
    date8_list = ptime.yyyymmdd(date_list)
    tbase_list = ptime.date_list2tbase(date8_list)[0]
    # Normalization (Pepe and Lanari, 2006, TGRS)
    temp2perp_scale = (max(pbase_list) - min(pbase_list)) / (max(tbase_list) -
                                                             min(tbase_list))
    tbase_list = [tbase * temp2perp_scale for tbase in tbase_list]

    # Get weight matrix
    ttMat1, ttMat2 = np.meshgrid(np.array(tbase_list), np.array(tbase_list))
    ppMat1, ppMat2 = np.meshgrid(np.array(pbase_list), np.array(pbase_list))
    ttMat = np.abs(ttMat1 - ttMat2)  # temporal distance matrix
    ppMat = np.abs(ppMat1 - ppMat2)  # spatial distance matrix

    # 2D distance matrix in temp/perp domain
    weightMat = np.sqrt(np.square(ttMat) + np.square(ppMat))
    weightMat = sparse.csr_matrix(weightMat)  # compress sparse row matrix

    # MST path based on weight matrix
    mstMat = sparse.csgraph.minimum_spanning_tree(weightMat)

    # Convert MST index matrix into date12 list
    [s_idx_list, m_idx_list] = [
        date_idx_array.tolist() for date_idx_array in sparse.find(mstMat)[0:2]
    ]
    date12_list = []
    for i in range(len(m_idx_list)):
        idx = sorted([m_idx_list[i], s_idx_list[i]])
        date12 = date6_list[idx[0]] + '-' + date6_list[idx[1]]
        date12_list.append(date12)
    if date12_format == 'YYYYMMDD_YYYYMMDD':
        date12_list = ptime.yyyymmdd_date12(date12_list)
    return date12_list
Ejemplo n.º 13
0
def select_pairs_mst(date_list, pbase_list, date12_format='YYMMDD-YYMMDD'):
    """Select Pairs using Minimum Spanning Tree technique
        Connection Cost is calculated using the baseline distance in perp and scaled temporal baseline (Pepe and Lanari,
        2006, TGRS) plane.
    Inputs:
        date_list  : list of date in YYMMDD/YYYYMMDD format
        pbase_list : list of float, perpendicular spatial baseline
    References:
        Pepe, A., and R. Lanari (2006), On the extension of the minimum cost flow algorithm for phase unwrapping
        of multitemporal differential SAR interferograms, IEEE TGRS, 44(9), 2374-2383.
        Perissin D., Wang T. (2012), Repeat-pass SAR interferometry with partially coherent targets. IEEE TGRS. 271-280
    """
    # Get temporal baseline in days
    date6_list = ptime.yymmdd(date_list)
    date8_list = ptime.yyyymmdd(date_list)
    tbase_list = ptime.date_list2tbase(date8_list)[0]
    # Normalization (Pepe and Lanari, 2006, TGRS)
    temp2perp_scale = (max(pbase_list)-min(pbase_list)) / (max(tbase_list)-min(tbase_list))
    tbase_list = [tbase*temp2perp_scale for tbase in tbase_list]

    # Get weight matrix
    ttMat1, ttMat2 = np.meshgrid(np.array(tbase_list), np.array(tbase_list))
    ppMat1, ppMat2 = np.meshgrid(np.array(pbase_list), np.array(pbase_list))
    ttMat = np.abs(ttMat1 - ttMat2)  # temporal distance matrix
    ppMat = np.abs(ppMat1 - ppMat2)  # spatial distance matrix

    # 2D distance matrix in temp/perp domain
    weightMat = np.sqrt(np.square(ttMat) + np.square(ppMat))
    weightMat = sparse.csr_matrix(weightMat)  # compress sparse row matrix

    # MST path based on weight matrix
    mstMat = sparse.csgraph.minimum_spanning_tree(weightMat)

    # Convert MST index matrix into date12 list
    [s_idx_list, m_idx_list] = [date_idx_array.tolist()
                                for date_idx_array in sparse.find(mstMat)[0:2]]
    date12_list = []
    for i in range(len(m_idx_list)):
        idx = sorted([m_idx_list[i], s_idx_list[i]])
        date12 = date6_list[idx[0]]+'-'+date6_list[idx[1]]
        date12_list.append(date12)
    if date12_format == 'YYYYMMDD_YYYYMMDD':
        date12_list = ptime.yyyymmdd_date12(date12_list)
    return date12_list
Ejemplo n.º 14
0
def get_design_matrix4time_func(date_list, poly_order=2, step_func_dates=[]):
    """get design matrix for temporal deformation model"""
    # temporal baseline in the unit of years
    tbase = ptime.date_list2tbase(date_list)[0]
    tbase = np.array(tbase, dtype=np.float32) / 365.25

    # 1. Polynomial - 2D matrix in size of (numDate, polyOrder+1)
    A_def = np.ones((len(date_list), 1), np.float32)
    for i in range(poly_order):
        Ai = np.array(tbase**(i + 1) / gamma(i + 2), np.float32).reshape(-1, 1)
        A_def = np.hstack((A_def, Ai))

    # 2. Step function - 2D matrix in size of (numDate, len(step_func_dates))
    if step_func_dates:
        t_steps = ptime.yyyymmdd2years(step_func_dates)
        t = np.array(ptime.yyyymmdd2years(date_list))
        for t_step in t_steps:
            Ai = np.array(t > t_step, np.float32).reshape(-1, 1)
            A_def = np.hstack((A_def, Ai))

    return A_def
Ejemplo n.º 15
0
def select_master_interferogram(date12_list, date_list, pbase_list, m_date=None):
    """Select reference interferogram based on input temp/perp baseline info
    If master_date is specified, select its closest slave_date, which is newer than master_date;
        otherwise, choose the closest pair among all pairs as master interferogram.
    Example:
        master_date12   = pnet.select_master_ifgram(date12_list, date_list, pbase_list)
        '080211-080326' = pnet.select_master_ifgram(date12_list, date_list, pbase_list, m_date='080211')
    """
    pbase_array = np.array(pbase_list, dtype='float64')
    # Get temporal baseline
    date8_list = ptime.yyyymmdd(date_list)
    date6_list = ptime.yymmdd(date8_list)
    tbase_array = np.array(ptime.date_list2tbase(date8_list)[0], dtype='float64')
    # Normalization (Pepe and Lanari, 2006, TGRS)
    temp2perp_scale = (max(pbase_array)-min(pbase_array)) / (max(tbase_array)-min(tbase_array))
    tbase_array *= temp2perp_scale

    # Calculate sqrt of temp/perp baseline for input pairs
    idx1 = np.array([date6_list.index(date12.split('-')[0]) for date12 in date12_list])
    idx2 = np.array([date6_list.index(date12.split('-')[1]) for date12 in date12_list])
    base_distance = np.sqrt((tbase_array[idx2] - tbase_array[idx1])**2 +
                            (pbase_array[idx2] - pbase_array[idx1])**2)

    # Get master interferogram index
    if not m_date:
        # Choose pair with shortest temp/perp baseline
        m_date12_idx = np.argmin(base_distance)
    else:
        m_date = ptime.yymmdd(m_date)
        # Choose pair contains m_date with shortest temp/perp baseline
        m_date12_idx_array = np.array([date12_list.index(date12) for date12 in date12_list
                                       if m_date+'-' in date12])
        min_base_distance = np.min(base_distance[m_date12_idx_array])
        m_date12_idx = np.where(base_distance == min_base_distance)[0][0]

    m_date12 = date12_list[m_date12_idx]
    return m_date12
Ejemplo n.º 16
0
def ifgram_inversion_patch(ifgram_file,
                           box=None,
                           ref_phase=None,
                           obs_ds_name='unwrapPhase',
                           weight_func='var',
                           water_mask_file=None,
                           min_norm_velocity=True,
                           mask_ds_name=None,
                           mask_threshold=0.4,
                           min_redundancy=1.0):
    """Invert one patch of an ifgram stack into timeseries.

    Parameters: box               - tuple of 4 int, indicating (x0, y0, x1, y1) of the area of interest
                                    or None for the whole image
                ifgram_file       - str, interferograms stack HDF5 file, e.g. ./inputs/ifgramStack.h5
                ref_phase         - 1D array in size of (num_ifgram), or None
                obs_ds_name       - str, dataset to feed the inversion.
                weight_func       - str, weight function, choose in ['no', 'fim', 'var', 'coh']
                water_mask_file   - str, water mask filename if available, to skip inversion on water
                min_norm_velocity - bool, minimize the residual phase or phase velocity
                mask_ds_name      - str, dataset name in ifgram_file used to mask unwrapPhase pixelwisely
                mask_threshold    - float, min coherence of pixels if mask_dataset_name='coherence'
                min_redundancy    - float, the min number of ifgrams for every acquisition.
    Returns:    ts                - 3D array in size of (num_date, num_row, num_col)
                temp_coh          - 2D array in size of (num_row, num_col)
                num_inv_ifg       - 2D array in size of (num_row, num_col)
                box               - tuple of 4 int
    Example:    ifgram_inversion_patch('ifgramStack.h5', box=(0,200,1316,400))
    """

    stack_obj = ifgramStack(ifgram_file)
    stack_obj.open(print_msg=False)

    # debug
    #y, x = 258, 454
    #box = (x, y, x+1, y+1)

    ## 1. input info

    # size
    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

    # get tbase_diff
    date_list = stack_obj.get_date_list(dropIfgram=True)
    num_date = len(date_list)
    tbase = np.array(ptime.date_list2tbase(date_list)[0], np.float32) / 365.25
    tbase_diff = np.diff(tbase).reshape(-1, 1)

    # design matrix
    date12_list = stack_obj.get_date12_list(dropIfgram=True)
    A, B = stack_obj.get_design_matrix4timeseries(date12_list=date12_list)[0:2]

    # prep for decor std time-series
    #if os.path.isfile('reference_date.txt'):
    #    ref_date = str(np.loadtxt('reference_date.txt', dtype=bytes).astype(str))
    #else:
    #    ref_date = date_list[0]
    #Astd = stack_obj.get_design_matrix4timeseries(date12_list=date12_list, refDate=ref_date)[0]
    #ref_idx = date_list.index(ref_date)
    #time_idx = [i for i in range(num_date)]
    #time_idx.remove(ref_idx)

    # skip zero value in the network inversion for phase
    if 'phase' in obs_ds_name.lower():
        skip_zero_value = True
    else:
        skip_zero_value = False

    # 1.1 read / calcualte weight
    if weight_func in ['no', 'sbas']:
        weight = None
    else:
        weight = calc_weight(stack_obj,
                             box,
                             weight_func=weight_func,
                             dropIfgram=True,
                             chunk_size=100000)

    # 1.2 read / mask unwrapPhase / offset
    pha_data = read_unwrap_phase(stack_obj,
                                 box,
                                 ref_phase,
                                 obs_ds_name=obs_ds_name,
                                 dropIfgram=True)

    pha_data = mask_unwrap_phase(pha_data,
                                 stack_obj,
                                 box,
                                 dropIfgram=True,
                                 mask_ds_name=mask_ds_name,
                                 mask_threshold=mask_threshold)

    # 1.3 mask of pixels to invert
    mask = np.ones(num_pixel, np.bool_)

    # 1.3.1 - Water Mask
    if water_mask_file:
        print('skip pixels on water with mask from file: {}'.format(
            os.path.basename(water_mask_file)))
        atr_msk = readfile.read_attribute(water_mask_file)
        len_msk, wid_msk = int(atr_msk['LENGTH']), int(atr_msk['WIDTH'])
        if (len_msk, wid_msk) != (stack_obj.length, stack_obj.width):
            raise ValueError(
                'Input water mask file has different size from ifgramStack file.'
            )

        dsName = [
            i for i in readfile.get_dataset_list(water_mask_file)
            if i in ['waterMask', 'mask']
        ][0]
        waterMask = readfile.read(water_mask_file, datasetName=dsName,
                                  box=box)[0].flatten()
        mask *= np.array(waterMask, dtype=np.bool_)
        del waterMask

    # 1.3.2 - Mask for Zero Phase in ALL ifgrams
    if 'phase' in obs_ds_name.lower():
        print('skip pixels with zero/nan value in all interferograms')
        with warnings.catch_warnings():
            # ignore warning message for all-NaN slices
            warnings.simplefilter("ignore", category=RuntimeWarning)
            phase_stack = np.nanmean(pha_data, axis=0)
        mask *= np.multiply(~np.isnan(phase_stack), phase_stack != 0.)
        del phase_stack

    # 1.3.3 invert pixels on mask 1+2
    num_pixel2inv = int(np.sum(mask))
    idx_pixel2inv = np.where(mask)[0]
    print('number of pixels to invert: {} out of {} ({:.1f}%)'.format(
        num_pixel2inv, num_pixel, num_pixel2inv / num_pixel * 100))

    ## 2. inversion

    # 2.1 initiale the output matrices
    ts = np.zeros((num_date, num_pixel), np.float32)
    #ts_std = np.zeros((num_date, num_pixel), np.float32)
    temp_coh = np.zeros(num_pixel, np.float32)
    num_inv_ifg = np.zeros(num_pixel, np.int16)

    # return directly if there is nothing to invert
    if num_pixel2inv < 1:
        ts = ts.reshape(num_date, num_row, num_col)
        #ts_std = ts_std.reshape(num_date, num_row, num_col)
        temp_coh = temp_coh.reshape(num_row, num_col)
        num_inv_ifg = num_inv_ifg.reshape(num_row, num_col)
        return ts, temp_coh, num_inv_ifg

    # 2.2 un-weighted inversion (classic SBAS)
    if weight_func in ['no', 'sbas']:

        # a. mask for Non-Zero Phase in ALL ifgrams (share one B in sbas inversion)
        if 'phase' in obs_ds_name.lower():
            mask_all_net = np.all(pha_data, axis=0)
            mask_all_net *= mask
        else:
            mask_all_net = np.array(mask)
        mask_part_net = mask ^ mask_all_net
        del mask

        # b. invert once for all pixels with obs in all ifgrams
        if np.sum(mask_all_net) > 0:
            print(('inverting pixels with valid phase in all  ifgrams'
                   ' ({:.0f} pixels) ...').format(np.sum(mask_all_net)))
            tsi, tcohi, num_ifgi = estimate_timeseries(
                A,
                B,
                tbase_diff,
                ifgram=pha_data[:, mask_all_net],
                weight_sqrt=None,
                min_norm_velocity=min_norm_velocity,
                min_redundancy=min_redundancy,
                skip_zero_value=skip_zero_value)
            ts[:, mask_all_net] = tsi
            temp_coh[mask_all_net] = tcohi
            num_inv_ifg[mask_all_net] = num_ifgi

        # c. pixel-by-pixel for pixels with obs not in all ifgrams
        if np.sum(mask_part_net) > 0:
            print(('inverting pixels with valid phase in some ifgrams'
                   ' ({:.0f} pixels) ...').format(np.sum(mask_part_net)))
            num_pixel2inv = int(np.sum(mask_part_net))
            idx_pixel2inv = np.where(mask_part_net)[0]
            prog_bar = ptime.progressBar(maxValue=num_pixel2inv)
            for i in range(num_pixel2inv):
                idx = idx_pixel2inv[i]
                tsi, tcohi, num_ifgi = estimate_timeseries(
                    A,
                    B,
                    tbase_diff,
                    ifgram=pha_data[:, idx],
                    weight_sqrt=None,
                    min_norm_velocity=min_norm_velocity,
                    min_redundancy=min_redundancy,
                    skip_zero_value=skip_zero_value)
                ts[:, idx] = tsi.flatten()
                temp_coh[idx] = tcohi
                num_inv_ifg[idx] = num_ifgi
                prog_bar.update(i + 1,
                                every=2000,
                                suffix='{}/{} pixels'.format(
                                    i + 1, num_pixel2inv))
            prog_bar.close()

    # 2.3 weighted inversion - pixel-by-pixel
    else:
        print('inverting network of interferograms into time-series ...')
        prog_bar = ptime.progressBar(maxValue=num_pixel2inv)
        for i in range(num_pixel2inv):
            idx = idx_pixel2inv[i]
            tsi, tcohi, num_ifgi = estimate_timeseries(
                A,
                B,
                tbase_diff,
                ifgram=pha_data[:, idx],
                weight_sqrt=weight[:, idx],
                min_norm_velocity=min_norm_velocity,
                min_redundancy=min_redundancy,
                skip_zero_value=skip_zero_value)
            ts[:, idx] = tsi.flatten()
            temp_coh[idx] = tcohi
            num_inv_ifg[idx] = num_ifgi

            prog_bar.update(i + 1,
                            every=2000,
                            suffix='{}/{} pixels'.format(i + 1, num_pixel2inv))
        prog_bar.close()
        del weight
    del pha_data

    ## 3. prepare output

    # 3.1 reshape
    ts = ts.reshape(num_date, num_row, num_col)
    #ts_std = ts_std.reshape(num_date, num_row, num_col)
    temp_coh = temp_coh.reshape(num_row, num_col)
    num_inv_ifg = num_inv_ifg.reshape(num_row, num_col)

    # 3.2 convert displacement unit to meter
    if obs_ds_name.startswith('unwrapPhase'):
        phase2range = -1 * float(
            stack_obj.metadata['WAVELENGTH']) / (4. * np.pi)
        ts *= phase2range
        print('converting LOS phase unit from radian to meter')

    elif obs_ds_name == 'azimuthOffset':
        az_pixel_size = ut.azimuth_ground_resolution(stack_obj.metadata)
        ts *= az_pixel_size
        print('converting azimuth offset unit from pixel ({:.2f} m) to meter'.
              format(az_pixel_size))

    elif obs_ds_name == 'rangeOffset':
        rg_pixel_size = float(stack_obj.metadata['RANGE_PIXEL_SIZE'])
        ts *= rg_pixel_size
        print('converting range offset unit from pixel ({:.2f} m) to meter'.
              format(rg_pixel_size))

    return ts, temp_coh, num_inv_ifg, box
Ejemplo n.º 17
0
def simulate_coherence(date12_list, baseline_file='bl_list.txt', sensor_name='Env', inc_angle=22.8,
                       decor_time=200.0, coh_resid=0.2, display=False):
    """Simulate coherence for a given set of interferograms
    Inputs:
        date12_list  - list of string in YYMMDD-YYMMDD format, indicating pairs configuration
        baseline_file - string, path of baseline list text file
        sensor_name     - string, SAR sensor name
        inc_angle  - float, incidence angle
        decor_time - float / 2D np.array in size of (1, pixel_num)
                     decorrelation rate in days, time for coherence to drop to 1/e of its initial value
        coh_resid  - float / 2D np.array in size of (1, pixel_num)
                     long-term coherence, minimum attainable coherence value
        display    - bool, display result as matrix or not
    Output:
        cohs       - 2D np.array in size of (ifgram_num, pixel_num)
    Example:
        date12_list = pnet.get_date12_list('ifgram_list.txt')
        cohs = simulate_coherences(date12_list, 'bl_list.txt', sensor_name='Tsx')

    References:
        Zebker, H. A., & Villasenor, J. (1992). Decorrelation in interferometric radar echoes.
            IEEE-TGRS, 30(5), 950-959. 
        Hanssen, R. F. (2001). Radar interferometry: data interpretation and error analysis
            (Vol. 2). Dordrecht, Netherlands: Kluwer Academic Pub.
        Morishita, Y., & Hanssen, R. F. (2015). Temporal decorrelation in L-, C-, and X-band satellite
            radar interferometry for pasture on drained peat soils. IEEE-TGRS, 53(2), 1096-1104. 
        Parizzi, A., Cong, X., & Eineder, M. (2009). First Results from Multifrequency Interferometry.
            A comparison of different decorrelation time constants at L, C, and X Band. ESA Scientific
            Publications(SP-677), 1-5. 
    """
    date_list, pbase_list, dop_list = read_baseline_file(baseline_file)[0:3]
    tbase_list = ptime.date_list2tbase(date_list)[0]

    # Thermal decorrelation (Zebker and Villasenor, 1992, Eq.4)
    SNR = sensor.signal2noise_ratio(sensor_name)
    coh_thermal = 1. / (1. + 1./SNR)

    pbase_c = critical_perp_baseline(sensor_name, inc_angle)
    bandwidth_az = sensor.azimuth_bandwidth(sensor_name)

    date12_list = ptime.yyyymmdd_date12(date12_list)
    ifgram_num = len(date12_list)

    if isinstance(decor_time, (int, float)):
        pixel_num = 1
        decor_time = float(decor_time)
    else:
        pixel_num = decor_time.shape[1]
    if decor_time == 0.:
        decor_time = 0.01
    cohs = np.zeros((ifgram_num, pixel_num), np.float32)
    for i in range(ifgram_num):
        if display:
            sys.stdout.write('\rinterferogram = %4d/%4d' % (i, ifgram_num))
            sys.stdout.flush()
        m_date, s_date = date12_list[i].split('_')
        m_idx = date_list.index(m_date)
        s_idx = date_list.index(s_date)

        pbase = pbase_list[s_idx] - pbase_list[m_idx]
        tbase = tbase_list[s_idx] - tbase_list[m_idx]

        # Geometric decorrelation (Hanssen, 2001, Eq. 4.4.12)
        coh_geom = (pbase_c - abs(pbase)) / pbase_c
        if coh_geom < 0.:
            coh_geom = 0.

        # Doppler centroid decorrelation (Hanssen, 2001, Eq. 4.4.13)
        if not dop_list:
            coh_dc = 1.
        else:
            coh_dc = calculate_doppler_overlap(dop_list[m_idx],
                                               dop_list[s_idx],
                                               bandwidth_az)
            if coh_dc < 0.:
                coh_dc = 0.

        # Option 1: Temporal decorrelation - exponential delay model (Parizzi et al., 2009; Morishita and Hanssen, 2015)
        coh_temp = np.multiply((coh_thermal - coh_resid), np.exp(-1*abs(tbase)/decor_time)) + coh_resid

        coh = coh_geom * coh_dc * coh_temp
        cohs[i, :] = coh
    #epsilon = 1e-3
    #cohs[cohs < epsilon] = epsilon
    if display:
        print('')

    if display:
        print(('critical perp baseline: %.f m' % pbase_c))
        cohs_mat = coherence_matrix(date12_list, cohs)
        plt.figure()
        plt.imshow(cohs_mat, vmin=0.0, vmax=1.0, cmap='jet')
        plt.xlabel('Image number')
        plt.ylabel('Image number')
        cbar = plt.colorbar()
        cbar.set_label('Coherence')
        plt.title('Coherence matrix')
        plt.show()
    return cohs
Ejemplo n.º 18
0
def simulate_coherence(date12_list,
                       baseline_file='bl_list.txt',
                       sensor_name='Env',
                       inc_angle=22.8,
                       decor_time=200.0,
                       coh_resid=0.2,
                       display=False):
    """Simulate coherence for a given set of interferograms
    Inputs:
        date12_list  - list of string in YYMMDD-YYMMDD format, indicating pairs configuration
        baseline_file - string, path of baseline list text file
        sensor_name     - string, SAR sensor name
        inc_angle  - float, incidence angle
        decor_time - float / 2D np.array in size of (1, pixel_num)
                     decorrelation rate in days, time for coherence to drop to 1/e of its initial value
        coh_resid  - float / 2D np.array in size of (1, pixel_num)
                     long-term coherence, minimum attainable coherence value
        display    - bool, display result as matrix or not
    Output:
        cohs       - 2D np.array in size of (ifgram_num, pixel_num)
    Example:
        date12_list = pnet.get_date12_list('ifgram_list.txt')
        cohs = simulate_coherences(date12_list, 'bl_list.txt', sensor_name='Tsx')

    References:
        Zebker, H. A., & Villasenor, J. (1992). Decorrelation in interferometric radar echoes.
            IEEE-TGRS, 30(5), 950-959. 
        Hanssen, R. F. (2001). Radar interferometry: data interpretation and error analysis
            (Vol. 2). Dordrecht, Netherlands: Kluwer Academic Pub.
        Morishita, Y., & Hanssen, R. F. (2015). Temporal decorrelation in L-, C-, and X-band satellite
            radar interferometry for pasture on drained peat soils. IEEE-TGRS, 53(2), 1096-1104. 
        Parizzi, A., Cong, X., & Eineder, M. (2009). First Results from Multifrequency Interferometry.
            A comparison of different decorrelation time constants at L, C, and X Band. ESA Scientific
            Publications(SP-677), 1-5. 
    """
    date_list, pbase_list, dop_list = read_baseline_file(baseline_file)[0:3]
    tbase_list = ptime.date_list2tbase(date_list)[0]

    # Thermal decorrelation (Zebker and Villasenor, 1992, Eq.4)
    SNR = sensor.signal2noise_ratio(sensor_name)
    coh_thermal = 1. / (1. + 1. / SNR)

    pbase_c = critical_perp_baseline(sensor_name, inc_angle)
    bandwidth_az = sensor.azimuth_bandwidth(sensor_name)

    date12_list = ptime.yyyymmdd_date12(date12_list)
    ifgram_num = len(date12_list)

    if isinstance(decor_time, (int, float)):
        pixel_num = 1
        decor_time = float(decor_time)
    else:
        pixel_num = decor_time.shape[1]
    if decor_time == 0.:
        decor_time = 0.01
    cohs = np.zeros((ifgram_num, pixel_num), np.float32)
    for i in range(ifgram_num):
        if display:
            sys.stdout.write('\rinterferogram = %4d/%4d' % (i, ifgram_num))
            sys.stdout.flush()
        m_date, s_date = date12_list[i].split('_')
        m_idx = date_list.index(m_date)
        s_idx = date_list.index(s_date)

        pbase = pbase_list[s_idx] - pbase_list[m_idx]
        tbase = tbase_list[s_idx] - tbase_list[m_idx]

        # Geometric decorrelation (Hanssen, 2001, Eq. 4.4.12)
        coh_geom = (pbase_c - abs(pbase)) / pbase_c
        if coh_geom < 0.:
            coh_geom = 0.

        # Doppler centroid decorrelation (Hanssen, 2001, Eq. 4.4.13)
        if not dop_list:
            coh_dc = 1.
        else:
            coh_dc = calculate_doppler_overlap(dop_list[m_idx],
                                               dop_list[s_idx], bandwidth_az)
            if coh_dc < 0.:
                coh_dc = 0.

        # Option 1: Temporal decorrelation - exponential delay model (Parizzi et al., 2009; Morishita and Hanssen, 2015)
        coh_temp = np.multiply(
            (coh_thermal - coh_resid), np.exp(
                -1 * abs(tbase) / decor_time)) + coh_resid

        coh = coh_geom * coh_dc * coh_temp
        cohs[i, :] = coh
    #epsilon = 1e-3
    #cohs[cohs < epsilon] = epsilon
    if display:
        print('')

    if display:
        print(('critical perp baseline: %.f m' % pbase_c))
        cohs_mat = coherence_matrix(date12_list, cohs)
        plt.figure()
        plt.imshow(cohs_mat, vmin=0.0, vmax=1.0, cmap='jet')
        plt.xlabel('Image number')
        plt.ylabel('Image number')
        cbar = plt.colorbar()
        cbar.set_label('Coherence')
        plt.title('Coherence matrix')
        plt.show()
    return cohs