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!")
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("===================================================")
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!"
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