Esempio n. 1
0
def mosaic_texture(humfile,
                   sonpath,
                   cs2cs_args="epsg:26949",
                   res=99,
                   nn=5,
                   weight=1):
    '''
    Create mosaics of the spatially referenced sidescan echograms

    Syntax
    ----------
    [] = PyHum.mosaic_texture(humfile, sonpath, cs2cs_args, res, nn, weight)

    Parameters
    ----------
    humfile : str
       path to the .DAT file
    sonpath : str
       path where the *.SON files are
    cs2cs_args : int, *optional* [Default="epsg:26949"]
       arguments to create coordinates in a projected coordinate system
       this argument gets given to pyproj to turn wgs84 (lat/lon) coordinates
       into any projection supported by the proj.4 libraries
    res : float, *optional* [Default=0]
       grid resolution of output gridded texture map
       if res=99, res will be determined automatically from the spatial resolution of 1 pixel
    nn: int, *optional* [Default=5]
       number of nearest neighbours for gridding
    weight: int, *optional* [Default=1]
       specifies the type of pixel weighting in the gridding process
       weight = 1, based on grazing angle and inverse distance weighting
       weight = 2, based on grazing angle only
       weight = 3, inverse distance weighting only
       weight = 4, no weighting
    
    Returns
    -------

    sonpath+'GroundOverlay.kml': kml file
        contains gridded (or point cloud) sidescan intensity map for importing into google earth
        of the pth chunk

    sonpath+'map.png' : 
        image overlay associated with the kml file

    '''

    # prompt user to supply file if no input file given
    if not humfile:
        print('An input file is required!!!!!!')
        Tk().withdraw(
        )  # we don't want a full GUI, so keep the root window from appearing
        humfile = askopenfilename(filetypes=[("DAT files", "*.DAT")])

    # prompt user to supply directory if no input sonpath is given
    if not sonpath:
        print('A *.SON directory is required!!!!!!')
        Tk().withdraw(
        )  # we don't want a full GUI, so keep the root window from appearing
        sonpath = askdirectory()

    # print given arguments to screen and convert data type where necessary
    if humfile:
        print('Input file is %s' % (humfile))

    if sonpath:
        print('Sonar file path is %s' % (sonpath))

    if cs2cs_args:
        print('cs2cs arguments are %s' % (cs2cs_args))

    if res:
        res = np.asarray(res, float)
        print('Gridding resolution: %s' % (str(res)))

    if nn:
        nn = int(nn)
        print('Number of nearest neighbours for gridding: %s' % (str(nn)))

    if weight:
        weight = int(weight)
        print('Weighting for gridding: %s' % (str(weight)))

    ##nn = 5 #number of nearest neighbours in gridding
    ##noisefloor=10 # noise threshold in dB W

    # start timer
    if os.name == 'posix':  # true if linux/mac or cygwin on windows
        start = time.time()
    else:  # windows
        start = time.clock()

    trans = pyproj.Proj(init=cs2cs_args)

    # if son path name supplied has no separator at end, put one on
    if sonpath[-1] != os.sep:
        sonpath = sonpath + os.sep

    base = humfile.split('.DAT')  # get base of file name for output
    base = base[0].split(os.sep)[-1]

    # remove underscores, negatives and spaces from basename
    base = humutils.strip_base(base)

    meta = loadmat(os.path.normpath(os.path.join(sonpath, base + 'meta.mat')))

    esi = np.squeeze(meta['e'])
    nsi = np.squeeze(meta['n'])

    theta = np.squeeze(meta['heading']) / (180 / np.pi)

    # load memory mapped scans
    shape_port = np.squeeze(meta['shape_port'])
    if shape_port != '':
        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_port_lar.dat'))):
            port_fp = io.get_mmap_data(sonpath, base, '_data_port_lar.dat',
                                       'float32', tuple(shape_port))
        else:
            port_fp = io.get_mmap_data(sonpath, base, '_data_port_la.dat',
                                       'float32', tuple(shape_port))

    shape_star = np.squeeze(meta['shape_star'])
    if shape_star != '':
        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_star_lar.dat'))):
            star_fp = io.get_mmap_data(sonpath, base, '_data_star_lar.dat',
                                       'float32', tuple(shape_star))
        else:
            star_fp = io.get_mmap_data(sonpath, base, '_data_star_la.dat',
                                       'float32', tuple(shape_star))

    # time varying gain
    tvg = ((8.5 * 10**-5) + (3 / 76923) + ((8.5 * 10**-5) / 4)) * meta['c']

    # depth correction
    dist_tvg = np.squeeze((
        (np.tan(np.radians(25))) * np.squeeze(meta['dep_m'])) - (tvg))

    # read in range data
    R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat', 'float32',
                            tuple(shape_star))

    dx = np.arcsin(meta['c'] / (1000 * meta['t'] * meta['f']))
    pix_m = meta['pix_m']
    c = meta['c']

    if not os.path.isfile(os.path.normpath(os.path.join(sonpath,
                                                        base + "S.p"))):
        #if 2 > 1:
        inputfiles = []
        if len(shape_star) > 2:
            for p in range(len(star_fp)):
                e = esi[shape_port[-1] * p:shape_port[-1] * (p + 1)]
                n = nsi[shape_port[-1] * p:shape_port[-1] * (p + 1)]
                t = theta[shape_port[-1] * p:shape_port[-1] * (p + 1)]
                d = dist_tvg[shape_port[-1] * p:shape_port[-1] * (p + 1)]
                dat_port = port_fp[p]
                dat_star = star_fp[p]
                data_R = R_fp[p]
                print("writing chunk %s " % (str(p)))
                write_points(e, n, t, d, dat_port, dat_star, data_R, pix_m,
                             res, cs2cs_args, sonpath, p, c, dx)
                inputfiles.append(
                    os.path.normpath(
                        os.path.join(sonpath, 'x_y_class' + str(p) + '.asc')))
        else:
            p = 0
            print("writing chunk %s " % (str(p)))
            write_points(esi, nsi, theta, dist_tvg, port_fp, star_fp, R_fp,
                         meta['pix_m'], res, cs2cs_args, sonpath, 0, c, dx)
            inputfiles.append(
                os.path.normpath(
                    os.path.join(sonpath, 'x_y_class' + str(p) + '.asc')))

        #trans =  pyproj.Proj(init=cs2cs_args)

        # D, R, h, t
        print("reading points from %s files" % (str(len(inputfiles))))
        X, Y, S, D, R, h, t, i = getxys(inputfiles)

        print("%s points read from %s files" %
              (str(len(S)), str(len(inputfiles))))

        # remove values where sidescan intensity is zero
        ind = np.where(np.logical_not(S == 0))[0]

        X = X[ind]
        Y = Y[ind]
        S = S[ind]
        D = D[ind]
        R = R[ind]
        h = h[ind]
        t = t[ind]
        i = i[ind]
        del ind

        # save to file for temporary storage
        pickle.dump(
            S, open(os.path.normpath(os.path.join(sonpath, base + "S.p")),
                    "wb"))
        del S
        pickle.dump(
            D, open(os.path.normpath(os.path.join(sonpath, base + "D.p")),
                    "wb"))
        del D
        pickle.dump(
            t, open(os.path.normpath(os.path.join(sonpath, base + "t.p")),
                    "wb"))
        del t
        pickle.dump(
            i, open(os.path.normpath(os.path.join(sonpath, base + "i.p")),
                    "wb"))
        del i

        pickle.dump(
            X, open(os.path.normpath(os.path.join(sonpath, base + "X.p")),
                    "wb"))
        del X
        pickle.dump(
            Y, open(os.path.normpath(os.path.join(sonpath, base + "Y.p")),
                    "wb"))
        del Y
        pickle.dump(
            R, open(os.path.normpath(os.path.join(sonpath, base + "R.p")),
                    "wb"))
        pickle.dump(
            h, open(os.path.normpath(os.path.join(sonpath, base + "h.p")),
                    "wb"))

        #grazing angle
        g = np.arctan(R.flatten(), h.flatten())
        pickle.dump(
            g, open(os.path.normpath(os.path.join(sonpath, base + "g.p")),
                    "wb"))
        del g, R, h

    print("creating grids ...")

    if res == 0:
        res = 99

    if res == 99:

        #### prepare grids
        R = pickle.load(
            open(os.path.normpath(os.path.join(sonpath, base + "R.p")), "rb"))

        ## actual along-track resolution is this: dx times dy = Af
        tmp = R * dx * (c * 0.007 / 2)
        del R

        resg = np.min(tmp[tmp > 0])
        del tmp
    else:
        resg = res

    X = pickle.load(
        open(os.path.normpath(os.path.join(sonpath, base + "X.p")), "rb"))
    Y = pickle.load(
        open(os.path.normpath(os.path.join(sonpath, base + "Y.p")), "rb"))

    humlon, humlat = trans(X, Y, inverse=True)

    grid_x, grid_y = np.meshgrid(np.arange(np.min(X), np.max(X), resg),
                                 np.arange(np.min(Y), np.max(Y), resg))

    shape = np.shape(grid_x)

    tree = KDTree(zip(X.flatten(), Y.flatten()))
    del X, Y

    print("mosaicking ...")
    #k nearest neighbour
    try:
        dist, inds = tree.query(zip(grid_x.flatten(), grid_y.flatten()),
                                k=nn,
                                n_jobs=-1)
    except:
        #print ".... update your scipy installation to use faster kd-tree"
        dist, inds = tree.query(zip(grid_x.flatten(), grid_y.flatten()), k=nn)

    #del grid_x, grid_y

    if weight == 1:
        g = pickle.load(
            open(os.path.normpath(os.path.join(sonpath, base + "g.p")), "rb"))
        w = g[inds] + 1.0 / dist**2
        del g
    elif weight == 2:
        g = pickle.load(
            open(os.path.normpath(os.path.join(sonpath, base + "g.p")), "rb"))
        w = g[inds]
        del g
    elif weight == 3:
        w = 1.0 / dist**2
    elif weight == 4:
        w = 1.0

    #g = pickle.load( open( os.path.normpath(os.path.join(sonpath,base+"g.p")), "rb" ) )
    #w = g[inds] + 1.0 / dist**2
    #del g

    if weight < 4:
        w[np.isinf(w)] = 1
        w[np.isnan(w)] = 1
        w[w > 10000] = 10000
        w[w <= 0] = 1

    # load in sidescan intensity
    S = pickle.load(
        open(os.path.normpath(os.path.join(sonpath, base + "S.p")), "rb"))
    # filter out noise pixels
    S[S < noisefloor] = np.nan

    if nn == 1:
        Sdat_g = (w * S.flatten()[inds]).reshape(shape)
        del w
        dist = dist.reshape(shape)
    else:
        if weight < 4:
            Sdat_g = (np.nansum(w * S.flatten()[inds], axis=1) /
                      np.nansum(w, axis=1)).reshape(shape)
        else:
            Sdat_g = (np.nansum(S.flatten()[inds], axis=1)).reshape(shape)
        del w
        dist = np.nanmean(dist, axis=1).reshape(shape)

    del S

    Sdat_g[dist > 1] = np.nan
    Sdat_g[Sdat_g < noisefloor] = np.nan

    dat = Sdat_g.copy()
    dat[dist > 1] = 0
    dat2 = replace_nans.RN(dat.astype('float64'), 1000, 0.01, 2,
                           'localmean').getdata()
    dat2[dat == 0] = np.nan
    del dat

    dat2[dat2 < noisefloor] = np.nan

    Sdat_g = dat2.copy()
    del dat2

    Sdat_g[Sdat_g == 0] = np.nan
    Sdat_g[np.isinf(Sdat_g)] = np.nan
    Sdat_gm = np.ma.masked_invalid(Sdat_g)
    del Sdat_g

    glon, glat = trans(grid_x, grid_y, inverse=True)
    del grid_x, grid_y

    # =========================================================
    print("creating kmz file ...")
    ## new way to create kml file
    pixels = 1024 * 10

    fig, ax = humutils.gearth_fig(llcrnrlon=glon.min(),
                                  llcrnrlat=glat.min(),
                                  urcrnrlon=glon.max(),
                                  urcrnrlat=glat.max(),
                                  pixels=pixels)
    cs = ax.pcolormesh(glon, glat, Sdat_gm)
    ax.set_axis_off()
    fig.savefig(os.path.normpath(os.path.join(sonpath, 'class_overlay1.png')),
                transparent=True,
                format='png')

    fig = plt.figure(figsize=(1.0, 4.0), facecolor=None, frameon=False)
    ax = fig.add_axes([0.0, 0.05, 0.2, 0.9])
    cb = fig.colorbar(cs, cax=ax)
    cb.set_label('Texture lengthscale [m]',
                 rotation=-90,
                 color='k',
                 labelpad=20)
    fig.savefig(os.path.normpath(os.path.join(sonpath, 'class_legend.png')),
                transparent=False,
                format='png')

    humutils.make_kml(
        llcrnrlon=glon.min(),
        llcrnrlat=glat.min(),
        urcrnrlon=glon.max(),
        urcrnrlat=glat.max(),
        figs=[os.path.normpath(os.path.join(sonpath, 'class_overlay1.png'))],
        colorbar=os.path.normpath(os.path.join(sonpath, 'class_legend.png')),
        kmzfile=os.path.normpath(
            os.path.join(sonpath, 'class_GroundOverlay.kmz')),
        name='Sidescan Intensity')

    # =========================================================
    print("drawing and printing map ...")
    fig = plt.figure(frameon=False)
    map = Basemap(
        projection='merc',
        epsg=cs2cs_args.split(':')[1],
        resolution='i',  #h #f
        llcrnrlon=np.min(humlon) - 0.001,
        llcrnrlat=np.min(humlat) - 0.001,
        urcrnrlon=np.max(humlon) + 0.001,
        urcrnrlat=np.max(humlat) + 0.001)

    gx, gy = map.projtran(glon, glat)

    try:
        map.arcgisimage(server='http://server.arcgisonline.com/ArcGIS',
                        service='ESRI_Imagery_World_2D',
                        xpixels=1000,
                        ypixels=None,
                        dpi=300)
    except:
        map.arcgisimage(server='http://server.arcgisonline.com/ArcGIS',
                        service='World_Imagery',
                        xpixels=1000,
                        ypixels=None,
                        dpi=300)
    #finally:
    #   print "error: map could not be created..."

    ax = plt.Axes(
        fig,
        [0., 0., 1., 1.],
    )
    ax.set_axis_off()
    fig.add_axes(ax)

    if Sdat_gm.size > 25000000:
        print(
            "matrix size > 25,000,000 - decimating by factor of 5 for display")
        map.pcolormesh(gx[::5, ::5],
                       gy[::5, ::5],
                       Sdat_gm[::5, ::5],
                       vmin=np.nanmin(Sdat_gm),
                       vmax=np.nanmax(Sdat_gm))
    else:
        map.pcolormesh(gx,
                       gy,
                       Sdat_gm,
                       vmin=np.nanmin(Sdat_gm),
                       vmax=np.nanmax(Sdat_gm))

    custom_save2(sonpath, 'class_map_imagery')
    del fig

    if os.name == 'posix':  # true if linux/mac
        elapsed = (time.time() - start)
    else:  # windows
        elapsed = (time.clock() - start)
    print("Processing took " + str(elapsed) + "seconds to analyse")

    print("Done!")
Esempio n. 2
0
def texture2(humfile, sonpath, win, doplot, numclasses):
    '''
      Create a texture lengthscale map using the algorithm detailed by Buscombe et al. (2015)
      This textural lengthscale is not a direct measure of grain size. Rather, it is a statistical 
      representation that integrates over many attributes of bed texture, of which grain size is the most important. 
      The technique is a physically based means to identify regions of texture within a sidescan echogram, 
      and could provide a basis for objective, automated riverbed sediment classification.

      Syntax
      ----------
      [] = PyHum.texture(humfile, sonpath, win, doplot, numclasses)

      Parameters
      ----------
      humfile : str
       path to the .DAT file
      sonpath : str
       path where the *.SON files are
      win : int, *optional* [Default=10]
       pixel in pixels of the moving window
      doplot : int, *optional* [Default=1]
       if 1, make plots, otherwise do not make plots
      numclasses : int, *optional* [Default=4]
       number of 'k means' that the texture lengthscale will be segmented into

      Returns
      -------
      sonpath+base+'_data_class.dat': memory-mapped file
        contains the texture lengthscale map

      sonpath+base+'_data_kclass.dat': memory-mapped file
        contains the k-means segmented texture lengthscale map

      References
      ----------
      .. [1] Buscombe, D., Grams, P.E., and Smith, S.M.C., 2015, Automated riverbed sediment
       classification using low-cost sidescan sonar. Journal of Hydraulic Engineering 10.1061/(ASCE)HY.1943-7900.0001079, 06015019.
      '''

    # prompt user to supply file if no input file given
    if not humfile:
        print('An input file is required!!!!!!')
        Tk().withdraw(
        )  # we don't want a full GUI, so keep the root window from appearing
        humfile = askopenfilename(filetypes=[("DAT files", "*.DAT")])

    # prompt user to supply directory if no input sonpath is given
    if not sonpath:
        print('A *.SON directory is required!!!!!!')
        Tk().withdraw(
        )  # we don't want a full GUI, so keep the root window from appearing
        sonpath = askdirectory()

    # print given arguments to screen and convert data type where necessary
    if humfile:
        print('Input file is %s' % (humfile))

    if sonpath:
        print('Sonar file path is %s' % (sonpath))

    if win:
        win = np.asarray(win, int)
        print('Window is %s square pixels' % (str(win)))

    if numclasses:
        numclasses = np.asarray(numclasses, int)
        print('Number of sediment classes: %s' % (str(numclasses)))

    if doplot:
        doplot = int(doplot)
        if doplot == 0:
            print("Plots will not be made")

    print('[Default] Number of processors is %s' % (str(cpu_count())))

    ########################################################
    ########################################################

    # start timer
    if os.name == 'posix':  # true if linux/mac or cygwin on windows
        start = time.time()
    else:  # windows
        start = time.clock()

    # if son path name supplied has no separator at end, put one on
    if sonpath[-1] != os.sep:
        sonpath = sonpath + os.sep

    base = humfile.split('.DAT')  # get base of file name for output
    base = base[0].split(os.sep)[-1]

    # remove underscores, negatives and spaces from basename
    base = humutils.strip_base(base)

    meta = loadmat(os.path.normpath(os.path.join(sonpath, base + 'meta.mat')))

    ft = 1 / loadmat(sonpath + base + 'meta.mat')['pix_m']
    #pix_m = np.squeeze(meta['pix_m'])
    #dep_m = np.squeeze(meta['dep_m'])
    dist_m = np.squeeze(meta['dist_m'])

    ### port
    print("processing port side ...")
    # load memory mapped scan ... port
    shape_port = np.squeeze(meta['shape_port'])
    if shape_port != '':

        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_port_lar.dat'))):
            port_fp = io.get_mmap_data(sonpath, base, '_data_port_lar.dat',
                                       'float32', tuple(shape_port))
        else:
            port_fp = io.get_mmap_data(sonpath, base, '_data_port_la.dat',
                                       'float32', tuple(shape_port))

        port_fp2 = io.get_mmap_data(sonpath, base, '_data_port_l.dat',
                                    'float32', tuple(shape_port))

    ### star
    print("processing starboard side ...")
    # load memory mapped scan ... port
    shape_star = np.squeeze(loadmat(sonpath + base + 'meta.mat')['shape_star'])
    if shape_star != '':
        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_star_lar.dat'))):
            star_fp = io.get_mmap_data(sonpath, base, '_data_star_lar.dat',
                                       'float32', tuple(shape_star))
        else:
            star_fp = io.get_mmap_data(sonpath, base, '_data_star_la.dat',
                                       'float32', tuple(shape_star))

        star_fp2 = io.get_mmap_data(sonpath, base, '_data_star_l.dat',
                                    'float32', tuple(shape_star))

    if len(shape_star) > 2:
        shape = shape_port.copy()
        shape[1] = shape_port[1] + shape_star[1]
    else:
        shape = []
        shape.append(1)
        shape.append(shape_port[0])
        shape.append(shape_port[1])
        shape[1] = shape_port[0] + shape_star[0]

    # create memory mapped file for Sp
    #with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'w+') as ff:
    #   fp = np.memmap(ff, dtype='float32', mode='w+', shape=tuple(shape))
    fp = np.zeros(tuple(shape), dtype='float32')

    if len(shape_star) > 2:

        for p in range(len(port_fp)):

            merge = np.vstack((np.flipud(port_fp[p]), star_fp[p]))
            merge = denoise_tv_chambolle(merge.copy(),
                                         weight=2,
                                         multichannel=False).astype('float32')
            Snn = std_convoluted(merge, win)[1]
            del merge

            try:
                Snn = medfilt2d(Snn, (win + 1, win + 1))
            except:
                Snn = medfilt2d(Snn, (win, win))

            Snn[np.isnan(np.vstack(
                (np.flipud(port_fp[p]), star_fp[p])))] = np.nan
            Snn[np.isnan(np.vstack(
                (np.flipud(port_fp2[p]), star_fp2[p])))] = np.nan

            R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat',
                                    'float32', tuple(shape_star))

            R = np.vstack((np.flipud(R_fp[0]), R_fp[0]))

            R = R / np.max(R)

            rn = replace_nans.RN(R.astype('float64'), 1000, 0.01, 2,
                                 'localmean')
            R = rn.getdata()
            del rn

            Sp = (Snn**2) * np.cos(np.deg2rad(R)) / win  ##**2

            fp[p] = Sp.astype('float32')
            del Sp

        #del fp # flush data to file
        shape = io.set_mmap_data(sonpath, base, '_data_class.dat', 'float32',
                                 np.squeeze(fp))
        del fp
        class_fp = io.get_mmap_data(sonpath, base, '_data_class.dat',
                                    'float32', tuple(shape))

    else:

        merge = np.vstack((np.flipud(port_fp), star_fp))
        merge = denoise_tv_chambolle(merge.copy(),
                                     weight=2,
                                     multichannel=False).astype('float32')
        Snn = std_convoluted(merge, win)[1]
        del merge

        try:
            Snn = medfilt2d(Snn, (win + 1, win + 1))
        except:
            Snn = medfilt2d(Snn, (win, win))

        Snn[np.isnan(np.vstack((np.flipud(port_fp), star_fp)))] = np.nan
        Snn[np.isnan(np.vstack((np.flipud(port_fp2), star_fp2)))] = np.nan

        R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat', 'float32',
                                tuple(shape_star))

        R = np.vstack((np.flipud(R_fp), R_fp))
        R = R / np.max(R)

        rn = replace_nans.RN(R.astype('float64'), 1000, 0.01, 2, 'localmean')
        R = rn.getdata()
        del rn

        Sp = (Snn**2) * np.cos(np.deg2rad(R)) / win  ##**2

        shape = io.set_mmap_data(sonpath, base, '_data_class.dat', 'float32',
                                 np.squeeze(Sp))

        #with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'w+') as ff:
        #   np.save(ff, np.squeeze(Sp).astype('float32'))

        #with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'r') as ff:
        #   class_fp = np.load(ff)

        #del Sp
        class_fp = io.get_mmap_data(sonpath, base, '_data_class.dat',
                                    'float32', tuple(shape))

    dist_m = np.squeeze(loadmat(sonpath + base + 'meta.mat')['dist_m'])

    ########################################################
    if doplot == 1:

        if len(shape_star) > 2:
            for p in range(len(star_fp)):
                plot_class(dist_m, shape_port, port_fp[p], star_fp[p],
                           class_fp[p], ft, humfile, sonpath, base, p)
        else:
            plot_class(dist_m, shape_port, port_fp, star_fp, class_fp, ft,
                       humfile, sonpath, base, 0)

        if len(shape_star) > 2:
            for p in range(len(star_fp)):
                plot_contours(dist_m, shape_port, class_fp[p], ft, humfile,
                              sonpath, base, numclasses, p)
        else:
            plot_contours(dist_m, shape_port, port_fp, star_fp, class_fp, ft,
                          humfile, sonpath, base, numclasses, 0)

    #######################################################
    # k-means

    if len(shape_star) > 2:
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_kclass.dat')),
                'w+') as ff:
            fp = np.memmap(ff, dtype='float32', mode='w+', shape=tuple(shape))

        for p in range(len(port_fp)):
            wc = get_kclass(class_fp[p].copy(), numclasses)
            fp[p] = wc.astype('float32')
            del wc

        del fp

        kclass_fp = io.get_mmap_data(sonpath, base, '_data_kclass.dat',
                                     'float32', tuple(shape))

    else:
        wc = get_kclass(class_fp.copy(), numclasses)

        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_kclass.dat')),
                'w+') as ff:
            np.save(ff, np.squeeze(wc).astype('float32'))

        del wc

        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_kclass.dat')),
                'r') as ff:
            kclass_fp = np.load(ff)

    ########################################################
    if doplot == 1:

        if len(shape_star) > 2:
            for p in range(len(star_fp)):
                plot_kmeans(dist_m, shape_port, port_fp[p], star_fp[p],
                            kclass_fp[p], ft, humfile, sonpath, base, p)
        else:
            plot_kmeans(dist_m, shape_port, port_fp, star_fp, kclass_fp, ft,
                        humfile, sonpath, base, 0)

    if os.name == 'posix':  # true if linux/mac
        elapsed = (time.time() - start)
    else:  # windows
        elapsed = (time.clock() - start)
    print("Processing took " + str(elapsed) + "seconds to analyse")

    print("Done!")
    print("===================================================")
Esempio n. 3
0
def texture(humfile,
            sonpath,
            win=100,
            shift=10,
            doplot=1,
            density=50,
            numclasses=4,
            maxscale=20,
            notes=4):
    '''
      Create a texture lengthscale map using the algorithm detailed by Buscombe et al. (2015)
      This textural lengthscale is not a direct measure of grain size. Rather, it is a statistical 
      representation that integrates over many attributes of bed texture, of which grain size is the most important. 
      The technique is a physically based means to identify regions of texture within a sidescan echogram, 
      and could provide a basis for objective, automated riverbed sediment classification.

      Syntax
      ----------
      [] = PyHum.texture(humfile, sonpath, win, shift, doplot, density, numclasses, maxscale, notes)

      Parameters
      ----------
      humfile : str
       path to the .DAT file
      sonpath : str
       path where the *.SON files are
      win : int, *optional* [Default=100]
       pixel in pixels of the moving window
      shift : int, *optional* [Default=10]
       shift in pixels for moving window operation
      doplot : int, *optional* [Default=1]
       if 1, make plots, otherwise do not make plots
      density : int, *optional* [Default=win/2]
       echogram will be sampled every 'density' pixels
      numclasses : int, *optional* [Default=4]
       number of 'k means' that the texture lengthscale will be segmented into
      maxscale : int, *optional* [Default=20]
       Max scale as inverse fraction of data length for wavelet analysis
      notes : int, *optional* [Default=100]
       notes per octave for wavelet analysis

      Returns
      -------
      sonpath+base+'_data_class.dat': memory-mapped file
        contains the texture lengthscale map

      sonpath+base+'_data_kclass.dat': memory-mapped file
        contains the k-means segmented texture lengthscale map

      References
      ----------
      .. [1] Buscombe, D., Grams, P.E., and Smith, S.M.C., 2015, Automated riverbed sediment
       classification using low-cost sidescan sonar. Journal of Hydraulic Engineering 10.1061/(ASCE)HY.1943-7900.0001079, 06015019.
      '''

    # prompt user to supply file if no input file given
    if not humfile:
        print 'An input file is required!!!!!!'
        Tk().withdraw(
        )  # we don't want a full GUI, so keep the root window from appearing
        humfile = askopenfilename(filetypes=[("DAT files", "*.DAT")])

    # prompt user to supply directory if no input sonpath is given
    if not sonpath:
        print 'A *.SON directory is required!!!!!!'
        Tk().withdraw(
        )  # we don't want a full GUI, so keep the root window from appearing
        sonpath = askdirectory()

    # print given arguments to screen and convert data type where necessary
    if humfile:
        print 'Input file is %s' % (humfile)

    if sonpath:
        print 'Sonar file path is %s' % (sonpath)

    if win:
        win = np.asarray(win, int)
        print 'Window is %s square pixels' % (str(win))

    if shift:
        shift = np.asarray(shift, int)
        print 'Min shift is %s pixels' % (str(shift))

    if density:
        density = np.asarray(density, int)
        print 'Image will be sampled every %s pixels' % (str(density))

    if numclasses:
        numclasses = np.asarray(numclasses, int)
        print 'Number of sediment classes: %s' % (str(numclasses))

    if maxscale:
        maxscale = np.asarray(maxscale, int)
        print 'Max scale as inverse fraction of data length: %s' % (
            str(maxscale))

    if notes:
        notes = np.asarray(notes, int)
        print 'Notes per octave: %s' % (str(notes))

    if doplot:
        doplot = int(doplot)
        if doplot == 0:
            print "Plots will not be made"

    print '[Default] Number of processors is %s' % (str(cpu_count()))

    ########################################################
    ########################################################

    # start timer
    if os.name == 'posix':  # true if linux/mac or cygwin on windows
        start = time.time()
    else:  # windows
        start = time.clock()

    # if son path name supplied has no separator at end, put one on
    if sonpath[-1] != os.sep:
        sonpath = sonpath + os.sep

    base = humfile.split('.DAT')  # get base of file name for output
    base = base[0].split(os.sep)[-1]

    # remove underscores, negatives and spaces from basename
    base = humutils.strip_base(base)

    meta = loadmat(os.path.normpath(os.path.join(sonpath, base + 'meta.mat')))

    ft = 1 / loadmat(sonpath + base + 'meta.mat')['pix_m']
    #pix_m = np.squeeze(meta['pix_m'])
    #dep_m = np.squeeze(meta['dep_m'])
    dist_m = np.squeeze(meta['dist_m'])

    ### port
    print "processing port side ..."
    # load memory mapped scan ... port
    shape_port = np.squeeze(meta['shape_port'])
    if shape_port != '':

        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_port_lar.dat'))):
            port_fp = io.get_mmap_data(sonpath, base, '_data_port_lar.dat',
                                       'float32', tuple(shape_port))
        else:
            port_fp = io.get_mmap_data(sonpath, base, '_data_port_la.dat',
                                       'float32', tuple(shape_port))

        port_fp2 = io.get_mmap_data(sonpath, base, '_data_port_l.dat',
                                    'float32', tuple(shape_port))

    ### star
    print "processing starboard side ..."
    # load memory mapped scan ... port
    shape_star = np.squeeze(loadmat(sonpath + base + 'meta.mat')['shape_star'])
    if shape_star != '':
        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_star_lar.dat'))):
            star_fp = io.get_mmap_data(sonpath, base, '_data_star_lar.dat',
                                       'float32', tuple(shape_star))
        else:
            star_fp = io.get_mmap_data(sonpath, base, '_data_star_la.dat',
                                       'float32', tuple(shape_star))

        star_fp2 = io.get_mmap_data(sonpath, base, '_data_star_l.dat',
                                    'float32', tuple(shape_star))

    if len(shape_star) > 2:
        shape = shape_port.copy()
        shape[1] = shape_port[1] + shape_star[1]
    else:
        shape = []
        shape.append(1)
        shape.append(shape_port[0])
        shape.append(shape_port[1])
        shape[1] = shape_port[0] + shape_star[0]

    # create memory mapped file for Sp
    with open(
            os.path.normpath(os.path.join(sonpath, base + '_data_class.dat')),
            'w+') as ff:
        fp = np.memmap(ff, dtype='float32', mode='w+', shape=tuple(shape))

    if len(shape_star) > 2:
        #SRT = []
        for p in xrange(len(port_fp)):

            Z, ind = humutils.sliding_window_sliced(
                np.vstack((np.flipud(port_fp[p]), star_fp[p])), density,
                (win, win), (shift, shift))

            Snn = get_srt(Z, ind, maxscale, notes, win)  #, density)

            # replace nans using infilling algorithm
            rn = replace_nans.RN(Snn.astype('float64'), 1000, 0.01, 2,
                                 'localmean')
            Snn = rn.getdata()
            del rn

            Ny, Nx = np.shape(np.vstack((np.flipud(port_fp[p]), star_fp[p])))

            Snn = median_filter(Snn, (int(Nx / 100), int(Ny / 100)))

            Sp = humutils.im_resize(Snn, Nx, Ny)
            del Snn

            Sp[np.isnan(np.vstack(
                (np.flipud(port_fp[p]), star_fp[p])))] = np.nan
            Sp[np.isnan(np.vstack(
                (np.flipud(port_fp2[p]), star_fp2[p])))] = np.nan

            #extent = shape_port[1]
            #Zdist = dist_m[shape_port[-1]*p:shape_port[-1]*(p+1)]
            #yvec = np.linspace(pix_m,extent*pix_m,extent)
            #d = dep_m[shape_port[-1]*p:shape_port[-1]*(p+1)]

            R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat',
                                    'float32', tuple(shape_star))

            R = np.vstack((np.flipud(R_fp[0]), R_fp[0]))

            R = R / np.max(R)

            #R[R>0.8] = np.nan

            rn = replace_nans.RN(R.astype('float64'), 1000, 0.01, 2,
                                 'localmean')
            R = rn.getdata()
            del rn

            Sp = (Sp**2) * np.cos(R) / shift**2

            fp[p] = Sp.astype('float32')
            del Sp

        del fp  # flush data to file

        class_fp = io.get_mmap_data(sonpath, base, '_data_class.dat',
                                    'float32', tuple(shape))

    else:

        Z, ind = humutils.sliding_window_sliced(
            np.vstack((np.flipud(port_fp), star_fp)), density, (win, win),
            (shift, shift))

        Snn = get_srt(Z, ind, maxscale, notes, win)  #, density)

        # replace nans using infilling algorithm
        rn = replace_nans.RN(Snn.astype('float64'), 1000, 0.01, 2, 'localmean')
        Snn = rn.getdata()
        del rn

        Ny, Nx = np.shape(np.vstack((np.flipud(port_fp), star_fp)))

        Snn = median_filter(Snn, (int(Nx / 100), int(Ny / 100)))

        Sp = humutils.im_resize(Snn, Nx, Ny)
        del Snn

        Sp[np.isnan(np.vstack((np.flipud(port_fp), star_fp)))] = np.nan
        Sp[np.isnan(np.vstack((np.flipud(port_fp2), star_fp2)))] = np.nan

        #extent = shape_port[0]
        #Zdist = dist_m
        #yvec = np.linspace(pix_m,extent*pix_m,extent)
        #d = dep_m

        R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat', 'float32',
                                tuple(shape_star))

        R = np.vstack((np.flipud(R_fp), R_fp))
        R = R / np.max(R)

        #R[R>0.8] = np.nan

        rn = replace_nans.RN(R.astype('float64'), 1000, 0.01, 2, 'localmean')
        R = rn.getdata()
        del rn

        Sp = (Sp**2) * np.cos(R) / shift**2

        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_class.dat')),
                'w+') as ff:
            np.save(ff, np.squeeze(Sp).astype('float32'))

        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_class.dat')),
                'r') as ff:
            class_fp = np.load(ff)

        del Sp

    dist_m = np.squeeze(loadmat(sonpath + base + 'meta.mat')['dist_m'])

    ########################################################
    if doplot == 1:

        if len(shape_star) > 2:
            for p in xrange(len(star_fp)):
                plot_class(dist_m, shape_port, port_fp[p], star_fp[p],
                           class_fp[p], ft, humfile, sonpath, base, p)
        else:
            plot_class(dist_m, shape_port, port_fp, star_fp, class_fp, ft,
                       humfile, sonpath, base, 0)

        if len(shape_star) > 2:
            for p in xrange(len(star_fp)):
                plot_contours(dist_m, shape_port, class_fp[p], ft, humfile,
                              sonpath, base, numclasses, p)
        else:
            plot_contours(dist_m, shape_port, class_fp, ft, humfile, sonpath,
                          base, numclasses, 0)

    #######################################################
    # k-means

    if len(shape_star) > 2:
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_kclass.dat')),
                'w+') as ff:
            fp = np.memmap(ff, dtype='float32', mode='w+', shape=tuple(shape))

        for p in xrange(len(port_fp)):
            wc = get_kclass(class_fp[p].copy(), numclasses)
            fp[p] = wc.astype('float32')
            del wc

        del fp

        kclass_fp = io.get_mmap_data(sonpath, base, '_data_kclass.dat',
                                     'float32', tuple(shape))

    else:
        wc = get_kclass(class_fp.copy(), numclasses)

        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_kclass.dat')),
                'w+') as ff:
            np.save(ff, np.squeeze(wc).astype('float32'))

        del wc

        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_kclass.dat')),
                'r') as ff:
            kclass_fp = np.load(ff)

    ########################################################
    if doplot == 1:

        if len(shape_star) > 2:
            for p in xrange(len(star_fp)):
                plot_kmeans(dist_m, shape_port, port_fp[p], star_fp[p],
                            kclass_fp[p], ft, humfile, sonpath, base, p)
        else:
            plot_kmeans(dist_m, shape_port, port_fp, star_fp, kclass_fp, ft,
                        humfile, sonpath, base, 0)

    if os.name == 'posix':  # true if linux/mac
        elapsed = (time.time() - start)
    else:  # windows
        elapsed = (time.clock() - start)
    print "Processing took ", elapsed, "seconds to analyse"

    print "Done!"
Esempio n. 4
0
def get_grid(mode, orig_def, targ_def, merge, influence, minX, maxX, minY, maxY, res, nn, sigmas, eps, shape, numstdevs, trans, humlon, humlat):

    if mode==1:

       wf = None
       
       complete=0
       while complete==0:
          try:
             try:
                dat = pyresample.kd_tree.resample_nearest(orig_def, merge.flatten(), targ_def, radius_of_influence=res*20, fill_value=None, nprocs = cpu_count()) 
             except:
                dat = pyresample.kd_tree.resample_nearest(orig_def, merge.flatten(), targ_def, radius_of_influence=res*20, fill_value=None, nprocs = 1)              
             if 'dat' in locals(): 
                complete=1 
          except:
             #del grid_x, grid_y, targ_def, orig_def
             dat, res, complete = getgrid_lm(humlon, humlat, merge, res*10, minX, maxX, minY, maxY, res*2, mode, trans, nn, wf, sigmas, eps)

    elif mode==2:
       # custom inverse distance 
       wf = lambda r: 1/r**2

       complete=0
       while complete==0:
          try:
             try:
                dat, stdev, counts = pyresample.kd_tree.resample_custom(orig_def, merge.flatten(),targ_def, radius_of_influence=res*20, neighbours=nn, weight_funcs=wf, fill_value=None, with_uncert = True, nprocs = cpu_count())
             except:
                dat, stdev, counts = pyresample.kd_tree.resample_custom(orig_def, merge.flatten(),targ_def, radius_of_influence=res*20, neighbours=nn, weight_funcs=wf, fill_value=None, with_uncert = True, nprocs = 1)             
             if 'dat' in locals(): 
                complete=1 
          except:
             #del grid_x, grid_y, targ_def, orig_def
             dat, stdev, counts, res, complete = getgrid_lm(humlon, humlat, merge, res*10, minX, maxX, minY, maxY, res*2, mode, trans, nn, wf, sigmas, eps)

    elif mode==3:

       wf = None
       
       complete=0
       while complete==0:
          try:
             try:
                dat, stdev, counts = pyresample.kd_tree.resample_gauss(orig_def, merge.flatten(), targ_def, radius_of_influence=res*20, neighbours=nn, sigmas=sigmas, fill_value=None, with_uncert = np.nan, nprocs = cpu_count(), epsilon = eps)
             except:
                dat, stdev, counts = pyresample.kd_tree.resample_gauss(orig_def, merge.flatten(), targ_def, radius_of_influence=res*20, neighbours=nn, sigmas=sigmas, fill_value=None, with_uncert = np.nan, nprocs = 1, epsilon = eps)             
             if 'dat' in locals(): 
                complete=1 
          except:
             #del grid_x, grid_y, targ_def, orig_def
             dat, stdev, counts, res, complete = getgrid_lm(humlon, humlat, merge, res*10, minX, maxX, minY, maxY, res*2, mode, trans, nn, wf, sigmas, eps)

    dat = dat.reshape(shape)
    if mode>1:
       stdev = stdev.reshape(shape)
       counts = counts.reshape(shape)

    mask = dat.mask.copy()

    dat[mask==1] = 0

    if mode>1:
       dat[(stdev>numstdevs) & (mask!=0)] = np.nan
       dat[(counts<nn) & (counts>0)] = np.nan

    dat2 = replace_nans.RN(dat.astype('float64'),1000,0.01,2,'localmean').getdata()
    dat2[dat==0] = np.nan

    # get a new mask
    mask = np.isnan(dat2)

    mask = ~binary_dilation(binary_erosion(~mask,structure=np.ones((15,15))), structure=np.ones((15,15)))
    
    dat2[mask==1] = np.nan
    dat2[dat2<0] = np.nan
    del dat
    dat = dat2
    del dat2

    return dat, res