def select_pairs_sequential(date_list, num_connection=2, date12_format='YYMMDD-YYMMDD'): """Select Pairs in a Sequential way: For each acquisition, find its num_connection nearest acquisitions in the past time. Inputs: date_list : list of date in YYMMDD/YYYYMMDD format Reference: Fattahi, H., and F. Amelung (2013), DEM Error Correction in InSAR Time Series, IEEE TGRS, 51(7), 4249-4259. """ date8_list = sorted(ptime.yyyymmdd(date_list)) date6_list = ptime.yymmdd(date8_list) date_idx_list = list(range(len(date6_list))) # Get pairs index list date12_idx_list = [] for date_idx in date_idx_list: for i in range(num_connection): if date_idx - i - 1 >= 0: date12_idx_list.append([date_idx - i - 1, date_idx]) 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
def select_pairs_star(date_list, m_date=None, pbase_list=[], date12_format='YYMMDD-YYMMDD'): """Select Star-like network/interferograms/pairs, it's a single master network, similar to PS approach. Usage: m_date : master date, choose it based on the following cretiria: 1) near the center in temporal and spatial baseline 2) prefer winter season than summer season for less temporal decorrelation Reference: Ferretti, A., C. Prati, and F. Rocca (2001), Permanent scatterers in SAR interferometry, IEEE TGRS, 39(1), 8-20. """ date8_list = sorted(ptime.yyyymmdd(date_list)) date6_list = ptime.yymmdd(date8_list) # Select master date if not existed if not m_date: m_date = select_master_date(date8_list, pbase_list) print(('auto select master date: '+m_date)) # Check input master date m_date8 = ptime.yyyymmdd(m_date) if m_date8 not in date8_list: print('Input master date is not existed in date list!') print(('Input master date: '+str(m_date8))) print(('Input date list: '+str(date8_list))) m_date8 = None # Generate star/ps network m_idx = date8_list.index(m_date8) date12_idx_list = [sorted([m_idx, s_idx]) for s_idx in range(len(date8_list)) if s_idx is not m_idx] 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
def select_pairs_sequential(date_list, num_connection=2, date12_format='YYMMDD-YYMMDD'): """Select Pairs in a Sequential way: For each acquisition, find its num_connection nearest acquisitions in the past time. Inputs: date_list : list of date in YYMMDD/YYYYMMDD format Reference: Fattahi, H., and F. Amelung (2013), DEM Error Correction in InSAR Time Series, IEEE TGRS, 51(7), 4249-4259. """ date8_list = sorted(ptime.yyyymmdd(date_list)) date6_list = ptime.yymmdd(date8_list) date_idx_list = list(range(len(date6_list))) # Get pairs index list date12_idx_list = [] for date_idx in date_idx_list: for i in range(num_connection): if date_idx-i-1 >= 0: date12_idx_list.append([date_idx-i-1, date_idx]) 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
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
def get_date12_list(fname, dropIfgram=False): """Read date12 info from input file: Pairs.list or multi-group hdf5 file Parameters: fname - string, path/name of input multi-group hdf5 file or text file dropIfgram - bool, check the "dropIfgram" dataset in ifgramStack hdf5 file Returns: date12_list - list of string in YYYYMMDD_YYYYMMDD format Example: date12List = get_date12_list('ifgramStack.h5') date12List = get_date12_list('ifgramStack.h5', dropIfgram=True) date12List = get_date12_list('coherenceSpatialAvg.txt') """ date12_list = [] ext = os.path.splitext(fname)[1].lower() if ext == '.h5': k = readfile.read_attribute(fname)['FILE_TYPE'] if k == 'ifgramStack': date12_list = ifgramStack(fname).get_date12_list( dropIfgram=dropIfgram) else: return None else: date12_list = np.loadtxt(fname, dtype=bytes, usecols=0).astype(str).tolist() # for txt file with only one interferogram if isinstance(date12_list, str): date12_list = [date12_list] date12_list = sorted(date12_list) date12_list = ptime.yyyymmdd_date12(date12_list) return date12_list
def select_pairs_all(date_list, date12_format='YYMMDD-YYMMDD'): """Select All Possible Pairs/Interferograms Input : date_list - list of date in YYMMDD/YYYYMMDD format Output: date12_list - list date12 in YYMMDD-YYMMDD format Reference: Berardino, P., G. Fornaro, R. Lanari, and E. Sansosti (2002), A new algorithm for surface deformation monitoring based on small baseline differential SAR interferograms, IEEE TGRS, 40(11), 2375-2383. """ date8_list = sorted(ptime.yyyymmdd(date_list)) date6_list = ptime.yymmdd(date8_list) date12_list = list(itertools.combinations(date6_list, 2)) date12_list = [date12[0] + '-' + date12[1] for date12 in date12_list] if date12_format == 'YYYYMMDD_YYYYMMDD': date12_list = ptime.yyyymmdd_date12(date12_list) return date12_list
def select_pairs_all(date_list, date12_format='YYMMDD-YYMMDD'): """Select All Possible Pairs/Interferograms Input : date_list - list of date in YYMMDD/YYYYMMDD format Output: date12_list - list date12 in YYMMDD-YYMMDD format Reference: Berardino, P., G. Fornaro, R. Lanari, and E. Sansosti (2002), A new algorithm for surface deformation monitoring based on small baseline differential SAR interferograms, IEEE TGRS, 40(11), 2375-2383. """ date8_list = sorted(ptime.yyyymmdd(date_list)) date6_list = ptime.yymmdd(date8_list) date12_list = list(itertools.combinations(date6_list, 2)) date12_list = [date12[0]+'-'+date12[1] for date12 in date12_list] if date12_format == 'YYYYMMDD_YYYYMMDD': date12_list = ptime.yyyymmdd_date12(date12_list) return date12_list
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
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
def select_pairs_sequential(date_list, num_conn=2, date_format=None): """Select Pairs in a Sequential way: For each acquisition, find its num_connection nearest acquisitions in the past time. Reference: Fattahi, H., and F. Amelung (2013), DEM Error Correction in InSAR Time Series, IEEE TGRS, 51(7), 4249-4259. Parameters: date_list - list of str for date num_conn - int, number of sequential connections date_format - str / None, output date format Returns: date12_list - list of str for date12 """ date_list = sorted(date_list) date_inds = list(range(len(date_list))) # Get pairs index list date12_inds = [] for date_ind in date_inds: for i in range(num_conn): if date_ind - i - 1 >= 0: date12_inds.append([date_ind - i - 1, date_ind]) date12_inds = [sorted(i) for i in sorted(date12_inds)] # Convert index into date12 date12_list = [ '{}_{}'.format(date_list[ind12[0]], date_list[ind12[1]]) for ind12 in date12_inds ] # adjust output date format if date_format is not None: if date_format == 'YYYYMMDD': date12_list = ptime.yyyymmdd_date12(date12_list) elif date_format == 'YYMMDD': date12_list = ptime.yymmdd_date12(date12_list) else: raise ValueError( 'un-supported date format: {}!'.format(date_format)) return date12_list
def get_mst_date12(keep_mst, par_list_all, date12_list_all, date12_to_drop, min_par, par_name='average coherence'): """Get the date12_list of the MST network for the given parameter.""" if keep_mst: print(f'Get minimum spanning tree (MST) of interferograms with inverse of {par_name}.') msg = ('Drop ifgrams with ' '1) {} < {} AND ' '2) not in MST network: '.format(par_name, min_par)) # get the current remaining network (after all the above criteria and before data-driven) date12_to_keep = sorted(list(set(date12_list_all) - set(date12_to_drop))) par_to_keep = [par for par, date12 in zip(par_list_all, date12_list_all) if date12 in date12_to_keep] # get MST from the current remaining network mst_date12_list = pnet.threshold_coherence_based_mst(date12_to_keep, par_to_keep) mst_date12_list = ptime.yyyymmdd_date12(mst_date12_list) else: msg = 'Drop ifgrams with {} < {}: '.format(par_name, min_par) mst_date12_list = [] return mst_date12_list, msg
def select_pairs_hierarchical(date_list, pbase_list, temp_perp_list, date12_format='YYMMDD-YYMMDD'): """Select Pairs in a hierarchical way using list of temporal and perpendicular baseline thresholds For each temporal/perpendicular combination, select all possible pairs; and then merge all combination results together for the final output (Zhao, 2015). Inputs: date_list : list of date in YYMMDD/YYYYMMDD format pbase_list : list of float, perpendicular spatial baseline temp_perp_list : list of list of 2 floats, for list of temporal/perp baseline, e.g. [[32.0, 800.0], [48.0, 600.0], [64.0, 200.0]] Examples: pairs = select_pairs_hierarchical(date_list, pbase_list, [[32.0, 800.0], [48.0, 600.0], [64.0, 200.0]]) Reference: Zhao, W., (2015), Small deformation detected from InSAR time-series and their applications in geophysics, Doctoral dissertation, Univ. of Miami, Section 6.3. """ # Get all date12 date12_list_all = select_pairs_all(date_list) # Loop of Threshold print('List of temporal and perpendicular spatial baseline thresholds:') print(temp_perp_list) date12_list = [] for temp_perp in temp_perp_list: tbase_max = temp_perp[0] pbase_max = temp_perp[1] date12_list_tmp = threshold_temporal_baseline(date12_list_all, tbase_max, keep_seasonal=False) date12_list_tmp = threshold_perp_baseline(date12_list_tmp, date_list, pbase_list, pbase_max) date12_list += date12_list_tmp date12_list = sorted(list(set(date12_list))) if date12_format == 'YYYYMMDD_YYYYMMDD': date12_list = ptime.yyyymmdd_date12(date12_list) return date12_list
def get_date12_to_drop(inps): """Get date12 list to dropped Return [] if no ifgram to drop, thus KEEP ALL ifgrams; None if nothing to change, exit without doing anything. """ obj = ifgramStack(inps.file) obj.open() date12ListAll = obj.date12List dateList = obj.dateList print('number of interferograms: {}'.format(len(date12ListAll))) # Get date12_to_drop date12_to_drop = [] # reference file if inps.referenceFile: date12_to_keep = pnet.get_date12_list(inps.referenceFile, dropIfgram=True) print('--------------------------------------------------') print('use reference pairs info from file: {}'.format(inps.referenceFile)) print('number of interferograms in reference: {}'.format(len(date12_to_keep))) tempList = sorted(list(set(date12ListAll) - set(date12_to_keep))) date12_to_drop += tempList print('date12 not in reference file: ({})\n{}'.format(len(tempList), tempList)) # temp baseline threshold if inps.tempBaseMax: tempIndex = np.abs(obj.tbaseIfgram) > inps.tempBaseMax tempList = list(np.array(date12ListAll)[tempIndex]) date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with temporal baseline > {} days: ({})\n{}'.format( inps.tempBaseMax, len(tempList), tempList)) # perp baseline threshold if inps.perpBaseMax: tempIndex = np.abs(obj.pbaseIfgram) > inps.perpBaseMax tempList = list(np.array(date12ListAll)[tempIndex]) date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with perp baseline > {} meters: ({})\n{}'.format( inps.perpBaseMax, len(tempList), tempList)) # connection number threshold if inps.connNumMax: seq_date12_list = pnet.select_pairs_sequential(dateList, inps.connNumMax) seq_date12_list = ptime.yyyymmdd_date12(seq_date12_list) tempList = [i for i in date12ListAll if i not in seq_date12_list] date12_to_drop += tempList print('--------------------------------------------------') msg = 'Drop ifgrams with temporal baseline beyond {} neighbors: ({})'.format( inps.connNumMax, len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # excludeIfgIndex if inps.excludeIfgIndex: tempList = [date12ListAll[i] for i in inps.excludeIfgIndex] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with the following index number: {}'.format(len(tempList))) for i, date12 in enumerate(tempList): print('{} : {}'.format(i, date12)) # excludeDate if inps.excludeDate: tempList = [i for i in date12ListAll if any(j in inps.excludeDate for j in i.split('_'))] date12_to_drop += tempList print('-'*50+'\nDrop ifgrams including the following dates: ({})\n{}'.format( len(tempList), inps.excludeDate)) print('-'*30+'\n{}'.format(tempList)) # startDate if inps.startDate: minDate = int(inps.startDate) tempList = [i for i in date12ListAll if any(int(j) < minDate for j in i.split('_'))] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with date earlier than: {} ({})\n{}'.format( inps.startDate, len(tempList), tempList)) # endDate if inps.endDate: maxDate = int(inps.endDate) tempList = [i for i in date12ListAll if any(int(j) > maxDate for j in i.split('_'))] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with date later than: {} ({})\n{}'.format( inps.endDate, len(tempList), tempList)) # coherence file if inps.coherenceBased: print('--------------------------------------------------') print('use coherence-based network modification') # get area of interest for coherence calculation pix_box = get_aoi_pix_box(obj.metadata, inps.lookupFile, inps.aoi_pix_box, inps.aoi_geo_box) # calculate spatial average coherence cohList = ut.spatial_average(inps.file, datasetName='coherence', maskFile=inps.maskFile, box=pix_box, saveList=True)[0] # get coherence-based network coh_date12_list = list(np.array(date12ListAll)[np.array(cohList) >= inps.minCoherence]) # get MST network mst_date12_list, msg = get_mst_date12(inps.keepMinSpanTree, cohList, date12ListAll, date12_to_drop, min_par=inps.minCoherence, par_name='average coherence') # drop all dates (below cohh thresh AND not in MST) tempList = sorted(list(set(date12ListAll) - set(coh_date12_list + mst_date12_list))) date12_to_drop += tempList msg += '({})'.format(len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # area ratio file if inps.areaRatioBased: print('--------------------------------------------------') print('use area-ratio-based network modification') # get area of interest for coherence calculation pix_box = get_aoi_pix_box(obj.metadata, inps.lookupFile, inps.aoi_pix_box, inps.aoi_geo_box) # calculate average coherence in masked out areas as threshold meanMaskCoh = np.nanmean(ut.spatial_average(inps.file, datasetName='coherence', maskFile=inps.maskFile, saveList=True, reverseMask=True)[0]) print(f'Average coherence of {inps.maskFile} reverse is {meanMaskCoh:.2f}') # calculate area-ratio with pixels greater than meanMaskCoh areaRatioList = ut.spatial_average(inps.file, datasetName='coherence', maskFile=inps.maskFile, box=pix_box, saveList=True, checkAoi=True, threshold=meanMaskCoh)[0] # get area-ratio-based network area_ratio_date12_list = list(np.array(date12ListAll)[np.array(areaRatioList) >= inps.minAreaRatio]) # get MST network mst_date12_list, msg = get_mst_date12(inps.keepMinSpanTree, areaRatioList, date12ListAll, date12_to_drop, min_par=inps.minAreaRatio, par_name='coherent area ratio') # drop all dates (below area-ratio thresh AND not in MST) tempList = sorted(list(set(date12ListAll) - set(area_ratio_date12_list + mst_date12_list))) date12_to_drop += tempList msg += '({})'.format(len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # Manually drop pairs if inps.manual: tempList = manual_select_pairs_to_remove(inps.file) if tempList is None: return None tempList = [i for i in tempList if i in date12ListAll] print('date12 selected to remove: ({})\n{}'.format(len(tempList), tempList)) date12_to_drop += tempList ## summary # drop duplicate date12 and sort in order date12_to_drop = sorted(list(set(date12_to_drop))) date12_to_keep = sorted(list(set(date12ListAll) - set(date12_to_drop))) print('--------------------------------------------------') print('number of interferograms to remove: {}'.format(len(date12_to_drop))) print('number of interferograms to keep : {}'.format(len(date12_to_keep))) # print list of date to drop date_to_keep = [d for date12 in date12_to_keep for d in date12.split('_')] date_to_keep = sorted(list(set(date_to_keep))) date_to_drop = sorted(list(set(dateList) - set(date_to_keep))) if len(date_to_drop) > 0: print('number of acquisitions to remove: {}\n{}'.format(len(date_to_drop), date_to_drop)) # checking: # 1) no new date12 to drop against existing file # 2) no date12 left after dropping date12ListKept = obj.get_date12_list(dropIfgram=True) date12ListDropped = sorted(list(set(date12ListAll) - set(date12ListKept))) if date12_to_drop == date12ListDropped: print('Calculated date12 to drop is the same as exsiting marked input file, skip updating file.') date12_to_drop = None elif date12_to_drop == date12ListAll: raise Exception('Zero interferogram left! Please adjust your setting and try again.') return date12_to_drop
def get_date12_to_drop(inps): """Get date12 list to dropped Return [] if no ifgram to drop, thus KEEP ALL ifgrams; None if nothing to change, exit without doing anything. """ obj = ifgramStack(inps.file) obj.open() date12ListAll = obj.date12List dateList = obj.dateList print('number of interferograms: {}'.format(len(date12ListAll))) # Get date12_to_drop date12_to_drop = [] # reference file if inps.referenceFile: date12_to_keep = ifgramStack(inps.referenceFile).get_date12_list(dropIfgram=True) print('--------------------------------------------------') print('use reference pairs info from file: {}'.format(inps.referenceFile)) print('number of interferograms in reference: {}'.format(len(date12_to_keep))) tempList = sorted(list(set(date12ListAll) - set(date12_to_keep))) date12_to_drop += tempList print('date12 not in reference file: ({})\n{}'.format(len(tempList), tempList)) # coherence file if inps.coherenceBased: print('--------------------------------------------------') print('use coherence-based network modification') coord = ut.coordinate(obj.metadata, lookup_file=inps.lookupFile) if inps.aoi_geo_box and inps.lookupFile: print('input AOI in (lon0, lat1, lon1, lat0): {}'.format(inps.aoi_geo_box)) inps.aoi_pix_box = coord.bbox_geo2radar(inps.aoi_geo_box) if inps.aoi_pix_box: inps.aoi_pix_box = coord.check_box_within_data_coverage(inps.aoi_pix_box) print('input AOI in (x0,y0,x1,y1): {}'.format(inps.aoi_pix_box)) # Calculate spatial average coherence cohList = ut.spatial_average(inps.file, datasetName='coherence', maskFile=inps.maskFile, box=inps.aoi_pix_box, saveList=True)[0] coh_date12_list = list(np.array(date12ListAll)[np.array(cohList) >= inps.minCoherence]) # MST network if inps.keepMinSpanTree: print('Get minimum spanning tree (MST) of interferograms with inverse of coherence.') msg = ('Drop ifgrams with ' '1) average coherence < {} AND ' '2) not in MST network: '.format(inps.minCoherence)) mst_date12_list = pnet.threshold_coherence_based_mst(date12ListAll, cohList) mst_date12_list = ptime.yyyymmdd_date12(mst_date12_list) else: msg = 'Drop ifgrams with average coherence < {}: '.format(inps.minCoherence) mst_date12_list = [] tempList = sorted(list(set(date12ListAll) - set(coh_date12_list + mst_date12_list))) date12_to_drop += tempList msg += '({})'.format(len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # temp baseline threshold if inps.tempBaseMax: tempIndex = np.abs(obj.tbaseIfgram) > inps.tempBaseMax tempList = list(np.array(date12ListAll)[tempIndex]) date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with temporal baseline > {} days: ({})\n{}'.format( inps.tempBaseMax, len(tempList), tempList)) # perp baseline threshold if inps.perpBaseMax: tempIndex = np.abs(obj.pbaseIfgram) > inps.perpBaseMax tempList = list(np.array(date12ListAll)[tempIndex]) date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with perp baseline > {} meters: ({})\n{}'.format( inps.perpBaseMax, len(tempList), tempList)) # connection number threshold if inps.connNumMax: seq_date12_list = pnet.select_pairs_sequential(dateList, inps.connNumMax) seq_date12_list = ptime.yyyymmdd_date12(seq_date12_list) tempList = [i for i in date12ListAll if i not in seq_date12_list] date12_to_drop += tempList print('--------------------------------------------------') msg = 'Drop ifgrams with temporal baseline beyond {} neighbors: ({})'.format( inps.connNumMax, len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # excludeIfgIndex if inps.excludeIfgIndex: tempList = [date12ListAll[i] for i in inps.excludeIfgIndex] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with the following index number: {}'.format(len(tempList))) for i in range(len(tempList)): print('{} : {}'.format(i, tempList[i])) #len(tempList), zip(inps.excludeIfgIndex, tempList))) # excludeDate if inps.excludeDate: tempList = [i for i in date12ListAll if any(j in inps.excludeDate for j in i.split('_'))] date12_to_drop += tempList print('-'*50+'\nDrop ifgrams including the following dates: ({})\n{}'.format( len(tempList), inps.excludeDate)) print('-'*30+'\n{}'.format(tempList)) # startDate if inps.startDate: minDate = int(inps.startDate) tempList = [i for i in date12ListAll if any(int(j) < minDate for j in i.split('_'))] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with date earlier than: {} ({})\n{}'.format( inps.startDate, len(tempList), tempList)) # endDate if inps.endDate: maxDate = int(inps.endDate) tempList = [i for i in date12ListAll if any(int(j) > maxDate for j in i.split('_'))] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with date later than: {} ({})\n{}'.format( inps.endDate, len(tempList), tempList)) # Manually drop pairs if inps.manual: tempList = manual_select_pairs_to_remove(inps.file) if tempList is None: return None tempList = [i for i in tempList if i in date12ListAll] print('date12 selected to remove: ({})\n{}'.format(len(tempList), tempList)) date12_to_drop += tempList # drop duplicate date12 and sort in order date12_to_drop = sorted(list(set(date12_to_drop))) date12_to_keep = sorted(list(set(date12ListAll) - set(date12_to_drop))) print('--------------------------------------------------') print('number of interferograms to remove: {}'.format(len(date12_to_drop))) print('number of interferograms to keep : {}'.format(len(date12_to_keep))) date_to_keep = [d for date12 in date12_to_keep for d in date12.split('_')] date_to_keep = sorted(list(set(date_to_keep))) date_to_drop = sorted(list(set(dateList) - set(date_to_keep))) if len(date_to_drop) > 0: print('number of acquisitions to remove: {}\n{}'.format(len(date_to_drop), date_to_drop)) date12ListKept = obj.get_date12_list(dropIfgram=True) date12ListDropped = sorted(list(set(date12ListAll) - set(date12ListKept))) if date12_to_drop == date12ListDropped: print('Calculated date12 to drop is the same as exsiting marked input file, skip updating file.') date12_to_drop = None elif date12_to_drop == date12ListAll: raise Exception('Zero interferogram left! Please adjust your setting and try again.') return date12_to_drop
def get_date12_to_drop(inps): """Get date12 list to dropped Return [] if no ifgram to drop, thus KEEP ALL ifgrams; None if nothing to change, exit without doing anything. """ obj = ifgramStack(inps.file) obj.open() date12ListAll = obj.date12List dateList = obj.dateList print('number of interferograms: {}'.format(len(date12ListAll))) # Get date12_to_drop date12_to_drop = [] # reference file if inps.referenceFile: date12_to_keep = ifgramStack( inps.referenceFile).get_date12_list(dropIfgram=True) print('--------------------------------------------------') print('use reference pairs info from file: {}'.format( inps.referenceFile)) print('number of interferograms in reference: {}'.format( len(date12_to_keep))) tempList = sorted(list(set(date12ListAll) - set(date12_to_keep))) date12_to_drop += tempList print('date12 not in reference file: ({})\n{}'.format( len(tempList), tempList)) # coherence file if inps.coherenceBased: print('--------------------------------------------------') print('use coherence-based network modification') coord = ut.coordinate(obj.metadata, lookup_file=inps.lookupFile) if inps.aoi_geo_box and inps.lookupFile: print('input AOI in (lon0, lat1, lon1, lat0): {}'.format( inps.aoi_geo_box)) inps.aoi_pix_box = coord.bbox_geo2radar(inps.aoi_geo_box) if inps.aoi_pix_box: inps.aoi_pix_box = coord.check_box_within_data_coverage( inps.aoi_pix_box) print('input AOI in (x0,y0,x1,y1): {}'.format(inps.aoi_pix_box)) # Calculate spatial average coherence cohList = ut.spatial_average(inps.file, datasetName='coherence', maskFile=inps.maskFile, box=inps.aoi_pix_box, saveList=True)[0] coh_date12_list = list( np.array(date12ListAll)[np.array(cohList) >= inps.minCoherence]) # MST network if inps.keepMinSpanTree: print( 'Get minimum spanning tree (MST) of interferograms with inverse of coherence.' ) msg = ('Drop ifgrams with ' '1) average coherence < {} AND ' '2) not in MST network: '.format(inps.minCoherence)) mst_date12_list = pnet.threshold_coherence_based_mst( date12ListAll, cohList) mst_date12_list = ptime.yyyymmdd_date12(mst_date12_list) else: msg = 'Drop ifgrams with average coherence < {}: '.format( inps.minCoherence) mst_date12_list = [] tempList = sorted( list(set(date12ListAll) - set(coh_date12_list + mst_date12_list))) date12_to_drop += tempList msg += '({})'.format(len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # temp baseline threshold if inps.tempBaseMax: tempIndex = np.abs(obj.tbaseIfgram) > inps.tempBaseMax tempList = list(np.array(date12ListAll)[tempIndex]) date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with temporal baseline > {} days: ({})\n{}'.format( inps.tempBaseMax, len(tempList), tempList)) # perp baseline threshold if inps.perpBaseMax: tempIndex = np.abs(obj.pbaseIfgram) > inps.perpBaseMax tempList = list(np.array(date12ListAll)[tempIndex]) date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with perp baseline > {} meters: ({})\n{}'.format( inps.perpBaseMax, len(tempList), tempList)) # connection number threshold if inps.connNumMax: seq_date12_list = pnet.select_pairs_sequential(dateList, inps.connNumMax) seq_date12_list = ptime.yyyymmdd_date12(seq_date12_list) tempList = [i for i in date12ListAll if i not in seq_date12_list] date12_to_drop += tempList print('--------------------------------------------------') msg = 'Drop ifgrams with temporal baseline beyond {} neighbors: ({})'.format( inps.connNumMax, len(tempList)) if len(tempList) <= 200: msg += '\n{}'.format(tempList) print(msg) # excludeIfgIndex if inps.excludeIfgIndex: tempList = [date12ListAll[i] for i in inps.excludeIfgIndex] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with the following index number: {}'.format( len(tempList))) for i in range(len(tempList)): print('{} : {}'.format(i, tempList[i])) #len(tempList), zip(inps.excludeIfgIndex, tempList))) # excludeDate if inps.excludeDate: tempList = [ i for i in date12ListAll if any(j in inps.excludeDate for j in i.split('_')) ] date12_to_drop += tempList print('-' * 50 + '\nDrop ifgrams including the following dates: ({})\n{}'.format( len(tempList), inps.excludeDate)) print('-' * 30 + '\n{}'.format(tempList)) # startDate if inps.startDate: minDate = int(inps.startDate) tempList = [ i for i in date12ListAll if any( int(j) < minDate for j in i.split('_')) ] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with date earlier than: {} ({})\n{}'.format( inps.startDate, len(tempList), tempList)) # endDate if inps.endDate: maxDate = int(inps.endDate) tempList = [ i for i in date12ListAll if any( int(j) > maxDate for j in i.split('_')) ] date12_to_drop += tempList print('--------------------------------------------------') print('Drop ifgrams with date later than: {} ({})\n{}'.format( inps.endDate, len(tempList), tempList)) # Manually drop pairs if inps.manual: tempList = manual_select_pairs_to_remove(inps.file) if tempList is None: return None tempList = [i for i in tempList if i in date12ListAll] print('date12 selected to remove: ({})\n{}'.format( len(tempList), tempList)) date12_to_drop += tempList # drop duplicate date12 and sort in order date12_to_drop = sorted(list(set(date12_to_drop))) date12_to_keep = sorted(list(set(date12ListAll) - set(date12_to_drop))) print('--------------------------------------------------') print('number of interferograms to remove: {}'.format(len(date12_to_drop))) print('number of interferograms to keep : {}'.format(len(date12_to_keep))) date_to_keep = [d for date12 in date12_to_keep for d in date12.split('_')] date_to_keep = sorted(list(set(date_to_keep))) date_to_drop = sorted(list(set(dateList) - set(date_to_keep))) if len(date_to_drop) > 0: print('number of acquisitions to remove: {}\n{}'.format( len(date_to_drop), date_to_drop)) date12ListKept = obj.get_date12_list(dropIfgram=True) date12ListDropped = sorted(list(set(date12ListAll) - set(date12ListKept))) if date12_to_drop == date12ListDropped: print( 'Calculated date12 to drop is the same as exsiting marked input file, skip updating file.' ) date12_to_drop = None elif date12_to_drop == date12ListAll: raise Exception( 'Zero interferogram left! Please adjust your setting and try again.' ) return date12_to_drop
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
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