Beispiel #1
0
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('')
Beispiel #2
0
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)))
Beispiel #3
0
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)))
Beispiel #4
0
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)))
Beispiel #5
0
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)))
Beispiel #6
0
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()
Beispiel #7
0
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)))
Beispiel #8
0
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)))
Beispiel #9
0
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)))