def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() #%% Set default imd_s = [] imd_e = [] cumfile = 'cum_filt.h5' outfile = [] refarea = [] maskfile = [] vstdflag = False sinflag = False pngflag = False #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "hs:e:i:o:r:", ["help", "vstd", "sin", "png", "mask="]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-s': imd_s = a elif o == '-e': imd_e = a elif o == '-i': cumfile = a elif o == '-o': outfile = a elif o == '-r': refarea = a elif o == '--vstd': vstdflag = True elif o == '--sin': sinflag = True elif o == '--mask': maskfile = a elif o == '--png': pngflag = True if not os.path.exists(cumfile): raise Usage('No {} exists! Use -i option.'.format(cumfile)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Read info ### Read cumfile cumh5 = h5.File(cumfile, 'r') imdates = cumh5['imdates'][()].astype(str).tolist() cum = cumh5['cum'] n_im_all, length, width = cum.shape if not refarea: refarea = cumh5['refarea'][()] refx1, refx2, refy1, refy2 = [ int(s) for s in re.split('[:/]', refarea) ] else: if not tools_lib.read_range(refarea, width, length): print('\nERROR in {}\n'.format(refarea), file=sys.stderr) return 2 else: refx1, refx2, refy1, refy2 = tools_lib.read_range( refarea, width, length) #%% Setting ### Dates if not imd_s: imd_s = imdates[0] if not imd_e: imd_e = imdates[-1] ### mask if maskfile: mask = io_lib.read_img(maskfile, length, width) mask[mask == 0] = np.nan suffix_mask = '.mskd' else: mask = np.ones((length, width), dtype=np.float32) suffix_mask = '' ### Find date index if not exist in imdates if not imd_s in imdates: for imd in imdates: if int(imd) >= int(imd_s): ## First larger one than imd_s imd_s = imd break if not imd_e in imdates: for imd in imdates[::-1]: if int(imd) <= int(imd_e): ## Last smaller one than imd_e imd_e = imd break ix_s = imdates.index(imd_s) ix_e = imdates.index(imd_e) + 1 #+1 for python custom n_im = ix_e - ix_s ### Calc dt in year imdates_dt = ([ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates[ix_s:ix_e] ]) dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) ### Outfile if not outfile: outfile = '{}_{}.vel{}'.format(imd_s, imd_e, suffix_mask) #%% Display info print('') print('Start date : {}'.format(imdates[ix_s])) print('End date : {}'.format(imdates[ix_e - 1])) print('# of images : {}'.format(n_im)) print('Ref area : {}:{}/{}:{}'.format(refx1, refx2, refy1, refy2)) print('') #%% Calc velocity and vstd vconst = np.zeros((length, width), dtype=np.float32) * np.nan vel = np.zeros((length, width), dtype=np.float32) * np.nan ### Read cum data cum_tmp = cum[ix_s:ix_e, :, :] * mask cum_ref = np.nanmean(cum[ix_s:ix_e, refy1:refy2, refx1:refx2] * mask[refy1:refy2, refx1:refx2], axis=(1, 2)) if np.all(np.isnan(cum_ref)): print('\nERROR: Ref area has only NaN value!\n', file=sys.stderr) return 2 cum_tmp = cum_tmp - cum_ref[:, np.newaxis, np.newaxis] ### Extract not nan points bool_allnan = np.all(np.isnan(cum_tmp), axis=0) cum_tmp = cum_tmp.reshape(n_im, length * width)[:, ~bool_allnan.ravel()].transpose() if not sinflag: ## Linear function print('Calc velocity...') vel[~bool_allnan], vconst[~bool_allnan] = inv_lib.calc_vel( cum_tmp, dt_cum) vel.tofile(outfile) else: ## Linear+sin function print('Calc velocity and annual components...') amp = np.zeros((length, width), dtype=np.float32) * np.nan delta_t = np.zeros((length, width), dtype=np.float32) * np.nan ampfile = outfile.replace('vel', 'amp') dtfile = outfile.replace('vel', 'dt') vel[~bool_allnan], vconst[~bool_allnan], amp[~bool_allnan], delta_t[ ~bool_allnan] = inv_lib.calc_velsin(cum_tmp, dt_cum, imdates[0]) vel.tofile(outfile) amp.tofile(ampfile) delta_t.tofile(dtfile) ### vstd if vstdflag: vstdfile = outfile.replace('vel', 'vstd') vstd = np.zeros((length, width), dtype=np.float32) * np.nan print('Calc vstd...') vstd[~bool_allnan] = inv_lib.calc_velstd_withnan(cum_tmp, dt_cum) vstd.tofile(vstdfile) #%% Make png if specified if pngflag: pngfile = outfile + '.png' title = 'n_im: {}, Ref X/Y {}:{}/{}:{}'.format(n_im, refx1, refx2, refy1, refy2) plot_lib.make_im_png(vel, pngfile, 'jet', title) if sinflag: amp_max = np.nanpercentile(amp, 99) plot_lib.make_im_png(amp, ampfile + '.png', 'viridis', title, vmax=amp_max) plot_lib.make_im_png(delta_t, dtfile + '.png', 'hsv', title) if vstdflag: plot_lib.make_im_png(vstd, vstdfile + '.png', 'jet', title) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output: {}'.format(outfile), flush=True) if vstdflag: print(' {}'.format(vstdfile), flush=True) print('')
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() ver = 1.3 date = 20200907 author = "Y. Morishita" print("\n{} ver{} {} {}".format(os.path.basename(argv[0]), ver, date, author), flush=True) print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) global Aloop, ifgdates, ifgdir, length, width, loop_pngdir ## for parallel processing #%% Set default ifgdir = [] tsadir = [] loop_thre = 1.5 n_para = len(os.sched_getaffinity(0)) cmap_noise = 'viridis' cmap_noise_r = 'viridis_r' #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "hd:t:l:", ["help", "n_para="]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-d': ifgdir = a elif o == '-t': tsadir = a elif o == '-l': loop_thre = float(a) elif o == '--n_para': n_para = int(a) if not ifgdir: raise Usage('No data directory given, -d is not optional!') elif not os.path.isdir(ifgdir): raise Usage('No {} dir exists!'.format(ifgdir)) elif not os.path.exists(os.path.join(ifgdir, 'slc.mli.par')): raise Usage('No slc.mli.par file exists in {}!'.format(ifgdir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 print("\nloop_thre : {} rad".format(loop_thre), flush=True) #%% Directory setting ifgdir = os.path.abspath(ifgdir) if not tsadir: tsadir = os.path.join(os.path.dirname(ifgdir), 'TS_' + os.path.basename(ifgdir)) if not os.path.isdir(tsadir): print('\nNo {} exists!'.format(tsadir), file=sys.stderr) return 1 tsadir = os.path.abspath(tsadir) loopdir = os.path.join(tsadir, '12loop') if not os.path.exists(loopdir): os.mkdir(loopdir) loop_pngdir = os.path.join(loopdir, 'good_loop_png') bad_loop_pngdir = os.path.join(loopdir, 'bad_loop_png') bad_loop_cand_pngdir = os.path.join(loopdir, 'bad_loop_cand_png') if os.path.exists(loop_pngdir): shutil.move(loop_pngdir + '/', loop_pngdir + '_old') #move to old dir if os.path.exists(bad_loop_pngdir): for png in glob.glob(bad_loop_pngdir + '/*.png'): shutil.move(png, loop_pngdir + '_old') #move to old dir shutil.rmtree(bad_loop_pngdir) if os.path.exists(bad_loop_cand_pngdir): for png in glob.glob(bad_loop_cand_pngdir + '/*.png'): shutil.move(png, loop_pngdir + '_old') #move to old dir shutil.rmtree(bad_loop_cand_pngdir) os.mkdir(loop_pngdir) os.mkdir(bad_loop_pngdir) os.mkdir(bad_loop_cand_pngdir) ifg_rasdir = os.path.join(tsadir, '12ifg_ras') if os.path.isdir(ifg_rasdir): shutil.rmtree(ifg_rasdir) os.mkdir(ifg_rasdir) bad_ifgrasdir = os.path.join(tsadir, '12bad_ifg_ras') if os.path.isdir(bad_ifgrasdir): shutil.rmtree(bad_ifgrasdir) os.mkdir(bad_ifgrasdir) bad_ifg_candrasdir = os.path.join(tsadir, '12bad_ifg_cand_ras') if os.path.isdir(bad_ifg_candrasdir): shutil.rmtree(bad_ifg_candrasdir) os.mkdir(bad_ifg_candrasdir) no_loop_ifgrasdir = os.path.join(tsadir, '12no_loop_ifg_ras') if os.path.isdir(no_loop_ifgrasdir): shutil.rmtree(no_loop_ifgrasdir) os.mkdir(no_loop_ifgrasdir) infodir = os.path.join(tsadir, 'info') if not os.path.exists(infodir): os.mkdir(infodir) resultsdir = os.path.join(tsadir, 'results') if not os.path.exists(resultsdir): os.mkdir(resultsdir) netdir = os.path.join(tsadir, 'network') #%% Read date, network information and size ### Get dates ifgdates = tools_lib.get_ifgdates(ifgdir) ### Read bad_ifg11 bad_ifg11file = os.path.join(infodir, '11bad_ifg.txt') bad_ifg11 = io_lib.read_ifg_list(bad_ifg11file) ### Remove bad ifgs and images from list ifgdates = list(set(ifgdates) - set(bad_ifg11)) ifgdates.sort() imdates = tools_lib.ifgdates2imdates(ifgdates) n_ifg = len(ifgdates) n_im = len(imdates) ### Get size mlipar = os.path.join(ifgdir, 'slc.mli.par') width = int(io_lib.get_param_par(mlipar, 'range_samples')) length = int(io_lib.get_param_par(mlipar, 'azimuth_lines')) ### Get loop matrix Aloop = loop_lib.make_loop_matrix(ifgdates) n_loop = Aloop.shape[0] ### Extract no loop ifgs ns_loop4ifg = np.abs(Aloop).sum(axis=0) ixs_ifg_no_loop = np.where(ns_loop4ifg == 0)[0] no_loop_ifg = [ifgdates[ix] for ix in ixs_ifg_no_loop] #%% 1st loop closure check. First without reference print('\n1st Loop closure check and make png for all possible {} loops,'. format(n_loop), flush=True) print('with {} parallel processing...'.format(n_para), flush=True) bad_ifg_cand = [] good_ifg = [] ### Parallel processing p = multi.Pool(n_para) loop_ph_rms_ifg = np.array(p.map(loop_closure_1st_wrapper, range(n_loop)), dtype=object) p.close() for i in range(n_loop): ### Find index of ifg ix_ifg12, ix_ifg23 = np.where(Aloop[i, :] == 1)[0] ix_ifg13 = np.where(Aloop[i, :] == -1)[0][0] ifgd12 = ifgdates[ix_ifg12] ifgd23 = ifgdates[ix_ifg23] ifgd13 = ifgdates[ix_ifg13] ### List as good or bad candidate if loop_ph_rms_ifg[i] >= loop_thre: #Bad loop including bad ifg. bad_ifg_cand.extend([ifgd12, ifgd23, ifgd13]) else: good_ifg.extend([ifgd12, ifgd23, ifgd13]) if os.path.exists(loop_pngdir + '_old/'): shutil.rmtree(loop_pngdir + '_old/') #%% Identify bad ifgs and output text bad_ifg = loop_lib.identify_bad_ifg(bad_ifg_cand, good_ifg) bad_ifgfile = os.path.join(loopdir, 'bad_ifg_loop.txt') with open(bad_ifgfile, 'w') as f: for i in bad_ifg: print('{}'.format(i), file=f) ### Compute n_unw without bad_ifg11 and bad_ifg n_unw = np.zeros((length, width), dtype=np.int16) for ifgd in ifgdates: if ifgd in bad_ifg: continue unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') unw = io_lib.read_img(unwfile, length, width) unw[unw == 0] = np.nan # Fill 0 with nan n_unw += ~np.isnan(unw) # Summing number of unnan unw #%% 2nd loop closure check without bad ifgs to define stable ref area print('\n2nd Loop closure check without bad ifgs to define ref area...', flush=True) ns_loop_ph = np.zeros((length, width), dtype=np.float32) ns_bad_loop = np.zeros((length, width), dtype=np.int16) loop_ph_rms_points = np.zeros((length, width), dtype=np.float32) for i in range(n_loop): if np.mod(i, 100) == 0: print(" {0:3}/{1:3}th loop...".format(i, n_loop), flush=True) ### Read unw unw12, unw23, unw13, ifgd12, ifgd23, ifgd13 = loop_lib.read_unw_loop_ph( Aloop[i, :], ifgdates, ifgdir, length, width) ### Skip if bad ifg is included if ifgd12 in bad_ifg or ifgd23 in bad_ifg or ifgd13 in bad_ifg: continue ## Calculate loop phase and rms at points loop_ph = unw12 + unw23 - unw13 loop_2pin = int(np.round(np.nanmedian(loop_ph) / (2 * np.pi))) * 2 * np.pi loop_ph = loop_ph - loop_2pin #unbias ns_loop_ph = ns_loop_ph + ~np.isnan(loop_ph) loop_ph_sq = loop_ph**2 loop_ph_sq[np.isnan(loop_ph_sq)] = 0 loop_ph_rms_points = loop_ph_rms_points + loop_ph_sq ns_bad_loop = ns_bad_loop + (loop_ph_sq > np.pi**2 ) #suspected unw error # ns_bad_loop = ns_bad_loop+(np.abs(loop_ph)>loop_thre) ## multiple nan seem to generate RuntimeWarning ns_loop_ph[ns_loop_ph == 0] = np.nan # To avoid 0 division loop_ph_rms_points = np.sqrt(loop_ph_rms_points / ns_loop_ph) ### Find stable ref area which have all n_unw and minimum ns_bad_loop and loop_ph_rms_points mask1 = (n_unw == np.nanmax(n_unw)) min_ns_bad_loop = np.nanmin(ns_bad_loop) while True: mask2 = (ns_bad_loop == min_ns_bad_loop) if np.all(~(mask1 * mask2)): ## All masked min_ns_bad_loop = min_ns_bad_loop + 1 ## Make mask2 again else: break loop_ph_rms_points_masked = loop_ph_rms_points * mask1 * mask2 loop_ph_rms_points_masked[loop_ph_rms_points_masked == 0] = np.nan refyx = np.where( loop_ph_rms_points_masked == np.nanmin(loop_ph_rms_points_masked)) refy1 = refyx[0][0] # start from 0, not 1 refy2 = refyx[0][ 0] + 1 # shift +1 for python custom. start from 1 end with width refx1 = refyx[1][0] refx2 = refyx[1][0] + 1 ### Save 12ref.txt reffile = os.path.join(infodir, '12ref.txt') with open(reffile, 'w') as f: print('{0}:{1}/{2}:{3}'.format(refx1, refx2, refy1, refy2), file=f) ### Save loop_ph_rms_masked and png loop_ph_rms_maskedfile = os.path.join(loopdir, 'loop_ph_rms_masked') loop_ph_rms_points_masked.tofile(loop_ph_rms_maskedfile) cmax = np.nanpercentile(loop_ph_rms_points_masked, 95) pngfile = loop_ph_rms_maskedfile + '.png' title = 'RMS of loop phase (rad)' plot_lib.make_im_png(loop_ph_rms_points_masked, pngfile, cmap_noise_r, title, None, cmax) ### Check ref exist in unw. If not, list as noref_ifg noref_ifg = [] for ifgd in ifgdates: if ifgd in bad_ifg: continue unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') unw_ref = io_lib.read_img(unwfile, length, width)[refy1:refy2, refx1:refx2] unw_ref[unw_ref == 0] = np.nan # Fill 0 with nan if np.all(np.isnan(unw_ref)): noref_ifg.append(ifgd) bad_ifgfile = os.path.join(loopdir, 'bad_ifg_noref.txt') with open(bad_ifgfile, 'w') as f: for i in noref_ifg: print('{}'.format(i), file=f) #%% 3rd loop closure check without bad ifgs wrt ref point print('\n3rd loop closure check taking into account ref phase...', flush=True) bad_ifg_cand2 = [] good_ifg2 = [] loop_ph_rms_ifg2 = [] for i in range(n_loop): if np.mod(i, 100) == 0: print(" {0:3}/{1:3}th loop...".format(i, n_loop), flush=True) ### Read unw unw12, unw23, unw13, ifgd12, ifgd23, ifgd13 = loop_lib.read_unw_loop_ph( Aloop[i, :], ifgdates, ifgdir, length, width) ### Skip if bad ifg is included if ifgd12 in bad_ifg or ifgd23 in bad_ifg or ifgd13 in bad_ifg: loop_ph_rms_ifg2.append('--') continue ### Skip if noref ifg is included if ifgd12 in noref_ifg or ifgd23 in noref_ifg or ifgd13 in noref_ifg: loop_ph_rms_ifg2.append('--') continue ## Skip if no data in ref area in any unw. It is bad data. ref_unw12 = np.nanmean(unw12[refy1:refy2, refx1:refx2]) ref_unw23 = np.nanmean(unw23[refy1:refy2, refx1:refx2]) ref_unw13 = np.nanmean(unw13[refy1:refy2, refx1:refx2]) ## Calculate loop phase taking into account ref phase loop_ph = unw12 + unw23 - unw13 - (ref_unw12 + ref_unw23 - ref_unw13) loop_ph_rms_ifg2.append(np.sqrt(np.nanmean((loop_ph)**2))) ### List as good or bad candidate if loop_ph_rms_ifg2[i] >= loop_thre: #Bad loop including bad ifg. bad_ifg_cand2.extend([ifgd12, ifgd23, ifgd13]) else: good_ifg2.extend([ifgd12, ifgd23, ifgd13]) #%% Identify additional bad ifgs and output text bad_ifg2 = loop_lib.identify_bad_ifg(bad_ifg_cand2, good_ifg2) bad_ifgfile = os.path.join(loopdir, 'bad_ifg_loopref.txt') with open(bad_ifgfile, 'w') as f: for i in bad_ifg2: print('{}'.format(i), file=f) #%% Output all bad ifg list and identify remaining candidate of bad ifgs ### Merge bad ifg, bad_ifg2, noref_ifg bad_ifg_all = list(set(bad_ifg + bad_ifg2 + noref_ifg)) # Remove multiple bad_ifg_all.sort() ifgdates_good = list(set(ifgdates) - set(bad_ifg_all)) ifgdates_good.sort() bad_ifgfile = os.path.join(infodir, '12bad_ifg.txt') with open(bad_ifgfile, 'w') as f: for i in bad_ifg_all: print('{}'.format(i), file=f) ### Identify removed image and output file imdates_good = tools_lib.ifgdates2imdates(ifgdates_good) imdates_bad = list(set(imdates) - set(imdates_good)) imdates_bad.sort() bad_imfile = os.path.join(infodir, '12removed_image.txt') with open(bad_imfile, 'w') as f: for i in imdates_bad: print('{}'.format(i), file=f) ### Remaining candidate of bad ifg bad_ifg_cand_res = list(set(bad_ifg_cand2) - set(bad_ifg_all)) bad_ifg_cand_res.sort() bad_ifg_candfile = os.path.join(infodir, '12bad_ifg_cand.txt') with open(bad_ifg_candfile, 'w') as f: for i in bad_ifg_cand_res: print('{}'.format(i), file=f) #%% 4th loop to be used to calc n_loop_err and n_ifg_noloop print('\n4th loop to compute statistics...', flush=True) ns_loop_err = np.zeros((length, width), dtype=np.int16) for i in range(n_loop): if np.mod(i, 100) == 0: print(" {0:3}/{1:3}th loop...".format(i, n_loop), flush=True) ### Read unw unw12, unw23, unw13, ifgd12, ifgd23, ifgd13 = loop_lib.read_unw_loop_ph( Aloop[i, :], ifgdates, ifgdir, length, width) ### Skip if bad ifg is included if ifgd12 in bad_ifg_all or ifgd23 in bad_ifg_all or ifgd13 in bad_ifg_all: continue ## Compute ref ref_unw12 = np.nanmean(unw12[refy1:refy2, refx1:refx2]) ref_unw23 = np.nanmean(unw23[refy1:refy2, refx1:refx2]) ref_unw13 = np.nanmean(unw13[refy1:refy2, refx1:refx2]) ## Calculate loop phase taking into account ref phase loop_ph = unw12 + unw23 - unw13 - (ref_unw12 + ref_unw23 - ref_unw13) ## Count number of loops with suspected unwrap error (>pi) loop_ph[np.isnan(loop_ph)] = 0 #to avoid warning ns_loop_err = ns_loop_err + (np.abs(loop_ph) > np.pi ) #suspected unw error #%% Output loop info, move bad_loop_png loop_info_file = os.path.join(loopdir, 'loop_info.txt') f = open(loop_info_file, 'w') print('# loop_thre: {} rad. *: Removed w/o ref, **: Removed w/ ref'.format( loop_thre), file=f) print('# /: Candidates of bad loops but causative ifgs unidentified', file=f) print('# image1 image2 image3 RMS w/oref w/ref', file=f) for i in range(n_loop): ### Find index of ifg ix_ifg12, ix_ifg23 = np.where(Aloop[i, :] == 1)[0] ix_ifg13 = np.where(Aloop[i, :] == -1)[0][0] ifgd12 = ifgdates[ix_ifg12] ifgd23 = ifgdates[ix_ifg23] ifgd13 = ifgdates[ix_ifg13] imd1 = ifgd12[:8] imd2 = ifgd23[:8] imd3 = ifgd23[-8:] ## Move loop_png if bad ifg or bad ifg_cand is included looppngfile = os.path.join( loop_pngdir, '{0}_{1}_{2}_loop.png'.format(imd1, imd2, imd3)) badlooppngfile = os.path.join( bad_loop_pngdir, '{0}_{1}_{2}_loop.png'.format(imd1, imd2, imd3)) badloopcandpngfile = os.path.join( bad_loop_cand_pngdir, '{0}_{1}_{2}_loop.png'.format(imd1, imd2, imd3)) badloopflag1 = ' ' badloopflag2 = ' ' if ifgd12 in bad_ifg or ifgd23 in bad_ifg or ifgd13 in bad_ifg: badloopflag1 = '*' shutil.move(looppngfile, badlooppngfile) elif ifgd12 in bad_ifg2 or ifgd23 in bad_ifg2 or ifgd13 in bad_ifg2: badloopflag2 = '**' shutil.move(looppngfile, badlooppngfile) elif ifgd12 in bad_ifg_cand_res or ifgd23 in bad_ifg_cand_res or ifgd13 in bad_ifg_cand_res: badloopflag1 = '/' if os.path.exists(looppngfile): shutil.move(looppngfile, badloopcandpngfile) if type(loop_ph_rms_ifg2[i]) == np.float32: str_loop_ph_rms_ifg2 = "{:.2f}".format(loop_ph_rms_ifg2[i]) else: ## -- str_loop_ph_rms_ifg2 = loop_ph_rms_ifg2[i] print('{0} {1} {2} {3:5.2f} {4} {5:5s} {6}'.format( imd1, imd2, imd3, loop_ph_rms_ifg[i], badloopflag1, str_loop_ph_rms_ifg2, badloopflag2), file=f) f.close() #%% Saving coh_avg, n_unw, and n_loop_err only for good ifgs print('\nSaving coh_avg, n_unw, and n_loop_err...', flush=True) ### Calc coh avg and n_unw coh_avg = np.zeros((length, width), dtype=np.float32) n_coh = np.zeros((length, width), dtype=np.int16) n_unw = np.zeros((length, width), dtype=np.int16) for ifgd in ifgdates_good: ccfile = os.path.join(ifgdir, ifgd, ifgd + '.cc') if os.path.getsize(ccfile) == length * width: coh = io_lib.read_img(ccfile, length, width, np.uint8) coh = coh.astype(np.float32) / 255 else: coh = io_lib.read_img(ccfile, length, width) coh[np.isnan(coh)] = 0 # Fill nan with 0 coh_avg += coh n_coh += (coh != 0) unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') unw = io_lib.read_img(unwfile, length, width) unw[unw == 0] = np.nan # Fill 0 with nan n_unw += ~np.isnan(unw) # Summing number of unnan unw coh_avg[n_coh == 0] = np.nan n_coh[n_coh == 0] = 1 #to avoid zero division coh_avg = coh_avg / n_coh ### Save files n_unwfile = os.path.join(resultsdir, 'n_unw') np.float32(n_unw).tofile(n_unwfile) coh_avgfile = os.path.join(resultsdir, 'coh_avg') coh_avg.tofile(coh_avgfile) n_loop_errfile = os.path.join(resultsdir, 'n_loop_err') np.float32(ns_loop_err).tofile(n_loop_errfile) ### Save png title = 'Average coherence' plot_lib.make_im_png(coh_avg, coh_avgfile + '.png', cmap_noise, title) title = 'Number of used unw data' plot_lib.make_im_png(n_unw, n_unwfile + '.png', cmap_noise, title, n_im) title = 'Number of unclosed loops' plot_lib.make_im_png(ns_loop_err, n_loop_errfile + '.png', cmap_noise_r, title) #%% Link ras ### First, identify suffix of raster image (ras, bmp, or png?) unwfile = os.path.join(ifgdir, ifgdates[0], ifgdates[0] + '.unw') if os.path.exists(unwfile + '.ras'): suffix = '.ras' elif os.path.exists(unwfile + '.bmp'): suffix = '.bmp' elif os.path.exists(unwfile + '.png'): suffix = '.png' for ifgd in ifgdates: rasname = ifgd + '.unw' + suffix rasorg = os.path.join(ifgdir, ifgd, rasname) ### Bad ifgs if ifgd in bad_ifg_all: os.symlink(os.path.relpath(rasorg, bad_ifgrasdir), os.path.join(bad_ifgrasdir, rasname)) ### Remaining bad ifg candidates elif ifgd in bad_ifg_cand_res: os.symlink(os.path.relpath(rasorg, bad_ifg_candrasdir), os.path.join(bad_ifg_candrasdir, rasname)) ### Good ifgs else: os.symlink(os.path.relpath(rasorg, ifg_rasdir), os.path.join(ifg_rasdir, rasname)) if ifgd in no_loop_ifg: os.symlink(os.path.relpath(rasorg, no_loop_ifgrasdir), os.path.join(no_loop_ifgrasdir, rasname)) #%% Plot network ## Read bperp data or dummy bperp_file = os.path.join(ifgdir, 'baselines') if os.path.exists(bperp_file): bperp = io_lib.read_bperp_file(bperp_file, imdates) else: #dummy bperp = np.random.random(n_im).tolist() pngfile = os.path.join(netdir, 'network12_all.png') plot_lib.plot_network(ifgdates, bperp, [], pngfile) pngfile = os.path.join(netdir, 'network12.png') plot_lib.plot_network(ifgdates, bperp, bad_ifg_all, pngfile) pngfile = os.path.join(netdir, 'network12_nobad.png') plot_lib.plot_network(ifgdates, bperp, bad_ifg_all, pngfile, plot_bad=False) ### Network info ## Identify gaps G = inv_lib.make_sb_matrix(ifgdates_good) ixs_inc_gap = np.where(G.sum(axis=0) == 0)[0] ## Connected network ix1 = 0 connected_list = [] for ix2 in np.append(ixs_inc_gap, len(imdates_good) - 1): #append for last image imd1 = imdates_good[ix1] imd2 = imdates_good[ix2] dyear = (dt.datetime.strptime(imd2, '%Y%m%d').toordinal() - dt.datetime.strptime(imd1, '%Y%m%d').toordinal()) / 365.25 n_im_connect = ix2 - ix1 + 1 connected_list.append( [imdates_good[ix1], imdates_good[ix2], dyear, n_im_connect]) ix1 = ix2 + 1 # Next connection #%% Caution about no_loop ifg, remaining large RMS loop and gap ### no_loop ifg if len(no_loop_ifg) != 0: no_loop_ifgfile = os.path.join(infodir, '12no_loop_ifg.txt') with open(no_loop_ifgfile, 'w') as f: print( "\nThere are {} ifgs without loop, recommend to check manually in no_loop_ifg_ras12" .format(len(no_loop_ifg)), flush=True) for ifgd in no_loop_ifg: print('{}'.format(ifgd), flush=True) print('{}'.format(ifgd), file=f) ### Remaining candidates of bad ifgs if len(bad_ifg_cand_res) != 0: print( "\nThere are {} remaining candidates of bad ifgs but not identified." .format(len(bad_ifg_cand_res)), flush=True) print("Check 12bad_ifg_cand_ras and loop/bad_loop_cand_png.", flush=True) # for ifgd in bad_ifg_cand_res: # print('{}'.format(ifgd)) print('\n{0}/{1} ifgs are discarded from further processing.'.format( len(bad_ifg_all), n_ifg), flush=True) for ifgd in bad_ifg_all: print('{}'.format(ifgd), flush=True) ### Gap gap_infofile = os.path.join(infodir, '12network_gap_info.txt') with open(gap_infofile, 'w') as f: if ixs_inc_gap.size != 0: print("Gaps between:", file=f) print("\nGaps in network between:", flush=True) for ix in ixs_inc_gap: print("{} {}".format(imdates_good[ix], imdates_good[ix + 1]), file=f) print("{} {}".format(imdates_good[ix], imdates_good[ix + 1]), flush=True) print("\nConnected network (year, n_image):", file=f) print("\nConnected network (year, n_image):", flush=True) for list1 in connected_list: print("{0}-{1} ({2:.2f}, {3})".format(list1[0], list1[1], list1[2], list1[3]), file=f) print("{0}-{1} ({2:.2f}, {3})".format(list1[0], list1[1], list1[2], list1[3]), flush=True) print( '\nIf you want to change the bad ifgs to be discarded, re-run with different thresholds before next step.', flush=True) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output directory: {}\n'.format(os.path.relpath(tsadir)))
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() ver = 1.2 date = 20210309 author = "Y. Morishita" print("\n{} ver{} {} {}".format(os.path.basename(argv[0]), ver, date, author), flush=True) print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) #%% Set default tsadir = [] memory_size = 4000 gpu = False cmap_noise_r = 'viridis_r' #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "ht:", ["help", "mem_size=", "gpu"]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-t': tsadir = a elif o == '--mem_size': memory_size = float(a) elif o == '--gpu': gpu = True if not tsadir: raise Usage('No tsa directory given, -d is not optional!') elif not os.path.isdir(tsadir): raise Usage('No {} dir exists!'.format(tsadir)) if gpu: print("\nGPU option is activated. Need cupy module.\n") import cupy as cp except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Directory settings tsadir = os.path.abspath(tsadir) resultsdir = os.path.join(tsadir, 'results') #%% Read data information cumh5 = h5.File(os.path.join(tsadir, 'cum.h5'), 'r') imdates = cumh5['imdates'][()].astype(str).tolist() cum = cumh5['cum'] n_im, length, width = cum.shape imdates_dt = [ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates ] dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) #%% Get patch row number n_store_data = n_im * 2.25 + 100 #3:cum,data,M(bool); 100:bootnum n_patch, patchrow = tools_lib.get_patchrow(width, length, n_store_data, memory_size) #%% For each patch for i, rows in enumerate(patchrow): print('\nProcess {0}/{1}th line ({2}/{3}th patch)...'.format( rows[1], patchrow[-1][-1], i + 1, n_patch), flush=True) start2 = time.time() lengththis = rows[1] - rows[0] #%% Calc STC print(' Calculating STC...', flush=True) ### Read data with extra 1 line for overlapping row_ex1 = 0 if i == 0 else 1 ## first patch row_ex2 = 0 if i == len(patchrow) - 1 else 1 ## last patch _cum = cum[:, rows[0] - row_ex1:rows[1] + row_ex2, :].reshape( n_im, lengththis + row_ex1 + row_ex2, width) ### Calc STC stc = inv_lib.calc_stc(_cum, gpu=gpu)[row_ex1:lengththis + row_ex1, :] ## original length del _cum ### Output data and image stcfile = os.path.join(resultsdir, 'stc') openmode = 'w' if i == 0 else 'a' #w only 1st patch with open(stcfile, openmode) as f: stc.tofile(f) #%% Calc vstd ### Read data for vstd n_pt_all = lengththis * width cum_patch = cum[:, rows[0]:rows[1], :].reshape( (n_im, n_pt_all)).transpose() #(n_pt_all, n_im) ### Remove invalid points bool_unnan_pt = ~np.isnan(cum_patch[:, 0]) cum_patch = cum_patch[bool_unnan_pt, :] ## remain only unnan data n_pt_unnan = bool_unnan_pt.sum() print(' {}/{} points removed due to no data...'.format( n_pt_all - n_pt_unnan, n_pt_all), flush=True) ### Calc vstd by bootstrap vstd = np.zeros((n_pt_all), dtype=np.float32) * np.nan print(' Calculating std of velocity by bootstrap...', flush=True) vstd[bool_unnan_pt] = inv_lib.calc_velstd_withnan(cum_patch, dt_cum, gpu=gpu) ### Output data and image vstdfile = os.path.join(resultsdir, 'vstd') openmode = 'w' if i == 0 else 'a' #w only 1st patch with open(vstdfile, openmode) as f: vstd.tofile(f) #%% Finish patch elapsed_time2 = int(time.time() - start2) print(' Elapsed time for {0}th patch: {1} sec'.format( i + 1, elapsed_time2)) #%% Close h5 file cumh5.close() #%% Output png print('\nOutput png images...') stc = io_lib.read_img(stcfile, length, width) pngfile = stcfile + '.png' title = 'Spatio-temporal consistency (mm)' cmin = np.nanpercentile(stc, 1) cmax = np.nanpercentile(stc, 99) plot_lib.make_im_png(stc, pngfile, cmap_noise_r, title, cmin, cmax) vstd = io_lib.read_img(vstdfile, length, width) pngfile = vstdfile + '.png' title = 'STD of velocity (mm/yr)' cmin = np.nanpercentile(vstd, 1) cmax = np.nanpercentile(vstd, 99) plot_lib.make_im_png(vstd, pngfile, cmap_noise_r, title, cmin, cmax) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output directory: {}\n'.format(os.path.relpath(tsadir)))
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() ver = 1.3 date = 20200909 author = "Y. Morishita" print("\n{} ver{} {} {}".format(os.path.basename(argv[0]), ver, date, author), flush=True) print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) ## for parallel processing global cum, mask, deg_ramp, hgt_linearflag, hgt, hgt_min, hgt_max,\ filtcumdir, filtincdir, imdates, cycle, coef_r2m, models, \ filtwidth_yr, filtwidth_km, dt_cum, x_stddev, y_stddev ## global cum_org from hdf5 contaminate in paralell warpper? So pass them by arg. #%% Set default tsadir = [] filtwidth_km = 2 filtwidth_yr = [] deg_ramp = [] hgt_linearflag = False hgt_min = 200 ## meter hgt_max = 10000 ## meter maskflag = True n_para = len(os.sched_getaffinity(0)) cumname = 'cum.h5' cmap_vel = SCM.roma.reversed() cmap_noise_r = 'viridis_r' #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "ht:s:y:r:", [ "help", "hgt_linear", "hgt_min=", "hgt_max=", "nomask", "n_para=" ]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-t': tsadir = a elif o == '-s': filtwidth_km = float(a) elif o == '-y': filtwidth_yr = float(a) elif o == '-r': deg_ramp = a elif o == '--hgt_linear': hgt_linearflag = True elif o == '--hgt_min': hgt_min = int(a) elif o == '--hgt_max': hgt_max = int(a) elif o == '--nomask': maskflag = False elif o == '--n_para': n_para = int(a) if not tsadir: raise Usage('No tsa directory given, -t is not optional!') elif not os.path.isdir(tsadir): raise Usage('No {} dir exists!'.format(tsadir)) elif not os.path.exists(os.path.join(tsadir, cumname)): raise Usage('No {} exists in {}!'.format(cumname, tsadir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Directory and file setting tsadir = os.path.abspath(tsadir) cumfile = os.path.join(tsadir, cumname) resultsdir = os.path.join(tsadir, 'results') infodir = os.path.join(tsadir, 'info') inparmfile = os.path.join(infodir, '13parameters.txt') if not os.path.exists(inparmfile): ## for old LiCSBAS13 <v1.2 inparmfile = os.path.join(infodir, 'parameters.txt') outparmfile = os.path.join(infodir, '16parameters.txt') pixsp_r = float(io_lib.get_param_par(inparmfile, 'pixel_spacing_r')) pixsp_a = float(io_lib.get_param_par(inparmfile, 'pixel_spacing_a')) x_stddev = filtwidth_km * 1000 / pixsp_r y_stddev = filtwidth_km * 1000 / pixsp_a wavelength = float(io_lib.get_param_par(inparmfile, 'wavelength')) #meter coef_r2m = -wavelength / 4 / np.pi * 1000 #rad -> mm, positive is -LOS if wavelength > 0.2: ## L-band cycle = 1.5 # 2pi/cycle for comparison png elif wavelength <= 0.2: ## C-band cycle = 3 # 3*2pi/cycle for comparison png filtincdir = os.path.join(tsadir, '16filt_increment') if os.path.exists(filtincdir): shutil.rmtree(filtincdir) os.mkdir(filtincdir) filtcumdir = os.path.join(tsadir, '16filt_cum') if os.path.exists(filtcumdir): shutil.rmtree(filtcumdir) os.mkdir(filtcumdir) cumffile = os.path.join(tsadir, 'cum_filt.h5') vconstfile = os.path.join(resultsdir, 'vintercept.filt') velfile = os.path.join(resultsdir, 'vel.filt') cumh5 = h5.File(cumfile, 'r') if os.path.exists(cumffile): os.remove(cumffile) cumfh5 = h5.File(cumffile, 'w') #%% Dates imdates = cumh5['imdates'][()].astype(str).tolist() cum_org = cumh5['cum'] n_im, length, width = cum_org.shape if n_para > n_im: n_para = n_im ### Calc dt in year imdates_dt = ([ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates ]) dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) ### Save dates and other info into cumf cumfh5.create_dataset('imdates', data=cumh5['imdates']) cumfh5.create_dataset('gap', data=cumh5['gap']) if 'bperp' in list(cumh5.keys()): ## if dummy, no bperp field cumfh5.create_dataset('bperp', data=cumh5['bperp']) else: print('No bperp field found in {}. Skip.'.format(cumname)) if 'corner_lat' in list(cumh5.keys()): lat1 = float(cumh5['corner_lat'][()]) lon1 = float(cumh5['corner_lon'][()]) dlat = float(cumh5['post_lat'][()]) dlon = float(cumh5['post_lon'][()]) cumfh5.create_dataset('corner_lat', data=cumh5['corner_lat']) cumfh5.create_dataset('corner_lon', data=cumh5['corner_lon']) cumfh5.create_dataset('post_lat', data=cumh5['post_lat']) cumfh5.create_dataset('post_lon', data=cumh5['post_lon']) else: ## not geocoded print('No latlon field found in {}. Skip.'.format(cumname)) ### temporal filter width if not filtwidth_yr and filtwidth_yr != 0: filtwidth_yr = dt_cum[-1] / (n_im - 1) * 3 ## avg interval*3 ### hgt_linear if hgt_linearflag: hgtfile = os.path.join(resultsdir, 'hgt') if not os.path.exists(hgtfile): print('\nERROR: No hgt file exist in results dir!', file=sys.stderr) print('--hgt_linear option cannot be used.', file=sys.stderr) return 2 hgt = io_lib.read_img(hgtfile, length, width) hgt[np.isnan(hgt)] = 0 else: hgt = [] #%% Display settings print('') print('Size of image (w,l) : {0}, {1}'.format(width, length)) print('Number of images : {}'.format(n_im)) print('Width of filter in space : {} km ({:.1f}x{:.1f} pixel)'.format( filtwidth_km, x_stddev, y_stddev)) print('Width of filter in time : {:.3f} yr ({} days)'.format( filtwidth_yr, int(filtwidth_yr * 365.25))) print('Deramp flag : {}'.format(deg_ramp), flush=True) print('hgt-linear flag : {}'.format(hgt_linearflag), flush=True) if hgt_linearflag: print('Minimum hgt : {} m'.format(hgt_min), flush=True) print('Maximum hgt : {} m'.format(hgt_max), flush=True) with open(outparmfile, "w") as f: print('filtwidth_km: {}'.format(filtwidth_km), file=f) print('filtwidth_xpixels: {:.1f}'.format(x_stddev), file=f) print('filtwidth_ypixels: {:.1f}'.format(y_stddev), file=f) print('filtwidth_yr: {:.3f}'.format(filtwidth_yr), file=f) print('filtwidth_day: {}'.format(int(filtwidth_yr * 365.25)), file=f) print('deg_ramp: {}'.format(deg_ramp), file=f) print('hgt_linear: {}'.format(hgt_linearflag * 1), file=f) print('hgt_min: {}'.format(hgt_min), file=f) print('hgt_max: {}'.format(hgt_max), file=f) #%% Load Mask (1: unmask, 0: mask, nan: no cum data) if maskflag: maskfile = os.path.join(resultsdir, 'mask') mask = io_lib.read_img(maskfile, length, width) mask[mask == 0] = np.nan ## 0->nan else: mask = np.ones((length, width), dtype=np.float32) mask[np.isnan(cum_org[0, :, :])] = np.nan #%% First, deramp and hgt-linear if indicated cum = np.zeros((cum_org.shape), dtype=np.float32) * np.nan if not deg_ramp and not hgt_linearflag: cum = cum_org[()] else: if not deg_ramp: print('\nEstimate hgt-linear component,', flush=True) elif not hgt_linearflag: print('\nDeramp ifgs with the degree of {},'.format(deg_ramp), flush=True) else: print('\nDeramp ifgs with the degree of {} and hgt-linear,'.format( deg_ramp), flush=True) print('with {} parallel processing...'.format(n_para), flush=True) args = [(i, cum_org[i, :, :]) for i in range(n_im)] ### Parallel processing p = multi.Pool(n_para) _result = np.array(p.map(deramp_wrapper, args), dtype=object) p.close() del args models = _result[:, 1] for i in range(n_im): cum[i, :, :] = _result[i, 0] del _result ### Only for output increment png files print( '\nCreate png for increment with {} parallel processing...'.format( n_para), flush=True) args = [(i, cum_org[i, :, :], cum_org[i - 1, :, :]) for i in range(1, n_im)] p = multi.Pool(n_para) p.map(deramp_wrapper2, args) p.close() del args #%% Filter each image cum_filt = cumfh5.require_dataset('cum', (n_im, length, width), dtype=np.float32) print('\nHP filter in time, LP filter in space,', flush=True) print('with {} parallel processing...'.format(n_para), flush=True) ### Parallel processing p = multi.Pool(n_para) cum_filt[:, :, :] = np.array(p.map(filter_wrapper, range(n_im)), dtype=np.float32) p.close() ### Only for output increment png files print('\nCreate png for increment with {} parallel processing...'.format( n_para), flush=True) args = [(i, cum_filt[i, :, :] - cum_filt[i - 1, :, :]) for i in range(1, n_im)] p = multi.Pool(n_para) p.map(filter_wrapper2, args) p.close() del args #%% Find stable ref point print('\nFind stable reference point...', flush=True) ### Compute RMS of time series with reference to all points sumsq_cum_wrt_med = np.zeros((length, width), dtype=np.float32) for i in range(n_im): sumsq_cum_wrt_med = sumsq_cum_wrt_med + ( cum_filt[i, :, :] - np.nanmedian(cum_filt[i, :, :]))**2 rms_cum_wrt_med = np.sqrt(sumsq_cum_wrt_med / n_im) * mask ### Mask by minimum n_gap n_gap = io_lib.read_img(os.path.join(resultsdir, 'n_gap'), length, width) min_n_gap = np.nanmin(n_gap) mask_n_gap = np.float32(n_gap == min_n_gap) mask_n_gap[mask_n_gap == 0] = np.nan rms_cum_wrt_med = rms_cum_wrt_med * mask_n_gap ### Find stable reference min_rms = np.nanmin(rms_cum_wrt_med) refy1s, refx1s = np.where(rms_cum_wrt_med == min_rms) refy1s, refx1s = refy1s[0], refx1s[0] ## Only first index refy2s, refx2s = refy1s + 1, refx1s + 1 print('Selected ref: {}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s), flush=True) ### Rerferencing cumulative displacement to new stable ref for i in range(n_im): cum_filt[i, :, :] = cum_filt[i, :, :] - cum[i, refy1s, refx1s] ### Save image rms_cum_wrt_med_file = os.path.join(infodir, '16rms_cum_wrt_med') with open(rms_cum_wrt_med_file, 'w') as f: rms_cum_wrt_med.tofile(f) pngfile = os.path.join(infodir, '16rms_cum_wrt_med.png') plot_lib.make_im_png(rms_cum_wrt_med, pngfile, cmap_noise_r, 'RMS of cum wrt median (mm)', np.nanpercentile(rms_cum_wrt_med, 1), np.nanpercentile(rms_cum_wrt_med, 99)) ### Save ref cumfh5.create_dataset('refarea', data='{}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s)) refsfile = os.path.join(infodir, '16ref.txt') with open(refsfile, 'w') as f: print('{}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s), file=f) if 'corner_lat' in list(cumh5.keys()): ## Geocoded ### Make ref_stable.kml reflat = lat1 + dlat * refy1s reflon = lon1 + dlon * refx1s io_lib.make_point_kml(reflat, reflon, os.path.join(infodir, '16ref.kml')) #%% Calc filtered velocity print('\nCalculate velocity of filtered time series...', flush=True) G = np.stack((np.ones_like(dt_cum), dt_cum), axis=1) vconst = np.zeros((length, width), dtype=np.float32) * np.nan vel = np.zeros((length, width), dtype=np.float32) * np.nan bool_unnan = ~np.isnan(cum_filt[0, :, :]).reshape(length, width) ## not all nan cum_pt = cum_filt[()].reshape(n_im, length * width)[:, bool_unnan.ravel()] #n_im x n_pt n_pt_unnan = bool_unnan.sum() vconst_tmp = np.zeros((n_pt_unnan), dtype=np.float32) * np.nan vel_tmp = np.zeros((n_pt_unnan), dtype=np.float32) * np.nan bool_nonan_pt = np.all(~np.isnan(cum_pt), axis=0) ### First, calc vel point without nan print(' First, solving {0:6}/{1:6}th points with full cum...'.format( bool_nonan_pt.sum(), n_pt_unnan), flush=True) vconst_tmp[bool_nonan_pt], vel_tmp[bool_nonan_pt] = np.linalg.lstsq( G, cum_pt[:, bool_nonan_pt], rcond=None)[0] ### Next, calc vel point with nan print(' Next, solving {0:6}/{1:6}th points with nan in cum...'.format( (~bool_nonan_pt).sum(), n_pt_unnan), flush=True) mask_cum = ~np.isnan(cum_pt[:, ~bool_nonan_pt]) vconst_tmp[~bool_nonan_pt], vel_tmp[ ~bool_nonan_pt] = inv_lib.censored_lstsq_slow( G, cum_pt[:, ~bool_nonan_pt], mask_cum) vconst[bool_unnan], vel[bool_unnan] = vconst_tmp, vel_tmp vconst.tofile(vconstfile) vel.tofile(velfile) if maskflag: vel_mskd = vel * mask vconst_mskd = vconst * mask vconst_mskd.tofile(vconstfile + '.mskd') vel_mskd.tofile(velfile + '.mskd') cumfh5.create_dataset('vel', data=vel.reshape(length, width)) cumfh5.create_dataset('vintercept', data=vconst.reshape(length, width)) #%% Add info and close cumfh5.create_dataset('filtwidth_yr', data=filtwidth_yr) cumfh5.create_dataset('filtwidth_km', data=filtwidth_km) cumfh5.create_dataset('deramp_flag', data=deg_ramp) cumfh5.create_dataset('hgt_linear_flag', data=hgt_linearflag * 1) cumh5.close() cumfh5.close() #%% Output image pngfile = os.path.join(resultsdir, 'vel.filt.png') title = 'Filtered velocity (mm/yr)' vmin = np.nanpercentile(vel, 1) vmax = np.nanpercentile(vel, 99) plot_lib.make_im_png(vel, pngfile, cmap_vel, title, vmin, vmax) ## vintercept pngfile = os.path.join(resultsdir, 'vintercept.filt.png') title = 'Intercept of filtered velocity (mm)' vmin = np.nanpercentile(vconst, 1) vmax = np.nanpercentile(vconst, 99) plot_lib.make_im_png(vconst, pngfile, cmap_vel, title, vmin, vmax) if maskflag: pngfile = os.path.join(resultsdir, 'vel.filt.mskd.png') title = 'Masked filtered velocity (mm/yr)' vmin = np.nanpercentile(vel_mskd, 1) vmax = np.nanpercentile(vel_mskd, 99) plot_lib.make_im_png(vel_mskd, pngfile, cmap_vel, title, vmin, vmax) ## vintercept pngfile = os.path.join(resultsdir, 'vintercept.filt.mskd.png') title = 'Masked intercept of filtered velocity (mm)' vmin = np.nanpercentile(vconst_mskd, 1) vmax = np.nanpercentile(vconst_mskd, 99) plot_lib.make_im_png(vconst_mskd, pngfile, cmap_vel, title, vmin, vmax) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output: {}\n'.format(os.path.relpath(cumffile)), flush=True) print('To plot the time-series:') print('LiCSBAS_plot_ts.py -i {} &\n'.format(os.path.relpath(cumffile)))
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() ver = "1.4.8" date = 20210127 author = "Y. Morishita" print("\n{} ver{} {} {}".format(os.path.basename(argv[0]), ver, date, author), flush=True) print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) ## For parallel processing global n_para_gap, G, Aloop, unwpatch, imdates, incdir, ifgdir, length, width,\ coef_r2m, ifgdates, ref_unw, cycle, keep_incfile, resdir, restxtfile, \ cmap_vel, cmap_wrap, wavelength #%% Set default ifgdir = [] tsadir = [] inv_alg = 'LS' try: n_para = len(os.sched_getaffinity(0)) except: n_para = multi.cpu_count() n_para_inv = 1 memory_size = 4000 gamma = 0.0001 n_unw_r_thre = [] keep_incfile = False cmap_vel = SCM.roma.reversed() cmap_noise = 'viridis' cmap_noise_r = 'viridis_r' cmap_wrap = SCM.romaO # q = multi.get_context('fork') q = multi.get_context('spawn') compress = 'gzip' #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "hd:t:", [ "help", "mem_size=", "gamma=", "n_unw_r_thre=", "keep_incfile", "inv_alg=", "n_para=" ]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-d': ifgdir = a elif o == '-t': tsadir = a elif o == '--mem_size': memory_size = float(a) elif o == '--gamma': gamma = float(a) elif o == '--n_unw_r_thre': n_unw_r_thre = float(a) elif o == '--keep_incfile': keep_incfile = True elif o == '--inv_alg': inv_alg = a elif o == '--n_para': n_para = int(a) if not ifgdir: raise Usage('No data directory given, -d is not optional!') elif not os.path.isdir(ifgdir): raise Usage('No {} dir exists!'.format(ifgdir)) elif not os.path.exists(os.path.join(ifgdir, 'slc.mli.par')): raise Usage('No slc.mli.par file exists in {}!'.format(ifgdir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Directory settings ifgdir = os.path.abspath(ifgdir) if not tsadir: tsadir = os.path.join(os.path.dirname(ifgdir), 'TS_' + os.path.basename(ifgdir)) if not os.path.isdir(tsadir): print('\nNo {} exists!'.format(tsadir), file=sys.stderr) return 1 tsadir = os.path.abspath(tsadir) resultsdir = os.path.join(tsadir, 'results') infodir = os.path.join(tsadir, 'info') netdir = os.path.join(tsadir, 'network') bad_ifg11file = os.path.join(infodir, '11bad_ifg.txt') bad_ifg12file = os.path.join(infodir, '12bad_ifg.txt') reffile = os.path.join(infodir, '12ref.txt') if not os.path.exists(reffile): ## for old LiCSBAS12 < v1.1 reffile = os.path.join(infodir, 'ref.txt') incdir = os.path.join(tsadir, '13increment') if not os.path.exists(incdir): os.mkdir(incdir) resdir = os.path.join(tsadir, '13resid') if not os.path.exists(resdir): os.mkdir(resdir) restxtfile = os.path.join(infodir, '13resid.txt') cumh5file = os.path.join(tsadir, 'cum.h5') #%% Check files try: if not os.path.exists(bad_ifg11file): raise Usage('No 11bad_ifg.txt file exists in {}!'.format(infodir)) if not os.path.exists(bad_ifg12file): raise Usage('No 12bad_ifg.txt file exists in {}!'.format(infodir)) if not os.path.exists(reffile): raise Usage('No 12ref.txt file exists in {}!'.format(infodir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Set preliminaly reference with open(reffile, "r") as f: refarea = f.read().split()[0] #str, x1/x2/y1/y2 refx1, refx2, refy1, refy2 = [int(s) for s in re.split('[:/]', refarea)] #%% Check RAM mem_avail = (psutil.virtual_memory().available) / 2**20 #MB if memory_size > mem_avail / 2: print('\nNot enough memory available compared to mem_size ({} MB).'. format(memory_size)) print('Reduce mem_size automatically to {} MB.'.format( int(mem_avail / 2))) memory_size = int(mem_avail / 2) #%% Read data information ### Get size mlipar = os.path.join(ifgdir, 'slc.mli.par') width = int(io_lib.get_param_par(mlipar, 'range_samples')) length = int(io_lib.get_param_par(mlipar, 'azimuth_lines')) speed_of_light = 299792458 #m/s radar_frequency = float(io_lib.get_param_par(mlipar, 'radar_frequency')) #Hz wavelength = speed_of_light / radar_frequency #meter coef_r2m = -wavelength / 4 / np.pi * 1000 #rad -> mm, positive is -LOS ### Calc pixel spacing depending on IFG or GEOC, used in later spatial filter dempar = os.path.join(ifgdir, 'EQA.dem_par') width_geo = int(io_lib.get_param_par(dempar, 'width')) length_geo = int(io_lib.get_param_par(dempar, 'nlines')) dlat = float(io_lib.get_param_par(dempar, 'post_lat')) #negative dlon = float(io_lib.get_param_par(dempar, 'post_lon')) #positive lat1 = float(io_lib.get_param_par(dempar, 'corner_lat')) lon1 = float(io_lib.get_param_par(dempar, 'corner_lon')) if width == width_geo and length == length_geo: ## Geocoded print('\nIn geographical coordinates', flush=True) centerlat = lat1 + dlat * (length / 2) ra = float(io_lib.get_param_par(dempar, 'ellipsoid_ra')) recip_f = float( io_lib.get_param_par(dempar, 'ellipsoid_reciprocal_flattening')) rb = ra * (1 - 1 / recip_f) ## polar radius pixsp_a = 2 * np.pi * rb / 360 * abs(dlat) pixsp_r = 2 * np.pi * ra / 360 * dlon * np.cos(np.deg2rad(centerlat)) else: print('\nIn radar coordinates', flush=True) pixsp_r_org = float(io_lib.get_param_par(mlipar, 'range_pixel_spacing')) pixsp_a = float(io_lib.get_param_par(mlipar, 'azimuth_pixel_spacing')) inc_agl = float(io_lib.get_param_par(mlipar, 'incidence_angle')) pixsp_r = pixsp_r_org / np.sin(np.deg2rad(inc_agl)) ### Set n_unw_r_thre and cycle depending on L- or C-band if wavelength > 0.2: ## L-band if not n_unw_r_thre: n_unw_r_thre = 0.5 cycle = 1.5 # 2pi/cycle for comparison png elif wavelength <= 0.2: ## C-band if not n_unw_r_thre: n_unw_r_thre = 1.0 cycle = 3 # 3*2pi/cycle for comparison png #%% Read date and network information ### Get all ifgdates in ifgdir ifgdates_all = tools_lib.get_ifgdates(ifgdir) imdates_all = tools_lib.ifgdates2imdates(ifgdates_all) n_im_all = len(imdates_all) n_ifg_all = len(ifgdates_all) ### Read bad_ifg11 and 12 bad_ifg11 = io_lib.read_ifg_list(bad_ifg11file) bad_ifg12 = io_lib.read_ifg_list(bad_ifg12file) bad_ifg_all = list(set(bad_ifg11 + bad_ifg12)) bad_ifg_all.sort() ### Remove bad ifgs and images from list ifgdates = list(set(ifgdates_all) - set(bad_ifg_all)) ifgdates.sort() imdates = tools_lib.ifgdates2imdates(ifgdates) n_ifg = len(ifgdates) n_ifg_bad = len(set(bad_ifg11 + bad_ifg12)) n_im = len(imdates) n_unw_thre = int(n_unw_r_thre * n_im) ### Make 13used_image.txt imfile = os.path.join(infodir, '13used_image.txt') with open(imfile, 'w') as f: for i in imdates: print('{}'.format(i), file=f) ### Calc dt in year imdates_dt = ([ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates ]) dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) ### Construct G and Aloop matrix for increment and n_gap G = inv_lib.make_sb_matrix(ifgdates) Aloop = loop_lib.make_loop_matrix(ifgdates) #%% Plot network ## Read bperp data or dummy bperp_file = os.path.join(ifgdir, 'baselines') if os.path.exists(bperp_file): bperp_all = io_lib.read_bperp_file(bperp_file, imdates_all) bperp = io_lib.read_bperp_file(bperp_file, imdates) else: #dummy bperp_all = np.random.random(len(imdates_all)).tolist() bperp = np.random.random(n_im).tolist() pngfile = os.path.join(netdir, 'network13_all.png') plot_lib.plot_network(ifgdates_all, bperp_all, [], pngfile) pngfile = os.path.join(netdir, 'network13.png') plot_lib.plot_network(ifgdates_all, bperp_all, bad_ifg_all, pngfile) pngfile = os.path.join(netdir, 'network13_nobad.png') plot_lib.plot_network(ifgdates_all, bperp_all, bad_ifg_all, pngfile, plot_bad=False) #%% Get patch row number if inv_alg == 'WLS': n_store_data = n_ifg * 3 + n_im * 2 + n_im * 0.3 # else: n_store_data = n_ifg * 2 + n_im * 2 + n_im * 0.3 #not sure n_patch, patchrow = tools_lib.get_patchrow(width, length, n_store_data, memory_size) #%% Display and output settings & parameters print('') print('Size of image (w,l) : {}, {}'.format(width, length)) print('# of all images : {}'.format(n_im_all)) print('# of images to be used : {}'.format(n_im)) print('# of all ifgs : {}'.format(n_ifg_all)) print('# of ifgs to be used : {}'.format(n_ifg)) print('# of removed ifgs : {}'.format(n_ifg_bad)) print('Threshold of used unw : {}'.format(n_unw_thre)) print('') print('Reference area (X/Y) : {}:{}/{}:{}'.format( refx1, refx2, refy1, refy2)) print('Allowed memory size : {} MB'.format(memory_size)) print('Number of patches : {}'.format(n_patch)) print('Inversion algorism : {}'.format(inv_alg)) print('Gamma value : {}'.format(gamma), flush=True) with open(os.path.join(infodir, '13parameters.txt'), "w") as f: print('range_samples: {}'.format(width), file=f) print('azimuth_lines: {}'.format(length), file=f) print('wavelength: {}'.format(wavelength), file=f) print('n_im_all: {}'.format(n_im_all), file=f) print('n_im: {}'.format(n_im), file=f) print('n_ifg_all: {}'.format(n_ifg_all), file=f) print('n_ifg: {}'.format(n_ifg), file=f) print('n_ifg_bad: {}'.format(n_ifg_bad), file=f) print('n_unw_thre: {}'.format(n_unw_thre), file=f) print('ref_area: {}:{}/{}:{}'.format(refx1, refx2, refy1, refy2), file=f) print('memory_size: {} MB'.format(memory_size), file=f) print('n_patch: {}'.format(n_patch), file=f) print('inv_alg: {}'.format(inv_alg), file=f) print('gamma: {}'.format(gamma), file=f) print('pixel_spacing_r: {:.2f} m'.format(pixsp_r), file=f) print('pixel_spacing_a: {:.2f} m'.format(pixsp_a), file=f) #%% Ref phase for inversion lengththis = refy2 - refy1 countf = width * refy1 countl = width * lengththis # Number to be read ref_unw = [] for i, ifgd in enumerate(ifgdates): unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') f = open(unwfile, 'rb') f.seek(countf * 4, os.SEEK_SET) #Seek for >=2nd path, 4 means byte ### Read unw data (mm) at ref area unw = np.fromfile(f, dtype=np.float32, count=countl).reshape( (lengththis, width))[:, refx1:refx2] * coef_r2m unw[unw == 0] = np.nan if np.all(np.isnan(unw)): print('All nan in ref area in {}.'.format(ifgd)) print('Rerun LiCSBAS12.') return 1 ref_unw.append(np.nanmean(unw)) f.close() #%% Open cum.h5 for output if os.path.exists(cumh5file): os.remove(cumh5file) cumh5 = h5.File(cumh5file, 'w') cumh5.create_dataset('imdates', data=[np.int32(imd) for imd in imdates]) if not np.all(np.abs(np.array(bperp)) <= 1): # if not dummy cumh5.create_dataset('bperp', data=bperp) cum = cumh5.require_dataset('cum', (n_im, length, width), dtype=np.float32, compression=compress) vel = cumh5.require_dataset('vel', (length, width), dtype=np.float32, compression=compress) vconst = cumh5.require_dataset('vintercept', (length, width), dtype=np.float32, compression=compress) gap = cumh5.require_dataset('gap', (n_im - 1, length, width), dtype=np.int8, compression=compress) if width == width_geo and length == length_geo: ## if geocoded cumh5.create_dataset('corner_lat', data=lat1) cumh5.create_dataset('corner_lon', data=lon1) cumh5.create_dataset('post_lat', data=dlat) cumh5.create_dataset('post_lon', data=dlon) #%% For each patch for i_patch, rows in enumerate(patchrow): print('\nProcess {0}/{1}th line ({2}/{3}th patch)...'.format( rows[1], patchrow[-1][-1], i_patch + 1, n_patch), flush=True) start2 = time.time() #%% Read data ### Allocate memory lengththis = rows[1] - rows[0] n_pt_all = lengththis * width unwpatch = np.zeros((n_ifg, lengththis, width), dtype=np.float32) if inv_alg == 'WLS': cohpatch = np.zeros((n_ifg, lengththis, width), dtype=np.float32) ### For each ifg print(" Reading {0} ifg's unw data...".format(n_ifg), flush=True) countf = width * rows[0] countl = width * lengththis for i, ifgd in enumerate(ifgdates): unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') f = open(unwfile, 'rb') f.seek(countf * 4, os.SEEK_SET) #Seek for >=2nd patch, 4 means byte ### Read unw data (mm) at patch area unw = np.fromfile(f, dtype=np.float32, count=countl).reshape( (lengththis, width)) * coef_r2m unw[unw == 0] = np.nan # Fill 0 with nan unw = unw - ref_unw[i] unwpatch[i] = unw f.close() ### Read coh file at patch area for WLS if inv_alg == 'WLS': cohfile = os.path.join(ifgdir, ifgd, ifgd + '.cc') f = open(cohfile, 'rb') if os.path.getsize(cohfile) == length * width: ## uint8 format f.seek(countf, os.SEEK_SET) #Seek for >=2nd patch cohpatch[i, :, :] = (np.fromfile( f, dtype=np.uint8, count=countl).reshape( (lengththis, width))).astype(np.float32) / 255 else: ## old float32 format f.seek(countf * 4, os.SEEK_SET) #Seek for >=2nd patch, 4 means byte cohpatch[i, :, :] = np.fromfile(f, dtype=np.float32, count=countl).reshape( (lengththis, width)) cohpatch[cohpatch == 0] = np.nan unwpatch = unwpatch.reshape( (n_ifg, n_pt_all)).transpose() #(n_pt_all, n_ifg) ### Calc variance from coherence for WLS if inv_alg == 'WLS': cohpatch = cohpatch.reshape( (n_ifg, n_pt_all)).transpose() #(n_pt_all, n_ifg) cohpatch[ cohpatch < 0.01] = 0.01 ## because negative value possible due to geocode cohpatch[ cohpatch > 0.99] = 0.99 ## because >1 possible due to geocode varpatch = (1 - cohpatch**2) / (2 * cohpatch**2) del cohpatch #%% Remove points with less valid data than n_unw_thre ix_unnan_pt = np.where( np.sum(~np.isnan(unwpatch), axis=1) > n_unw_thre)[0] n_pt_unnan = len(ix_unnan_pt) unwpatch = unwpatch[ix_unnan_pt, :] ## keep only unnan data if inv_alg == 'WLS': varpatch = varpatch[ix_unnan_pt, :] ## keep only unnan data print(' {}/{} points removed due to not enough ifg data...'.format( n_pt_all - n_pt_unnan, n_pt_all), flush=True) #%% Compute number of gaps, ifg_noloop, maxTlen point-by-point if n_pt_unnan != 0: ns_gap_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan gap_patch = np.zeros((n_im - 1, n_pt_all), dtype=np.int8) ns_ifg_noloop_patch = np.zeros( (n_pt_all), dtype=np.float32) * np.nan maxTlen_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan ### Determine n_para n_pt_patch_min = 1000 if n_pt_patch_min * n_para > n_pt_unnan: ## Too much n_para n_para_gap = int(np.floor(n_pt_unnan / n_pt_patch_min)) if n_para_gap == 0: n_para_gap = 1 else: n_para_gap = n_para print('\n Identifing gaps, and counting n_gap and n_ifg_noloop,') print(' with {} parallel processing...'.format(n_para_gap), flush=True) ### Devide unwpatch by n_para for parallel processing p = q.Pool(n_para_gap) # _result = np.array(p.map(count_gaps_wrapper, range(n_para_gap)), dtype=object) _result = np.array(p.map(count_gaps_wrapper, [(i, n_para_gap, G, Aloop, unwpatch) for i in range(n_para_gap)]), dtype=object) p.close() ns_gap_patch[ix_unnan_pt] = np.hstack(_result[:, 0]) #n_pt gap_patch[:, ix_unnan_pt] = np.hstack(_result[:, 1]) #n_im-1, n_pt ns_ifg_noloop_patch[ix_unnan_pt] = np.hstack(_result[:, 2]) ### maxTlen _maxTlen = np.zeros((n_pt_unnan), dtype=np.float32) #temporaly _Tlen = np.zeros((n_pt_unnan), dtype=np.float32) #temporaly for imx in range(n_im - 1): _Tlen = _Tlen + (dt_cum[imx + 1] - dt_cum[imx]) ## Adding dt _Tlen[gap_patch[imx, ix_unnan_pt] == 1] = 0 ## reset to 0 if gap _maxTlen[_maxTlen < _Tlen] = _Tlen[ _maxTlen < _Tlen] ## Set Tlen to maxTlen maxTlen_patch[ix_unnan_pt] = _maxTlen #%% Time series inversion print('\n Small Baseline inversion by {}...\n'.format(inv_alg), flush=True) if inv_alg == 'WLS': inc_tmp, vel_tmp, vconst_tmp = inv_lib.invert_nsbas_wls( unwpatch, varpatch, G, dt_cum, gamma, n_para_inv) else: inc_tmp, vel_tmp, vconst_tmp = inv_lib.invert_nsbas( unwpatch, G, dt_cum, gamma, n_para_inv) ### Set to valuables inc_patch = np.zeros( (n_im - 1, n_pt_all), dtype=np.float32) * np.nan vel_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan vconst_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan inc_patch[:, ix_unnan_pt] = inc_tmp vel_patch[ix_unnan_pt] = vel_tmp vconst_patch[ix_unnan_pt] = vconst_tmp ### Calculate residuals res_patch = np.zeros((n_ifg, n_pt_all), dtype=np.float32) * np.nan res_patch[:, ix_unnan_pt] = unwpatch.T - np.dot(G, inc_tmp) res_sumsq = np.nansum(res_patch**2, axis=0) res_n = np.float32((~np.isnan(res_patch)).sum(axis=0)) res_n[res_n == 0] = np.nan # To avoid 0 division res_rms_patch = np.sqrt(res_sumsq / res_n) ### Cumulative displacememt cum_patch = np.zeros((n_im, n_pt_all), dtype=np.float32) * np.nan cum_patch[1:, :] = np.cumsum(inc_patch, axis=0) ## Fill 1st image with 0 at unnan points from 2nd images bool_unnan_pt = ~np.isnan(cum_patch[1, :]) cum_patch[0, bool_unnan_pt] = 0 ## Drop (fill with nan) interpolated cum by 2 continuous gaps for i in range(n_im - 2): ## from 1->n_im-1 gap2 = gap_patch[i, :] + gap_patch[i + 1, :] bool_gap2 = (gap2 == 2 ) ## true if 2 continuous gaps for each point cum_patch[i + 1, :][bool_gap2] = np.nan ## Last (n_im th) image. 1 gap means interpolated cum_patch[-1, :][gap_patch[-1, :] == 1] = np.nan #%% Fill by np.nan if n_pt_unnan == 0 else: cum_patch = np.zeros((n_im, n_pt_all), dtype=np.float32) * np.nan vel_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan vconst_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan gap_patch = np.zeros((n_im - 1, n_pt_all), dtype=np.int8) inc_patch = np.zeros( (n_im - 1, n_pt_all), dtype=np.float32) * np.nan res_patch = np.zeros((n_ifg, n_pt_all), dtype=np.float32) * np.nan res_rms_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan ns_gap_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan ns_ifg_noloop_patch = np.zeros( (n_pt_all), dtype=np.float32) * np.nan maxTlen_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan #%% Output data and image ### cum.h5 file cum[:, rows[0]:rows[1], :] = cum_patch.reshape( (n_im, lengththis, width)) vel[rows[0]:rows[1], :] = vel_patch.reshape((lengththis, width)) vconst[rows[0]:rows[1], :] = vconst_patch.reshape((lengththis, width)) gap[:, rows[0]:rows[1], :] = gap_patch.reshape( (n_im - 1, lengththis, width)) ### Others openmode = 'w' if rows[0] == 0 else 'a' #w only 1st patch ## For each imd. cum and inc for imx, imd in enumerate(imdates): ## Incremental displacement if imd == imdates[-1]: continue #skip last incfile = os.path.join(incdir, '{0}_{1}.inc'.format(imd, imdates[imx + 1])) with open(incfile, openmode) as f: inc_patch[imx, :].tofile(f) ## For each ifgd. resid for i, ifgd in enumerate(ifgdates): resfile = os.path.join(resdir, '{0}.res'.format(ifgd)) with open(resfile, openmode) as f: res_patch[i, :].tofile(f) ## velocity and noise indecies in results dir names = [ 'vel', 'vintercept', 'resid_rms', 'n_gap', 'n_ifg_noloop', 'maxTlen' ] data = [ vel_patch, vconst_patch, res_rms_patch, ns_gap_patch, ns_ifg_noloop_patch, maxTlen_patch ] for i in range(len(names)): file = os.path.join(resultsdir, names[i]) with open(file, openmode) as f: data[i].tofile(f) #%% Finish patch elapsed_time2 = int(time.time() - start2) hour2 = int(elapsed_time2 / 3600) minite2 = int(np.mod((elapsed_time2 / 60), 60)) sec2 = int(np.mod(elapsed_time2, 60)) print(" Elapsed time for {0}th patch: {1:02}h {2:02}m {3:02}s".format( i_patch + 1, hour2, minite2, sec2), flush=True) #%% Find stable ref point print('\nFind stable reference point...', flush=True) ### Compute RMS of time series with reference to all points sumsq_cum_wrt_med = np.zeros((length, width), dtype=np.float32) for i in range(n_im): sumsq_cum_wrt_med = sumsq_cum_wrt_med + (cum[i, :, :] - np.nanmedian(cum[i, :, :]))**2 rms_cum_wrt_med = np.sqrt(sumsq_cum_wrt_med / n_im) ### Mask by minimum n_gap n_gap = io_lib.read_img(os.path.join(resultsdir, 'n_gap'), length, width) min_n_gap = np.nanmin(n_gap) mask_n_gap = np.float32(n_gap == min_n_gap) mask_n_gap[mask_n_gap == 0] = np.nan rms_cum_wrt_med = rms_cum_wrt_med * mask_n_gap ### Find stable reference min_rms = np.nanmin(rms_cum_wrt_med) refy1s, refx1s = np.where(rms_cum_wrt_med == min_rms) refy1s, refx1s = refy1s[0], refx1s[0] ## Only first index refy2s, refx2s = refy1s + 1, refx1s + 1 print('Selected ref: {}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s), flush=True) ### Rerferencing cumulative displacement and vel to new stable ref for i in range(n_im): cum[i, :, :] = cum[i, :, :] - cum[i, refy1s, refx1s] vel = vel - vel[refy1s, refx1s] vconst = vconst - vconst[refy1s, refx1s] ### Save image rms_cum_wrt_med_file = os.path.join(infodir, '13rms_cum_wrt_med') with open(rms_cum_wrt_med_file, 'w') as f: rms_cum_wrt_med.tofile(f) pngfile = os.path.join(infodir, '13rms_cum_wrt_med.png') plot_lib.make_im_png(rms_cum_wrt_med, pngfile, cmap_noise_r, 'RMS of cum wrt median (mm)', np.nanpercentile(rms_cum_wrt_med, 1), np.nanpercentile(rms_cum_wrt_med, 99)) ### Save ref cumh5.create_dataset('refarea', data='{}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s)) refsfile = os.path.join(infodir, '13ref.txt') with open(refsfile, 'w') as f: print('{}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s), file=f) if width == width_geo and length == length_geo: ## Geocoded ### Make ref_stable.kml reflat = lat1 + dlat * refy1s reflon = lon1 + dlon * refx1s io_lib.make_point_kml(reflat, reflon, os.path.join(infodir, '13ref.kml')) #%% Close h5 file cumh5.close() #%% Output png images ### Incremental displacement _n_para = n_im - 1 if n_para > n_im - 1 else n_para print( '\nOutput increment png images with {} parallel processing...'.format( _n_para), flush=True) p = q.Pool(_n_para) # p.map(inc_png_wrapper, range(n_im-1)) p.map(inc_png_wrapper, [(i, imdates, incdir, ifgdir, length, width, coef_r2m, ifgdates, ref_unw, cycle, cmap_wrap, keep_incfile) for i in range(n_im - 1)]) p.close() ### Residual for each ifg. png and txt. with open(restxtfile, "w") as f: print('# RMS of residual (mm)', file=f) _n_para = n_ifg if n_para > n_ifg else n_para print('\nOutput residual png images with {} parallel processing...'.format( _n_para), flush=True) p = q.Pool(_n_para) # p.map(resid_png_wrapper, range(n_ifg)) p.map(resid_png_wrapper, [(i, ifgdates, resdir, length, width, restxtfile, cmap_vel, wavelength, keep_incfile) for i in range(n_ifg)]) p.close() ### Velocity and noise indices cmins = [None, None, None, None, None, None] cmaxs = [None, None, None, None, None, None] cmaps = [ cmap_vel, cmap_vel, cmap_noise_r, cmap_noise_r, cmap_noise_r, cmap_noise ] titles = [ 'Velocity (mm/yr)', 'Intercept of velocity (mm)', 'RMS of residual (mm)', 'Number of gaps in SB network', 'Number of ifgs with no loops', 'Max length of connected SB network (yr)' ] print('\nOutput noise png images...', flush=True) for i in range(len(names)): file = os.path.join(resultsdir, names[i]) data = io_lib.read_img(file, length, width) pngfile = file + '.png' ## Get color range if None if cmins[i] is None: cmins[i] = np.nanpercentile(data, 1) if cmaxs[i] is None: cmaxs[i] = np.nanpercentile(data, 99) if cmins[i] == cmaxs[i]: cmins[i] = cmaxs[i] - 1 plot_lib.make_im_png(data, pngfile, cmaps[i], titles[i], cmins[i], cmaxs[i]) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output directory: {}\n'.format(os.path.relpath(tsadir)))
def plot_network(ifgdates, bperp, rm_ifgdates, pngfile, plot_bad=True): """ Plot network of interferometric pairs. bperp can be dummy (-1~1). Suffix of pngfile can be png, ps, pdf, or svg. plot_bad True : Plot bad ifgs by red lines False : Do not plot bad ifgs """ imdates_all = tools_lib.ifgdates2imdates(ifgdates) n_im_all = len(imdates_all) idlist_all = [dt.datetime.strptime(x, '%Y%m%d').toordinal() for x in imdates_all] ifgdates = list(set(ifgdates)-set(rm_ifgdates)) ifgdates.sort() imdates = tools_lib.ifgdates2imdates(ifgdates) n_im = len(imdates) idlist = [dt.datetime.strptime(x, '%Y%m%d').toordinal() for x in imdates] ### Identify gaps G = inv_lib.make_sb_matrix(ifgdates) ixs_inc_gap = np.where(G.sum(axis=0)==0)[0] ### Plot fig figsize_x = np.round((idlist_all[-1]-idlist_all[0])/80)+2 fig = plt.figure(figsize=(figsize_x, 6)) ax = fig.add_axes([0.12, 0.12, 0.85,0.85]) ### IFG blue lines for i, ifgd in enumerate(ifgdates): ix_m = imdates_all.index(ifgd[:8]) ix_s = imdates_all.index(ifgd[-8:]) label = 'IFG' if i==0 else '' #label only first plt.plot([idlist_all[ix_m], idlist_all[ix_s]], [bperp[ix_m], bperp[ix_s]], color='b', alpha=0.6, zorder=2, label=label) ### IFG bad red lines if plot_bad: for i, ifgd in enumerate(rm_ifgdates): ix_m = imdates_all.index(ifgd[:8]) ix_s = imdates_all.index(ifgd[-8:]) label = 'Removed IFG' if i==0 else '' #label only first plt.plot([idlist_all[ix_m], idlist_all[ix_s]], [bperp[ix_m], bperp[ix_s]], color='r', alpha=0.6, zorder=6, label=label) ### Image points and dates ax.scatter(idlist_all, bperp, alpha=0.6, zorder=4) for i in range(n_im_all): if bperp[i] > np.median(bperp): va='bottom' else: va = 'top' ax.annotate(imdates_all[i][4:6]+'/'+imdates_all[i][6:], (idlist_all[i], bperp[i]), ha='center', va=va, zorder=8) ### gaps if len(ixs_inc_gap)!=0: gap_idlist = [] for ix_gap in ixs_inc_gap: gap_idlist.append((idlist[ix_gap]+idlist[ix_gap+1])/2) plt.vlines(gap_idlist, 0, 1, transform=ax.get_xaxis_transform(), zorder=1, label='Gap', alpha=0.6, colors='k', linewidth=3) ### Locater loc = ax.xaxis.set_major_locator(mdates.AutoDateLocator()) try: # Only support from Matplotlib 3.1 ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(loc)) except: ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m/%d')) for label in ax.get_xticklabels(): label.set_rotation(20) label.set_horizontalalignment('right') ax.grid(b=True, which='major') ### Add bold line every 1yr ax.xaxis.set_minor_locator(mdates.YearLocator()) ax.grid(b=True, which='minor', linewidth=2) ax.set_xlim((idlist_all[0]-10, idlist_all[-1]+10)) ### Labels and legend plt.xlabel('Time') if np.all(np.abs(np.array(bperp))<=1): ## dummy plt.ylabel('dummy') else: plt.ylabel('Bperp [m]') plt.legend() ### Save plt.savefig(pngfile) plt.close()
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) #%% Set default tsadir = [] filtwidth_km = 2 filtwidth_yr = [] deg_ramp = [] maskflag = True cumname = 'cum.h5' #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "ht:s:y:r:", ["help", "nomask"]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-t': tsadir = a elif o == '-s': filtwidth_km = float(a) elif o == '-y': filtwidth_yr = float(a) elif o == '-r': deg_ramp = a elif o == '--nomask': maskflag = False if not tsadir: raise Usage('No tsa directory given, -t is not optional!') elif not os.path.isdir(tsadir): raise Usage('No {} dir exists!'.format(tsadir)) elif not os.path.exists(os.path.join(tsadir, cumname)): raise Usage('No {} exists in {}!'.format(cumname, tsadir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Directory and file setting tsadir = os.path.abspath(tsadir) cumfile = os.path.join(tsadir, cumname) resultsdir = os.path.join(tsadir, 'results') parmfile = os.path.join(tsadir, 'info', 'parameters.txt') pixsp_r = float(io_lib.get_param_par(parmfile, 'pixel_spacing_r')) pixsp_a = float(io_lib.get_param_par(parmfile, 'pixel_spacing_a')) x_stddev = filtwidth_km * 1000 / pixsp_r y_stddev = filtwidth_km * 1000 / pixsp_a wavelength = float(io_lib.get_param_par(parmfile, 'wavelength')) #meter coef_r2m = -wavelength / 4 / np.pi * 1000 #rad -> mm, positive is -LOS if wavelength > 0.2: ## L-band cycle = 1.5 # 2pi/cycle for comparison png elif wavelength <= 0.2: ## C-band cycle = 3 # 3*2pi/cycle for comparison png filtdir = os.path.join(tsadir, '16filt') if not os.path.exists(filtdir): os.mkdir(filtdir) cumffile = os.path.join(tsadir, 'cum_filt.h5') vconstfile = os.path.join(resultsdir, 'vintercept.filt') velfile = os.path.join(resultsdir, 'vel.filt') cumh5 = h5.File(cumfile, 'r') if os.path.exists(cumffile): os.remove(cumffile) cumfh5 = h5.File(cumffile, 'w') #%% Dates imdates = cumh5['imdates'][()].astype(str).tolist() cum_org = cumh5['cum'] n_im, length, width = cum_org.shape ### Calc dt in year imdates_dt = ([ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates ]) dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) ### Save dates and refarea into cumf cumfh5.create_dataset('imdates', data=cumh5['imdates']) cumfh5.create_dataset('refarea', data=cumh5['refarea']) cumfh5.create_dataset('gap', data=cumh5['gap']) try: ## if dummy, no bperp field cumfh5.create_dataset('bperp', data=cumh5['bperp']) except: print('No bperp field found in {}. Skip.'.format(cumname)) try: cumfh5.create_dataset('corner_lat', data=cumh5['corner_lat']) cumfh5.create_dataset('corner_lon', data=cumh5['corner_lon']) cumfh5.create_dataset('post_lat', data=cumh5['post_lat']) cumfh5.create_dataset('post_lon', data=cumh5['post_lon']) except: ## not geocoded print('No latlon field found in {}. Skip.'.format(cumname)) ### temporal filter width if not filtwidth_yr and filtwidth_yr != 0: filtwidth_yr = dt_cum[-1] / (n_im - 1) * 3 ## avg interval*3 #%% Display settings print('') print('Size of image (w,l) : {0}, {1}'.format(width, length)) print('Number of images : {}'.format(n_im)) print('Width of filter in space : {} km ({:.1f}x{:.1f} pixel)'.format( filtwidth_km, x_stddev, y_stddev)) print('Width of filter in time : {:.3f} yr ({} days)'.format( filtwidth_yr, int(filtwidth_yr * 365.25))) print('Deramp flag : {}'.format(deg_ramp), flush=True) #%% Load Mask (1: unmask, 0: mask, nan: no cum data) if maskflag: maskfile = os.path.join(resultsdir, 'mask') mask = io_lib.read_img(maskfile, length, width) mask[mask == 0] = np.nan ## 0->nan else: mask = np.ones((length, width), dtype=np.float32) mask[np.isnan(cum_org[0, :, :])] = np.nan #%% First, deramp if indicated cum = np.zeros((cum_org.shape), dtype=np.float32) * np.nan if not deg_ramp: cum = cum_org[()] ## Remove past *_deramp.png if exist for png in glob.glob(os.path.join(filtdir, '*_deramp.png')): os.remove(png) else: print('\nDeramp ifgs with the degree of {}...'.format(deg_ramp), flush=True) ramp1 = [] for i in range(n_im): if np.mod(i, 10) == 0: print(" {0:3}/{1:3}th image...".format(i, n_im), flush=True) ramp, _ = tools_lib.fit2d(cum_org[i, :, :], deg=deg_ramp) cum[i, :, :] = cum_org[i, :, :] - ramp ## Output comparison image of deramp data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [cum_org[i, :, :] * mask, ramp, cum[i, :, :] * mask] ] title3 = [ 'Before deramp ({}pi/cycle)'.format(cycle * 2), 'ramp phase (deg:{}, {}pi/cycle)'.format(deg_ramp, cycle * 2), 'After deramp ({}pi/cycle)'.format(cycle * 2) ] pngfile = os.path.join(filtdir, imdates[i] + '_deramp.png') plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) ## Output comparison image of deramp for increment if i != 0: data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [(cum_org[i, :, :] - cum_org[i - 1, :, :]) * mask, ramp - ramp1, (cum[i, :, :] - cum[i - 1, :, :]) * mask] ] title3 = [ 'Before deramp ({}pi/cycle)'.format(cycle * 2), 'ramp phase (deg:{}, {}pi/cycle)'.format( deg_ramp, cycle * 2), 'After deramp ({}pi/cycle)'.format(cycle * 2) ] pngfile = os.path.join( filtdir, '{}_{}_deramp.png'.format(imdates[i - 1], imdates[i])) plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) ramp1 = ramp.copy() ## backup last ramp #%% Filter each image cum_filt = cumfh5.require_dataset('cum', (n_im, length, width), dtype=np.float32) cum_hptlps1 = [] print('\nHP filter in time, LP filter in space...', flush=True) for i in range(n_im): if np.mod(i, 10) == 0: print(" {0:3}/{1:3}th image...".format(i, n_im), flush=True) #%% Second, HP in time if filtwidth_yr == 0.0: cum_hpt = cum[i, :, :] ## No temporal filter else: time_diff_sq = (dt_cum[i] - dt_cum)**2 ## Limit reading data within filtwidth_yr**8 ixs = time_diff_sq < filtwidth_yr * 8 weight_factor = np.tile( np.exp(-time_diff_sq[ixs] / 2 / filtwidth_yr**2)[:, np.newaxis, np.newaxis], (1, length, width)) #len(ixs), length, width ## Take into account nan in cum weight_factor = weight_factor * (~np.isnan(cum[ixs, :, :])) ## Normalize weight with warnings.catch_warnings( ): ## To silence warning by zero division warnings.simplefilter('ignore', RuntimeWarning) weight_factor = weight_factor / np.sum(weight_factor, axis=0) cum_lpt = np.nansum(cum[ixs, :, :] * weight_factor, axis=0) cum_hpt = cum[i, :, :] - cum_lpt #%% Third, LP in space and subtract from original if filtwidth_km == 0.0: cum_filt[i, :, :] = cum[i, :, :] ## No spatial else: with warnings.catch_warnings(): ## To silence warning if i == 0: cum_hpt = cum_hpt + sys.float_info.epsilon ##To distinguish from 0 of filtered nodata # warnings.simplefilter('ignore', FutureWarning) warnings.simplefilter('ignore', RuntimeWarning) kernel = Gaussian2DKernel(x_stddev, y_stddev) cum_hptlps = convolve_fft( cum_hpt * mask, kernel, fill_value=np.nan, allow_huge=True) ## fill edge 0 for interpolation cum_hptlps[cum_hptlps == 0] = np.nan ## fill 0 with nan cum_filt[i, :, :] = cum[i, :, :] - cum_hptlps #%% Output comparison image data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [cum[i, :, :] * mask, cum_hptlps, cum_filt[i, :, :] * mask] ] title3 = [ 'Before filter ({}pi/cycle)'.format(cycle * 2), 'Filter phase ({}pi/cycle)'.format(cycle * 2), 'After filter ({}pi/cycle)'.format(cycle * 2) ] pngfile = os.path.join(filtdir, imdates[i] + '_filt.png') plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) ### Output comparison image for increment if i != 0: data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [(cum[i, :, :] - cum[i - 1, :, :]) * mask, cum_hptlps - cum_hptlps1, (cum_filt[i, :, :] - cum_filt[i - 1, :, :]) * mask] ] title3 = [ 'Before filter ({}pi/cycle)'.format(cycle * 2), 'Filter phase ({}pi/cycle)'.format(cycle * 2), 'After filter ({}pi/cycle)'.format(cycle * 2) ] pngfile = os.path.join(filtdir, imdates[i] + '_filt.png') pngfile = os.path.join( filtdir, '{}_{}_filt.png'.format(imdates[i - 1], imdates[i])) plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) cum_hptlps1 = cum_hptlps.copy() ## backup last filt phase #%% Calc filtered velocity print('\nCalculate velocity of filtered time series...', flush=True) G = np.stack((np.ones_like(dt_cum), dt_cum), axis=1) vconst = np.zeros((length, width), dtype=np.float32) * np.nan vel = np.zeros((length, width), dtype=np.float32) * np.nan bool_unnan = ~np.isnan(cum_filt[0, :, :]).reshape(length, width) ## not all nan cum_pt = cum_filt[()].reshape(n_im, length * width)[:, bool_unnan.ravel()] #n_im x n_pt n_pt_unnan = bool_unnan.sum() vconst_tmp = np.zeros((n_pt_unnan), dtype=np.float32) * np.nan vel_tmp = np.zeros((n_pt_unnan), dtype=np.float32) * np.nan bool_nonan_pt = np.all(~np.isnan(cum_pt), axis=0) ### First, calc vel point without nan print(' First, solving {0:6}/{1:6}th points with full cum...'.format( bool_nonan_pt.sum(), n_pt_unnan), flush=True) vconst_tmp[bool_nonan_pt], vel_tmp[bool_nonan_pt] = np.linalg.lstsq( G, cum_pt[:, bool_nonan_pt], rcond=None)[0] ### Next, calc vel point with nan print(' Next, solving {0:6}/{1:6}th points with nan in cum...'.format( (~bool_nonan_pt).sum(), n_pt_unnan), flush=True) mask_cum = ~np.isnan(cum_pt[:, ~bool_nonan_pt]) vconst_tmp[~bool_nonan_pt], vel_tmp[ ~bool_nonan_pt] = inv_lib.censored_lstsq_slow( G, cum_pt[:, ~bool_nonan_pt], mask_cum) vconst[bool_unnan], vel[bool_unnan] = vconst_tmp, vel_tmp vconst.tofile(vconstfile) vel.tofile(velfile) if maskflag: vel_mskd = vel * mask vconst_mskd = vconst * mask vconst_mskd.tofile(vconstfile + '.mskd') vel_mskd.tofile(velfile + '.mskd') cumfh5.create_dataset('vel', data=vel.reshape(length, width)) cumfh5.create_dataset('vintercept', data=vconst.reshape(length, width)) #%% Add info and close cumfh5.create_dataset('filtwidth_yr', data=filtwidth_yr) cumfh5.create_dataset('filtwidth_km', data=filtwidth_km) cumfh5.create_dataset('deramp_flag', data=deg_ramp) cumh5.close() cumfh5.close() #%% Output image cmap = 'jet' pngfile = os.path.join(resultsdir, 'vel.filt.png') title = 'Filtered velocity (mm/yr)' vmin = np.nanpercentile(vel, 1) vmax = np.nanpercentile(vel, 99) plot_lib.make_im_png(vel, pngfile, cmap, title, vmin, vmax) ## vintercept pngfile = os.path.join(resultsdir, 'vintercept.filt.png') title = 'Intercept of filtered velocity (mm)' vmin = np.nanpercentile(vconst, 1) vmax = np.nanpercentile(vconst, 99) plot_lib.make_im_png(vconst, pngfile, cmap, title, vmin, vmax) if maskflag: pngfile = os.path.join(resultsdir, 'vel.filt.mskd.png') title = 'Masked filtered velocity (mm/yr)' vmin = np.nanpercentile(vel_mskd, 1) vmax = np.nanpercentile(vel_mskd, 99) plot_lib.make_im_png(vel_mskd, pngfile, cmap, title, vmin, vmax) ## vintercept pngfile = os.path.join(resultsdir, 'vintercept.filt.mskd.png') title = 'Masked intercept of filtered velocity (mm)' vmin = np.nanpercentile(vconst_mskd, 1) vmax = np.nanpercentile(vconst_mskd, 99) plot_lib.make_im_png(vconst_mskd, pngfile, cmap, title, vmin, vmax) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output: {}\n'.format(os.path.relpath(cumffile)), flush=True) print('To plot the time-series:') print('LiCSBAS_plot_ts.py -i {} &\n'.format(os.path.relpath(cumffile)))
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) #%% Set default ifgdir = [] tsadir = [] refflag = 'auto' ## not supported inv_alg = 'LS' n_core = 1 memory_size = 4000 gamma = 0.0001 n_unw_r_thre = [] keep_incfile = False #%% Read options try: try: opts, args = getopt.getopt(argv[1:], "hd:t:r:", [ "help", "mem_size=", "gamma=", "n_unw_r_thre=", "keep_incfile", "inv_alg=", "n_core=" ]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-d': ifgdir = a elif o == '-t': tsadir = a elif o == '-r': refflag = a elif o == '--mem_size': memory_size = float(a) elif o == '--gamma': gamma = float(a) elif o == '--n_unw_r_thre': n_unw_r_thre = float(a) elif o == '--keep_incfile': keep_incfile = True elif o == '--inv_alg': inv_alg = a elif o == '--n_core': n_core = int(a) if not ifgdir: raise Usage('No data directory given, -d is not optional!') elif not os.path.isdir(ifgdir): raise Usage('No {} dir exists!'.format(ifgdir)) elif not os.path.exists(os.path.join(ifgdir, 'slc.mli.par')): raise Usage('No slc.mli.par file exists in {}!'.format(ifgdir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Directory settings ifgdir = os.path.abspath(ifgdir) if not tsadir: tsadir = os.path.join(os.path.dirname(ifgdir), 'TS_' + os.path.basename(ifgdir)) if not os.path.isdir(tsadir): print('\nNo {} exists!'.format(tsadir), file=sys.stderr) return 1 tsadir = os.path.abspath(tsadir) resultsdir = os.path.join(tsadir, 'results') infodir = os.path.join(tsadir, 'info') netdir = os.path.join(tsadir, 'network') bad_ifg11file = os.path.join(infodir, '11bad_ifg.txt') bad_ifg12file = os.path.join(infodir, '12bad_ifg.txt') reffile = os.path.join(infodir, 'ref.txt') incdir = os.path.join(tsadir, '13increment') if not os.path.exists(incdir): os.mkdir(incdir) resdir = os.path.join(tsadir, '13resid') if not os.path.exists(resdir): os.mkdir(resdir) restxtfile = os.path.join(infodir, '13resid.txt') cumh5file = os.path.join(tsadir, 'cum.h5') #%% Check files try: if not os.path.exists(bad_ifg11file): raise Usage('No 11bad_ifg.txt file exists in {}!'.format(tsadir)) if not os.path.exists(bad_ifg12file): raise Usage('No 12bad_ifg.txt file exists in {}!'.format(tsadir)) if not os.path.exists(reffile): raise Usage('No ref.txt file exists in {}!'.format(tsadir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Check and set reference if refflag == 'auto': # Automatic setting based on ref.txt with open(reffile, "r") as f: refarea = f.read().split()[0] #str, x1/x2/y1/y2 refx1, refx2, refy1, refy2 = [ int(s) for s in re.split('[:/]', refarea) ] #%% Read data information ### Get size mlipar = os.path.join(ifgdir, 'slc.mli.par') width = int(io_lib.get_param_par(mlipar, 'range_samples')) length = int(io_lib.get_param_par(mlipar, 'azimuth_lines')) speed_of_light = 299792458 #m/s radar_frequency = float(io_lib.get_param_par(mlipar, 'radar_frequency')) #Hz wavelength = speed_of_light / radar_frequency #meter coef_r2m = -wavelength / 4 / np.pi * 1000 #rad -> mm, positive is -LOS ### Calc pixel spacing depending on IFG or GEOC, used in later spatial filter dempar = os.path.join(ifgdir, 'EQA.dem_par') width_geo = int(io_lib.get_param_par(dempar, 'width')) length_geo = int(io_lib.get_param_par(dempar, 'nlines')) dlat = float(io_lib.get_param_par(dempar, 'post_lat')) #negative dlon = float(io_lib.get_param_par(dempar, 'post_lon')) #positive lat1 = float(io_lib.get_param_par(dempar, 'corner_lat')) lon1 = float(io_lib.get_param_par(dempar, 'corner_lon')) if width == width_geo and length == length_geo: ## Geocoded print('In geographical coordinates', flush=True) centerlat = lat1 + dlat * (length / 2) ra = float(io_lib.get_param_par(dempar, 'ellipsoid_ra')) recip_f = float( io_lib.get_param_par(dempar, 'ellipsoid_reciprocal_flattening')) rb = ra * (1 - 1 / recip_f) ## polar radius pixsp_a = 2 * np.pi * rb / 360 * abs(dlat) pixsp_r = 2 * np.pi * ra / 360 * dlon * np.cos(np.deg2rad(centerlat)) ### Make ref.kml reflat = lat1 + dlat * refy1 reflon = lon1 + dlon * refx1 make_point_kml(reflat, reflon, os.path.join(infodir, 'ref.kml')) else: print('In radar coordinates', flush=True) pixsp_r_org = float(io_lib.get_param_par(mlipar, 'range_pixel_spacing')) pixsp_a = float(io_lib.get_param_par(mlipar, 'azimuth_pixel_spacing')) inc_agl = float(io_lib.get_param_par(mlipar, 'incidence_angle')) pixsp_r = pixsp_r_org / np.sin(np.deg2rad(inc_agl)) ### Set n_unw_r_thre and cycle depending on L- or C-band if wavelength > 0.2: ## L-band if not n_unw_r_thre: n_unw_r_thre = 0.5 cycle = 1.5 # 2pi/cycle for comparison png elif wavelength <= 0.2: ## C-band if not n_unw_r_thre: n_unw_r_thre = 1.0 cycle = 3 # 3*2pi/cycle for comparison png #%% Read date and network information ### Get all ifgdates in ifgdir ifgdates_all = tools_lib.get_ifgdates(ifgdir) imdates_all = tools_lib.ifgdates2imdates(ifgdates_all) n_im_all = len(imdates_all) n_ifg_all = len(ifgdates_all) ### Read bad_ifg11 and 12 bad_ifg11 = io_lib.read_ifg_list(bad_ifg11file) bad_ifg12 = io_lib.read_ifg_list(bad_ifg12file) bad_ifg_all = list(set(bad_ifg11 + bad_ifg12)) bad_ifg_all.sort() ### Remove bad ifgs and images from list ifgdates = list(set(ifgdates_all) - set(bad_ifg_all)) ifgdates.sort() imdates = tools_lib.ifgdates2imdates(ifgdates) n_ifg = len(ifgdates) n_ifg_bad = len(set(bad_ifg11 + bad_ifg12)) n_im = len(imdates) n_unw_thre = int(n_unw_r_thre * n_im) ### Make 13used_image.txt imfile = os.path.join(infodir, '13used_image.txt') with open(imfile, 'w') as f: for i in imdates: print('{}'.format(i), file=f) ### Calc dt in year imdates_dt = ([ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates ]) dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) ### Construct G and Aloop matrix for increment and n_gap G = inv_lib.make_sb_matrix(ifgdates) Aloop = loop_lib.make_loop_matrix(ifgdates) n_loop = Aloop.shape[0] # (n_loop,n_ifg) #%% Plot network ## Read bperp data or dummy bperp_file = os.path.join(ifgdir, 'baselines') if os.path.exists(bperp_file): bperp_all = io_lib.read_bperp_file(bperp_file, imdates_all) bperp = io_lib.read_bperp_file(bperp_file, imdates) else: #dummy bperp_all = np.random.random(len(imdates_all)).tolist() bperp = np.random.random(n_im).tolist() pngfile = os.path.join(netdir, 'network13_all.png') plot_lib.plot_network(ifgdates_all, bperp_all, [], pngfile, pdf=True) pngfile = os.path.join(netdir, 'network13.png') plot_lib.plot_network(ifgdates_all, bperp_all, bad_ifg_all, pngfile, pdf=True) pngfile = os.path.join(netdir, 'network13_nobad.png') plot_lib.plot_network(ifgdates_all, bperp_all, bad_ifg_all, pngfile, plot_bad=False, pdf=True) #%% Get patch row number if inv_alg == 'WLS': n_store_data = n_ifg * 3 + n_im * 2 + n_im * 0.3 # else: n_store_data = n_ifg * 2 + n_im * 2 + n_im * 0.3 #not sure n_patch, patchrow = tools_lib.get_patchrow(width, length, n_store_data, memory_size) #%% Display and output settings & paramters print('') print('Size of image (w,l) : {}, {}'.format(width, length)) print('# of all images : {}'.format(n_im_all)) print('# of images to be used : {}'.format(n_im)) print('# of all ifgs : {}'.format(n_ifg_all)) print('# of ifgs to be used : {}'.format(n_ifg)) print('# of removed ifgs : {}'.format(n_ifg_bad)) print('Threshold of used unw : {}'.format(n_unw_thre)) print('') print('Reference area (X/Y) : {}:{}/{}:{}'.format( refx1, refx2, refy1, refy2)) print('Allowed memory size : {} MB'.format(memory_size)) print('Number of patches : {}'.format(n_patch)) print('Inversion algorism : {}'.format(inv_alg)) print('Gamma value : {}'.format(gamma), flush=True) with open(os.path.join(infodir, 'parameters.txt'), "w") as f: print('range_samples: {}'.format(width), file=f) print('azimuth_lines: {}'.format(length), file=f) print('wavelength: {}'.format(wavelength), file=f) print('n_im_all: {}'.format(n_im_all), file=f) print('n_im: {}'.format(n_im), file=f) print('n_ifg_all: {}'.format(n_ifg_all), file=f) print('n_ifg: {}'.format(n_ifg), file=f) print('n_ifg_bad: {}'.format(n_ifg_bad), file=f) print('n_unw_thre: {}'.format(n_unw_thre), file=f) print('ref_area: {}:{}/{}:{}'.format(refx1, refx2, refy1, refy2), file=f) print('memory_size: {} MB'.format(memory_size), file=f) print('n_patch: {}'.format(n_patch), file=f) print('inv_alg: {}'.format(inv_alg), file=f) print('gamma: {}'.format(gamma), file=f) print('pixel_spacing_r: {:.2f} m'.format(pixsp_r), file=f) print('pixel_spacing_a: {:.2f} m'.format(pixsp_a), file=f) #%% Ref phase for inversion lengththis = refy2 - refy1 countf = width * refy1 countl = width * lengththis # Number to be read ref_unw = [] for i, ifgd in enumerate(ifgdates): unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') f = open(unwfile, 'rb') f.seek(countf * 4, os.SEEK_SET) #Seek for >=2nd path, 4 means byte ### Read unw data (mm) at ref area unw = np.fromfile(f, dtype=np.float32, count=countl).reshape( (lengththis, width))[:, refx1:refx2] * coef_r2m unw[unw == 0] = np.nan if np.all(np.isnan(unw)): print('All nan in ref area in {}.'.format(ifgd)) print('Rerun LiCSBAS12.') return 1 ref_unw.append(np.nanmean(unw)) f.close() #%% Open cum.h5 for output if os.path.exists(cumh5file): os.remove(cumh5file) cumh5 = h5.File(cumh5file, 'w') cumh5.create_dataset('imdates', data=[np.int32(imd) for imd in imdates]) cumh5.create_dataset('refarea', data=refarea) if not np.all(np.abs(np.array(bperp)) <= 1): # if not dummy cumh5.create_dataset('bperp', data=bperp) cum = cumh5.require_dataset('cum', (n_im, length, width), dtype=np.float32) vel = cumh5.require_dataset('vel', (length, width), dtype=np.float32) vconst = cumh5.require_dataset('vintercept', (length, width), dtype=np.float32) gap = cumh5.require_dataset('gap', (n_im - 1, length, width), dtype=np.int8) if width == width_geo and length == length_geo: ## if geocoded cumh5.create_dataset('corner_lat', data=lat1) cumh5.create_dataset('corner_lon', data=lon1) cumh5.create_dataset('post_lat', data=dlat) cumh5.create_dataset('post_lon', data=dlon) #%% For each patch i_patch = 1 for rows in patchrow: print('\nProcess {0}/{1}th line ({2}/{3}th patch)...'.format( rows[1], patchrow[-1][-1], i_patch, n_patch), flush=True) start2 = time.time() #%% Read data ### Allocate memory lengththis = rows[1] - rows[0] n_pt_all = lengththis * width unwpatch = np.zeros((n_ifg, lengththis, width), dtype=np.float32) if inv_alg == 'WLS': cohpatch = np.zeros((n_ifg, lengththis, width), dtype=np.float32) ### For each ifg print(" Reading {0} ifg's unw data...".format(n_ifg), flush=True) countf = width * rows[0] countl = width * lengththis for i, ifgd in enumerate(ifgdates): unwfile = os.path.join(ifgdir, ifgd, ifgd + '.unw') f = open(unwfile, 'rb') f.seek(countf * 4, os.SEEK_SET) #Seek for >=2nd path, 4 means byte ### Read unw data (mm) at patch area unw = np.fromfile(f, dtype=np.float32, count=countl).reshape( (lengththis, width)) * coef_r2m unw[unw == 0] = np.nan # Fill 0 with nan unw = unw - ref_unw[i] unwpatch[i] = unw f.close() ### Read coh file at patch area for WLS if inv_alg == 'WLS': cohfile = os.path.join(ifgdir, ifgd, ifgd + '.cc') f = open(cohfile, 'rb') f.seek(countf * 4, os.SEEK_SET) #Seek for >=2nd path, 4 means byte cohpatch[i, :, :] = np.fromfile(f, dtype=np.float32, count=countl).reshape( (lengththis, width)) unwpatch = unwpatch.reshape( (n_ifg, n_pt_all)).transpose() #(n_pt_all, n_ifg) ### Calc variance from coherence for WLS if inv_alg == 'WLS': cohpatch = cohpatch.reshape( (n_ifg, n_pt_all)).transpose() #(n_pt_all, n_ifg) cohpatch[ cohpatch < 0.01] = 0.01 ## because negative value possible due to geocode cohpatch[ cohpatch > 0.99] = 0.99 ## because >1 possible due to geocode varpatch = (1 - cohpatch**2) / (2 * cohpatch**2) del cohpatch #%% Remove points with less valid data than n_unw_thre ix_unnan_pt = np.where( np.sum(~np.isnan(unwpatch), axis=1) > n_unw_thre)[0] n_pt_unnan = len(ix_unnan_pt) unwpatch = unwpatch[ix_unnan_pt, :] ## keep only unnan data if inv_alg == 'WLS': varpatch = varpatch[ix_unnan_pt, :] ## keep only unnan data print(' {}/{} points removed due to not enough ifg data...'.format( n_pt_all - n_pt_unnan, n_pt_all), flush=True) #%% Compute number of gaps, ifg_noloop, maxTlen point-by-point ns_gap_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan gap_patch = np.zeros((n_im - 1, n_pt_all), dtype=np.int8) ns_ifg_noloop_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan maxTlen_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan ### n_gap print('\n Identifing gaps and counting n_gap...', flush=True) # ns_unw_unnan4inc = (np.matmul(np.int8(G[:, :, None]), (~np.isnan(unwpatch.T))[:, None, :])).sum(axis=0, dtype=np.int16) #n_ifg, n_im-1, n_pt -> n_im-1, n_pt ns_unw_unnan4inc = np.array([ (G[:, i] * (~np.isnan(unwpatch))).sum(axis=1, dtype=np.int16) for i in range(n_im - 1) ]) #n_ifg*(n_pt,n_ifg) -> (n_im-1,n_pt) ns_gap_patch[ix_unnan_pt] = (ns_unw_unnan4inc == 0).sum(axis=0) #n_pt gap_patch[:, ix_unnan_pt] = ns_unw_unnan4inc == 0 del ns_unw_unnan4inc ### n_ifg_noloop print(' Counting n_ifg_noloop...', flush=True) # n_ifg*(n_pt,n_ifg)->(n_loop,n_pt) # Number of ifgs for each loop at eath point. # 3 means complete loop, 1 or 2 means broken loop. ns_ifg4loop = np.array([ (np.abs(Aloop[i, :]) * (~np.isnan(unwpatch))).sum(axis=1) for i in range(n_loop) ]) bool_loop = (ns_ifg4loop == 3 ) #(n_loop,n_pt) identify complete loop only # n_loop*(n_loop,n_pt)*n_pt->(n_ifg,n_pt) # Number of loops for each ifg at eath point. ns_loop4ifg = np.array([((np.abs(Aloop[:, i]) * bool_loop.T).T * (~np.isnan(unwpatch[:, i]))).sum(axis=0) for i in range(n_ifg)]) # ns_ifg_noloop_tmp = (ns_loop4ifg == 0).sum(axis=0) #n_pt ns_nan_ifg = np.isnan(unwpatch).sum(axis=1) #n_pt, nan ifg count ns_ifg_noloop_patch[ix_unnan_pt] = ns_ifg_noloop_tmp - ns_nan_ifg del bool_loop, ns_ifg4loop, ns_loop4ifg ### maxTlen _maxTlen = np.zeros((n_pt_unnan), dtype=np.float32) #temporaly _Tlen = np.zeros((n_pt_unnan), dtype=np.float32) #temporaly for imx in range(n_im - 1): _Tlen = _Tlen + (dt_cum[imx + 1] - dt_cum[imx]) ## Adding dt _Tlen[gap_patch[imx, ix_unnan_pt] == 1] = 0 ## reset to 0 if gap _maxTlen[_maxTlen < _Tlen] = _Tlen[_maxTlen < _Tlen] ## Set Tlen to maxTlen maxTlen_patch[ix_unnan_pt] = _maxTlen #%% Time series inversion print('\n Small Baseline inversion by {}...\n'.format(inv_alg), flush=True) if inv_alg == 'WLS': inc_tmp, vel_tmp, vconst_tmp = inv_lib.invert_nsbas_wls( unwpatch, varpatch, G, dt_cum, gamma, n_core) else: inc_tmp, vel_tmp, vconst_tmp = inv_lib.invert_nsbas( unwpatch, G, dt_cum, gamma, n_core) ### Set to valuables inc_patch = np.zeros((n_im - 1, n_pt_all), dtype=np.float32) * np.nan vel_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan vconst_patch = np.zeros((n_pt_all), dtype=np.float32) * np.nan inc_patch[:, ix_unnan_pt] = inc_tmp vel_patch[ix_unnan_pt] = vel_tmp vconst_patch[ix_unnan_pt] = vconst_tmp ### Calculate residuals res_patch = np.zeros((n_ifg, n_pt_all), dtype=np.float32) * np.nan res_patch[:, ix_unnan_pt] = unwpatch.T - np.dot(G, inc_tmp) res_sumsq = np.nansum(res_patch**2, axis=0) res_n = np.float32((~np.isnan(res_patch)).sum(axis=0)) res_n[res_n == 0] = np.nan # To avoid 0 division res_rms_patch = np.sqrt(res_sumsq / res_n) ### Cumulative displacememt cum_patch = np.zeros((n_im, n_pt_all), dtype=np.float32) * np.nan cum_patch[1:, :] = np.cumsum(inc_patch, axis=0) ## Fill 1st image with 0 at unnan points from 2nd images bool_unnan_pt = ~np.isnan(cum_patch[1, :]) cum_patch[0, bool_unnan_pt] = 0 ## Drop (fill with nan) interpolated cum by 2 continuous gaps for i in range(n_im - 2): ## from 1->n_im-1 gap2 = gap_patch[i, :] + gap_patch[i + 1, :] bool_gap2 = (gap2 == 2 ) ## true if 2 continuous gaps for each point cum_patch[i + 1, :][bool_gap2] = np.nan ## Last (n_im th) image. 1 gap means interpolated cum_patch[-1, :][gap_patch[-1, :] == 1] = np.nan #%% Output data and image ### cum.h5 file cum[:, rows[0]:rows[1], :] = cum_patch.reshape( (n_im, lengththis, width)) vel[rows[0]:rows[1], :] = vel_patch.reshape((lengththis, width)) vconst[rows[0]:rows[1], :] = vconst_patch.reshape((lengththis, width)) gap[:, rows[0]:rows[1], :] = gap_patch.reshape( (n_im - 1, lengththis, width)) ### Others openmode = 'w' if rows[0] == 0 else 'a' #w only 1st patch ## For each imd. cum and inc for imx, imd in enumerate(imdates): ## Incremental displacement if imd == imdates[-1]: continue #skip last incfile = os.path.join(incdir, '{0}_{1}.inc'.format(imd, imdates[imx + 1])) with open(incfile, openmode) as f: inc_patch[imx, :].tofile(f) ## For each ifgd. resid for i, ifgd in enumerate(ifgdates): resfile = os.path.join(resdir, '{0}.res'.format(ifgd)) with open(resfile, openmode) as f: res_patch[i, :].tofile(f) ## velocity and noise indecies in results dir names = [ 'vel', 'vintercept', 'resid_rms', 'n_gap', 'n_ifg_noloop', 'maxTlen' ] data = [ vel_patch, vconst_patch, res_rms_patch, ns_gap_patch, ns_ifg_noloop_patch, maxTlen_patch ] for i in range(len(names)): file = os.path.join(resultsdir, names[i]) with open(file, openmode) as f: data[i].tofile(f) #%% Finish patch elapsed_time2 = int(time.time() - start2) hour2 = int(elapsed_time2 / 3600) minite2 = int(np.mod((elapsed_time2 / 60), 60)) sec2 = int(np.mod(elapsed_time2, 60)) print(" Elapsed time for {0}th patch: {1:02}h {2:02}m {3:02}s".format( i_patch, hour2, minite2, sec2), flush=True) i_patch += 1 #Next patch count #%% Close h5 file cumh5.close() #%% Output png images print('\nOutput png images...', flush=True) ### Incremental displacement for imx, imd in enumerate(imdates): if imd == imdates[-1]: continue #skip last for increment ## Comparison of increment and daisy chain pair ifgd = '{}_{}'.format(imd, imdates[imx + 1]) incfile = os.path.join(incdir, '{}.inc'.format(ifgd)) unwfile = os.path.join(ifgdir, ifgd, '{}.unw'.format(ifgd)) pngfile = os.path.join(incdir, '{}.inc_comp.png'.format(ifgd)) inc = io_lib.read_img(incfile, length, width) try: unw = io_lib.read_img(unwfile, length, width) * coef_r2m ix_ifg = ifgdates.index(ifgd) unw = unw - ref_unw[ix_ifg] except: unw = np.zeros((length, width), dtype=np.float32) * np.nan ### Output png for comparison data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [unw, inc, inc - unw] ] title3 = ['Daisy-chain IFG', 'Inverted', 'Difference'] pngfile = os.path.join(incdir, '{}.increment.png'.format(ifgd)) plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) if not keep_incfile: os.remove(incfile) ### Residual for each ifg. png and txt. cmap = 'jet' with open(restxtfile, "w") as f: print('# RMS of residual (mm)', file=f) for ifgd in ifgdates: infile = os.path.join(resdir, '{}.res'.format(ifgd)) resid = io_lib.read_img(infile, length, width) resid_rms = np.sqrt(np.nanmean(resid**2)) with open(restxtfile, "a") as f: print('{} {:5.2f}'.format(ifgd, resid_rms), file=f) pngfile = infile + '.png' title = 'Residual (mm) of {} (RMS:{:.2f}mm)'.format(ifgd, resid_rms) plot_lib.make_im_png(resid, pngfile, cmap, title, -wavelength / 2 * 1000, wavelength / 2 * 1000) if not keep_incfile: os.remove(infile) ### Velocity and noise indices #names = ['vel', 'vconst', 'resid_rms', 'n_gap', 'n_ifg_noloop', 'maxTlen'] cmins = [None, None, None, None, None, None] cmaxs = [None, None, None, None, None, None] cmaps = ['jet', 'jet', 'viridis_r', 'viridis_r', 'viridis_r', 'viridis'] titles = [ 'Velocity (mm/yr)', 'Intercept of velocity (mm)', 'RMS of residual (mm)', 'Number of gaps in SB network', 'Number of ifgs with no loops', 'Max length of connected SB network (yr)' ] for i in range(len(names)): file = os.path.join(resultsdir, names[i]) data = io_lib.read_img(file, length, width) pngfile = file + '.png' ## Get color range if None if cmins[i] is None: cmins[i] = np.nanpercentile(data, 1) if cmaxs[i] is None: cmaxs[i] = np.nanpercentile(data, 99) if cmins[i] == cmaxs[i]: cmins[i] = cmaxs[i] - 1 plot_lib.make_im_png(data, pngfile, cmaps[i], titles[i], cmins[i], cmaxs[i]) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output directory: {}\n'.format(os.path.relpath(tsadir)))
def main(argv=None): #%% Check argv if argv == None: argv = sys.argv start = time.time() ver = 1.2 date = 20200228 author = "Y. Morishita" print("\n{} ver{} {} {}".format(os.path.basename(argv[0]), ver, date, author), flush=True) print("{} {}".format(os.path.basename(argv[0]), ' '.join(argv[1:])), flush=True) #%% Set default tsadir = [] filtwidth_km = 2 filtwidth_yr = [] deg_ramp = [] hgt_linearflag = False hgt_min = 200 ## meter hgt_max = 10000 ## meter maskflag = True cumname = 'cum.h5' cmap_vel = SCM.roma.reversed() cmap_noise_r = 'viridis_r' #%% Read options try: try: opts, args = getopt.getopt( argv[1:], "ht:s:y:r:", ["help", "hgt_linear", "hgt_min=", "hgt_max=", "nomask"]) except getopt.error as msg: raise Usage(msg) for o, a in opts: if o == '-h' or o == '--help': print(__doc__) return 0 elif o == '-t': tsadir = a elif o == '-s': filtwidth_km = float(a) elif o == '-y': filtwidth_yr = float(a) elif o == '-r': deg_ramp = a elif o == '--hgt_linear': hgt_linearflag = True elif o == '--hgt_min': hgt_min = int(a) elif o == '--hgt_max': hgt_max = int(a) elif o == '--nomask': maskflag = False if not tsadir: raise Usage('No tsa directory given, -t is not optional!') elif not os.path.isdir(tsadir): raise Usage('No {} dir exists!'.format(tsadir)) elif not os.path.exists(os.path.join(tsadir, cumname)): raise Usage('No {} exists in {}!'.format(cumname, tsadir)) except Usage as err: print("\nERROR:", file=sys.stderr, end='') print(" " + str(err.msg), file=sys.stderr) print("\nFor help, use -h or --help.\n", file=sys.stderr) return 2 #%% Directory and file setting tsadir = os.path.abspath(tsadir) cumfile = os.path.join(tsadir, cumname) resultsdir = os.path.join(tsadir, 'results') infodir = os.path.join(tsadir, 'info') inparmfile = os.path.join(infodir, '13parameters.txt') if not os.path.exists(inparmfile): ## for old LiCSBAS13 <v1.2 inparmfile = os.path.join(infodir, 'parameters.txt') outparmfile = os.path.join(infodir, '16parameters.txt') pixsp_r = float(io_lib.get_param_par(inparmfile, 'pixel_spacing_r')) pixsp_a = float(io_lib.get_param_par(inparmfile, 'pixel_spacing_a')) x_stddev = filtwidth_km * 1000 / pixsp_r y_stddev = filtwidth_km * 1000 / pixsp_a wavelength = float(io_lib.get_param_par(inparmfile, 'wavelength')) #meter coef_r2m = -wavelength / 4 / np.pi * 1000 #rad -> mm, positive is -LOS if wavelength > 0.2: ## L-band cycle = 1.5 # 2pi/cycle for comparison png elif wavelength <= 0.2: ## C-band cycle = 3 # 3*2pi/cycle for comparison png filtincdir = os.path.join(tsadir, '16filt_increment') if os.path.exists(filtincdir): shutil.rmtree(filtincdir) os.mkdir(filtincdir) filtcumdir = os.path.join(tsadir, '16filt_cum') if os.path.exists(filtcumdir): shutil.rmtree(filtcumdir) os.mkdir(filtcumdir) cumffile = os.path.join(tsadir, 'cum_filt.h5') vconstfile = os.path.join(resultsdir, 'vintercept.filt') velfile = os.path.join(resultsdir, 'vel.filt') cumh5 = h5.File(cumfile, 'r') if os.path.exists(cumffile): os.remove(cumffile) cumfh5 = h5.File(cumffile, 'w') #%% Dates imdates = cumh5['imdates'][()].astype(str).tolist() cum_org = cumh5['cum'] n_im, length, width = cum_org.shape ### Calc dt in year imdates_dt = ([ dt.datetime.strptime(imd, '%Y%m%d').toordinal() for imd in imdates ]) dt_cum = np.float32((np.array(imdates_dt) - imdates_dt[0]) / 365.25) ### Save dates and other info into cumf cumfh5.create_dataset('imdates', data=cumh5['imdates']) cumfh5.create_dataset('gap', data=cumh5['gap']) if 'bperp' in list(cumh5.keys()): ## if dummy, no bperp field cumfh5.create_dataset('bperp', data=cumh5['bperp']) else: print('No bperp field found in {}. Skip.'.format(cumname)) if 'corner_lat' in list(cumh5.keys()): lat1 = float(cumh5['corner_lat'][()]) lon1 = float(cumh5['corner_lon'][()]) dlat = float(cumh5['post_lat'][()]) dlon = float(cumh5['post_lon'][()]) cumfh5.create_dataset('corner_lat', data=cumh5['corner_lat']) cumfh5.create_dataset('corner_lon', data=cumh5['corner_lon']) cumfh5.create_dataset('post_lat', data=cumh5['post_lat']) cumfh5.create_dataset('post_lon', data=cumh5['post_lon']) else: ## not geocoded print('No latlon field found in {}. Skip.'.format(cumname)) ### temporal filter width if not filtwidth_yr and filtwidth_yr != 0: filtwidth_yr = dt_cum[-1] / (n_im - 1) * 3 ## avg interval*3 ### hgt_linear if hgt_linearflag: hgtfile = os.path.join(resultsdir, 'hgt') if not os.path.exists(hgtfile): print('\nERROR: No hgt file exist in results dir!', file=sys.stderr) print('--hgt_linear option cannot be used.', file=sys.stderr) return 2 hgt = io_lib.read_img(hgtfile, length, width) hgt[np.isnan(hgt)] = 0 else: hgt = [] #%% Display settings print('') print('Size of image (w,l) : {0}, {1}'.format(width, length)) print('Number of images : {}'.format(n_im)) print('Width of filter in space : {} km ({:.1f}x{:.1f} pixel)'.format( filtwidth_km, x_stddev, y_stddev)) print('Width of filter in time : {:.3f} yr ({} days)'.format( filtwidth_yr, int(filtwidth_yr * 365.25))) print('Deramp flag : {}'.format(deg_ramp), flush=True) print('hgt-linear flag : {}'.format(hgt_linearflag), flush=True) if hgt_linearflag: print('Minimum hgt : {} m'.format(hgt_min), flush=True) print('Maximum hgt : {} m'.format(hgt_max), flush=True) with open(outparmfile, "w") as f: print('filtwidth_km: {}'.format(filtwidth_km), file=f) print('filtwidth_xpixels: {:.1f}'.format(x_stddev), file=f) print('filtwidth_ypixels: {:.1f}'.format(y_stddev), file=f) print('filtwidth_yr: {:.3f}'.format(filtwidth_yr), file=f) print('filtwidth_day: {}'.format(int(filtwidth_yr * 365.25)), file=f) print('deg_ramp: {}'.format(deg_ramp), file=f) print('hgt_linear: {}'.format(hgt_linearflag * 1), file=f) print('hgt_min: {}'.format(hgt_min), file=f) print('hgt_max: {}'.format(hgt_max), file=f) #%% Load Mask (1: unmask, 0: mask, nan: no cum data) if maskflag: maskfile = os.path.join(resultsdir, 'mask') mask = io_lib.read_img(maskfile, length, width) mask[mask == 0] = np.nan ## 0->nan else: mask = np.ones((length, width), dtype=np.float32) mask[np.isnan(cum_org[0, :, :])] = np.nan #%% First, deramp and hgt-linear if indicated cum = np.zeros((cum_org.shape), dtype=np.float32) * np.nan if not deg_ramp and not hgt_linearflag: cum = cum_org[()] else: if not deg_ramp: print('\nEstimate hgt-linear component...', flush=True) elif not hgt_linearflag: print('\nDeramp ifgs with the degree of {}...'.format(deg_ramp), flush=True) else: print( '\nDeramp ifgs with the degree of {} and hgt-linear...'.format( deg_ramp), flush=True) ramp1 = [] ## backup last ramp to plot increment fit_hgt1 = [] ## backup last fit_hgt to plot increment model1 = [] deramp_title3 = [ 'Before deramp ({}pi/cycle)'.format(cycle * 2), 'ramp phase (deg:{})'.format(deg_ramp), 'After deramp ({}pi/cycle)'.format(cycle * 2) ] for i in range(n_im): if np.mod(i, 10) == 0: print(" {0:3}/{1:3}th image...".format(i, n_im), flush=True) fit, model = tools_lib.fit2dh(cum_org[i, :, :] * mask, deg_ramp, hgt, hgt_min, hgt_max) ## fit is not masked cum[i, :, :] = cum_org[i, :, :] - fit if hgt_linearflag: fit_hgt = hgt * model[ -1] * mask ## extract only hgt-linear component cum_bf = cum[ i, :, :] + fit_hgt ## After deramp before hgt-linear ## Output comparison image of hgt_linear std_before = np.nanstd(cum_bf) std_after = np.nanstd(cum[i, :, :] * mask) data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [cum_bf, fit_hgt, cum[i, :, :] * mask] ] title3 = [ 'Before hgt-linear (STD: {:.1f}mm)'.format(std_before), 'hgt-linear phase ({:.1f}mm/km)'.format(model[-1] * 1000), 'After hgt-linear (STD: {:.1f}mm)'.format(std_after) ] pngfile = os.path.join(filtcumdir, imdates[i] + '_hgt_linear.png') plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) pngfile = os.path.join(filtcumdir, imdates[i] + '_hgt_corr.png') title = '{} ({:.1f}mm/km, based on {}<=hgt<={})'.format( imdates[i], model[-1] * 1000, hgt_min, hgt_max) plot_lib.plot_hgt_corr(cum_bf, fit_hgt, hgt, title, pngfile) ## Output comparison image of hgt_linear for increment if i != 0: ## first image has no increment inc = (cum[i, :, :] - cum[i - 1, :, :]) * mask std_before = np.nanstd(inc + fit_hgt - fit_hgt1) std_after = np.nanstd(inc) data3 = [ np.angle( np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [inc + fit_hgt - fit_hgt1, fit_hgt - fit_hgt1, inc] ] title3 = [ 'Before hgt-linear (STD: {:.1f}mm)'.format(std_before), 'hgt-linear phase ({:.1f}mm/km)'.format( (model[-1] - model1) * 1000), 'After hgt-linear (STD: {:.1f}mm)'.format(std_after) ] pngfile = os.path.join( filtincdir, '{}_{}_hgt_linear.png'.format(imdates[i - 1], imdates[i])) plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) pngfile = os.path.join( filtincdir, '{}_{}_hgt_corr.png'.format(imdates[i - 1], imdates[i])) title = '{}_{} ({:.1f}mm/km, based on {}<=hgt<={})'.format( imdates[i - 1], imdates[i], (model[-1] - model1) * 1000, hgt_min, hgt_max) plot_lib.plot_hgt_corr(inc + fit_hgt - fit_hgt1, fit_hgt - fit_hgt1, hgt, title, pngfile) fit_hgt1 = fit_hgt.copy() ## backup last fit_hgt model1 = model[-1] else: fit_hgt = 0 ## for plot deframp if deg_ramp: ramp = (fit - fit_hgt) * mask ## Output comparison image of deramp data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [ cum_org[i, :, :] * mask, ramp, cum_org[i, :, :] * mask - ramp ] ] pngfile = os.path.join(filtcumdir, imdates[i] + '_deramp.png') plot_lib.make_3im_png(data3, pngfile, 'insar', deramp_title3, vmin=-np.pi, vmax=np.pi, cbar=False) ## Output comparison image of deramp for increment if i != 0: ## first image has no increment inc_org = (cum_org[i, :, :] - cum_org[i - 1, :, :]) * mask data3 = [ np.angle( np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [inc_org, ramp - ramp1, inc_org - (ramp - ramp1)] ] pngfile = os.path.join( filtincdir, '{}_{}_deramp.png'.format(imdates[i - 1], imdates[i])) plot_lib.make_3im_png(data3, pngfile, 'insar', deramp_title3, vmin=-np.pi, vmax=np.pi, cbar=False) ramp1 = ramp.copy() ## backup last ramp #%% Filter each image cum_filt = cumfh5.require_dataset('cum', (n_im, length, width), dtype=np.float32) cum_hptlps1 = [] print('\nHP filter in time, LP filter in space...', flush=True) for i in range(n_im): if np.mod(i, 10) == 0: print(" {0:3}/{1:3}th image...".format(i, n_im), flush=True) #%% Second, HP in time if filtwidth_yr == 0.0: cum_hpt = cum[i, :, :] ## No temporal filter else: time_diff_sq = (dt_cum[i] - dt_cum)**2 ## Limit reading data within filtwidth_yr**8 ixs = time_diff_sq < filtwidth_yr * 8 weight_factor = np.tile( np.exp(-time_diff_sq[ixs] / 2 / filtwidth_yr**2)[:, np.newaxis, np.newaxis], (1, length, width)) #len(ixs), length, width ## Take into account nan in cum weight_factor = weight_factor * (~np.isnan(cum[ixs, :, :])) ## Normalize weight with warnings.catch_warnings( ): ## To silence warning by zero division warnings.simplefilter('ignore', RuntimeWarning) weight_factor = weight_factor / np.sum(weight_factor, axis=0) cum_lpt = np.nansum(cum[ixs, :, :] * weight_factor, axis=0) cum_hpt = cum[i, :, :] - cum_lpt #%% Third, LP in space and subtract from original if filtwidth_km == 0.0: cum_filt[i, :, :] = cum[i, :, :] ## No spatial else: with warnings.catch_warnings(): ## To silence warning if i == 0: cum_hpt = cum_hpt + sys.float_info.epsilon ##To distinguish from 0 of filtered nodata # warnings.simplefilter('ignore', FutureWarning) warnings.simplefilter('ignore', RuntimeWarning) kernel = Gaussian2DKernel(x_stddev, y_stddev) cum_hptlps = convolve_fft( cum_hpt * mask, kernel, fill_value=np.nan, allow_huge=True) ## fill edge 0 for interpolation cum_hptlps[cum_hptlps == 0] = np.nan ## fill 0 with nan cum_filt[i, :, :] = cum[i, :, :] - cum_hptlps #%% Output comparison image data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [cum[i, :, :] * mask, cum_hptlps, cum_filt[i, :, :] * mask] ] title3 = [ 'Before filter ({}pi/cycle)'.format(cycle * 2), 'Filter phase ({}pi/cycle)'.format(cycle * 2), 'After filter ({}pi/cycle)'.format(cycle * 2) ] pngfile = os.path.join(filtcumdir, imdates[i] + '_filt.png') plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) ### Output comparison image for increment if i != 0: data3 = [ np.angle(np.exp(1j * (data / coef_r2m / cycle)) * cycle) for data in [(cum[i, :, :] - cum[i - 1, :, :]) * mask, cum_hptlps - cum_hptlps1, (cum_filt[i, :, :] - cum_filt[i - 1, :, :]) * mask] ] title3 = [ 'Before filter ({}pi/cycle)'.format(cycle * 2), 'Filter phase ({}pi/cycle)'.format(cycle * 2), 'After filter ({}pi/cycle)'.format(cycle * 2) ] pngfile = os.path.join( filtincdir, '{}_{}_filt.png'.format(imdates[i - 1], imdates[i])) plot_lib.make_3im_png(data3, pngfile, 'insar', title3, vmin=-np.pi, vmax=np.pi, cbar=False) cum_hptlps1 = cum_hptlps.copy() ## backup last filt phase #%% Find stable ref point print('\nFind stable reference point...', flush=True) ### Compute RMS of time series with reference to all points sumsq_cum_wrt_med = np.zeros((length, width), dtype=np.float32) for i in range(n_im): sumsq_cum_wrt_med = sumsq_cum_wrt_med + ( cum_filt[i, :, :] - np.nanmedian(cum_filt[i, :, :]))**2 rms_cum_wrt_med = np.sqrt(sumsq_cum_wrt_med / n_im) * mask ### Mask by minimum n_gap n_gap = io_lib.read_img(os.path.join(resultsdir, 'n_gap'), length, width) min_n_gap = np.nanmin(n_gap) mask_n_gap = np.float32(n_gap == min_n_gap) mask_n_gap[mask_n_gap == 0] = np.nan rms_cum_wrt_med = rms_cum_wrt_med * mask_n_gap ### Find stable reference min_rms = np.nanmin(rms_cum_wrt_med) refy1s, refx1s = np.where(rms_cum_wrt_med == min_rms) refy1s, refx1s = refy1s[0], refx1s[0] ## Only first index refy2s, refx2s = refy1s + 1, refx1s + 1 print('Selected ref: {}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s), flush=True) ### Rerferencing cumulative displacement to new stable ref for i in range(n_im): cum_filt[i, :, :] = cum_filt[i, :, :] - cum[i, refy1s, refx1s] ### Save image rms_cum_wrt_med_file = os.path.join(infodir, '16rms_cum_wrt_med') with open(rms_cum_wrt_med_file, 'w') as f: rms_cum_wrt_med.tofile(f) pngfile = os.path.join(infodir, '16rms_cum_wrt_med.png') plot_lib.make_im_png(rms_cum_wrt_med, pngfile, cmap_noise_r, 'RMS of cum wrt median (mm)', np.nanpercentile(rms_cum_wrt_med, 1), np.nanpercentile(rms_cum_wrt_med, 99)) ### Save ref cumfh5.create_dataset('refarea', data='{}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s)) refsfile = os.path.join(infodir, '16ref.txt') with open(refsfile, 'w') as f: print('{}:{}/{}:{}'.format(refx1s, refx2s, refy1s, refy2s), file=f) if 'corner_lat' in list(cumh5.keys()): ## Geocoded ### Make ref_stable.kml reflat = lat1 + dlat * refy1s reflon = lon1 + dlon * refx1s io_lib.make_point_kml(reflat, reflon, os.path.join(infodir, '16ref.kml')) #%% Calc filtered velocity print('\nCalculate velocity of filtered time series...', flush=True) G = np.stack((np.ones_like(dt_cum), dt_cum), axis=1) vconst = np.zeros((length, width), dtype=np.float32) * np.nan vel = np.zeros((length, width), dtype=np.float32) * np.nan bool_unnan = ~np.isnan(cum_filt[0, :, :]).reshape(length, width) ## not all nan cum_pt = cum_filt[()].reshape(n_im, length * width)[:, bool_unnan.ravel()] #n_im x n_pt n_pt_unnan = bool_unnan.sum() vconst_tmp = np.zeros((n_pt_unnan), dtype=np.float32) * np.nan vel_tmp = np.zeros((n_pt_unnan), dtype=np.float32) * np.nan bool_nonan_pt = np.all(~np.isnan(cum_pt), axis=0) ### First, calc vel point without nan print(' First, solving {0:6}/{1:6}th points with full cum...'.format( bool_nonan_pt.sum(), n_pt_unnan), flush=True) vconst_tmp[bool_nonan_pt], vel_tmp[bool_nonan_pt] = np.linalg.lstsq( G, cum_pt[:, bool_nonan_pt], rcond=None)[0] ### Next, calc vel point with nan print(' Next, solving {0:6}/{1:6}th points with nan in cum...'.format( (~bool_nonan_pt).sum(), n_pt_unnan), flush=True) mask_cum = ~np.isnan(cum_pt[:, ~bool_nonan_pt]) vconst_tmp[~bool_nonan_pt], vel_tmp[ ~bool_nonan_pt] = inv_lib.censored_lstsq_slow( G, cum_pt[:, ~bool_nonan_pt], mask_cum) vconst[bool_unnan], vel[bool_unnan] = vconst_tmp, vel_tmp vconst.tofile(vconstfile) vel.tofile(velfile) if maskflag: vel_mskd = vel * mask vconst_mskd = vconst * mask vconst_mskd.tofile(vconstfile + '.mskd') vel_mskd.tofile(velfile + '.mskd') cumfh5.create_dataset('vel', data=vel.reshape(length, width)) cumfh5.create_dataset('vintercept', data=vconst.reshape(length, width)) #%% Add info and close cumfh5.create_dataset('filtwidth_yr', data=filtwidth_yr) cumfh5.create_dataset('filtwidth_km', data=filtwidth_km) cumfh5.create_dataset('deramp_flag', data=deg_ramp) cumfh5.create_dataset('hgt_linear_flag', data=hgt_linearflag * 1) cumh5.close() cumfh5.close() #%% Output image pngfile = os.path.join(resultsdir, 'vel.filt.png') title = 'Filtered velocity (mm/yr)' vmin = np.nanpercentile(vel, 1) vmax = np.nanpercentile(vel, 99) plot_lib.make_im_png(vel, pngfile, cmap_vel, title, vmin, vmax) ## vintercept pngfile = os.path.join(resultsdir, 'vintercept.filt.png') title = 'Intercept of filtered velocity (mm)' vmin = np.nanpercentile(vconst, 1) vmax = np.nanpercentile(vconst, 99) plot_lib.make_im_png(vconst, pngfile, cmap_vel, title, vmin, vmax) if maskflag: pngfile = os.path.join(resultsdir, 'vel.filt.mskd.png') title = 'Masked filtered velocity (mm/yr)' vmin = np.nanpercentile(vel_mskd, 1) vmax = np.nanpercentile(vel_mskd, 99) plot_lib.make_im_png(vel_mskd, pngfile, cmap_vel, title, vmin, vmax) ## vintercept pngfile = os.path.join(resultsdir, 'vintercept.filt.mskd.png') title = 'Masked intercept of filtered velocity (mm)' vmin = np.nanpercentile(vconst_mskd, 1) vmax = np.nanpercentile(vconst_mskd, 99) plot_lib.make_im_png(vconst_mskd, pngfile, cmap_vel, title, vmin, vmax) #%% Finish elapsed_time = time.time() - start hour = int(elapsed_time / 3600) minite = int(np.mod((elapsed_time / 60), 60)) sec = int(np.mod(elapsed_time, 60)) print("\nElapsed time: {0:02}h {1:02}m {2:02}s".format(hour, minite, sec)) print('\n{} Successfully finished!!\n'.format(os.path.basename(argv[0]))) print('Output: {}\n'.format(os.path.relpath(cumffile)), flush=True) print('To plot the time-series:') print('LiCSBAS_plot_ts.py -i {} &\n'.format(os.path.relpath(cumffile)))